    -- | Expand environment variables in strings
    module Agda.Utils.Environment ( expandEnvironmentVariables ) where

    import Data.Char
    import Data.Maybe
    import System.Environment
    import System.Directory ( getHomeDirectory )

    expandEnvironmentVariables :: String -> IO String
    expandEnvironmentVariables s = do
      env <- getEnvironment
      home <- getHomeDirectory
      return $ expandVars home env s

    expandVars :: String -> [(String, String)] -> String -> String
    expandVars home env s = concatMap repl $ tokens s
      where
        repl Home = home ++ "/"
        repl (Var x) = fromMaybe "" $ lookup x env
        repl (Str s) = s

    data Token = Home | Var String | Str String
      deriving (Eq, Show)

    tokens :: String -> [Token]
    tokens s = case s of
      '~' : '/' : s -> Home : tokens' s
      '\\' : '~' : s -> cons '~' $ tokens' s
      _ -> tokens' s
      where
        tokens' :: String -> [Token]
        tokens' s =
          case s of
            '$' : '$' : s -> cons '$' $ tokens' s
            '$' : s@(c : _) | c == '_' || isAlpha c -> Var x : tokens' s'
              where (x, s') = span (\ c -> c == '_' || isAlphaNum c) s
            '$' : '{' : s ->
              case break (== '}') s of
                (x, '}' : s) -> Var x : tokens' s
                _            -> [Str $ "${" ++ s] -- abort on unterminated '{'
            c : s -> cons c $ tokens' s
            ""    -> []
        cons c (Str s : ts) = Str (c : s) : ts
        cons c ts           = Str [c] : ts