Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package hledger-ui for openSUSE:Factory 
checked in at 2025-09-24 15:24:24
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/hledger-ui (Old)
 and      /work/SRC/openSUSE:Factory/.hledger-ui.new.27445 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "hledger-ui"

Wed Sep 24 15:24:24 2025 rev:41 rq:1306809 version:1.50.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/hledger-ui/hledger-ui.changes    2025-09-11 
14:43:32.414452489 +0200
+++ /work/SRC/openSUSE:Factory/.hledger-ui.new.27445/hledger-ui.changes 
2025-09-24 15:26:39.678361994 +0200
@@ -1,0 +2,9 @@
+Tue Sep 16 13:40:46 UTC 2025 - Peter Simons <[email protected]>
+
+- Update hledger-ui to version 1.50.1.
+  Upstream's change log file format is strange (too much unmodified
+  text at at the top). The automatic updater cannot extract the
+  relevant additions. You can find the file at:
+  http://hackage.haskell.org/package/hledger-ui-1.50.1/src/CHANGES.md
+
+-------------------------------------------------------------------

Old:
----
  hledger-ui-1.50.tar.gz

New:
----
  hledger-ui-1.50.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ hledger-ui.spec ++++++
--- /var/tmp/diff_new_pack.M9c5Be/_old  2025-09-24 15:26:40.198383888 +0200
+++ /var/tmp/diff_new_pack.M9c5Be/_new  2025-09-24 15:26:40.198383888 +0200
@@ -19,7 +19,7 @@
 %global pkg_name hledger-ui
 %global pkgver %{pkg_name}-%{version}
 Name:           %{pkg_name}
-Version:        1.50
+Version:        1.50.1
 Release:        0
 Summary:        Terminal interface for the hledger accounting system
 License:        GPL-3.0-or-later
@@ -72,6 +72,8 @@
 BuildRequires:  ghc-safe-prof
 BuildRequires:  ghc-split-devel
 BuildRequires:  ghc-split-prof
+BuildRequires:  ghc-stm-devel
+BuildRequires:  ghc-stm-prof
 BuildRequires:  ghc-text-devel
 BuildRequires:  ghc-text-prof
 BuildRequires:  ghc-text-zipper-devel

++++++ hledger-ui-1.50.tar.gz -> hledger-ui-1.50.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/CHANGES.md 
new/hledger-ui-1.50.1/CHANGES.md
--- old/hledger-ui-1.50/CHANGES.md      2025-09-03 21:03:21.000000000 +0200
+++ new/hledger-ui-1.50.1/CHANGES.md    2025-09-16 14:22:23.000000000 +0200
@@ -23,6 +23,36 @@
 See also the hledger changelog.
 
 
+# 1.50.1 2025-09-16
+
+Fixes
+
+- The transaction screen and error screen now update on data changes like 
other screens,
+  eg when using the E key, g key, or --watch.
+  [#2014], [#2288]
+
+- When the journal is reloaded by the `g` key or `--watch`, the
+  --pivot (and --obfuscate) options are now preserved,
+  and spurious errors are avoided.
+  [#2451]
+
+- The Z key (and the -E command line flag) toggles zero-balance accounts again.
+  (Stephen Morgan, [#2454])
+
+Improvements
+
+- Debug output has improved, eg it's easier to see changes to the screen stack.
+
+API
+
+- Hledger.UI.ErrorScreen:
+  uiReloadJournal -> uiReload,
+  uiReloadJournalIfChanged -> uiReloadIfFileChanged
+- Hledger.UI.UIState:
+  enableForecastPreservingPeriod -> enableForecast
+
+
+
 # 1.50 2025-09-03
 
 Breaking changes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/Hledger/UI/AccountsScreen.hs 
new/hledger-ui-1.50.1/Hledger/UI/AccountsScreen.hs
--- old/hledger-ui-1.50/Hledger/UI/AccountsScreen.hs    2025-08-28 
16:06:09.000000000 +0200
+++ new/hledger-ui-1.50.1/Hledger/UI/AccountsScreen.hs  2025-09-16 
02:35:06.000000000 +0200
@@ -48,7 +48,7 @@
 import Hledger.UI.UIUtils
 import Hledger.UI.UIScreens
 import Hledger.UI.Editor
-import Hledger.UI.ErrorScreen (uiReloadJournal, uiCheckBalanceAssertions, 
uiReloadJournalIfChanged)
+import Hledger.UI.ErrorScreen (uiCheckBalanceAssertions, uiReload, 
uiReloadIfFileChanged)
 import Hledger.UI.RegisterScreen (rsCenterSelection)
 import Data.Either (fromRight)
 import Control.Arrow ((>>>))
@@ -69,7 +69,7 @@
 asDrawHelper UIState{aScreen=scr, aopts=uopts, ajournal=j, aMode=mode} ropts 
scrname =
   dbgui "asDrawHelper" $
   case toAccountsLikeScreen scr of
-    Nothing          -> dbgui "asDrawHelper" $ errorWrongScreenType "draw 
helper"  -- PARTIAL:
+    Nothing          -> dbgui "asDrawHelper" $ errorWrongScreenType 
"asDrawHelper"  -- PARTIAL:
     Just (ALS _ ass) -> case mode of
       Help -> [helpDialog, maincontent]
       _    -> [maincontent]
@@ -189,7 +189,7 @@
   dbguiEv "asHandle"
   ui0@UIState{aScreen=scr, aMode=mode} <- get'
   case toAccountsLikeScreen scr of
-    Nothing -> dbgui "asHandle" $ errorWrongScreenType "event handler"  -- 
PARTIAL:
+    Nothing -> dbgui "asHandle" $ errorWrongScreenType "asHandle"  -- PARTIAL:
     Just als@(ALS scons ass) -> do
       -- save the currently selected account, in case we leave this screen and 
lose the selection
       put' ui0{aScreen=scons ass{_assSelectedAccount=asSelectedAccount ass}}
@@ -231,7 +231,7 @@
     -- XXX be sure we don't leave unconsumed app events piling up
     -- A data file has changed (or the user has pressed g): reload.
     e | e `elem` [AppEvent FileChange, VtyEvent (EvKey (KChar 'g') [])] ->
-      liftIO (uiReloadJournal copts d ui) >>= put'
+      uiReload copts d ui >>= put'
 
     -- The date has changed (and we are viewing a standard period which 
contained the old date):
     -- adjust the viewed period and regenerate, just in case needed.
@@ -245,9 +245,9 @@
     VtyEvent (EvKey k           []) | k `elem` [KBS, KDel] -> modify' 
(resetFilter >>> regenerateScreens j d)
 
     -- run external programs:
-    VtyEvent (EvKey (KChar 'a') []) -> suspendAndResume $ clearScreen >> 
setCursorPosition 0 0 >> add (cliOptsDropArgs copts) j >> 
uiReloadJournalIfChanged copts d j ui
-    VtyEvent (EvKey (KChar 'A') []) -> suspendAndResume $ void (runIadd 
(journalFilePath j)) >> uiReloadJournalIfChanged copts d j ui
-    VtyEvent (EvKey (KChar 'E') []) -> suspendAndResume $ void (runEditor 
endPosition (journalFilePath j)) >> uiReloadJournalIfChanged copts d j ui
+    VtyEvent (EvKey (KChar 'a') []) -> suspendAndResume $ clearScreen >> 
setCursorPosition 0 0 >> add (cliOptsDropArgs copts) j >> uiReloadIfFileChanged 
copts d j ui
+    VtyEvent (EvKey (KChar 'A') []) -> suspendAndResume $ void (runIadd 
(journalFilePath j)) >> uiReloadIfFileChanged copts d j ui
+    VtyEvent (EvKey (KChar 'E') []) -> suspendAndResume $ void (runEditor 
endPosition (journalFilePath j)) >> uiReloadIfFileChanged copts d j ui
 
     -- adjust the period displayed:
     VtyEvent (EvKey (KChar 'T') []) ->       modify' (setReportPeriod 
(DayPeriod d)    >>> regenerateScreens j d)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/Hledger/UI/ErrorScreen.hs 
new/hledger-ui-1.50.1/Hledger/UI/ErrorScreen.hs
--- old/hledger-ui-1.50/Hledger/UI/ErrorScreen.hs       2025-09-02 
08:59:50.000000000 +0200
+++ new/hledger-ui-1.50.1/Hledger/UI/ErrorScreen.hs     2025-09-16 
14:20:53.000000000 +0200
@@ -11,6 +11,8 @@
  ,esDraw
  ,esHandle
  ,uiCheckBalanceAssertions
+ ,uiReload
+ ,uiReloadIfFileChanged
  ,uiReloadJournal
  ,uiReloadJournalIfChanged
  )
@@ -18,12 +20,12 @@
 
 import Brick
 -- import Brick.Widgets.Border ("border")
-import Control.Monad
 import Control.Monad.IO.Class (liftIO)
 import Data.Time.Calendar (Day)
 import Data.Void (Void)
 import Graphics.Vty (Event(..),Key(..),Modifier(..))
 import Lens.Micro ((^.))
+import Safe (headMay)
 import Text.Megaparsec
 import Text.Megaparsec.Char
 
@@ -35,6 +37,10 @@
 import Hledger.UI.UIScreens
 import Hledger.UI.Editor
 
+-- legacy aliases
+uiReloadJournal = uiReload
+uiReloadJournalIfChanged = uiReloadIfFileChanged
+
 esDraw :: UIState -> [Widget Name]
 esDraw UIState{aScreen=ES ESS{..}
               ,aMode=mode
@@ -88,23 +94,41 @@
             VtyEvent (EvKey (KChar 'q') []) -> halt
             VtyEvent (EvKey KEsc        []) -> put' $ uiCheckBalanceAssertions 
d $ resetScreens d ui
             VtyEvent (EvKey (KChar c)   []) | c `elem` ['h','?'] -> put' $ 
setMode Help ui
-            VtyEvent (EvKey (KChar 'E') []) -> suspendAndResume $ void 
(runEditor pos f) >> uiReloadJournalIfChanged copts d j (popScreen ui)
-              where
-                (pos,f) = case parsewithString hledgerparseerrorpositionp 
_essError of
-                            Right (f',l,c) -> (Just (l, Just c),f')
-                            Left  _       -> (endPosition, journalFilePath j)
-            e | e `elem` [VtyEvent (EvKey (KChar 'g') []), AppEvent 
FileChange] ->
-              liftIO (uiReloadJournal copts d (popScreen ui)) >>= put' . 
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
+
+            -- g or file change: reload the journal and rebuild app state.
+            e | e `elem` [VtyEvent (EvKey (KChar 'g') []), AppEvent 
FileChange] -> esReload copts d ui
+
+            -- E: run editor, reload the journal.
+            VtyEvent (EvKey (KChar 'E') []) -> do
+              suspendAndResume' $ do
+                let
+                  (pos,f) = case parsewithString hledgerparseerrorpositionp 
_essError of
+                              Right (f',l,c) -> (Just (l, Just c),f')
+                              Left  _       -> (endPosition, journalFilePath j)
+                runEditor pos f
+              esReloadIfFileChanged copts d j ui
+
             VtyEvent (EvKey (KChar 'I') []) -> put' $ uiCheckBalanceAssertions 
d (popScreen $ toggleIgnoreBalanceAssertions ui)
             VtyEvent (EvKey (KChar 'l') [MCtrl]) -> redraw
             VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspend ui
             _ -> return ()
 
-    _ -> errorWrongScreenType "event handler"
+    _ -> errorWrongScreenType "esHandle"
+
+    where
+      -- Reload and fully regenerate the error screen.
+      -- XXX On an error screen below the transaction screen, this is tricky 
because of a current limitation of regenerateScreens.
+      -- For now we try to work around by re-entering the transaction screen.
+      -- This can show flicker in the UI and it's hard to handle all 
situations robustly.
+      esReload copts d ui = uiReload copts d ui >>= maybeReloadErrorScreen 
copts d
+      esReloadIfFileChanged copts d j ui = liftIO (uiReloadIfFileChanged copts 
d j ui) >>= maybeReloadErrorScreen copts d
+      maybeReloadErrorScreen copts d ui =
+        case headMay $ aPrevScreens ui of
+          Just (TS _) -> do
+            -- check balance assertions, exit to register screen, enter 
transaction screen, reload once more
+            put' $ popScreen $ popScreen $ uiCheckBalanceAssertions d ui
+            sendVtyEvents [EvKey KEnter [], EvKey (KChar 'g') []]  -- XXX 
Might be disrupted if other events are queued ?
+          _ -> uiReload copts d (popScreen ui) >>= put' . 
uiCheckBalanceAssertions d
 
 -- | 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
@@ -130,29 +154,27 @@
       ]
 
 
--- | Unconditionally reload the journal, regenerating the current screen
--- and all previous screens in the history as of the provided today-date.
--- If reloading fails, enter the error screen, or if we're already
--- on the error screen, update the error displayed.
--- Defined here so it can reference the error screen.
+-- Defined here so it can reference the error screen:
+
+-- | Reload the journal from its input files, then update the ui app state 
accordingly.
+-- This means regenerate the entire screen stack from top level down to the 
current screen, using the provided today-date.
+-- As a convenience (usually), if journal reloading fails, this enters the 
error screen, or if already there, updates its message.
 --
--- The provided CliOpts are used for reloading, and then saved in the
--- UIState if reloading is successful (otherwise the UIState keeps its old
--- CliOpts.) (XXX needed for.. ?)
+-- The provided cli options can influence reloading; then if reloading 
succeeds they are saved in the ui state,
+-- otherwise the UIState keeps its old options. (XXX needed for.. ?)
 --
--- Forecasted transactions are always generated, as at hledger-ui startup.
--- If a forecast period is specified in the provided opts, or was specified
--- at startup, it is preserved.
+-- Like at hledger-ui startup, --forecast is always enabled.
+-- A forecast period specified in the provided opts, or at startup, is 
preserved.
 --
-uiReloadJournal :: CliOpts -> Day -> UIState -> IO UIState
-uiReloadJournal copts d ui = do
+uiReload :: CliOpts -> Day -> UIState -> EventM Name UIState UIState
+uiReload copts d ui = liftIO $ do
   ej <-
-    let copts' = enableForecastPreservingPeriod ui copts
-    in runExceptT $ journalReload copts'
-  -- dbg1IO "uiReloadJournal before reload" (map tdescription $ jtxns $ 
ajournal ui)
+    let copts' = enableForecast (astartupopts ui) copts
+    in runExceptT $ journalTransform copts' <$> journalReload copts'
+  -- dbg1IO "uiReload before reload" (map tdescription $ jtxns $ ajournal ui)
   return $ case ej of
     Right j  ->
-      -- dbg1 "uiReloadJournal after reload" (map tdescription $ jtxns j) $
+      -- dbg1 "uiReload after reload" (map tdescription $ jtxns j) $
       regenerateScreens j d ui
     Left err ->
       case ui of
@@ -167,12 +189,12 @@
       --             RegisterScreen _ _ _ _ _ _
       --             TransactionScreen _ _ _ _ _ _
 
--- | Like uiReloadJournal, but does not re-parse the journal if the file(s)
--- have not changed since last loaded. Always regenerates the screens though,
--- since the provided options or today-date may have changed.
-uiReloadJournalIfChanged :: CliOpts -> Day -> Journal -> UIState -> IO UIState
-uiReloadJournalIfChanged copts d j ui = do
-  let copts' = enableForecastPreservingPeriod ui copts
+-- | Like uiReload, except it skips re-reading the journal if its file(s) have 
not changed
+-- since it was last loaded. The up app state is always updated, since the 
options or today-date may have changed.
+-- Also, this one runs in IO, suitable for suspendAndResume.
+uiReloadIfFileChanged :: CliOpts -> Day -> Journal -> UIState -> IO UIState
+uiReloadIfFileChanged copts d j ui = do
+  let copts' = enableForecast (astartupopts ui) copts
   ej <- runExceptT $ journalReloadIfChanged copts' d j
   return $ case ej of
     Right (j', _) -> regenerateScreens j' d ui
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/Hledger/UI/Main.hs 
new/hledger-ui-1.50.1/Hledger/UI/Main.hs
--- old/hledger-ui-1.50/Hledger/UI/Main.hs      2025-09-02 08:59:57.000000000 
+0200
+++ new/hledger-ui-1.50.1/Hledger/UI/Main.hs    2025-09-16 02:35:06.000000000 
+0200
@@ -118,7 +118,7 @@
     _ | boolopt "man"     rawopts -> runManForTopic  "hledger-ui" Nothing
     _ | boolopt "version" rawopts -> putStrLn prognameandversion
     -- _ | boolopt "binary-filename" rawopts -> putStrLn (binaryfilename 
progname)
-    _                                         -> withJournalDo copts' 
(runBrickUi opts)
+    _                                         -> withJournal copts' 
(runBrickUi opts)
 
   when (ghcDebugMode == GDPauseAtEnd) $ ghcDebugPause'
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/Hledger/UI/MenuScreen.hs 
new/hledger-ui-1.50.1/Hledger/UI/MenuScreen.hs
--- old/hledger-ui-1.50/Hledger/UI/MenuScreen.hs        2025-08-28 
16:06:09.000000000 +0200
+++ new/hledger-ui-1.50.1/Hledger/UI/MenuScreen.hs      2025-09-16 
02:35:06.000000000 +0200
@@ -33,7 +33,7 @@
 import Hledger.UI.UIState
 import Hledger.UI.UIUtils
 import Hledger.UI.UIScreens
-import Hledger.UI.ErrorScreen (uiReloadJournal, uiCheckBalanceAssertions, 
uiReloadJournalIfChanged)
+import Hledger.UI.ErrorScreen (uiCheckBalanceAssertions, uiReload, 
uiReloadIfFileChanged)
 import Hledger.UI.Editor (runIadd, runEditor, endPosition)
 import Brick.Widgets.Edit (getEditContents, handleEditorEvent)
 import Control.Arrow ((>>>))
@@ -87,7 +87,7 @@
               ,("q", str "quit")
               ]
 
-msDraw _ =  dbgui "msDraw" $ errorWrongScreenType "draw function"  -- PARTIAL:
+msDraw _ =  dbgui "msDraw" $ errorWrongScreenType "msDraw"  -- PARTIAL:
 
 -- msDrawItem :: (Int,Int) -> Bool -> MenuScreenItem -> Widget Name
 -- msDrawItem (_acctwidth, _balwidth) _selected MenuScreenItem{..} =
@@ -155,12 +155,11 @@
               put' $ regenerateScreens j d $ setReportPeriod (DayPeriod d) ui
               where
                 p = reportPeriod ui
-            e | e `elem` [VtyEvent (EvKey (KChar 'g') []), AppEvent 
FileChange] ->
-              liftIO (uiReloadJournal copts d ui) >>= put'
+            e | e `elem` [VtyEvent (EvKey (KChar 'g') []), AppEvent 
FileChange] -> uiReload copts d ui >>= put'
             VtyEvent (EvKey (KChar 'I') []) -> put' $ uiCheckBalanceAssertions 
d (toggleIgnoreBalanceAssertions ui)
-            VtyEvent (EvKey (KChar 'a') []) -> suspendAndResume $ clearScreen 
>> setCursorPosition 0 0 >> add (cliOptsDropArgs copts) j >> 
uiReloadJournalIfChanged copts d j ui
-            VtyEvent (EvKey (KChar 'A') []) -> suspendAndResume $ void 
(runIadd (journalFilePath j)) >> uiReloadJournalIfChanged copts d j ui
-            VtyEvent (EvKey (KChar 'E') []) -> suspendAndResume $ void 
(runEditor endPosition (journalFilePath j)) >> uiReloadJournalIfChanged copts d 
j ui
+            VtyEvent (EvKey (KChar 'a') []) -> suspendAndResume $ clearScreen 
>> setCursorPosition 0 0 >> add (cliOptsDropArgs copts) j >> 
uiReloadIfFileChanged copts d j ui
+            VtyEvent (EvKey (KChar 'A') []) -> suspendAndResume $ void 
(runIadd (journalFilePath j)) >> uiReloadIfFileChanged copts d j ui
+            VtyEvent (EvKey (KChar 'E') []) -> suspendAndResume $ void 
(runEditor endPosition (journalFilePath j)) >> uiReloadIfFileChanged copts d j 
ui
 
 --             VtyEvent (EvKey (KChar 'B') []) -> put' $ regenerateScreens j d 
$ toggleConversionOp ui
 --             VtyEvent (EvKey (KChar 'V') []) -> put' $ regenerateScreens j d 
$ toggleValue ui
@@ -257,7 +256,7 @@
             MouseUp{}   -> return ()
             AppEvent _  -> return ()
 
-    _ -> dbguiEv "msHandle" >> errorWrongScreenType "event handler"
+    _ -> dbguiEv "msHandle" >> errorWrongScreenType "msHandle"
 
 msEnterScreen :: Day -> ScreenName -> UIState -> EventM Name UIState ()
 msEnterScreen d scrname ui@UIState{ajournal=j, aopts=uopts} = do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/Hledger/UI/RegisterScreen.hs 
new/hledger-ui-1.50.1/Hledger/UI/RegisterScreen.hs
--- old/hledger-ui-1.50/Hledger/UI/RegisterScreen.hs    2025-08-28 
16:06:09.000000000 +0200
+++ new/hledger-ui-1.50.1/Hledger/UI/RegisterScreen.hs  2025-09-16 
02:35:06.000000000 +0200
@@ -43,13 +43,13 @@
 import Hledger.UI.UIUtils
 import Hledger.UI.UIScreens
 import Hledger.UI.Editor
-import Hledger.UI.ErrorScreen (uiReloadJournal, uiCheckBalanceAssertions, 
uiReloadJournalIfChanged)
+import Hledger.UI.ErrorScreen (uiCheckBalanceAssertions, uiReload, 
uiReloadIfFileChanged)
 
 rsDraw :: UIState -> [Widget Name]
 rsDraw UIState{aopts=_uopts@UIOpts{uoCliOpts=copts@CliOpts{reportspec_=rspec}}
               ,aScreen=RS RSS{..}
               ,aMode=mode
-              } = dbgui "rsDraw 1" $
+              } = dbgui "rsDraw" $
   case mode of
     Help       -> [helpDialog, maincontent]
     _          -> [maincontent]
@@ -156,7 +156,7 @@
               -- ,("q", "quit")
               ]
 
-rsDraw _ = dbgui "rsDraw 2" $ errorWrongScreenType "draw function"  -- PARTIAL:
+rsDraw _ = dbgui "rsDraw" $ errorWrongScreenType "rsDraw"  -- PARTIAL:
 
 rsDrawItem :: (Int,Int,Int,Int,Int) -> Bool -> RegisterScreenItem -> Widget 
Name
 rsDrawItem (datewidth,descwidth,acctswidth,changewidth,balwidth) selected 
RegisterScreenItem{..} =
@@ -187,7 +187,7 @@
 rsHandle :: BrickEvent Name AppEvent -> EventM Name UIState ()
 rsHandle ev = do
   ui0 <- get'
-  dbguiEv "rsHandle 1"
+  dbguiEv "rsHandle"
   case ui0 of
     ui@UIState{
       aScreen=RS sst@RSS{..}
@@ -245,14 +245,13 @@
               where
                 p = reportPeriod ui
 
-            e | e `elem` [AppEvent FileChange, VtyEvent (EvKey (KChar 'g') 
[])] ->
-              liftIO (uiReloadJournal copts d ui) >>= put'
+            e | e `elem` [AppEvent FileChange, VtyEvent (EvKey (KChar 'g') 
[])] -> uiReload copts d ui >>= put'
 
             VtyEvent (EvKey (KChar 'I') []) -> put' $ uiCheckBalanceAssertions 
d (toggleIgnoreBalanceAssertions ui)
-            VtyEvent (EvKey (KChar 'a') []) -> suspendAndResume $ clearScreen 
>> setCursorPosition 0 0 >> add (cliOptsDropArgs copts) j >> 
uiReloadJournalIfChanged copts d j ui
-            VtyEvent (EvKey (KChar 'A') []) -> suspendAndResume $ void 
(runIadd (journalFilePath j)) >> uiReloadJournalIfChanged copts d j ui
+            VtyEvent (EvKey (KChar 'a') []) -> suspendAndResume $ clearScreen 
>> setCursorPosition 0 0 >> add (cliOptsDropArgs copts) j >> 
uiReloadIfFileChanged copts d j ui
+            VtyEvent (EvKey (KChar 'A') []) -> suspendAndResume $ void 
(runIadd (journalFilePath j)) >> uiReloadIfFileChanged copts d j ui
             VtyEvent (EvKey (KChar 'T') []) -> put' $ regenerateScreens j d $ 
setReportPeriod (DayPeriod d) ui
-            VtyEvent (EvKey (KChar 'E') []) -> suspendAndResume $ void 
(runEditor pos f) >> uiReloadJournalIfChanged copts d j ui
+            VtyEvent (EvKey (KChar 'E') []) -> suspendAndResume $ void 
(runEditor pos f) >> uiReloadIfFileChanged copts d j ui
               where
                 (pos,f) = case listSelectedElement _rssList of
                             Nothing -> (endPosition, journalFilePath j)
@@ -332,7 +331,7 @@
             MouseUp{}         -> return ()
             AppEvent _        -> return ()
 
-    _ -> dbgui "rsHandle 2" $ errorWrongScreenType "event handler"
+    _ -> errorWrongScreenType "rsHandle"
 
 isBlankElement mel = ((rsItemDate . snd) <$> mel) == Just ""
 
@@ -354,8 +353,4 @@
 rsEnterTransactionScreen :: AccountName -> [NumberedTransaction] -> 
NumberedTransaction -> UIState -> EventM Name UIState ()
 rsEnterTransactionScreen acct nts nt ui = do
   dbguiEv "rsEnterTransactionScreen"
-  put' $
-    pushScreen (tsNew acct nts nt)
-    ui
-
-
+  put' $ pushScreen (tsNew acct nts nt) ui
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/Hledger/UI/TransactionScreen.hs 
new/hledger-ui-1.50.1/Hledger/UI/TransactionScreen.hs
--- old/hledger-ui-1.50/Hledger/UI/TransactionScreen.hs 2025-09-02 
08:59:50.000000000 +0200
+++ new/hledger-ui-1.50.1/Hledger/UI/TransactionScreen.hs       2025-09-16 
02:35:06.000000000 +0200
@@ -12,14 +12,15 @@
 ,tsHandle
 ) where
 
-import Control.Monad
+import Brick
+import Brick.Widgets.Edit (editorText, renderEditor)
+import Brick.Widgets.List (listMoveTo)
 import Control.Monad.IO.Class (liftIO)
 import Data.List
 import Data.Maybe
 import qualified Data.Text as T
 import Graphics.Vty (Event(..),Key(..),Modifier(..), Button (BLeft))
-import Brick
-import Brick.Widgets.List (listMoveTo)
+import System.Exit (ExitCode (..))
 
 import Hledger
 import Hledger.Cli hiding (mode, prices, progname,prognameandversion)
@@ -29,8 +30,8 @@
 import Hledger.UI.UIUtils
 import Hledger.UI.UIScreens
 import Hledger.UI.Editor
-import Brick.Widgets.Edit (editorText, renderEditor)
-import Hledger.UI.ErrorScreen (uiReloadJournalIfChanged, 
uiCheckBalanceAssertions, uiReloadJournal)
+import Hledger.UI.ErrorScreen (uiCheckBalanceAssertions, uiReload, 
uiReloadIfFileChanged)
+import Hledger.UI.RegisterScreen (rsHandle)
 
 tsDraw :: UIState -> [Widget Name]
 tsDraw 
UIState{aopts=UIOpts{uoCliOpts=copts@CliOpts{reportspec_=rspec@ReportSpec{_rsReportOpts=ropts}}}
@@ -95,7 +96,7 @@
               -- ,("q", "quit")
               ]
 
-tsDraw _ = errorWrongScreenType "draw function"  -- PARTIAL:
+tsDraw _ = errorWrongScreenType "tsDraw"  -- PARTIAL:
 
 -- Render a transaction suitably for the transaction screen.
 showTxn :: ReportOpts -> ReportSpec -> Journal -> Transaction -> T.Text
@@ -137,23 +138,30 @@
             VtyEvent (EvKey (KChar 'q') []) -> halt
             VtyEvent (EvKey KEsc        []) -> put' $ resetScreens d ui
             VtyEvent (EvKey (KChar c)   []) | c == '?' -> put' $ setMode Help 
ui
-            VtyEvent (EvKey (KChar 'E') []) -> suspendAndResume $ void 
(runEditor pos f) >> uiReloadJournalIfChanged copts d j ui
-              where
-                (pos,f) = case tsourcepos t of
-                            (SourcePos f' l1 c1,_) -> (Just (unPos l1, Just $ 
unPos c1),f')
+
+            -- g or file change: reload the journal and rebuild app state.
+            e | e `elem` [VtyEvent (EvKey (KChar 'g') []), AppEvent 
FileChange] ->
+              tsReload copts d ui
+
+              -- for debugging; leaving these here because they were hard to 
find
+              -- \u -> dbguiEv (pshow u) >> put' u  -- doesn't log
+              -- \UIState{aScreen=TS tss} -> error' $ pshow $ _tssTransaction 
tss
+
+            -- E: run editor, reload the journal.
+            VtyEvent (EvKey (KChar 'E') []) -> do
+              suspendAndResume' $ do
+                let (pos,f) = case tsourcepos t of (SourcePos f' l1 c1,_) -> 
(Just (unPos l1, Just $ unPos c1),f')
+                exitcode <- runEditor pos f
+                case exitcode of
+                  ExitSuccess   -> return ()
+                  ExitFailure c -> error' $ "running the text editor failed 
with exit code " ++ show c
+              tsReloadIfFileChanged copts d j ui
+
             AppEvent (DateChange old _) | isStandardPeriod p && p 
`periodContainsDate` old ->
               put' $ regenerateScreens j d $ setReportPeriod (DayPeriod d) ui
               where
                 p = reportPeriod ui
 
-            -- Reload. Warning, this updates parent screens but not the 
transaction screen itself (see tsUpdate).
-            -- To see the updated transaction, one must exit and re-enter the 
transaction screen.
-            e | e `elem` [VtyEvent (EvKey (KChar 'g') []), AppEvent 
FileChange] ->
-              liftIO (uiReloadJournal copts d ui) >>= put'
-                -- debugging.. leaving these here because they were hard to 
find
-                -- \u -> dbguiEv (pshow u) >> put' u  -- doesn't log
-                -- \UIState{aScreen=TS tss} -> error' $ pshow $ 
_tssTransaction tss
-
             VtyEvent (EvKey (KChar 'I') []) -> put' $ uiCheckBalanceAssertions 
d (toggleIgnoreBalanceAssertions ui)
 
             -- for toggles that may change the current/prev/next transactions,
@@ -176,7 +184,54 @@
             VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspend ui
             _ -> return ()
 
-    _ -> errorWrongScreenType "event handler"
+    _ -> errorWrongScreenType "tsHandle"
+
+    where
+      -- Reload and fully regenerate the transaction screen.
+      -- XXX On transaction screen or below, this is tricky because of a 
current limitation of regenerateScreens.
+      -- For now we try to work around by re-entering the screen(s).
+      -- This can show flicker in the UI and it's hard to handle all 
situations robustly.
+      tsReload copts d ui = uiReload copts d ui >>= reEnterTransactionScreen 
copts d
+      tsReloadIfFileChanged copts d j ui = liftIO (uiReloadIfFileChanged copts 
d j ui) >>= reEnterTransactionScreen copts d
+      
+      reEnterTransactionScreen _copts d ui = do
+        -- 1. If uiReload (or checking balance assertions) moved us to the 
error screen, save that, and return to the transaction screen.
+        let
+          (merrscr, uiTxn) = case aScreen $ uiCheckBalanceAssertions d ui of
+            s@(ES _) -> (Just s,  popScreen ui)
+            _        -> (Nothing, ui)
+        -- 2. Exit to register screen
+        let uiReg = popScreen uiTxn
+        put' uiReg
+        -- 3. Re-enter the transaction screen
+        rsHandle (VtyEvent (EvKey KEnter [])) -- PARTIAL assumes we are on the 
register screen.
+        -- 4. Return to the error screen (below the transaction screen) if 
there was one.
+        -- Next events will be handled by esHandle. Error repair will return 
to the transaction screen.
+        maybe (return ()) (put' . flip pushScreen uiTxn) merrscr
+          -- doesn't uiTxn have old state from before step 3 ? seems to work
+
+        -- XXX some problem:
+        -- 4. Reload once more, possibly re-entering the error screen, by 
sending a g event.
+        -- sendVtyEvents [EvKey (KChar 'g') []]  --  XXX Might be disrupted if 
other events are queued
+
+        -- XXX doesn't update on non-error change:
+        -- 4. Reload once more, possibly re-entering the error screen.
+        -- uiTxnOrErr <- uiReload copts d uiTxn
+          -- uiReloadIfChanged ?
+          -- uiCheckBalanceAssertions ? seems unneeded
+        -- put' uiTxnOrErr
+
+        -- XXX not working right:
+        -- -- 1. If uiReload (or checking balance assertions) moved us to the 
error screen, exit to the transaction screen.
+        -- let
+        --   uiTxn = case aScreen $ uiCheckBalanceAssertions d ui of
+        --     ES _ -> popScreen ui
+        --     _    -> ui
+        -- -- 2. Exit to register screen
+        -- put' $ popScreen uiTxn
+        -- -- 3. Re-enter the transaction screen, and reload once more.
+        -- sendVtyEvents [EvKey KEnter [], EvKey (KChar 'g') []]  -- XXX Might 
be disrupted if other events are queued
+
 
 -- | Select a new transaction and update the previous register screen
 tsSelect :: Integer -> Transaction -> UIState -> UIState
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/Hledger/UI/UIState.hs 
new/hledger-ui-1.50.1/Hledger/UI/UIState.hs
--- old/hledger-ui-1.50/Hledger/UI/UIState.hs   2025-09-02 08:59:50.000000000 
+0200
+++ new/hledger-ui-1.50.1/Hledger/UI/UIState.hs 2025-09-16 02:35:06.000000000 
+0200
@@ -35,7 +35,7 @@
 ,resetDepth
 ,popScreen
 ,pushScreen
-,enableForecastPreservingPeriod
+,enableForecast
 ,resetFilter
 ,resetScreens
 ,regenerateScreens
@@ -60,6 +60,7 @@
 import Hledger.UI.UITypes
 import Hledger.UI.UIOptions (UIOpts(uoCliOpts))
 import Hledger.UI.UIScreens (screenUpdate)
+import Hledger.UI.UIUtils (showScreenId, showScreenStack)
 
 -- | Make an initial UI state with the given options, journal,
 -- parent screen stack if any, and starting screen.
@@ -201,20 +202,19 @@
   where
     newForecast = case ui^.forecast of
       Just _  -> Nothing
-      Nothing -> enableForecastPreservingPeriod ui (ui^.cliOpts) ^. forecast
+      Nothing -> enableForecast (astartupopts ui) (ui^.cliOpts) ^. forecast
 
--- | Ensure this CliOpts enables forecasted transactions.
--- If a forecast period was specified in the old CliOpts,
--- or in the provided UIState's startup options,
--- it is preserved.
-enableForecastPreservingPeriod :: UIState -> CliOpts -> CliOpts
-enableForecastPreservingPeriod ui copts = set forecast mforecast copts
+-- | Enable forecasting in this CliOpts.
+-- If it previously specified a forecast period, or else if the given ui 
startup options did,
+-- preserve that as the forecast period.
+enableForecast :: UIOpts -> CliOpts -> CliOpts
+enableForecast startopts currentopts = set forecast mforecast currentopts
   where
-    mforecast = asum [mprovidedforecastperiod, mstartupforecastperiod, 
mdefaultforecastperiod]
+    mforecast = asum [mcurrentforecastperiod, mstartupforecastperiod, 
mdefaultforecastperiod]
       where
-        mprovidedforecastperiod = copts ^. forecast
-        mstartupforecastperiod  = astartupopts ui ^. forecast
-        mdefaultforecastperiod  = Just nulldatespan
+        mcurrentforecastperiod = currentopts ^. forecast
+        mstartupforecastperiod = startopts ^. forecast
+        mdefaultforecastperiod = Just nulldatespan
 
 -- | Toggle between showing all and showing only real (non-virtual) items.
 toggleReal :: UIState -> UIState
@@ -340,12 +340,16 @@
 setMode m ui = ui{aMode=m}
 
 pushScreen :: Screen -> UIState -> UIState
-pushScreen scr ui = ui{aPrevScreens=(aScreen ui:aPrevScreens ui)
-                      ,aScreen=scr
-                      }
+pushScreen scr ui =
+  dbg1Msg ("pushing screen " <> showScreenId scr <> ". " <> showScreenStack "" 
showScreenId ui1)
+  ui1
+  where ui1 = ui{aPrevScreens=aScreen ui:aPrevScreens ui, aScreen=scr }
 
 popScreen :: UIState -> UIState
-popScreen ui@UIState{aPrevScreens=s:ss} = ui{aScreen=s, aPrevScreens=ss}
+popScreen ui@UIState{aPrevScreens = s : ss} =
+  dbg1Msg ("popping screen " <> showScreenId (aScreen ui) <> ". " <> 
showScreenStack "" showScreenId ui1)
+  ui1
+  where ui1 = ui{aPrevScreens = ss ,aScreen = s }
 popScreen ui = ui
 
 -- | Reset options to their startup values, discard screen navigation history,
@@ -361,7 +365,9 @@
 -- then regenerate the content of all screens in the stack
 -- (using the ui state's current options), preserving the screen navigation 
history.
 -- Note, does not save the reporting date.
+--
+-- XXX Currently this does not properly regenerate the transaction screen or 
error screen,
+-- which depend on state from their parent(s); those screens' handlers must do 
additional work, which is fragile.
 regenerateScreens :: Journal -> Day -> UIState -> UIState
 regenerateScreens j d ui@UIState{aopts=opts, aScreen=s,aPrevScreens=ss} =
   ui{ajournal=j, aScreen=screenUpdate opts d j s, aPrevScreens=map 
(screenUpdate opts d j) ss}
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/Hledger/UI/UIUtils.hs 
new/hledger-ui-1.50.1/Hledger/UI/UIUtils.hs
--- old/hledger-ui-1.50/Hledger/UI/UIUtils.hs   2025-09-02 08:04:18.000000000 
+0200
+++ new/hledger-ui-1.50.1/Hledger/UI/UIUtils.hs 2025-09-16 02:35:06.000000000 
+0200
@@ -42,6 +42,7 @@
   ,mapScreens
   ,uiNumBlankItems
   ,showScreenStack
+  ,sendVtyEvents
   )
 where
 
@@ -51,6 +52,7 @@
 import Brick.Widgets.Dialog
 import Brick.Widgets.Edit
 import Brick.Widgets.List (List, listSelectedL, listNameL, listItemHeightL, 
listSelected, listMoveDown, listMoveUp, GenericList, listElements)
+import Control.Concurrent.STM (atomically, writeTChan)  -- GHC only
 import Control.Monad.IO.Class
 import Data.Bifunctor (second)
 import Data.List
@@ -59,6 +61,7 @@
 import Graphics.Vty
   (Event(..),Key(..),Modifier(..),Vty(..),Color,Attr,currentAttr,refresh, 
displayBounds
   -- ,Output(displayBounds,mkDisplayContext),DisplayContext(..)
+  ,Vty (inputIface), InternalEvent (InputEvent), Input (eventChannel)
   )
 import Lens.Micro.Platform
 
@@ -530,3 +533,10 @@
   -- | debugLevel >= uiDebugLevel = 0    -- suppress to improve debug output.
   -- | otherwise 
   = 100  -- 100 ought to be enough for anyone
+
+-- Send some events to vty, atomically so they won't have other events 
interleaved.
+-- (But there may be events already in the channel ahead of them.)
+sendVtyEvents :: [Event] -> EventM n s ()
+sendVtyEvents evs = do
+  input <- eventChannel . inputIface <$> getVtyHandle
+  liftIO $ atomically $ mapM_ (writeTChan input . InputEvent) evs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/hledger-ui.1 
new/hledger-ui-1.50.1/hledger-ui.1
--- old/hledger-ui-1.50/hledger-ui.1    2025-09-03 21:06:35.000000000 +0200
+++ new/hledger-ui-1.50.1/hledger-ui.1  2025-09-16 14:20:53.000000000 +0200
@@ -1,5 +1,5 @@
 
-.TH "HLEDGER\-UI" "1" "September 2025" "hledger-ui-1.50 " "hledger User 
Manuals"
+.TH "HLEDGER\-UI" "1" "September 2025" "hledger-ui-1.50.1 " "hledger User 
Manuals"
 
 
 
@@ -17,7 +17,7 @@
 .PD
 \f[CR]hledger ui [OPTS] [QUERYARGS]\f[R]
 .SH DESCRIPTION
-This manual is for hledger\[aq]s terminal interface, version 1.50.
+This manual is for hledger\[aq]s terminal interface, version 1.50.1.
 See also the hledger manual for common concepts and file formats.
 .PP
 hledger is a robust, user\-friendly, cross\-platform set of programs for
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/hledger-ui.cabal 
new/hledger-ui-1.50.1/hledger-ui.cabal
--- old/hledger-ui-1.50/hledger-ui.cabal        2025-09-03 21:06:35.000000000 
+0200
+++ new/hledger-ui-1.50.1/hledger-ui.cabal      2025-09-16 14:20:53.000000000 
+0200
@@ -1,11 +1,11 @@
 cabal-version: 2.2
 
--- This file has been generated from package.yaml by hpack version 0.38.2.
+-- This file has been generated from package.yaml by hpack version 0.38.1.
 --
 -- see: https://github.com/sol/hpack
 
 name:           hledger-ui
-version:        1.50
+version:        1.50.1
 synopsis:       Terminal interface for the hledger accounting system
 description:    A simple terminal user interface for the hledger accounting 
system.
                 It can be a more convenient way to browse your accounts than 
the CLI.
@@ -74,7 +74,7 @@
   hs-source-dirs:
       ./
   ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-missing-signatures 
-Wno-orphans -Wno-type-defaults -Wno-unused-do-bind
-  cpp-options: -DVERSION="1.50" -DVERSION="1.50"
+  cpp-options: -DVERSION="1.50.1" -DVERSION="1.50.1"
   build-depends:
       ansi-terminal >=0.9
     , async
@@ -89,8 +89,8 @@
     , filepath
     , fsnotify >=0.4.2.0 && <0.5
     , githash >=0.1.6.2
-    , hledger ==1.50.*
-    , hledger-lib ==1.50.*
+    , hledger >=1.50.1 && <1.51
+    , hledger-lib >=1.50.1 && <1.51
     , megaparsec >=7.0.0 && <9.8
     , microlens >=0.4
     , microlens-platform >=0.2.3.1
@@ -98,6 +98,7 @@
     , process >=1.2
     , safe >=0.3.20
     , split >=0.1
+    , stm
     , text >=1.2.4.1
     , text-zipper >=0.4
     , time >=1.5
@@ -124,7 +125,7 @@
   hs-source-dirs:
       app
   ghc-options: -Wall -Wno-incomplete-uni-patterns -Wno-missing-signatures 
-Wno-orphans -Wno-type-defaults -Wno-unused-do-bind -with-rtsopts=-T
-  cpp-options: -DVERSION="1.50"
+  cpp-options: -DVERSION="1.50.1"
   build-depends:
       base >=4.18 && <4.22
     , hledger-ui
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/hledger-ui.info 
new/hledger-ui-1.50.1/hledger-ui.info
--- old/hledger-ui-1.50/hledger-ui.info 2025-09-03 21:06:35.000000000 +0200
+++ new/hledger-ui-1.50.1/hledger-ui.info       2025-09-16 14:20:53.000000000 
+0200
@@ -18,7 +18,7 @@
 or
 'hledger ui [OPTS] [QUERYARGS]'
 
-   This manual is for hledger's terminal interface, version 1.50.  See
+   This manual is for hledger's terminal interface, version 1.50.1.  See
 also the hledger manual for common concepts and file formats.
 
    hledger is a robust, user-friendly, cross-platform set of programs
@@ -565,22 +565,22 @@
 
 Tag Table:
 Node: Top221
-Node: OPTIONS1867
-Node: MOUSE8753
-Node: KEYS9085
-Node: SCREENS14089
-Node: Menu screen14829
-Node: Cash accounts screen15145
-Node: Balance sheet accounts screen15506
-Node: Income statement accounts screen15842
-Node: All accounts screen16227
-Node: Register screen16590
-Node: Transaction screen19033
-Node: Error screen20608
-Node: WATCH MODE20974
-Node: --watch problems21872
-Node: ENVIRONMENT23225
-Node: BUGS23458
+Node: OPTIONS1869
+Node: MOUSE8755
+Node: KEYS9087
+Node: SCREENS14091
+Node: Menu screen14831
+Node: Cash accounts screen15147
+Node: Balance sheet accounts screen15508
+Node: Income statement accounts screen15844
+Node: All accounts screen16229
+Node: Register screen16592
+Node: Transaction screen19035
+Node: Error screen20610
+Node: WATCH MODE20976
+Node: --watch problems21874
+Node: ENVIRONMENT23227
+Node: BUGS23460
 
 End Tag Table
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/hledger-ui-1.50/hledger-ui.txt 
new/hledger-ui-1.50.1/hledger-ui.txt
--- old/hledger-ui-1.50/hledger-ui.txt  2025-09-03 21:06:35.000000000 +0200
+++ new/hledger-ui-1.50.1/hledger-ui.txt        2025-09-16 14:20:53.000000000 
+0200
@@ -11,7 +11,7 @@
        hledger ui [OPTS] [QUERYARGS]
 
 DESCRIPTION
-       This manual is for hledger's terminal  interface,  version  1.50.   See
+       This manual is for hledger's terminal interface, version  1.50.1.   See
        also the hledger manual for common concepts and file formats.
 
        hledger  is a robust, user-friendly, cross-platform set of programs for
@@ -471,4 +471,4 @@
 SEE ALSO
        hledger(1), hledger-ui(1), hledger-web(1), ledger(1)
 
-hledger-ui-1.50                 September 2025                   HLEDGER-UI(1)
+hledger-ui-1.50.1               September 2025                   HLEDGER-UI(1)

Reply via email to