Merge branch 'master' into installer
This commit is contained in:
commit
efc75db8d8
@ -19,6 +19,7 @@ module Hledger.Query (
|
|||||||
-- * accessors
|
-- * accessors
|
||||||
queryIsNull,
|
queryIsNull,
|
||||||
queryIsAcct,
|
queryIsAcct,
|
||||||
|
queryIsAmt,
|
||||||
queryIsDepth,
|
queryIsDepth,
|
||||||
queryIsDate,
|
queryIsDate,
|
||||||
queryIsDate2,
|
queryIsDate2,
|
||||||
@ -41,6 +42,8 @@ module Hledger.Query (
|
|||||||
matchesAccount,
|
matchesAccount,
|
||||||
matchesMixedAmount,
|
matchesMixedAmount,
|
||||||
matchesAmount,
|
matchesAmount,
|
||||||
|
matchesCommodity,
|
||||||
|
matchesMarketPrice,
|
||||||
words'',
|
words'',
|
||||||
-- * tests
|
-- * tests
|
||||||
tests_Hledger_Query
|
tests_Hledger_Query
|
||||||
@ -481,6 +484,10 @@ queryIsAcct :: Query -> Bool
|
|||||||
queryIsAcct (Acct _) = True
|
queryIsAcct (Acct _) = True
|
||||||
queryIsAcct _ = False
|
queryIsAcct _ = False
|
||||||
|
|
||||||
|
queryIsAmt :: Query -> Bool
|
||||||
|
queryIsAmt (Amt _ _) = True
|
||||||
|
queryIsAmt _ = False
|
||||||
|
|
||||||
queryIsSym :: Query -> Bool
|
queryIsSym :: Query -> Bool
|
||||||
queryIsSym (Sym _) = True
|
queryIsSym (Sym _) = True
|
||||||
queryIsSym _ = False
|
queryIsSym _ = False
|
||||||
@ -530,33 +537,27 @@ queryEndDate _ _ = Nothing
|
|||||||
queryTermDateSpan (Date span) = Just span
|
queryTermDateSpan (Date span) = Just span
|
||||||
queryTermDateSpan _ = Nothing
|
queryTermDateSpan _ = Nothing
|
||||||
|
|
||||||
-- | What date span (or secondary date span) does this query specify ?
|
-- | What date span (or with a true argument, what secondary date span) does this query specify ?
|
||||||
-- For OR expressions, use the widest possible span. NOT is ignored.
|
-- OR clauses specifying multiple spans return their union (the span enclosing all of them).
|
||||||
|
-- AND clauses specifying multiple spans return their intersection.
|
||||||
|
-- NOT clauses are ignored.
|
||||||
queryDateSpan :: Bool -> Query -> DateSpan
|
queryDateSpan :: Bool -> Query -> DateSpan
|
||||||
queryDateSpan secondary q = spansUnion $ queryDateSpans secondary q
|
queryDateSpan secondary (Or qs) = spansUnion $ map (queryDateSpan secondary) qs
|
||||||
|
queryDateSpan secondary (And qs) = spansIntersect $ map (queryDateSpan secondary) qs
|
||||||
|
queryDateSpan False (Date span) = span
|
||||||
|
queryDateSpan True (Date2 span) = span
|
||||||
|
queryDateSpan _ _ = nulldatespan
|
||||||
|
|
||||||
-- | Extract all date (or secondary date) spans specified in this query.
|
-- | What date span does this query specify, treating primary and secondary dates as equivalent ?
|
||||||
-- NOT is ignored.
|
-- OR clauses specifying multiple spans return their union (the span enclosing all of them).
|
||||||
queryDateSpans :: Bool -> Query -> [DateSpan]
|
-- AND clauses specifying multiple spans return their intersection.
|
||||||
queryDateSpans secondary (Or qs) = concatMap (queryDateSpans secondary) qs
|
-- NOT clauses are ignored.
|
||||||
queryDateSpans secondary (And qs) = concatMap (queryDateSpans secondary) qs
|
|
||||||
queryDateSpans False (Date span) = [span]
|
|
||||||
queryDateSpans True (Date2 span) = [span]
|
|
||||||
queryDateSpans _ _ = []
|
|
||||||
|
|
||||||
-- | What date span (or secondary date span) does this query specify ?
|
|
||||||
-- For OR expressions, use the widest possible span. NOT is ignored.
|
|
||||||
queryDateSpan' :: Query -> DateSpan
|
queryDateSpan' :: Query -> DateSpan
|
||||||
queryDateSpan' q = spansUnion $ queryDateSpans' q
|
queryDateSpan' (Or qs) = spansUnion $ map queryDateSpan' qs
|
||||||
|
queryDateSpan' (And qs) = spansIntersect $ map queryDateSpan' qs
|
||||||
-- | Extract all date (or secondary date) spans specified in this query.
|
queryDateSpan' (Date span) = span
|
||||||
-- NOT is ignored.
|
queryDateSpan' (Date2 span) = span
|
||||||
queryDateSpans' :: Query -> [DateSpan]
|
queryDateSpan' _ = nulldatespan
|
||||||
queryDateSpans' (Or qs) = concatMap queryDateSpans' qs
|
|
||||||
queryDateSpans' (And qs) = concatMap queryDateSpans' qs
|
|
||||||
queryDateSpans' (Date span) = [span]
|
|
||||||
queryDateSpans' (Date2 span) = [span]
|
|
||||||
queryDateSpans' _ = []
|
|
||||||
|
|
||||||
-- | What is the earliest of these dates, where Nothing is latest ?
|
-- | What is the earliest of these dates, where Nothing is latest ?
|
||||||
earliestMaybeDate :: [Maybe Day] -> Maybe Day
|
earliestMaybeDate :: [Maybe Day] -> Maybe Day
|
||||||
@ -641,6 +642,10 @@ matchesMixedAmount :: Query -> MixedAmount -> Bool
|
|||||||
matchesMixedAmount q (Mixed []) = q `matchesAmount` nullamt
|
matchesMixedAmount q (Mixed []) = q `matchesAmount` nullamt
|
||||||
matchesMixedAmount q (Mixed as) = any (q `matchesAmount`) as
|
matchesMixedAmount q (Mixed as) = any (q `matchesAmount`) as
|
||||||
|
|
||||||
|
matchesCommodity :: Query -> CommoditySymbol -> Bool
|
||||||
|
matchesCommodity (Sym r) s = regexMatchesCI ("^" ++ r ++ "$") (T.unpack s)
|
||||||
|
matchesCommodity _ _ = True
|
||||||
|
|
||||||
-- | Does the match expression match this (simple) amount ?
|
-- | Does the match expression match this (simple) amount ?
|
||||||
matchesAmount :: Query -> Amount -> Bool
|
matchesAmount :: Query -> Amount -> Bool
|
||||||
matchesAmount (Not q) a = not $ q `matchesAmount` a
|
matchesAmount (Not q) a = not $ q `matchesAmount` a
|
||||||
@ -650,7 +655,7 @@ matchesAmount (Or qs) a = any (`matchesAmount` a) qs
|
|||||||
matchesAmount (And qs) a = all (`matchesAmount` a) qs
|
matchesAmount (And qs) a = all (`matchesAmount` a) qs
|
||||||
--
|
--
|
||||||
matchesAmount (Amt ord n) a = compareAmount ord n a
|
matchesAmount (Amt ord n) a = compareAmount ord n a
|
||||||
matchesAmount (Sym r) a = regexMatchesCI ("^" ++ r ++ "$") $ T.unpack $ acommodity a
|
matchesAmount (Sym r) a = matchesCommodity (Sym r) (acommodity a)
|
||||||
--
|
--
|
||||||
matchesAmount _ _ = True
|
matchesAmount _ _ = True
|
||||||
|
|
||||||
@ -694,7 +699,7 @@ matchesPosting q@(Amt _ _) Posting{pamount=amt} = q `matchesMixedAmount` amt
|
|||||||
-- matchesPosting (Empty False) Posting{pamount=a} = True
|
-- matchesPosting (Empty False) Posting{pamount=a} = True
|
||||||
-- matchesPosting (Empty True) Posting{pamount=a} = isZeroMixedAmount a
|
-- matchesPosting (Empty True) Posting{pamount=a} = isZeroMixedAmount a
|
||||||
matchesPosting (Empty _) _ = True
|
matchesPosting (Empty _) _ = True
|
||||||
matchesPosting (Sym r) Posting{pamount=Mixed as} = any (regexMatchesCI $ "^" ++ r ++ "$") $ map (T.unpack . acommodity) as
|
matchesPosting (Sym r) Posting{pamount=Mixed as} = any (matchesCommodity (Sym r)) $ map acommodity as
|
||||||
matchesPosting (Tag n v) p = case (n, v) of
|
matchesPosting (Tag n v) p = case (n, v) of
|
||||||
("payee", Just v) -> maybe False (regexMatchesCI v . T.unpack . transactionPayee) $ ptransaction p
|
("payee", Just v) -> maybe False (regexMatchesCI v . T.unpack . transactionPayee) $ ptransaction p
|
||||||
("note", Just v) -> maybe False (regexMatchesCI v . T.unpack . transactionNote) $ ptransaction p
|
("note", Just v) -> maybe False (regexMatchesCI v . T.unpack . transactionNote) $ ptransaction p
|
||||||
@ -777,6 +782,18 @@ matchesTags namepat valuepat = not . null . filter (match namepat valuepat)
|
|||||||
match npat Nothing (n,_) = regexMatchesCI npat (T.unpack n) -- XXX
|
match npat Nothing (n,_) = regexMatchesCI npat (T.unpack n) -- XXX
|
||||||
match npat (Just vpat) (n,v) = regexMatchesCI npat (T.unpack n) && regexMatchesCI vpat (T.unpack v)
|
match npat (Just vpat) (n,v) = regexMatchesCI npat (T.unpack n) && regexMatchesCI vpat (T.unpack v)
|
||||||
|
|
||||||
|
-- | Does the query match this market price ?
|
||||||
|
matchesMarketPrice :: Query -> MarketPrice -> Bool
|
||||||
|
matchesMarketPrice (None) _ = False
|
||||||
|
matchesMarketPrice (Not q) p = not $ matchesMarketPrice q p
|
||||||
|
matchesMarketPrice (Or qs) p = any (`matchesMarketPrice` p) qs
|
||||||
|
matchesMarketPrice (And qs) p = all (`matchesMarketPrice` p) qs
|
||||||
|
matchesMarketPrice q@(Amt _ _) p = matchesAmount q (mpamount p)
|
||||||
|
matchesMarketPrice q@(Sym _) p = matchesCommodity q (mpcommodity p)
|
||||||
|
matchesMarketPrice (Date span) p = spanContainsDate span (mpdate p)
|
||||||
|
matchesMarketPrice _ _ = True
|
||||||
|
|
||||||
|
|
||||||
-- tests
|
-- tests
|
||||||
|
|
||||||
tests_Hledger_Query :: Test
|
tests_Hledger_Query :: Test
|
||||||
|
|||||||
@ -17,28 +17,34 @@ import System.Console.CmdArgs.Explicit
|
|||||||
|
|
||||||
pricesmode = hledgerCommandMode
|
pricesmode = hledgerCommandMode
|
||||||
[here| prices
|
[here| prices
|
||||||
Print all market prices from the journal.
|
Print market price directives from the journal.
|
||||||
|
With --costs, also print synthetic market prices based on transaction prices.
|
||||||
|
With --inverted-costs, also print inverse prices based on transaction prices.
|
||||||
|
Prices (and postings providing prices) can be filtered by a query.
|
||||||
|]
|
|]
|
||||||
[flagNone ["costs"] (setboolopt "costs") "print transaction prices from postings"
|
[flagNone ["costs"] (setboolopt "costs") "print transaction prices from postings"
|
||||||
,flagNone ["inverted-costs"] (setboolopt "inverted-costs") "print transaction inverted prices from postings also"]
|
,flagNone ["inverted-costs"] (setboolopt "inverted-costs") "print transaction inverted prices from postings also"]
|
||||||
[generalflagsgroup1]
|
[generalflagsgroup1]
|
||||||
[]
|
[]
|
||||||
([], Nothing)
|
([], Just $ argsFlag "[QUERY]")
|
||||||
|
|
||||||
prices opts j = do
|
|
||||||
-- XXX the original hledger-prices script always ignored assertions
|
-- XXX the original hledger-prices script always ignored assertions
|
||||||
let cprices = concatMap postingCosts . allPostings $ j
|
prices opts j = do
|
||||||
icprices = concatMap postingCosts . mapAmount invertPrice . allPostings $ j
|
d <- getCurrentDay
|
||||||
printPrices = mapM_ (putStrLn . showPrice)
|
let
|
||||||
forBoolOpt opt | boolopt opt $ rawopts_ opts = id
|
q = queryFromOpts d (reportopts_ opts)
|
||||||
|
ps = filter (matchesPosting q) $ allPostings j
|
||||||
|
mprices = jmarketprices j
|
||||||
|
cprices = concatMap postingCosts ps
|
||||||
|
icprices = concatMap postingCosts . mapAmount invertPrice $ ps
|
||||||
|
allprices = mprices ++ ifBoolOpt "costs" cprices ++ ifBoolOpt "inverted-costs" icprices
|
||||||
|
mapM_ (putStrLn . showPrice) $
|
||||||
|
sortOn mpdate $
|
||||||
|
filter (matchesMarketPrice q) $
|
||||||
|
allprices
|
||||||
|
where
|
||||||
|
ifBoolOpt opt | boolopt opt $ rawopts_ opts = id
|
||||||
| otherwise = const []
|
| otherwise = const []
|
||||||
allPrices = sortOn mpdate . concat $
|
|
||||||
[ jmarketprices j
|
|
||||||
, forBoolOpt "costs" cprices
|
|
||||||
, forBoolOpt "inverted-costs" icprices
|
|
||||||
]
|
|
||||||
|
|
||||||
printPrices allPrices
|
|
||||||
|
|
||||||
showPrice :: MarketPrice -> String
|
showPrice :: MarketPrice -> String
|
||||||
showPrice mp = unwords ["P", show $ mpdate mp, T.unpack . quoteCommoditySymbolIfNeeded $ mpcommodity mp, showAmountWithZeroCommodity $ mpamount mp]
|
showPrice mp = unwords ["P", show $ mpdate mp, T.unpack . quoteCommoditySymbolIfNeeded $ mpcommodity mp, showAmountWithZeroCommodity $ mpamount mp]
|
||||||
|
|||||||
@ -2426,7 +2426,12 @@ This command also supports output destination and output format
|
|||||||
selection.
|
selection.
|
||||||
.SS prices
|
.SS prices
|
||||||
.PP
|
.PP
|
||||||
Print all market prices from the journal.
|
Print market price directives from the journal.
|
||||||
|
With \[en]costs, also print synthetic market prices based on transaction
|
||||||
|
prices.
|
||||||
|
With \[en]inverted\-costs, also print inverse prices based on
|
||||||
|
transaction prices.
|
||||||
|
Prices (and postings providing prices) can be filtered by a query.
|
||||||
.SS print
|
.SS print
|
||||||
.PP
|
.PP
|
||||||
Show transactions from the journal.
|
Show transactions from the journal.
|
||||||
|
|||||||
@ -1921,7 +1921,10 @@ File: hledger.info, Node: prices, Next: print, Prev: incomestatement, Up: CO
|
|||||||
4.14 prices
|
4.14 prices
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Print all market prices from the journal.
|
Print market price directives from the journal. With -costs, also print
|
||||||
|
synthetic market prices based on transaction prices. With
|
||||||
|
-inverted-costs, also print inverse prices based on transaction prices.
|
||||||
|
Prices (and postings providing prices) can be filtered by a query.
|
||||||
|
|
||||||
|
|
||||||
File: hledger.info, Node: print, Next: print-unique, Prev: prices, Up: COMMANDS
|
File: hledger.info, Node: print, Next: print-unique, Prev: prices, Up: COMMANDS
|
||||||
@ -2520,51 +2523,51 @@ Node: incomestatement61310
|
|||||||
Ref: #incomestatement61444
|
Ref: #incomestatement61444
|
||||||
Node: prices63848
|
Node: prices63848
|
||||||
Ref: #prices63963
|
Ref: #prices63963
|
||||||
Node: print64006
|
Node: print64235
|
||||||
Ref: #print64116
|
Ref: #print64345
|
||||||
Node: print-unique69010
|
Node: print-unique69239
|
||||||
Ref: #print-unique69136
|
Ref: #print-unique69365
|
||||||
Node: register69204
|
Node: register69433
|
||||||
Ref: #register69331
|
Ref: #register69560
|
||||||
Node: Custom register output73832
|
Node: Custom register output74061
|
||||||
Ref: #custom-register-output73961
|
Ref: #custom-register-output74190
|
||||||
Node: register-match75191
|
Node: register-match75420
|
||||||
Ref: #register-match75325
|
Ref: #register-match75554
|
||||||
Node: rewrite75508
|
Node: rewrite75737
|
||||||
Ref: #rewrite75625
|
Ref: #rewrite75854
|
||||||
Node: stats75694
|
Node: stats75923
|
||||||
Ref: #stats75797
|
Ref: #stats76026
|
||||||
Node: tags76667
|
Node: tags76896
|
||||||
Ref: #tags76765
|
Ref: #tags76994
|
||||||
Node: test77001
|
Node: test77230
|
||||||
Ref: #test77085
|
Ref: #test77314
|
||||||
Node: ADD-ON COMMANDS77453
|
Node: ADD-ON COMMANDS77682
|
||||||
Ref: #add-on-commands77563
|
Ref: #add-on-commands77792
|
||||||
Node: Official add-ons78850
|
Node: Official add-ons79079
|
||||||
Ref: #official-add-ons78990
|
Ref: #official-add-ons79219
|
||||||
Node: api79077
|
Node: api79306
|
||||||
Ref: #api79166
|
Ref: #api79395
|
||||||
Node: ui79218
|
Node: ui79447
|
||||||
Ref: #ui79317
|
Ref: #ui79546
|
||||||
Node: web79375
|
Node: web79604
|
||||||
Ref: #web79464
|
Ref: #web79693
|
||||||
Node: Third party add-ons79510
|
Node: Third party add-ons79739
|
||||||
Ref: #third-party-add-ons79685
|
Ref: #third-party-add-ons79914
|
||||||
Node: diff79820
|
Node: diff80049
|
||||||
Ref: #diff79917
|
Ref: #diff80146
|
||||||
Node: iadd80016
|
Node: iadd80245
|
||||||
Ref: #iadd80130
|
Ref: #iadd80359
|
||||||
Node: interest80213
|
Node: interest80442
|
||||||
Ref: #interest80334
|
Ref: #interest80563
|
||||||
Node: irr80429
|
Node: irr80658
|
||||||
Ref: #irr80527
|
Ref: #irr80756
|
||||||
Node: Experimental add-ons80605
|
Node: Experimental add-ons80834
|
||||||
Ref: #experimental-add-ons80757
|
Ref: #experimental-add-ons80986
|
||||||
Node: autosync81037
|
Node: autosync81266
|
||||||
Ref: #autosync81148
|
Ref: #autosync81377
|
||||||
Node: chart81387
|
Node: chart81616
|
||||||
Ref: #chart81506
|
Ref: #chart81735
|
||||||
Node: check81577
|
Node: check81806
|
||||||
Ref: #check81679
|
Ref: #check81908
|
||||||
|
|
||||||
End Tag Table
|
End Tag Table
|
||||||
|
|||||||
@ -1727,7 +1727,10 @@ COMMANDS
|
|||||||
tion.
|
tion.
|
||||||
|
|
||||||
prices
|
prices
|
||||||
Print all market prices from the journal.
|
Print market price directives from the journal. With -costs, also
|
||||||
|
print synthetic market prices based on transaction prices. With
|
||||||
|
-inverted-costs, also print inverse prices based on transaction prices.
|
||||||
|
Prices (and postings providing prices) can be filtered by a query.
|
||||||
|
|
||||||
print
|
print
|
||||||
Show transactions from the journal. Aliases: p, txns.
|
Show transactions from the journal. Aliases: p, txns.
|
||||||
|
|||||||
@ -506,7 +506,10 @@ you can alter the report mode with `--change`/`--cumulative`/`--historical`.
|
|||||||
This command also supports [output destination](/manual.html#output-destination) and [output format](/manual.html#output-format) selection.
|
This command also supports [output destination](/manual.html#output-destination) and [output format](/manual.html#output-format) selection.
|
||||||
|
|
||||||
## prices
|
## prices
|
||||||
Print all [market prices](/manual#market-prices) from the journal.
|
Print [market price directives](/manual#market-prices) from the journal.
|
||||||
|
With --costs, also print synthetic market prices based on [transaction prices](/manual#transaction-prices).
|
||||||
|
With --inverted-costs, also print inverse prices based on transaction prices.
|
||||||
|
Prices (and postings providing prices) can be filtered by a query.
|
||||||
|
|
||||||
## print
|
## print
|
||||||
Show transactions from the journal. Aliases: p, txns.
|
Show transactions from the journal. Aliases: p, txns.
|
||||||
|
|||||||
@ -148,15 +148,13 @@ If you prefer more control or if hledger-install failed, here's how to use stack
|
|||||||
|
|
||||||
On Windows, the 64-bit version of stack is [preferred](https://github.com/simonmichael/hledger/issues/275#issuecomment-123834252).
|
On Windows, the 64-bit version of stack is [preferred](https://github.com/simonmichael/hledger/issues/275#issuecomment-123834252).
|
||||||
|
|
||||||
2. **`stack install --resolver=nightly-2018-06-02 hledger-lib-1.10 hledger-1.10 hledger-ui-1.10 fsnotify-0.3.0.1 hledger-web-1.10.1 hledger-api-1.10`**\
|
2. **`stack install --resolver=lts-12 hledger-lib-1.10 hledger-1.10 hledger-ui-1.10.1 hledger-web-1.10 hledger-api-1.10`**\
|
||||||
This installs the main hledger packages (and dependencies) from [Stackage](https://www.stackage.org) and/or [Hackage](http://hackage.haskell.org).
|
This installs the main hledger packages (and dependencies) from [Stackage](https://www.stackage.org) and/or [Hackage](http://hackage.haskell.org).
|
||||||
You can save some time by omitting hledger-* packages you don't want.\
|
You can save some time by omitting hledger-* packages you don't want.\
|
||||||
<span class=warnings>([windows: hledger-ui is not available](https://github.com/jtdaugherty/vty/pull/1#issuecomment-297143444))</span>
|
<span class=warnings>([windows: hledger-ui is not available](https://github.com/jtdaugherty/vty/pull/1#issuecomment-297143444))</span>
|
||||||
|
|
||||||
The command above uses stackage's nightly snapshot.
|
|
||||||
You might be able to reduce build time by specifying an older snapshot that you've used before (eg: `--resolver=lts-10.8`), or by omitting the --resolver option.
|
|
||||||
To estimate the build time, add `--dry-run`.
|
|
||||||
You can kill and restart this without losing progress.
|
You can kill and restart this without losing progress.
|
||||||
|
To estimate the build time, add `--dry-run`.
|
||||||
|
|
||||||
If you see "was generated with a newer version of hpack, please upgrade and try again" errors, you can ignore them.
|
If you see "was generated with a newer version of hpack, please upgrade and try again" errors, you can ignore them.
|
||||||
(Upgrade to the latest stack release to stop them.)
|
(Upgrade to the latest stack release to stop them.)
|
||||||
@ -179,9 +177,7 @@ If you prefer more control or if hledger-install failed, here's how to use stack
|
|||||||
[hledger-iadd](http://hackage.haskell.org/package/hledger-iadd),
|
[hledger-iadd](http://hackage.haskell.org/package/hledger-iadd),
|
||||||
[hledger-interest](http://hackage.haskell.org/package/hledger-interest),
|
[hledger-interest](http://hackage.haskell.org/package/hledger-interest),
|
||||||
and [hledger-irr](http://hackage.haskell.org/package/hledger-irr)
|
and [hledger-irr](http://hackage.haskell.org/package/hledger-irr)
|
||||||
can be installed similarly to the above. Eg:
|
can be installed similarly to the above.
|
||||||
|
|
||||||
**`stack install --resolver=nightly-2018-06-02 hledger-lib-1.10 hledger-1.10 hledger-iadd-1.3.5`**
|
|
||||||
|
|
||||||
6. **[Test](#test)**
|
6. **[Test](#test)**
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user