packages feed

hledger-ui 1.22.2 → 1.23

raw patch · 14 files changed

+477/−431 lines, 14 filesdep ~basedep ~hledgerdep ~hledger-lib

Dependency ranges changed: base, hledger, hledger-lib, megaparsec

Files

CHANGES.md view
@@ -9,6 +9,23 @@ User-visible changes in hledger-ui. See also the hledger changelog. +# 1.23 2021-09-21++Improvements++- Require base >=4.11, prevent red squares on Hackage's build matrix.++API changes++- Lenses are now available for UIState etc., saving a lot of boilerplate. (Stephen Morgan)++- Renamed:+  ```+  version -> packageversion+  versiondescription -> versionStringFor+  UIOpts fields+  ```+ # 1.22.2 2021-08-07  - Use hledger 1.22.2.@@ -17,8 +34,7 @@  Improvements -- Document watch mode and its limitations.-  (#1617, #911, #836)+- Document watch mode and its limitations. (#1617, #911, #836)  - Allow megaparsec 9.1. 
Hledger/UI/AccountsScreen.hs view
@@ -19,7 +19,7 @@ import Data.List import Data.Maybe import qualified Data.Text as T-import Data.Time.Calendar (Day, addDays)+import Data.Time.Calendar (Day) import qualified Data.Vector as V import Graphics.Vty (Event(..),Key(..),Modifier(..)) import Lens.Micro.Platform@@ -49,7 +49,7 @@  asInit :: Day -> Bool -> UIState -> UIState asInit d reset ui@UIState{-  aopts=UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}},+  aopts=UIOpts{uoCliOpts=copts@CliOpts{reportspec_=rspec@ReportSpec{_rsReportOpts=ropts}}},   ajournal=j,   aScreen=s@AccountsScreen{}   } =@@ -69,7 +69,7 @@                    (_, Nothing)            -> 0                    (_, Just (_,AccountsScreenItem{asItemAccountName=a})) ->                      headDef 0 $ catMaybes [-                       findIndex (a ==) as+                       elemIndex a as                       ,findIndex (a `isAccountNamePrefixOf`) as                       ,Just $ max 0 (length (filter (< a) as) - 1)                       ]@@ -77,16 +77,7 @@                         as = map asItemAccountName displayitems      -- Further restrict the query based on the current period and future/forecast mode.-    rspec' = rspec{rsQuery=simplifyQuery $ And [rsQuery rspec, periodq, excludeforecastq (forecast_ $ inputopts_ copts)]}-      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-          And [-             Not (Date $ DateSpan (Just $ addDays 1 d) Nothing)-            ,Not generatedTransactionTag-          ]+    rspec' = reportSpecSetFutureAndForecast d (forecast_ $ inputopts_ copts) rspec      -- run the report     (items,_total) = balanceReport rspec' j@@ -112,7 +103,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{reportspec_=rspec}}+asDraw UIState{aopts=_uopts@UIOpts{uoCliOpts=copts@CliOpts{reportspec_=rspec}}               ,ajournal=j               ,aScreen=s@AccountsScreen{}               ,aMode=mode@@ -152,8 +143,8 @@       render $ defaultLayout toplabel bottomlabel $ renderList (asDrawItem colwidths) True (_asList s)        where-        ropts = rsOpts rspec-        ishistorical = balancetype_ ropts == HistoricalBalance+        ropts = _rsReportOpts rspec+        ishistorical = balanceaccum_ ropts == Historical          toplabel =               withAttr ("border" <> "filename") files@@ -232,12 +223,12 @@ asHandle :: UIState -> BrickEvent Name AppEvent -> EventM Name (Next UIState) asHandle ui0@UIState{    aScreen=scr@AccountsScreen{..}-  ,aopts=UIOpts{cliopts_=copts}+  ,aopts=UIOpts{uoCliOpts=copts}   ,ajournal=j   ,aMode=mode   } ev = do-  d <- liftIO getCurrentDay   let+    d = copts^.rsDay     nonblanks = V.takeWhile (not . T.null . asItemAccountName) $ _asList^.listElementsL     lastnonblankidx = max 0 (length nonblanks - 1) @@ -259,8 +250,8 @@         VtyEvent ev        -> do ed' <- handleEditorEvent ev ed                                  continue $ ui{aMode=Minibuffer ed'}         AppEvent _        -> continue ui-        MouseDown _ _ _ _ -> continue ui-        MouseUp _ _ _     -> continue ui+        MouseDown{}       -> continue ui+        MouseUp{}         -> continue ui      Help ->       case ev of@@ -274,7 +265,7 @@         VtyEvent (EvKey (KChar 'q') []) -> halt ui         -- EvKey (KChar 'l') [MCtrl] -> do         VtyEvent (EvKey KEsc        []) -> continue $ resetScreens d ui-        VtyEvent (EvKey (KChar c)   []) | c `elem` ['?'] -> continue $ setMode Help ui+        VtyEvent (EvKey (KChar c)   []) | c == '?' -> continue $ setMode Help ui         -- XXX AppEvents currently handled only in Normal mode         -- XXX be sure we don't leave unconsumed events piling up         AppEvent (DateChange old _) | isStandardPeriod p && p `periodContainsDate` old ->@@ -365,8 +356,8 @@                                     }          AppEvent _        -> continue ui-        MouseDown _ _ _ _ -> continue ui-        MouseUp _ _ _     -> continue ui+        MouseDown{}       -> continue ui+        MouseUp{}         -> continue ui    where     journalspan = journalDateSpan False j
Hledger/UI/ErrorScreen.hs view
@@ -19,6 +19,7 @@ import Data.Time.Calendar (Day) import Data.Void (Void) import Graphics.Vty (Event(..),Key(..),Modifier(..))+import Lens.Micro ((^.)) import Text.Megaparsec import Text.Megaparsec.Char @@ -28,7 +29,6 @@ import Hledger.UI.UIState import Hledger.UI.UIUtils import Hledger.UI.Editor-import Data.Foldable (asum)  errorScreen :: Screen errorScreen = ErrorScreen{@@ -43,7 +43,7 @@ esInit _ _ _ = error "init function called with wrong screen type, should not happen"  -- PARTIAL:  esDraw :: UIState -> [Widget Name]-esDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{}}+esDraw UIState{aopts=UIOpts{uoCliOpts=copts}               ,aScreen=ErrorScreen{..}               ,aMode=mode               } =@@ -59,9 +59,10 @@               withAttr ("border" <> "bold") (str "Oops. Please fix this problem then press g to reload")               -- <+> (if ignore_assertions_ copts then withAttr ("border" <> "query") (str " ignoring") else str " not ignoring") -        bottomlabel = case mode of+        bottomlabel = quickhelp+                        -- case mode of                         -- Minibuffer ed -> minibuffer ed-                        _             -> quickhelp+                        -- _             -> quickhelp           where             quickhelp = borderKeysStr [                ("h", "help")@@ -75,7 +76,7 @@  esHandle :: UIState -> BrickEvent Name AppEvent -> EventM Name (Next UIState) esHandle ui@UIState{aScreen=ErrorScreen{..}-                   ,aopts=UIOpts{cliopts_=copts}+                   ,aopts=UIOpts{uoCliOpts=copts}                    ,ajournal=j                    ,aMode=mode                    }@@ -89,7 +90,7 @@         _                    -> helpHandle ui ev      _ -> do-      d <- liftIO getCurrentDay+      let d = copts^.rsDay       case ev of         VtyEvent (EvKey (KChar 'q') []) -> halt ui         VtyEvent (EvKey KEsc        []) -> continue $ uiCheckBalanceAssertions d $ resetScreens d ui@@ -177,26 +178,12 @@         UIState{aScreen=s@ErrorScreen{}} -> ui{aScreen=s{esError=err}}         _                                -> screenEnter d errorScreen{esError=err} ui --- | Ensure this CliOpts enables forecasted transactions.--- If a forecast period was specified in the old CliOpts,--- or in the provided UIState's startup options,--- it is preserved.-enableForecastPreservingPeriod :: UIState -> CliOpts -> CliOpts-enableForecastPreservingPeriod ui copts@CliOpts{inputopts_=iopts} =-    copts{inputopts_=iopts{forecast_=mforecast}}-  where-    mforecast = asum [mprovidedforecastperiod, mstartupforecastperiod, mdefaultforecastperiod]-      where-        mprovidedforecastperiod = forecast_ $ inputopts_ copts-        mstartupforecastperiod  = forecast_ $ inputopts_ $ cliopts_ $ astartupopts ui-        mdefaultforecastperiod  = Just nulldatespan- -- Re-check any balance assertions in the current journal, and if any -- fail, enter (or update) the error screen. Or if balance assertions -- are disabled, do nothing. uiCheckBalanceAssertions :: Day -> UIState -> UIState-uiCheckBalanceAssertions d ui@UIState{aopts=UIOpts{cliopts_=copts}, ajournal=j}-  | ignore_assertions_ . balancingopts_ $ inputopts_ copts = ui+uiCheckBalanceAssertions d ui@UIState{ajournal=j}+  | ui^.ignore_assertions = ui   | otherwise =     case journalCheckBalanceAssertions j of       Nothing  -> ui
Hledger/UI/Main.hs view
@@ -3,6 +3,7 @@ Copyright (c) 2007-2015 Simon Michael <simon@joyful.com> Released under GPL version 3 or later. -}+{-# LANGUAGE LambdaCase            #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings     #-} @@ -17,6 +18,7 @@ import Data.Maybe (fromMaybe) import qualified Data.Text as T import Graphics.Vty (mkVty)+import Lens.Micro ((^.)) import System.Directory (canonicalizePath) import System.FilePath (takeDirectory) import System.FSNotify (Event(Modified), isPollingManager, watchDir, withManager)@@ -28,7 +30,6 @@ import Hledger.Cli hiding (progname,prognameandversion) import Hledger.UI.UIOptions import Hledger.UI.UITypes-import Hledger.UI.UIState (toggleHistorical) import Hledger.UI.Theme import Hledger.UI.AccountsScreen import Hledger.UI.RegisterScreen@@ -44,7 +45,7 @@  main :: IO () main = do-  opts@UIOpts{cliopts_=copts@CliOpts{inputopts_=iopts,rawopts_=rawopts}} <- getHledgerUIOpts+  opts@UIOpts{uoCliOpts=copts@CliOpts{inputopts_=iopts,rawopts_=rawopts}} <- getHledgerUIOpts   -- when (debug_ $ cliopts_ opts) $ printf "%s\n" prognameandversion >> printf "opts: %s\n" (show opts)    -- always generate forecasted periodic transactions; their visibility will be toggled by the UI.@@ -55,14 +56,13 @@     _ | "info"            `inRawOpts` rawopts -> runInfoForTopic "hledger-ui" Nothing     _ | "man"             `inRawOpts` rawopts -> runManForTopic  "hledger-ui" Nothing     _ | "version"         `inRawOpts` rawopts -> putStrLn prognameandversion-    _ | "binary-filename" `inRawOpts` rawopts -> putStrLn (binaryfilename progname)+    -- _ | "binary-filename" `inRawOpts` rawopts -> putStrLn (binaryfilename progname)     _                                         -> withJournalDo copts' (runBrickUi opts)  runBrickUi :: UIOpts -> Journal -> IO ()-runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportspec_=rspec@ReportSpec{rsOpts=ropts}}} j = do-  d <- getCurrentDay-+runBrickUi uopts@UIOpts{uoCliOpts=copts@CliOpts{inputopts_=_iopts,reportspec_=rspec@ReportSpec{_rsReportOpts=ropts}}} j = do   let+    today = copts^.rsDay      -- hledger-ui's query handling is currently in flux, mixing old and new approaches.     -- Related: #1340, #1383, #1387. Some notes and terminology:@@ -102,32 +102,26 @@     -- It's cleaner and less conflicting to keep the former out of the latter.      uopts' = uopts{-      cliopts_=copts{+      uoCliOpts=copts{          reportspec_=rspec{-            rsQuery=filteredQuery $ rsQuery rspec,  -- query with depth/date parts removed-            rsOpts=ropts{-               depth_ =queryDepth $ rsQuery rspec,  -- query's depth part+            _rsQuery=filteredQuery $ _rsQuery rspec,  -- query with depth/date parts removed+            _rsReportOpts=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)+               empty_=not $ empty_ ropts  -- show zero items by default, hide them with -E (unlike hledger)                }             }          }       }       where-        datespanfromargs = queryDateSpan (date2_ ropts) $ rsQuery rspec+        datespanfromargs = queryDateSpan (date2_ ropts) $ _rsQuery rspec         periodfromoptsandargs =           dateSpanAsPeriod $ spansIntersect [periodAsDateSpan $ period_ ropts, datespanfromargs]         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) $-            maybestringopt "theme" $ rawopts_ copts-    mregister = maybestringopt "register" $ rawopts_ copts--    (scr, prevscrs) = case mregister of+    (scr, prevscrs) = case uoRegister uopts' of       Nothing   -> (accountsScreen, [])       -- with --register, start on the register screen, and also put       -- the accounts screen on the prev screens stack so you can exit@@ -142,7 +136,7 @@           -- Initialising the accounts screen is awkward, requiring           -- another temporary UIState value..           ascr' = aScreen $-                  asInit d True+                  asInit today True                     UIState{                      astartupopts=uopts'                     ,aopts=uopts'@@ -153,8 +147,7 @@                     }      ui =-      (sInit scr) d True $-        (if change_ uopts' then toggleHistorical else id) -- XXX+      (sInit scr) today True $           UIState{            astartupopts=uopts'           ,aopts=uopts'@@ -167,7 +160,7 @@     brickapp :: App UIState AppEvent Name     brickapp = App {         appStartEvent   = return-      , appAttrMap      = const theme+      , appAttrMap      = const $ fromMaybe defaultTheme $ getTheme =<< uoTheme uopts'       , appChooseCursor = showFirstCursor       , appHandleEvent  = \ui ev -> sHandle (aScreen ui) ui ev       , appDraw         = \ui    -> sDraw   (aScreen ui) ui@@ -175,7 +168,7 @@    -- print (length (show ui)) >> exitSuccess  -- show any debug output to this point & quit -  if not (watch_ uopts')+  if not (uoWatch uopts')   then     void $ Brick.defaultMain brickapp ui @@ -197,9 +190,10 @@         watchDate new      withAsync+      -- run this small task asynchronously:       (getCurrentDay >>= watchDate)-      $ \_ ->-+      -- until this main task terminates:+      $ \_async ->       -- start one or more background threads reporting changes in the directories of our files       -- XXX many quick successive saves causes the problems listed in BUGS       -- with Debounce increased to 1s it easily gets stuck on an error or blank screen@@ -218,7 +212,7 @@           mgr           d           -- predicate: ignore changes not involving our files-          (\fev -> case fev of+          (\case             Modified f _ False -> f `elem` files             -- Added    f _ -> f `elem` files             -- Removed  f _ -> f `elem` files
Hledger/UI/RegisterScreen.hs view
@@ -56,7 +56,7 @@ rsSetAccount _ _ scr = scr  rsInit :: Day -> Bool -> UIState -> UIState-rsInit d reset ui@UIState{aopts=_uopts@UIOpts{cliopts_=CliOpts{inputopts_=iopts,reportspec_=rspec@ReportSpec{rsOpts=ropts}}}, ajournal=j, aScreen=s@RegisterScreen{..}} =+rsInit d reset ui@UIState{aopts=_uopts@UIOpts{uoCliOpts=copts@CliOpts{reportspec_=rspec@ReportSpec{_rsReportOpts=ropts}}}, ajournal=j, aScreen=s@RegisterScreen{..}} =   ui{aScreen=s{rsList=newitems'}}   where     -- gather arguments and queries@@ -70,24 +70,12 @@         depth_=Nothing       -- XXX aregister also has this, needed ?         -- always show historical balance-      -- , balancetype_= HistoricalBalance+      -- , balanceaccum_= Historical       }-    rspec' =+    rspec' = reportSpecSetFutureAndForecast d (forecast_ $ inputopts_ copts) .       either (error "rsInit: adjusting the query for register, should not have failed") id $ -- PARTIAL:-      updateReportSpec ropts' rspec--    -- Further restrict the query based on the current period and future/forecast mode.-    q = simplifyQuery $ And [rsQuery rspec', periodq, excludeforecastq (forecast_ iopts)]-      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-          And [-             Not (Date $ DateSpan (Just $ addDays 1 d) Nothing)-            ,Not generatedTransactionTag-          ]-    items = accountTransactionsReport rspec' j q thisacctq+      updateReportSpec ropts' rspec{_rsDay=d}+    items = accountTransactionsReport rspec' j thisacctq     items' = (if empty_ ropts then id else filter (not . mixedAmountLooksZero . fifth6)) $  -- without --empty, exclude no-change txns              reverse  -- most recent last              items@@ -96,7 +84,7 @@     displayitems = map displayitem items'       where         displayitem (t, _, _issplit, otheracctsstr, change, bal) =-          RegisterScreenItem{rsItemDate          = showDate $ transactionRegisterDate q thisacctq t+          RegisterScreenItem{rsItemDate          = showDate $ transactionRegisterDate (_rsQuery rspec') thisacctq t                             ,rsItemStatus        = tstatus t                             ,rsItemDescription   = tdescription t                             ,rsItemOtherAccounts = otheracctsstr@@ -141,12 +129,12 @@                 nearestidbydatethenid = third3 <$> (headMay $ sort                   [(abs $ diffDays (tdate t) prevseld, abs (tindex t - prevselidx), tindex t) | t <- ts])                 ts = map rsItemTransaction displayitems-        endidx = length displayitems - 1+        endidx = max 0 $ length displayitems - 1  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{reportspec_=rspec}}+rsDraw UIState{aopts=_uopts@UIOpts{uoCliOpts=copts@CliOpts{reportspec_=rspec}}               ,aScreen=RegisterScreen{..}               ,aMode=mode               } =@@ -200,8 +188,8 @@       render $ defaultLayout toplabel bottomlabel $ renderList (rsDrawItem colwidths) True rsList        where-        ropts = rsOpts rspec-        ishistorical = balancetype_ ropts == HistoricalBalance+        ropts = _rsReportOpts rspec+        ishistorical = balanceaccum_ ropts == Historical         -- inclusive = tree_ ropts || rsForceInclusive          toplabel =@@ -287,12 +275,12 @@ rsHandle :: UIState -> BrickEvent Name AppEvent -> EventM Name (Next UIState) rsHandle ui@UIState{    aScreen=s@RegisterScreen{..}-  ,aopts=UIOpts{cliopts_=copts}+  ,aopts=UIOpts{uoCliOpts=copts}   ,ajournal=j   ,aMode=mode   } ev = do-  d <- liftIO getCurrentDay   let+    d = copts^.rsDay     journalspan = journalDateSpan False j     nonblanks = V.takeWhile (not . T.null . rsItemDate) $ rsList^.listElementsL     lastnonblankidx = max 0 (length nonblanks - 1)@@ -308,8 +296,8 @@         VtyEvent ev              -> do ed' <- handleEditorEvent ev ed                                        continue $ ui{aMode=Minibuffer ed'}         AppEvent _        -> continue ui-        MouseDown _ _ _ _ -> continue ui-        MouseUp _ _ _     -> continue ui+        MouseDown{}       -> continue ui+        MouseUp{}         -> continue ui      Help ->       case ev of@@ -322,7 +310,7 @@       case ev of         VtyEvent (EvKey (KChar 'q') []) -> halt ui         VtyEvent (EvKey KEsc        []) -> continue $ resetScreens d ui-        VtyEvent (EvKey (KChar c)   []) | c `elem` ['?'] -> continue $ setMode Help ui+        VtyEvent (EvKey (KChar c)   []) | c == '?' -> continue $ setMode Help ui         AppEvent (DateChange old _) | isStandardPeriod p && p `periodContainsDate` old ->           continue $ regenerateScreens j d $ setReportPeriod (DayPeriod d) ui           where@@ -338,9 +326,7 @@             (pos,f) = case listSelectedElement rsList of                         Nothing -> (endPosition, journalFilePath j)                         Just (_, RegisterScreenItem{-                          rsItemTransaction=Transaction{tsourcepos=GenericSourcePos f l c}}) -> (Just (l, Just c),f)-                        Just (_, RegisterScreenItem{-                          rsItemTransaction=Transaction{tsourcepos=JournalSourcePos f (l,_)}}) -> (Just (l, Nothing),f)+                          rsItemTransaction=Transaction{tsourcepos=(SourcePos f l c,_)}}) -> (Just (unPos l, Just $ unPos c),f)          -- display mode/query toggles         VtyEvent (EvKey (KChar 'B') []) -> rsCenterAndContinue $ regenerateScreens j d $ toggleCost ui@@ -396,8 +382,8 @@           continue ui{aScreen=s{rsList=newitems}}          AppEvent _        -> continue ui-        MouseDown _ _ _ _ -> continue ui-        MouseUp _ _ _     -> continue ui+        MouseDown{}       -> continue ui+        MouseUp{}         -> continue ui  rsHandle _ _ = error "event handler called with wrong screen type, should not happen"  -- PARTIAL: 
Hledger/UI/TransactionScreen.hs view
@@ -41,7 +41,7 @@   }  tsInit :: Day -> Bool -> UIState -> UIState-tsInit _d _reset ui@UIState{aopts=UIOpts{cliopts_=CliOpts{reportspec_=_rspec}}+tsInit _d _reset ui@UIState{aopts=UIOpts{}                            ,ajournal=_j                            ,aScreen=s@TransactionScreen{tsTransaction=(_,t),tsTransactions=nts}                            ,aPrevScreens=prevscreens@@ -60,7 +60,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{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}+tsDraw UIState{aopts=UIOpts{uoCliOpts=copts@CliOpts{reportspec_=rspec@ReportSpec{_rsReportOpts=ropts}}}               ,ajournal=j               ,aScreen=TransactionScreen{tsTransaction=(i,t')                                         ,tsTransactions=nts@@ -77,7 +77,7 @@     t = transactionMapPostingAmounts mixedAmountSetFullPrecision t'     maincontent = Widget Greedy Greedy $ do       let-        prices = journalPriceOracle (infer_value_ ropts) j+        prices = journalPriceOracle (infer_prices_ ropts) j         styles = journalCommodityStyles j         periodlast =           fromMaybe (error' "TransactionScreen: expected a non-empty journal") $  -- PARTIAL: shouldn't happen@@ -85,7 +85,7 @@        render . defaultLayout toplabel bottomlabel . str         . T.unpack . showTransactionOneLineAmounts-        . maybe id (transactionApplyValuation prices styles periodlast (rsToday rspec)) (value_ ropts)+        . maybe id (transactionApplyValuation prices styles periodlast (_rsDay rspec)) (value_ ropts)         $ case cost_ ropts of                Cost   -> transactionToCost styles t                NoCost -> t@@ -113,9 +113,10 @@                 [] -> str ""                 fs -> withAttr ("border" <> "query") (str $ " " ++ intercalate ", " fs) -        bottomlabel = case mode of+        bottomlabel = quickhelp+                        -- case mode of                         -- Minibuffer ed -> minibuffer ed-                        _             -> quickhelp+                        -- _             -> quickhelp           where             quickhelp = borderKeysStr [                ("?", "help")@@ -132,7 +133,7 @@  tsHandle :: UIState -> BrickEvent Name AppEvent -> EventM Name (Next UIState) tsHandle ui@UIState{aScreen=TransactionScreen{tsTransaction=(i,t), tsTransactions=nts}-                   ,aopts=UIOpts{cliopts_=copts}+                   ,aopts=UIOpts{uoCliOpts=copts}                    ,ajournal=j                    ,aMode=mode                    }@@ -146,26 +147,24 @@         _                    -> helpHandle ui ev      _ -> do-      d <- liftIO getCurrentDay       let+        d = copts^.rsDay         (iprev,tprev) = maybe (i,t) ((i-1),) $ lookup (i-1) nts         (inext,tnext) = maybe (i,t) ((i+1),) $ lookup (i+1) nts       case ev of         VtyEvent (EvKey (KChar 'q') []) -> halt ui         VtyEvent (EvKey KEsc        []) -> continue $ resetScreens d ui-        VtyEvent (EvKey (KChar c)   []) | c `elem` ['?'] -> continue $ setMode Help ui+        VtyEvent (EvKey (KChar c)   []) | c == '?' -> continue $ setMode Help ui         VtyEvent (EvKey (KChar 'E') []) -> suspendAndResume $ void (runEditor pos f) >> uiReloadJournalIfChanged copts d j ui           where             (pos,f) = case tsourcepos t of-                        GenericSourcePos f l c    -> (Just (l, Just c),f)-                        JournalSourcePos f (l1,_) -> (Just (l1, Nothing),f)+                        (SourcePos f l1 c1,_) -> (Just (unPos l1, Just $ unPos c1),f)         AppEvent (DateChange old _) | isStandardPeriod p && p `periodContainsDate` old ->           continue $ regenerateScreens j d $ setReportPeriod (DayPeriod d) ui           where             p = reportPeriod ui         e | e `elem` [VtyEvent (EvKey (KChar 'g') []), AppEvent FileChange] -> do           -- plog (if e == AppEvent FileChange then "file change" else "manual reload") "" `seq` return ()-          d <- liftIO getCurrentDay           ej <- liftIO $ journalReload copts           case ej of             Left err -> continue $ screenEnter d errorScreen{esError=err} ui
Hledger/UI/UIOptions.hs view
@@ -5,22 +5,32 @@  module Hledger.UI.UIOptions where-import Data.Default++import Data.Default (def) import Data.List (intercalate)-import System.Environment+import qualified Data.Map as M+import Data.Maybe (fromMaybe)+import Lens.Micro (set)+import System.Environment (getArgs) -import Hledger.Cli hiding (progname,version,prognameandversion)-import Hledger.UI.Theme (themeNames)+import Hledger.Cli hiding (packageversion, progname, prognameandversion)+import Hledger.UI.Theme (themes, themeNames) -progname, version, prognameandversion :: String-progname = "hledger-ui"+-- cf Hledger.Cli.Version++packageversion :: String #ifdef VERSION-version = VERSION+packageversion = VERSION #else-version = ""+packageversion = "" #endif-prognameandversion = versiondescription progname +progname :: String+progname = "hledger-ui"++prognameandversion :: String+prognameandversion = versionStringForProgname progname+ uiflags = [   -- flagNone ["debug-ui"] (setboolopt "rules-file") "run with no terminal output, showing console"    flagNone ["watch"] (setboolopt "watch") "watch for data and date changes and reload automatically"@@ -55,35 +65,35 @@            }  -- hledger-ui options, used in hledger-ui and above-data UIOpts = UIOpts {-     watch_       :: Bool-    ,change_      :: Bool-    ,cliopts_     :: CliOpts- } deriving (Show)+data UIOpts = UIOpts+  { uoWatch    :: Bool+  , uoTheme    :: Maybe String+  , uoRegister :: Maybe String+  , uoCliOpts  :: CliOpts+  } deriving (Show)  defuiopts = UIOpts-  { watch_   = False-  , change_  = False-  , cliopts_ = def+  { uoWatch    = False+  , uoTheme    = Nothing+  , uoRegister = Nothing+  , uoCliOpts  = defcliopts   } --- instance Default CliOpts where def = defcliopts-+-- | Process a RawOpts into a UIOpts.+-- This will return a usage error if provided an invalid theme. rawOptsToUIOpts :: RawOpts -> IO UIOpts-rawOptsToUIOpts rawopts = checkUIOpts <$> do-  cliopts <- rawOptsToCliOpts rawopts-  return defuiopts {-              watch_       = boolopt "watch" rawopts-             ,change_      = boolopt "change" rawopts-             ,cliopts_     = cliopts-             }--checkUIOpts :: UIOpts -> UIOpts-checkUIOpts opts =-  either usageError (const opts) $ do-    case maybestringopt "theme" $ rawopts_ $ cliopts_ opts of-      Just t | not $ elem t themeNames -> Left $ "invalid theme name: "++t-      _                                -> Right ()+rawOptsToUIOpts rawopts = do+    cliopts <- set balanceaccum accum <$> rawOptsToCliOpts rawopts+    return defuiopts {+                uoWatch    = boolopt "watch" rawopts+               ,uoTheme    = checkTheme <$> maybestringopt "theme" rawopts+               ,uoRegister = maybestringopt "register" rawopts+               ,uoCliOpts  = cliopts+               }+  where+    -- show historical balance by default (unlike hledger)+    accum = fromMaybe Historical $ balanceAccumulationOverride rawopts+    checkTheme t = if t `M.member` themes then t else usageError $ "invalid theme name: " ++ t  -- XXX some refactoring seems due getHledgerUIOpts :: IO UIOpts@@ -93,3 +103,21 @@   let args' = replaceNumericFlags args   let cmdargopts = either usageError id $ process uimode args'   rawOptsToUIOpts cmdargopts++instance HasCliOpts UIOpts where+    cliOpts f uiopts = (\x -> uiopts{uoCliOpts=x}) <$> f (uoCliOpts uiopts)++instance HasInputOpts UIOpts where+    inputOpts = cliOpts.inputOpts++instance HasBalancingOpts UIOpts where+    balancingOpts = cliOpts.balancingOpts++instance HasReportSpec UIOpts where+    reportSpec = cliOpts.reportSpec++instance HasReportOptsNoUpdate UIOpts where+    reportOptsNoUpdate = cliOpts.reportOptsNoUpdate++instance HasReportOpts UIOpts where+    reportOpts = cliOpts.reportOpts
Hledger/UI/UIState.hs view
@@ -7,32 +7,30 @@ where  import Brick.Widgets.Edit-import Control.Applicative ((<|>))+import Data.Foldable (asum)+import Data.Either (fromRight) import Data.List ((\\), foldl', sort) import Data.Semigroup (Max(..)) import qualified Data.Text as T import Data.Text.Zipper (gotoEOL) import Data.Time.Calendar (Day)+import Lens.Micro ((^.), over, set)  import Hledger import Hledger.Cli.CliOptions import Hledger.UI.UITypes-import Hledger.UI.UIOptions  -- | Toggle between showing only unmarked items or all items. toggleUnmarked :: UIState -> UIState-toggleUnmarked ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =-  ui{aopts=uopts{cliopts_=copts{reportspec_=reportSpecToggleStatus Unmarked copts rspec}}}+toggleUnmarked = over statuses (toggleStatus1 Unmarked)  -- | Toggle between showing only pending items or all items. togglePending :: UIState -> UIState-togglePending ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =-  ui{aopts=uopts{cliopts_=copts{reportspec_=reportSpecToggleStatus Pending copts rspec}}}+togglePending = over statuses (toggleStatus1 Pending)  -- | Toggle between showing only cleared items or all items. toggleCleared :: UIState -> UIState-toggleCleared ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =-  ui{aopts=uopts{cliopts_=copts{reportspec_=reportSpecToggleStatus Cleared copts rspec}}}+toggleCleared = over statuses (toggleStatus1 Cleared)  -- TODO testing different status toggle styles @@ -52,17 +50,11 @@     showstatus Pending  = "pending"     showstatus Unmarked = "unmarked" -reportSpecToggleStatus :: Status -> CliOpts -> ReportSpec -> ReportSpec-reportSpecToggleStatus s _copts =-    either (error "reportSpecToggleStatus: changing status should not have caused this error") id  -- PARTIAL:-    . updateReportSpecWith (reportOptsToggleStatus1 s)- -- various toggle behaviours:  -- 1 UPC toggles only X/all-reportOptsToggleStatus1 s ropts@ReportOpts{statuses_=ss}-  | ss == [s]  = ropts{statuses_=[]}-  | otherwise = ropts{statuses_=[s]}+toggleStatus1 :: Status -> [Status] -> [Status]+toggleStatus1 s ss = if ss == [s] then [] else [s]  -- 2 UPC cycles X/not-X/all -- repeatedly pressing X cycles:@@ -72,25 +64,25 @@ -- pressing Y after first or second step starts new cycle: -- [u] P [p] -- [pc] P [p]--- reportOptsToggleStatus2 s ropts@ReportOpts{statuses_=ss}---   | ss == [s]            = ropts{statuses_=complement [s]}---   | ss == complement [s] = ropts{statuses_=[]}---   | otherwise            = ropts{statuses_=[s]}  -- XXX assume only three values+-- toggleStatus2 s ss+--   | ss == [s]            = complement [s]+--   | ss == complement [s] = []+--   | otherwise            = [s]  -- XXX assume only three values  -- 3 UPC toggles each X--- reportOptsToggleStatus3 s ropts@ReportOpts{statuses_=ss}---   | s `elem` ss = ropts{statuses_=filter (/= s) ss}---   | otherwise   = ropts{statuses_=simplifyStatuses (s:ss)}+-- toggleStatus3 s ss+--   | s `elem` ss = filter (/= s) ss+--   | otherwise   = simplifyStatuses (s:ss)  -- 4 upc sets X, UPC sets not-X---reportOptsToggleStatus4 s ropts@ReportOpts{statuses_=ss}---  | s `elem` ss = ropts{statuses_=filter (/= s) ss}---  | otherwise   = ropts{statuses_=simplifyStatuses (s:ss)}+-- toggleStatus4 s ss+--  | s `elem` ss = filter (/= s) ss+--  | otherwise   = simplifyStatuses (s:ss)  -- 5 upc toggles X, UPC toggles not-X---reportOptsToggleStatus5 s ropts@ReportOpts{statuses_=ss}---  | s `elem` ss = ropts{statuses_=filter (/= s) ss}---  | otherwise   = ropts{statuses_=simplifyStatuses (s:ss)}+-- toggleStatus5 s ss+--  | s `elem` ss = filter (/= s) ss+--  | otherwise   = simplifyStatuses (s:ss)  -- | Given a list of unique enum values, list the other possible values of that enum. complement :: (Bounded a, Enum a, Eq a) => [a] -> [a]@@ -100,56 +92,44 @@  -- | Toggle between showing all and showing only nonempty (more precisely, nonzero) items. toggleEmpty :: UIState -> UIState-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}+toggleEmpty = over empty__ not  -- | Toggle between showing the primary amounts or costs. toggleCost :: UIState -> UIState-toggleCost ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =-    ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{cost_ = toggle $ cost_ ropts}}}}}+toggleCost = over cost toggleCostMode   where-    toggle Cost   = NoCost-    toggle NoCost = Cost+    toggleCostMode Cost   = NoCost+    toggleCostMode NoCost = Cost  -- | Toggle between showing primary amounts or default valuation. toggleValue :: UIState -> UIState-toggleValue ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =-  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{-    value_ = valuationToggleValue $ value_ ropts}}}}}---- | Basic toggling of -V, for hledger-ui.-valuationToggleValue :: Maybe ValuationType -> Maybe ValuationType-valuationToggleValue (Just (AtEnd _)) = Nothing-valuationToggleValue _                = Just $ AtEnd Nothing+toggleValue = over value valuationToggleValue+  where+    -- | Basic toggling of -V, for hledger-ui.+    valuationToggleValue (Just (AtEnd _)) = Nothing+    valuationToggleValue _                = Just $ AtEnd Nothing  -- | Set hierarchic account tree mode. setTree :: UIState -> UIState-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}}}}}+setTree = set accountlistmode ALTree  -- | Set flat account list mode. setList :: UIState -> UIState-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}}}}}+setList = set 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{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =-  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=toggleTreeMode ropts}}}}+toggleTree = over accountlistmode toggleTreeMode   where-    toggleTreeMode ropts-      | accountlistmode_ ropts == ALTree = ropts{accountlistmode_=ALFlat}-      | otherwise                        = ropts{accountlistmode_=ALTree}+    toggleTreeMode ALTree = ALFlat+    toggleTreeMode ALFlat = ALTree  -- | Toggle between historical balances and period balances. toggleHistorical :: UIState -> UIState-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}}}}}+toggleHistorical = over balanceaccum toggleBalanceAccum   where-    b | balancetype_ ropts == HistoricalBalance = PeriodChange-      | otherwise                               = HistoricalBalance+    toggleBalanceAccum Historical = PerPeriod+    toggleBalanceAccum _          = Historical  -- | Toggle hledger-ui's "forecast/future mode". When this mode is enabled, -- hledger-shows regular transactions which have future dates, and@@ -157,32 +137,33 @@ -- (which are usually but not necessarily future-dated). -- In normal mode, both of these are hidden. toggleForecast :: Day -> UIState -> UIState-toggleForecast d ui@UIState{aopts=UIOpts{cliopts_=copts@CliOpts{inputopts_=iopts}}} =-  uiSetForecast ui $-    case forecast_ iopts of+toggleForecast _d ui = set forecast newForecast ui+  where+    newForecast = case ui^.forecast of       Just _  -> Nothing-      Nothing -> forecastPeriodFromRawOpts d (rawopts_ copts) <|> Just nulldatespan+      Nothing -> enableForecastPreservingPeriod ui (ui^.cliOpts) ^. forecast --- | Helper: set forecast mode (with the given forecast period) on or off in the UI state.-uiSetForecast :: UIState -> Maybe DateSpan -> UIState-uiSetForecast-  ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=iopts}}}-  mforecast =-  -- we assume forecast mode has no effect on ReportSpec's derived fields-  ui{aopts=uopts{cliopts_=copts{inputopts_=iopts{forecast_=mforecast}}}}+-- | Ensure this CliOpts enables forecasted transactions.+-- If a forecast period was specified in the old CliOpts,+-- or in the provided UIState's startup options,+-- it is preserved.+enableForecastPreservingPeriod :: UIState -> CliOpts -> CliOpts+enableForecastPreservingPeriod ui copts = set forecast mforecast copts+  where+    mforecast = asum [mprovidedforecastperiod, mstartupforecastperiod, mdefaultforecastperiod]+      where+        mprovidedforecastperiod = copts ^. forecast+        mstartupforecastperiod  = astartupopts ui ^. forecast+        mdefaultforecastperiod  = Just nulldatespan  -- | Toggle between showing all and showing only real (non-virtual) items. toggleReal :: UIState -> UIState-toggleReal ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =-    ui{aopts=uopts{cliopts_=copts{reportspec_=update rspec}}}-  where-    update = either (error "toggleReal: updating Real should not result in an error") id  -- PARTIAL:-           . updateReportSpecWith (\ropts -> ropts{real_=not $ real_ ropts})+toggleReal = fromRight err . overEither real not  -- PARTIAL:+  where err = error "toggleReal: updating Real should not result in an error"  -- | Toggle the ignoring of balance assertions. toggleIgnoreBalanceAssertions :: UIState -> UIState-toggleIgnoreBalanceAssertions ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=iopts@InputOpts{balancingopts_=bopts}}}} =-  ui{aopts=uopts{cliopts_=copts{inputopts_=iopts{balancingopts_=bopts{ignore_assertions_=not $ ignore_assertions_ bopts}}}}}+toggleIgnoreBalanceAssertions = over ignore_assertions not  -- | Step through larger report periods, up to all. growReportPeriod :: Day -> UIState -> UIState@@ -207,47 +188,34 @@ moveReportPeriodToDate :: Day -> UIState -> UIState moveReportPeriodToDate d = updateReportPeriod (periodMoveTo d) +-- | Clear any report period limits.+resetReportPeriod :: UIState -> UIState+resetReportPeriod = setReportPeriod PeriodAll+ -- | Get the report period. reportPeriod :: UIState -> Period-reportPeriod = period_ . rsOpts . reportspec_ . cliopts_ . aopts+reportPeriod = (^.period)  -- | Set the report period. setReportPeriod :: Period -> UIState -> UIState 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:-           . updateReportSpecWith (\ropts -> ropts{period_=updatePeriod $ period_ ropts})+updateReportPeriod updatePeriod = fromRight err . overEither period updatePeriod  -- PARTIAL:+  where err = error "updateReportPeriod: updating period should not result in an error"  -- | Apply a new filter query. setFilter :: String -> UIState -> UIState-setFilter s ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =-    ui{aopts=uopts{cliopts_=copts{reportspec_=update rspec}}}+setFilter s = over reportSpec update   where-    update = either (const rspec) id . updateReportSpecWith (\ropts -> ropts{querystring_=querystring})  -- XXX silently ignores an error-    querystring = words'' prefixes $ T.pack s+    update rspec = fromRight rspec $ setEither querystring (words'' prefixes $ T.pack s) rspec  -- XXX silently ignores an error  -- | Reset some filters & toggles. resetFilter :: UIState -> UIState-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-    }}}}}+resetFilter = set querystringNoUpdate [] . set realNoUpdate False . set statusesNoUpdate []+            . set empty__ True  -- set period PeriodAll+            . set rsQuery Any . set rsQueryOpts []  -- | Reset all options state to exactly what it was at startup -- (preserving any command-line options/arguments).@@ -282,15 +250,14 @@ setDepth mdepth = updateReportDepth (const mdepth)  getDepth :: UIState -> Maybe Int-getDepth = depth_ . rsOpts . reportspec_ . cliopts_ . aopts+getDepth = (^.depth)  -- | 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}}}+updateReportDepth updateDepth ui = over reportSpec update ui   where-    update = either (error "updateReportDepth: updating depth should not result in an error") id  -- PARTIAL:+    update = fromRight (error "updateReportDepth: updating depth should not result in an error")  -- PARTIAL:            . updateReportSpecWith (\ropts -> ropts{depth_=updateDepth (depth_ ropts) >>= clipDepth ropts})     clipDepth ropts d | d < 0            = depth_ ropts                       | d >= maxDepth ui = Nothing@@ -301,8 +268,7 @@ showMinibuffer ui = setMode (Minibuffer e) ui   where     e = applyEdit gotoEOL $ editor MinibufferEditor (Just 1) oldq-    oldq = T.unpack . T.unwords . map textQuoteIfNeeded-         . querystring_ . rsOpts . reportspec_ . cliopts_ $ aopts ui+    oldq = T.unpack . T.unwords . map textQuoteIfNeeded $ ui^.querystring  -- | Close the minibuffer, discarding any edit in progress. closeMinibuffer :: UIState -> UIState@@ -351,4 +317,3 @@ screenEnter d scr ui = (sInit scr) d True $                        pushScreen scr                        ui-
Hledger/UI/UITypes.hs view
@@ -48,6 +48,7 @@   -- import the Show instance for functions. Warning, this also re-exports it  import Hledger+import Hledger.Cli (HasCliOpts(..)) import Hledger.UI.UIOptions  -- | hledger-ui's application state. This holds one or more stateful screens.@@ -160,7 +161,24 @@ --    mempty        = list "" V.empty 1  -- XXX problem in 0.7, every list requires a unique Name --    mappend l1 l2 = l1 & listElementsL .~ (l1^.listElementsL <> l2^.listElementsL) -concat <$> mapM makeLenses [-   ''Screen-  ]+makeLenses ''Screen +uioptslens f ui = (\x -> ui{aopts=x}) <$> f (aopts ui)++instance HasCliOpts UIState where+    cliOpts = uioptslens.cliOpts++instance HasInputOpts UIState where+    inputOpts = uioptslens.inputOpts++instance HasBalancingOpts UIState where+    balancingOpts = uioptslens.balancingOpts++instance HasReportSpec UIState where+    reportSpec = uioptslens.reportSpec++instance HasReportOptsNoUpdate UIState where+    reportOptsNoUpdate = uioptslens.reportOptsNoUpdate++instance HasReportOpts UIState where+    reportOpts = uioptslens.reportOpts
Hledger/UI/UIUtils.hs view
@@ -24,6 +24,7 @@   ,scrollSelectionToMiddle   ,suspend   ,redraw+  ,reportSpecSetFutureAndForecast ) where @@ -34,15 +35,17 @@ import Brick.Widgets.Edit import Brick.Widgets.List (List, listSelectedL, listNameL, listItemHeightL) import Control.Monad.IO.Class+import Data.Bifunctor (second) import Data.List import qualified Data.Text as T+import Data.Time (Day, addDays) import Graphics.Vty   (Event(..),Key(..),Modifier(..),Vty(..),Color,Attr,currentAttr,refresh   -- ,Output(displayBounds,mkDisplayContext),DisplayContext(..)   ) import Lens.Micro.Platform -import Hledger hiding (Color)+import Hledger import Hledger.Cli (CliOpts) import Hledger.Cli.DocFiles import Hledger.UI.UITypes@@ -190,7 +193,7 @@ borderPeriodStr preposition p         = str (" "++preposition++" ") <+> withAttr ("border" <> "query") (str . T.unpack $ showPeriod p)  borderKeysStr :: [(String,String)] -> Widget Name-borderKeysStr = borderKeysStr' . map (\(a,b) -> (a, str b))+borderKeysStr = borderKeysStr' . map (second str)  borderKeysStr' :: [(String,Widget Name)] -> Widget Name borderKeysStr' keydescs =@@ -280,8 +283,7 @@ -- XXX May disrupt border style of inner widgets. -- XXX Should reduce the available size visible to inner widget, but doesn't seem to (cf rsDraw2). margin :: Int -> Int -> Maybe Color -> Widget Name -> Widget Name-margin h v mcolour = \w ->-  Widget Greedy Greedy $ do+margin h v mcolour w = Widget Greedy Greedy $ do     c <- getContext     let w' = vLimit (c^.availHeightL - v*2) $ hLimit (c^.availWidthL - h*2) w         attr = maybe currentAttr (\c -> c `on` c) mcolour@@ -342,3 +344,19 @@   | ev `elem` moveLeftEvents  = EvKey KLeft []   | ev `elem` moveRightEvents = EvKey KRight []   | otherwise = ev++-- | Update the ReportSpec's query to exclude future transactions (later than the given day)+-- and forecast transactions (generated by --forecast), if the given forecast DateSpan is Nothing,+-- and include them otherwise.+reportSpecSetFutureAndForecast :: Day -> Maybe DateSpan -> ReportSpec -> ReportSpec+reportSpecSetFutureAndForecast d forecast rspec =+    rspec{_rsQuery=simplifyQuery $ And [_rsQuery rspec, periodq, excludeforecastq forecast]}+  where+    periodq = Date . periodAsDateSpan . period_ $ _rsReportOpts rspec+    -- Except in forecast mode, exclude future/forecast transactions.+    excludeforecastq (Just _) = Any+    excludeforecastq Nothing  =  -- not:date:tomorrow- not:tag:generated-transaction+      And [+         Not (Date $ DateSpan (Just $ addDays 1 d) Nothing)+        ,Not generatedTransactionTag+      ]
hledger-ui.1 view
@@ -1,5 +1,5 @@ -.TH "HLEDGER-UI" "1" "August 2021" "hledger-ui-1.22.2 " "hledger User Manuals"+.TH "HLEDGER-UI" "1" "September 2021" "hledger-ui-1.23 " "hledger User Manuals"   @@ -7,7 +7,7 @@ .PP hledger-ui is a terminal interface (TUI) for the hledger accounting tool.-This manual is for hledger-ui 1.22.2.+This manual is for hledger-ui 1.23. .SH SYNOPSIS .PP \f[C]hledger-ui [OPTIONS] [QUERYARGS]\f[R]@@ -126,6 +126,10 @@ \f[B]\f[CB]--date2\f[B]\f[R] match the secondary date instead (see command help for other effects) .TP+\f[B]\f[CB]--today=DATE\f[B]\f[R]+override today\[aq]s date (affects relative smart dates, for+tests/examples)+.TP \f[B]\f[CB]-U --unmarked\f[B]\f[R] include only unmarked postings/txns (can combine with -P or -C) .TP@@ -169,6 +173,10 @@ next 6 months or till report end date. In hledger-ui, also make ordinary future transactions visible. .TP+\f[B]\f[CB]--commodity-style\f[B]\f[R]+Override the commodity style in the output for the specified commodity.+For example \[aq]EUR1.000,00\[aq].+.TP \f[B]\f[CB]--color=WHEN (or --colour=WHEN)\f[B]\f[R] Should color-supporting commands use ANSI color codes in text output. \[aq]auto\[aq] (default): whenever stdout seems to be a color-supporting@@ -177,6 +185,14 @@ into \[aq]less -R\[aq]. \[aq]never\[aq] or \[aq]no\[aq]: never. A NO_COLOR environment variable overrides this.+.TP+\f[B]\f[CB]--pretty[=WHEN]\f[B]\f[R]+Show prettier output, e.g.+using unicode box-drawing characters.+Accepts \[aq]yes\[aq] (the default) or \[aq]no\[aq] (\[aq]y\[aq],+\[aq]n\[aq], \[aq]always\[aq], \[aq]never\[aq] also work).+If you provide an argument you must use \[aq]=\[aq], e.g.+\[aq]--pretty=yes\[aq]. .PP When a reporting option appears more than once in the command line, the last one takes precedence.
hledger-ui.cabal view
@@ -5,7 +5,7 @@ -- see: https://github.com/sol/hpack  name:           hledger-ui-version:        1.22.2+version:        1.23 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.@@ -27,7 +27,7 @@ license-file:   LICENSE build-type:     Simple tested-with:-    GHC==8.6.5, GHC==8.8.4, GHC==8.10.4+    GHC==8.6.5, GHC==8.8.4, GHC==8.10.4, GHC==9.0.1 extra-source-files:     CHANGES.md     README.md@@ -63,11 +63,11 @@   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.22.2"+  cpp-options: -DVERSION="1.23"   build-depends:       ansi-terminal >=0.9     , async-    , base >=4.10.1.0 && <4.16+    , base >=4.11 && <4.16     , base-compat-batteries >=0.10.1 && <0.12     , brick >=0.23     , cmdargs >=0.8@@ -77,8 +77,8 @@     , extra >=1.6.3     , filepath     , fsnotify >=0.2.1.2 && <0.4-    , hledger >=1.22.2 && <1.23-    , hledger-lib >=1.22.2 && <1.23+    , hledger ==1.23.*+    , hledger-lib ==1.23.*     , megaparsec >=7.0.0 && <9.2     , microlens >=0.4     , microlens-platform >=0.2.3.1
hledger-ui.info view
@@ -12,7 +12,7 @@ *************  hledger-ui is a terminal interface (TUI) for the hledger accounting-tool.  This manual is for hledger-ui 1.22.2.+tool.  This manual is for hledger-ui 1.23.     'hledger-ui [OPTIONS] [QUERYARGS]' 'hledger ui -- [OPTIONS] [QUERYARGS]'@@ -144,6 +144,10 @@       match the secondary date instead (see command help for other      effects)+'--today=DATE'++     override today's date (affects relative smart dates, for+     tests/examples) '-U --unmarked'       include only unmarked postings/txns (can combine with -P or -C)@@ -189,6 +193,10 @@      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.+'--commodity-style'++     Override the commodity style in the output for the specified+     commodity.  For example 'EUR1.000,00'. '--color=WHEN (or --colour=WHEN)'       Should color-supporting commands use ANSI color codes in text@@ -196,7 +204,13 @@      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.+'--pretty[=WHEN]' +     Show prettier output, e.g.  using unicode box-drawing characters.+     Accepts 'yes' (the default) or 'no' ('y', 'n', 'always', 'never'+     also work).  If you provide an argument you must use '=', e.g.+     '-pretty=yes'.+    When a reporting option appears more than once in the command line, the last one takes precedence. @@ -594,32 +608,32 @@  Tag Table: Node: Top221-Node: OPTIONS1646-Ref: #options1743-Node: KEYS6144-Ref: #keys6239-Node: SCREENS10310-Ref: #screens10408-Node: Accounts screen10498-Ref: #accounts-screen10626-Node: Register screen12841-Ref: #register-screen12996-Node: Transaction screen14993-Ref: #transaction-screen15151-Node: Error screen16021-Ref: #error-screen16143-Node: TIPS16387-Ref: #tips16486-Node: Watch mode16538-Ref: #watch-mode16655-Node: Watch mode limitations17401-Ref: #watch-mode-limitations17542-Node: ENVIRONMENT18678-Ref: #environment18789-Node: FILES19596-Ref: #files19695-Node: BUGS19908-Ref: #bugs19985+Node: OPTIONS1644+Ref: #options1741+Node: KEYS6620+Ref: #keys6715+Node: SCREENS10786+Ref: #screens10884+Node: Accounts screen10974+Ref: #accounts-screen11102+Node: Register screen13317+Ref: #register-screen13472+Node: Transaction screen15469+Ref: #transaction-screen15627+Node: Error screen16497+Ref: #error-screen16619+Node: TIPS16863+Ref: #tips16962+Node: Watch mode17014+Ref: #watch-mode17131+Node: Watch mode limitations17877+Ref: #watch-mode-limitations18018+Node: ENVIRONMENT19154+Ref: #environment19265+Node: FILES20072+Ref: #files20171+Node: BUGS20384+Ref: #bugs20461  End Tag Table 
hledger-ui.txt view
@@ -5,7 +5,7 @@  NAME        hledger-ui  is  a  terminal  interface (TUI) for the hledger accounting-       tool.  This manual is for hledger-ui 1.22.2.+       tool.  This manual is for hledger-ui 1.23.  SYNOPSIS        hledger-ui [OPTIONS] [QUERYARGS]@@ -122,6 +122,10 @@               match the secondary date instead (see  command  help  for  other               effects) +       --today=DATE+              override   today's  date  (affects  relative  smart  dates,  for+              tests/examples)+        -U --unmarked               include only unmarked postings/txns (can combine with -P or -C) @@ -138,34 +142,38 @@               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-market-prices-              use  transaction  prices  (recorded  with @ or @@) as additional+              use transaction prices (recorded with @  or  @@)  as  additional               market prices, as if they were P directives         --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. +       --commodity-style+              Override  the  commodity  style  in the output for the specified+              commodity.  For example 'EUR1.000,00'.+        --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-@@ -173,6 +181,12 @@               piping  output  into  'less  -R'.   'never'  or  'no': never.  A               NO_COLOR environment variable overrides this. +       --pretty[=WHEN]+              Show prettier output, e.g.  using  unicode  box-drawing  charac-+              ters.   Accepts 'yes' (the default) or 'no' ('y', 'n', 'always',+              'never' also work).  If you provide an  argument  you  must  use+              '=', e.g.  '--pretty=yes'.+        When a reporting option appears more than once in the command line, the        last one takes precedence. @@ -194,86 +208,86 @@               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+       actions   generated  by  rule.   F  toggles  forecast  mode,  in  which        future/forecasted transactions are shown. -       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+       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        entry 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.         q quits the application.@@ -282,44 +296,44 @@  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-       below).  In tree mode, all account balances  are  inclusive  of  subac-+       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+       below).   In  tree  mode,  all account balances are inclusive of subac-        counts. -       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-       depth limit, set it higher than the maximum  account  depth,  or  press+       less detail, collapsing all accounts to a single total.  To remove  the+       depth  limit,  set  it  higher than the maximum account depth, or press        ESCAPE.         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+       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        before 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+       toggles cleared postings.  (By default, balances include all  postings;+       if  you  activate  one  or  two status filters, only those postings are        included; 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.@@ -328,124 +342,124 @@        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,-       description, comments, along with  all  of  its  account  postings  are-       shown.   Simple  transactions  have two postings, but there can be more+       The transaction's date(s)  and  any  cleared  flag,  transaction  code,+       description,  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+       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        depending on which account register you came from (remember most trans-        actions 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.)  TIPS    Watch mode-       One  of  hledger-ui's best features is the auto-reloading --watch mode.-       With this flag, it  will  update  the  display  automatically  whenever+       One of hledger-ui's best features is the auto-reloading  --watch  mode.+       With  this  flag,  it  will  update  the display automatically whenever        changes are saved to the data files. -       This  is very useful when reconciling.  A good workflow is to have your-       bank's online register open in a browser  window,  for  reference;  the-       journal  file open in an editor window; and hledger-ui in watch mode in+       This is very useful when reconciling.  A good workflow is to have  your+       bank's  online  register  open  in a browser window, for reference; the+       journal file open in an editor window; and hledger-ui in watch mode  in        a terminal window, eg:                $ hledger-ui --watch --register checking -C -       As you mark things cleared in the editor, you can see the effect  imme--       diately  without  having  to  context  switch.  This leaves more mental-       bandwidth for your accounting.  Of course you can still  interact  with-       hledger-ui  when  needed,  eg to toggle cleared mode, or to explore the+       As  you mark things cleared in the editor, you can see the effect imme-+       diately without having to context  switch.   This  leaves  more  mental+       bandwidth  for  your accounting.  Of course you can still interact with+       hledger-ui when needed, eg to toggle cleared mode, or  to  explore  the        history.     Watch mode limitations-       There are situations in which it won't work, ie the  display  will  not-       update  when  you save a change (because the underlying inotify library+       There  are  situations  in which it won't work, ie the display will not+       update when you save a change (because the underlying  inotify  library        does not support it).  Here are some that we know of: -       o Certain editors: saving with gedit, and perhaps  any  Gnome  applica--         tion,  won't be detected (#1617).  Jetbrains IDEs, such as IDEA, also+       o Certain  editors:  saving  with gedit, and perhaps any Gnome applica-+         tion, won't be detected (#1617).  Jetbrains IDEs, such as IDEA,  also          may not work (#911). -       o Certain unusual filesystems might not be supported.  (All  the  usual+       o Certain  unusual  filesystems might not be supported.  (All the usual          ones on unix, mac and windows are supported.)         In such cases, the workaround is to switch to the hledger-ui window and-       press g each time you want it to  reload.   (Actually,  see  #1617  for+       press  g  each  time  you  want it to reload.  (Actually, see #1617 for        another workaround, and let us know if it works for you.) -       If  you leave hledger-ui --watch running for days, on certain platforms-       (?), perhaps with many transactions in your journal (?),  perhaps  with-       large  numbers  of  other  files  present (?), you may see it gradually-       using more and more memory and CPU over time, as seen in top or  Activ-+       If you leave hledger-ui --watch running for days, on certain  platforms+       (?),  perhaps  with many transactions in your journal (?), perhaps with+       large numbers of other files present (?),  you  may  see  it  gradually+       using  more and more memory and CPU over time, as seen in top or Activ-        ity Monitor or Task Manager. -       A  workaround  is to quit and restart it, or to suspend it (CTRL-z) and+       A workaround is to quit and restart it, or to suspend it  (CTRL-z)  and        restart it (fg) if your shell supports that.  ENVIRONMENT        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-       (say,   an   Emacs   dock  icon).   Eg  on  MacOS  Catalina  I  have  a+       more  thorough  way that also affects applications started from the GUI+       (say,  an  Emacs  dock  icon).   Eg  on  MacOS  Catalina   I   have   a        ~/.MacOSX/environment.plist file containing                {@@ -455,13 +469,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).@@ -469,24 +483,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)  @@ -504,4 +518,4 @@   -hledger-ui-1.22.2                 August 2021                    HLEDGER-UI(1)+hledger-ui-1.23                 September 2021                   HLEDGER-UI(1)