ui: add --present/--future, hide future txns by default, toggle with F

You may have transactions dated later than today, perhaps piped from
print --forecast or recorded in the journal, which you don't want to
see except when forecasting.

By default, we now hide future transactions, showing "today's balance".
This can be toggled with the F key, which is easier than setting a
date query. --present and --future flags have been added to set the
initial mode.

(Experimental. Interactions with date queries have not been explored.)
This commit is contained in:
Simon Michael 2018-10-15 15:11:22 -07:00
parent e52430bd62
commit 1db9b018f1
6 changed files with 70 additions and 13 deletions

View File

@ -23,7 +23,7 @@ import Data.Maybe
import Data.Monoid
#endif
import qualified Data.Text as T
import Data.Time.Calendar (Day)
import Data.Time.Calendar (Day, addDays)
import qualified Data.Vector as V
import Graphics.Vty (Event(..),Key(..),Modifier(..))
import Lens.Micro.Platform
@ -82,7 +82,10 @@ asInit d reset ui@UIState{
uopts' = uopts{cliopts_=copts{reportopts_=ropts'}}
ropts' = ropts{accountlistmode_=if tree_ ropts then ALTree else ALFlat}
q = queryFromOpts d ropts
pfq | presentorfuture_ uopts == PFFuture = Any
| otherwise = Date $ DateSpan Nothing (Just $ addDays 1 d)
q = And [queryFromOpts d ropts, pfq]
-- run the report
(items,_total) = report ropts' q j
@ -116,7 +119,7 @@ asInit d reset ui@UIState{
asInit _ _ _ = error "init function called with wrong screen type, should not happen"
asDraw :: UIState -> [Widget Name]
asDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
asDraw UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
,ajournal=j
,aScreen=s@AccountsScreen{}
,aMode=mode
@ -223,6 +226,10 @@ asDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
,if tree_ ropts
then str "flat/" <+> selectedstr "tree"
else selectedstr "flat" <+> str "/tree")
,("F"
,if presentorfuture_ uopts == PFFuture
then str "present/" <+> selectedstr "future"
else selectedstr "present" <+> str "/future")
,("-+", str "depth")
--,("/", "filter")
--,("DEL", "unfilter")
@ -338,6 +345,7 @@ asHandle ui0@UIState{
VtyEvent (EvKey (KChar 'U') []) -> asCenterAndContinue $ regenerateScreens j d $ toggleUnmarked ui
VtyEvent (EvKey (KChar 'P') []) -> asCenterAndContinue $ regenerateScreens j d $ togglePending ui
VtyEvent (EvKey (KChar 'C') []) -> asCenterAndContinue $ regenerateScreens j d $ toggleCleared ui
VtyEvent (EvKey (KChar 'F') []) -> asCenterAndContinue $ regenerateScreens j d $ toggleFuture ui
VtyEvent (EvKey (KDown) [MShift]) -> continue $ regenerateScreens j d $ shrinkReportPeriod d ui
VtyEvent (EvKey (KUp) [MShift]) -> continue $ regenerateScreens j d $ growReportPeriod d ui

View File

@ -59,7 +59,7 @@ rsSetAccount a forceinclusive scr@RegisterScreen{} =
rsSetAccount _ _ scr = scr
rsInit :: Day -> Bool -> UIState -> UIState
rsInit d reset ui@UIState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}, ajournal=j, aScreen=s@RegisterScreen{..}} =
rsInit d reset ui@UIState{aopts=uopts@UIOpts{cliopts_=CliOpts{reportopts_=ropts}}, ajournal=j, aScreen=s@RegisterScreen{..}} =
ui{aScreen=s{rsList=newitems'}}
where
-- gather arguments and queries
@ -69,7 +69,9 @@ rsInit d reset ui@UIState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}, ajo
ropts' = ropts{
depth_=Nothing
}
q = queryFromOpts d ropts'
pfq | presentorfuture_ uopts == PFFuture = Any
| otherwise = Date $ DateSpan Nothing (Just $ addDays 1 d)
q = And [queryFromOpts d ropts', pfq]
-- reportq = filterQuery (not . queryIsDepth) q
(_label,items) = accountTransactionsReport ropts' j q thisacctq
@ -131,7 +133,7 @@ rsInit d reset ui@UIState{aopts=UIOpts{cliopts_=CliOpts{reportopts_=ropts}}, ajo
rsInit _ _ _ = error "init function called with wrong screen type, should not happen"
rsDraw :: UIState -> [Widget Name]
rsDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
rsDraw UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
,aScreen=RegisterScreen{..}
,aMode=mode
} =
@ -235,8 +237,12 @@ rsDraw UIState{aopts=UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}
else str "historical/" <+> selectedstr "period")
,("T"
,if inclusive
then str "this/" <+> selectedstr "+subs"
else selectedstr "this" <+> str "/+subs")
then str "flat/" <+> selectedstr "tree"
else selectedstr "flat" <+> str "/tree")
,("F"
,if presentorfuture_ uopts == PFFuture
then str "present/" <+> selectedstr "future"
else selectedstr "present" <+> str "/future")
-- ,("a", "add")
-- ,("g", "reload")
-- ,("q", "quit")
@ -329,6 +335,7 @@ rsHandle ui@UIState{
VtyEvent (EvKey (KChar 'U') []) -> rsCenterAndContinue $ regenerateScreens j d $ toggleUnmarked ui
VtyEvent (EvKey (KChar 'P') []) -> rsCenterAndContinue $ regenerateScreens j d $ togglePending ui
VtyEvent (EvKey (KChar 'C') []) -> rsCenterAndContinue $ regenerateScreens j d $ toggleCleared ui
VtyEvent (EvKey (KChar 'F') []) -> rsCenterAndContinue $ regenerateScreens j d $ toggleFuture ui
VtyEvent (EvKey (KChar '/') []) -> continue $ regenerateScreens j d $ showMinibuffer ui
VtyEvent (EvKey (KDown) [MShift]) -> continue $ regenerateScreens j d $ shrinkReportPeriod d ui

View File

@ -1,11 +1,14 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-|
-}
module Hledger.UI.UIOptions
where
import Data.Data (Data)
import Data.Default
import Data.Typeable (Typeable)
import Data.List (intercalate)
import System.Environment
@ -35,6 +38,8 @@ uiflags = [
-- "show historical ending balance in each period (includes postings before report start date)\n "
,flagNone ["flat","F"] (\opts -> setboolopt "flat" opts) "show full account names, unindented (default)"
,flagNone ["tree","T"] (\opts -> setboolopt "tree" opts) "show accounts as a tree"
,flagNone ["present"] (\opts -> setboolopt "present" opts) "exclude transactions dated later than today (default)"
,flagNone ["future"] (\opts -> setboolopt "future" opts) "include transactions dated later than today"
-- ,flagReq ["drop"] (\s opts -> Right $ setopt "drop" s opts) "N" "with --flat, omit this many leading account name components"
-- ,flagReq ["format"] (\s opts -> Right $ setopt "format" s opts) "FORMATSTR" "use this custom line format"
-- ,flagNone ["no-elide"] (\opts -> setboolopt "no-elide" opts) "don't compress empty parent accounts on one line"
@ -67,6 +72,7 @@ uimode = (mode "hledger-ui" [("command","ui")]
data UIOpts = UIOpts {
watch_ :: Bool
,change_ :: Bool
,presentorfuture_ :: PresentOrFutureOpt
,cliopts_ :: CliOpts
} deriving (Show)
@ -74,6 +80,7 @@ defuiopts = UIOpts
def
def
def
def
-- instance Default CliOpts where def = defcliopts
@ -83,9 +90,22 @@ rawOptsToUIOpts rawopts = checkUIOpts <$> do
return defuiopts {
watch_ = boolopt "watch" rawopts
,change_ = boolopt "change" rawopts
,presentorfuture_ = presentorfutureopt rawopts
,cliopts_ = cliopts
}
-- | Should transactions dated later than today be included ?
-- Like flat/tree mode, there are three states, and the meaning of default can vary by command.
data PresentOrFutureOpt = PFDefault | PFPresent | PFFuture deriving (Eq, Show, Data, Typeable)
instance Default PresentOrFutureOpt where def = PFDefault
presentorfutureopt :: RawOpts -> PresentOrFutureOpt
presentorfutureopt rawopts =
case reverse $ filter (`elem` ["present","future"]) $ map fst rawopts of
("present":_) -> PFPresent
("future":_) -> PFFuture
_ -> PFDefault
checkUIOpts :: UIOpts -> UIOpts
checkUIOpts opts =
either usageError (const opts) $ do

View File

@ -124,6 +124,14 @@ toggleHistorical ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts
b | balancetype_ ropts == HistoricalBalance = PeriodChange
| otherwise = HistoricalBalance
-- | Toggle between including and excluding transactions dated later than today.
toggleFuture :: UIState -> UIState
toggleFuture ui@UIState{aopts=uopts@UIOpts{presentorfuture_=pf}} =
ui{aopts=uopts{presentorfuture_=pf'}}
where
pf' | pf == PFFuture = PFPresent
| otherwise = PFFuture
-- | 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}}} =

View File

@ -92,6 +92,7 @@ helpDialog copts =
,"cycle cleared/not cleared/all"
,"toggle cleared filter"
] !! (statusstyle-1))
,renderKey ("F", "toggle future/present")
,renderKey ("R", "toggle real/all")
,renderKey ("Z", "toggle nonzero/all")
,renderKey ("DEL/BS", "remove filters")

View File

@ -44,6 +44,7 @@ hledger-ui is hledger's curses-style interface, providing an efficient full-wind
for viewing accounts and transactions, and some limited data entry capability.
It is easier than hledger's command-line interface, and
sometimes quicker and more convenient than the web interface.
Note hledger-ui hides transactions dated in the future, by default.
Like hledger, it reads _files_
For more about this see hledger(1), hledger_journal(5) etc.
@ -72,7 +73,13 @@ Any QUERYARGS are interpreted as a hledger search query which filters the data.
`-T --tree`
: show accounts as a tree
hledger input options:
`--present`
: exclude transactions dated later than today (default) (experimental)
`--future`
: include transactions dated later than today (experimental)
hledger input options:
_inputoptions_
@ -122,6 +129,12 @@ 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 transactions.
As mentioned above, hledger-ui hides transactions in the future by default.
`F` toggles showing and hiding these future transactions.
This is similar to using a query like `date:-tomorrow`, but more convenient.
(experimental)
`ESCAPE` removes all filters and jumps back to the top screen.
Or, it cancels a minibuffer edit or help dialog in progress.
@ -211,10 +224,10 @@ Similar to the accounts screen, the historical total is affected by transactions
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 shown if
the accounts screen was in tree mode,
or if it was in flat mode but the selected account had depth-clipped subaccounts.
In other words, the register always shows just the transactions contributing to the balance on the accounts screen.
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 flat 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/flat mode can be toggled with `T` here also.
`U` toggles filtering by [unmarked status](/journal.html#status), showing or hiding unmarked transactions.