diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,5 +1,43 @@
+<!--
+       _ 
+ _   _(_)
+| | | | |
+| |_| | |
+ \__,_|_|
+         
+-->
 User-visible changes in hledger-ui.
 See also the hledger changelog.
+
+# 1.22 2021-07-03
+
+Improvements
+
+- Don't reset the `B`/`V` (cost, value) state when reloading with `g`
+  or `--watch`. (Stephen Morgan)
+
+- The accounts screen is a little smarter at allocating space to
+  columns. (Stephen Morgan)
+
+- Add support for the kakoune editor, and improve the invocations of
+  some other editors. (crocket)
+
+- The `--version` flag shows more detail (git tag/patchlevel/commit
+  hash, platform/architecture). (Stephen Morgan)
+
+- GHC 9.0 is now officially supported, and GHC 8.0, 8.2, 8.4 are not;
+  building hledger now requires GHC 8.6 or greater.
+
+- Added a now-required lower bound on containers. (#1514)
+
+Fixes
+
+- Queries in the register screen work again (broken in 1.21). (#1523)
+  (Stephen Morgan)
+
+- Don't write to `./debug.log` when toggling value with `V`, or when
+  reloading with `g` or `--watch` in the Transaction screen. (#1556)
+  (Simon Michael, Stephen Morgan)
 
 # 1.21 2021-03-10
 
diff --git a/Hledger/UI/AccountsScreen.hs b/Hledger/UI/AccountsScreen.hs
--- a/Hledger/UI/AccountsScreen.hs
+++ b/Hledger/UI/AccountsScreen.hs
@@ -2,7 +2,6 @@
 
 {-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE RecordWildCards #-}
-{-# LANGUAGE CPP #-}
 
 module Hledger.UI.AccountsScreen
  (accountsScreen
@@ -19,9 +18,6 @@
 import Control.Monad.IO.Class (liftIO)
 import Data.List
 import Data.Maybe
-#if !(MIN_VERSION_base(4,11,0))
-import Data.Monoid ((<>))
-#endif
 import qualified Data.Text as T
 import Data.Time.Calendar (Day, addDays)
 import qualified Data.Vector as V
@@ -100,11 +96,8 @@
       AccountsScreenItem{asItemIndentLevel        = indent
                         ,asItemAccountName        = fullacct
                         ,asItemDisplayAccountName = replaceHiddenAccountsNameWith "All" $ if tree_ ropts then shortacct else fullacct
-                        ,asItemRenderedAmounts    = map showAmountWithoutPrice amts
+                        ,asItemMixedAmount        = Just bal
                         }
-      where
-        Mixed amts = normaliseMixedAmountSquashPricesForDisplay $ stripPrices bal
-        stripPrices (Mixed as) = Mixed $ map stripprice as where stripprice a = a{aprice=Nothing}
     displayitems = map displayitem items
     -- blanks added for scrolling control, cf RegisterScreen.
     -- XXX Ugly. Changing to 0 helps when debugging.
@@ -112,7 +105,7 @@
       AccountsScreenItem{asItemIndentLevel        = 0
                         ,asItemAccountName        = ""
                         ,asItemDisplayAccountName = ""
-                        ,asItemRenderedAmounts    = []
+                        ,asItemMixedAmount        = Nothing
                         }
 
 
@@ -124,10 +117,10 @@
               ,aScreen=s@AccountsScreen{}
               ,aMode=mode
               } =
-  case mode of
-    Help       -> [helpDialog copts, maincontent]
-    -- Minibuffer e -> [minibuffer e, maincontent]
-    _          -> [maincontent]
+    case mode of
+      Help       -> [helpDialog copts, maincontent]
+      -- Minibuffer e -> [minibuffer e, maincontent]
+      _          -> [maincontent]
   where
     maincontent = Widget Greedy Greedy $ do
       c <- getContext
@@ -137,33 +130,25 @@
           c^.availWidthL
           - 2 -- XXX due to margin ? shouldn't be necessary (cf UIUtils)
         displayitems = s ^. asList . listElementsL
-        maxacctwidthseen =
-          -- ltrace "maxacctwidthseen" $
-          V.maximum $
-          V.map (\AccountsScreenItem{..} -> asItemIndentLevel + Hledger.Cli.textWidth asItemDisplayAccountName) $
-          -- V.filter (\(indent,_,_,_) -> (indent-1) <= fromMaybe 99999 mdepth) $
-          displayitems
-        maxbalwidthseen =
-          -- ltrace "maxbalwidthseen" $
-          V.maximum $ V.map (\AccountsScreenItem{..} -> sum (map strWidth asItemRenderedAmounts) + 2 * (length asItemRenderedAmounts - 1)) displayitems
-        maxbalwidth =
-          -- ltrace "maxbalwidth" $
-          max 0 (availwidth - 2 - 4) -- leave 2 whitespace plus least 4 for accts
-        balwidth =
-          -- ltrace "balwidth" $
-          min maxbalwidth maxbalwidthseen
-        maxacctwidth =
-          -- ltrace "maxacctwidth" $
-          availwidth - 2 - balwidth
-        acctwidth =
-          -- ltrace "acctwidth" $
-          min maxacctwidth maxacctwidthseen
 
-        -- XXX how to minimise the balance column's jumping around
-        -- as you change the depth limit ?
+        acctwidths = V.map (\AccountsScreenItem{..} -> asItemIndentLevel + Hledger.Cli.textWidth asItemDisplayAccountName) displayitems
+        balwidths  = V.map (maybe 0 (wbWidth . showMixedAmountB oneLine) . asItemMixedAmount) displayitems
+        preferredacctwidth = V.maximum acctwidths
+        totalacctwidthseen = V.sum acctwidths
+        preferredbalwidth  = V.maximum balwidths
+        totalbalwidthseen  = V.sum balwidths
 
-        colwidths = (acctwidth, balwidth)
+        totalwidthseen = totalacctwidthseen + totalbalwidthseen
+        shortfall = preferredacctwidth + preferredbalwidth + 2 - availwidth
+        acctwidthproportion = fromIntegral totalacctwidthseen / fromIntegral totalwidthseen
+        adjustedacctwidth = min preferredacctwidth . max 15 . round $ acctwidthproportion * fromIntegral (availwidth - 2)  -- leave 2 whitespace for padding
+        adjustedbalwidth  = availwidth - 2 - adjustedacctwidth
 
+        -- XXX how to minimise the balance column's jumping around as you change the depth limit ?
+
+        colwidths | shortfall <= 0 = (preferredacctwidth, preferredbalwidth)
+                  | otherwise      = (adjustedacctwidth, adjustedbalwidth)
+
       render $ defaultLayout toplabel bottomlabel $ renderList (asDrawItem colwidths) True (_asList s)
 
       where
@@ -178,7 +163,7 @@
           <+> borderQueryStr (T.unpack . T.unwords . map textQuoteIfNeeded $ querystring_ ropts)
           <+> borderDepthStr mdepth
           <+> str (" ("++curidx++"/"++totidx++")")
-          <+> (if ignore_assertions_ $ inputopts_ copts
+          <+> (if ignore_assertions_ . balancingopts_ $ inputopts_ copts
                then withAttr ("border" <> "query") (str " ignoring balance assertions")
                else str "")
           where
@@ -230,24 +215,17 @@
     -- c <- getContext
       -- let showitem = intercalate "\n" . balanceReportItemAsText defreportopts fmt
     render $
-      addamts asItemRenderedAmounts $
-      str (T.unpack $ fitText (Just acctwidth) (Just acctwidth) True True $ T.replicate (asItemIndentLevel) " " <> asItemDisplayAccountName) <+>
-      str "  " <+>
-      str (balspace asItemRenderedAmounts)
+      txt (fitText (Just acctwidth) (Just acctwidth) True True $ T.replicate (asItemIndentLevel) " " <> asItemDisplayAccountName) <+>
+      txt balspace <+>
+      splitAmounts balBuilder
       where
-        balspace as = replicate n ' '
-          where n = max 0 (balwidth - (sum (map strWidth as) + 2 * (length as - 1)))
-        addamts :: [String] -> Widget Name -> Widget Name
-        addamts [] w = w
-        addamts [a] w = (<+> renderamt a) w
-        -- foldl' :: (b -> a -> b) -> b -> t a -> b
-        -- foldl' (Widget -> String -> Widget) -> Widget -> [String] -> Widget
-        addamts (a:as) w = foldl' addamt (addamts [a] w) as
-        addamt :: Widget Name -> String -> Widget Name
-        addamt w a = ((<+> renderamt a) . (<+> str ", ")) w
-        renderamt :: String -> Widget Name
-        renderamt a | '-' `elem` a = withAttr (sel $ "list" <> "balance" <> "negative") $ str a
-                    | otherwise    = withAttr (sel $ "list" <> "balance" <> "positive") $ str a
+        balBuilder = maybe mempty showamt asItemMixedAmount
+        showamt = showMixedAmountB oneLine{displayMinWidth=Just balwidth, displayMaxWidth=Just balwidth}
+        balspace = T.replicate (2 + balwidth - wbWidth balBuilder) " "
+        splitAmounts = foldr1 (<+>) . intersperse (str ", ") . map renderamt . T.splitOn ", " . wbToText
+        renderamt :: T.Text -> Widget Name
+        renderamt a | T.any (=='-') a = withAttr (sel $ "list" <> "balance" <> "negative") $ txt a
+                    | otherwise       = withAttr (sel $ "list" <> "balance" <> "positive") $ txt a
         sel | selected  = (<> "selected")
             | otherwise = id
 
diff --git a/Hledger/UI/Editor.hs b/Hledger/UI/Editor.hs
--- a/Hledger/UI/Editor.hs
+++ b/Hledger/UI/Editor.hs
@@ -11,6 +11,7 @@
 import Control.Applicative ((<|>))
 import Data.List (intercalate)
 import Data.Maybe (catMaybes)
+import Data.Bifunctor (bimap)
 import Safe
 import System.Environment
 import System.Exit
@@ -25,7 +26,7 @@
 
 -- | The text position meaning "last line, first column".
 endPosition :: Maybe TextPosition
-endPosition = Just (-1,Nothing)
+endPosition = Just (-1, Nothing)
 
 -- | Run the hledger-iadd executable on the given file, blocking until it exits,
 -- and return the exit code; or raise an error.
@@ -43,62 +44,82 @@
 -- | Get a shell command line to open the user's preferred text editor
 -- (or a default editor) on the given file, and to focus it at the
 -- given text position if one is provided and if we know how.
--- We know how to focus on position for: emacs, vi, nano, VS code.
--- We know how to focus on last line for: vi.
 --
+-- Just ('-' : _, _) is any text position with a negative line number.
+-- A text position with a negative line number means the last line.
+--
 -- Some tests:
 -- @
--- EDITOR program is:  LINE/COL specified ?  Command should be:               
--- ------------------  --------------------  ----------------------------------- 
--- emacs, emacsclient  LINE COL              emacs +LINE:COL FILE
---                     LINE                  emacs +LINE     FILE
---                                           emacs           FILE
+-- EDITOR program:  Maybe TextPosition    Command should be:
+-- ---------------  --------------------- ------------------------------------
+-- emacs            Just (line, Just col) emacs +LINE:COL FILE
+--                  Just (line, Nothing)  emacs +LINE     FILE
+--                  Just ('-' : _, _)     emacs FILE -f end-of-buffer
+--                  Nothing               emacs           FILE
 --
--- nano                LINE COL              nano +LINE,COL FILE
---                     LINE                  nano +LINE     FILE
---                                           nano           FILE
+-- emacsclient      Just (line, Just col) emacsclient +LINE:COL FILE
+--                  Just (line, Nothing)  emacsclient +LINE     FILE
+--                  Just ('-' : _, _)     emacsclient           FILE
+--                  Nothing               emacsclient           FILE
 --
--- code                LINE COL              code --goto FILE:LINE:COL
---                     LINE                  code --goto FILE:LINE
---                                           code        FILE
+-- nano             Just (line, Just col) nano +LINE:COL FILE
+--                  Just (line, Nothing)  nano +LINE     FILE
+--                  Just ('-' : _, _)     nano           FILE
+--                  Nothing               nano           FILE
 --
--- vi, & variants      LINE [COL]            vi +LINE FILE
---                     LINE (negative)       vi +     FILE
---                                           vi       FILE
+-- vscode           Just (line, Just col) vscode --goto FILE:LINE:COL
+--                  Just (line, Nothing)  vscode --goto FILE:LINE
+--                  Just ('-' : _, _)     vscode        FILE
+--                  Nothing               vscode        FILE
 --
--- (other PROG)        [LINE [COL]]          PROG FILE
+-- kak              Just (line, Just col) kak +LINE:COL FILE
+--                  Just (line, Nothing)  kak +LINE     FILE
+--                  Just ('-' : _, _)     kak +:        FILE
+--                  Nothing               kak           FILE
 --
--- (not set)           LINE COL              emacsclient -a '' -nw +LINE:COL FILE
---                     LINE                  emacsclient -a '' -nw +LINE     FILE
---                                           emacsclient -a '' -nw           FILE
--- @
+-- vi & variants    Just (line, _)        vi +LINE FILE
+--                  Just ('-' : _, _)     vi +     FILE
+--                  Nothing               vi       FILE
 --
--- Notes on opening editors at the last line of a file:
--- @
--- emacs:       emacs FILE -f end-of-buffer  # (-f must appear after FILE, +LINE:COL must appear before)
--- emacsclient: can't
--- vi:          vi + FILE
+-- (other PROG)     _                     PROG FILE
+--
+-- (not set)        Just (line, Just col) emacsclient -a '' -nw +LINE:COL FILE
+--                  Just (line, Nothing)  emacsclient -a '' -nw +LINE     FILE
+--                  Just ('-' : _, _)     emacsclient -a '' -nw           FILE
+--                  Nothing               emacsclient -a '' -nw           FILE
 -- @
 --
 editFileAtPositionCommand :: Maybe TextPosition -> FilePath -> IO String
 editFileAtPositionCommand mpos f = do
   cmd <- getEditCommand
-  let
-    editor = lowercase $ takeBaseName $ headDef "" $ words' cmd
-    f' = singleQuoteIfNeeded f
-    ml = show.fst <$> mpos
-    mc = maybe Nothing (fmap show.snd) mpos
-    args = case editor of
-             e | e `elem` ["emacs", "emacsclient"] -> ['+' : join ":" [ml,mc], f']
-             e | e `elem` ["nano"]                 -> ['+' : join "," [ml,mc], f']
-             e | e `elem` ["code"]                 -> ["--goto " ++ join ":" [Just f',ml,mc]]
-             e | e `elem` ["vi","vim","view","nvim","evim","eview","gvim","gview","rvim","rview",
-                           "rgvim","rgview","ex"]  -> [maybe "" plusMaybeLine ml, f']
-             _ -> [f']
-           where
-             join sep = intercalate sep . catMaybes
-             plusMaybeLine l = "+" ++ if take 1 l == "-" then "" else l
-
+  let editor = lowercase $ takeBaseName $ headDef "" $ words' cmd
+      f' = singleQuoteIfNeeded f
+      mpos' = Just . bimap show (fmap show) =<< mpos
+      join sep = intercalate sep . catMaybes
+      args = case editor of
+        "emacs" -> case mpos' of
+          Nothing -> [f']
+          Just ('-' : _, _) -> [f', "-f", "end-of-buffer"]
+          Just (l, mc) -> ['+' : join ":" [Just l, mc], f']
+        e | e `elem` ["emacsclient", "nano"] -> case mpos' of
+          Nothing -> [f']
+          Just ('-' : _, _) -> [f']
+          Just (l, mc) -> ['+' : join ":" [Just l, mc], f']
+        "vscode" -> case mpos' of
+          Nothing -> [f']
+          Just ('-' : _, _) -> [f']
+          Just (l, mc) -> ["--goto", join ":" [Just f', Just l, mc]]
+        "kak" -> case mpos' of
+          Nothing -> [f']
+          Just ('-' : _, _) -> ["+:", f']
+          Just (l, mc) -> ['+' : join ":" [Just l, mc], f']
+        e | e `elem` ["vi",  "vim", "view", "nvim", "evim", "eview",
+                      "gvim", "gview", "rvim", "rview",
+                      "rgvim", "rgview", "ex"] -> case mpos' of
+          Nothing -> [f']
+          Just ('-' : _, _) -> ["+", f']
+          Just (l, _) -> ['+' : l, f']
+        _ -> [f']
   return $ unwords $ cmd:args
 
 -- | Get the user's preferred edit command. This is the value of the
diff --git a/Hledger/UI/ErrorScreen.hs b/Hledger/UI/ErrorScreen.hs
--- a/Hledger/UI/ErrorScreen.hs
+++ b/Hledger/UI/ErrorScreen.hs
@@ -1,7 +1,8 @@
 -- The error screen, showing a current error condition (such as a parse error after reloading the journal)
 
-{-# LANGUAGE OverloadedStrings, FlexibleContexts, RecordWildCards #-}
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards   #-}
 
 module Hledger.UI.ErrorScreen
  (errorScreen
@@ -15,9 +16,6 @@
 -- import Brick.Widgets.Border ("border")
 import Control.Monad
 import Control.Monad.IO.Class (liftIO)
-#if !(MIN_VERSION_base(4,11,0))
-import Data.Monoid
-#endif
 import Data.Time.Calendar (Day)
 import Data.Void (Void)
 import Graphics.Vty (Event(..),Key(..),Modifier(..))
@@ -198,7 +196,7 @@
 -- are disabled, do nothing.
 uiCheckBalanceAssertions :: Day -> UIState -> UIState
 uiCheckBalanceAssertions d ui@UIState{aopts=UIOpts{cliopts_=copts}, ajournal=j}
-  | ignore_assertions_ $ inputopts_ copts = ui
+  | ignore_assertions_ . balancingopts_ $ inputopts_ copts = ui
   | otherwise =
     case journalCheckBalanceAssertions j of
       Nothing  -> ui
diff --git a/Hledger/UI/Main.hs b/Hledger/UI/Main.hs
--- a/Hledger/UI/Main.hs
+++ b/Hledger/UI/Main.hs
@@ -3,30 +3,22 @@
 Copyright (c) 2007-2015 Simon Michael <simon@joyful.com>
 Released under GPL version 3 or later.
 -}
-{-# LANGUAGE CPP #-}
-{-# LANGUAGE LambdaCase #-}
-{-# LANGUAGE OverloadedStrings #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings     #-}
 
 module Hledger.UI.Main where
 
--- import Control.Applicative
--- import Lens.Micro.Platform ((^.))
 import Control.Concurrent (threadDelay)
-import Control.Concurrent.Async
-import Control.Monad
--- import Control.Monad.IO.Class (liftIO)
--- import Data.Monoid              --
+import Control.Concurrent.Async (withAsync)
+import Control.Monad (forM_, void, when)
+import Data.List (find)
 import Data.List.Extra (nubSort)
-import Data.Maybe
--- import Data.Text (Text)
+import Data.Maybe (fromMaybe)
 import qualified Data.Text as T
--- import Data.Time.Calendar
 import Graphics.Vty (mkVty)
-import Safe
-import System.Directory
-import System.FilePath
-import System.FSNotify
+import System.Directory (canonicalizePath)
+import System.FilePath (takeDirectory)
+import System.FSNotify (Event(Modified), isPollingManager, watchDir, withManager)
 import Brick
 
 import qualified Brick.BChan as BC
@@ -141,11 +133,11 @@
       -- to that as usual.
       Just apat -> (rsSetAccount acct False registerScreen, [ascr'])
         where
-          acct = headDef (error' $ "--register "++apat++" did not match any account")  -- PARTIAL:
-                 . filterAccts $ journalAccountNames j
-          filterAccts = case toRegexCI $ T.pack apat of
-              Right re -> filter (regexMatchText re)
-              Left  _  -> const []
+          acct = fromMaybe (error' $ "--register "++apat++" did not match any account")  -- PARTIAL:
+                 . firstMatch $ journalAccountNamesDeclaredOrImplied j
+          firstMatch = case toRegexCI $ T.pack apat of
+              Right re -> find (regexMatchText re)
+              Left  _  -> const Nothing
           -- Initialising the accounts screen is awkward, requiring
           -- another temporary UIState value..
           ascr' = aScreen $
@@ -226,12 +218,7 @@
           d
           -- predicate: ignore changes not involving our files
           (\fev -> case fev of
-#if MIN_VERSION_fsnotify(0,3,0)
-            Modified f _ False
-#else
-            Modified f _
-#endif
-                               -> f `elem` files
+            Modified f _ False -> f `elem` files
             -- Added    f _ -> f `elem` files
             -- Removed  f _ -> f `elem` files
             -- we don't handle adding/removing journal files right now
@@ -248,9 +235,5 @@
 
         -- and start the app. Must be inside the withManager block
         let mkvty = mkVty mempty
-#if MIN_VERSION_brick(0,47,0)
         vty0 <- mkvty
         void $ customMain vty0 mkvty (Just eventChan) brickapp ui
-#else
-        void $ customMain mkvty (Just eventChan) brickapp ui
-#endif
diff --git a/Hledger/UI/RegisterScreen.hs b/Hledger/UI/RegisterScreen.hs
--- a/Hledger/UI/RegisterScreen.hs
+++ b/Hledger/UI/RegisterScreen.hs
@@ -1,7 +1,8 @@
 -- The account register screen, showing transactions in an account, like hledger-web's register.
 
-{-# LANGUAGE OverloadedStrings, FlexibleContexts, RecordWildCards #-}
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE FlexibleContexts  #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards   #-}
 
 module Hledger.UI.RegisterScreen
  (registerScreen
@@ -14,9 +15,6 @@
 import Control.Monad
 import Control.Monad.IO.Class (liftIO)
 import Data.List
-#if !(MIN_VERSION_base(4,11,0))
-import Data.Monoid ((<>))
-#endif
 import Data.Maybe
 import qualified Data.Text as T
 import Data.Time.Calendar
@@ -65,6 +63,8 @@
     -- XXX temp
     inclusive = tree_ ropts || rsForceInclusive
     thisacctq = Acct $ (if inclusive then accountNameToAccountRegex else accountNameToAccountOnlyRegex) rsAccount
+
+    -- adjust the report options and regenerate the ReportSpec, carefully as usual to avoid screwups (#1523)
     ropts' = ropts {
         -- ignore any depth limit, as in postingsReport; allows register's total to match accounts screen
         depth_=Nothing
@@ -72,10 +72,10 @@
         -- always show historical balance
       -- , balancetype_= HistoricalBalance
       }
-    -- regenerate the ReportSpec, making sure to use the above
-    rspec' = rspec{ rsQuery=simplifyQuery $ queryFromFlags ropts'
-                  , rsOpts=ropts'
-                  }
+    rspec' =
+      either (error "rsInit: adjusting the query for register, should not have failed") id $ -- PARTIAL:
+      updateReportSpec ropts' rspec
+
     -- Further restrict the query based on the current period and future/forecast mode.
     q = simplifyQuery $ And [rsQuery rspec', periodq, excludeforecastq (forecast_ ropts)]
       where
@@ -87,7 +87,6 @@
              Not (Date $ DateSpan (Just $ addDays 1 d) Nothing)
             ,Not generatedTransactionTag
           ]
-
     items = accountTransactionsReport rspec' j q thisacctq
     items' = (if empty_ ropts then id else filter (not . mixedAmountLooksZero . fifth6)) $  -- without --empty, exclude no-change txns
              reverse  -- most recent last
@@ -97,17 +96,16 @@
     displayitems = map displayitem items'
       where
         displayitem (t, _, _issplit, otheracctsstr, change, bal) =
-          RegisterScreenItem{rsItemDate          = T.unpack . showDate $ transactionRegisterDate q thisacctq t
+          RegisterScreenItem{rsItemDate          = showDate $ transactionRegisterDate q thisacctq t
                             ,rsItemStatus        = tstatus t
-                            ,rsItemDescription   = T.unpack $ tdescription t
-                            ,rsItemOtherAccounts = T.unpack otheracctsstr
+                            ,rsItemDescription   = tdescription t
+                            ,rsItemOtherAccounts = otheracctsstr
                                                      -- _   -> "<split>"  -- should do this if accounts field width < 30
                             ,rsItemChangeAmount  = showamt change
                             ,rsItemBalanceAmount = showamt bal
                             ,rsItemTransaction   = t
                             }
-            where showamt = (\wb -> (wbUnpack wb, wbWidth wb))
-                          . showMixedAmountB oneLine{displayMaxWidth=Just 32}
+            where showamt = showMixedAmountB oneLine{displayMaxWidth=Just 32}
     -- blank items are added to allow more control of scroll position; we won't allow movement over these.
     -- XXX Ugly. Changing to 0 helps when debugging.
     blankitems = replicate 100  -- "100 ought to be enough for anyone"
@@ -115,8 +113,8 @@
                             ,rsItemStatus        = Unmarked
                             ,rsItemDescription   = ""
                             ,rsItemOtherAccounts = ""
-                            ,rsItemChangeAmount  = ("", 0)
-                            ,rsItemBalanceAmount = ("", 0)
+                            ,rsItemChangeAmount  = mempty
+                            ,rsItemBalanceAmount = mempty
                             ,rsItemTransaction   = nulltransaction
                             }
     -- build the List
@@ -174,8 +172,8 @@
         whitespacewidth = 10 -- inter-column whitespace, fixed width
         minnonamtcolswidth = datewidth + 1 + 2 + 2 -- date column plus at least 1 for status and 2 for desc and accts
         maxamtswidth = max 0 (totalwidth - minnonamtcolswidth - whitespacewidth)
-        maxchangewidthseen = maximum' $ map (snd . rsItemChangeAmount) displayitems
-        maxbalwidthseen = maximum' $ map (snd . rsItemBalanceAmount) displayitems
+        maxchangewidthseen = maximum' $ map (wbWidth . rsItemChangeAmount) displayitems
+        maxbalwidthseen = maximum' $ map (wbWidth . rsItemBalanceAmount) displayitems
         changewidthproportion = fromIntegral maxchangewidthseen / fromIntegral (maxchangewidthseen + maxbalwidthseen)
         maxchangewidth = round $ changewidthproportion * fromIntegral maxamtswidth
         maxbalwidth = maxamtswidth - maxchangewidth
@@ -220,7 +218,7 @@
           <+> str "/"
           <+> total
           <+> str ")"
-          <+> (if ignore_assertions_ $ inputopts_ copts then withAttr ("border" <> "query") (str " ignoring balance assertions") else str "")
+          <+> (if ignore_assertions_ . balancingopts_ $ inputopts_ copts then withAttr ("border" <> "query") (str " ignoring balance assertions") else str "")
           where
             togglefilters =
               case concat [
@@ -234,7 +232,7 @@
                          Nothing -> "-"
                          Just i -> show (i + 1)
             total = str $ show $ length nonblanks
-            nonblanks = V.takeWhile (not . null . rsItemDate) $ rsList^.listElementsL
+            nonblanks = V.takeWhile (not . T.null . rsItemDate) $ rsList^.listElementsL
 
             -- query = query_ $ reportopts_ $ cliopts_ opts
 
@@ -265,22 +263,24 @@
 rsDrawItem (datewidth,descwidth,acctswidth,changewidth,balwidth) selected RegisterScreenItem{..} =
   Widget Greedy Fixed $ do
     render $
-      str (fitString (Just datewidth) (Just datewidth) True True rsItemDate) <+>
-      str " " <+>
-      str (fitString (Just 1) (Just 1) True True (show rsItemStatus)) <+>
-      str " " <+>
-      str (fitString (Just descwidth) (Just descwidth) True True rsItemDescription) <+>
-      str "  " <+>
-      str (fitString (Just acctswidth) (Just acctswidth) True True rsItemOtherAccounts) <+>
-      str "   " <+>
-      withAttr changeattr (str (fitString (Just changewidth) (Just changewidth) True False $ fst rsItemChangeAmount)) <+>
-      str "   " <+>
-      withAttr balattr (str (fitString (Just balwidth) (Just balwidth) True False $ fst rsItemBalanceAmount))
+      txt (fitText (Just datewidth) (Just datewidth) True True rsItemDate) <+>
+      txt " " <+>
+      txt (fitText (Just 1) (Just 1) True True (T.pack $ show rsItemStatus)) <+>
+      txt " " <+>
+      txt (fitText (Just descwidth) (Just descwidth) True True rsItemDescription) <+>
+      txt "  " <+>
+      txt (fitText (Just acctswidth) (Just acctswidth) True True rsItemOtherAccounts) <+>
+      txt "   " <+>
+      withAttr changeattr (txt $ fitText (Just changewidth) (Just changewidth) True False changeAmt) <+>
+      txt "   " <+>
+      withAttr balattr (txt $ fitText (Just balwidth) (Just balwidth) True False balanceAmt)
   where
-    changeattr | '-' `elem` fst rsItemChangeAmount = sel $ "list" <> "amount" <> "decrease"
-               | otherwise                     = sel $ "list" <> "amount" <> "increase"
-    balattr    | '-' `elem` fst rsItemBalanceAmount = sel $ "list" <> "balance" <> "negative"
-               | otherwise                      = sel $ "list" <> "balance" <> "positive"
+    changeAmt  = wbToText rsItemChangeAmount
+    balanceAmt = wbToText rsItemBalanceAmount
+    changeattr | T.any (=='-') changeAmt  = sel $ "list" <> "amount" <> "decrease"
+               | otherwise                = sel $ "list" <> "amount" <> "increase"
+    balattr    | T.any (=='-') balanceAmt = sel $ "list" <> "balance" <> "negative"
+               | otherwise                = sel $ "list" <> "balance" <> "positive"
     sel | selected  = (<> "selected")
         | otherwise = id
 
@@ -294,7 +294,7 @@
   d <- liftIO getCurrentDay
   let
     journalspan = journalDateSpan False j
-    nonblanks = V.takeWhile (not . null . rsItemDate) $ rsList^.listElementsL
+    nonblanks = V.takeWhile (not . T.null . rsItemDate) $ rsList^.listElementsL
     lastnonblankidx = max 0 (length nonblanks - 1)
 
   case mode of
@@ -365,17 +365,9 @@
         VtyEvent (EvKey (KChar 'z') [MCtrl]) -> suspend ui
 
         -- enter transaction screen for selected transaction
-        VtyEvent e | e `elem` moveRightEvents -> do
+        VtyEvent e | e `elem` moveRightEvents ->
           case listSelectedElement rsList of
-            Just (_, RegisterScreenItem{rsItemTransaction=t}) ->
-              let
-                ts = map rsItemTransaction $ V.toList $ nonblanks
-                numberedts = zip [1..] ts
-                i = maybe 0 (toInteger . (+1)) $ elemIndex t ts -- XXX
-              in
-                continue $ screenEnter d transactionScreen{tsTransaction=(i,t)
-                                                          ,tsTransactions=numberedts
-                                                          ,tsAccount=rsAccount} ui
+            Just _  -> continue $ screenEnter d transactionScreen{tsAccount=rsAccount} ui
             Nothing -> continue ui
 
         -- prevent moving down over blank padding items;
diff --git a/Hledger/UI/Theme.hs b/Hledger/UI/Theme.hs
--- a/Hledger/UI/Theme.hs
+++ b/Hledger/UI/Theme.hs
@@ -7,7 +7,6 @@
 -- http://hackage.haskell.org/package/brick-0.1/docs/Brick-Widgets-Core.html#g:5
 -- http://hackage.haskell.org/package/brick-0.1/docs/Brick-Widgets-Border.html
 
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE OverloadedStrings #-}
 
 module Hledger.UI.Theme (
@@ -20,9 +19,6 @@
 
 import qualified Data.Map as M
 import Data.Maybe
-#if !(MIN_VERSION_base(4,11,0))
-import Data.Monoid
-#endif
 import Graphics.Vty
 import Brick
 
diff --git a/Hledger/UI/TransactionScreen.hs b/Hledger/UI/TransactionScreen.hs
--- a/Hledger/UI/TransactionScreen.hs
+++ b/Hledger/UI/TransactionScreen.hs
@@ -1,7 +1,8 @@
 -- The transaction screen, showing a single transaction's general journal entry.
 
-{-# LANGUAGE OverloadedStrings, TupleSections, RecordWildCards #-} -- , FlexibleContexts
-{-# LANGUAGE CPP #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RecordWildCards   #-}
+{-# LANGUAGE TupleSections     #-}
 
 module Hledger.UI.TransactionScreen
  (transactionScreen
@@ -13,14 +14,13 @@
 import Control.Monad.IO.Class (liftIO)
 import Data.List
 import Data.Maybe
-#if !(MIN_VERSION_base(4,11,0))
-import Data.Monoid
-#endif
 import qualified Data.Text as T
 import Data.Time.Calendar (Day)
+import qualified Data.Vector as V
 import Graphics.Vty (Event(..),Key(..),Modifier(..))
+import Lens.Micro ((^.))
 import Brick
-import Brick.Widgets.List (listMoveTo)
+import Brick.Widgets.List (listElementsL, listMoveTo, listSelectedElement)
 
 import Hledger
 import Hledger.Cli hiding (progname,prognameandversion)
@@ -45,16 +45,20 @@
 tsInit :: Day -> Bool -> UIState -> UIState
 tsInit _d _reset ui@UIState{aopts=UIOpts{cliopts_=CliOpts{reportspec_=_rspec}}
                            ,ajournal=_j
-                           ,aScreen=TransactionScreen{}
+                           ,aScreen=s@TransactionScreen{tsTransaction=(_,t),tsTransactions=nts}
+                           ,aPrevScreens=prevscreens
                            } =
-  -- plog ("initialising TransactionScreen, value_ is "
-  --       -- ++ (pshow (Just (AtDefault Nothing)::Maybe ValuationType))
-  --       ++(pshow (value_ _ropts))  -- XXX calling value_ here causes plog to fail with: debug.log: openFile: resource busy (file is locked)
-  --       ++ "?"
-  --       ++" and first commodity is")
-  --       (acommodity$head$amounts$pamount$head$tpostings$snd$tsTransaction)
-  --      `seq`
-  ui
+    ui{aScreen=s{tsTransaction=(i',t'),tsTransactions=nts'}}
+  where
+    i' = maybe 0 (toInteger . (+1)) . elemIndex t' $ map snd nts'
+    -- If the previous screen was RegisterScreen, use the listed and selected items as
+    -- the transactions. Otherwise, use the provided transaction and list.
+    (t',nts') = case prevscreens of
+        RegisterScreen{rsList=xs}:_ -> (seltxn, zip [1..] $ map rsItemTransaction nonblanks)
+          where
+            seltxn = maybe nulltransaction (rsItemTransaction . snd) $ listSelectedElement xs
+            nonblanks = V.toList . V.takeWhile (not . T.null . rsItemDate) $ xs ^. listElementsL
+        _                           -> (t, nts)
 tsInit _ _ _ = error "init function called with wrong screen type, should not happen"  -- PARTIAL:
 
 tsDraw :: UIState -> [Widget Name]
@@ -72,7 +76,7 @@
     _          -> [maincontent]
   where
     -- as with print, show amounts with all of their decimal places
-    t = transactionMapPostingAmounts amountSetFullPrecision t'
+    t = transactionMapPostingAmounts mixedAmountSetFullPrecision t'
     maincontent = Widget Greedy Greedy $ do
       let
         prices = journalPriceOracle (infer_value_ ropts) j
@@ -83,7 +87,10 @@
 
       render . defaultLayout toplabel bottomlabel . str
         . T.unpack . showTransactionOneLineAmounts
-        $ transactionApplyCostValuation prices styles periodlast (rsToday rspec) (cost_ ropts) (value_ ropts) t
+        . maybe id (transactionApplyValuation prices styles periodlast (rsToday rspec)) (value_ ropts)
+        $ case cost_ ropts of
+               Cost   -> transactionToCost styles t
+               NoCost -> t
         -- (if real_ ropts then filterTransactionPostings (Real True) else id) -- filter postings by --real
       where
         toplabel =
@@ -97,7 +104,7 @@
           <+> togglefilters
           <+> borderQueryStr (unwords . map (quoteIfNeeded . T.unpack) $ querystring_ ropts)
           <+> str (" in "++T.unpack (replaceHiddenAccountsNameWith "All" acct)++")")
-          <+> (if ignore_assertions_ $ inputopts_ copts then withAttr ("border" <> "query") (str " ignoring balance assertions") else str "")
+          <+> (if ignore_assertions_ . balancingopts_ $ inputopts_ copts then withAttr ("border" <> "query") (str " ignoring balance assertions") else str "")
           where
             togglefilters =
               case concat [
@@ -128,9 +135,8 @@
 tsHandle :: UIState -> BrickEvent Name AppEvent -> EventM Name (Next UIState)
 tsHandle ui@UIState{aScreen=s@TransactionScreen{tsTransaction=(i,t)
                                                ,tsTransactions=nts
-                                               ,tsAccount=acct
                                                }
-                   ,aopts=UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}
+                   ,aopts=UIOpts{cliopts_=copts}
                    ,ajournal=j
                    ,aMode=mode
                    }
@@ -167,12 +173,7 @@
           ej <- liftIO $ journalReload copts
           case ej of
             Left err -> continue $ screenEnter d errorScreen{esError=err} ui
-            Right j' -> do
-              continue $
-                regenerateScreens j' d $
-                regenerateTransactions rspec j' s acct i $   -- added (inline) 201512 (why ?)
-                clearCostValue $
-                ui
+            Right j' -> continue $ regenerateScreens j' d ui
         VtyEvent (EvKey (KChar 'I') []) -> continue $ uiCheckBalanceAssertions d (toggleIgnoreBalanceAssertions ui)
 
         -- for toggles that may change the current/prev/next transactions,
@@ -183,12 +184,10 @@
         VtyEvent (EvKey (KChar 'B') []) ->
           continue $
           regenerateScreens j d $
-          -- regenerateTransactions ropts d j s acct i $
           toggleCost ui
         VtyEvent (EvKey (KChar 'V') []) ->
           continue $
           regenerateScreens j d $
-          -- regenerateTransactions ropts d j s acct i $
           toggleValue ui
 
         VtyEvent e | e `elem` moveUpEvents   -> continue $ regenerateScreens j d ui{aScreen=s{tsTransaction=(iprev,tprev)}}
@@ -202,29 +201,6 @@
         _ -> continue ui
 
 tsHandle _ _ = error "event handler called with wrong screen type, should not happen"  -- PARTIAL:
-
--- Got to redo the register screen's transactions report, to get the latest transactions list for this screen.
--- XXX Duplicates rsInit. Why do we have to do this as well as regenerateScreens ?
-regenerateTransactions :: ReportSpec -> Journal -> Screen -> AccountName -> Integer -> UIState -> UIState
-regenerateTransactions rspec j s acct i ui =
-  let
-    q = filterQuery (not . queryIsDepth) $ rsQuery rspec
-    thisacctq = Acct $ accountNameToAccountRegex acct -- includes subs
-    items = reverse $ accountTransactionsReport rspec j q thisacctq
-    ts = map first6 items
-    numberedts = zip [1..] ts
-    -- select the best current transaction from the new list
-    -- stay at the same index if possible, or if we are now past the end, select the last, otherwise select the first
-    (i',t') = case lookup i numberedts
-              of Just t'' -> (i,t'')
-                 Nothing | null numberedts -> (0,nulltransaction)
-                         | i > fst (last numberedts) -> last numberedts
-                         | otherwise -> head numberedts
-  in
-    ui{aScreen=s{tsTransaction=(i',t')
-                ,tsTransactions=numberedts
-                ,tsAccount=acct
-                }}
 
 -- | Select the nth item on the register screen.
 rsSelect i scr@RegisterScreen{..} = scr{rsList=l'}
diff --git a/Hledger/UI/UIOptions.hs b/Hledger/UI/UIOptions.hs
--- a/Hledger/UI/UIOptions.hs
+++ b/Hledger/UI/UIOptions.hs
@@ -1,5 +1,4 @@
 {-# LANGUAGE CPP #-}
-{-# LANGUAGE LambdaCase #-}
 {-|
 
 -}
@@ -13,15 +12,14 @@
 import Hledger.Cli hiding (progname,version,prognameandversion)
 import Hledger.UI.Theme (themeNames)
 
-progname, version :: String
+progname, version, prognameandversion :: String
 progname = "hledger-ui"
 #ifdef VERSION
 version = VERSION
 #else
 version = ""
 #endif
-prognameandversion :: String
-prognameandversion = progname ++ " " ++ version :: String
+prognameandversion = versiondescription progname
 
 uiflags = [
   -- flagNone ["debug-ui"] (setboolopt "rules-file") "run with no terminal output, showing console"
diff --git a/Hledger/UI/UIState.hs b/Hledger/UI/UIState.hs
--- a/Hledger/UI/UIState.hs
+++ b/Hledger/UI/UIState.hs
@@ -2,7 +2,6 @@
 
 {-# LANGUAGE NamedFieldPuns    #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE RecordWildCards   #-}
 
 module Hledger.UI.UIState
 where
@@ -10,6 +9,7 @@
 import Brick.Widgets.Edit
 import Data.List ((\\), foldl', sort)
 import Data.Maybe (fromMaybe)
+import Data.Semigroup (Max(..))
 import qualified Data.Text as T
 import Data.Text.Zipper (gotoEOL)
 import Data.Time.Calendar (Day)
@@ -105,11 +105,6 @@
   where
     toggleEmpty ropts = ropts{empty_=not $ empty_ ropts}
 
--- | Show primary amounts, not cost or value.
-clearCostValue :: UIState -> UIState
-clearCostValue ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =
-  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{value_ = plog "clearing value mode" Nothing}}}}}
-
 -- | Toggle between showing the primary amounts or costs.
 toggleCost :: UIState -> UIState
 toggleCost ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =
@@ -122,7 +117,7 @@
 toggleValue :: UIState -> UIState
 toggleValue ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =
   ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{
-    value_ = plog "toggling value mode to" $ valuationToggleValue $ value_ ropts}}}}}
+    value_ = valuationToggleValue $ value_ ropts}}}}}
 
 -- | Basic toggling of -V, for hledger-ui.
 valuationToggleValue :: Maybe ValuationType -> Maybe ValuationType
@@ -186,8 +181,8 @@
 
 -- | Toggle the ignoring of balance assertions.
 toggleIgnoreBalanceAssertions :: UIState -> UIState
-toggleIgnoreBalanceAssertions ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=iopts}}} =
-  ui{aopts=uopts{cliopts_=copts{inputopts_=iopts{ignore_assertions_=not $ ignore_assertions_ iopts}}}}
+toggleIgnoreBalanceAssertions ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=iopts@InputOpts{balancingopts_=bopts}}}} =
+  ui{aopts=uopts{cliopts_=copts{inputopts_=iopts{balancingopts_=bopts{ignore_assertions_=not $ ignore_assertions_ bopts}}}}}
 
 -- | Step through larger report periods, up to all.
 growReportPeriod :: Day -> UIState -> UIState
@@ -237,7 +232,7 @@
 setFilter s ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =
     ui{aopts=uopts{cliopts_=copts{reportspec_=update rspec}}}
   where
-    update = either (const rspec) id . updateReportSpecWith (\ropts -> ropts{querystring_=querystring})
+    update = either (const rspec) id . updateReportSpecWith (\ropts -> ropts{querystring_=querystring})  -- XXX silently ignores an error
     querystring = words'' prefixes $ T.pack s
 
 -- | Reset some filters & toggles.
@@ -264,7 +259,7 @@
 
 -- | Get the maximum account depth in the current journal.
 maxDepth :: UIState -> Int
-maxDepth UIState{ajournal=j} = maximum $ map accountNameLevel $ journalAccountNames j
+maxDepth UIState{ajournal=j} = getMax . foldMap (Max . accountNameLevel) $ journalAccountNamesDeclaredOrImplied j
 
 -- | Decrement the current depth limit towards 0. If there was no depth limit,
 -- set it to one less than the maximum account depth.
diff --git a/Hledger/UI/UITypes.hs b/Hledger/UI/UITypes.hs
--- a/Hledger/UI/UITypes.hs
+++ b/Hledger/UI/UITypes.hs
@@ -38,6 +38,7 @@
 
 module Hledger.UI.UITypes where
 
+import Data.Text (Text)
 import Data.Time.Calendar (Day)
 import Brick
 import Brick.Widgets.List (List)
@@ -133,22 +134,21 @@
 
 -- | An item in the accounts screen's list of accounts and balances.
 data AccountsScreenItem = AccountsScreenItem {
-   asItemIndentLevel        :: Int          -- ^ indent level
-  ,asItemAccountName        :: AccountName  -- ^ full account name
-  ,asItemDisplayAccountName :: AccountName  -- ^ full or short account name to display
-  ,asItemRenderedAmounts    :: [String]     -- ^ rendered amounts
-  }
-  deriving (Show)
+   asItemIndentLevel        :: Int                -- ^ indent level
+  ,asItemAccountName        :: AccountName        -- ^ full account name
+  ,asItemDisplayAccountName :: AccountName        -- ^ full or short account name to display
+  ,asItemMixedAmount        :: Maybe MixedAmount  -- ^ mixed amount to display
+  } deriving (Show)
 
 -- | An item in the register screen's list of transactions in the current account.
 data RegisterScreenItem = RegisterScreenItem {
-   rsItemDate           :: String           -- ^ date
-  ,rsItemStatus         :: Status           -- ^ transaction status
-  ,rsItemDescription    :: String           -- ^ description
-  ,rsItemOtherAccounts  :: String           -- ^ other accounts
-  ,rsItemChangeAmount   :: (String, Int)    -- ^ the change to the current account from this transaction
-  ,rsItemBalanceAmount  :: (String, Int)    -- ^ the balance or running total after this transaction
-  ,rsItemTransaction    :: Transaction      -- ^ the full transaction
+   rsItemDate           :: Text         -- ^ date
+  ,rsItemStatus         :: Status       -- ^ transaction status
+  ,rsItemDescription    :: Text         -- ^ description
+  ,rsItemOtherAccounts  :: Text         -- ^ other accounts
+  ,rsItemChangeAmount   :: WideBuilder  -- ^ the change to the current account from this transaction
+  ,rsItemBalanceAmount  :: WideBuilder  -- ^ the balance or running total after this transaction
+  ,rsItemTransaction    :: Transaction  -- ^ the full transaction
   }
   deriving (Show)
 
diff --git a/Hledger/UI/UIUtils.hs b/Hledger/UI/UIUtils.hs
--- a/Hledger/UI/UIUtils.hs
+++ b/Hledger/UI/UIUtils.hs
@@ -1,7 +1,7 @@
 {- | Rendering & misc. helpers. -}
 
+{-# LANGUAGE CPP               #-}
 {-# LANGUAGE OverloadedStrings #-}
-{-# LANGUAGE CPP #-}
 
 module Hledger.UI.UIUtils (
    borderDepthStr
@@ -35,9 +35,6 @@
 import Brick.Widgets.List (List, listSelectedL, listNameL, listItemHeightL)
 import Control.Monad.IO.Class
 import Data.List
-#if !(MIN_VERSION_base(4,11,0))
-import Data.Monoid
-#endif
 import qualified Data.Text as T
 import Graphics.Vty
   (Event(..),Key(..),Modifier(..),Vty(..),Color,Attr,currentAttr,refresh
diff --git a/hledger-ui.1 b/hledger-ui.1
--- a/hledger-ui.1
+++ b/hledger-ui.1
@@ -1,5 +1,5 @@
 
-.TH "HLEDGER-UI" "1" "December 2020" "hledger-ui-1.21 " "hledger User Manuals"
+.TH "HLEDGER-UI" "1" "July 2021" "hledger-ui-1.22 " "hledger User Manuals"
 
 
 
@@ -7,7 +7,7 @@
 .PP
 hledger-ui is a terminal interface (TUI) for the hledger accounting
 tool.
-This manual is for hledger-ui 1.21.
+This manual is for hledger-ui 1.22.
 .SH SYNOPSIS
 .PP
 \f[C]hledger-ui [OPTIONS] [QUERYARGS]\f[R]
@@ -97,10 +97,12 @@
 hledger reporting options:
 .TP
 \f[B]\f[CB]-b --begin=DATE\f[B]\f[R]
-include postings/txns on or after this date
+include postings/txns on or after this date (will be adjusted to
+preceding subperiod start when using a report interval)
 .TP
 \f[B]\f[CB]-e --end=DATE\f[B]\f[R]
-include postings/txns before this date
+include postings/txns before this date (will be adjusted to following
+subperiod end when using a report interval)
 .TP
 \f[B]\f[CB]-D --daily\f[B]\f[R]
 multiperiod/multicolumn report by day
diff --git a/hledger-ui.cabal b/hledger-ui.cabal
--- a/hledger-ui.cabal
+++ b/hledger-ui.cabal
@@ -1,13 +1,11 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.33.0.
+-- This file has been generated from package.yaml by hpack version 0.34.4.
 --
 -- see: https://github.com/sol/hpack
---
--- hash: d46e4712160e17959b23d613872b2441b0138dcb5a455b7403dcef42e41b695c
 
 name:           hledger-ui
-version:        1.21
+version:        1.22
 synopsis:       Curses-style terminal interface for the hledger accounting system
 description:    A simple curses-style terminal user interface for the hledger accounting system.
                 It can be a more convenient way to browse your accounts than the CLI.
@@ -27,8 +25,9 @@
 maintainer:     Simon Michael <simon@joyful.com>
 license:        GPL-3
 license-file:   LICENSE
-tested-with:    GHC==8.0.2, GHC==8.2.2, GHC==8.4.4, GHC==8.6.5, GHC==8.8.3, GHC==8.10.0.20200123
 build-type:     Simple
+tested-with:
+    GHC==8.6.5, GHC==8.8.4, GHC==8.10.4
 extra-source-files:
     CHANGES.md
     README.md
@@ -62,24 +61,24 @@
       Hledger.UI.UIUtils
       Paths_hledger_ui
   hs-source-dirs:
-      ./.
+      ./
   ghc-options: -Wall -fno-warn-unused-do-bind -fno-warn-name-shadowing -fno-warn-missing-signatures -fno-warn-type-defaults -fno-warn-orphans
-  cpp-options: -DVERSION="1.21"
+  cpp-options: -DVERSION="1.22"
   build-depends:
       ansi-terminal >=0.9
     , async
-    , base >=4.9 && <4.15
+    , base >=4.10.1.0 && <4.16
     , base-compat-batteries >=0.10.1 && <0.12
     , brick >=0.23
     , cmdargs >=0.8
-    , containers
+    , containers >=0.5.9
     , data-default
     , directory
     , extra >=1.6.3
     , filepath
     , fsnotify >=0.2.1.2 && <0.4
-    , hledger >=1.21 && <1.22
-    , hledger-lib >=1.21 && <1.22
+    , hledger ==1.22.*
+    , hledger-lib ==1.22.*
     , megaparsec >=7.0.0 && <9.1
     , microlens >=0.4
     , microlens-platform >=0.2.3.1
diff --git a/hledger-ui.hs b/hledger-ui.hs
--- a/hledger-ui.hs
+++ b/hledger-ui.hs
@@ -1,5 +1,7 @@
-#!/usr/bin/env runhaskell
-module Main
-  (module Hledger.UI)
+module Main (main)
 where
-import Hledger.UI (main)
+-- import Hledger.UI (main)
+-- workaround for GHC 9.0.1 https://gitlab.haskell.org/ghc/ghc/-/issues/19397, #1503
+import qualified Hledger.UI.Main (main)
+main :: IO ()
+main = Hledger.UI.Main.main
diff --git a/hledger-ui.info b/hledger-ui.info
--- a/hledger-ui.info
+++ b/hledger-ui.info
@@ -1,37 +1,41 @@
-This is hledger-ui/hledger-ui.info, produced by makeinfo version 4.8
-from stdin.
+This is hledger-ui.info, produced by makeinfo version 6.7 from stdin.
 
+INFO-DIR-SECTION User Applications
+START-INFO-DIR-ENTRY
+* hledger-ui: (hledger-ui/hledger-ui).  Terminal UI for the hledger accounting tool.
+END-INFO-DIR-ENTRY
+
 
-File: hledger-ui.info,  Node: Top,  Up: (dir)
+File: hledger-ui.info,  Node: Top,  Next: OPTIONS,  Up: (dir)
 
 hledger-ui(1)
 *************
 
 hledger-ui is a terminal interface (TUI) for the hledger accounting
-tool. This manual is for hledger-ui 1.21.
+tool.  This manual is for hledger-ui 1.22.
 
-   `hledger-ui [OPTIONS] [QUERYARGS]'
-`hledger ui -- [OPTIONS] [QUERYARGS]'
+   'hledger-ui [OPTIONS] [QUERYARGS]'
+'hledger ui -- [OPTIONS] [QUERYARGS]'
 
    hledger is a reliable, cross-platform set of programs for tracking
 money, time, or any other commodity, using double-entry accounting and a
-simple, editable file format. hledger is inspired by and largely
+simple, editable file format.  hledger is inspired by and largely
 compatible with ledger(1).
 
    hledger-ui is hledger's terminal interface, providing an efficient
 full-window text UI for viewing accounts and transactions, and some
-limited data entry capability. It is easier than hledger's command-line
+limited data entry capability.  It is easier than hledger's command-line
 interface, and sometimes quicker and more convenient than the web
 interface.
 
    Like hledger, it reads data from one or more files in hledger
-journal, timeclock, timedot, or CSV format specified with `-f', or
-`$LEDGER_FILE', or `$HOME/.hledger.journal' (on windows, perhaps
-`C:/Users/USER/.hledger.journal'). For more about this see hledger(1),
+journal, timeclock, timedot, or CSV format specified with '-f', or
+'$LEDGER_FILE', or '$HOME/.hledger.journal' (on windows, perhaps
+'C:/Users/USER/.hledger.journal').  For more about this see hledger(1),
 hledger_journal(5) etc.
 
    Unlike hledger, hledger-ui hides all future-dated transactions by
-default. They can be revealed, along with any rule-generated periodic
+default.  They can be revealed, along with any rule-generated periodic
 transactions, by pressing the F key (or starting with -forecast) to
 enable "forecast mode".
 
@@ -50,141 +54,146 @@
 1 OPTIONS
 *********
 
-Note: if invoking hledger-ui as a hledger subcommand, write `--' before
+Note: if invoking hledger-ui as a hledger subcommand, write '--' before
 options as shown above.
 
    Any QUERYARGS are interpreted as a hledger search query which filters
 the data.
 
-`--watch'
+'--watch'
+
      watch for data and date changes and reload automatically
+'--theme=default|terminal|greenterm'
 
-`--theme=default|terminal|greenterm'
      use this custom display theme
+'--register=ACCTREGEX'
 
-`--register=ACCTREGEX'
      start in the (first) matched account's register screen
+'--change'
 
-`--change'
      show period balances (changes) at startup instead of historical
      balances
+'-l --flat'
 
-`-l --flat'
      show accounts as a flat list (default)
+'-t --tree'
 
-`-t --tree'
      show accounts as a tree
 
    hledger input options:
 
-`-f FILE --file=FILE'
-     use a different input file. For stdin, use - (default:
-     `$LEDGER_FILE' or `$HOME/.hledger.journal')
+'-f FILE --file=FILE'
 
-`--rules-file=RULESFILE'
+     use a different input file.  For stdin, use - (default:
+     '$LEDGER_FILE' or '$HOME/.hledger.journal')
+'--rules-file=RULESFILE'
+
      Conversion rules file to use when reading CSV (default: FILE.rules)
+'--separator=CHAR'
 
-`--separator=CHAR'
      Field separator to expect when reading CSV (default: ',')
+'--alias=OLD=NEW'
 
-`--alias=OLD=NEW'
      rename accounts named OLD to NEW
+'--anon'
 
-`--anon'
      anonymize accounts and payees
+'--pivot FIELDNAME'
 
-`--pivot FIELDNAME'
      use some other field or tag for the account name
+'-I --ignore-assertions'
 
-`-I --ignore-assertions'
      disable balance assertion checks (note: does not disable balance
      assignments)
+'-s --strict'
 
-`-s --strict'
      do extra error checking (check that all posted accounts are
      declared)
 
    hledger reporting options:
 
-`-b --begin=DATE'
-     include postings/txns on or after this date
+'-b --begin=DATE'
 
-`-e --end=DATE'
-     include postings/txns before this date
+     include postings/txns on or after this date (will be adjusted to
+     preceding subperiod start when using a report interval)
+'-e --end=DATE'
 
-`-D --daily'
+     include postings/txns before this date (will be adjusted to
+     following subperiod end when using a report interval)
+'-D --daily'
+
      multiperiod/multicolumn report by day
+'-W --weekly'
 
-`-W --weekly'
      multiperiod/multicolumn report by week
+'-M --monthly'
 
-`-M --monthly'
      multiperiod/multicolumn report by month
+'-Q --quarterly'
 
-`-Q --quarterly'
      multiperiod/multicolumn report by quarter
+'-Y --yearly'
 
-`-Y --yearly'
      multiperiod/multicolumn report by year
+'-p --period=PERIODEXP'
 
-`-p --period=PERIODEXP'
      set start date, end date, and/or reporting interval all at once
      using period expressions syntax
+'--date2'
 
-`--date2'
      match the secondary date instead (see command help for other
      effects)
+'-U --unmarked'
 
-`-U --unmarked'
      include only unmarked postings/txns (can combine with -P or -C)
+'-P --pending'
 
-`-P --pending'
      include only pending postings/txns
+'-C --cleared'
 
-`-C --cleared'
      include only cleared postings/txns
+'-R --real'
 
-`-R --real'
      include only non-virtual postings
+'-NUM --depth=NUM'
 
-`-NUM --depth=NUM'
      hide/aggregate accounts or postings more than NUM levels deep
+'-E --empty'
 
-`-E --empty'
      show items with zero amount, normally hidden (and vice-versa in
      hledger-ui/hledger-web)
+'-B --cost'
 
-`-B --cost'
      convert amounts to their cost/selling amount at transaction time
+'-V --market'
 
-`-V --market'
      convert amounts to their market value in default valuation
      commodities
+'-X --exchange=COMM'
 
-`-X --exchange=COMM'
      convert amounts to their market value in commodity COMM
+'--value'
 
-`--value'
      convert amounts to cost or market value, more flexibly than
      -B/-V/-X
+'--infer-market-prices'
 
-`--infer-market-prices'
      use transaction prices (recorded with @ or @@) as additional market
      prices, as if they were P directives
+'--auto'
 
-`--auto'
      apply automated posting rules to modify transactions.
+'--forecast'
 
-`--forecast'
      generate future transactions from periodic transaction rules, for
-     the next 6 months or till report end date. In hledger-ui, also
+     the next 6 months or till report end date.  In hledger-ui, also
      make ordinary future transactions visible.
+'--color=WHEN (or --colour=WHEN)'
 
-`--color=WHEN (or --colour=WHEN)'
      Should color-supporting commands use ANSI color codes in text
      output.  'auto' (default): whenever stdout seems to be a
      color-supporting terminal.  'always' or 'yes': always, useful eg
-     when piping output into 'less -R'.  'never' or 'no': never.  A
+     when piping output into 'less -R'. 'never' or 'no': never.  A
      NO_COLOR environment variable overrides this.
 
    When a reporting option appears more than once in the command line,
@@ -194,24 +203,25 @@
 
    hledger help options:
 
-`-h --help'
+'-h --help'
+
      show general or COMMAND help
+'--man'
 
-`--man'
      show general or COMMAND user manual with man
+'--info'
 
-`--info'
      show general or COMMAND user manual with info
+'--version'
 
-`--version'
      show general or ADDONCMD version
+'--debug[=N]'
 
-`--debug[=N]'
      show debug output (levels 1-9, default: 1)
 
    A @FILE argument will be expanded to the contents of FILE, which
-should contain one command line option/argument per line. (To prevent
-this, insert a `--' argument before.)
+should contain one command line option/argument per line.  (To prevent
+this, insert a '--' argument before.)
 
 
 File: hledger-ui.info,  Node: KEYS,  Next: SCREENS,  Prev: OPTIONS,  Up: Top
@@ -219,94 +229,94 @@
 2 KEYS
 ******
 
-`?' shows a help dialog listing all keys. (Some of these also appear in
-the quick help at the bottom of each screen.) Press `?' again (or
-`ESCAPE', or `LEFT', or `q') to close it. The following keys work on
+'?' shows a help dialog listing all keys.  (Some of these also appear in
+the quick help at the bottom of each screen.)  Press '?' again (or
+'ESCAPE', or 'LEFT', or 'q') to close it.  The following keys work on
 most screens:
 
-   The cursor keys navigate: `right' (or `enter') goes deeper, `left'
-returns to the previous screen, `up'/`down'/`page up'/`page
-down'/`home'/`end' move up and down through lists. Emacs-style
-(`ctrl-p'/`ctrl-n'/`ctrl-f'/`ctrl-b') movement keys are also supported
+   The cursor keys navigate: 'right' (or 'enter') goes deeper, 'left'
+returns to the previous screen, 'up'/'down'/'page up'/'page
+down'/'home'/'end' move up and down through lists.  Emacs-style
+('ctrl-p'/'ctrl-n'/'ctrl-f'/'ctrl-b') movement keys are also supported
 (but not vi-style keys, since hledger-1.19, sorry!).  A tip: movement
 speed is limited by your keyboard repeat rate, to move faster you may
-want to adjust it. (If you're on a mac, the karabiner app is one way to
+want to adjust it.  (If you're on a mac, the karabiner app is one way to
 do that.)
 
    With shift pressed, the cursor keys adjust the report period,
 limiting the transactions to be shown (by default, all are shown).
-`shift-down/up' steps downward and upward through these standard report
-period durations: year, quarter, month, week, day. Then,
-`shift-left/right' moves to the previous/next period. `T' sets the
-report period to today. With the `--watch' option, when viewing a
+'shift-down/up' steps downward and upward through these standard report
+period durations: year, quarter, month, week, day.  Then,
+'shift-left/right' moves to the previous/next period.  'T' sets the
+report period to today.  With the '--watch' option, when viewing a
 "current" period (the current day, week, month, quarter, or year), the
-period will move automatically to track the current date. To set a
-non-standard period, you can use `/' and a `date:' query.
+period will move automatically to track the current date.  To set a
+non-standard period, you can use '/' and a 'date:' query.
 
-   `/' lets you set a general filter query limiting the data shown,
-using the same query terms as in hledger and hledger-web. While editing
-the query, you can use CTRL-a/e/d/k, BS, cursor keys; press `ENTER' to
-set it, or `ESCAPE'to cancel. There are also keys for quickly adjusting
+   '/' lets you set a general filter query limiting the data shown,
+using the same query terms as in hledger and hledger-web.  While editing
+the query, you can use CTRL-a/e/d/k, BS, cursor keys; press 'ENTER' to
+set it, or 'ESCAPE'to cancel.  There are also keys for quickly adjusting
 some common filters like account depth and transaction status (see
-below). `BACKSPACE' or `DELETE' removes all filters, showing all
+below).  'BACKSPACE' or 'DELETE' removes all filters, showing all
 transactions.
 
    As mentioned above, by default hledger-ui hides future transactions -
 both ordinary transactions recorded in the journal, and periodic
-transactions generated by rule. `F' toggles forecast mode, in which
+transactions generated by rule.  'F' toggles forecast mode, in which
 future/forecasted transactions are shown.
 
-   `ESCAPE' resets the UI state and jumps back to the top screen,
-restoring the app's initial state at startup. Or, it cancels minibuffer
+   'ESCAPE' resets the UI state and jumps back to the top screen,
+restoring the app's initial state at startup.  Or, it cancels minibuffer
 data entry or the help dialog.
 
-   `CTRL-l' redraws the screen and centers the selection if possible
+   'CTRL-l' redraws the screen and centers the selection if possible
 (selections near the top won't be centered, since we don't scroll above
 the top).
 
-   `g' reloads from the data file(s) and updates the current screen and
-any previous screens. (With large files, this could cause a noticeable
+   'g' reloads from the data file(s) and updates the current screen and
+any previous screens.  (With large files, this could cause a noticeable
 pause.)
 
-   `I' toggles balance assertion checking. Disabling balance assertions
+   '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.
+   'a' runs command-line hledger's add command, and reloads the updated
+file.  This allows some basic data entry.
 
-   `A' is like `a', but runs the hledger-iadd tool, which provides a
-terminal interface. This key will be available if `hledger-iadd' is
+   'A' is like 'a', but runs the hledger-iadd tool, which provides a
+terminal interface.  This key will be available if 'hledger-iadd' is
 installed in $path.
 
-   `E' runs $HLEDGER_UI_EDITOR, or $EDITOR, or a default (`emacsclient
--a "" -nw') on the journal file. With some editors (emacs, vi), the
+   'E' runs $HLEDGER_UI_EDITOR, or $EDITOR, or a default ('emacsclient
+-a "" -nw') on the journal file.  With some editors (emacs, vi), the
 cursor will be positioned at the current transaction when invoked from
 the register and transaction screens, and at the error location (if
 possible) when invoked from the error screen.
 
-   `B' toggles cost mode, showing amounts in their transaction price's
-commodity (like toggling the `-B/--cost' flag).
+   'B' toggles cost mode, showing amounts in their transaction price's
+commodity (like toggling the '-B/--cost' flag).
 
-   `V' toggles value mode, showing amounts' current market value in
-their default valuation commodity (like toggling the `-V/--market'
-flag). Note, "current market value" means the value on the report end
-date if specified, otherwise today. To see the value on another date,
-you can temporarily set that as the report end date. Eg: to see a
+   'V' toggles value mode, showing amounts' current market value in
+their default valuation commodity (like toggling the '-V/--market'
+flag).  Note, "current market value" means the value on the report end
+date if specified, otherwise today.  To see the value on another date,
+you can temporarily set that as the report end date.  Eg: to see a
 transaction as it was valued on july 30, go to the accounts or register
-screen, press `/', and add `date:-7/30' to the query.
+screen, press '/', and add 'date:-7/30' to the query.
 
    At most one of cost or value mode can be active at once.
 
    There's not yet any visual reminder when cost or value mode is
-active; for now pressing `b' `b' `v' should reliably reset to normal
+active; for now pressing 'b' 'b' 'v' should reliably reset to normal
 mode.
 
-   With `--watch' active, if you save an edit to the journal file while
-viewing the transaction screen in cost or value mode, the `B'/`V' keys
-will stop working. To work around, press `g' to force a manual reload,
+   With '--watch' active, if you save an edit to the journal file while
+viewing the transaction screen in cost or value mode, the 'B'/'V' keys
+will stop working.  To work around, press 'g' to force a manual reload,
 or exit the transaction screen.
 
-   `q' quits the application.
+   'q' quits the application.
 
    Additional screen-specific keys are described below.
 
@@ -329,47 +339,48 @@
 3.1 Accounts screen
 ===================
 
-This is normally the first screen displayed. It lists accounts and their
-balances, like hledger's balance command. By default, it shows all
-accounts and their latest ending balances (including the balances of
-subaccounts). If you specify a query on the command line, it shows just
+This is normally the first screen displayed.  It lists accounts and
+their balances, like hledger's balance command.  By default, it shows
+all accounts and their latest ending balances (including the balances of
+subaccounts).  If you specify a query on the command line, it shows just
 the matched accounts and the balances from matched transactions.
 
-   Account names are shown as a flat list by default; press `t' to
-toggle tree mode. In list mode, account balances are exclusive of
+   Account names are shown as a flat list by default; press 't' to
+toggle tree mode.  In list mode, account balances are exclusive of
 subaccounts, except where subaccounts are hidden by a depth limit (see
-below). In tree mode, all account balances are inclusive of subaccounts.
+below).  In tree mode, all account balances are inclusive of
+subaccounts.
 
-   To see less detail, press a number key, `1' to `9', to set a depth
-limit. Or use `-' to decrease and `+'/`=' to increase the depth limit.
-`0' shows even less detail, collapsing all accounts to a single total.
-To remove the depth limit, set it higher than the maximum account
-depth, or press `ESCAPE'.
+   To see less detail, press a number key, '1' to '9', to set a depth
+limit.  Or use '-' to decrease and '+'/'=' to increase the depth limit.
+'0' shows even less detail, collapsing all accounts to a single total.
+To remove the depth limit, set it higher than the maximum account depth,
+or press 'ESCAPE'.
 
-   `H' toggles between showing historical balances or period balances.
+   'H' toggles between showing historical balances or period balances.
 Historical balances (the default) are ending balances at the end of the
 report period, taking into account all transactions before that date
 (filtered by the filter query if any), including transactions before the
-start of the report period. In other words, historical balances are what
-you would see on a bank statement for that account (unless disturbed by
-a filter query). Period balances ignore transactions before the report
-start date, so they show the change in balance during the report period.
-They are more useful eg when viewing a time log.
+start of the report period.  In other words, historical balances are
+what you would see on a bank statement for that account (unless
+disturbed by a filter query).  Period balances ignore transactions
+before the report start date, so they show the change in balance during
+the report period.  They are more useful eg when viewing a time log.
 
-   `U' toggles filtering by unmarked status, including or excluding
-unmarked postings in the balances. Similarly, `P' toggles pending
-postings, and `C' toggles cleared postings. (By default, balances
+   'U' toggles filtering by unmarked status, including or excluding
+unmarked postings in the balances.  Similarly, 'P' toggles pending
+postings, and 'C' toggles cleared postings.  (By default, balances
 include all postings; if you activate one or two status filters, only
 those postings are included; and if you activate all three, the filter
 is removed.)
 
-   `R' toggles real mode, in which virtual postings are ignored.
+   'R' toggles real mode, in which virtual postings are ignored.
 
-   `Z' toggles nonzero mode, in which only accounts with nonzero
+   'Z' toggles nonzero mode, in which only accounts with nonzero
 balances are shown (hledger-ui shows zero items by default, unlike
 command-line hledger).
 
-   Press `right' or `enter' to view an account's transactions register.
+   Press 'right' or 'enter' to view an account's transactions register.
 
 
 File: hledger-ui.info,  Node: Register screen,  Next: Transaction screen,  Prev: Accounts screen,  Up: SCREENS
@@ -378,46 +389,44 @@
 ===================
 
 This screen shows the transactions affecting a particular account, like
-a check register. Each line represents one transaction and shows:
+a check register.  Each line represents one transaction and shows:
 
-   * the other account(s) involved, in abbreviated form. (If there are
-     both real and virtual postings, it shows only the accounts
-     affected by real postings.)
+   * the other account(s) involved, in abbreviated form.  (If there are
+     both real and virtual postings, it shows only the accounts affected
+     by real postings.)
 
    * the overall change to the current account's balance; positive for
      an inflow to this account, negative for an outflow.
 
    * the running historical total or period total for the current
-     account, after the transaction. This can be toggled with `H'.
-     Similar to the accounts screen, the historical total is affected
-     by transactions (filtered by the filter query) before the report
-     start date, while the period total is not. If the historical total
-     is not disturbed by a filter query, it will be the running
-     historical balance you would see on a bank register for the
-     current account.
-
+     account, after the transaction.  This can be toggled with 'H'.
+     Similar to the accounts screen, the historical total is affected by
+     transactions (filtered by the filter query) before the report start
+     date, while the period total is not.  If the historical total is
+     not disturbed by a filter query, it will be the running historical
+     balance you would see on a bank register for the current account.
 
    Transactions affecting this account's subaccounts will be included in
 the register if the accounts screen is in tree mode, or if it's in list
 mode but this account has subaccounts which are not shown due to a depth
-limit. In other words, the register always shows the transactions
-contributing to the balance shown on the accounts screen. Tree mode/list
-mode can be toggled with `t' here also.
+limit.  In other words, the register always shows the transactions
+contributing to the balance shown on the accounts screen.  Tree
+mode/list mode can be toggled with 't' here also.
 
-   `U' toggles filtering by unmarked status, showing or hiding unmarked
-transactions. Similarly, `P' toggles pending transactions, and `C'
-toggles cleared transactions. (By default, transactions with all
+   'U' toggles filtering by unmarked status, showing or hiding unmarked
+transactions.  Similarly, 'P' toggles pending transactions, and 'C'
+toggles cleared transactions.  (By default, transactions with all
 statuses are shown; if you activate one or two status filters, only
 those transactions are shown; and if you activate all three, the filter
 is removed.)
 
-   `R' toggles real mode, in which virtual postings are ignored.
+   'R' toggles real mode, in which virtual postings are ignored.
 
-   `Z' toggles nonzero mode, in which only transactions posting a
+   'Z' toggles nonzero mode, in which only transactions posting a
 nonzero change are shown (hledger-ui shows zero items by default, unlike
 command-line hledger).
 
-   Press `right' (or `enter') to view the selected transaction in
+   Press 'right' (or 'enter') to view the selected transaction in
 detail.
 
 
@@ -435,11 +444,11 @@
 Simple transactions have two postings, but there can be more (or in
 certain cases, fewer).
 
-   `up' and `down' will step through all transactions listed in the
-previous account register screen. In the title bar, the numbers in
-parentheses show your position within that account register. They will
+   'up' and 'down' will step through all transactions listed in the
+previous account register screen.  In the title bar, the numbers in
+parentheses show your position within that account register.  They will
 vary depending on which account register you came from (remember most
-transactions appear in multiple account registers). The #N number
+transactions appear in multiple account registers).  The #N number
 preceding them is the transaction's position within the complete
 unfiltered journal, which is a more stable id (at least until the next
 reload).
@@ -451,8 +460,8 @@
 ================
 
 This screen will appear if there is a problem, such as a parse error,
-when you press g to reload. Once you have fixed the problem, press g
-again to reload and resume normal operation. (Or, you can press escape
+when you press g to reload.  Once you have fixed the problem, press g
+again to reload and resume normal operation.  (Or, you can press escape
 to cancel the reload attempt.)
 
 
@@ -461,28 +470,27 @@
 4 ENVIRONMENT
 *************
 
-*COLUMNS* The screen width to use. Default: the full terminal width.
+*COLUMNS* The screen width to use.  Default: the full terminal width.
 
-   *LEDGER_FILE* The journal file path when not specified with `-f'.
-Default: `~/.hledger.journal' (on windows, perhaps
-`C:/Users/USER/.hledger.journal').
+   *LEDGER_FILE* The journal file path when not specified with '-f'.
+Default: '~/.hledger.journal' (on windows, perhaps
+'C:/Users/USER/.hledger.journal').
 
-   A typical value is `~/DIR/YYYY.journal', where DIR is a
-version-controlled finance directory and YYYY is the current year. Or
-`~/DIR/current.journal', where current.journal is a symbolic link to
+   A typical value is '~/DIR/YYYY.journal', where DIR is a
+version-controlled finance directory and YYYY is the current year.  Or
+'~/DIR/current.journal', where current.journal is a symbolic link to
 YYYY.journal.
 
-   On Mac computers, you can set this and other environment variables
-in a more thorough way that also affects applications started from the
-GUI (say, an Emacs dock icon). Eg on MacOS Catalina I have a
-`~/.MacOSX/environment.plist' file containing
-
+   On Mac computers, you can set this and other environment variables in
+a more thorough way that also affects applications started from the GUI
+(say, an Emacs dock icon).  Eg on MacOS Catalina I have a
+'~/.MacOSX/environment.plist' file containing
 
 {
   "LEDGER_FILE" : "~/finance/current.journal"
 }
 
-   To see the effect you may need to `killall Dock', or reboot.
+   To see the effect you may need to 'killall Dock', or reboot.
 
 
 File: hledger-ui.info,  Node: FILES,  Next: BUGS,  Prev: ENVIRONMENT,  Up: Top
@@ -491,9 +499,9 @@
 *******
 
 Reads data from one or more files in hledger journal, timeclock,
-timedot, or CSV format specified with `-f', or `$LEDGER_FILE', or
-`$HOME/.hledger.journal' (on windows, perhaps
-`C:/Users/USER/.hledger.journal').
+timedot, or CSV format specified with '-f', or '$LEDGER_FILE', or
+'$HOME/.hledger.journal' (on windows, perhaps
+'C:/Users/USER/.hledger.journal').
 
 
 File: hledger-ui.info,  Node: BUGS,  Prev: FILES,  Up: Top
@@ -501,18 +509,18 @@
 6 BUGS
 ******
 
-The need to precede options with `--' when invoked from hledger is
+The need to precede options with '--' when invoked from hledger is
 awkward.
 
-   `-f-' doesn't work (hledger-ui can't read from stdin).
+   '-f-' doesn't work (hledger-ui can't read from stdin).
 
-   `-V' affects only the accounts screen.
+   '-V' affects only the accounts screen.
 
-   When you press `g', the current and all previous screens are
-regenerated, which may cause a noticeable pause with large files. Also
+   When you press 'g', the current and all previous screens are
+regenerated, which may cause a noticeable pause with large files.  Also
 there is no visual indication that this is in progress.
 
-   `--watch' is not yet fully robust. It works well for normal usage,
+   '--watch' is not yet fully robust.  It works well for normal usage,
 but many file changes in a short time (eg saving the file thousands of
 times with an editor macro) can cause problems at least on OSX. Symptoms
 include: unresponsive UI, periodic resetting of the cursor position,
@@ -521,31 +529,30 @@
 program is restarted.
 
    Also, if you are viewing files mounted from another machine,
-`--watch' requires that both machine clocks are roughly in step.
-
+'--watch' requires that both machine clocks are roughly in step.
 
 
 Tag Table:
-Node: Top82
-Node: OPTIONS1475
-Ref: #options1572
-Node: KEYS5805
-Ref: #keys5900
-Node: SCREENS10196
-Ref: #screens10301
-Node: Accounts screen10391
-Ref: #accounts-screen10519
-Node: Register screen12723
-Ref: #register-screen12878
-Node: Transaction screen14873
-Ref: #transaction-screen15031
-Node: Error screen15898
-Ref: #error-screen16020
-Node: ENVIRONMENT16262
-Ref: #environment16376
-Node: FILES17181
-Ref: #files17280
-Node: BUGS17493
-Ref: #bugs17570
+Node: Top232
+Node: OPTIONS1646
+Ref: #options1743
+Node: KEYS6144
+Ref: #keys6239
+Node: SCREENS10558
+Ref: #screens10663
+Node: Accounts screen10753
+Ref: #accounts-screen10881
+Node: Register screen13096
+Ref: #register-screen13251
+Node: Transaction screen15248
+Ref: #transaction-screen15406
+Node: Error screen16276
+Ref: #error-screen16398
+Node: ENVIRONMENT16642
+Ref: #environment16756
+Node: FILES17563
+Ref: #files17662
+Node: BUGS17875
+Ref: #bugs17952
 
 End Tag Table
diff --git a/hledger-ui.txt b/hledger-ui.txt
--- a/hledger-ui.txt
+++ b/hledger-ui.txt
@@ -5,7 +5,7 @@
 
 NAME
        hledger-ui  is  a  terminal  interface (TUI) for the hledger accounting
-       tool.  This manual is for hledger-ui 1.21.
+       tool.  This manual is for hledger-ui 1.22.
 
 SYNOPSIS
        hledger-ui [OPTIONS] [QUERYARGS]
@@ -92,10 +92,12 @@
        hledger reporting options:
 
        -b --begin=DATE
-              include postings/txns on or after this date
+              include postings/txns on or after this date (will be adjusted to
+              preceding subperiod start when using a report interval)
 
        -e --end=DATE
-              include postings/txns before this date
+              include postings/txns before this date (will be adjusted to fol-
+              lowing subperiod end when using a report interval)
 
        -D --daily
               multiperiod/multicolumn report by day
@@ -463,4 +465,4 @@
 
 
 
-hledger-ui-1.21                  December 2020                   HLEDGER-UI(1)
+hledger-ui-1.22                    July 2021                     HLEDGER-UI(1)
