2014-04-19 06:17:36 +00:00
|
|
|
module Language.Haskell.GhcMod.Utils where
|
2014-04-19 06:20:16 +00:00
|
|
|
|
2014-08-18 06:06:36 +00:00
|
|
|
|
|
|
|
import Control.Exception
|
|
|
|
import Control.Monad.Error (MonadError(..), Error(..))
|
2014-08-19 05:56:01 +00:00
|
|
|
import MonadUtils (MonadIO, liftIO)
|
2014-04-30 23:48:03 +00:00
|
|
|
import System.Directory (getCurrentDirectory, setCurrentDirectory)
|
|
|
|
import System.Exit (ExitCode(..))
|
2014-08-18 06:06:36 +00:00
|
|
|
import System.IO.Error (tryIOError)
|
2014-08-19 05:56:01 +00:00
|
|
|
import System.Process (readProcessWithExitCode)
|
2014-04-30 23:48:03 +00:00
|
|
|
|
2014-04-19 06:20:16 +00:00
|
|
|
-- dropWhileEnd is not provided prior to base 4.5.0.0.
|
|
|
|
dropWhileEnd :: (a -> Bool) -> [a] -> [a]
|
|
|
|
dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
|
2014-04-30 23:54:15 +00:00
|
|
|
|
|
|
|
extractParens :: String -> String
|
|
|
|
extractParens str = extractParens' str 0
|
|
|
|
where
|
|
|
|
extractParens' :: String -> Int -> String
|
|
|
|
extractParens' [] _ = []
|
|
|
|
extractParens' (s:ss) level
|
|
|
|
| s `elem` "([{" = s : extractParens' ss (level+1)
|
|
|
|
| level == 0 = extractParens' ss 0
|
2014-07-17 08:16:44 +00:00
|
|
|
| s `elem` "}])" && level == 1 = [s]
|
2014-04-30 23:54:15 +00:00
|
|
|
| s `elem` "}])" = s : extractParens' ss (level-1)
|
|
|
|
| otherwise = s : extractParens' ss level
|
|
|
|
|
2014-08-18 06:06:36 +00:00
|
|
|
readProcess' :: (MonadIO m, Error e, MonadError e m)
|
|
|
|
=> String
|
|
|
|
-> [String]
|
|
|
|
-> m String
|
2014-04-30 23:48:03 +00:00
|
|
|
readProcess' cmd opts = do
|
2014-07-17 13:52:33 +00:00
|
|
|
(rv,output,err) <- liftIO $ readProcessWithExitCode cmd opts ""
|
2014-04-30 23:48:03 +00:00
|
|
|
case rv of
|
|
|
|
ExitFailure val -> do
|
2014-08-18 06:06:36 +00:00
|
|
|
throwError $ strMsg $
|
|
|
|
cmd ++ " " ++ unwords opts ++ " (exit " ++ show val ++ ")"
|
2014-08-19 05:56:01 +00:00
|
|
|
++ "\n" ++ err
|
2014-04-30 23:48:03 +00:00
|
|
|
ExitSuccess ->
|
|
|
|
return output
|
2014-05-01 00:10:42 +00:00
|
|
|
|
|
|
|
withDirectory_ :: FilePath -> IO a -> IO a
|
|
|
|
withDirectory_ dir action =
|
|
|
|
bracket getCurrentDirectory setCurrentDirectory
|
|
|
|
(\_ -> setCurrentDirectory dir >> action)
|
2014-08-18 06:06:36 +00:00
|
|
|
|
|
|
|
rethrowError :: MonadError e m => (e -> e) -> m a -> m a
|
|
|
|
rethrowError f action = action `catchError` \e -> throwError $ f e
|
|
|
|
|
|
|
|
tryFix :: MonadError e m => m a -> (e -> m ()) -> m a
|
|
|
|
tryFix action fix = do
|
|
|
|
action `catchError` \e -> fix e >> action
|
|
|
|
|
2014-08-19 02:28:04 +00:00
|
|
|
-- | 'IOException's thrown in the computation passed to this function will be
|
|
|
|
-- converted to 'MonadError' failures using 'throwError'.
|
|
|
|
liftIOExceptions :: (MonadIO m, Error e, MonadError e m) => IO a -> m a
|
|
|
|
liftIOExceptions action = do
|
2014-08-18 06:06:36 +00:00
|
|
|
res <- liftIO $ tryIOError action
|
|
|
|
case res of
|
|
|
|
Right a -> return a
|
|
|
|
Left e -> case show e of
|
|
|
|
"" -> throwError $ noMsg
|
|
|
|
msg -> throwError $ strMsg msg
|