hledger-ui 1.19.1 → 1.20
raw patch · 13 files changed
+415/−356 lines, 13 filesdep −pretty-showdep ~hledgerdep ~hledger-lib
Dependencies removed: pretty-show
Dependency ranges changed: hledger, hledger-lib
Files
- CHANGES.md +17/−0
- Hledger/UI/AccountsScreen.hs +10/−11
- Hledger/UI/Editor.hs +47/−42
- Hledger/UI/Main.hs +52/−32
- Hledger/UI/RegisterScreen.hs +19/−19
- Hledger/UI/TransactionScreen.hs +12/−16
- Hledger/UI/UIOptions.hs +10/−10
- Hledger/UI/UIState.hs +93/−81
- Hledger/UI/UITypes.hs +2/−2
- hledger-ui.1 +4/−1
- hledger-ui.cabal +5/−6
- hledger-ui.info +26/−22
- hledger-ui.txt +118/−114
CHANGES.md view
@@ -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
Hledger/UI/AccountsScreen.hs view
@@ -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 -> "-"
Hledger/UI/Editor.hs view
@@ -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
Hledger/UI/Main.hs view
@@ -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) $
Hledger/UI/RegisterScreen.hs view
@@ -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
Hledger/UI/TransactionScreen.hs view
@@ -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
Hledger/UI/UIOptions.hs view
@@ -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-
Hledger/UI/UIState.hs view
@@ -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
Hledger/UI/UITypes.hs view
@@ -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)
hledger-ui.1 view
@@ -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
hledger-ui.cabal view
@@ -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
hledger-ui.info view
@@ -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: Top71-Node: OPTIONS1476-Ref: #options1573-Node: keys5545-Ref: #keys5640-Node: screens9972-Ref: #screens10077-Node: accounts screen10167-Ref: #accounts-screen10295-Node: Register screen12510-Ref: #register-screen12665-Node: Transaction screen14662-Ref: #transaction-screen14820-Node: Error screen15690-Ref: #error-screen15812-Node: ENVIRONMENT16056-Ref: #environment16170-Node: FILES16977-Ref: #files17076-Node: BUGS17289-Ref: #bugs17366+Node: OPTIONS1470+Ref: #options1567+Node: keys5634+Ref: #keys5729+Node: screens10061+Ref: #screens10166+Node: accounts screen10256+Ref: #accounts-screen10384+Node: Register screen12599+Ref: #register-screen12754+Node: Transaction screen14751+Ref: #transaction-screen14909+Node: Error screen15779+Ref: #error-screen15901+Node: ENVIRONMENT16145+Ref: #environment16259+Node: FILES17066+Ref: #files17165+Node: BUGS17378+Ref: #bugs17455 End Tag Table
hledger-ui.txt view
@@ -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)