diff options
-rw-r--r-- | ghc/GHCi/UI.hs | 44 | ||||
-rw-r--r-- | ghc/GHCi/UI/Monad.hs | 11 |
2 files changed, 46 insertions, 9 deletions
diff --git a/ghc/GHCi/UI.hs b/ghc/GHCi/UI.hs index e386fe6058..55d06dcc1e 100644 --- a/ghc/GHCi/UI.hs +++ b/ghc/GHCi/UI.hs @@ -102,7 +102,7 @@ import Data.Char import Data.Function import Data.IORef ( IORef, modifyIORef, newIORef, readIORef, writeIORef ) import Data.List ( find, group, intercalate, intersperse, isPrefixOf, nub, - partition, sort, sortBy ) + partition, sort, sortBy, (\\) ) import qualified Data.Set as S import Data.Maybe import Data.Map (Map) @@ -482,6 +482,7 @@ interactiveUI config srcs maybe_exprs = do stop = default_stop, editor = default_editor, options = [], + localConfig = SourceLocalConfig, -- We initialize line number as 0, not 1, because we use -- current line number while reporting errors which is -- incremented after reading a line. @@ -566,8 +567,6 @@ runGHCi paths maybe_exprs = do let ignore_dot_ghci = gopt Opt_IgnoreDotGhci dflags - current_dir = return (Just ".ghci") - app_user_dir = liftIO $ withGhcAppData (\dir -> return (Just (dir </> "ghci.conf"))) (return Nothing) @@ -606,17 +605,44 @@ runGHCi paths maybe_exprs = do setGHCContextFromGHCiState - dot_cfgs <- if ignore_dot_ghci then return [] else do - dot_files <- catMaybes <$> sequence [ current_dir, app_user_dir, home_dir ] - liftIO $ filterM checkFileAndDirPerms dot_files - mdot_cfgs <- liftIO $ mapM canonicalizePath' dot_cfgs + processedCfgs <- if ignore_dot_ghci + then pure [] + else do + userCfgs <- do + paths <- catMaybes <$> sequence [ app_user_dir, home_dir ] + checkedPaths <- liftIO $ filterM checkFileAndDirPerms paths + liftIO . fmap (nub . catMaybes) $ mapM canonicalizePath' checkedPaths + + localCfg <- do + let path = ".ghci" + ok <- liftIO $ checkFileAndDirPerms path + if ok then liftIO $ canonicalizePath' path else pure Nothing + + mapM_ sourceConfigFile userCfgs + -- Process the global and user .ghci + -- (but not $CWD/.ghci or CLI args, yet) + + behaviour <- localConfig <$> getGHCiState + + processedLocalCfg <- case localCfg of + Just path | path `notElem` userCfgs -> + -- don't read .ghci twice if CWD is $HOME + case behaviour of + SourceLocalConfig -> localCfg <$ sourceConfigFile path + IgnoreLocalConfig -> pure Nothing + _ -> pure Nothing + + pure $ maybe id (:) processedLocalCfg userCfgs let arg_cfgs = reverse $ ghciScripts dflags -- -ghci-script are collected in reverse order -- We don't require that a script explicitly added by -ghci-script -- is owned by the current user. (#6017) - mapM_ sourceConfigFile $ nub $ (catMaybes mdot_cfgs) ++ arg_cfgs - -- nub, because we don't want to read .ghci twice if the CWD is $HOME. + + mapM_ sourceConfigFile $ nub arg_cfgs \\ processedCfgs + -- Dedup, and remove any configs we already processed. + -- Importantly, if $PWD/.ghci was ignored due to configuration, + -- explicitly specifying it does cause it to be processed. -- Perform a :load for files given on the GHCi command line -- When in -e mode, if the load fails then we want to stop diff --git a/ghc/GHCi/UI/Monad.hs b/ghc/GHCi/UI/Monad.hs index 16bcd20ee4..696303b949 100644 --- a/ghc/GHCi/UI/Monad.hs +++ b/ghc/GHCi/UI/Monad.hs @@ -15,6 +15,7 @@ module GHCi.UI.Monad ( GHCiState(..), GhciMonad(..), GHCiOption(..), isOptionSet, setOption, unsetOption, Command(..), CommandResult(..), cmdSuccess, + LocalConfigBehaviour(..), PromptFunction, BreakLocation(..), TickArray, @@ -79,6 +80,7 @@ data GHCiState = GHCiState prompt_cont :: PromptFunction, editor :: String, stop :: String, + localConfig :: LocalConfigBehaviour, options :: [GHCiOption], line_number :: !Int, -- ^ input line break_ctr :: !Int, @@ -197,6 +199,15 @@ data GHCiOption -- modules after load deriving Eq +-- | Treatment of ./.ghci files. For now we either load or +-- ignore. But later we could implement a "safe mode" where +-- only safe operations are performed. +-- +data LocalConfigBehaviour + = SourceLocalConfig + | IgnoreLocalConfig + deriving (Eq) + data BreakLocation = BreakLocation { breakModule :: !GHC.Module |