packages feed

tricorder-0.7.0.0: src/Tricorder/CLI/Main.hs

module Tricorder.CLI.Main (main) where

import Atelier.Effects.Arguments (runArgumentsIO)
import Atelier.Effects.Clock (runClock)
import Atelier.Effects.Conc (runConc)
import Atelier.Effects.Console (Console, runConsole, runConsoleOut)
import Atelier.Effects.Delay (runDelay)
import Atelier.Effects.Env (runEnv)
import Atelier.Effects.Exit (exitFailure, runExit)
import Atelier.Effects.File (runFile)
import Atelier.Effects.FileSystem (runFileSystemIO)
import Atelier.Effects.Log (runLogNoOp)
import Atelier.Effects.Posix.Daemons (runDaemons)
import Atelier.Effects.Process (runProcessIO)
import Atelier.Effects.Timeout (runTimeout)
import Atelier.Signal (installTerminationHandler)
import Data.Default (def)
import Effectful (runEff)
import Effectful.Concurrent (runConcurrent)
import Effectful.Provider (provideWith_, runProvider_)

import Atelier.Effects.Console qualified as Console
import Atelier.Effects.FileSystem.Glob qualified as Glob
import Atelier.Effects.Input qualified as Input

import Tricorder.CLI.Arguments (runArguments)
import Tricorder.CLI.UI.Brick (runBrick)
import Tricorder.CLI.UI.BrickChan (runBrickChan)
import Tricorder.Config (asInput)
import Tricorder.Runtime (runLogPath, runPidFile, runProjectRoot, runRuntimeDir, runSocketPath)
import Tricorder.Session.CabalFile (inputCabalFiles)
import Tricorder.Session.CommandTemplate (CommandTemplate (..))
import Tricorder.Session.Stage.Build.Session (Session (..))

import Tricorder.CLI.App qualified as App
import Tricorder.CLI.UI.Keys qualified as Keys
import Tricorder.Config.LoadedConfig qualified as LoadedConfig
import Tricorder.Daemon.DaemonInfo qualified as DaemonInfo
import Tricorder.Session qualified as Session
import Tricorder.Session.StackProject qualified as StackProject
import Tricorder.Socket.UnixSocket qualified as UnixSocket
import Tricorder.SourceLookup.GhcPkg qualified as GhcPkg
import Tricorder.SourceLookup.Hackage qualified as Hackage
import Tricorder.SourceLookup.PackageStore qualified as PackageStore


main :: IO ()
main =
    runEff
        . runTimeout
        . runConcurrent
        . runConc
        . runBrickChan
        . runBrick
        . runConsole
        . runProvider_ @Console @Console.Output runConsoleOut
        . runExit
        . runClock
        . runDelay
        . runFile
        . runFileSystemIO
        . Glob.runIO
        . runProjectRoot
        . runRuntimeDir
        . runPidFile
        . runSocketPath
        . runLogPath
        . LoadedConfig.asInput
        . LoadedConfig.asNestedInput @"keybindings" @Keys.Config
        . Input.map (either @_ @Keys.Config (const def) id)
        . Input.toReader @Keys.Config
        . runDaemons
        . runProcessIO
        . runArgumentsIO
        . runArguments
        . UnixSocket.runIO
        . runEnv
        . runLogNoOp
        . StackProject.inputWithCache
        . inputCabalFiles
        . Tricorder.Config.asInput
        $ do
            Session.load >>= \case
                Left err -> do
                    provideWith_ @Console Console.Stderr
                        $ Console.putTextLn
                        $ "Failed to load session: " <> err
                    exitFailure
                Right session ->
                    Input.withConst session
                        -- TODO: Make whatever uses this 'Repl' value use it
                        -- more sensibly. Arbitrarily using the build stage's
                        -- 'Repl' doesn't seem right.
                        . Input.withConst session.buildSession.commandTemplate.repl
                        . GhcPkg.runGhcPkgIO
                        . PackageStore.run
                        . Hackage.run
                        . DaemonInfo.runInput
                        $ do
                            installTerminationHandler
                            App.run