packages feed

cabal-meta-0.2.3.1: OmniConfig.hs

{-# LANGUAGE OverloadedStrings, ScopedTypeVariables, GADTs #-}
module OmniConfig (
 OptionsSource(..), allProgramOpts, commandLine, environment, homeOptFile
 , checkNegatedOpt
) where

import Prelude hiding (FilePath)
import System.Environment
import Control.Exception (SomeException, handle)
import qualified Data.Text as T
import Data.Text (Text)

import Filesystem.Path.CurrentOS
import Filesystem (readTextFile, getHomeDirectory)

allProgramOpts :: [OptionsSource] -> IO [Text]
allProgramOpts confs = do
  fmap Prelude.concat $ mapM loadProgramOptions confs

checkNegatedOpt :: Text -> [Text] -> (Maybe Bool, [Text])
checkNegatedOpt optText args =
    if elem negatedOpt args
      then (Just False, filteredArgs)
      else if elem opt args
             then (Just True, filteredArgs)
             else (Nothing, args)
  where
    filteredArgs = filter (\arg -> arg /= negatedOpt && arg /= opt) args
    opt = "--" `T.append` optText
    negatedOpt = "--no-" `T.append` optText

data OptionsSource = OptionsSource {
    loadProgramOptions :: IO [Text]
  }

commandLine :: OptionsSource
commandLine = OptionsSource {
    loadProgramOptions = fmap (map T.pack) getArgs
  }

environment :: Text -> OptionsSource
environment name = OptionsSource {
    loadProgramOptions = do
      env <- getEnvironment
      return $ case lookup (T.unpack $ T.replace "-" "_" $ T.toUpper name `T.append` "_OPTS") env of
                Nothing -> []
                Just s -> T.splitOn " " $ T.pack s
  }

homeOptFile :: Text -> OptionsSource
homeOptFile name = OptionsSource {
    loadProgramOptions  = do
      hd <- getHomeDirectory
      contents <- handle (\(_::SomeException) -> return "") $
        readTextFile $ hd </> fromText ("." `T.append` name) </> "opts"
      return $ T.splitOn " " $ T.strip contents
  }