packages feed

execs-0.1.0.0: app/Main.hs

{-# LANGUAGE OverloadedStrings #-}

module Main where

  import           Control.Exception
  import           Control.Monad
  import qualified Data.List          as DL
  import qualified Data.Text          as T
  import qualified Data.Text.IO       as TIO
  import qualified System.Directory   as SD
  import qualified System.Environment as SE
  import qualified System.Process     as SP

  cabalExt :: String
  cabalExt = ".cabal"

  commandsSimpleMode :: [String]
  commandsSimpleMode = []

  commandsRebuildMode :: [String]
  commandsRebuildMode = ["stack clean", "stack build"]

  stackExec :: String
  stackExec = "stack exec"

  main :: IO ()
  main = do
    cbm <- getCabalFilename
    flip (maybe (error "Have no .cabal files found.")) cbm $ \cabal -> do
      mode <- getCommandsMode
      execs <- getExecutables . T.lines <$> TIO.readFile cabal
      if null execs
        then error "Have no executables found."
        else exe mode $ T.unpack (head execs)

  getCommandsMode :: IO [String]
  getCommandsMode = do
    args <- SE.getArgs
    if "-r" `elem` args
      then return commandsRebuildMode
      else return commandsSimpleMode

  exe :: [String] -> String -> IO ()
  exe _ [] = error "Empty executable name."
  exe cmds exename = do
    let
      cmd :: String
      cmd = stackExec ++ " " ++ exename
    r <- exe' cmds
    when r $ run' cmd
    where
      exe' :: [String] -> IO Bool
      exe' (a:as) = do
        r <- runFail a
        if r
          then exe' as
          else return r
      exe' _ = return True

      run' :: String -> IO ()
      run' cmd = void (try (SP.callCommand cmd) :: IO (Either SomeException ()))

      runFail :: String -> IO Bool
      runFail cmd = catch (SP.callCommand cmd >> return True) handlerFail

      handlerFail :: SomeException -> IO Bool
      handlerFail _ = return False

  getExecutables :: [T.Text] -> [T.Text]
  getExecutables [] = []
  getExecutables (l:ls)
    | T.null l = getExecutables ls
    | otherwise =
      let
        lc :: T.Text
        lc = T.strip . T.toLower $ l
      in
        if "executable" `T.isPrefixOf` lc
          then last (T.words lc) : getExecutables ls
          else getExecutables ls

  getCabalFilename :: IO (Maybe FilePath)
  getCabalFilename = do
    files <- SD.getCurrentDirectory >>= SD.getDirectoryContents
    return $ DL.find (cabalExt `DL.isSuffixOf`) files