{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE MultiWayIf #-} module Phoityne.IO.Main (run) where -- モジュール import Phoityne.Constant import qualified Phoityne.Argument as A import qualified Phoityne.IO.Control as CTRL -- システム import System.IO import Data.Either.Utils import Safe import qualified Control.Exception as E import qualified System.IO.Error as E import qualified Data.ConfigFile as C import qualified System.Console.CmdArgs as CMD import qualified System.Log.Logger as L import qualified System.Log.Formatter as L import qualified System.Log.Handler as LH import qualified System.Log.Handler.Simple as LHS -- | -- アプリケーションメイン -- run :: IO Int run = flip E.catches handlers $ do -- コマンドライン引数設定 args <- getArgs -- INI設定ファイルのRead iniSet <- loadIniFile args -- Loggerのセットアップ setupLogger iniSet -- ロジック実行 flip E.finally finalProc $ do CTRL.run args iniSet where handlers = [ E.Handler helpExcept , E.Handler ioExcept , E.Handler someExcept ] finalProc = L.removeAllHandlers helpExcept (_ :: A.HelpExitException) = return 0 ioExcept (e :: E.IOException) = print e >> return 1 someExcept (e :: E.SomeException) = print e >> return 1 -- | -- 引数データの取得 -- getArgs :: IO A.ArgData getArgs = E.catches (CMD.cmdArgs A.config) handlers where handlers = [E.Handler someExcept] someExcept (e :: E.SomeException) = if | "ExitSuccess" == show e -> E.throw A.HelpExitException | otherwise -> E.throwIO e -- | -- INI設定ファイルデータの取得 -- loadIniFile :: A.ArgData -- コマンドライン引数 -> IO C.ConfigParser -- INI設定 loadIniFile args = do cp <- if null (A.file args) then return $ forceEither $ C.readstring C.emptyCP defaultIniSetting else forceEither <$> C.readfile C.emptyCP (A.file args) return cp{ C.accessfunc = C.interpolatingAccess 5 } -- | -- デフォルトINI設定 -- defaultIniSetting :: String defaultIniSetting = unlines [ "[DEFAULT]" , "work_dir = ./" , "" , "[LOG]" , "file = %(work_dir)sphoityne.log" , "level = INFO" , "" , "[PHOITYNE]" , "target = ." , "ghci_auto_start = True" , "system_font_name = MS Gothic" , "system_font_size = 9" ] -- | -- Loggerのセットアップ -- setupLogger :: C.ConfigParser -- INI設定 -> IO () -- なし setupLogger cp = do let logFile = forceEither $ C.get cp _INI_SEC_LOG _INI_LOG_FILE logLevel = forceEither $ C.get cp _INI_SEC_LOG _INI_LOG_LEVEL level <- case readMay logLevel of Just a -> return a Nothing -> E.throwIO . E.userError $ "invalid log level[" ++ logLevel ++ "]" logStream <- openFile logFile AppendMode hSetEncoding logStream utf8 logH <- LHS.streamHandler logStream level logSTD <- LHS.streamHandler stdout level let logHandle = logH {LHS.closeFunc = hClose} logFormat = L.tfLogFormatter _LOG_FORMAT_DATE _LOG_FORMAT logHandler = LH.setFormatter logHandle logFormat logHndlerSTD = LH.setFormatter logSTD logFormat L.updateGlobalLogger L.rootLoggerName $ L.setHandlers ([] :: [LHS.GenericHandler Handle]) L.updateGlobalLogger _LOG_NAME $ L.setHandlers [logHandler, logHndlerSTD] L.updateGlobalLogger _LOG_NAME $ L.setLevel level