50 lines
1.5 KiB
Haskell
Executable File
50 lines
1.5 KiB
Haskell
Executable File
{-# LANGUAGE QuasiQuotes #-}
|
|
|
|
module Hledger.Cli.Commands.Checkdupes (
|
|
checkdupesmode
|
|
,checkdupes
|
|
)
|
|
where
|
|
|
|
import Data.Function
|
|
import Data.List
|
|
import Data.String.Here
|
|
import qualified Data.Text as T
|
|
import Hledger
|
|
import Hledger.Cli.CliOptions
|
|
import System.Console.CmdArgs.Explicit
|
|
import Text.Printf
|
|
|
|
checkdupesmode :: Mode RawOpts
|
|
checkdupesmode = hledgerCommandMode
|
|
[here| check-dupes
|
|
Reports account names having the same leaf but different prefixes.
|
|
In other words, two or more leaves that are categorized differently.
|
|
Reads the default journal file, or another specified as an argument.
|
|
An example: http://stefanorodighiero.net/software/hledger-dupes.html
|
|
|]
|
|
[]
|
|
[generalflagsgroup1]
|
|
[]
|
|
([], Nothing)
|
|
|
|
checkdupes _opts j = mapM_ render $ checkdupes' $ accountsNames j
|
|
|
|
accountsNames :: Journal -> [(String, AccountName)]
|
|
accountsNames j = map leafAndAccountName as
|
|
where leafAndAccountName a = (T.unpack $ accountLeafName a, a)
|
|
ps = journalPostings j
|
|
as = nub $ sort $ map paccount ps
|
|
|
|
checkdupes' :: (Ord k, Eq k) => [(k, v)] -> [(k, [v])]
|
|
checkdupes' l = zip dupLeafs dupAccountNames
|
|
where dupLeafs = map (fst . head) d
|
|
dupAccountNames = map (map snd) d
|
|
d = dupes' l
|
|
dupes' = filter ((> 1) . length)
|
|
. groupBy ((==) `on` fst)
|
|
. sortBy (compare `on` fst)
|
|
|
|
render :: (String, [AccountName]) -> IO ()
|
|
render (leafName, accountNameL) = printf "%s as %s\n" leafName (concat $ intersperse ", " (map T.unpack accountNameL))
|