bin: add register-match, convert all to stack scripts
This commit is contained in:
parent
792c807f2c
commit
ab19a92187
@ -3,6 +3,8 @@
|
|||||||
--package hledger-lib
|
--package hledger-lib
|
||||||
--package hledger
|
--package hledger
|
||||||
-}
|
-}
|
||||||
|
-- You can compile this script for speed:
|
||||||
|
-- stack build hledger && stack ghc bin/hledger-check-dates.hs
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
hledger-check-dates [--strict] [--date2] [-f JOURNALFILE]
|
hledger-check-dates [--strict] [--date2] [-f JOURNALFILE]
|
||||||
|
|||||||
@ -4,6 +4,8 @@
|
|||||||
--package hledger
|
--package hledger
|
||||||
--package time
|
--package time
|
||||||
-}
|
-}
|
||||||
|
-- You can compile this script for speed:
|
||||||
|
-- stack build hledger && stack ghc bin/hledger-equity.hs
|
||||||
|
|
||||||
{-
|
{-
|
||||||
hledger-equity [HLEDGEROPTS] [QUERY]
|
hledger-equity [HLEDGEROPTS] [QUERY]
|
||||||
|
|||||||
@ -1,11 +1,18 @@
|
|||||||
#!/usr/bin/env runhaskell
|
#!/usr/bin/env stack
|
||||||
{-|
|
{- stack runghc --verbosity info
|
||||||
|
--package hledger-lib
|
||||||
|
--package hledger
|
||||||
|
-}
|
||||||
|
-- You can compile this script for speed:
|
||||||
|
-- stack build hledger && stack ghc bin/hledger-print-unique.hs
|
||||||
|
|
||||||
|
{-
|
||||||
hledger-print-unique [-f JOURNALFILE | -f-]
|
hledger-print-unique [-f JOURNALFILE | -f-]
|
||||||
|
|
||||||
Print only journal entries which are unique by description (or
|
Print only journal entries which are unique by description (or
|
||||||
something else). Reads the default or specified journal, or stdin.
|
something else). Reads the default or specified journal, or stdin.
|
||||||
|
|
||||||
|-}
|
-}
|
||||||
|
|
||||||
import Data.List
|
import Data.List
|
||||||
import Data.Ord
|
import Data.Ord
|
||||||
|
|||||||
100
bin/hledger-register-match.hs
Executable file
100
bin/hledger-register-match.hs
Executable file
@ -0,0 +1,100 @@
|
|||||||
|
#!/usr/bin/env stack
|
||||||
|
{- stack runghc --verbosity info
|
||||||
|
--package hledger-lib
|
||||||
|
--package hledger
|
||||||
|
--package text
|
||||||
|
-}
|
||||||
|
-- You can compile this script for speed:
|
||||||
|
-- stack build hledger && stack ghc bin/hledger-register-match.hs
|
||||||
|
|
||||||
|
{-|
|
||||||
|
hledger-register-match DESC
|
||||||
|
|
||||||
|
A helper for ledger-autosync. This prints the one posting whose transaction
|
||||||
|
description is closest to DESC, in the style of the register command.
|
||||||
|
If there are multiple equally good matches, it shows the most recent.
|
||||||
|
Query options (options, not arguments) can be used to restrict the search space.
|
||||||
|
|
||||||
|
|-}
|
||||||
|
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
import Data.Char (toUpper)
|
||||||
|
import Data.List
|
||||||
|
import qualified Data.Text as T
|
||||||
|
|
||||||
|
import System.Console.CmdArgs
|
||||||
|
import System.Console.CmdArgs.Explicit
|
||||||
|
|
||||||
|
import Hledger
|
||||||
|
import Hledger.Cli.CliOptions
|
||||||
|
import Hledger.Cli ( withJournalDo, postingsReportAsText )
|
||||||
|
|
||||||
|
main = getCliOpts (defCommandMode ["hledger-register-match"]) >>= flip withJournalDo match
|
||||||
|
|
||||||
|
match :: CliOpts -> Journal -> IO ()
|
||||||
|
match opts@CliOpts{rawopts_=rawopts,reportopts_=ropts} j = do
|
||||||
|
let args' = listofstringopt "args" rawopts
|
||||||
|
case args' of
|
||||||
|
[desc] -> do
|
||||||
|
d <- getCurrentDay
|
||||||
|
let q = queryFromOptsOnly d ropts
|
||||||
|
(_,pris) = postingsReport ropts q j
|
||||||
|
ps = [p | (_,_,_,p,_) <- pris]
|
||||||
|
case similarPosting ps desc of
|
||||||
|
Nothing -> putStrLn "no matches found."
|
||||||
|
Just p -> putStr $ postingsReportAsText opts ("",[pri])
|
||||||
|
where pri = (Just (postingDate p)
|
||||||
|
,Nothing
|
||||||
|
,Just $ T.unpack (maybe "" tdescription $ ptransaction p)
|
||||||
|
,p
|
||||||
|
,0)
|
||||||
|
_ -> putStrLn "please provide one description argument."
|
||||||
|
|
||||||
|
-- Identify the closest recent match for this description in the given date-sorted postings.
|
||||||
|
similarPosting :: [Posting] -> String -> Maybe Posting
|
||||||
|
similarPosting ps desc =
|
||||||
|
let matches =
|
||||||
|
sortBy compareRelevanceAndRecency
|
||||||
|
$ filter ((> threshold).fst)
|
||||||
|
[(maybe 0 (\t -> compareDescriptions desc (T.unpack $ tdescription t)) (ptransaction p), p) | p <- ps]
|
||||||
|
where
|
||||||
|
compareRelevanceAndRecency (n1,p1) (n2,p2) = compare (n2,postingDate p2) (n1,postingDate p1)
|
||||||
|
threshold = 0
|
||||||
|
in case matches of [] -> Nothing
|
||||||
|
m:_ -> Just $ snd m
|
||||||
|
|
||||||
|
-- -- Identify the closest recent match for this description in past transactions.
|
||||||
|
-- similarTransaction :: Journal -> Query -> String -> Maybe Transaction
|
||||||
|
-- similarTransaction j q desc =
|
||||||
|
-- case historymatches = transactionsSimilarTo j q desc of
|
||||||
|
-- ((,t):_) = Just t
|
||||||
|
-- [] = Nothing
|
||||||
|
|
||||||
|
compareDescriptions :: [Char] -> [Char] -> Double
|
||||||
|
compareDescriptions s t = compareStrings s' t'
|
||||||
|
where s' = simplify s
|
||||||
|
t' = simplify t
|
||||||
|
simplify = filter (not . (`elem` ("0123456789"::String)))
|
||||||
|
|
||||||
|
-- | Return a similarity measure, from 0 to 1, for two strings.
|
||||||
|
-- This is Simon White's letter pairs algorithm from
|
||||||
|
-- http://www.catalysoft.com/articles/StrikeAMatch.html
|
||||||
|
-- with a modification for short strings.
|
||||||
|
compareStrings :: String -> String -> Double
|
||||||
|
compareStrings "" "" = 1
|
||||||
|
compareStrings (_:[]) "" = 0
|
||||||
|
compareStrings "" (_:[]) = 0
|
||||||
|
compareStrings (a:[]) (b:[]) = if toUpper a == toUpper b then 1 else 0
|
||||||
|
compareStrings s1 s2 = 2.0 * fromIntegral i / fromIntegral u
|
||||||
|
where
|
||||||
|
i = length $ intersect pairs1 pairs2
|
||||||
|
u = length pairs1 + length pairs2
|
||||||
|
pairs1 = wordLetterPairs $ uppercase s1
|
||||||
|
pairs2 = wordLetterPairs $ uppercase s2
|
||||||
|
|
||||||
|
wordLetterPairs = concatMap letterPairs . words
|
||||||
|
|
||||||
|
letterPairs (a:b:rest) = [a,b] : letterPairs (b:rest)
|
||||||
|
letterPairs _ = []
|
||||||
|
|
||||||
@ -5,9 +5,8 @@
|
|||||||
--package megaparsec
|
--package megaparsec
|
||||||
--package text
|
--package text
|
||||||
-}
|
-}
|
||||||
-- To run or compile this script, it's easiest to be in the hledger source tree. Then:
|
-- You can compile this script for speed:
|
||||||
-- To run it directly: bin/hledger-rewrite.hs ARGS
|
-- stack build hledger && stack ghc bin/hledger-rewrite.hs
|
||||||
-- To compile it: stack build hledger --only-dependencies && stack ghc bin/hledger-rewrite.hs
|
|
||||||
|
|
||||||
{-|
|
{-|
|
||||||
hledger-rewrite [PATTERNS] --add-posting "ACCT AMTEXPR" ...
|
hledger-rewrite [PATTERNS] --add-posting "ACCT AMTEXPR" ...
|
||||||
@ -23,9 +22,7 @@ hledger-rewrite.hs expenses:gifts --add-posting '(reserve:gifts) *-1"'
|
|||||||
|
|
||||||
Note the single quotes to protect the dollar sign from bash, and the two spaces between account and amount.
|
Note the single quotes to protect the dollar sign from bash, and the two spaces between account and amount.
|
||||||
See the command-line help for more details.
|
See the command-line help for more details.
|
||||||
Currently does not work when invoked via hledger, run hledger-rewrite[.hs] directly.
|
Currently does not work when invoked via hledger, run it directly instead.
|
||||||
|
|
||||||
Tested-with: hledger HEAD ~ 2016/3/2
|
|
||||||
|
|
||||||
Related: https://github.com/simonmichael/hledger/issues/99
|
Related: https://github.com/simonmichael/hledger/issues/99
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user