diff --git a/CHANGES.md b/CHANGES.md
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -1,6 +1,23 @@
 User-visible changes in hledger-ui.
 See also the hledger changelog.
 
+# 1.20 2020-12-05
+
+- When entering a query with `/`, malformed queries/regular expressions
+  no longer cause the program to exit. (Stephen Morgan)
+
+- Eliding of multicommodity amounts now makes better use of available space. (Stephen Morgan)
+
+- `E` now parses the `HLEDGER_UI_EDITOR` or `EDITOR` environment variable
+  correctly on Windows (ignoring the file extension), so if you have that set
+  it should be better at opening your editor at the correct line.
+
+- `E` now supports positioning when `HLEDGER_UI_EDITOR` or `EDITOR` 
+  is VS Code ("`code`") (#1359)
+
+- hledger-ui now has a (human-powered) test suite.
+
+
 # 1.19.1 2020-09-07
 
 - Allow megaparsec 9
diff --git a/Hledger/UI/AccountsScreen.hs b/Hledger/UI/AccountsScreen.hs
--- a/Hledger/UI/AccountsScreen.hs
+++ b/Hledger/UI/AccountsScreen.hs
@@ -53,7 +53,7 @@
 
 asInit :: Day -> Bool -> UIState -> UIState
 asInit d reset ui@UIState{
-  aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}},
+  aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}},
   ajournal=j,
   aScreen=s@AccountsScreen{}
   } =
@@ -80,11 +80,10 @@
                       where
                         as = map asItemAccountName displayitems
 
-    uopts' = uopts{cliopts_=copts{reportopts_=ropts'}}
-    ropts' = ropts{accountlistmode_=if tree_ ropts then ALTree else ALFlat}
-
-    q = And [queryFromOpts d ropts, excludeforecastq (forecast_ ropts)]
+    uopts' = uopts{cliopts_=copts{reportspec_=rspec'}}
+    rspec' = rspec{rsQuery=simplifyQuery $ And [rsQuery rspec, periodq, excludeforecastq (forecast_ ropts)]}
       where
+        periodq = Date $ periodAsDateSpan $ period_ ropts
         -- Except in forecast mode, exclude future/forecast transactions.
         excludeforecastq (Just _) = Any
         excludeforecastq Nothing  =  -- not:date:tomorrow- not:tag:generated-transaction
@@ -94,14 +93,14 @@
           ]
 
     -- run the report
-    (items,_total) = balanceReport ropts' q j
+    (items,_total) = balanceReport rspec' j
 
     -- pre-render the list items
     displayitem (fullacct, shortacct, indent, bal) =
       AccountsScreenItem{asItemIndentLevel        = indent
                         ,asItemAccountName        = fullacct
-                        ,asItemDisplayAccountName = replaceHiddenAccountsNameWith "All" $ if tree_ ropts' then shortacct else fullacct
-                        ,asItemRenderedAmounts    = map (showAmountWithoutPrice False) amts
+                        ,asItemDisplayAccountName = replaceHiddenAccountsNameWith "All" $ if tree_ ropts then shortacct else fullacct
+                        ,asItemRenderedAmounts    = map showAmountWithoutPrice amts
                         }
       where
         Mixed amts = normaliseMixedAmountSquashPricesForDisplay $ stripPrices bal
@@ -119,7 +118,7 @@
 asInit _ _ _ = error "init function called with wrong screen type, should not happen"  -- PARTIAL:
 
 asDraw :: UIState -> [Widget Name]
-asDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
+asDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}
               ,ajournal=j
               ,aScreen=s@AccountsScreen{}
               ,aMode=mode
@@ -167,6 +166,7 @@
       render $ defaultLayout toplabel bottomlabel $ renderList (asDrawItem colwidths) True (_asList s)
 
       where
+        ropts = rsOpts rspec
         ishistorical = balancetype_ ropts == HistoricalBalance
 
         toplabel =
@@ -174,7 +174,7 @@
           <+> toggles
           <+> str (" account " ++ if ishistorical then "balances" else "changes")
           <+> borderPeriodStr (if ishistorical then "at end of" else "in") (period_ ropts)
-          <+> borderQueryStr querystr
+          <+> borderQueryStr (unwords . map (quoteIfNeeded . T.unpack) $ querystring_ ropts)
           <+> borderDepthStr mdepth
           <+> str (" ("++curidx++"/"++totidx++")")
           <+> (if ignore_assertions_ $ inputopts_ copts
@@ -192,7 +192,6 @@
               ,uiShowStatus copts $ statuses_ ropts
               ,if real_ ropts then ["real"] else []
               ]
-            querystr = query_ ropts
             mdepth = depth_ ropts
             curidx = case _asList s ^. listSelectedL of
                        Nothing -> "-"
diff --git a/Hledger/UI/Editor.hs b/Hledger/UI/Editor.hs
--- a/Hledger/UI/Editor.hs
+++ b/Hledger/UI/Editor.hs
@@ -1,7 +1,5 @@
 {- | Editor integration. -}
 
--- {-# LANGUAGE OverloadedStrings #-}
-
 module Hledger.UI.Editor (
    -- TextPosition
    endPosition
@@ -11,6 +9,8 @@
 where
 
 import Control.Applicative ((<|>))
+import Data.List (intercalate)
+import Data.Maybe (catMaybes)
 import Safe
 import System.Environment
 import System.Exit
@@ -43,58 +43,63 @@
 -- | 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.
+-- We know how to focus on position for: emacs, vi, nano, VS code.
 -- We know how to focus on last line for: vi.
 --
--- Some tests: With line and column numbers specified,
+-- Some tests:
 -- @
--- if EDITOR is:  the command should be:
--- -------------  -----------------------------------
--- notepad        notepad FILE
--- vi             vi +LINE FILE
---                vi + FILE                                    # negative LINE
--- emacs          emacs +LINE:COL FILE
---                emacs FILE                                   # negative LINE
--- (unset)        emacsclient -a '' -nw +LINE:COL FILE
---                emacsclient -a '' -nw FILE                   # negative LINE
+-- EDITOR program is:  LINE/COL specified ?  Command should be:               
+-- ------------------  --------------------  ----------------------------------- 
+-- emacs, emacsclient  LINE COL              emacs +LINE:COL FILE
+--                     LINE                  emacs +LINE     FILE
+--                                           emacs           FILE
+--
+-- nano                LINE COL              nano +LINE,COL FILE
+--                     LINE                  nano +LINE     FILE
+--                                           nano           FILE
+--
+-- code                LINE COL              code --goto FILE:LINE:COL
+--                     LINE                  code --goto FILE:LINE
+--                                           code        FILE
+--
+-- vi, & variants      LINE [COL]            vi +LINE FILE
+--                     LINE (negative)       vi +     FILE
+--                                           vi       FILE
+--
+-- (other PROG)        [LINE [COL]]          PROG FILE
+--
+-- (not set)           LINE COL              emacsclient -a '' -nw +LINE:COL FILE
+--                     LINE                  emacsclient -a '' -nw +LINE     FILE
+--                                           emacsclient -a '' -nw           FILE
 -- @
 --
--- How to open editors at the last line of a file:
+-- Notes on opening editors at the last line of a file:
 -- @
--- emacs:       emacs FILE -f end-of-buffer
+-- emacs:       emacs FILE -f end-of-buffer  # (-f must appear after FILE, +LINE:COL must appear before)
 -- emacsclient: can't
 -- vi:          vi + FILE
 -- @
 --
 editFileAtPositionCommand :: Maybe TextPosition -> FilePath -> IO String
 editFileAtPositionCommand mpos f = do
-  let f' = singleQuoteIfNeeded f
-  editcmd <- getEditCommand
-  let editor = lowercase $ takeFileName $ headDef "" $ words' editcmd
-  let positionarg =
-        case mpos of
-          Just (l, mc)
-            | editor `elem` [
-                "ex",
-                "vi","vim","view","nvim","evim","eview",
-                "gvim","gview","rvim","rview","rgvim","rgview"
-                ] -> plusAndMaybeLine l mc
-          Just (l, mc)
-            | editor `elem` ["emacs", "emacsclient"] -> plusLineAndMaybeColonColumnOrEnd l mc
-          Just (l, mc)
-            | editor `elem` ["nano"] -> plusLineAndMaybeCommaColumn l mc
-          _ -> ""
-        where
-          plusAndMaybeLine            l _  = "+" ++ if l >= 0 then show l else ""
-          plusLineAndMaybeCommaColumn l mc = "+" ++ show l ++ maybe "" ((","++).show) mc
-          plusLineAndMaybeColonColumnOrEnd l mc
-            | l >= 0    = "+" ++ show l ++ maybe "" ((":"++).show) mc
-            | otherwise = ""
-            -- otherwise = "-f end-of-buffer"
-            -- XXX Problems with this:
-            -- it must appear after the filename, whereas +LINE:COL must appear before
-            -- it works only with emacs, not emacsclient
-  return $ unwords [editcmd, positionarg, f']
+  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
+
+  return $ unwords $ cmd:args
 
 -- | Get the user's preferred edit command. This is the value of the
 -- $HLEDGER_UI_EDITOR environment variable, or of $EDITOR, or a
diff --git a/Hledger/UI/Main.hs b/Hledger/UI/Main.hs
--- a/Hledger/UI/Main.hs
+++ b/Hledger/UI/Main.hs
@@ -17,7 +17,6 @@
 import Control.Monad
 -- import Control.Monad.IO.Class (liftIO)
 -- import Data.Monoid              --
-import Data.List
 import Data.List.Extra (nubSort)
 import Data.Maybe
 -- import Data.Text (Text)
@@ -52,12 +51,12 @@
 
 main :: IO ()
 main = do
-  opts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportopts_=ropts,rawopts_=rawopts}} <- getHledgerUIOpts
+  opts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportspec_=rspec@ReportSpec{rsOpts=ropts},rawopts_=rawopts}} <- getHledgerUIOpts
   -- when (debug_ $ cliopts_ opts) $ printf "%s\n" prognameandversion >> printf "opts: %s\n" (show opts)
 
   -- always include forecasted periodic transactions when loading data;
   -- they will be toggled on and off in the UI.
-  let copts' = copts{reportopts_=ropts{forecast_=Just $ fromMaybe nulldatespan (forecast_ ropts)}}
+  let copts' = copts{reportspec_=rspec{rsOpts=ropts{forecast_=Just $ fromMaybe nulldatespan (forecast_ ropts)}}}
 
   case True of
     _ | "help"            `inRawOpts` rawopts -> putStr (showModeUsage uimode)
@@ -66,47 +65,68 @@
     _                                         -> withJournalDo copts' (runBrickUi opts)
 
 runBrickUi :: UIOpts -> Journal -> IO ()
-runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportopts_=ropts}} j = do
+runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportspec_=rspec@ReportSpec{rsOpts=ropts}}} j = do
   d <- getCurrentDay
 
   let
 
-    -- depth: is a bit different from other queries. In hledger cli,
-    -- - reportopts{depth_} indicates --depth options
-    -- - reportopts{query_} is the query arguments as a string
-    -- - the report query is based on both of these.
-    -- For hledger-ui, for now, move depth: arguments out of reportopts{query_}
-    -- and into reportopts{depth_}, so that depth and other kinds of filter query
-    -- can be displayed independently.
+    -- hledger-ui's query handling is currently in flux, mixing old and new approaches.
+    -- Related: #1340, #1383, #1387. Some notes and terminology:
+
+    -- The *startup query* is the Query generated at program startup, from
+    -- command line options, arguments, and the current date. hledger CLI
+    -- uses this.
+
+    -- hledger-ui/hledger-web allow the query to be changed at will, creating
+    -- a new *runtime query* each time.
+
+    -- The startup query or part of it can be used as a *constraint query*,
+    -- limiting all runtime queries. hledger-web does this with the startup
+    -- report period, never showing transactions outside those dates.
+    -- hledger-ui does not do this.
+
+    -- A query is a combination of multiple subqueries/terms, which are
+    -- generated from command line options and arguments, ui/web app runtime
+    -- state, and/or the current date.
+
+    -- Some subqueries are generated by parsing freeform user input, which
+    -- can fail. We don't want hledger users to see such failures except:
+
+    -- 1. at program startup, in which case the program exits
+    -- 2. after entering a new freeform query in hledger-ui/web, in which case
+    --    the change is rejected and the program keeps running
+
+    -- So we should parse those kinds of subquery only at those times. Any
+    -- subqueries which do not require parsing can be kept separate. And
+    -- these can be combined to make the full query when needed, eg when
+    -- hledger-ui screens are generating their data. (TODO)
+
+    -- Some parts of the query are also kept separate for UI reasons.
+    -- hledger-ui provides special UI for controlling depth (number keys), 
+    -- the report period (shift arrow keys), realness/status filters (RUPC keys) etc.
+    -- There is also a freeform text area for extra query terms (/ key).
+    -- It's cleaner and less conflicting to keep the former out of the latter.
+
     uopts' = uopts{
       cliopts_=copts{
-         reportopts_= ropts{
-            -- incorporate any depth: query args into depth_,
-            -- any date: query args into period_
-            depth_ =queryDepth q,
-            period_=periodfromoptsandargs,
-            query_ =unwords -- as in ReportOptions, with same limitations
-                    $ collectopts filteredQueryArg (rawopts_ copts),
-            -- always disable boring account name eliding, unlike the CLI, for a more regular tree
-            no_elide_=True,
-            -- flip the default for items with zero amounts, show them by default
-            empty_=not $ empty_ ropts,
-            -- show historical balances by default, unlike the CLI
-            balancetype_=HistoricalBalance
+         reportspec_=rspec{
+            rsQuery=filteredQuery $ rsQuery rspec,  -- query with depth/date parts removed
+            rsOpts=ropts{
+               depth_ =queryDepth $ rsQuery rspec,  -- query's depth part
+               period_=periodfromoptsandargs,       -- query's date part
+               no_elide_=True,  -- avoid squashing boring account names, for a more regular tree (unlike hledger)
+               empty_=not $ empty_ ropts,  -- show zero items by default, hide them with -E (unlike hledger)
+               balancetype_=HistoricalBalance  -- show historical balances by default (unlike hledger)
+               }
             }
          }
       }
       where
-        q = queryFromOpts d ropts
-        datespanfromargs = queryDateSpan (date2_ ropts) $ fst $
-                           either error' id $ parseQuery d (T.pack $ query_ ropts)  -- PARTIAL:
+        datespanfromargs = queryDateSpan (date2_ ropts) $ rsQuery rspec
         periodfromoptsandargs =
           dateSpanAsPeriod $ spansIntersect [periodAsDateSpan $ period_ ropts, datespanfromargs]
-        filteredQueryArg = \case
-            ("args", v)
-                | not $ any (`isPrefixOf` v) ["depth:", "date:"] -- skip depth/date passed as query
-                    -> Just (quoteIfNeeded v)
-            _ -> Nothing
+        filteredQuery q = simplifyQuery $ And [queryFromFlags ropts, filtered q]
+          where filtered = filterQuery (\x -> not $ queryIsDepth x || queryIsDate x)
 
     -- XXX move this stuff into Options, UIOpts
     theme = maybe defaultTheme (fromMaybe defaultTheme . getTheme) $
diff --git a/Hledger/UI/RegisterScreen.hs b/Hledger/UI/RegisterScreen.hs
--- a/Hledger/UI/RegisterScreen.hs
+++ b/Hledger/UI/RegisterScreen.hs
@@ -59,18 +59,17 @@
 rsSetAccount _ _ scr = scr
 
 rsInit :: Day -> Bool -> UIState -> UIState
-rsInit d reset ui@UIState{aopts=_uopts@UIOpts{cliopts_=CliOpts{reportopts_=ropts}}, ajournal=j, aScreen=s@RegisterScreen{..}} =
+rsInit d reset ui@UIState{aopts=_uopts@UIOpts{cliopts_=CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}, ajournal=j, aScreen=s@RegisterScreen{..}} =
   ui{aScreen=s{rsList=newitems'}}
   where
     -- gather arguments and queries
     -- XXX temp
     inclusive = tree_ ropts || rsForceInclusive
     thisacctq = Acct $ (if inclusive then accountNameToAccountRegex else accountNameToAccountOnlyRegex) rsAccount
-    ropts' = ropts{
-               depth_=Nothing
-              }
-    q = And [queryFromOpts d ropts', excludeforecastq (forecast_ ropts)]
+    rspec' = rspec{rsOpts=ropts{depth_=Nothing}}
+    q = And [rsQuery rspec, periodq, excludeforecastq (forecast_ ropts)]
       where
+        periodq = Date $ periodAsDateSpan $ period_ ropts
         -- Except in forecast mode, exclude future/forecast transactions.
         excludeforecastq (Just _) = Any
         excludeforecastq Nothing  =  -- not:date:tomorrow- not:tag:generated-transaction
@@ -79,8 +78,8 @@
             ,Not generatedTransactionTag
           ]
 
-    (_label,items) = accountTransactionsReport ropts' j q thisacctq
-    items' = (if empty_ ropts' then id else filter (not . mixedAmountLooksZero . fifth6)) $  -- without --empty, exclude no-change txns
+    (_label,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
              items
 
@@ -95,8 +94,8 @@
                                                      [s] -> s
                                                      ss  -> intercalate ", " ss
                                                      -- _   -> "<split>"  -- should do this if accounts field width < 30
-                            ,rsItemChangeAmount  = showMixedAmountElided False change
-                            ,rsItemBalanceAmount = showMixedAmountElided False bal
+                            ,rsItemChangeAmount  = showMixedOneLine showAmountWithoutPrice Nothing (Just 32) False change
+                            ,rsItemBalanceAmount = showMixedOneLine showAmountWithoutPrice Nothing (Just 32) False bal
                             ,rsItemTransaction   = t
                             }
     -- blank items are added to allow more control of scroll position; we won't allow movement over these
@@ -105,8 +104,8 @@
                             ,rsItemStatus        = Unmarked
                             ,rsItemDescription   = ""
                             ,rsItemOtherAccounts = ""
-                            ,rsItemChangeAmount  = ""
-                            ,rsItemBalanceAmount = ""
+                            ,rsItemChangeAmount  = ("", 0)
+                            ,rsItemBalanceAmount = ("", 0)
                             ,rsItemTransaction   = nulltransaction
                             }
     -- build the List
@@ -138,7 +137,7 @@
 rsInit _ _ _ = error "init function called with wrong screen type, should not happen"  -- PARTIAL:
 
 rsDraw :: UIState -> [Widget Name]
-rsDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
+rsDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}
               ,aScreen=RegisterScreen{..}
               ,aMode=mode
               } =
@@ -164,8 +163,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 (strWidth . rsItemChangeAmount) displayitems
-        maxbalwidthseen = maximum' $ map (strWidth . rsItemBalanceAmount) displayitems
+        maxchangewidthseen = maximum' $ map (snd . rsItemChangeAmount) displayitems
+        maxbalwidthseen = maximum' $ map (snd . rsItemBalanceAmount) displayitems
         changewidthproportion = fromIntegral maxchangewidthseen / fromIntegral (maxchangewidthseen + maxbalwidthseen)
         maxchangewidth = round $ changewidthproportion * fromIntegral maxamtswidth
         maxbalwidth = maxamtswidth - maxchangewidth
@@ -192,6 +191,7 @@
       render $ defaultLayout toplabel bottomlabel $ renderList (rsDrawItem colwidths) True rsList
 
       where
+        ropts = rsOpts rspec
         ishistorical = balancetype_ ropts == HistoricalBalance
         -- inclusive = tree_ ropts || rsForceInclusive
 
@@ -201,7 +201,7 @@
           <+> togglefilters
           <+> str " transactions"
           -- <+> str (if ishistorical then " historical total" else " period total")
-          <+> borderQueryStr (query_ ropts)
+          <+> borderQueryStr (unwords . map (quoteIfNeeded . T.unpack) $ querystring_ ropts)
           -- <+> str " and subs"
           <+> borderPeriodStr "in" (period_ ropts)
           <+> str " ("
@@ -262,13 +262,13 @@
       str "  " <+>
       str (fitString (Just acctswidth) (Just acctswidth) True True rsItemOtherAccounts) <+>
       str "   " <+>
-      withAttr changeattr (str (fitString (Just changewidth) (Just changewidth) True False rsItemChangeAmount)) <+>
+      withAttr changeattr (str (fitString (Just changewidth) (Just changewidth) True False $ fst rsItemChangeAmount)) <+>
       str "   " <+>
-      withAttr balattr (str (fitString (Just balwidth) (Just balwidth) True False rsItemBalanceAmount))
+      withAttr balattr (str (fitString (Just balwidth) (Just balwidth) True False $ fst rsItemBalanceAmount))
   where
-    changeattr | '-' `elem` rsItemChangeAmount = sel $ "list" <> "amount" <> "decrease"
+    changeattr | '-' `elem` fst rsItemChangeAmount = sel $ "list" <> "amount" <> "decrease"
                | otherwise                     = sel $ "list" <> "amount" <> "increase"
-    balattr    | '-' `elem` rsItemBalanceAmount = sel $ "list" <> "balance" <> "negative"
+    balattr    | '-' `elem` fst rsItemBalanceAmount = sel $ "list" <> "balance" <> "negative"
                | otherwise                      = sel $ "list" <> "balance" <> "positive"
     sel | selected  = (<> "selected")
         | otherwise = id
diff --git a/Hledger/UI/TransactionScreen.hs b/Hledger/UI/TransactionScreen.hs
--- a/Hledger/UI/TransactionScreen.hs
+++ b/Hledger/UI/TransactionScreen.hs
@@ -43,7 +43,7 @@
   }
 
 tsInit :: Day -> Bool -> UIState -> UIState
-tsInit _d _reset ui@UIState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=_ropts}}
+tsInit _d _reset ui@UIState{aopts=UIOpts{cliopts_=CliOpts{reportspec_=_rspec}}
                            ,ajournal=_j
                            ,aScreen=TransactionScreen{}
                            } =
@@ -58,7 +58,7 @@
 tsInit _ _ _ = error "init function called with wrong screen type, should not happen"  -- PARTIAL:
 
 tsDraw :: UIState -> [Widget Name]
-tsDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
+tsDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}
               ,ajournal=j
               ,aScreen=TransactionScreen{tsTransaction=(i,t)
                                         ,tsTransactions=nts
@@ -77,15 +77,14 @@
         styles = journalCommodityStyles j
         periodlast =
           fromMaybe (error' "TransactionScreen: expected a non-empty journal") $  -- PARTIAL: shouldn't happen
-          reportPeriodOrJournalLastDay ropts j
-        mreportlast = reportPeriodLastDay ropts
-        today = fromMaybe (error' "TransactionScreen: could not pick a valuation date, ReportOpts today_ is unset") $ today_ ropts  -- PARTIAL:
+          reportPeriodOrJournalLastDay rspec j
+        mreportlast = reportPeriodLastDay rspec
         multiperiod = interval_ ropts /= NoInterval
 
       render $ defaultLayout toplabel bottomlabel $ str $
         showTransactionOneLineAmounts $
         (if valuationTypeIsCost ropts then transactionToCost (journalCommodityStyles j) else id) $
-        (if valuationTypeIsDefaultValue ropts then (\t -> transactionApplyValuation prices styles periodlast mreportlast today multiperiod t (AtDefault Nothing)) else id) $
+        (if valuationTypeIsDefaultValue ropts then (\t -> transactionApplyValuation prices styles periodlast mreportlast (rsToday rspec) multiperiod t (AtDefault Nothing)) else id) $
         -- (if real_ ropts then filterTransactionPostings (Real True) else id) -- filter postings by --real
         t
       where
@@ -98,7 +97,7 @@
           <+> withAttr ("border" <> "bold") (str $ show i)
           <+> str (" of "++show (length nts))
           <+> togglefilters
-          <+> borderQueryStr (query_ ropts)
+          <+> 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 "")
           where
@@ -133,7 +132,7 @@
                                                ,tsTransactions=nts
                                                ,tsAccount=acct
                                                }
-                   ,aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
+                   ,aopts=UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}
                    ,ajournal=j
                    ,aMode=mode
                    }
@@ -173,7 +172,7 @@
             Right j' -> do
               continue $
                 regenerateScreens j' d $
-                regenerateTransactions ropts d j' s acct i $   -- added (inline) 201512 (why ?)
+                regenerateTransactions rspec j' s acct i $   -- added (inline) 201512 (why ?)
                 clearCostValue $
                 ui
         VtyEvent (EvKey (KChar 'I') []) -> continue $ uiCheckBalanceAssertions d (toggleIgnoreBalanceAssertions ui)
@@ -208,15 +207,12 @@
 
 -- 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 :: ReportOpts -> Day -> Journal -> Screen -> AccountName -> Integer -> UIState -> UIState
-regenerateTransactions ropts d j s acct i ui =
+regenerateTransactions :: ReportSpec -> Journal -> Screen -> AccountName -> Integer -> UIState -> UIState
+regenerateTransactions rspec j s acct i ui =
   let
-    ropts' = ropts {depth_=Nothing
-                   ,balancetype_=HistoricalBalance
-                   }
-    q = filterQuery (not . queryIsDepth) $ queryFromOpts d ropts'
+    q = filterQuery (not . queryIsDepth) $ rsQuery rspec
     thisacctq = Acct $ accountNameToAccountRegex acct -- includes subs
-    items = reverse $ snd $ accountTransactionsReport ropts j q thisacctq
+    items = reverse $ snd $ accountTransactionsReport rspec j q thisacctq
     ts = map first6 items
     numberedts = zip [1..] ts
     -- select the best current transaction from the new list
diff --git a/Hledger/UI/UIOptions.hs b/Hledger/UI/UIOptions.hs
--- a/Hledger/UI/UIOptions.hs
+++ b/Hledger/UI/UIOptions.hs
@@ -58,15 +58,16 @@
 
 -- hledger-ui options, used in hledger-ui and above
 data UIOpts = UIOpts {
-     watch_   :: Bool
-    ,change_  :: Bool
-    ,cliopts_ :: CliOpts
+     watch_       :: Bool
+    ,change_      :: Bool
+    ,cliopts_     :: CliOpts
  } deriving (Show)
 
 defuiopts = UIOpts
-    def
-    def
-    def
+  { watch_   = False
+  , change_  = False
+  , cliopts_ = def
+  }
 
 -- instance Default CliOpts where def = defcliopts
 
@@ -74,9 +75,9 @@
 rawOptsToUIOpts rawopts = checkUIOpts <$> do
   cliopts <- rawOptsToCliOpts rawopts
   return defuiopts {
-              watch_   = boolopt "watch" rawopts
-             ,change_  = boolopt "change" rawopts
-             ,cliopts_ = cliopts
+              watch_       = boolopt "watch" rawopts
+             ,change_      = boolopt "change" rawopts
+             ,cliopts_     = cliopts
              }
 
 checkUIOpts :: UIOpts -> UIOpts
@@ -94,4 +95,3 @@
   let args' = replaceNumericFlags args
   let cmdargopts = either usageError id $ process uimode args'
   rawOptsToUIOpts cmdargopts
-
diff --git a/Hledger/UI/UIState.hs b/Hledger/UI/UIState.hs
--- a/Hledger/UI/UIState.hs
+++ b/Hledger/UI/UIState.hs
@@ -8,10 +8,11 @@
 where
 
 import Brick.Widgets.Edit
-import Data.List
+import Data.List ((\\), foldl', sort)
+import Data.Maybe (fromMaybe)
+import qualified Data.Text as T
 import Data.Text.Zipper (gotoEOL)
 import Data.Time.Calendar (Day)
-import Data.Maybe (fromMaybe)
 
 import Hledger
 import Hledger.Cli.CliOptions
@@ -20,18 +21,18 @@
 
 -- | Toggle between showing only unmarked items or all items.
 toggleUnmarked :: UIState -> UIState
-toggleUnmarked ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=reportOptsToggleStatusSomehow Unmarked copts ropts}}}
+toggleUnmarked ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =
+  ui{aopts=uopts{cliopts_=copts{reportspec_=reportSpecToggleStatusSomehow Unmarked copts rspec}}}
 
 -- | Toggle between showing only pending items or all items.
 togglePending :: UIState -> UIState
-togglePending ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=reportOptsToggleStatusSomehow Pending copts ropts}}}
+togglePending ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =
+  ui{aopts=uopts{cliopts_=copts{reportspec_=reportSpecToggleStatusSomehow Pending copts rspec}}}
 
 -- | Toggle between showing only cleared items or all items.
 toggleCleared :: UIState -> UIState
-toggleCleared ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=reportOptsToggleStatusSomehow Cleared copts ropts}}}
+toggleCleared ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =
+  ui{aopts=uopts{cliopts_=copts{reportspec_=reportSpecToggleStatusSomehow Cleared copts rspec}}}
 
 -- TODO testing different status toggle styles
 
@@ -51,14 +52,17 @@
     showstatus Pending  = "pending"
     showstatus Unmarked = "unmarked"
 
-reportOptsToggleStatusSomehow :: Status -> CliOpts -> ReportOpts -> ReportOpts
-reportOptsToggleStatusSomehow s copts ropts =
-  case maybeposintopt "status-toggles" $ rawopts_ copts of
-     Just 2 -> reportOptsToggleStatus2 s ropts
-     Just 3 -> reportOptsToggleStatus3 s ropts
---     Just 4 -> reportOptsToggleStatus4 s ropts
---     Just 5 -> reportOptsToggleStatus5 s ropts
-     _      -> reportOptsToggleStatus1 s ropts
+reportSpecToggleStatusSomehow :: Status -> CliOpts -> ReportSpec -> ReportSpec
+reportSpecToggleStatusSomehow s copts =
+    either (error "reportSpecToggleStatusSomehow: updating Status should not result in an error") id  -- PARTIAL:
+    . updateReportSpecFromOpts update
+  where
+    update = case maybeposintopt "status-toggles" $ rawopts_ copts of
+      Just 2 -> reportOptsToggleStatus2 s
+      Just 3 -> reportOptsToggleStatus3 s
+--      Just 4 -> reportOptsToggleStatus4 s
+--      Just 5 -> reportOptsToggleStatus5 s
+      _      -> reportOptsToggleStatus1 s
 
 -- 1 UPC toggles only X/all
 reportOptsToggleStatus1 s ropts@ReportOpts{statuses_=ss}
@@ -101,26 +105,26 @@
 
 -- | Toggle between showing all and showing only nonempty (more precisely, nonzero) items.
 toggleEmpty :: UIState -> UIState
-toggleEmpty ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=toggleEmpty ropts}}}
+toggleEmpty ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =
+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=toggleEmpty ropts}}}}
   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{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{value_ = plog "clearing value mode" Nothing}}}}
+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{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{value_ = valuationToggleCost $ value_ ropts}}}}
+toggleCost ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =
+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{value_ = valuationToggleCost $ value_ ropts}}}}}
 
 -- | Toggle between showing primary amounts or default valuation.
 toggleValue :: UIState -> UIState
-toggleValue ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{
-    value_ = plog "toggling value mode to" $ valuationToggleValue $ value_ ropts}}}}
+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}}}}}
 
 -- | Basic toggling of -B/cost, for hledger-ui.
 valuationToggleCost :: Maybe ValuationType -> Maybe ValuationType
@@ -134,18 +138,18 @@
 
 -- | Set hierarchic account tree mode.
 setTree :: UIState -> UIState
-setTree ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{accountlistmode_=ALTree}}}}
+setTree ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =
+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{accountlistmode_=ALTree}}}}}
 
 -- | Set flat account list mode.
 setList :: UIState -> UIState
-setList ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{accountlistmode_=ALFlat}}}}
+setList ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =
+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{accountlistmode_=ALFlat}}}}}
 
 -- | Toggle between flat and tree mode. If current mode is unspecified/default, assume it's flat.
 toggleTree :: UIState -> UIState
-toggleTree ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=toggleTreeMode ropts}}}
+toggleTree ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =
+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=toggleTreeMode ropts}}}}
   where
     toggleTreeMode ropts
       | accountlistmode_ ropts == ALTree = ropts{accountlistmode_=ALFlat}
@@ -153,8 +157,8 @@
 
 -- | Toggle between historical balances and period balances.
 toggleHistorical :: UIState -> UIState
-toggleHistorical ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{balancetype_=b}}}}
+toggleHistorical ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =
+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{rsOpts=ropts{balancetype_=b}}}}}
   where
     b | balancetype_ ropts == HistoricalBalance = PeriodChange
       | otherwise                               = HistoricalBalance
@@ -173,10 +177,10 @@
 -- transactions with a query for their special tag.
 --
 toggleForecast :: Day -> UIState -> UIState
-toggleForecast d ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
+toggleForecast d ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =
   ui{aopts=uopts{cliopts_=copts'}}
   where
-    copts' = copts{reportopts_=ropts{forecast_=forecast'}}
+    copts' = copts{reportspec_=rspec{rsOpts=ropts{forecast_=forecast'}}}
     forecast' =
       case forecast_ ropts of
         Just _  -> Nothing
@@ -184,10 +188,11 @@
 
 -- | Toggle between showing all and showing only real (non-virtual) items.
 toggleReal :: UIState -> UIState
-toggleReal ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=toggleReal ropts}}}
+toggleReal ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =
+    ui{aopts=uopts{cliopts_=copts{reportspec_=update rspec}}}
   where
-    toggleReal ropts = ropts{real_=not $ real_ ropts}
+    update = either (error "toggleReal: updating Real should not result in an error") id  -- PARTIAL:
+           . updateReportSpecFromOpts (\ropts -> ropts{real_=not $ real_ ropts})
 
 -- | Toggle the ignoring of balance assertions.
 toggleIgnoreBalanceAssertions :: UIState -> UIState
@@ -196,61 +201,68 @@
 
 -- | Step through larger report periods, up to all.
 growReportPeriod :: Day -> UIState -> UIState
-growReportPeriod _d ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=periodGrow $ period_ ropts}}}}
+growReportPeriod _d = updateReportPeriod periodGrow
 
 -- | Step through smaller report periods, down to a day.
 shrinkReportPeriod :: Day -> UIState -> UIState
-shrinkReportPeriod d ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=periodShrink d $ period_ ropts}}}}
+shrinkReportPeriod d = updateReportPeriod (periodShrink d)
 
 -- | Step the report start/end dates to the next period of same duration,
 -- remaining inside the given enclosing span.
 nextReportPeriod :: DateSpan -> UIState -> UIState
-nextReportPeriod enclosingspan ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{period_=p}}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=periodNextIn enclosingspan p}}}}
+nextReportPeriod enclosingspan = updateReportPeriod (periodNextIn enclosingspan)
 
 -- | Step the report start/end dates to the next period of same duration,
 -- remaining inside the given enclosing span.
 previousReportPeriod :: DateSpan -> UIState -> UIState
-previousReportPeriod enclosingspan ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{period_=p}}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=periodPreviousIn enclosingspan p}}}}
+previousReportPeriod enclosingspan = updateReportPeriod (periodPreviousIn enclosingspan)
 
 -- | If a standard report period is set, step it forward/backward if needed so that
 -- it encloses the given date.
 moveReportPeriodToDate :: Day -> UIState -> UIState
-moveReportPeriodToDate d ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{period_=p}}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=periodMoveTo d p}}}}
+moveReportPeriodToDate d = updateReportPeriod (periodMoveTo d)
 
 -- | Get the report period.
 reportPeriod :: UIState -> Period
-reportPeriod UIState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ReportOpts{period_=p}}}} =
-  p
+reportPeriod = period_ . rsOpts . reportspec_ . cliopts_ . aopts
 
 -- | Set the report period.
 setReportPeriod :: Period -> UIState -> UIState
-setReportPeriod p ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{period_=p}}}}
+setReportPeriod p = updateReportPeriod (const p)
 
 -- | Clear any report period limits.
 resetReportPeriod :: UIState -> UIState
 resetReportPeriod = setReportPeriod PeriodAll
 
+-- | Update report period by a applying a function.
+updateReportPeriod :: (Period -> Period) -> UIState -> UIState
+updateReportPeriod updatePeriod ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =
+    ui{aopts=uopts{cliopts_=copts{reportspec_=update rspec}}}
+  where
+    update = either (error "updateReportPeriod: updating period should not result in an error") id  -- PARTIAL:
+           . updateReportSpecFromOpts (\ropts -> ropts{period_=updatePeriod $ period_ ropts})
+
 -- | Apply a new filter query.
 setFilter :: String -> UIState -> UIState
-setFilter s ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{query_=s}}}}
+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 . updateReportSpecFromOpts (\ropts -> ropts{querystring_=querystring})
+    querystring = words'' prefixes $ T.pack s
 
 -- | Reset some filters & toggles.
 resetFilter :: UIState -> UIState
-resetFilter ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{
-     empty_=True
-    ,statuses_=[]
-    ,real_=False
-    ,query_=""
-    --,period_=PeriodAll
-    }}}}
+resetFilter ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec@ReportSpec{rsOpts=ropts}}}} =
+  ui{aopts=uopts{cliopts_=copts{reportspec_=rspec{
+     rsQuery=Any
+    ,rsQueryOpts=[]
+    ,rsOpts=ropts{
+       empty_=True
+      ,statuses_=[]
+      ,real_=False
+      ,querystring_=[]
+      --,period_=PeriodAll
+    }}}}}
 
 -- | Reset all options state to exactly what it was at startup
 -- (preserving any command-line options/arguments).
@@ -258,8 +270,7 @@
 resetOpts ui@UIState{astartupopts} = ui{aopts=astartupopts}
 
 resetDepth :: UIState -> UIState
-resetDepth ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
-  ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=Nothing}}}}
+resetDepth = updateReportDepth (const Nothing)
 
 -- | Get the maximum account depth in the current journal.
 maxDepth :: UIState -> Int
@@ -268,8 +279,7 @@
 -- | Decrement the current depth limit towards 0. If there was no depth limit,
 -- set it to one less than the maximum account depth.
 decDepth :: UIState -> UIState
-decDepth ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{..}}}}
-  = ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=dec depth_}}}}
+decDepth ui = updateReportDepth dec ui
   where
     dec (Just d) = Just $ max 0 (d-1)
     dec Nothing  = Just $ maxDepth ui - 1
@@ -277,35 +287,37 @@
 -- | Increment the current depth limit. If this makes it equal to the
 -- the maximum account depth, remove the depth limit.
 incDepth :: UIState -> UIState
-incDepth ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts@ReportOpts{..}}}}
-  = ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=inc depth_}}}}
-  where
-    inc (Just d) | d < (maxDepth ui - 1) = Just $ d+1
-    inc _ = Nothing
+incDepth = updateReportDepth (fmap succ)
 
 -- | Set the current depth limit to the specified depth, or remove the depth limit.
 -- Also remove the depth limit if the specified depth is greater than the current
 -- maximum account depth. If the specified depth is negative, reset the depth limit
 -- to whatever was specified at uiartup.
 setDepth :: Maybe Int -> UIState -> UIState
-setDepth mdepth ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}}
-  = ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{depth_=mdepth'}}}}
-  where
-    mdepth' = case mdepth of
-                Nothing                   -> Nothing
-                Just d | d < 0            -> depth_ ropts
-                       | d >= maxDepth ui -> Nothing
-                       | otherwise        -> mdepth
+setDepth mdepth = updateReportDepth (const mdepth)
 
 getDepth :: UIState -> Maybe Int
-getDepth UIState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}} = depth_ ropts
+getDepth = depth_ . rsOpts . reportspec_ . cliopts_ . aopts
 
+-- | Update report depth by a applying a function. If asked to set a depth less
+-- than zero, it will leave it unchanged.
+updateReportDepth :: (Maybe Int -> Maybe Int) -> UIState -> UIState
+updateReportDepth updateDepth ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportspec_=rspec}}} =
+    ui{aopts=uopts{cliopts_=copts{reportspec_=update rspec}}}
+  where
+    update = either (error "updateReportDepth: updating depth should not result in an error") id  -- PARTIAL:
+           . updateReportSpecFromOpts (\ropts -> ropts{depth_=updateDepth (depth_ ropts) >>= clipDepth ropts})
+    clipDepth ropts d | d < 0            = depth_ ropts
+                      | d >= maxDepth ui = Nothing
+                      | otherwise        = Just d
+
 -- | Open the minibuffer, setting its content to the current query with the cursor at the end.
 showMinibuffer :: UIState -> UIState
 showMinibuffer ui = setMode (Minibuffer e) ui
   where
     e = applyEdit gotoEOL $ editor MinibufferEditor (Just 1) oldq
-    oldq = query_ $ reportopts_ $ cliopts_ $ aopts ui
+    oldq = unwords . map (quoteIfNeeded . T.unpack)
+         . querystring_ . rsOpts . reportspec_ . cliopts_ $ aopts ui
 
 -- | Close the minibuffer, discarding any edit in progress.
 closeMinibuffer :: UIState -> UIState
diff --git a/Hledger/UI/UITypes.hs b/Hledger/UI/UITypes.hs
--- a/Hledger/UI/UITypes.hs
+++ b/Hledger/UI/UITypes.hs
@@ -146,8 +146,8 @@
   ,rsItemStatus         :: Status           -- ^ transaction status
   ,rsItemDescription    :: String           -- ^ description
   ,rsItemOtherAccounts  :: String           -- ^ other accounts
-  ,rsItemChangeAmount   :: String           -- ^ the change to the current account from this transaction
-  ,rsItemBalanceAmount  :: String           -- ^ the balance or running total after this transaction
+  ,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
   }
   deriving (Show)
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" "September 2020" "hledger-ui 1.18.99" "hledger User Manuals"
+.TH "hledger-ui" "1" "November 2020" "hledger-ui 1.20" "hledger User Manuals"
 
 
 
@@ -88,6 +88,9 @@
 \f[B]\f[CB]-I --ignore-assertions\f[B]\f[R]
 disable balance assertion checks (note: does not disable balance
 assignments)
+.TP
+\f[B]\f[CB]-s --strict\f[B]\f[R]
+do extra error checking (check that all posted accounts are declared)
 .PP
 hledger reporting options:
 .TP
diff --git a/hledger-ui.cabal b/hledger-ui.cabal
--- a/hledger-ui.cabal
+++ b/hledger-ui.cabal
@@ -4,10 +4,10 @@
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 9f306e545c5b87e192eac6bea6e0a46c9694e9844524b6ef500d2eb59e3d2fa0
+-- hash: 4007bd6deffcff3c3d5a40863cfa11bddaed31c367fdf5033728ec847c292a91
 
 name:           hledger-ui
-version:        1.19.1
+version:        1.20
 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.
@@ -64,7 +64,7 @@
   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.19.1"
+  cpp-options: -DVERSION="1.20"
   build-depends:
       ansi-terminal >=0.9
     , async
@@ -78,12 +78,11 @@
     , extra >=1.6.3
     , filepath
     , fsnotify >=0.2.1.2 && <0.4
-    , hledger >=1.19.1 && <1.20
-    , hledger-lib >=1.19.1 && <1.20
+    , hledger >=1.20 && <1.21
+    , hledger-lib >=1.20 && <1.21
     , megaparsec >=7.0.0 && <9.1
     , microlens >=0.4
     , microlens-platform >=0.2.3.1
-    , pretty-show >=1.6.4
     , process >=1.2
     , safe >=0.2
     , split >=0.1
diff --git a/hledger-ui.info b/hledger-ui.info
--- a/hledger-ui.info
+++ b/hledger-ui.info
@@ -3,8 +3,8 @@
 
 File: hledger-ui.info,  Node: Top,  Next: OPTIONS,  Up: (dir)
 
-hledger-ui(1) hledger-ui 1.18.99
-********************************
+hledger-ui(1) hledger-ui 1.20
+*****************************
 
 hledger-ui - terminal interface for the hledger accounting tool
 
@@ -99,7 +99,11 @@
 
      disable balance assertion checks (note: does not disable balance
      assignments)
+'-s --strict'
 
+     do extra error checking (check that all posted accounts are
+     declared)
+
    hledger reporting options:
 
 '-b --begin=DATE'
@@ -515,26 +519,26 @@
 
 Tag Table:
 Node: Top71
-Node: OPTIONS1476
-Ref: #options1573
-Node: keys5545
-Ref: #keys5640
-Node: screens9972
-Ref: #screens10077
-Node: accounts screen10167
-Ref: #accounts-screen10295
-Node: Register screen12510
-Ref: #register-screen12665
-Node: Transaction screen14662
-Ref: #transaction-screen14820
-Node: Error screen15690
-Ref: #error-screen15812
-Node: ENVIRONMENT16056
-Ref: #environment16170
-Node: FILES16977
-Ref: #files17076
-Node: BUGS17289
-Ref: #bugs17366
+Node: OPTIONS1470
+Ref: #options1567
+Node: keys5634
+Ref: #keys5729
+Node: screens10061
+Ref: #screens10166
+Node: accounts screen10256
+Ref: #accounts-screen10384
+Node: Register screen12599
+Ref: #register-screen12754
+Node: Transaction screen14751
+Ref: #transaction-screen14909
+Node: Error screen15779
+Ref: #error-screen15901
+Node: ENVIRONMENT16145
+Ref: #environment16259
+Node: FILES17066
+Ref: #files17165
+Node: BUGS17378
+Ref: #bugs17455
 
 End Tag Table
 
diff --git a/hledger-ui.txt b/hledger-ui.txt
--- a/hledger-ui.txt
+++ b/hledger-ui.txt
@@ -84,6 +84,10 @@
               disable balance assertion checks (note: does not disable balance
               assignments)
 
+       -s --strict
+              do  extra error checking (check that all posted accounts are de-
+              clared)
+
        hledger reporting options:
 
        -b --begin=DATE
@@ -108,7 +112,7 @@
               multiperiod/multicolumn report by year
 
        -p --period=PERIODEXP
-              set  start date, end date, and/or reporting interval all at once
+              set start date, end date, and/or reporting interval all at  once
               using period expressions syntax
 
        --date2
@@ -131,21 +135,21 @@
               hide/aggregate accounts or postings more than NUM levels deep
 
        -E --empty
-              show  items with zero amount, normally hidden (and vice-versa in
+              show items with zero amount, normally hidden (and vice-versa  in
               hledger-ui/hledger-web)
 
        -B --cost
               convert amounts to their cost/selling amount at transaction time
 
        -V --market
-              convert amounts to their market value in default valuation  com-
+              convert  amounts to their market value in default valuation com-
               modities
 
        -X --exchange=COMM
               convert amounts to their market value in commodity COMM
 
        --value
-              convert  amounts  to  cost  or  market value, more flexibly than
+              convert amounts to cost or  market  value,  more  flexibly  than
               -B/-V/-X
 
        --infer-value
@@ -154,15 +158,15 @@
        --auto apply automated posting rules to modify transactions.
 
        --forecast
-              generate future transactions from  periodic  transaction  rules,
-              for  the  next 6 months or till report end date.  In hledger-ui,
+              generate  future  transactions  from periodic transaction rules,
+              for the next 6 months or till report end date.   In  hledger-ui,
               also make ordinary future transactions visible.
 
        --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
+              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
               NO_COLOR environment variable overrides this.
 
        When a reporting option appears more than once in the command line, the
@@ -182,91 +186,91 @@
               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,
+       contain  one  command line option/argument per line.  (to prevent this,
        insert a -- argument before.)
 
 keys
-       ?  shows a help dialog listing all keys.  (some of these also appear in
+       ? 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
+       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,
+       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 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 "current" period  (the  current
+       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 "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.
 
-       /  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
+       / 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 escapeto cancel.  there are also keys for quickly adjusting some
-       common  filters  like account depth and transaction status (see below).
+       common filters like account depth and transaction status  (see  below).
        backspace or delete removes all filters, showing all transactions.
 
-       as mentioned above, by default hledger-ui hides future  transactions  -
+       as  mentioned  above, by default hledger-ui hides future transactions -
        both ordinary transactions recorded in the journal, and periodic trans-
-       actions generated by rule.  f  toggles  forecast  mode,  in  which  fu-
+       actions  generated  by  rule.   f  toggles  forecast mode, in which fu-
        ture/forecasted transactions are shown.  (experimental)
 
-       escape  resets the UI state and jumps back to the top screen, restoring
+       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 en-
        try or the help dialog.
 
        ctrl-l redraws the screen and centers the selection if possible (selec-
-       tions near the top won't be centered, since we don't scroll  above  the
+       tions  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
+       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 installed  in
+       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  cursor
-       will  be  positioned  at  the current transaction when invoked from the
-       register and transaction screens, and at the error location (if  possi-
+       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 possi-
        ble) when invoked from the error screen.
 
-       b  toggles cost mode, showing amounts in their transaction price's com-
+       b toggles cost mode, showing amounts in their transaction price's  com-
        modity (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  transaction
-       as  it  was  valued  on july 30, go to the accounts or register screen,
+       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.
 
        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;
+       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 mode.
 
-       with  --watch  active,  if  you  save an edit to the journal file while
+       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
+       stop working.  to work around, press g to force  a  manual  reload,  or
        exit the transaction screen.
 
        q quits the application.
@@ -275,43 +279,43 @@
 
 screens
    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
+       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 subac-
-       counts, except where subaccounts are hidden by a depth limit  (see  be-
+       Account  names  are  shown as a flat list by default; press t to toggle
+       tree mode.  In list mode, account  balances  are  exclusive  of  subac-
+       counts,  except  where subaccounts are hidden by a depth limit (see be-
        low).  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.
+       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
+       less detail, collapsing all accounts to a single total.  To remove  the
        depth limit, set it higher than the maximum account depth, or press ES-
        CAPE.
 
        H toggles between showing historical balances or period balances.  His-
-       torical 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 be-
-       fore the report start date, so they show the change in  balance  during
+       torical  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  be-
+       fore  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 include all postings;
-       if you activate one or two status filters, only those postings are  in-
+       toggles cleared postings.  (By default, balances include all  postings;
+       if  you activate one or two status filters, only those postings are in-
        cluded; and if you activate all three, the filter is removed.)
 
        R toggles real mode, in which virtual postings are ignored.
 
-       Z  toggles  nonzero  mode, in which only accounts with nonzero balances
-       are shown (hledger-ui shows zero items by default, unlike  command-line
+       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.
@@ -320,63 +324,63 @@
        This screen shows the transactions affecting a particular account, like
        a check register.  Each line represents one transaction and shows:
 
-       o the other account(s) involved, in abbreviated form.   (If  there  are
-         both  real  and virtual postings, it shows only the accounts affected
+       o 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.)
 
-       o the overall change to the current account's balance; positive for  an
+       o the  overall change to the current account's balance; positive for an
          inflow to this account, negative for an outflow.
 
        o 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
+         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
+         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
+       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  transac-
-       tions  contributing  to the balance shown on the accounts screen.  Tree
+       mode but this account has subaccounts which are  not  shown  due  to  a
+       depth  limit.   In  other words, the register always shows the transac-
+       tions 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
+       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 transac-
+       cleared  transactions.  (By default, transactions with all statuses are
+       shown; if you activate one or two status filters, only  those  transac-
        tions are shown; and if you activate all three, the filter is removed.)
 
        R toggles real mode, in which virtual postings are ignored.
 
-       Z toggles nonzero mode, in which only transactions  posting  a  nonzero
-       change  are  shown (hledger-ui shows zero items by default, unlike com-
+       Z  toggles  nonzero  mode, in which only transactions posting a nonzero
+       change are shown (hledger-ui shows zero items by default,  unlike  com-
        mand-line hledger).
 
        Press right (or enter) to view the selected transaction in detail.
 
    Transaction screen
-       This screen shows a single transaction, as  a  general  journal  entry,
-       similar  to  hledger's  print command and journal format (hledger_jour-
+       This  screen  shows  a  single transaction, as a general journal entry,
+       similar to hledger's print command and  journal  format  (hledger_jour-
        nal(5)).
 
-       The transaction's date(s) and any cleared flag, transaction  code,  de-
-       scription,  comments, along with all of its account postings are shown.
-       Simple transactions have two postings, but there can  be  more  (or  in
+       The  transaction's  date(s) and any cleared flag, transaction code, de-
+       scription, comments, along with all of its account postings are  shown.
+       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 vary de-
+       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  de-
        pending on which account register you came from (remember most transac-
-       tions  appear  in multiple account registers).  The #N number preceding
+       tions appear in multiple account registers).  The #N  number  preceding
        them is the transaction's position within the complete unfiltered jour-
        nal, which is a more stable id (at least until the next reload).
 
    Error screen
-       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
+       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
        to cancel the reload attempt.)
 
@@ -384,15 +388,15 @@
        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.jour-
+       ~/.hledger.journal (on  windows,  perhaps  C:/Users/USER/.hledger.jour-
        nal).
 
-       A typical value is ~/DIR/YYYY.journal,  where  DIR  is  a  version-con-
-       trolled  finance directory and YYYY is the current year.  Or ~/DIR/cur-
+       A  typical  value  is  ~/DIR/YYYY.journal,  where DIR is a version-con-
+       trolled finance directory and YYYY is the current year.  Or  ~/DIR/cur-
        rent.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
+       more thorough way that also affects applications started from  the  GUI
        (say, an Emacs dock icon).  Eg on MacOS Catalina I have a ~/.MacOSX/en-
        vironment.plist file containing
 
@@ -403,13 +407,13 @@
        To see the effect you may need to killall Dock, or reboot.
 
 FILES
-       Reads  data from one or more files in hledger journal, timeclock, time-
-       dot,  or  CSV  format  specified   with   -f,   or   $LEDGER_FILE,   or
-       $HOME/.hledger.journal           (on          windows,          perhaps
+       Reads data from one or more files in hledger journal, timeclock,  time-
+       dot,   or   CSV   format   specified   with  -f,  or  $LEDGER_FILE,  or
+       $HOME/.hledger.journal          (on          windows,           perhaps
        C:/Users/USER/.hledger.journal).
 
 BUGS
-       The need to precede options with -- when invoked from hledger  is  awk-
+       The  need  to precede options with -- when invoked from hledger is awk-
        ward.
 
        -f- doesn't work (hledger-ui can't read from stdin).
@@ -417,24 +421,24 @@
        -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 there is  no
+       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, 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.  Symp-
-       toms include: unresponsive UI, periodic resetting of the  cursor  posi-
+       --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.   Symp-
+       toms  include:  unresponsive UI, periodic resetting of the cursor posi-
        tion, momentary display of parse errors, high CPU usage eventually sub-
        siding, and possibly a small but persistent build-up of CPU usage until
        the program is restarted.
 
-       Also,  if  you  are viewing files mounted from another machine, --watch
+       Also, if you are viewing files mounted from  another  machine,  --watch
        requires that both machine clocks are roughly in step.
 
 
 
 REPORTING BUGS
-       Report bugs at http://bugs.hledger.org (or on the #hledger IRC  channel
+       Report  bugs at http://bugs.hledger.org (or on the #hledger IRC channel
        or hledger mail list)
 
 
@@ -448,7 +452,7 @@
 
 
 SEE ALSO
-       hledger(1),      hledger-ui(1),     hledger-web(1),     hledger-api(1),
+       hledger(1),     hledger-ui(1),     hledger-web(1),      hledger-api(1),
        hledger_csv(5), hledger_journal(5), hledger_timeclock(5), hledger_time-
        dot(5), ledger(1)
 
@@ -456,4 +460,4 @@
 
 
 
-hledger-ui 1.18.99              September 2020                   hledger-ui(1)
+hledger-ui 1.20                  November 2020                   hledger-ui(1)
