-- |various utility functions module Angel.Util ( sleepSecs , waitForWake , expandPath , split , strip , nnull ) where import Control.Concurrent.STM (atomically , retry , TVar , readTVar , writeTVar) import Control.Concurrent (threadDelay) import Data.Char (isSpace) import Data.Maybe (catMaybes) import System.Posix.User (getEffectiveUserName, UserEntry(homeDirectory), getUserEntryForName) -- |sleep for `s` seconds in an thread sleepSecs :: Int -> IO () sleepSecs s = threadDelay $ s * 1000000 -- |wait for the STM TVar to be non-nothing waitForWake :: TVar (Maybe Int) -> IO () waitForWake wakeSig = atomically $ do state <- readTVar wakeSig case state of Just _ -> writeTVar wakeSig Nothing Nothing -> retry expandPath :: FilePath -> IO FilePath expandPath ('~':rest) = do home <- getHome =<< getUser return $ home ++ relativePath where (userName, relativePath) = span (/= '/') rest getUser = if null userName then getEffectiveUserName else return userName getHome user = homeDirectory `fmap` getUserEntryForName user expandPath path = return path nnull :: [a] -> Bool nnull = not . null split :: Eq a => a -> [a] -> [[a]] split a = catMaybes . foldr go [] where go x acc = case (x == a, acc) of (True, xs) -> Nothing:xs (False, []) -> [Just [x]] (False, Nothing:rest) -> Just [x]:Nothing:rest (False, Just xs:rest) -> Just (x:xs):rest strip :: String -> String strip = reverse . dropWhile isSpace . reverse . dropWhile isSpace