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
</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>
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>
<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>
<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>