FIX #1838, #1987: change where GHCi searches for config files
authorSimon Marlow <simonmar@microsoft.com>
Wed, 23 Jan 2008 14:32:07 +0000 (14:32 +0000)
committerSimon Marlow <simonmar@microsoft.com>
Wed, 23 Jan 2008 14:32:07 +0000 (14:32 +0000)
6.6 behaviour:
  - ./.ghci
  - $HOME/.ghci

6.8.[12] behaviour:
  - ./.ghci
  - Windows: c:/Documents and Settings/<user>/.ghci
  - Unix: $HOME/.ghci

6.10 (and 6.8.3 when this is merged):
  - ./.ghci
  - Windows: c:/Documents and Settings/<user>/Application Data/ghc/ghci.conf
  - Unix: $HOME/.ghc/ghci.conf
  - $HOME/.ghci

We will need to document this in the 6.8.3 release notes because it
may affect Windows users who have adapted their setup to 6.8.[12].

compiler/ghci/InteractiveUI.hs
docs/users_guide/ghci.xml

index d98b6bc..6550c6d 100644 (file)
@@ -356,36 +356,43 @@ interactiveUI session srcs maybe_exprs = do
 
 runGHCi :: [(FilePath, Maybe Phase)] -> Maybe [String] -> GHCi ()
 runGHCi paths maybe_exprs = do
-  let read_dot_files = not opt_IgnoreDotGhci
+  let 
+   read_dot_files = not opt_IgnoreDotGhci
 
-  when (read_dot_files) $ do
-    -- Read in ./.ghci.
-    let file = "./.ghci"
-    exists <- io (doesFileExist file)
-    when exists $ do
-       dir_ok  <- io (checkPerms ".")
-       file_ok <- io (checkPerms file)
+   current_dir = return (Just ".ghci")
+
+   app_user_dir = do
+    either_dir <- io $ IO.try (getAppUserDataDirectory "ghc")
+    case either_dir of
+      Right dir -> return (Just (dir </> "ghci.conf"))
+      _ -> return Nothing
+
+   home_dir = do
+    either_dir <- io $ IO.try (getEnv "HOME")
+    case either_dir of
+      Right home -> return (Just (home </> ".ghci"))
+      _ -> return Nothing
+
+   sourceConfigFile :: FilePath -> GHCi ()
+   sourceConfigFile file = do
+     exists <- io $ doesFileExist file
+     when exists $ do
+       dir_ok  <- io $ checkPerms (getDirectory file)
+       file_ok <- io $ checkPerms file
        when (dir_ok && file_ok) $ do
-          either_hdl <- io (IO.try (openFile "./.ghci" ReadMode))
-          case either_hdl of
-             Left _e   -> return ()
-             Right hdl -> runCommands (fileLoop hdl False False)
+         either_hdl <- io $ IO.try (openFile file ReadMode)
+         case either_hdl of
+           Left _e   -> return ()
+           Right hdl -> runCommands (fileLoop hdl False False)
+     where
+      getDirectory f = case takeDirectory f of "" -> "."; d -> d
 
   when (read_dot_files) $ do
-    -- Read in $HOME/.ghci
-    either_dir <- io (IO.try getHomeDirectory)
-    case either_dir of
-       Left _e -> return ()
-       Right dir -> do
-          cwd <- io (getCurrentDirectory)
-          when (dir /= cwd) $ do
-             let file = dir ++ "/.ghci"
-             ok <- io (checkPerms file)
-             when ok $ do
-               either_hdl <- io (IO.try (openFile file ReadMode))
-               case either_hdl of
-                  Left _e   -> return ()
-                  Right hdl -> runCommands (fileLoop hdl False False)
+    cfgs0 <- sequence [ current_dir, app_user_dir, home_dir ]
+    cfgs <- io $ mapM canonicalizePath (catMaybes cfgs0)
+    mapM_ sourceConfigFile (nub cfgs)
+        -- nub, because we don't want to read .ghci twice if the
+        -- CWD is $HOME.
 
   -- Perform a :load for files given on the GHCi command line
   -- When in -e mode, if the load fails then we want to stop
index 9fa5d87..32fbc00 100644 (file)
@@ -2622,18 +2622,34 @@ Prelude> :set -fno-glasgow-exts
     </indexterm>
 
     <para>When it starts, unless the <literal>-ignore-dot-ghci</literal>
-    flag is given, GHCi reads and executes commands from
-    <filename>./.ghci</filename>, followed by
-    <filename>$HOME/.ghci</filename>.</para>
-
-    <para>The <filename>.ghci</filename> in your home directory is
-    most useful for turning on favourite options (eg. <literal>:set
-    +s</literal>), and defining useful macros.  Placing a
-    <filename>.ghci</filename> file in a directory with a Haskell
-    project is a useful way to set certain project-wide options so you
-    don't have to type them everytime you start GHCi: eg. if your
-    project uses GHC extensions and CPP, and has source files in three
-    subdirectories A, B and C, you might put the following lines in
+    flag is given, GHCi reads and executes commands from the following
+    files, in this order, if they exist:</para>
+
+    <enumeratedlist>
+    <listitem>
+      <para><filename>./.ghci</filename></para>
+    </listitem>
+    <listitem>
+      <para><literal><replaceable>appdata</replaceable>/ghc/ghci.conf</literal>,
+      where <replaceable>appdata</replaceable> depends on your system,
+      but is usually something like <literal>C:/Documents and Settings/<replaceable>user</replaceable>/Application Data</literal></para>
+    </listitem>
+    <listitem>
+      <para>On Unix: <literal>$HOME/.ghc/ghci.conf</literal></para>
+    </listitem>
+    <listitem>
+      <para><literal>$HOME/.ghci</literal></para>
+    </listitem>
+   </enumeratedlist>
+
+    <para>The <filename>ghci.conf</filename> file is most useful for
+    turning on favourite options (eg. <literal>:set +s</literal>), and
+    defining useful macros.  Placing a <filename>.ghci</filename> file
+    in a directory with a Haskell project is a useful way to set
+    certain project-wide options so you don't have to type them
+    everytime you start GHCi: eg. if your project uses GHC extensions
+    and CPP, and has source files in three subdirectories A, B and C,
+    you might put the following lines in
     <filename>.ghci</filename>:</para>
 
 <screen>
@@ -2647,7 +2663,7 @@ Prelude> :set -fno-glasgow-exts
     until the next <literal>:load</literal>, though.)</para>
 
     <para>Two command-line options control whether the
-    <filename>.ghci</filename> files are read:</para>
+    startup files files are read:</para>
 
     <variablelist>
       <varlistentry>
@@ -2656,8 +2672,8 @@ Prelude> :set -fno-glasgow-exts
           <indexterm><primary><option>-ignore-dot-ghci</option></primary></indexterm>
         </term>
        <listitem>
-         <para>Don't read either <filename>./.ghci</filename> or
-         <filename>$HOME/.ghci</filename> when starting up.</para>
+         <para>Don't read either <filename>./.ghci</filename> or the
+          other startup files when starting up.</para>
        </listitem>
       </varlistentry>
       <varlistentry>
@@ -2666,8 +2682,8 @@ Prelude> :set -fno-glasgow-exts
           <indexterm><primary><option>-read-dot-ghci</option></primary></indexterm>
         </term>
        <listitem>
-         <para>Read <filename>.ghci</filename> and
-         <filename>$HOME/.ghci</filename>.  This is normally the
+         <para>Read <filename>./.ghci</filename> and the other
+          startup files (see above).  This is normally the
          default, but the <option>-read-dot-ghci</option> option may
          be used to override a previous
          <option>-ignore-dot-ghci</option> option.</para>