module HolyProject.GitConfig ( getNameAndMailFromGitConfig ) where import qualified Data.ByteString.Lazy.Char8 as LZ import Control.Monad (guard) import Control.Exception import System.IO.Error import System.Environment (getEnv) -- | Return name and email in gitconfig if found getNameAndMailFromGitConfig :: IO (Maybe String, Maybe String) getNameAndMailFromGitConfig = return . getNameAndMail =<< safeReadGitConfig -- | return the content of ~/.gitconfig if it exists -- if the HOME environment variable is not set -- or the file doesn't exists -- We return an empty string safeReadGitConfig :: IO LZ.ByteString safeReadGitConfig = do e <- tryJust (guard . isDoesNotExistError) (do home <- getEnv "HOME" LZ.readFile $ home ++ "/.gitconfig" ) return $ either (const LZ.empty) id e -- | Returns the name and email from the content of a .gitconfig file -- almost equivalent to the two zsh lines: -- -- > name="$(< ~/.gitconfig awk '$1 == name {shift 2; print}')" -- > email="$(< ~/.gitconfig awk '$1 == email {shift 2; print}')" -- -- But in Haskell it doesn't read the entire file. -- The script after the first occurence of name and email. getNameAndMail :: LZ.ByteString -> (Maybe String,Maybe String) getNameAndMail gitConfigContent = (getFirstValueFor splitted "name", getFirstValueFor splitted "email") where -- make lines of words splitted :: [[LZ.ByteString]] splitted = map LZ.words (LZ.lines gitConfigContent) -- | Get the first line which start with -- 'elem =' and return the third field (value) getFirstValueFor :: [[LZ.ByteString]] -> String -> Maybe String getFirstValueFor splitted keyname = firstJust (map (getValueForKey keyname) splitted) -- | return the first Just value of a list of Maybe firstJust :: (Eq a) => [Maybe a] -> Maybe a firstJust l = case dropWhile (==Nothing) l of [] -> Nothing (j:_) -> j -- | Given a line of words ("word1":"word2":rest) -- getValue will return rest if word1 == key -- 'elem =' or Nothing otherwise getValueForKey :: String -- key -> [LZ.ByteString] -- line of words -> Maybe String -- the value if found getValueForKey el (n:e:xs) = if (n == LZ.pack el) && (e == LZ.pack "=") then Just (LZ.unpack (LZ.unwords xs)) else Nothing getValueForKey _ _ = Nothing