ui,web: Adopt new ReportOptions interface, store literal query string in UIOpts.

This commit is contained in:
Stephen Morgan 2020-09-03 17:12:36 +10:00 committed by Simon Michael
parent efc9758f82
commit fcbe511d42
8 changed files with 37 additions and 44 deletions

View File

@ -81,9 +81,7 @@ asInit d reset ui@UIState{
as = map asItemAccountName displayitems as = map asItemAccountName displayitems
uopts' = uopts{cliopts_=copts{reportopts_=ropts'}} uopts' = uopts{cliopts_=copts{reportopts_=ropts'}}
ropts' = ropts{accountlistmode_=if tree_ ropts then ALTree else ALFlat} ropts' = ropts{query_=simplifyQuery $ And [query_ ropts, excludeforecastq (forecast_ ropts)]}
q = And [queryFromOpts d ropts, excludeforecastq (forecast_ ropts)]
where where
-- Except in forecast mode, exclude future/forecast transactions. -- Except in forecast mode, exclude future/forecast transactions.
excludeforecastq (Just _) = Any excludeforecastq (Just _) = Any
@ -94,7 +92,7 @@ asInit d reset ui@UIState{
] ]
-- run the report -- run the report
(items,_total) = balanceReport ropts' q j (items,_total) = balanceReport ropts' j
-- pre-render the list items -- pre-render the list items
displayitem (fullacct, shortacct, indent, bal) = displayitem (fullacct, shortacct, indent, bal) =
@ -119,7 +117,7 @@ asInit d reset ui@UIState{
asInit _ _ _ = error "init function called with wrong screen type, should not happen" -- PARTIAL: asInit _ _ _ = error "init function called with wrong screen type, should not happen" -- PARTIAL:
asDraw :: UIState -> [Widget Name] asDraw :: UIState -> [Widget Name]
asDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} asDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts},querystring_=query}
,ajournal=j ,ajournal=j
,aScreen=s@AccountsScreen{} ,aScreen=s@AccountsScreen{}
,aMode=mode ,aMode=mode
@ -174,7 +172,7 @@ asDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
<+> toggles <+> toggles
<+> str (" account " ++ if ishistorical then "balances" else "changes") <+> str (" account " ++ if ishistorical then "balances" else "changes")
<+> borderPeriodStr (if ishistorical then "at end of" else "in") (period_ ropts) <+> borderPeriodStr (if ishistorical then "at end of" else "in") (period_ ropts)
<+> borderQueryStr querystr <+> borderQueryStr query
<+> borderDepthStr mdepth <+> borderDepthStr mdepth
<+> str (" ("++curidx++"/"++totidx++")") <+> str (" ("++curidx++"/"++totidx++")")
<+> (if ignore_assertions_ $ inputopts_ copts <+> (if ignore_assertions_ $ inputopts_ copts
@ -192,7 +190,6 @@ asDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
,uiShowStatus copts $ statuses_ ropts ,uiShowStatus copts $ statuses_ ropts
,if real_ ropts then ["real"] else [] ,if real_ ropts then ["real"] else []
] ]
querystr = query_ ropts
mdepth = depth_ ropts mdepth = depth_ ropts
curidx = case _asList s ^. listSelectedL of curidx = case _asList s ^. listSelectedL of
Nothing -> "-" Nothing -> "-"

View File

@ -17,7 +17,6 @@ import Control.Concurrent.Async
import Control.Monad import Control.Monad
-- import Control.Monad.IO.Class (liftIO) -- import Control.Monad.IO.Class (liftIO)
-- import Data.Monoid -- -- import Data.Monoid --
import Data.List
import Data.List.Extra (nubSort) import Data.List.Extra (nubSort)
import Data.Maybe import Data.Maybe
-- import Data.Text (Text) -- import Data.Text (Text)
@ -83,10 +82,9 @@ runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportopts_=rop
reportopts_= ropts{ reportopts_= ropts{
-- incorporate any depth: query args into depth_, -- incorporate any depth: query args into depth_,
-- any date: query args into period_ -- any date: query args into period_
depth_ =queryDepth q, depth_ =queryDepth $ query_ ropts,
period_=periodfromoptsandargs, period_=periodfromoptsandargs,
query_ =unwords -- as in ReportOptions, with same limitations query_ =filteredQuery $ query_ ropts, -- as in ReportOptions, with same limitations
$ collectopts filteredQueryArg (rawopts_ copts),
-- always disable boring account name eliding, unlike the CLI, for a more regular tree -- always disable boring account name eliding, unlike the CLI, for a more regular tree
no_elide_=True, no_elide_=True,
-- flip the default for items with zero amounts, show them by default -- flip the default for items with zero amounts, show them by default
@ -97,16 +95,11 @@ runBrickUi uopts@UIOpts{cliopts_=copts@CliOpts{inputopts_=_iopts,reportopts_=rop
} }
} }
where where
q = queryFromOpts d ropts datespanfromargs = queryDateSpan (date2_ ropts) $ query_ ropts
datespanfromargs = queryDateSpan (date2_ ropts) $ fst $
either error' id $ parseQuery d (T.pack $ query_ ropts) -- PARTIAL:
periodfromoptsandargs = periodfromoptsandargs =
dateSpanAsPeriod $ spansIntersect [periodAsDateSpan $ period_ ropts, datespanfromargs] dateSpanAsPeriod $ spansIntersect [periodAsDateSpan $ period_ ropts, datespanfromargs]
filteredQueryArg = \case filteredQuery q = simplifyQuery $ And [queryFromFlags ropts, filtered q]
("args", v) where filtered = filterQuery (\x -> not $ queryIsDepth x || queryIsDate x)
| not $ any (`isPrefixOf` v) ["depth:", "date:"] -- skip depth/date passed as query
-> Just (quoteIfNeeded v)
_ -> Nothing
-- XXX move this stuff into Options, UIOpts -- XXX move this stuff into Options, UIOpts
theme = maybe defaultTheme (fromMaybe defaultTheme . getTheme) $ theme = maybe defaultTheme (fromMaybe defaultTheme . getTheme) $

View File

@ -69,7 +69,7 @@ rsInit d reset ui@UIState{aopts=_uopts@UIOpts{cliopts_=CliOpts{reportopts_=ropts
ropts' = ropts{ ropts' = ropts{
depth_=Nothing depth_=Nothing
} }
q = And [queryFromOpts d ropts', excludeforecastq (forecast_ ropts)] q = And [query_ ropts', excludeforecastq (forecast_ ropts)]
where where
-- Except in forecast mode, exclude future/forecast transactions. -- Except in forecast mode, exclude future/forecast transactions.
excludeforecastq (Just _) = Any excludeforecastq (Just _) = Any
@ -138,7 +138,7 @@ rsInit d reset ui@UIState{aopts=_uopts@UIOpts{cliopts_=CliOpts{reportopts_=ropts
rsInit _ _ _ = error "init function called with wrong screen type, should not happen" -- PARTIAL: rsInit _ _ _ = error "init function called with wrong screen type, should not happen" -- PARTIAL:
rsDraw :: UIState -> [Widget Name] rsDraw :: UIState -> [Widget Name]
rsDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} rsDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts},querystring_=query}
,aScreen=RegisterScreen{..} ,aScreen=RegisterScreen{..}
,aMode=mode ,aMode=mode
} = } =
@ -201,7 +201,7 @@ rsDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
<+> togglefilters <+> togglefilters
<+> str " transactions" <+> str " transactions"
-- <+> str (if ishistorical then " historical total" else " period total") -- <+> str (if ishistorical then " historical total" else " period total")
<+> borderQueryStr (query_ ropts) <+> borderQueryStr query
-- <+> str " and subs" -- <+> str " and subs"
<+> borderPeriodStr "in" (period_ ropts) <+> borderPeriodStr "in" (period_ ropts)
<+> str " (" <+> str " ("

View File

@ -58,7 +58,7 @@ tsInit _d _reset ui@UIState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=_ropts}}
tsInit _ _ _ = error "init function called with wrong screen type, should not happen" -- PARTIAL: tsInit _ _ _ = error "init function called with wrong screen type, should not happen" -- PARTIAL:
tsDraw :: UIState -> [Widget Name] tsDraw :: UIState -> [Widget Name]
tsDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} tsDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts},querystring_=query}
,ajournal=j ,ajournal=j
,aScreen=TransactionScreen{tsTransaction=(i,t) ,aScreen=TransactionScreen{tsTransaction=(i,t)
,tsTransactions=nts ,tsTransactions=nts
@ -98,7 +98,7 @@ tsDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
<+> withAttr ("border" <> "bold") (str $ show i) <+> withAttr ("border" <> "bold") (str $ show i)
<+> str (" of "++show (length nts)) <+> str (" of "++show (length nts))
<+> togglefilters <+> togglefilters
<+> borderQueryStr (query_ ropts) <+> borderQueryStr query
<+> str (" in "++T.unpack (replaceHiddenAccountsNameWith "All" acct)++")") <+> 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_ $ inputopts_ copts then withAttr ("border" <> "query") (str " ignoring balance assertions") else str "")
where where
@ -173,7 +173,7 @@ tsHandle ui@UIState{aScreen=s@TransactionScreen{tsTransaction=(i,t)
Right j' -> do Right j' -> do
continue $ continue $
regenerateScreens j' d $ regenerateScreens j' d $
regenerateTransactions ropts d j' s acct i $ -- added (inline) 201512 (why ?) regenerateTransactions ropts j' s acct i $ -- added (inline) 201512 (why ?)
clearCostValue $ clearCostValue $
ui ui
VtyEvent (EvKey (KChar 'I') []) -> continue $ uiCheckBalanceAssertions d (toggleIgnoreBalanceAssertions ui) VtyEvent (EvKey (KChar 'I') []) -> continue $ uiCheckBalanceAssertions d (toggleIgnoreBalanceAssertions ui)
@ -208,13 +208,13 @@ tsHandle _ _ = error "event handler called with wrong screen type, should not ha
-- Got to redo the register screen's transactions report, to get the latest transactions list for this screen. -- 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 ? -- XXX Duplicates rsInit. Why do we have to do this as well as regenerateScreens ?
regenerateTransactions :: ReportOpts -> Day -> Journal -> Screen -> AccountName -> Integer -> UIState -> UIState regenerateTransactions :: ReportOpts -> Journal -> Screen -> AccountName -> Integer -> UIState -> UIState
regenerateTransactions ropts d j s acct i ui = regenerateTransactions ropts j s acct i ui =
let let
ropts' = ropts {depth_=Nothing ropts' = ropts {depth_=Nothing
,balancetype_=HistoricalBalance ,balancetype_=HistoricalBalance
} }
q = filterQuery (not . queryIsDepth) $ queryFromOpts d ropts' q = filterQuery (not . queryIsDepth) $ query_ ropts'
thisacctq = Acct $ accountNameToAccountRegex acct -- includes subs thisacctq = Acct $ accountNameToAccountRegex acct -- includes subs
items = reverse $ snd $ accountTransactionsReport ropts j q thisacctq items = reverse $ snd $ accountTransactionsReport ropts j q thisacctq
ts = map first6 items ts = map first6 items

View File

@ -58,15 +58,17 @@ uimode = (mode "hledger-ui" (setopt "command" "ui" def)
-- hledger-ui options, used in hledger-ui and above -- hledger-ui options, used in hledger-ui and above
data UIOpts = UIOpts { data UIOpts = UIOpts {
watch_ :: Bool watch_ :: Bool
,change_ :: Bool ,change_ :: Bool
,cliopts_ :: CliOpts ,cliopts_ :: CliOpts
,querystring_ :: String
} deriving (Show) } deriving (Show)
defuiopts = UIOpts defuiopts = UIOpts
def def
def def
def def
""
-- instance Default CliOpts where def = defcliopts -- instance Default CliOpts where def = defcliopts
@ -74,9 +76,10 @@ rawOptsToUIOpts :: RawOpts -> IO UIOpts
rawOptsToUIOpts rawopts = checkUIOpts <$> do rawOptsToUIOpts rawopts = checkUIOpts <$> do
cliopts <- rawOptsToCliOpts rawopts cliopts <- rawOptsToCliOpts rawopts
return defuiopts { return defuiopts {
watch_ = boolopt "watch" rawopts watch_ = boolopt "watch" rawopts
,change_ = boolopt "change" rawopts ,change_ = boolopt "change" rawopts
,cliopts_ = cliopts ,cliopts_ = cliopts
,querystring_ = unwords . map quoteIfNeeded $ listofstringopt "args" rawopts
} }
checkUIOpts :: UIOpts -> UIOpts checkUIOpts :: UIOpts -> UIOpts
@ -94,4 +97,3 @@ getHledgerUIOpts = do
let args' = replaceNumericFlags args let args' = replaceNumericFlags args
let cmdargopts = either usageError id $ process uimode args' let cmdargopts = either usageError id $ process uimode args'
rawOptsToUIOpts cmdargopts rawOptsToUIOpts cmdargopts

View File

@ -8,10 +8,11 @@ module Hledger.UI.UIState
where where
import Brick.Widgets.Edit 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.Text.Zipper (gotoEOL)
import Data.Time.Calendar (Day) import Data.Time.Calendar (Day)
import Data.Maybe (fromMaybe)
import Hledger import Hledger
import Hledger.Cli.CliOptions import Hledger.Cli.CliOptions
@ -239,7 +240,8 @@ resetReportPeriod = setReportPeriod PeriodAll
-- | Apply a new filter query. -- | Apply a new filter query.
setFilter :: String -> UIState -> UIState setFilter :: String -> UIState -> UIState
setFilter s ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} = setFilter s ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} =
ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{query_=s}}}} ui{aopts=uopts{cliopts_=copts{reportopts_=ropts{query_=q}},querystring_=s}}
where q = either (const None) fst . parseQuery undefined $ T.pack s
-- | Reset some filters & toggles. -- | Reset some filters & toggles.
resetFilter :: UIState -> UIState resetFilter :: UIState -> UIState
@ -248,7 +250,7 @@ resetFilter ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=rop
empty_=True empty_=True
,statuses_=[] ,statuses_=[]
,real_=False ,real_=False
,query_="" ,query_=Any
--,period_=PeriodAll --,period_=PeriodAll
}}}} }}}}
@ -305,7 +307,7 @@ showMinibuffer :: UIState -> UIState
showMinibuffer ui = setMode (Minibuffer e) ui showMinibuffer ui = setMode (Minibuffer e) ui
where where
e = applyEdit gotoEOL $ editor MinibufferEditor (Just 1) oldq e = applyEdit gotoEOL $ editor MinibufferEditor (Just 1) oldq
oldq = query_ $ reportopts_ $ cliopts_ $ aopts ui oldq = querystring_ $ aopts ui
-- | Close the minibuffer, discarding any edit in progress. -- | Close the minibuffer, discarding any edit in progress.
closeMinibuffer :: UIState -> UIState closeMinibuffer :: UIState -> UIState

View File

@ -130,7 +130,7 @@ instance Yesod App where
} }
accounts = accounts =
balanceReportAsHtml (JournalR, RegisterR) here hideEmptyAccts j q qopts $ balanceReportAsHtml (JournalR, RegisterR) here hideEmptyAccts j q qopts $
balanceReport ropts' m j balanceReport ropts'{query_=m} j
topShowmd = if showSidebar then "col-md-4" else "col-any-0" :: Text topShowmd = if showSidebar then "col-md-4" else "col-any-0" :: Text
topShowsm = if showSidebar then "col-sm-4" else "" :: Text topShowsm = if showSidebar then "col-sm-4" else "" :: Text
@ -265,7 +265,7 @@ getCurrentJournal jref opts d = do
j <- liftIO (readIORef jref) j <- liftIO (readIORef jref)
(ej, changed) <- liftIO $ journalReloadIfChanged opts d j (ej, changed) <- liftIO $ journalReloadIfChanged opts d j
-- re-apply any initial filter specified at startup -- re-apply any initial filter specified at startup
let initq = queryFromOpts d (reportopts_ opts) let initq = query_ $ reportopts_ opts
case (changed, filterJournalTransactions initq <$> ej) of case (changed, filterJournalTransactions initq <$> ej) of
(False, _) -> return (j, Nothing) (False, _) -> return (j, Nothing)
(True, Right j') -> do (True, Right j') -> do

View File

@ -58,8 +58,7 @@ runWith opts
-- | The web command. -- | The web command.
web :: WebOpts -> Journal -> IO () web :: WebOpts -> Journal -> IO ()
web opts j = do web opts j = do
d <- getCurrentDay let initq = query_ . reportopts_ $ cliopts_ opts
let initq = queryFromOpts d $ reportopts_ $ cliopts_ opts
j' = filterJournalTransactions initq j j' = filterJournalTransactions initq j
h = host_ opts h = host_ opts
p = port_ opts p = port_ opts