diff --git a/hledger-ui/Hledger/UI/AccountsScreen.hs b/hledger-ui/Hledger/UI/AccountsScreen.hs index ef5e43856..2e40e68c9 100644 --- a/hledger-ui/Hledger/UI/AccountsScreen.hs +++ b/hledger-ui/Hledger/UI/AccountsScreen.hs @@ -208,7 +208,11 @@ handleAccountsScreen st@AppState{ acct = case listSelectedElement l of Just (_, (_, fullacct, _, _)) -> fullacct Nothing -> "" - reload = continue . initAccountsScreen (Just acct) d + + -- Customize reload to preserve the account selection while reloading. + -- XXX reloads only the current screen, not previous ones - ok for now as accounts screen is always the first + -- XXX won't have any effect when this screen is reloaded by a deeper screen's reload - should move selected acct into state + reload' = initAccountsScreen (Just acct) case e of Vty.EvKey Vty.KEsc [] -> halt st @@ -218,7 +222,7 @@ handleAccountsScreen st@AppState{ Vty.EvKey (Vty.KChar 'g') [] -> do ej <- liftIO $ journalReload j case ej of - Right j' -> reload st{ajournal=j'} + Right j' -> continue $ reload j' d st Left err -> continue $ screenEnter d ES.screen{esState=err} st -- (ej, changed) <- liftIO $ journalReloadIfChanged copts j -- case (changed, ej) of @@ -226,20 +230,20 @@ handleAccountsScreen st@AppState{ -- -- (True, Left err) -> continue st{amsg=err} -- XXX report parse error -- _ -> continue st - Vty.EvKey (Vty.KChar '-') [] -> reload $ decDepth st - Vty.EvKey (Vty.KChar '+') [] -> reload $ incDepth st - Vty.EvKey (Vty.KChar '=') [] -> reload $ incDepth st - Vty.EvKey (Vty.KChar '1') [] -> reload $ setDepth 1 st - Vty.EvKey (Vty.KChar '2') [] -> reload $ setDepth 2 st - Vty.EvKey (Vty.KChar '3') [] -> reload $ setDepth 3 st - Vty.EvKey (Vty.KChar '4') [] -> reload $ setDepth 4 st - Vty.EvKey (Vty.KChar '5') [] -> reload $ setDepth 5 st - Vty.EvKey (Vty.KChar '6') [] -> reload $ setDepth 6 st - Vty.EvKey (Vty.KChar '7') [] -> reload $ setDepth 7 st - Vty.EvKey (Vty.KChar '8') [] -> reload $ setDepth 8 st - Vty.EvKey (Vty.KChar '9') [] -> reload $ setDepth 9 st - Vty.EvKey (Vty.KChar '0') [] -> reload $ setDepth 0 st - Vty.EvKey (Vty.KChar 'f') [] -> reload $ st' + Vty.EvKey (Vty.KChar '-') [] -> continue $ reload' d $ decDepth st + Vty.EvKey (Vty.KChar '+') [] -> continue $ reload' d $ incDepth st + Vty.EvKey (Vty.KChar '=') [] -> continue $ reload' d $ incDepth st + Vty.EvKey (Vty.KChar '1') [] -> continue $ reload' d $ setDepth 1 st + Vty.EvKey (Vty.KChar '2') [] -> continue $ reload' d $ setDepth 2 st + Vty.EvKey (Vty.KChar '3') [] -> continue $ reload' d $ setDepth 3 st + Vty.EvKey (Vty.KChar '4') [] -> continue $ reload' d $ setDepth 4 st + Vty.EvKey (Vty.KChar '5') [] -> continue $ reload' d $ setDepth 5 st + Vty.EvKey (Vty.KChar '6') [] -> continue $ reload' d $ setDepth 6 st + Vty.EvKey (Vty.KChar '7') [] -> continue $ reload' d $ setDepth 7 st + Vty.EvKey (Vty.KChar '8') [] -> continue $ reload' d $ setDepth 8 st + Vty.EvKey (Vty.KChar '9') [] -> continue $ reload' d $ setDepth 9 st + Vty.EvKey (Vty.KChar '0') [] -> continue $ reload' d $ setDepth 0 st + Vty.EvKey (Vty.KChar 'f') [] -> continue $ reload' d $ st' where st' = st{ aopts=(aopts st){ diff --git a/hledger-ui/Hledger/UI/ErrorScreen.hs b/hledger-ui/Hledger/UI/ErrorScreen.hs index 023702c3a..1f8ecfa58 100644 --- a/hledger-ui/Hledger/UI/ErrorScreen.hs +++ b/hledger-ui/Hledger/UI/ErrorScreen.hs @@ -103,24 +103,16 @@ handleErrorScreen st@AppState{ ,aopts=UIOpts{cliopts_=_copts} ,ajournal=j } e = do - -- d <- liftIO getCurrentDay - -- let - -- reload = continue . initErrorScreen d case e of Vty.EvKey Vty.KEsc [] -> halt st Vty.EvKey (Vty.KChar 'q') [] -> halt st Vty.EvKey (Vty.KChar 'g') [] -> do - ej <- liftIO $ journalReload j + d <- liftIO getCurrentDay + ej <- liftIO $ journalReload j -- (ej, changed) <- liftIO $ journalReloadIfChanged copts j case ej of Left err -> continue st{aScreen=s{esState=err}} -- show latest parse error - Right _j' -> continue $ popScreen st -- return to previous screen. XXX should reload it too - - -- (ej, changed) <- liftIO $ journalReloadIfChanged copts j - -- case (changed, ej) of - -- (True, Right j') -> reload st{ajournal=j'} - -- -- (True, Left err) -> continue st{amsg=err} -- XXX report parse error - -- _ -> continue st + Right j' -> continue $ reload j' d $ popScreen st -- return to previous screen, and reload it -- Vty.EvKey (Vty.KLeft) [] -> continue $ popScreen st -- Vty.EvKey (Vty.KRight) [] -> error (show curItem) where curItem = listSelectedElement is diff --git a/hledger-ui/Hledger/UI/RegisterScreen.hs b/hledger-ui/Hledger/UI/RegisterScreen.hs index 764954f25..92e49be76 100644 --- a/hledger-ui/Hledger/UI/RegisterScreen.hs +++ b/hledger-ui/Hledger/UI/RegisterScreen.hs @@ -185,26 +185,19 @@ drawRegisterItem (datewidth,descwidth,acctswidth,changewidth,balwidth) selected handleRegisterScreen :: AppState -> Vty.Event -> EventM (Next AppState) handleRegisterScreen st@AppState{ aScreen=s@RegisterScreen{rsState=is} - ,aopts=UIOpts{cliopts_=copts} + ,aopts=UIOpts{cliopts_=_copts} ,ajournal=j } e = do - d <- liftIO getCurrentDay - let - reload = continue . initRegisterScreen d case e of Vty.EvKey Vty.KEsc [] -> halt st Vty.EvKey (Vty.KChar 'q') [] -> halt st Vty.EvKey (Vty.KChar 'g') [] -> do - ej <- liftIO $ journalReload j + d <- liftIO getCurrentDay + ej <- liftIO $ journalReload j -- (ej, changed) <- liftIO $ journalReloadIfChanged copts j case ej of - Right j' -> reload st{ajournal=j'} + Right j' -> continue $ reload j' d st Left err -> continue $ screenEnter d ES.screen{esState=err} st - -- (ej, changed) <- liftIO $ journalReloadIfChanged copts j - -- case (changed, ej) of - -- (True, Right j') -> reload st{ajournal=j'} - -- -- (True, Left err) -> continue st{amsg=err} -- XXX report parse error - -- _ -> continue st Vty.EvKey (Vty.KLeft) [] -> continue $ popScreen st -- Vty.EvKey (Vty.KRight) [] -> error (show curItem) where curItem = listSelectedElement is diff --git a/hledger-ui/Hledger/UI/UIUtils.hs b/hledger-ui/Hledger/UI/UIUtils.hs index 5b6572791..52351173b 100644 --- a/hledger-ui/Hledger/UI/UIUtils.hs +++ b/hledger-ui/Hledger/UI/UIUtils.hs @@ -4,6 +4,7 @@ module Hledger.UI.UIUtils ( pushScreen ,popScreen ,screenEnter + ,reload ,getViewportSize -- ,margin ,withBorderAttr @@ -29,7 +30,24 @@ import Brick.Widgets.Border.Style import Graphics.Vty as Vty import Hledger.UI.UITypes +import Hledger.Data.Types (Journal) import Hledger.Utils (applyN) +-- import Hledger.Utils.Debug + +-- | Regenerate the content for the current and previous screens, from a new journal and current date. +reload :: Journal -> Day -> AppState -> AppState +reload j d st@AppState{aScreen=s,aPrevScreens=ss} = + -- clumsy due to entanglement of AppState and Screen. + -- sInitFn operates only on an appstate's current screen, so + -- remove all the screens from the appstate and then add them back + -- one at a time, regenerating as we go. + let + first:rest = reverse $ s:ss + st0 = st{ajournal=j, aScreen=first, aPrevScreens=[]} + st1 = (sInitFn first) d st0 + st2 = foldl' (\st s -> (sInitFn s) d $ pushScreen s st) st1 rest + in + st2 pushScreen :: Screen -> AppState -> AppState pushScreen scr st = st{aPrevScreens=(aScreen st:aPrevScreens st) diff --git a/hledger-ui/hledger-ui.1.md b/hledger-ui/hledger-ui.1.md index 116c724ef..fcaf820da 100644 --- a/hledger-ui/hledger-ui.1.md +++ b/hledger-ui/hledger-ui.1.md @@ -178,6 +178,7 @@ The need to precede options with `--` when invoked from hledger is awkward. `-V` doesn't affect the register screen. -If you reload while in the register screen, when you return to the -accounts screen it will be showing old data, and pressing g again will -not reload it; you must adjust depth to force it (eg press 0). +When you press `g`, the current and all previous screens are +regenerated. With large data this will cause a noticeable pause, +which could be reduced if the previous screens were processed in a +background thread.