From 7868da2a48121d63c7da52c8c5b5c17fe41f7013 Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Sat, 18 Jul 2020 12:24:37 -0700 Subject: [PATCH] ui: ESC now restores exactly to initial app state (#1286) Also resetFilter (DEL/BS key) no longer changes tree/list mode. --- hledger-ui/Hledger/UI/Main.hs | 6 ++++-- hledger-ui/Hledger/UI/UIState.hs | 14 ++++++++++---- hledger-ui/Hledger/UI/UITypes.hs | 3 ++- hledger-ui/Hledger/UI/UIUtils.hs | 12 +++++------- hledger-ui/hledger-ui.m4.md | 5 +++-- 5 files changed, 24 insertions(+), 16 deletions(-) diff --git a/hledger-ui/Hledger/UI/Main.hs b/hledger-ui/Hledger/UI/Main.hs index 5491b39f0..f788eb369 100644 --- a/hledger-ui/Hledger/UI/Main.hs +++ b/hledger-ui/Hledger/UI/Main.hs @@ -136,7 +136,8 @@ runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportopts_=rop ascr' = aScreen $ asInit d True UIState{ - aopts=uopts' + astartupopts=uopts' + ,aopts=uopts' ,ajournal=j ,aScreen=asSetSelectedAccount acct accountsScreen ,aPrevScreens=[] @@ -147,7 +148,8 @@ runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportopts_=rop (sInit scr) d True $ (if change_ uopts' then toggleHistorical else id) -- XXX UIState{ - aopts=uopts' + astartupopts=uopts' + ,aopts=uopts' ,ajournal=j ,aScreen=scr ,aPrevScreens=prevscrs diff --git a/hledger-ui/Hledger/UI/UIState.hs b/hledger-ui/Hledger/UI/UIState.hs index 58672cf8c..3d0f8d76c 100644 --- a/hledger-ui/Hledger/UI/UIState.hs +++ b/hledger-ui/Hledger/UI/UIState.hs @@ -245,18 +245,22 @@ 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}}}} --- | Clear all filters/flags. +-- | 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{ - accountlistmode_=ALFlat - ,empty_=True + empty_=True ,statuses_=[] ,real_=False ,query_="" --,period_=PeriodAll }}}} +-- | Reset all options state to exactly what it was at startup +-- (preserving any command-line options/arguments). +resetOpts :: UIState -> UIState +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}}}} @@ -345,7 +349,9 @@ popScreen ui = ui resetScreens :: Day -> UIState -> UIState resetScreens d ui@UIState{aScreen=s,aPrevScreens=ss} = - (sInit topscreen) d True $ resetDepth $ resetReportPeriod $ resetFilter $ closeMinibuffer ui{aScreen=topscreen, aPrevScreens=[]} + (sInit topscreen) d True $ + resetOpts $ + closeMinibuffer ui{aScreen=topscreen, aPrevScreens=[]} where topscreen = case ss of _:_ -> last ss [] -> s diff --git a/hledger-ui/Hledger/UI/UITypes.hs b/hledger-ui/Hledger/UI/UITypes.hs index 43937e1c3..a5d2c96ae 100644 --- a/hledger-ui/Hledger/UI/UITypes.hs +++ b/hledger-ui/Hledger/UI/UITypes.hs @@ -54,7 +54,8 @@ import Hledger.UI.UIOptions -- The app can be in one of several modes: normal screen operation, -- showing a help dialog, entering data in the minibuffer etc. data UIState = UIState { - aopts :: UIOpts -- ^ the command-line options and query arguments currently in effect + astartupopts :: UIOpts -- ^ the command-line options and query arguments specified at startup + ,aopts :: UIOpts -- ^ the command-line options and query arguments currently in effect ,ajournal :: Journal -- ^ the journal being viewed ,aPrevScreens :: [Screen] -- ^ previously visited screens, most recent first ,aScreen :: Screen -- ^ the currently active screen diff --git a/hledger-ui/Hledger/UI/UIUtils.hs b/hledger-ui/Hledger/UI/UIUtils.hs index 3f849cfa0..4bdc988fc 100644 --- a/hledger-ui/Hledger/UI/UIUtils.hs +++ b/hledger-ui/Hledger/UI/UIUtils.hs @@ -98,11 +98,10 @@ helpDialog _copts = vBox [ withAttr ("help" <> "heading") $ str "Navigation" ,renderKey ("UP/DOWN/PUP/PDN/HOME/END/k/j/C-p/C-n", "") - ,str " move selection up/down" - ,renderKey ("RIGHT/l/C-f", "") - ,str " show account txns, or txn detail" + ,str " move selection up/down" + ,renderKey ("RIGHT/l/C-f", "show txns, or txn detail") ,renderKey ("LEFT/h/C-b ", "go back") - ,renderKey ("ESC ", "cancel or reset") + ,renderKey ("ESC ", "cancel or reset to initial state") ,str " " ,withAttr ("help" <> "heading") $ str "Accounts screen" @@ -168,15 +167,14 @@ helpHandle :: UIState -> BrickEvent Name AppEvent -> EventM Name (Next UIState) helpHandle ui ev = do pagerprog <- liftIO $ fromMaybe "less" <$> lookupEnv "PAGER" case ev of - VtyEvent e - | e `elem` (moveLeftEvents ++ [EvKey KEsc [], EvKey (KChar '?') [], EvKey (KChar 'q') []]) - -> continue $ setMode Normal ui + VtyEvent e | e `elem` closeHelpEvents -> continue $ setMode Normal ui VtyEvent (EvKey (KChar 'p') []) -> suspendAndResume $ runPagerForTopic pagerprog "hledger-ui" >> return ui' VtyEvent (EvKey (KChar 'm') []) -> suspendAndResume $ runManForTopic "hledger-ui" >> return ui' VtyEvent (EvKey (KChar 'i') []) -> suspendAndResume $ runInfoForTopic "hledger-ui" >> return ui' _ -> continue ui where ui' = setMode Normal ui + closeHelpEvents = moveLeftEvents ++ [EvKey KEsc [], EvKey (KChar '?') [], EvKey (KChar 'q') []] -- | Draw the minibuffer. minibuffer :: Editor String Name -> Widget Name diff --git a/hledger-ui/hledger-ui.m4.md b/hledger-ui/hledger-ui.m4.md index a1f8dbad7..b1ad65db6 100644 --- a/hledger-ui/hledger-ui.m4.md +++ b/hledger-ui/hledger-ui.m4.md @@ -131,8 +131,9 @@ both ordinary transactions recorded in the journal, and periodic transactions generated by rule. `f` toggles forecast mode, in which future/forecasted transactions are shown. *(experimental)* -`escape` removes all filters and report period limits and jumps back to the top screen. -Or, it cancels minibuffer data entry or a help popup. +`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 (selections near the top won't be centered, since we don't scroll above the top).