This example looks for Haskell files and sorts their import statements into a standard (alphabetical) order
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE OverloadedStrings #-}
module Main
( mainwhere
)
import Control.Applicative
import qualified Control.Monad as M
import qualified Data.ByteString.Lazy.Char8 as LBS
import Prelude.Compat
import System.Directory
import System.Environment
import System.Exit
import System.FilePath
import TestKit
import Text.Printf
import Text.RE.TDFA.String
import Text.RE.Tools.Find
This program can run in one of two modes.
data Mode
= Check -- only check for unsorted files, generating an
-- error if any not sorted
| Update -- update any unsorted files
deriving (Eq,Show)
main :: IO ()
= do
main <- getArgs
as case as of
-> test
[] "test"] -> test
["update",fp] | is_file fp -> sort_r Update fp
["check" ,fp] | is_file fp -> sort_r Check fp
[-> usage
_ where
= not . (== "--") . take 2
is_file
= do
test Check "Text"
sort_r Check "examples"
sort_r
= do
usage <- getProgName
prg putStr $ unlines
"usage:"
[ " "++prg++" [test]"
, " "++prg++" check <directory>"
, " "++prg++" update <directory>"
, ]
sort_r :: Mode -> FilePath -> IO ()
= findMatches_ fm [re|\.l?hs|] root >>= sort_these md root
sort_r md root where
= FindMethods
fm = doesDirectoryExist
{ doesDirectoryExistDM = getDirectoryContents
, listDirectoryDM = (</>)
, combineDM }
sort_these :: Mode -> FilePath -> [FilePath] -> IO ()
= do
sort_these md root fps <- and <$> mapM (sort_this md) fps
ok case ok of
True -> msg "all imports sorted"
False -> case md of
Check -> do
"Some imports need sorting"
msg $ ExitFailure 1
exitWith Update ->
"Some imports were sorted"
msg where
msg :: String -> IO ()
= printf "%-10s : %s\n" root s msg s
sort_this :: Mode -> FilePath -> IO Bool
= LBS.readFile fp >>= sort_this'
sort_this md fp where
= do
sort_this' lbs not same) $ putStrLn fp
M.when (==Update) $ LBS.writeFile fp lbs'
M.when (mdreturn same
where
= lbs==lbs'
same = sortImports lbs lbs'
The function for sorting a Haskell script, sortImports
has been placed in TestKit
so that it can be shared with re-gen-modules`.
sortImports :: LBS.ByteString -> LBS.ByteString
=
sortImports lbs $ map (matchesSource . getLineMatches) $
LBS.unlines ++ L.sortBy cMp bdy
hdr where
= case (extr ln1,extr ln2) of
cMp ln1 ln2 Nothing,Nothing) -> EQ
(Nothing,Just _ ) -> GT
(Just _ ,Nothing) -> LT
(Just x ,Just y) -> compare x y
(
Line{..} = case allMatches getLineMatches of
extr :_ -> mtch !$$? [cp|mod|]
mtch-> Nothing
_
= span (not . anyMatches . getLineMatches) lns
(hdr,bdy) = grepFilter rex lbs
lns = [re|^import +(qualified| ) ${mod}([^ ].*)$|] rex