module HsImport.Main
( hsimport
, hsimport_
) where
import Control.Lens
import Control.Applicative ((<$>))
import Control.Monad (when)
import System.Exit (exitFailure, exitSuccess)
import System.IO (hPutStrLn, stderr)
import Data.Maybe (isJust)
import Data.List (foldl')
import qualified Data.Text as T
import qualified Data.Text.IO as TIO
import qualified Config.Dyre as Dyre
import HsImport.ImportChange
import HsImport.ImportSpec
import HsImport.ImportPos (ImportPos(..))
import qualified HsImport.Args as Args
import HsImport.Config
import HsImport.Utils
import qualified HsImport.Parse as P
hsimport = Dyre.wrapMain $ Dyre.defaultParams
{ Dyre.projectName = "hsimport"
, Dyre.realMain = realMain
, Dyre.showError = \config err -> config { configError = Just err }
}
where
realMain :: Config -> IO ()
realMain config = do
case configError config of
Just error -> hPutStrLn stderr ("hsimport: " ++ error) >> exitFailure
_ -> return ()
args <- Args.hsImportArgs
maybeSpec <- hsImportSpec args
case maybeSpec of
Left error -> hPutStrLn stderr ("hsimport: " ++ error) >> exitFailure
Right spec -> hsimport_ config spec >> exitSuccess
hsimport_ :: Config -> ImportSpec -> IO ()
hsimport_ Config { prettyPrint = prettyPrint, findImportPos = findImportPos } spec = do
let impChanges = importChanges (spec ^. moduleToImport)
(spec ^. symbolToImport)
(spec ^. qualifiedName)
(spec ^. parsedSrcFile)
srcLines <- lines . T.unpack <$> TIO.readFile (spec ^. sourceFile)
let srcLines' = applyChanges srcLines impChanges
when (srcLines' /= srcLines || isJust (spec ^. saveToFile)) $
TIO.writeFile (outputFile spec) (T.pack $ unlines srcLines')
where
applyChanges = foldl' applyChange
applyChange srcLines (ReplaceImportAt srcLine importDecl) =
let numTakes = max 0 (srcLine 1)
numDrops = lastImportSrcLine srcLine srcLines
in take numTakes srcLines ++ [prettyPrint importDecl] ++ drop numDrops srcLines
applyChange srcLines (AddImportAfter srcLine importDecl) =
let numTakes = lastImportSrcLine srcLine srcLines
numDrops = numTakes
in take numTakes srcLines ++ [prettyPrint importDecl] ++ drop numDrops srcLines
applyChange srcLines (AddImportAtEnd importDecl) =
srcLines ++ [prettyPrint importDecl]
applyChange srcLines (FindImportPos importDecl) =
case findImportPos importDecl allImportDecls of
Just (After impDecl) -> applyChange srcLines (AddImportAfter (srcLine impDecl) importDecl)
Just (Before impDecl) -> applyChange srcLines (AddImportAfter (max 0 (srcLine impDecl 1)) importDecl)
_ -> applyChange srcLines (AddImportAfter (srcLine . last $ allImportDecls) importDecl)
applyChange srcLines NoImportChange = srcLines
outputFile spec
| Just file <- spec ^. saveToFile = file
| otherwise = spec ^. sourceFile
lastImportSrcLine fstLine srcLines
| Just lastLine <- P.lastImportSrcLine $ drop (max 0 (fstLine 1)) srcLines
= fstLine + (lastLine 1)
| otherwise
= fstLine
allImportDecls = importDecls $ spec ^. parsedSrcFile