|
#!/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 <pre class=Agda> tag"
|