dev: ui: avoid MonadFail entirely, simplifying ghc version compat (#1889)

This commit is contained in:
Simon Michael 2022-08-17 15:22:20 +01:00
parent 2a594b7fb7
commit 4bd9f4a6f7
5 changed files with 363 additions and 349 deletions

View File

@ -227,24 +227,25 @@ asDrawItem (acctwidth, balwidth) selected AccountsScreenItem{..} =
asHandle :: BrickEvent Name AppEvent -> EventM Name UIState () asHandle :: BrickEvent Name AppEvent -> EventM Name UIState ()
asHandle ev = do asHandle ev = do
ui0@UIState{ ui0 <- get
case ui0 of
ui1@UIState{
aScreen=scr@AccountsScreen{..} aScreen=scr@AccountsScreen{..}
,aopts=UIOpts{uoCliOpts=copts} ,aopts=UIOpts{uoCliOpts=copts}
,ajournal=j ,ajournal=j
,aMode=mode ,aMode=mode
} <- get -- PARTIAL: should not fail } -> do
let
d = copts^.rsDay
nonblanks = V.takeWhile (not . T.null . asItemAccountName) $ _asList^.listElementsL
lastnonblankidx = max 0 (length nonblanks - 1)
journalspan = journalDateSpan False j
-- save the currently selected account, in case we leave this screen and lose the selection
let let
-- save the currently selected account, in case we leave this screen and lose the selection
selacct = case listSelectedElement _asList of selacct = case listSelectedElement _asList of
Just (_, AccountsScreenItem{..}) -> asItemAccountName Just (_, AccountsScreenItem{..}) -> asItemAccountName
Nothing -> scr ^. asSelectedAccount Nothing -> scr ^. asSelectedAccount
ui = ui0{aScreen=scr & asSelectedAccount .~ selacct} ui = ui1{aScreen=scr & asSelectedAccount .~ selacct}
nonblanks = V.takeWhile (not . T.null . asItemAccountName) $ _asList^.listElementsL
lastnonblankidx = max 0 (length nonblanks - 1)
journalspan = journalDateSpan False j
d = copts^.rsDay
case mode of case mode of
Minibuffer _ ed -> Minibuffer _ ed ->
@ -334,7 +335,7 @@ asHandle ev = do
-- MouseDown is sometimes duplicated, https://github.com/jtdaugherty/brick/issues/347 -- MouseDown is sometimes duplicated, https://github.com/jtdaugherty/brick/issues/347
-- just use it to move the selection -- just use it to move the selection
MouseDown _n BLeft _mods Location{loc=(_x,y)} | not $ (=="") clickedacct -> do MouseDown _n BLeft _mods Location{loc=(_x,y)} | not $ (=="") clickedacct -> do
case scr of AccountsScreen{} -> put ui{aScreen=scr}; _ -> fail "" -- PARTIAL: should not happen put ui{aScreen=scr} -- XXX does this do anything ?
where clickedacct = maybe "" asItemAccountName $ listElements _asList !? y where clickedacct = maybe "" asItemAccountName $ listElements _asList !? y
-- and on MouseUp, enter the subscreen -- and on MouseUp, enter the subscreen
MouseUp _n (Just BLeft) Location{loc=(_x,y)} | not $ (=="") clickedacct -> do MouseUp _n (Just BLeft) Location{loc=(_x,y)} | not $ (=="") clickedacct -> do
@ -343,7 +344,7 @@ asHandle ev = do
-- when selection is at the last item, DOWN scrolls instead of moving, until maximally scrolled -- when selection is at the last item, DOWN scrolls instead of moving, until maximally scrolled
VtyEvent e | e `elem` moveDownEvents, isBlankElement mnextelement -> do VtyEvent e | e `elem` moveDownEvents, isBlankElement mnextelement -> do
vScrollBy (viewportScroll $ _asList^.listNameL) 1 >> put ui vScrollBy (viewportScroll $ _asList^.listNameL) 1
where mnextelement = listSelectedElement $ listMoveDown _asList where mnextelement = listSelectedElement $ listMoveDown _asList
-- mouse scroll wheel scrolls the viewport up or down to its maximum extent, -- mouse scroll wheel scrolls the viewport up or down to its maximum extent,
@ -351,7 +352,7 @@ asHandle ev = do
MouseDown name btn _mods _loc | btn `elem` [BScrollUp, BScrollDown] -> do MouseDown name btn _mods _loc | btn `elem` [BScrollUp, BScrollDown] -> do
let scrollamt = if btn==BScrollUp then -1 else 1 let scrollamt = if btn==BScrollUp then -1 else 1
list' <- nestEventM' _asList $ listScrollPushingSelection name (asListSize _asList) scrollamt list' <- nestEventM' _asList $ listScrollPushingSelection name (asListSize _asList) scrollamt
case scr of AccountsScreen{} -> put ui{aScreen=scr{_asList=list'}}; _ -> fail "" -- PARTIAL: should not fail put ui{aScreen=scr{_asList=list'}}
-- if page down or end leads to a blank padding item, stop at last non-blank -- if page down or end leads to a blank padding item, stop at last non-blank
VtyEvent e@(EvKey k []) | k `elem` [KPageDown, KEnd] -> do VtyEvent e@(EvKey k []) | k `elem` [KPageDown, KEnd] -> do
@ -360,9 +361,9 @@ asHandle ev = do
then do then do
let list' = listMoveTo lastnonblankidx list let list' = listMoveTo lastnonblankidx list
scrollSelectionToMiddle list' scrollSelectionToMiddle list'
case scr of AccountsScreen{} -> put ui{aScreen=scr{_asList=list'}}; _ -> fail "" -- PARTIAL: should not fail put ui{aScreen=scr{_asList=list'}}
else else
case scr of AccountsScreen{} -> put ui{aScreen=scr{_asList=list}}; _ -> fail "" -- PARTIAL: should not fail put ui{aScreen=scr{_asList=list}}
-- fall through to the list's event handler (handles up/down) -- fall through to the list's event handler (handles up/down)
VtyEvent ev -> do VtyEvent ev -> do
@ -373,6 +374,8 @@ asHandle ev = do
MouseUp{} -> put ui MouseUp{} -> put ui
AppEvent _ -> put ui AppEvent _ -> put ui
_ -> errorWrongScreenType
asEnterRegister d selacct ui = do asEnterRegister d selacct ui = do
rsCenterAndContinue $ rsCenterAndContinue $
-- flip rsHandle (VtyEvent (EvKey (KChar 'l') [MCtrl])) $ -- flip rsHandle (VtyEvent (EvKey (KChar 'l') [MCtrl])) $

View File

@ -77,11 +77,13 @@ esDraw _ = error "draw function called with wrong screen type, should not happen
esHandle :: BrickEvent Name AppEvent -> EventM Name UIState () esHandle :: BrickEvent Name AppEvent -> EventM Name UIState ()
esHandle ev = do esHandle ev = do
ui0 <- get
case ui0 of
ui@UIState{aScreen=ErrorScreen{..} ui@UIState{aScreen=ErrorScreen{..}
,aopts=UIOpts{uoCliOpts=copts} ,aopts=UIOpts{uoCliOpts=copts}
,ajournal=j ,ajournal=j
,aMode=mode ,aMode=mode
} <- get } ->
case mode of case mode of
Help -> Help ->
case ev of case ev of
@ -103,15 +105,17 @@ esHandle ev = do
Left _ -> (endPosition, journalFilePath j) Left _ -> (endPosition, journalFilePath j)
e | e `elem` [VtyEvent (EvKey (KChar 'g') []), AppEvent FileChange] -> e | e `elem` [VtyEvent (EvKey (KChar 'g') []), AppEvent FileChange] ->
liftIO (uiReloadJournal copts d (popScreen ui)) >>= put . uiCheckBalanceAssertions d liftIO (uiReloadJournal copts d (popScreen ui)) >>= put . uiCheckBalanceAssertions d
-- (ej, _) <- liftIO $ journalReloadIfChanged copts d j -- (ej, _) <- liftIO $ journalReloadIfChanged copts d j
-- case ej of -- case ej of
-- Left err -> continue ui{aScreen=s{esError=err}} -- show latest parse error -- Left err -> continue ui{aScreen=s{esError=err}} -- show latest parse error
-- Right j' -> continue $ regenerateScreens j' d $ popScreen ui -- return to previous screen, and reload it -- Right j' -> continue $ regenerateScreens j' d $ popScreen ui -- return to previous screen, and reload it
VtyEvent (EvKey (KChar 'I') []) -> put $ uiCheckBalanceAssertions d (popScreen $ toggleIgnoreBalanceAssertions ui) VtyEvent (EvKey (KChar 'I') []) -> put $ uiCheckBalanceAssertions d (popScreen $ toggleIgnoreBalanceAssertions ui)
VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw
VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspend ui VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspend ui
_ -> return () _ -> return ()
_ -> errorWrongScreenType
-- | Parse the file name, line and column number from a hledger parse error message, if possible. -- | Parse the file name, line and column number from a hledger parse error message, if possible.
-- Temporary, we should keep the original parse error location. XXX -- Temporary, we should keep the original parse error location. XXX
-- Keep in sync with 'Hledger.Data.Transaction.showGenericSourcePos' -- Keep in sync with 'Hledger.Data.Transaction.showGenericSourcePos'

View File

@ -279,12 +279,14 @@ rsDrawItem (datewidth,descwidth,acctswidth,changewidth,balwidth) selected Regist
rsHandle :: BrickEvent Name AppEvent -> EventM Name UIState () rsHandle :: BrickEvent Name AppEvent -> EventM Name UIState ()
rsHandle ev = do rsHandle ev = do
ui0 <- get
case ui0 of
ui@UIState{ ui@UIState{
aScreen=s@RegisterScreen{..} aScreen=s@RegisterScreen{..}
,aopts=UIOpts{uoCliOpts=copts} ,aopts=UIOpts{uoCliOpts=copts}
,ajournal=j ,ajournal=j
,aMode=mode ,aMode=mode
} <- get } -> do
let let
d = copts^.rsDay d = copts^.rsDay
journalspan = journalDateSpan False j journalspan = journalDateSpan False j
@ -417,6 +419,8 @@ rsHandle ev = do
MouseUp{} -> put ui MouseUp{} -> put ui
AppEvent _ -> put ui AppEvent _ -> put ui
_ -> errorWrongScreenType
isBlankElement mel = ((rsItemDate . snd) <$> mel) == Just "" isBlankElement mel = ((rsItemDate . snd) <$> mel) == Just ""
rsCenterAndContinue ui = do rsCenterAndContinue ui = do

View File

@ -143,11 +143,13 @@ tsDraw _ = error "draw function called with wrong screen type, should not happen
tsHandle :: BrickEvent Name AppEvent -> EventM Name UIState () tsHandle :: BrickEvent Name AppEvent -> EventM Name UIState ()
tsHandle ev = do tsHandle ev = do
ui0 <- get
case ui0 of
ui@UIState{aScreen=TransactionScreen{tsTransaction=(i,t), tsTransactions=nts} ui@UIState{aScreen=TransactionScreen{tsTransaction=(i,t), tsTransactions=nts}
,aopts=UIOpts{uoCliOpts=copts@CliOpts{reportspec_=rspec@ReportSpec{_rsReportOpts=ropts}}} ,aopts=UIOpts{uoCliOpts=copts@CliOpts{reportspec_=rspec@ReportSpec{_rsReportOpts=ropts}}}
,ajournal=j ,ajournal=j
,aMode=mode ,aMode=mode
} <- get } ->
case mode of case mode of
Help -> Help ->
case ev of case ev of
@ -204,6 +206,8 @@ tsHandle ev = do
VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspend ui VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspend ui
_ -> return () _ -> return ()
_ -> errorWrongScreenType
-- | Select a new transaction and update the previous register screen -- | Select a new transaction and update the previous register screen
tsSelect i t ui@UIState{aScreen=s@TransactionScreen{}} = case aPrevScreens ui of tsSelect i t ui@UIState{aScreen=s@TransactionScreen{}} = case aPrevScreens ui of
x:xs -> ui'{aPrevScreens=rsSelect i x : xs} x:xs -> ui'{aPrevScreens=rsSelect i x : xs}

View File

@ -135,6 +135,9 @@ data Screen =
} }
deriving (Show) deriving (Show)
-- | Error message to use in case statements adapting to the different Screen shapes.
errorWrongScreenType = error' "handler called with wrong screen type, should not happen"
-- | An item in the accounts screen's list of accounts and balances. -- | An item in the accounts screen's list of accounts and balances.
data AccountsScreenItem = AccountsScreenItem { data AccountsScreenItem = AccountsScreenItem {
asItemIndentLevel :: Int -- ^ indent level asItemIndentLevel :: Int -- ^ indent level
@ -155,10 +158,6 @@ data RegisterScreenItem = RegisterScreenItem {
} }
deriving (Show) deriving (Show)
instance MonadFail (EventM Name UIState) where fail _ = wrongScreenTypeError
wrongScreenTypeError = error' "handler called with wrong screen type, should not happen"
type NumberedTransaction = (Integer, Transaction) type NumberedTransaction = (Integer, Transaction)
-- dummy monoid instance needed make lenses work with List fields not common across constructors -- dummy monoid instance needed make lenses work with List fields not common across constructors