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:
		
							parent
							
								
									e52430bd62
								
							
						
					
					
						commit
						1db9b018f1
					
				| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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}}} = | ||||
|  | ||||
| @ -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") | ||||
|  | ||||
| @ -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,6 +73,12 @@ Any QUERYARGS are interpreted as a hledger search query which filters the data. | ||||
| `-T --tree` | ||||
| : show accounts as a tree | ||||
| 
 | ||||
| `--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.  | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user