{- |
Copyright: (c) 2020 Kowainik
SPDX-License-Identifier: MPL-2.0
Maintainer: Kowainik <xrom.xkov@gmail.com>

Main running module.
-}

module Stan
    ( run
    , runStan
    , getAnalysis
    , getStanConfig

      -- ** Internal
    , createCabalExtensionsMap
    ) where

import Colourista (errorMessage, formatWith, infoMessage, italic, successMessage, warningMessage)
import Data.Aeson.Micro (encode)
import System.Directory (doesFileExist, getCurrentDirectory)
import System.FilePath (takeFileName)
import Trial (Trial (..), prettyTaggedTrial, prettyTrial, prettyTrialWith, trialToMaybe,
              whenResult_)

import Stan.Analysis (Analysis (..), runAnalysis)
import Stan.Analysis.Pretty (prettyShowAnalysis)
import Stan.Browse (openBrowser)
import Stan.Cabal (createCabalExtensionsMap, usedCabalFiles)
import Stan.Cli (CliToTomlArgs (..), InspectionArgs (..), ReportArgs (..), StanArgs (..),
                 StanCommand (..), TomlToCliArgs (..), runStanCli)
import Stan.Config (ConfigP (..), applyConfig, configToCliCommand, defaultConfig, finaliseConfig, Config)
import Stan.Config.Pretty (prettyConfigCli)
import Stan.Core.Id (Id (..))
import Stan.EnvVars (EnvVars (..), envVarsToText, getEnvVars)
import Stan.Hie (readHieFiles)
import Stan.Hie.Compat (HieFile (..))
import Stan.Info (ProjectInfo (..), StanEnv (..))
import Stan.Inspection (Inspection (..), inspectionsMd, prettyShowInspection,
                        prettyShowInspectionShort)
import Stan.Inspection.All (getInspectionById, inspections, lookupInspectionById)
import Stan.Observation (Observation (..), prettyShowIgnoredObservations)
import Stan.Report (generateReport)
import Stan.Severity (Severity (Error))
import Stan.Toml (configCodec, getTomlConfig, usedTomlFiles)

import qualified Toml


run :: IO ()
run :: IO ()
run = IO StanCommand
runStanCli IO StanCommand -> (StanCommand -> IO ()) -> IO ()
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \case
    Stan StanArgs
stanArgs -> StanArgs -> IO ()
runStan StanArgs
stanArgs
    StanInspection InspectionArgs
inspectionArgs -> InspectionArgs -> IO ()
runInspection InspectionArgs
inspectionArgs
    StanTomlToCli TomlToCliArgs
tomlToCliArgs -> TomlToCliArgs -> IO ()
runTomlToCli TomlToCliArgs
tomlToCliArgs
    StanCliToToml CliToTomlArgs
cliToTomlArgs -> CliToTomlArgs -> IO ()
runCliToToml CliToTomlArgs
cliToTomlArgs
    StanCommand
StanInspectionsToMd -> Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putTextLn (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ [Inspection] -> Text
inspectionsMd [Inspection]
inspections

getStanConfig :: StanArgs -> Bool -> IO (Trial Text Config, Bool, EnvVars)
getStanConfig :: StanArgs -> Bool -> IO (Trial Text Config, Bool, EnvVars)
getStanConfig StanArgs{Bool
FilePath
[FilePath]
Maybe FilePath
Maybe ReportArgs
TaggedTrial Text Bool
OutputSettings
PartialConfig
stanArgsHiedir :: FilePath
stanArgsCabalFilePath :: [FilePath]
stanArgsOutputSettings :: OutputSettings
stanArgsReport :: Maybe ReportArgs
stanArgsUseDefaultConfigFile :: TaggedTrial Text Bool
stanArgsConfigFile :: Maybe FilePath
stanArgsConfig :: PartialConfig
stanArgsJsonOut :: Bool
stanArgsHiedir :: StanArgs -> FilePath
stanArgsCabalFilePath :: StanArgs -> [FilePath]
stanArgsOutputSettings :: StanArgs -> OutputSettings
stanArgsReport :: StanArgs -> Maybe ReportArgs
stanArgsUseDefaultConfigFile :: StanArgs -> TaggedTrial Text Bool
stanArgsConfigFile :: StanArgs -> Maybe FilePath
stanArgsConfig :: StanArgs -> PartialConfig
stanArgsJsonOut :: StanArgs -> Bool
..} Bool
notJson = do
    -- ENV vars
    env :: EnvVars
env@EnvVars{TaggedTrial Text Bool
envVarsUseDefaultConfigFile :: TaggedTrial Text Bool
envVarsUseDefaultConfigFile :: EnvVars -> TaggedTrial Text Bool
..} <- IO EnvVars
getEnvVars
    let defConfTrial :: TaggedTrial Text Bool
defConfTrial = TaggedTrial Text Bool
envVarsUseDefaultConfigFile TaggedTrial Text Bool
-> TaggedTrial Text Bool -> TaggedTrial Text Bool
forall a. Semigroup a => a -> a -> a
<> TaggedTrial Text Bool
stanArgsUseDefaultConfigFile
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
notJson (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        Text -> IO ()
infoMessage Text
"Checking environment variables and CLI arguments for default configurations file usage..."
        Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putTextLn (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text -> Text
indent (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ TaggedTrial Text Bool -> Text
forall a e.
(Show a, Semigroup e, IsString e) =>
TaggedTrial e a -> e
prettyTaggedTrial TaggedTrial Text Bool
defConfTrial
    let useDefConfig :: Bool
useDefConfig = Bool -> ((Text, Bool) -> Bool) -> Maybe (Text, Bool) -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
True (Text, Bool) -> Bool
forall a b. (a, b) -> b
snd (TaggedTrial Text Bool -> Maybe (Text, Bool)
forall e a. Trial e a -> Maybe a
trialToMaybe TaggedTrial Text Bool
defConfTrial)
    -- config
    PartialConfig
tomlConfig <- Bool -> Bool -> Maybe FilePath -> IO PartialConfig
getTomlConfig Bool
notJson Bool
useDefConfig Maybe FilePath
stanArgsConfigFile
    let configTrial :: Trial Text Config
configTrial = PartialConfig -> Trial Text Config
finaliseConfig (PartialConfig -> Trial Text Config)
-> PartialConfig -> Trial Text Config
forall a b. (a -> b) -> a -> b
$ PartialConfig
defaultConfig PartialConfig -> PartialConfig -> PartialConfig
forall a. Semigroup a => a -> a -> a
<> PartialConfig
tomlConfig PartialConfig -> PartialConfig -> PartialConfig
forall a. Semigroup a => a -> a -> a
<> PartialConfig
stanArgsConfig
    Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
notJson (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
        Text -> IO ()
infoMessage Text
"The following Configurations are used:\n"
        Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putTextLn (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text -> Text
indent (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ (Config -> FilePath) -> Trial Text Config -> Text
forall e a.
(Semigroup e, IsString e) =>
(a -> FilePath) -> Trial e a -> e
prettyTrialWith (Text -> FilePath
forall a. ToString a => a -> FilePath
toString (Text -> FilePath) -> (Config -> Text) -> Config -> FilePath
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Config -> Text
prettyConfigCli) Trial Text Config
configTrial
    (Trial Text Config, Bool, EnvVars)
-> IO (Trial Text Config, Bool, EnvVars)
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Trial Text Config
configTrial, Bool
useDefConfig, EnvVars
env)

getAnalysis :: StanArgs -> Bool -> Config -> [HieFile] -> IO Analysis
getAnalysis :: StanArgs -> Bool -> Config -> [HieFile] -> IO Analysis
getAnalysis StanArgs{Bool
FilePath
[FilePath]
Maybe FilePath
Maybe ReportArgs
TaggedTrial Text Bool
OutputSettings
PartialConfig
stanArgsHiedir :: StanArgs -> FilePath
stanArgsCabalFilePath :: StanArgs -> [FilePath]
stanArgsOutputSettings :: StanArgs -> OutputSettings
stanArgsReport :: StanArgs -> Maybe ReportArgs
stanArgsUseDefaultConfigFile :: StanArgs -> TaggedTrial Text Bool
stanArgsConfigFile :: StanArgs -> Maybe FilePath
stanArgsConfig :: StanArgs -> PartialConfig
stanArgsJsonOut :: StanArgs -> Bool
stanArgsHiedir :: FilePath
stanArgsCabalFilePath :: [FilePath]
stanArgsOutputSettings :: OutputSettings
stanArgsReport :: Maybe ReportArgs
stanArgsUseDefaultConfigFile :: TaggedTrial Text Bool
stanArgsConfigFile :: Maybe FilePath
stanArgsConfig :: PartialConfig
stanArgsJsonOut :: Bool
..} Bool
notJson Config
config [HieFile]
hieFiles = do
    -- create cabal default extensions map
    Map FilePath (Either ExtensionsError ParsedExtensions)
cabalExtensionsMap <- Bool
-> [FilePath]
-> [HieFile]
-> IO (Map FilePath (Either ExtensionsError ParsedExtensions))
createCabalExtensionsMap Bool
notJson [FilePath]
stanArgsCabalFilePath [HieFile]
hieFiles
    -- get checks for each file
    let checksMap :: HashMap FilePath (HashSet (Id Inspection))
checksMap = [FilePath] -> Config -> HashMap FilePath (HashSet (Id Inspection))
applyConfig ((HieFile -> FilePath) -> [HieFile] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map HieFile -> FilePath
hie_hs_file [HieFile]
hieFiles) Config
config

    let analysis :: Analysis
analysis = Map FilePath (Either ExtensionsError ParsedExtensions)
-> HashMap FilePath (HashSet (Id Inspection))
-> [Id Observation]
-> [HieFile]
-> Analysis
runAnalysis Map FilePath (Either ExtensionsError ParsedExtensions)
cabalExtensionsMap HashMap FilePath (HashSet (Id Inspection))
checksMap (Config -> 'Final ::- [Id Observation]
forall (p :: Phase Text). ConfigP p -> p ::- [Id Observation]
configIgnored Config
config) [HieFile]
hieFiles
    -- show what observations are ignored
    Analysis -> IO Analysis
forall a. a -> IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Analysis
analysis

runStan :: StanArgs -> IO ()
runStan :: StanArgs -> IO ()
runStan stanArgs :: StanArgs
stanArgs@StanArgs{Bool
FilePath
[FilePath]
Maybe FilePath
Maybe ReportArgs
TaggedTrial Text Bool
OutputSettings
PartialConfig
stanArgsHiedir :: StanArgs -> FilePath
stanArgsCabalFilePath :: StanArgs -> [FilePath]
stanArgsOutputSettings :: StanArgs -> OutputSettings
stanArgsReport :: StanArgs -> Maybe ReportArgs
stanArgsUseDefaultConfigFile :: StanArgs -> TaggedTrial Text Bool
stanArgsConfigFile :: StanArgs -> Maybe FilePath
stanArgsConfig :: StanArgs -> PartialConfig
stanArgsJsonOut :: StanArgs -> Bool
stanArgsHiedir :: FilePath
stanArgsCabalFilePath :: [FilePath]
stanArgsOutputSettings :: OutputSettings
stanArgsReport :: Maybe ReportArgs
stanArgsUseDefaultConfigFile :: TaggedTrial Text Bool
stanArgsConfigFile :: Maybe FilePath
stanArgsConfig :: PartialConfig
stanArgsJsonOut :: Bool
..} = do
    let notJson :: Bool
notJson = Bool -> Bool
not Bool
stanArgsJsonOut
    (Trial Text Config
configTrial, Bool
useDefConfig, EnvVars
env) <- StanArgs -> Bool -> IO (Trial Text Config, Bool, EnvVars)
getStanConfig StanArgs
stanArgs Bool
notJson
    Trial Text Config -> ([Text] -> Config -> IO ()) -> IO ()
forall (f :: * -> *) e a.
Applicative f =>
Trial e a -> ([e] -> a -> f ()) -> f ()
whenResult_ Trial Text Config
configTrial (([Text] -> Config -> IO ()) -> IO ())
-> ([Text] -> Config -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \[Text]
warnings Config
config -> do
        [HieFile]
hieFiles <- FilePath -> IO [HieFile]
readHieFiles FilePath
stanArgsHiedir
        Analysis
analysis <- StanArgs -> Bool -> Config -> [HieFile] -> IO Analysis
getAnalysis StanArgs
stanArgs Bool
notJson Config
config [HieFile]
hieFiles
        -- show what observations are ignored
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
notJson (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putText (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text -> Text
indent (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ [Id Observation] -> Observations -> Text
prettyShowIgnoredObservations
            (Config -> 'Final ::- [Id Observation]
forall (p :: Phase Text). ConfigP p -> p ::- [Id Observation]
configIgnored Config
config)
            (Analysis -> Observations
analysisIgnoredObservations Analysis
analysis)
        -- show the result
        let observations :: Observations
observations = Analysis -> Observations
analysisObservations Analysis
analysis
        let isNullObs :: Bool
isNullObs = Observations -> Bool
forall a. Slist a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null Observations
observations
        if Bool
notJson
        then do
            if Bool
isNullObs
            then Text -> IO ()
successMessage Text
"All clean! Stan did not find any observations at the moment."
            else Text -> IO ()
warningMessage Text
"Stan found the following observations for the project:\n"
            Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putTextLn (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Analysis -> OutputSettings -> Text
prettyShowAnalysis Analysis
analysis OutputSettings
stanArgsOutputSettings
        else LByteString -> IO ()
forall (m :: * -> *). MonadIO m => LByteString -> m ()
putLBSLn (LByteString -> IO ()) -> LByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ Analysis -> LByteString
forall a. ToJSON a => a -> LByteString
encode Analysis
analysis

        -- report generation
        Maybe ReportArgs -> (ReportArgs -> IO ()) -> IO ()
forall (f :: * -> *) a.
Applicative f =>
Maybe a -> (a -> f ()) -> f ()
whenJust Maybe ReportArgs
stanArgsReport ((ReportArgs -> IO ()) -> IO ()) -> (ReportArgs -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \ReportArgs{Bool
reportArgsBrowse :: Bool
reportArgsBrowse :: ReportArgs -> Bool
..} -> do
            -- Project Info
            FilePath
piName <- FilePath -> FilePath
takeFileName (FilePath -> FilePath) -> IO FilePath -> IO FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> IO FilePath
getCurrentDirectory
            [FilePath]
piCabalFiles <- [FilePath] -> IO [FilePath]
usedCabalFiles [FilePath]
stanArgsCabalFilePath
            let piHieDir :: FilePath
piHieDir = FilePath
stanArgsHiedir
            let piFileNumber :: Int
piFileNumber = [HieFile] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [HieFile]
hieFiles
            -- Stan Env Info
            [FilePath]
seCliArgs <- IO [FilePath]
forall (m :: * -> *). MonadIO m => m [FilePath]
getArgs
            [FilePath]
seTomlFiles <- Bool -> Maybe FilePath -> IO [FilePath]
usedTomlFiles Bool
useDefConfig Maybe FilePath
stanArgsConfigFile
            let stanEnv :: StanEnv
stanEnv = StanEnv
                    { seEnvVars :: Text
seEnvVars = EnvVars -> Text
envVarsToText EnvVars
env
                    , [FilePath]
seCliArgs :: [FilePath]
seTomlFiles :: [FilePath]
seTomlFiles :: [FilePath]
seCliArgs :: [FilePath]
..
                    }
            Analysis -> Config -> [Text] -> StanEnv -> ProjectInfo -> IO ()
generateReport Analysis
analysis Config
config [Text]
warnings StanEnv
stanEnv ProjectInfo{Int
FilePath
[FilePath]
piName :: FilePath
piCabalFiles :: [FilePath]
piHieDir :: FilePath
piFileNumber :: Int
piName :: FilePath
piCabalFiles :: [FilePath]
piHieDir :: FilePath
piFileNumber :: Int
..}
            Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
notJson (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Text -> IO ()
infoMessage Text
"Report is generated here -> stan.html"
            Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
reportArgsBrowse (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> IO ()
openBrowser FilePath
"stan.html"

        -- decide on exit status
        Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when
            (  Bool -> Bool
not Bool
isNullObs
            Bool -> Bool -> Bool
&& (Observation -> Bool) -> Observations -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((Severity -> Severity -> Bool
forall a. Ord a => a -> a -> Bool
>= Severity
Error) (Severity -> Bool)
-> (Observation -> Severity) -> Observation -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Observation -> Severity
getObservationSeverity) Observations
observations
            )
            IO ()
forall (m :: * -> *) a. MonadIO m => m a
exitFailure
  where
    getObservationSeverity :: Observation -> Severity
    getObservationSeverity :: Observation -> Severity
getObservationSeverity = Inspection -> Severity
inspectionSeverity (Inspection -> Severity)
-> (Observation -> Inspection) -> Observation -> Severity
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Id Inspection -> Inspection
getInspectionById (Id Inspection -> Inspection)
-> (Observation -> Id Inspection) -> Observation -> Inspection
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Observation -> Id Inspection
observationInspectionId

indent :: Text -> Text
indent :: Text -> Text
indent = [Text] -> Text
forall t. IsText t "unlines" => [t] -> t
unlines ([Text] -> Text) -> (Text -> [Text]) -> Text -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text) -> [Text] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (Text
"    " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<>) ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> [Text]
forall t. IsText t "lines" => t -> [t]
lines

runInspection :: InspectionArgs -> IO ()
runInspection :: InspectionArgs -> IO ()
runInspection InspectionArgs{Maybe (Id Inspection)
inspectionArgsId :: Maybe (Id Inspection)
inspectionArgsId :: InspectionArgs -> Maybe (Id Inspection)
..} = case Maybe (Id Inspection)
inspectionArgsId of
    Maybe (Id Inspection)
Nothing  -> [Inspection] -> (Inspection -> IO ()) -> IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [Inspection]
inspections (Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putTextLn (Text -> IO ()) -> (Inspection -> Text) -> Inspection -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Inspection -> Text
prettyShowInspectionShort)
    Just Id Inspection
insId -> case Id Inspection -> Maybe Inspection
lookupInspectionById Id Inspection
insId of
        Just Inspection
ins -> Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putTextLn (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Inspection -> Text
prettyShowInspection Inspection
ins
        Maybe Inspection
Nothing  -> do
            Text -> IO ()
errorMessage (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
"Inspection with such ID does not exist: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Id Inspection -> Text
forall a. Id a -> Text
unId Id Inspection
insId
            Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putTextLn (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
" 💡 " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Text] -> Text -> Text
forall str. (IsString str, Semigroup str) => [str] -> str -> str
formatWith [Text
forall str. IsString str => str
italic] Text
"Use 'stan inspection' to see the list of all available inspections."

runTomlToCli :: TomlToCliArgs -> IO ()
runTomlToCli :: TomlToCliArgs -> IO ()
runTomlToCli TomlToCliArgs{Maybe FilePath
tomlToCliArgsFilePath :: Maybe FilePath
tomlToCliArgsFilePath :: TomlToCliArgs -> Maybe FilePath
..} = do
    let useDefConfig :: Bool
useDefConfig = Maybe FilePath -> Bool
forall a. Maybe a -> Bool
isNothing Maybe FilePath
tomlToCliArgsFilePath
    PartialConfig
partialConfig <- Bool -> Bool -> Maybe FilePath -> IO PartialConfig
getTomlConfig Bool
True Bool
useDefConfig Maybe FilePath
tomlToCliArgsFilePath
    case PartialConfig -> Trial Text Config
finaliseConfig PartialConfig
partialConfig of
        Result DList Text
_ Config
res -> Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putTextLn (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Config -> Text
configToCliCommand Config
res
        Trial Text Config
fiasco -> do
            Text -> IO ()
errorMessage Text
"Could not get Configurations:"
            Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putTextLn (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Trial Text Config -> Text
forall a e. (Show a, Semigroup e, IsString e) => Trial e a -> e
prettyTrial Trial Text Config
fiasco

runCliToToml :: CliToTomlArgs -> IO ()
runCliToToml :: CliToTomlArgs -> IO ()
runCliToToml CliToTomlArgs{Maybe FilePath
PartialConfig
cliToTomlArgsFilePath :: Maybe FilePath
cliToTomlArgsConfig :: PartialConfig
cliToTomlArgsFilePath :: CliToTomlArgs -> Maybe FilePath
cliToTomlArgsConfig :: CliToTomlArgs -> PartialConfig
..} = do
    let toml :: Text
toml = TomlCodec PartialConfig -> PartialConfig -> Text
forall a. TomlCodec a -> a -> Text
Toml.encode TomlCodec PartialConfig
configCodec PartialConfig
cliToTomlArgsConfig
    case Maybe FilePath
cliToTomlArgsFilePath of
        Maybe FilePath
Nothing -> do
            Text -> IO ()
forall (m :: * -> *). MonadIO m => Text -> m ()
putTextLn Text
toml
            Text -> IO ()
infoMessage Text
"Copy-paste the above TOML into .stan.toml and stan will pick up this file on the next run"
        Just FilePath
path -> do
            Bool
isFile <- FilePath -> IO Bool
doesFileExist FilePath
path
            if Bool
isFile
            then Text -> IO ()
errorMessage (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
"Aborting writing to file because it already exists: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> FilePath -> Text
forall a. ToText a => a -> Text
toText FilePath
path
            else do
                FilePath -> Text -> IO ()
forall (m :: * -> *). MonadIO m => FilePath -> Text -> m ()
writeFileText FilePath
path Text
toml
                Text -> IO ()
infoMessage (Text -> IO ()) -> Text -> IO ()
forall a b. (a -> b) -> a -> b
$ Text
"TOML configuration is written to file: " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> FilePath -> Text
forall a. ToText a => a -> Text
toText FilePath
path