{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} module System.Taffybar.DBus.Client.Util where import Control.Applicative import DBus.Generation import qualified DBus.Internal.Types as T import qualified DBus.Introspection as I import qualified Data.Char as Char import Data.Coerce import Data.Maybe import Language.Haskell.TH import StatusNotifier.Util (getIntrospectionObjectFromFile) #if __GLASGOW_HASKELL__ >= 802 deriveShowAndEQ :: [DerivClause] deriveShowAndEQ = [DerivClause Nothing [ConT ''Eq, ConT ''Show]] #endif buildDataFromNameTypePairs :: Name -> [(Name, Type)] -> Dec buildDataFromNameTypePairs name pairs = DataD [] name [] Nothing [RecC name (map mkVarBangType pairs)] #if __GLASGOW_HASKELL__ >= 802 deriveShowAndEQ #else [] #endif where mkVarBangType (fieldName, fieldType) = (fieldName, Bang NoSourceUnpackedness NoSourceStrictness, fieldType) standaloneDeriveEqShow :: Name -> [Dec] #if __GLASGOW_HASKELL__ < 802 standaloneDeriveEqShow name = [ StandaloneDerivD [] (ConT ''Eq `AppT` ConT name) , StandaloneDerivD [] (ConT ''Show `AppT` ConT name) ] #else standaloneDeriveEqShow _ = [] #endif type GetTypeForName = String -> T.Type -> Maybe Type data RecordGenerationParams = RecordGenerationParams { recordName :: Maybe String , recordPrefix :: String , recordTypeForName :: GetTypeForName } defaultRecordGenerationParams :: RecordGenerationParams defaultRecordGenerationParams = RecordGenerationParams { recordName = Nothing , recordPrefix = "_" , recordTypeForName = const $ const Nothing } generateGetAllRecord :: RecordGenerationParams -> GenerationParams -> I.Interface -> Q [Dec] generateGetAllRecord RecordGenerationParams { recordName = recordNameString , recordPrefix = prefix , recordTypeForName = getTypeForName } GenerationParams { getTHType = getArgType } I.Interface { I.interfaceName = interfaceName , I.interfaceProperties = properties } = do let theRecordName = maybe (mkName $ map Char.toUpper $ filter Char.isLetter $ coerce interfaceName) mkName recordNameString let getPairFromProperty I.Property { I.propertyName = propName , I.propertyType = propType } = ( mkName $ prefix ++ propName , fromMaybe (getArgType propType) $ getTypeForName propName propType ) getAllRecord = buildDataFromNameTypePairs theRecordName $ map getPairFromProperty properties return $ getAllRecord:standaloneDeriveEqShow theRecordName generateClientFromFile :: RecordGenerationParams -> GenerationParams -> Bool -> FilePath -> Q [Dec] generateClientFromFile recordGenerationParams params useObjectPath filepath = do object <- getIntrospectionObjectFromFile filepath "/" let interface = head $ I.objectInterfaces object actualObjectPath = I.objectPath object realParams = if useObjectPath then params {genObjectPath = Just actualObjectPath} else params (<++>) = liftA2 (++) generateGetAllRecord recordGenerationParams params interface <++> generateClient realParams interface <++> generateSignalsFromInterface realParams interface