module Graphics.UI.Qtah.Generator.Enum (installEnumCalculator) where
import qualified Data.ByteString.Lazy as B
import Data.Maybe (isJust)
import Foreign.Hoppy.Generator.Hook (
EnumEvaluator,
enumEvaluatorArgsKeepOutputsOnFailure,
hookEvaluateEnums,
interpretOutputToEvaluateEnums,
makeCppSourceToEvaluateEnums,
)
import Foreign.Hoppy.Generator.Spec (Interface, interfaceModifyHooks)
import Foreign.Hoppy.Generator.Util (withTempDirectory)
import Graphics.UI.Qtah.Generator.Config (
qmakeArguments,
qmakeExecutable,
)
import System.Directory (withCurrentDirectory)
import System.FilePath ((</>))
import System.IO (hPutStrLn, stderr)
import System.Process (callProcess, readProcess)
installEnumCalculator :: Interface -> Interface
installEnumCalculator :: Interface -> Interface
installEnumCalculator = (Hooks -> Hooks) -> Interface -> Interface
interfaceModifyHooks ((Hooks -> Hooks) -> Interface -> Interface)
-> (Hooks -> Hooks) -> Interface -> Interface
forall a b. (a -> b) -> a -> b
$ \Hooks
hooks ->
Hooks
hooks { hookEvaluateEnums :: EnumEvaluator
hookEvaluateEnums = EnumEvaluator
calculateEnumValues }
calculateEnumValues :: EnumEvaluator
calculateEnumValues :: EnumEvaluator
calculateEnumValues EnumEvaluatorArgs
args =
String
-> Bool
-> (String -> IO (Bool, Maybe EnumEvaluatorResult))
-> IO (Maybe EnumEvaluatorResult)
forall a. String -> Bool -> (String -> IO (Bool, a)) -> IO a
withTempDirectory String
"qtahenum" Bool
removeBuildFailures ((String -> IO (Bool, Maybe EnumEvaluatorResult))
-> IO (Maybe EnumEvaluatorResult))
-> (String -> IO (Bool, Maybe EnumEvaluatorResult))
-> IO (Maybe EnumEvaluatorResult)
forall a b. (a -> b) -> a -> b
$ \String
dir ->
String
-> IO (Bool, Maybe EnumEvaluatorResult)
-> IO (Bool, Maybe EnumEvaluatorResult)
forall a. String -> IO a -> IO a
withCurrentDirectory String
dir (IO (Bool, Maybe EnumEvaluatorResult)
-> IO (Bool, Maybe EnumEvaluatorResult))
-> IO (Bool, Maybe EnumEvaluatorResult)
-> IO (Bool, Maybe EnumEvaluatorResult)
forall a b. (a -> b) -> a -> b
$ do
let sourceFile :: String
sourceFile = String
"qtahenum.cpp"
qmakeFile :: String
qmakeFile = String
"qtahenum.pro"
String -> ByteString -> IO ()
B.writeFile String
sourceFile (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ EnumEvaluatorArgs -> ByteString
makeCppSourceToEvaluateEnums EnumEvaluatorArgs
args
String -> String -> IO ()
writeFile String
qmakeFile (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$
[String] -> String
unlines
[ String
"# This file is generated by qtah-generator."
, String
""
, String
"QT += core gui"
, String
"greaterThan(QT_MAJOR_VERSION, 4): QT += widgets"
, String
"CONFIG -= debug_and_release"
, String
"CONFIG += cmdline"
, String
"TARGET = qtahenum"
, String
"SOURCES += " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
sourceFile
]
String -> [String] -> IO ()
callProcess String
qmakeExecutable ([String] -> IO ()) -> [String] -> IO ()
forall a b. (a -> b) -> a -> b
$ [String]
qmakeArguments [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
qmakeFile]
String -> [String] -> IO ()
callProcess String
"make" []
String
out <- String -> [String] -> String -> IO String
readProcess (String
"." String -> String -> String
</> String
"qtahenum") [] String
""
Maybe EnumEvaluatorResult
result <- case EnumEvaluatorArgs -> String -> Either String EnumEvaluatorResult
interpretOutputToEvaluateEnums EnumEvaluatorArgs
args String
out of
Left String
err -> do Handle -> String -> IO ()
hPutStrLn Handle
stderr String
err
Maybe EnumEvaluatorResult -> IO (Maybe EnumEvaluatorResult)
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe EnumEvaluatorResult
forall a. Maybe a
Nothing
Right EnumEvaluatorResult
values -> Maybe EnumEvaluatorResult -> IO (Maybe EnumEvaluatorResult)
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe EnumEvaluatorResult -> IO (Maybe EnumEvaluatorResult))
-> Maybe EnumEvaluatorResult -> IO (Maybe EnumEvaluatorResult)
forall a b. (a -> b) -> a -> b
$ EnumEvaluatorResult -> Maybe EnumEvaluatorResult
forall a. a -> Maybe a
Just EnumEvaluatorResult
values
let remove :: Bool
remove = Bool
False Bool -> Bool -> Bool
&& (Maybe EnumEvaluatorResult -> Bool
forall a. Maybe a -> Bool
isJust Maybe EnumEvaluatorResult
result Bool -> Bool -> Bool
|| Bool
removeBuildFailures)
(Bool, Maybe EnumEvaluatorResult)
-> IO (Bool, Maybe EnumEvaluatorResult)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
remove, Maybe EnumEvaluatorResult
result)
where removeBuildFailures :: Bool
removeBuildFailures = Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ EnumEvaluatorArgs -> Bool
enumEvaluatorArgsKeepOutputsOnFailure EnumEvaluatorArgs
args