55 lines
1.5 KiB
Haskell
55 lines
1.5 KiB
Haskell
module ListTags where
|
|
|
|
import Info
|
|
|
|
import Control.Monad
|
|
import Data.Foldable
|
|
import Data.HashMap.Strict (HashMap)
|
|
import qualified Data.HashMap.Strict as HashMap
|
|
import Data.HashSet (HashSet)
|
|
import qualified Data.HashSet as HashSet
|
|
import Data.List (sort)
|
|
import Data.Tuple (swap)
|
|
import Text.Printf (printf)
|
|
|
|
|
|
type TagStats = HashMap Text Int
|
|
type PathSet = HashSet FilePath
|
|
|
|
data Stats =
|
|
Stats {
|
|
tags :: TagStats,
|
|
untagged :: PathSet
|
|
}
|
|
|
|
instance Semigroup Stats where
|
|
Stats {tags = t1, untagged = u1} <> Stats {tags = t2, untagged = u2} =
|
|
Stats {tags = HashMap.unionWith (+) t1 t2, untagged = u1 <> u2}
|
|
|
|
instance Monoid Stats where
|
|
mempty = Stats {tags = [], untagged = []}
|
|
|
|
|
|
stats1 :: Bool -> FilePath -> Info -> Stats
|
|
stats1 nsfw path (Info {tags, nsfwTags}) =
|
|
let tags' = if nsfw then tags <> nsfwTags else tags in
|
|
if null tags' then
|
|
Stats {tags = [], untagged = [path]}
|
|
else
|
|
Stats {tags = HashMap.fromList $ map (, 1) tags', untagged = []}
|
|
|
|
stats :: Bool -> [(FilePath, Info)] -> Stats
|
|
stats nsfw = foldMap $ uncurry $ stats1 nsfw
|
|
|
|
run :: Bool -> Bool -> [(FilePath, Info)] -> IO ()
|
|
run nsfw listUntagged infos = do
|
|
let Stats {tags, untagged} = stats nsfw infos
|
|
let sortedTags = reverse $ sort $ map swap $ HashMap.toList tags
|
|
putStrLn "TAGS\n----"
|
|
for_ sortedTags \(count, path) ->
|
|
printf "%4d: %s\n" count path
|
|
when (listUntagged && not (null untagged)) $ do
|
|
let sortedUntagged = sort $ HashSet.toList untagged
|
|
putStrLn "\nUNTAGGED FILES\n--------------"
|
|
for_ sortedUntagged $ printf " - %s\n"
|