diff --git a/hledger-ui/Hledger/UI/AccountsScreen.hs b/hledger-ui/Hledger/UI/AccountsScreen.hs index cac7a5c77..4a26f385d 100644 --- a/hledger-ui/Hledger/UI/AccountsScreen.hs +++ b/hledger-ui/Hledger/UI/AccountsScreen.hs @@ -83,12 +83,13 @@ asInit d reset ui@UIState{ uopts' = uopts{cliopts_=copts{reportopts_=ropts'}} ropts' = ropts{accountlistmode_=if tree_ ropts then ALTree else ALFlat} - -- Add a date:-tomorrow to the query to exclude future txns, by default. - -- XXX this necessitates special handling in multiBalanceReport, at least - pfq | presentorfuture_ uopts == PFFuture = Any - | otherwise = Date $ DateSpan Nothing (Just $ addDays 1 d) - q = And [queryFromOpts d ropts, pfq] - + q = And [queryFromOpts d ropts + -- Exclude future transactions except in forecast mode + -- XXX this necessitates special handling in multiBalanceReport, at least + ,if forecast_ ropts + then Any + else Date $ DateSpan Nothing (Just $ addDays 1 d) + ] -- run the report (items,_total) = report ropts' q j @@ -123,7 +124,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=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} +asDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} ,ajournal=j ,aScreen=s@AccountsScreen{} ,aMode=mode @@ -215,7 +216,7 @@ asDraw UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} ,("-+", str "depth") ,("T", renderToggle (tree_ ropts) "flat" "tree") ,("H", renderToggle (not ishistorical) "end-bals" "changes") - ,("F", renderToggle (presentorfuture_ uopts == PFFuture) "present" "future") + ,("F", renderToggle1 (forecast_ ropts) "forecast") --,("/", "filter") --,("DEL", "unfilter") --,("ESC", "cancel/top") @@ -336,7 +337,9 @@ 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 (KChar 'F') []) -> + let ui'@UIState{aopts=UIOpts{cliopts_=copts'}} = toggleForecast ui + in liftIO (uiReloadJournal copts' d ui') >>= continue VtyEvent (EvKey (KDown) [MShift]) -> continue $ regenerateScreens j d $ shrinkReportPeriod d ui VtyEvent (EvKey (KUp) [MShift]) -> continue $ regenerateScreens j d $ growReportPeriod d ui diff --git a/hledger-ui/Hledger/UI/Main.hs b/hledger-ui/Hledger/UI/Main.hs index 62bac3e06..102d0b3f5 100644 --- a/hledger-ui/Hledger/UI/Main.hs +++ b/hledger-ui/Hledger/UI/Main.hs @@ -63,14 +63,8 @@ writeChan = BC.writeBChan main :: IO () main = do opts <- getHledgerUIOpts - let copts = cliopts_ opts - copts' = copts - { inputopts_ = (inputopts_ copts) { auto_ = True } - , reportopts_ = (reportopts_ copts) { forecast_ = True } - } - -- when (debug_ $ cliopts_ opts) $ printf "%s\n" prognameandversion >> printf "opts: %s\n" (show opts) - run $ opts { cliopts_ = copts' } + run opts where run opts | "help" `inRawOpts` (rawopts_ $ cliopts_ opts) = putStr (showModeUsage uimode) >> exitSuccess diff --git a/hledger-ui/Hledger/UI/RegisterScreen.hs b/hledger-ui/Hledger/UI/RegisterScreen.hs index b1b54028c..cee71152b 100644 --- a/hledger-ui/Hledger/UI/RegisterScreen.hs +++ b/hledger-ui/Hledger/UI/RegisterScreen.hs @@ -59,7 +59,7 @@ rsSetAccount a forceinclusive scr@RegisterScreen{} = 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{reportopts_=ropts}}, ajournal=j, aScreen=s@RegisterScreen{..}} = ui{aScreen=s{rsList=newitems'}} where -- gather arguments and queries @@ -69,9 +69,13 @@ rsInit d reset ui@UIState{aopts=uopts@UIOpts{cliopts_=CliOpts{reportopts_=ropts} ropts' = ropts{ depth_=Nothing } - pfq | presentorfuture_ uopts == PFFuture = Any - | otherwise = Date $ DateSpan Nothing (Just $ addDays 1 d) - q = And [queryFromOpts d ropts', pfq] + q = And [queryFromOpts d ropts' + -- Exclude future transactions except in forecast mode + -- XXX this necessitates special handling in multiBalanceReport, at least + ,if forecast_ ropts + then Any + else Date $ DateSpan Nothing (Just $ addDays 1 d) + ] -- reportq = filterQuery (not . queryIsDepth) q (_label,items) = accountTransactionsReport ropts' j q thisacctq @@ -133,7 +137,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" rsDraw :: UIState -> [Widget Name] -rsDraw UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} +rsDraw UIState{aopts=_uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} ,aScreen=RegisterScreen{..} ,aMode=mode } = @@ -232,7 +236,7 @@ rsDraw UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}} -- ,("RIGHT", str "transaction") ,("T", renderToggle (tree_ ropts) "flat(-subs)" "tree(+subs)") -- rsForceInclusive may override, but use tree_ to ensure a visible toggle effect ,("H", renderToggle (not ishistorical) "historical" "period") - ,("F", renderToggle (presentorfuture_ uopts == PFFuture) "present" "future") + ,("F", renderToggle1 (forecast_ ropts) "forecast") -- ,("a", "add") -- ,("g", "reload") -- ,("q", "quit") @@ -331,7 +335,9 @@ 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 'F') []) -> + let ui'@UIState{aopts=UIOpts{cliopts_=copts'}} = toggleForecast ui + in liftIO (uiReloadJournal copts' d ui') >>= rsCenterAndContinue VtyEvent (EvKey (KChar '/') []) -> continue $ regenerateScreens j d $ showMinibuffer ui VtyEvent (EvKey (KDown) [MShift]) -> continue $ regenerateScreens j d $ shrinkReportPeriod d ui diff --git a/hledger-ui/Hledger/UI/UIOptions.hs b/hledger-ui/Hledger/UI/UIOptions.hs index e136ec1fe..e1826a29a 100644 --- a/hledger-ui/Hledger/UI/UIOptions.hs +++ b/hledger-ui/Hledger/UI/UIOptions.hs @@ -7,11 +7,8 @@ module Hledger.UI.UIOptions where -import Data.Data (Data) import Data.Default -import Data.Typeable (Typeable) import Data.List (intercalate) -import Data.Maybe (fromMaybe) import System.Environment import Hledger.Cli hiding (progname,version,prognameandversion) @@ -41,7 +38,6 @@ uiflags = [ ,flagNone ["flat","F"] (setboolopt "flat") "show accounts as a list (default)" ,flagNone ["tree","T"] (setboolopt "tree") "show accounts as a tree" -- ,flagNone ["present"] (setboolopt "present") "exclude transactions dated later than today (default)" - ,flagNone ["future"] (setboolopt "future") "show transactions dated later than today (normally hidden)" -- ,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"] (setboolopt "no-elide") "don't compress empty parent accounts on one line" @@ -54,6 +50,7 @@ uimode = (mode "hledger-ui" (setopt "command" "ui" def) modeGroupFlags = Group { groupUnnamed = uiflags ,groupHidden = hiddenflags + ++ [flagNone ["future"] (setboolopt "forecast") "compatibility alias, use --forecast instead"] ,groupNamed = [(generalflagsgroup1)] } ,modeHelpSuffix=[ @@ -65,7 +62,6 @@ uimode = (mode "hledger-ui" (setopt "command" "ui" def) data UIOpts = UIOpts { watch_ :: Bool ,change_ :: Bool - ,presentorfuture_ :: PresentOrFutureOpt ,cliopts_ :: CliOpts } deriving (Show) @@ -73,7 +69,6 @@ defuiopts = UIOpts def def def - def -- instance Default CliOpts where def = defcliopts @@ -83,23 +78,9 @@ 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 = - fromMaybe PFDefault . choiceopt parse where - parse = \case - "present" -> Just PFPresent - "future" -> Just PFFuture - _ -> Nothing - checkUIOpts :: UIOpts -> UIOpts checkUIOpts opts = either usageError (const opts) $ do diff --git a/hledger-ui/Hledger/UI/UIState.hs b/hledger-ui/Hledger/UI/UIState.hs index 44c412c60..a09008ea8 100644 --- a/hledger-ui/Hledger/UI/UIState.hs +++ b/hledger-ui/Hledger/UI/UIState.hs @@ -151,13 +151,24 @@ 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'}} +-- | Toggle hledger-ui's "forecast mode". In forecast mode, periodic +-- transactions (generated by periodic rules) are enabled (as with +-- hledger --forecast), and also future transactions in general +-- (including non-periodic ones) are displayed. In normal mode, all +-- future transactions (periodic or not) are suppressed (unlike +-- command-line hledger). +-- +-- After toggling this, we do a full reload of the journal from disk +-- to make it take effect; currently that's done in the callers (cf +-- AccountsScreen, RegisterScreen) where it's easier. This is +-- overkill, probably we should just hide/show the periodic +-- transactions with a query for their special tag. +-- +toggleForecast :: UIState -> UIState +toggleForecast ui@UIState{aopts=uopts@UIOpts{cliopts_=copts@CliOpts{reportopts_=ropts}}} = + ui{aopts=uopts{cliopts_=copts'}} where - pf' | pf == PFFuture = PFPresent - | otherwise = PFFuture + copts' = copts{reportopts_=ropts{forecast_=not $ forecast_ ropts}} -- | Toggle between showing all and showing only real (non-virtual) items. toggleReal :: UIState -> UIState diff --git a/hledger-ui/Hledger/UI/UIUtils.hs b/hledger-ui/Hledger/UI/UIUtils.hs index 123a5a38b..da8962890 100644 --- a/hledger-ui/Hledger/UI/UIUtils.hs +++ b/hledger-ui/Hledger/UI/UIUtils.hs @@ -19,6 +19,7 @@ module Hledger.UI.UIUtils ( ,moveUpEvents ,normaliseMovementKeys ,renderToggle + ,renderToggle1 ,replaceHiddenAccountsNameWith ,scrollSelectionToMiddle ,suspend @@ -122,7 +123,7 @@ helpDialog _copts = withAttr ("help" <> "heading") $ str "Filtering" ,renderKey ("/ ", "set a filter query") ,renderKey ("UPC ", "show unmarked/pending/cleared") - ,renderKey ("F ", "show future/present txns") + ,renderKey ("F ", "show future & periodic txns") ,renderKey ("R ", "show real/all postings") ,renderKey ("Z ", "show nonzero/all amounts") ,renderKey ("DEL ", "remove filters") @@ -210,7 +211,7 @@ borderKeysStr' keydescs = -- sep = str " | " sep = str " " --- | Render the two states of a toggle, highlighting the active one. +-- | Show both states of a toggle ("aaa/bbb"), highlighting the active one. renderToggle :: Bool -> String -> String -> Widget Name renderToggle isright l r = let bold = withAttr ("border" <> "selected") in @@ -218,6 +219,14 @@ renderToggle isright l r = then str (l++"/") <+> bold (str r) else bold (str l) <+> str ("/"++r) +-- | Show a toggle's label, highlighted (bold) when the toggle is active. +renderToggle1 :: Bool -> String -> Widget Name +renderToggle1 isactive l = + let bold = withAttr ("border" <> "selected") in + if isactive + then bold (str l) + else str l + -- temporary shenanigans: -- | Convert the special account name "*" (from balance report with depth limit 0) to something clearer. diff --git a/hledger-ui/hledger-ui.m4.md b/hledger-ui/hledger-ui.m4.md index 5784fb7c3..01a0f5012 100644 --- a/hledger-ui/hledger-ui.m4.md +++ b/hledger-ui/hledger-ui.m4.md @@ -44,14 +44,13 @@ 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 has some different defaults (experimental): - -- it generates rule-based transactions and postings by default (--forecast and --auto are always on). -- it hides transactions dated in the future by default (change this with --future or the F key). - Like hledger, it reads _files_ For more about this see hledger(1), hledger_journal(5) etc. +Unlike hledger, hledger-ui hides all future-dated transactions by default. +They can be revealed, along with any rule-generated periodic transactions, +by pressing the F key (or starting with --forecast) to enable "forecast mode". + # OPTIONS Note: if invoking hledger-ui as a hledger subcommand, write `--` before options as shown above. @@ -76,9 +75,6 @@ Any QUERYARGS are interpreted as a hledger search query which filters the data. `-T --tree` : show accounts as a tree -`--future` -: show transactions dated later than today (normally hidden) - hledger input options: _inputoptions_ @@ -129,11 +125,10 @@ 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 shows auto-generated periodic transactions, -and hides future transactions (auto-generated or not) by default. -`F` toggles showing and hiding these future transactions. -This is similar to using a query like `date:-tomorrow`, but more convenient. -(experimental) +As mentioned above, by default hledger-ui hides future transactions - +both ordinary transactions recorded in the journal, and periodic +transactions generated by rule. `F` toggles forecast mode, in which +future/forecasted transactions are shown. (experimental) `ESCAPE` removes all filters and jumps back to the top screen. Or, it cancels a minibuffer edit or help dialog in progress.