module IdeSession.Config ( SessionConfig(..) , InProcess , ProgramSearchPath, ProgramSearchPathEntry(..) , sessionConfigFromEnv , defaultSessionConfig ) where import Distribution.License (License (..)) import Distribution.Simple (PackageDB (..), PackageDBStack) import Distribution.Simple.Program.Find (ProgramSearchPath,ProgramSearchPathEntry(..),defaultProgramSearchPath) import System.FilePath (splitSearchPath) import System.Directory (getCurrentDirectory, getTemporaryDirectory) import System.Environment (lookupEnv) type InProcess = Bool -- | Configuration parameters for a session. These remain the same throughout -- the whole session's lifetime. -- data SessionConfig = SessionConfig { -- | The directory to use for all session files. configDir :: FilePath -- | When set to Just "", we'll use the files in that -- directory as source and datafiles. This means that the -- ide-backend is no longer directly managing the files, and -- file updates like 'updateSourceFile' will fail. -- -- Note that this feature is experimental and does not have a -- suite of tests. -- -- Since this is likely used with an existing cabal project, which -- might have multiple source directories, you'll likely want to -- use 'TargetsInclude' instead of 'TargetsExclude'. , configLocalWorkingDir :: Maybe FilePath -- | Extra directories in which to look for programs, including ghc -- and other tools. Note that the @$PATH@ is still searched /first/, these -- directories are extra. , configExtraPathDirs :: [FilePath] -- | Should the GHC client run in-process? -- NOTE: This is currently broken. Set to False. , configInProcess :: InProcess -- | Whether to generate module type/autocompletion info. , configGenerateModInfo :: Bool -- | Package DBs to consult , configPackageDBStack :: PackageDBStack -- | Packages that don't need the .cabal files provided for license -- concatenation (e.g., because they are covered by the core license set). , configLicenseExc :: [String] -- | Hard-coded package licence information, e.g., for the packages -- that always stay installed in-place in the GHC tree, so it's -- troublesome to automatically retrieve their .cabal files. , configLicenseFixed :: [( String , (Maybe License, Maybe FilePath, Maybe String) )] -- | Function to be used for logging. Messages logged in this manner may be -- provided to users in a special debugging UI. , configLog :: String -> IO () -- | Delete temporary files when session finishes? -- (Defaults to True; mostly for internal debugging purposes) , configDeleteTempFiles :: Bool -- | The name of the ide-backend-server program to use, and where to find it. -- The default is @(defaultProgramSearchPath,"ide-backend-server")@, -- that is, to look for a program called ide-backend-server on the system -- search path only. , configIdeBackendServer :: (ProgramSearchPath,FilePath) -- | The name of the ide-backend-exe-cabal program to use, and where to find it. -- The default is @(defaultProgramSearchPath,"ide-backend-exe-cabal")@. , configIdeBackendExeCabal :: (ProgramSearchPath,FilePath) } -- | Get the default local session configuration, pulling the following -- information from the environment: -- -- * OS temporary directory (used for session.* files) -- -- * Current working directory - assumed to be the project root. Instead -- of sending files in updates, they are read from the filesystem. -- -- * GHC package database. Like GHC, it takes the GHC_PACKAGE_PATH, -- and uses this list of package databases. This allows ide-backend -- to do the 'right thing' when used with tools like stack. -- -- NOTE: In order for it to pull GHC_PACKAGE_PATH from the environment, -- this must be used before any ide-backend session is initialized. This -- is because the environment variable gets unset due to -- https://github.com/haskell/cabal/issues/1944 sessionConfigFromEnv :: IO SessionConfig sessionConfigFromEnv = do tmpDir <- getTemporaryDirectory cwd <- getCurrentDirectory mpkgPath <- lookupEnv "GHC_PACKAGE_PATH" let dbStack = case mpkgPath of Nothing -> configPackageDBStack defaultSessionConfig Just pkgPath -> let dbPaths = drop 1 (reverse (splitSearchPath pkgPath)) in GlobalPackageDB : map SpecificPackageDB dbPaths return defaultSessionConfig { configDir = tmpDir , configLocalWorkingDir = Just cwd , configPackageDBStack = dbStack } -- | Default session configuration. Most users will probably instead -- want 'localSessionConfigFromEnv'. -- -- Use this instead of creating your own SessionConfig to be robust -- against extensions of SessionConfig. -- -- > defaultSessionConfig = SessionConfig { -- > configDir = "." -- > , configLocalWorkingDir = Nothing -- > , configExtraPathDirs = [] -- > , configInProcess = False -- > , configGenerateModInfo = True -- > , configPackageDBStack = [GlobalPackageDB, UserPackageDB] -- > -- ghc-prim, integer-gmp, etc., all have their own licenses specified -- > -- in their .cabal files. -- > , configLicenseExc = ["rts"] -- > , configLicenseFixed = [ -- > ("bin-package-db", (Just BSD3, Nothing, Nothing)) -- > , ("ghc", (Just BSD3, Just "../LICENSE", Just "The GHC Team")) -- > , ("ghc-prim", (Just BSD3, Just "LICENSE", Nothing)) -- > , ("integer-gmp", (Just BSD3, Just "LICENSE", Nothing)) -- > ] -- > , configLog = const $ return () -- > , configDeleteTempFiles = True -- > , configIdeBackendServer = (defaultProgramSearchPath,"ide-backend-server") -- > , configIdeBackendExeCabal = (defaultProgramSearchPath,"ide-backend-exe-cabal") -- > } defaultSessionConfig :: SessionConfig defaultSessionConfig = SessionConfig { configDir = "." , configLocalWorkingDir = Nothing , configExtraPathDirs = [] , configInProcess = False , configGenerateModInfo = True , configPackageDBStack = [GlobalPackageDB, UserPackageDB] -- ghc-prim, integer-gmp, etc., all have their own licenses specified -- in their .cabal files. , configLicenseExc = ["rts"] , configLicenseFixed = [ ("bin-package-db", (Just BSD3, Nothing, Nothing)) , ("ghc", (Just BSD3, Just "../LICENSE", Just "The GHC Team")) , ("ghc-prim", (Just BSD3, Just "LICENSE", Nothing)) , ("integer-gmp", (Just BSD3, Just "LICENSE", Nothing)) ] , configLog = const $ return () , configDeleteTempFiles = True , configIdeBackendServer = (defaultProgramSearchPath,"ide-backend-server") , configIdeBackendExeCabal = (defaultProgramSearchPath,"ide-backend-exe-cabal") }