From 7eeb5e01ee92581adf457d79a46556968d1a6dc0 Mon Sep 17 00:00:00 2001 From: Simon Michael Date: Wed, 6 Jul 2016 15:08:57 -0700 Subject: [PATCH] ui: I toggles balance assertions This was a bit tricky. --- hledger-lib/Hledger/Data/Journal.hs | 1 + hledger-ui/Hledger/UI/AccountsScreen.hs | 1 + hledger-ui/Hledger/UI/ErrorScreen.hs | 20 ++++++++++++++++++-- hledger-ui/Hledger/UI/RegisterScreen.hs | 1 + hledger-ui/Hledger/UI/TransactionScreen.hs | 1 + hledger-ui/Hledger/UI/UIState.hs | 5 +++++ hledger-ui/Hledger/UI/UIUtils.hs | 1 + hledger-ui/doc/hledger-ui.1.m4.md | 3 +++ 8 files changed, 31 insertions(+), 2 deletions(-) diff --git a/hledger-lib/Hledger/Data/Journal.hs b/hledger-lib/Hledger/Data/Journal.hs index 6299e2446..d1452695f 100644 --- a/hledger-lib/Hledger/Data/Journal.hs +++ b/hledger-lib/Hledger/Data/Journal.hs @@ -53,6 +53,7 @@ module Hledger.Data.Journal ( canonicalStyleFrom, matchpats, nulljournal, + journalCheckBalanceAssertions, -- * Tests samplejournal, tests_Hledger_Data_Journal, diff --git a/hledger-ui/Hledger/UI/AccountsScreen.hs b/hledger-ui/Hledger/UI/AccountsScreen.hs index cfc6c6334..36b9d0754 100644 --- a/hledger-ui/Hledger/UI/AccountsScreen.hs +++ b/hledger-ui/Hledger/UI/AccountsScreen.hs @@ -271,6 +271,7 @@ asHandle ui0@UIState{ EvKey KEsc [] -> continue $ resetScreens d ui EvKey (KChar c) [] | c `elem` ['?'] -> continue $ setMode Help ui EvKey (KChar 'g') [] -> liftIO (uiReloadJournalIfChanged copts d j ui) >>= continue + EvKey (KChar 'I') [] -> continue $ uiCheckBalanceAssertions d (toggleIgnoreBalanceAssertions ui) EvKey (KChar 'a') [] -> suspendAndResume $ clearScreen >> setCursorPosition 0 0 >> add copts j >> uiReloadJournalIfChanged copts d j ui EvKey (KChar 'E') [] -> suspendAndResume $ void (runEditor endPos (journalFilePath j)) >> uiReloadJournalIfChanged copts d j ui EvKey (KChar '0') [] -> continue $ regenerateScreens j d $ setDepth (Just 0) ui diff --git a/hledger-ui/Hledger/UI/ErrorScreen.hs b/hledger-ui/Hledger/UI/ErrorScreen.hs index 5ae7fbf4b..2fb466904 100644 --- a/hledger-ui/Hledger/UI/ErrorScreen.hs +++ b/hledger-ui/Hledger/UI/ErrorScreen.hs @@ -4,6 +4,8 @@ module Hledger.UI.ErrorScreen (errorScreen + ,uiCheckBalanceAssertions + ,uiReloadJournal ,uiReloadJournalIfChanged ) where @@ -82,18 +84,19 @@ esHandle ui@UIState{ d <- liftIO getCurrentDay case ev of EvKey (KChar 'q') [] -> halt ui - EvKey KEsc [] -> continue $ resetScreens d ui + EvKey KEsc [] -> continue $ uiCheckBalanceAssertions d $ resetScreens d ui EvKey (KChar c) [] | c `elem` ['h','?'] -> continue $ setMode Help ui EvKey (KChar 'E') [] -> suspendAndResume $ void (runEditor pos f) >> uiReloadJournalIfChanged copts d j (popScreen ui) where (pos,f) = case parsewith hledgerparseerrorpositionp esError of Right (f,l,c) -> (Just (l, Just c),f) Left _ -> (endPos, journalFilePath j) - EvKey (KChar 'g') [] -> liftIO (uiReloadJournalIfChanged copts d j (popScreen ui)) >>= continue + EvKey (KChar 'g') [] -> liftIO (uiReloadJournalIfChanged copts d j (popScreen ui)) >>= continue . uiCheckBalanceAssertions d -- (ej, _) <- liftIO $ journalReloadIfChanged copts d j -- case ej of -- 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 + EvKey (KChar 'I') [] -> continue $ uiCheckBalanceAssertions d (popScreen $ toggleIgnoreBalanceAssertions ui) _ -> continue ui esHandle _ _ = error "event handler called with wrong screen type, should not happen" @@ -140,3 +143,16 @@ uiReloadJournalIfChanged copts d j ui = do UIState{aScreen=s@ErrorScreen{}} -> ui{aScreen=s{esError=err}} _ -> screenEnter d errorScreen{esError=err} ui +-- 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_ copts = ui + | otherwise = + case journalCheckBalanceAssertions j of + Right _ -> ui + Left err -> + case ui of + UIState{aScreen=s@ErrorScreen{}} -> ui{aScreen=s{esError=err}} + _ -> screenEnter d errorScreen{esError=err} ui diff --git a/hledger-ui/Hledger/UI/RegisterScreen.hs b/hledger-ui/Hledger/UI/RegisterScreen.hs index 51d537721..dc68d27e3 100644 --- a/hledger-ui/Hledger/UI/RegisterScreen.hs +++ b/hledger-ui/Hledger/UI/RegisterScreen.hs @@ -250,6 +250,7 @@ rsHandle ui@UIState{ EvKey KEsc [] -> continue $ resetScreens d ui EvKey (KChar c) [] | c `elem` ['?'] -> continue $ setMode Help ui EvKey (KChar 'g') [] -> liftIO (uiReloadJournalIfChanged copts d j ui) >>= continue + EvKey (KChar 'I') [] -> continue $ uiCheckBalanceAssertions d (toggleIgnoreBalanceAssertions ui) EvKey (KChar 'a') [] -> suspendAndResume $ clearScreen >> setCursorPosition 0 0 >> add copts j >> uiReloadJournalIfChanged copts d j ui EvKey (KChar 'E') [] -> suspendAndResume $ void (runEditor pos f) >> uiReloadJournalIfChanged copts d j ui where diff --git a/hledger-ui/Hledger/UI/TransactionScreen.hs b/hledger-ui/Hledger/UI/TransactionScreen.hs index a2d6fb126..be1612a02 100644 --- a/hledger-ui/Hledger/UI/TransactionScreen.hs +++ b/hledger-ui/Hledger/UI/TransactionScreen.hs @@ -157,6 +157,7 @@ tsHandle ui@UIState{aScreen=s@TransactionScreen{tsTransaction=(i,t) ,tsTransactions=numberedts ,tsAccount=acct}} continue $ regenerateScreens j' d ui' + EvKey (KChar 'I') [] -> continue $ uiCheckBalanceAssertions d (toggleIgnoreBalanceAssertions ui) -- if allowing toggling here, we should refresh the txn list from the parent register screen -- EvKey (KChar 'E') [] -> continue $ regenerateScreens j d $ stToggleEmpty ui -- EvKey (KChar 'C') [] -> continue $ regenerateScreens j d $ stToggleCleared ui diff --git a/hledger-ui/Hledger/UI/UIState.hs b/hledger-ui/Hledger/UI/UIState.hs index 03daeb0d9..f78257ded 100644 --- a/hledger-ui/Hledger/UI/UIState.hs +++ b/hledger-ui/Hledger/UI/UIState.hs @@ -60,6 +60,11 @@ toggleReal ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropt where toggleReal ropts = ropts{real_=not $ real_ ropts} +-- | Toggle the ignoring of balance assertions. +toggleIgnoreBalanceAssertions :: UIState -> UIState +toggleIgnoreBalanceAssertions ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{}}} = + ui{aopts=uopts{cliopts_=copts{ignore_assertions_=not $ ignore_assertions_ copts}}} + -- | Apply a new filter query. setFilter :: String -> UIState -> UIState setFilter s ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} = diff --git a/hledger-ui/Hledger/UI/UIUtils.hs b/hledger-ui/Hledger/UI/UIUtils.hs index 621335828..360c56aa7 100644 --- a/hledger-ui/Hledger/UI/UIUtils.hs +++ b/hledger-ui/Hledger/UI/UIUtils.hs @@ -52,6 +52,7 @@ helpDialog = ,renderKey ("a", "add transaction") ,renderKey ("E", "open editor") ,renderKey ("g", "reload data") + ,renderKey ("I", "toggle balance assertions") ,renderKey ("q", "quit") ] ,padLeftRight 1 $ diff --git a/hledger-ui/doc/hledger-ui.1.m4.md b/hledger-ui/doc/hledger-ui.1.m4.md index 9e0fae62d..c6a9b074d 100644 --- a/hledger-ui/doc/hledger-ui.1.m4.md +++ b/hledger-ui/doc/hledger-ui.1.m4.md @@ -103,6 +103,9 @@ Or, it cancels a minibuffer edit or help dialog if one is active. `g` reloads from the data file(s) and updates the current screen and any previous screens. (With large files, there can be a noticeable pause.) +`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 file. This allows some basic data entry.