@@ -12,14 +12,15 @@ module Hledger.UI.TransactionScreen
1212,tsHandle
1313) where
1414
15+ import Brick
1516import Brick.Widgets.Edit (editorText , renderEditor )
17+ import Brick.Widgets.List (listMoveTo )
1618import Control.Monad.IO.Class (liftIO )
1719import Data.List
1820import Data.Maybe
1921import qualified Data.Text as T
2022import Graphics.Vty (Event (.. ),Key (.. ),Modifier (.. ), Button (BLeft ))
21- import Brick
22- import Brick.Widgets.List (listMoveTo )
23+ import System.Exit (ExitCode (.. ))
2324
2425import Hledger
2526import Hledger.Cli hiding (mode , prices , progname ,prognameandversion )
@@ -31,8 +32,6 @@ import Hledger.UI.UIScreens
3132import Hledger.UI.Editor
3233import Hledger.UI.ErrorScreen (uiCheckBalanceAssertions , uiReload , uiReloadIfFileChanged )
3334import Hledger.UI.RegisterScreen (rsHandle )
34- import System.Exit (ExitCode (.. ))
35- import Data.Function ((&) )
3635
3736tsDraw :: UIState -> [Widget Name ]
3837tsDraw UIState {aopts= UIOpts {uoCliOpts= copts@ CliOpts {reportspec_= rspec@ ReportSpec {_rsReportOpts= ropts}}}
@@ -140,25 +139,9 @@ tsHandle ev = do
140139 VtyEvent (EvKey KEsc [] ) -> put' $ resetScreens d ui
141140 VtyEvent (EvKey (KChar c) [] ) | c == ' ?' -> put' $ setMode Help ui
142141
143- -- g or file change: reload the journal.
144- e | e `elem` [VtyEvent (EvKey (KChar ' g' ) [] ), AppEvent FileChange ] -> do
145- -- Update app state. This is tricky: (XXX anywhere else we need to be this thorough ?)
146-
147- -- Reload and regenerate screens
148- ui1 <- uiReload copts d ui
149- -- If that moved us to the error screen, save that and return to the transaction screen.
150- let
151- (merrscr, ui2) = case aScreen ui1 of
152- s@ (ES _) -> (Just s, popScreen ui1)
153- _ -> (Nothing , ui1)
154- -- put' ui2
155- -- Now exit to register screen and make it regenerate the transaction screen,
156- -- for best initialisation.
157- put' $ popScreen ui2
158- rsHandle (VtyEvent (EvKey KEnter [] )) -- XXX PARTIAL assumes we are on the register screen
159- -- Then re-enter the error screen if any, so error repair will return to the transaction screen.
160- let ui3 = maybe ui2 (`pushScreen` ui2) merrscr
161- put' ui3
142+ -- g or file change: reload the journal and rebuild app state.
143+ e | e `elem` [VtyEvent (EvKey (KChar ' g' ) [] ), AppEvent FileChange ] ->
144+ tsReload copts d ui
162145
163146 -- for debugging; leaving these here because they were hard to find
164147 -- \u -> dbguiEv (pshow u) >> put' u -- doesn't log
@@ -167,14 +150,12 @@ tsHandle ev = do
167150 -- E: run editor, reload the journal.
168151 VtyEvent (EvKey (KChar ' E' ) [] ) -> do
169152 suspendAndResume' $ do
153+ let (pos,f) = case tsourcepos t of (SourcePos f' l1 c1,_) -> (Just (unPos l1, Just $ unPos c1),f')
170154 exitcode <- runEditor pos f
171155 case exitcode of
172156 ExitSuccess -> return ()
173157 ExitFailure c -> error' $ " running the text editor failed with exit code " ++ show c
174- -- Update all state, similar to above.
175- put' =<< liftIO (popScreen ui & uiReloadIfFileChanged copts d j)
176- rsHandle (VtyEvent (EvKey KEnter [] ))
177- where (pos,f) = case tsourcepos t of (SourcePos f' l1 c1,_) -> (Just (unPos l1, Just $ unPos c1),f')
158+ tsReloadIfFileChanged copts d j ui
178159
179160 AppEvent (DateChange old _) | isStandardPeriod p && p `periodContainsDate` old ->
180161 put' $ regenerateScreens j d $ setReportPeriod (DayPeriod d) ui
@@ -205,6 +186,53 @@ tsHandle ev = do
205186
206187 _ -> errorWrongScreenType " tsHandle"
207188
189+ where
190+ -- Reload and fully regenerate the transaction screen.
191+ -- XXX On transaction screen or below, this is tricky because of a current limitation of regenerateScreens.
192+ -- For now we try to work around by re-entering the screen(s).
193+ -- This can show flicker in the UI and it's hard to handle all situations robustly.
194+ tsReload copts d ui = uiReload copts d ui >>= reEnterTransactionScreen copts d
195+ tsReloadIfFileChanged copts d j ui = liftIO (uiReloadIfFileChanged copts d j ui) >>= reEnterTransactionScreen copts d
196+
197+ reEnterTransactionScreen _copts d ui = do
198+ -- 1. If uiReload (or checking balance assertions) moved us to the error screen, save that, and return to the transaction screen.
199+ let
200+ (merrscr, uiTxn) = case aScreen $ uiCheckBalanceAssertions d ui of
201+ s@ (ES _) -> (Just s, popScreen ui)
202+ _ -> (Nothing , ui)
203+ -- 2. Exit to register screen
204+ let uiReg = popScreen uiTxn
205+ put' uiReg
206+ -- 3. Re-enter the transaction screen
207+ rsHandle (VtyEvent (EvKey KEnter [] )) -- PARTIAL assumes we are on the register screen.
208+ -- 4. Return to the error screen (below the transaction screen) if there was one.
209+ -- Next events will be handled by esHandle. Error repair will return to the transaction screen.
210+ maybe (return () ) (put' . flip pushScreen uiTxn) merrscr
211+ -- doesn't uiTxn have old state from before step 3 ? seems to work
212+
213+ -- XXX some problem:
214+ -- 4. Reload once more, possibly re-entering the error screen, by sending a g event.
215+ -- sendVtyEvents [EvKey (KChar 'g') []] -- XXX Might be disrupted if other events are queued
216+
217+ -- XXX doesn't update on non-error change:
218+ -- 4. Reload once more, possibly re-entering the error screen.
219+ -- uiTxnOrErr <- uiReload copts d uiTxn
220+ -- uiReloadIfChanged ?
221+ -- uiCheckBalanceAssertions ? seems unneeded
222+ -- put' uiTxnOrErr
223+
224+ -- XXX not working right:
225+ -- -- 1. If uiReload (or checking balance assertions) moved us to the error screen, exit to the transaction screen.
226+ -- let
227+ -- uiTxn = case aScreen $ uiCheckBalanceAssertions d ui of
228+ -- ES _ -> popScreen ui
229+ -- _ -> ui
230+ -- -- 2. Exit to register screen
231+ -- put' $ popScreen uiTxn
232+ -- -- 3. Re-enter the transaction screen, and reload once more.
233+ -- sendVtyEvents [EvKey KEnter [], EvKey (KChar 'g') []] -- XXX Might be disrupted if other events are queued
234+
235+
208236-- | Select a new transaction and update the previous register screen
209237tsSelect :: Integer -> Transaction -> UIState -> UIState
210238tsSelect i t ui@ UIState {aScreen= TS sst} = case aPrevScreens ui of
0 commit comments