#!/usr/bin/env stack {- stack --resolver lts-18.14 script --package text --package unordered-containers --package tagsoup --package filepath --package hashable -} {-# LANGUAGE OverloadedStrings #-} module Main where import qualified Data.Text.Lazy.IO as Text import qualified Data.HashSet as HashSet import qualified Data.Text.Lazy as Text import Data.HashSet (HashSet) import Data.Text.Lazy (Text) import Data.Hashable import System.Environment import Text.HTML.TagSoup import Data.Function import Data.Int import Data.Foldable import System.FilePath import Control.Monad main :: IO () main = do args <- getArgs for_ args $ \mod -> do contents <- Text.readFile mod let unused = findUnusedImports mempty (parseTags contents) unless (null unused) $ do putStrLn $ "Potentially unused imports for: \x1b[1m" <> dropExtension (takeFileName mod) <> "\x1b[0m" Text.putStrLn $ " * " <> Text.intercalate ", " (toList unused) findUnusedImports :: HashSet Text -> [Tag Text] -> HashSet Text findUnusedImports unused (TagOpen "pre" attrs:ts) | Just "Agda" <- lookup "class" attrs = goAgda 0 unused ts findUnusedImports unused (_:ts) = findUnusedImports unused ts findUnusedImports unused [] = unused goAgda :: Int64 -> HashSet Text -> [Tag Text] -> HashSet Text goAgda line unused (TagOpen "a" attrs:TagText text:TagClose "a":ts) | Just "Module" <- lookup "class" attrs , Just href <- lookup "href" attrs , ".html" `Text.isSuffixOf` href = let imp = Text.take (Text.length href - 5) href in goAgda line (HashSet.insert imp unused) ts | Just href <- lookup "href" attrs , let (mod, ident) = Text.break (== '#') href , not (Text.null mod), not (Text.null (Text.drop 1 ident)) = let imp = Text.take (Text.length mod - 5) mod in goAgda line (HashSet.delete imp unused) ts goAgda line unused (TagClose "pre":ts) = findUnusedImports unused ts goAgda line unused (TagText text:ts) | newlines <- Text.filter (== '\n') text = goAgda (line + Text.length newlines) unused ts goAgda line unused (t:ts) = goAgda line unused ts goAgda line unused [] = error "Unclosed
 tag"