From bbcbaf60804577aa91f6bcfb9c849d9d452bc3bf Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Tue, 7 Jun 2016 09:26:16 -0700 Subject: [PATCH] ui: Esc (outside minibuffer) resets, jumps to top --- hledger-ui/Hledger/UI/AccountsScreen.hs | 15 ++++++----- hledger-ui/Hledger/UI/ErrorScreen.hs | 10 +++---- hledger-ui/Hledger/UI/Main.hs | 4 +-- hledger-ui/Hledger/UI/RegisterScreen.hs | 15 ++++++----- hledger-ui/Hledger/UI/TransactionScreen.hs | 8 +++--- hledger-ui/Hledger/UI/UITypes.hs | 13 ++++----- hledger-ui/Hledger/UI/UIUtils.hs | 31 +++++++++++++++++++--- 7 files changed, 64 insertions(+), 32 deletions(-) diff --git a/hledger-ui/Hledger/UI/AccountsScreen.hs b/hledger-ui/Hledger/UI/AccountsScreen.hs index 0d10f2e13..1fab87ac0 100644 --- a/hledger-ui/Hledger/UI/AccountsScreen.hs +++ b/hledger-ui/Hledger/UI/AccountsScreen.hs @@ -49,8 +49,8 @@ screen = AccountsScreen{ asSetSelectedAccount a scr@AccountsScreen{asState=(l,_)} = scr{asState=(l,a)} asSetSelectedAccount _ scr = scr -initAccountsScreen :: Day -> AppState -> AppState -initAccountsScreen d st@AppState{ +initAccountsScreen :: Day -> Bool -> AppState -> AppState +initAccountsScreen d reset st@AppState{ aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}, ajournal=j, aScreen=s@AccountsScreen{asState=(oldl,selacct)} @@ -63,9 +63,10 @@ initAccountsScreen d st@AppState{ -- (may need to move to the next leaf account when entering flat mode) newl' = listMoveTo selidx newl where - selidx = case listSelectedElement oldl of - Nothing -> 0 - Just (_,(_,a,_,_)) -> fromMaybe (fromMaybe 0 mprefixmatch) mexactmatch + selidx = case (reset, listSelectedElement oldl) of + (True, _) -> 0 + (_, Nothing) -> 0 + (_, Just (_,(_,a,_,_))) -> fromMaybe (fromMaybe 0 mprefixmatch) mexactmatch where mexactmatch = findIndex ((a ==) . second4) displayitems mprefixmatch = findIndex ((a `isAccountNamePrefixOf`) . second4) displayitems @@ -99,7 +100,7 @@ initAccountsScreen d st@AppState{ displayitems = map displayitem items -initAccountsScreen _ _ = error "init function called with wrong screen type, should not happen" +initAccountsScreen _ _ _ = error "init function called with wrong screen type, should not happen" drawAccountsScreen :: AppState -> [Widget] drawAccountsScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}} @@ -153,6 +154,7 @@ drawAccountsScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}} ,("/", "filter") ,("DEL", "unfilter") ,("right/enter", "register") + ,("ESC", "cancel/top") ,("g", "reload") ,("q", "quit") ] @@ -253,6 +255,7 @@ handleAccountsScreen st@AppState{ case ev of Vty.EvKey (Vty.KChar 'q') [] -> halt st' -- Vty.EvKey (Vty.KChar 'l') [Vty.MCtrl] -> do + Vty.EvKey Vty.KEsc [] -> continue $ resetScreens d st' Vty.EvKey (Vty.KChar 'g') [] -> do (ej, _) <- liftIO $ journalReloadIfChanged copts d j diff --git a/hledger-ui/Hledger/UI/ErrorScreen.hs b/hledger-ui/Hledger/UI/ErrorScreen.hs index 02de808aa..c5351c93a 100644 --- a/hledger-ui/Hledger/UI/ErrorScreen.hs +++ b/hledger-ui/Hledger/UI/ErrorScreen.hs @@ -33,9 +33,9 @@ screen = ErrorScreen{ ,sHandleFn = handleErrorScreen } -initErrorScreen :: Day -> AppState -> AppState -initErrorScreen _ st@AppState{aScreen=ErrorScreen{}} = st -initErrorScreen _ _ = error "init function called with wrong screen type, should not happen" +initErrorScreen :: Day -> Bool -> AppState -> AppState +initErrorScreen _ _ st@AppState{aScreen=ErrorScreen{}} = st +initErrorScreen _ _ _ = error "init function called with wrong screen type, should not happen" drawErrorScreen :: AppState -> [Widget] drawErrorScreen AppState{ -- aopts=_uopts@UIOpts{cliopts_=_copts@CliOpts{reportopts_=_ropts@ReportOpts{query_=querystr}}}, @@ -103,12 +103,12 @@ handleErrorScreen st@AppState{ ,aopts=UIOpts{cliopts_=copts} ,ajournal=j } e = do + d <- liftIO getCurrentDay case e of - Vty.EvKey Vty.KEsc [] -> halt st Vty.EvKey (Vty.KChar 'q') [] -> halt st + Vty.EvKey Vty.KEsc [] -> continue $ resetScreens d st Vty.EvKey (Vty.KChar 'g') [] -> do - d <- liftIO getCurrentDay (ej, _) <- liftIO $ journalReloadIfChanged copts d j case ej of Left err -> continue st{aScreen=s{esState=err}} -- show latest parse error diff --git a/hledger-ui/Hledger/UI/Main.hs b/hledger-ui/Hledger/UI/Main.hs index 651d24e53..c7d20494b 100644 --- a/hledger-ui/Hledger/UI/Main.hs +++ b/hledger-ui/Hledger/UI/Main.hs @@ -109,7 +109,7 @@ runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} j = do -- Initialising the accounts screen is awkward, requiring -- another temporary AppState value.. ascr' = aScreen $ - AS.initAccountsScreen d $ + AS.initAccountsScreen d True $ AppState{ aopts=uopts' ,ajournal=j @@ -118,7 +118,7 @@ runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} j = do ,aMinibuffer=Nothing } - st = (sInitFn scr) d + st = (sInitFn scr) d True AppState{ aopts=uopts' ,ajournal=j diff --git a/hledger-ui/Hledger/UI/RegisterScreen.hs b/hledger-ui/Hledger/UI/RegisterScreen.hs index ec285be71..c67024def 100644 --- a/hledger-ui/Hledger/UI/RegisterScreen.hs +++ b/hledger-ui/Hledger/UI/RegisterScreen.hs @@ -45,8 +45,8 @@ screen = RegisterScreen{ rsSetCurrentAccount a scr@RegisterScreen{rsState=(l,_)} = scr{rsState=(l,a)} rsSetCurrentAccount _ scr = scr -initRegisterScreen :: Day -> AppState -> AppState -initRegisterScreen d st@AppState{aopts=opts, ajournal=j, aScreen=s@RegisterScreen{rsState=(oldl,acct)}} = +initRegisterScreen :: Day -> Bool -> AppState -> AppState +initRegisterScreen d reset st@AppState{aopts=opts, ajournal=j, aScreen=s@RegisterScreen{rsState=(oldl,acct)}} = st{aScreen=s{rsState=(newl',acct)}} where -- gather arguments and queries @@ -86,12 +86,13 @@ initRegisterScreen d st@AppState{aopts=opts, ajournal=j, aScreen=s@RegisterScree -- (eg after toggling nonzero mode), otherwise select the last element. newl' = listMoveTo newselidx newl where - newselidx = case listSelectedElement oldl of - Nothing -> endidx - Just (_,(_,_,_,_,_,Transaction{tindex=ti})) -> fromMaybe endidx $ findIndex ((==ti) . tindex . sixth6) displayitems + newselidx = case (reset, listSelectedElement oldl) of + (True, _) -> 0 + (_, Nothing) -> endidx + (_, Just (_,(_,_,_,_,_,Transaction{tindex=ti}))) -> fromMaybe endidx $ findIndex ((==ti) . tindex . sixth6) displayitems endidx = length displayitems -initRegisterScreen _ _ = error "init function called with wrong screen type, should not happen" +initRegisterScreen _ _ _ = error "init function called with wrong screen type, should not happen" drawRegisterScreen :: AppState -> [Widget] drawRegisterScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}} @@ -182,6 +183,7 @@ drawRegisterScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}} ,("/", "filter") ,("DEL", "unfilter") ,("right/enter", "transaction") + ,("ESC", "cancel/top") ,("g", "reload") ,("q", "quit") ] @@ -228,6 +230,7 @@ handleRegisterScreen st@AppState{ case ev of Vty.EvKey (Vty.KChar 'q') [] -> halt st + Vty.EvKey Vty.KEsc [] -> continue $ resetScreens d st Vty.EvKey (Vty.KChar 'g') [] -> do (ej, _) <- liftIO $ journalReloadIfChanged copts d j diff --git a/hledger-ui/Hledger/UI/TransactionScreen.hs b/hledger-ui/Hledger/UI/TransactionScreen.hs index cd1a716af..4b68bbf55 100644 --- a/hledger-ui/Hledger/UI/TransactionScreen.hs +++ b/hledger-ui/Hledger/UI/TransactionScreen.hs @@ -42,13 +42,13 @@ screen = TransactionScreen{ ,sHandleFn = handleTransactionScreen } -initTransactionScreen :: Day -> AppState -> AppState -initTransactionScreen _d st@AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=_ropts}} +initTransactionScreen :: Day -> Bool -> AppState -> AppState +initTransactionScreen _d _reset st@AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=_ropts}} ,ajournal=_j ,aScreen=s@TransactionScreen{tsState=((n,t),nts,a)}} = st{aScreen=s{tsState=((n,t),nts,a)}} -initTransactionScreen _ _ = error "init function called with wrong screen type, should not happen" +initTransactionScreen _ _ _ = error "init function called with wrong screen type, should not happen" drawTransactionScreen :: AppState -> [Widget] drawTransactionScreen AppState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}} @@ -104,8 +104,8 @@ handleTransactionScreen st@AppState{ (iprev,tprev) = maybe (i,t) ((i-1),) $ lookup (i-1) nts (inext,tnext) = maybe (i,t) ((i+1),) $ lookup (i+1) nts case e of - Vty.EvKey Vty.KEsc [] -> halt st Vty.EvKey (Vty.KChar 'q') [] -> halt st + Vty.EvKey Vty.KEsc [] -> continue $ resetScreens d st Vty.EvKey (Vty.KChar 'g') [] -> do d <- liftIO getCurrentDay diff --git a/hledger-ui/Hledger/UI/UITypes.hs b/hledger-ui/Hledger/UI/UITypes.hs index 7ca6157bd..cbdfb7b03 100644 --- a/hledger-ui/Hledger/UI/UITypes.hs +++ b/hledger-ui/Hledger/UI/UITypes.hs @@ -70,7 +70,8 @@ data Screen = ) ,AccountName -- full name of the currently selected account (or "") ) - ,sInitFn :: Day -> AppState -> AppState -- ^ function to generate the screen's state on entry or change + ,sInitFn :: Day -> Bool -> AppState -> AppState -- ^ function to generate/update the screen's state, + -- takes the current date and whether to reset the selection. ,sDrawFn :: AppState -> [Widget] -- ^ brick renderer to use for this screen ,sHandleFn :: AppState -> V.Event -> EventM (Next AppState) -- ^ brick event handler to use for this screen } @@ -85,22 +86,22 @@ data Screen = ) ,AccountName -- full name of the acct we are showing a register for ) - ,sInitFn :: Day -> AppState -> AppState -- ^ function to generate the screen's state on entry or change - ,sDrawFn :: AppState -> [Widget] -- ^ brick renderer to use for this screen - ,sHandleFn :: AppState -> V.Event -> EventM (Next AppState) -- ^ brick event handler to use for this screen + ,sInitFn :: Day -> Bool -> AppState -> AppState + ,sDrawFn :: AppState -> [Widget] + ,sHandleFn :: AppState -> V.Event -> EventM (Next AppState) } | TransactionScreen { tsState :: ((Integer, Transaction) -- the (numbered) transaction we are currently viewing ,[(Integer, Transaction)] -- the list of numbered transactions we can step through ,AccountName -- the account whose register we entered this screen from ) - ,sInitFn :: Day -> AppState -> AppState + ,sInitFn :: Day -> Bool -> AppState -> AppState ,sDrawFn :: AppState -> [Widget] ,sHandleFn :: AppState -> V.Event -> EventM (Next AppState) } | ErrorScreen { esState :: String -- error message to display - ,sInitFn :: Day -> AppState -> AppState + ,sInitFn :: Day -> Bool -> AppState -> AppState ,sDrawFn :: AppState -> [Widget] ,sHandleFn :: AppState -> V.Event -> EventM (Next AppState) } diff --git a/hledger-ui/Hledger/UI/UIUtils.hs b/hledger-ui/Hledger/UI/UIUtils.hs index 97ee6b83c..2bc2e5918 100644 --- a/hledger-ui/Hledger/UI/UIUtils.hs +++ b/hledger-ui/Hledger/UI/UIUtils.hs @@ -3,6 +3,7 @@ module Hledger.UI.UIUtils ( pushScreen ,popScreen + ,resetScreens ,screenEnter ,reload ,getViewportSize @@ -23,6 +24,7 @@ module Hledger.UI.UIUtils ( ,stToggleFlat ,stToggleReal ,stFilter + ,stResetFilter ,stShowMinibuffer ,stHideMinibuffer ) where @@ -98,6 +100,22 @@ stFilter :: String -> AppState -> AppState stFilter s st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} = st{aopts=uopts{cliopts_=copts{reportopts_=ropts{query_=s}}}} +-- | Clear all filter queries/flags. +stResetFilter :: AppState -> AppState +stResetFilter st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} = + st{aopts=uopts{cliopts_=copts{reportopts_=ropts{ + empty_=True + ,cleared_=False + ,pending_=False + ,uncleared_=False + ,real_=False + ,query_="" + }}}} + +stResetDepth :: AppState -> AppState +stResetDepth st@AppState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} = + st{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=Nothing}}}} + -- | Enable the minibuffer, setting its content to the current query with the cursor at the end. stShowMinibuffer st = st{aMinibuffer=Just e} where @@ -117,8 +135,8 @@ reload j d st@AppState{aScreen=s,aPrevScreens=ss} = 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 + st1 = (sInitFn first) d False st0 + st2 = foldl' (\st s -> (sInitFn s) d False $ pushScreen s st) st1 rest in st2 @@ -131,13 +149,20 @@ popScreen :: AppState -> AppState popScreen st@AppState{aPrevScreens=s:ss} = st{aScreen=s, aPrevScreens=ss} popScreen st = st +resetScreens :: Day -> AppState -> AppState +resetScreens d st@AppState{aScreen=s,aPrevScreens=ss} = + (sInitFn topscreen) d True $ stResetDepth $ stResetFilter $ stHideMinibuffer st{aScreen=topscreen, aPrevScreens=[]} + where + topscreen = case ss of _:_ -> last ss + [] -> s + -- clearScreens :: AppState -> AppState -- clearScreens st = st{aPrevScreens=[]} -- | Enter a new screen, saving the old screen & state in the -- navigation history and initialising the new screen's state. screenEnter :: Day -> Screen -> AppState -> AppState -screenEnter d scr st = (sInitFn scr) d $ +screenEnter d scr st = (sInitFn scr) d True $ pushScreen scr st