import System.Environment import System.Directory import System.IO import System.Exit (exitSuccess,exitFailure) import Data.List type EnvKey = String type EnvValue = String data EnvFile = End | Entry EnvKey EnvValue EnvFile deriving (Show,Eq,Read) main = do args <- getArgs cliRun args cliRun :: [String] -> IO () cliRun ("get":args) = cliGet args cliRun ("set":args) = cliSet args cliRun ("unset":args) = cliUnset args cliRun ("list":_) = cliList cliRun _ = cliFail "USAGE: fenv [...args]" cliGet :: [String] -> IO () cliGet (name:_) = do env <- getEnvFile case (getEntry env name) of (Just value) -> putStrLn value Nothing -> cliFail "ERROR: No value defined" cliGet _ = cliFail "USAGE: fenv get " cliUnset :: [String] -> IO () cliUnset (name:_) = do env <- getEnvFile let env' = (removeEntry env name) in replaceEnvFile env' cliUnset _ = cliFail "USAGE: fenv unset " cliSet :: [String] -> IO () cliSet (name:value:_) = do env <- getEnvFile let env' = (setEntry env name value) in replaceEnvFile env' cliSet _ = cliFail "USAGE: fenv set " cliList :: IO () cliList = do env <- getEnvFile printLevel env where printLevel (Entry key value rest) = putStrLn (key ++ ": " ++ value) >>= (printLevel rest) printLevel End = return () cliFail :: String -> IO () cliFail message = putStrLn message >>= return exitFailure setEntry :: EnvFile -> EnvKey -> EnvValue -> EnvFile setEntry env key value = let env'=(removeEntry env key) in (Entry key value env') removeEntry :: EnvFile -> EnvKey -> EnvFile removeEntry End _ = End removeEntry (Entry entryKey entryValue rest) key = if entryKey==key then rest else (Entry entryKey entryValue (removeEntry rest key)) getEntry :: EnvFile -> EnvKey -> Maybe EnvValue getEntry End _ = Nothing getEntry (Entry entryKey entryValue rest) key = if entryKey==key then return entryValue else (getEntry rest key) replaceEnvFile :: EnvFile -> IO () replaceEnvFile env = do path <- getEnvFilePath (tempName, tempHandle) <- openTempFile "/tmp" ".fenv" hPutStr tempHandle (show env) hClose tempHandle removeFile path renameFile tempName path getEnvFile :: IO EnvFile getEnvFile = do path <- getEnvFilePath contents <- readFile path if contents == "" then return End else return $ read contents getEnvFilePath :: IO FilePath getEnvFilePath = do home <- getHomeDirectory return (home ++ "/.fenv")