diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2014-04-30 v4.1.0
+	* ghc-modi now provides "type", "info", and "boot".
+	* ghc-mod now provides "find".
+	* Packages, which are specified in a cabal file but not installed,
+	  are filtered out. (@DanielG)
+	* ghc-mod/ghc-modi treats "-l" properly.
+	* ghc-mod obsoletes "-p". Use "ghc-mod browse package:module".
+	* M-x ghc-debug has been implemented.
+	* "type" and "info" can work even if files contain type errors.
+	* "boot" as a new API.
+
+2014-04-07 v4.0.2
+	* The ghc-display-error option (@notogawa)
+	* Fixing a file bug for Windows (@Kiripon)
+	* The -b option for ghc-modi (@yuga)
+
 2014-04-03 v4.0.1
 	* Displaying a qualified name for one if two unqualified names
 	  are conflict.
diff --git a/Language/Haskell/GhcMod.hs b/Language/Haskell/GhcMod.hs
--- a/Language/Haskell/GhcMod.hs
+++ b/Language/Haskell/GhcMod.hs
@@ -13,9 +13,11 @@
   , ModuleString
   , Expression
   -- * 'IO' utilities
+  , bootInfo
   , browseModule
   , checkSyntax
   , lintSyntax
+  , expandTemplate
   , infoExpr
   , typeExpr
   , listModules
@@ -24,25 +26,16 @@
   , debugInfo
   , rootInfo
   , packageDoc
-  -- * Converting the 'Ghc' monad to the 'IO' monad
-  , withGHC
-  , withGHCDummyFile
-  -- * 'Ghc' utilities
-  , browse
-  , check
-  , info
-  , typeOf
-  , listMods
-  , debug
-  , lint
+  , findSymbol
   ) where
 
+import Language.Haskell.GhcMod.Boot
 import Language.Haskell.GhcMod.Browse
 import Language.Haskell.GhcMod.Check
 import Language.Haskell.GhcMod.Cradle
 import Language.Haskell.GhcMod.Debug
+import Language.Haskell.GhcMod.Find
 import Language.Haskell.GhcMod.Flag
-import Language.Haskell.GhcMod.GHCApi
 import Language.Haskell.GhcMod.Info
 import Language.Haskell.GhcMod.Lang
 import Language.Haskell.GhcMod.Lint
diff --git a/Language/Haskell/GhcMod/Boot.hs b/Language/Haskell/GhcMod/Boot.hs
new file mode 100644
--- /dev/null
+++ b/Language/Haskell/GhcMod/Boot.hs
@@ -0,0 +1,38 @@
+module Language.Haskell.GhcMod.Boot where
+
+import Control.Applicative ((<$>))
+import CoreMonad (liftIO, liftIO)
+import GHC (Ghc)
+import Language.Haskell.GhcMod.Browse
+import Language.Haskell.GhcMod.Flag
+import Language.Haskell.GhcMod.GHCApi
+import Language.Haskell.GhcMod.Lang
+import Language.Haskell.GhcMod.List
+import Language.Haskell.GhcMod.Types
+
+-- | Printing necessary information for front-end booting.
+bootInfo :: Options -> Cradle -> IO String
+bootInfo opt cradle = withGHC' $ do
+    initializeFlagsWithCradle opt cradle
+    boot opt
+
+-- | Printing necessary information for front-end booting.
+boot :: Options -> Ghc String
+boot opt = do
+    mods  <- modules opt
+    langs <- liftIO $ listLanguages opt
+    flags <- liftIO $ listFlags opt
+    pre   <- concat <$> mapM (browse opt) preBrowsedModules
+    return $ mods ++ langs ++ flags ++ pre
+
+preBrowsedModules :: [String]
+preBrowsedModules = [
+    "Prelude"
+  , "Control.Applicative"
+  , "Control.Exception"
+  , "Control.Monad"
+  , "Data.Char"
+  , "Data.List"
+  , "Data.Maybe"
+  , "System.IO"
+  ]
diff --git a/Language/Haskell/GhcMod/Browse.hs b/Language/Haskell/GhcMod/Browse.hs
--- a/Language/Haskell/GhcMod/Browse.hs
+++ b/Language/Haskell/GhcMod/Browse.hs
@@ -5,10 +5,11 @@
   where
 
 import Control.Applicative ((<$>))
-import Control.Monad (void)
+import Control.Exception (SomeException(..))
 import Data.Char (isAlpha)
 import Data.List (sort)
 import Data.Maybe (catMaybes)
+import Exception (ghandle)
 import FastString (mkFastString)
 import GHC (Ghc, GhcException(CmdLineError), ModuleInfo, Name, TyThing, DynFlags, Type, TyCon, Module)
 import qualified GHC as G
@@ -18,7 +19,6 @@
 import Language.Haskell.GhcMod.Types
 import Name (getOccString)
 import Outputable (ppr, Outputable)
-import Panic (throwGhcException)
 import TyCon (isAlgTyCon)
 import Type (dropForAlls, splitFunTy_maybe, mkFunTy, isPredTy)
 
@@ -31,22 +31,22 @@
              -> Cradle
              -> ModuleString -- ^ A module name. (e.g. \"Data.List\")
              -> IO String
-browseModule opt cradle mdlName = convert opt . sort <$> withGHCDummyFile (browse opt cradle mdlName)
+browseModule opt cradle pkgmdl = withGHC' $ do
+    initializeFlagsWithCradle opt cradle
+    browse opt pkgmdl
 
 -- | Getting functions, classes, etc from a module.
 --   If 'detailed' is 'True', their types are also obtained.
 --   If 'operators' is 'True', operators are also returned.
 browse :: Options
-       -> Cradle
        -> ModuleString -- ^ A module name. (e.g. \"Data.List\")
-       -> Ghc [String]
-browse opt cradle mdlName = do
-    void $ initializeFlagsWithCradle opt cradle [] False
-    getModule >>= G.getModuleInfo >>= listExports
+       -> Ghc String
+browse opt pkgmdl = do
+    convert opt . sort <$> (getModule >>= listExports)
   where
-    getModule = G.findModule mdlname mpkgid `G.gcatch` fallback
-    mdlname = G.mkModuleName mdlName
-    mpkgid = mkFastString <$> packageId opt
+    (mpkg,mdl) = splitPkgMdl pkgmdl
+    mdlname = G.mkModuleName mdl
+    mpkgid = mkFastString <$> mpkg
     listExports Nothing       = return []
     listExports (Just mdinfo) = processExports opt mdinfo
     -- findModule works only for package modules, moreover,
@@ -54,12 +54,24 @@
     -- to browse a local module you need to load it first.
     -- If CmdLineError is signalled, we assume the user
     -- tried browsing a local module.
-    fallback (CmdLineError _) = loadAndFind
-    fallback e                = throwGhcException e
-    loadAndFind = do
-      setTargetFiles [mdlName]
-      void $ G.load G.LoadAllTargets
-      G.findModule mdlname Nothing
+    getModule = browsePackageModule `G.gcatch` fallback `G.gcatch` handler
+    browsePackageModule = G.findModule mdlname mpkgid >>= G.getModuleInfo
+    browseLocalModule = ghandle handler $ do
+      setTargetFiles [mdl]
+      G.findModule mdlname Nothing >>= G.getModuleInfo
+    fallback (CmdLineError _) = browseLocalModule
+    fallback _                = return Nothing
+    handler (SomeException _) = return Nothing
+-- |
+--
+-- >>> splitPkgMdl "base:Prelude"
+-- (Just "base","Prelude")
+-- >>> splitPkgMdl "Prelude"
+-- (Nothing,"Prelude")
+splitPkgMdl :: String -> (Maybe String,String)
+splitPkgMdl pkgmdl = case break (==':') pkgmdl of
+    (mdl,"")    -> (Nothing,mdl)
+    (pkg,_:mdl) -> (Just pkg,mdl)
 
 processExports :: Options -> ModuleInfo -> Ghc [String]
 processExports opt minfo = mapM (showExport opt minfo) $ removeOps $ G.modInfoExports minfo
diff --git a/Language/Haskell/GhcMod/CabalApi.hs b/Language/Haskell/GhcMod/CabalApi.hs
--- a/Language/Haskell/GhcMod/CabalApi.hs
+++ b/Language/Haskell/GhcMod/CabalApi.hs
@@ -9,16 +9,19 @@
   , cabalAllTargets
   ) where
 
+import Language.Haskell.GhcMod.Types
+import Language.Haskell.GhcMod.GhcPkg
+
 import Control.Applicative ((<$>))
 import Control.Exception (throwIO)
 import Control.Monad (filterM)
 import CoreMonad (liftIO)
-import Data.Maybe (maybeToList)
+import Data.Maybe (maybeToList, catMaybes)
 import Data.Set (fromList, toList)
 import Distribution.ModuleName (ModuleName,toFilePath)
 import Distribution.Package (Dependency(Dependency)
-                           , PackageName(PackageName)
-                           , PackageIdentifier(pkgName))
+                           , PackageName(PackageName))
+import qualified Distribution.Package as C
 import Distribution.PackageDescription (PackageDescription, BuildInfo, TestSuite, TestSuiteInterface(..), Executable)
 import qualified Distribution.PackageDescription as P
 import Distribution.PackageDescription.Configuration (finalizePackageDescription)
@@ -30,35 +33,34 @@
 import Distribution.Text (display)
 import Distribution.Verbosity (silent)
 import Distribution.Version (Version)
-import Language.Haskell.GhcMod.Types
-import Language.Haskell.GhcMod.Cradle
 import System.Directory (doesFileExist)
 import System.FilePath (dropExtension, takeFileName, (</>))
 
 ----------------------------------------------------------------
 
 -- | Getting necessary 'CompilerOptions' from three information sources.
-getCompilerOptions :: [GHCOption] -> Cradle -> PackageDescription -> IO CompilerOptions
+getCompilerOptions :: [GHCOption]
+                   -> Cradle
+                   -> PackageDescription
+                   -> IO CompilerOptions
 getCompilerOptions ghcopts cradle pkgDesc = do
     gopts <- getGHCOptions ghcopts cradle rdir $ head buildInfos
-    return $ CompilerOptions gopts idirs depPkgs
+    dbPkgs <- ghcPkgListEx (cradlePkgDbStack cradle)
+    return $ CompilerOptions gopts idirs (depPkgs dbPkgs)
   where
     wdir       = cradleCurrentDir cradle
     rdir       = cradleRootDir    cradle
     Just cfile = cradleCabalFile  cradle
-    pkgs       = cradlePackages   cradle
+    thisPkg    = dropExtension $ takeFileName cfile
     buildInfos = cabalAllBuildInfo pkgDesc
     idirs      = includeDirectories rdir wdir $ cabalSourceDirs buildInfos
-    depPkgs    = attachPackageIds pkgs $ removeThem problematicPackages $ removeMe cfile $ cabalDependPackages buildInfos
+    depPkgs ps = attachPackageIds ps
+                   $ removeThem (problematicPackages ++ [thisPkg])
+                   $ cabalDependPackages buildInfos
 
 ----------------------------------------------------------------
 -- Dependent packages
 
-removeMe :: FilePath -> [PackageBaseName] -> [PackageBaseName]
-removeMe cabalfile = filter (/= me)
-  where
-    me = dropExtension $ takeFileName cabalfile
-
 removeThem :: [PackageBaseName] -> [PackageBaseName] -> [PackageBaseName]
 removeThem badpkgs = filter (`notElem` badpkgs)
 
@@ -68,12 +70,14 @@
   ]
 
 attachPackageIds :: [Package] -> [PackageBaseName] -> [Package]
-attachPackageIds pkgs = map attachId
-  where
-    attachId x = case lookup x pkgs of
-      Nothing -> (x, Nothing)
-      Just p -> (x, p)
+attachPackageIds pkgs = catMaybes . fmap (`lookup3` pkgs)
 
+lookup3 :: Eq a => a -> [(a,b,c)] -> Maybe (a,b,c)
+lookup3 _ [] = Nothing
+lookup3 k (t@(a,_,_):ls)
+    | k == a = Just t
+    | otherwise = lookup3 k ls
+
 ----------------------------------------------------------------
 -- Include directories for modules
 
@@ -104,7 +108,7 @@
     toPkgDesc cid = finalizePackageDescription [] (const True) buildPlatform cid []
     nullPkg pd = name == ""
       where
-        PackageName name = pkgName (P.package pd)
+        PackageName name = C.pkgName (P.package pd)
 
 ----------------------------------------------------------------
 
@@ -114,7 +118,7 @@
     let cpps = map ("-optP" ++) $ P.cppOptions binfo ++ cabalCpp
     return $ ghcopts ++ pkgDb ++ exts ++ [lang] ++ libs ++ libDirs ++ cpps
   where
-    pkgDb = userPackageDbOptsForGhc $ cradlePackageDb cradle
+    pkgDb = ghcDbStackOpts $ cradlePkgDbStack cradle
     lang = maybe "-XHaskell98" (("-X" ++) . display) $ P.defaultLanguage binfo
     libDirs = map ("-L" ++) $ P.extraLibDirs binfo
     exts = map (("-X" ++) . display) $ P.usedExtensions binfo
@@ -134,11 +138,16 @@
 
 -- | Extracting all 'BuildInfo' for libraries, executables, and tests.
 cabalAllBuildInfo :: PackageDescription -> [BuildInfo]
-cabalAllBuildInfo pd = libBI ++ execBI ++ testBI
+cabalAllBuildInfo pd = libBI ++ execBI ++ testBI ++ benchBI
   where
     libBI   = map P.libBuildInfo       $ maybeToList $ P.library pd
     execBI  = map P.buildInfo          $ P.executables pd
     testBI  = map P.testBuildInfo      $ P.testSuites pd
+#if __GLASGOW_HASKELL__ >= 704
+    benchBI = map P.benchmarkBuildInfo $ P.benchmarks pd
+#else
+    benchBI = []
+#endif
 
 ----------------------------------------------------------------
 
@@ -211,4 +220,3 @@
     getExecutableTarget exe = do
       let maybeExes = [p </> e | p <- P.hsSourceDirs $ P.buildInfo exe, e <- [P.modulePath exe]]
       liftIO $ filterM doesFileExist maybeExes
-
diff --git a/Language/Haskell/GhcMod/Check.hs b/Language/Haskell/GhcMod/Check.hs
--- a/Language/Haskell/GhcMod/Check.hs
+++ b/Language/Haskell/GhcMod/Check.hs
@@ -1,12 +1,15 @@
-module Language.Haskell.GhcMod.Check (checkSyntax, check) where
+module Language.Haskell.GhcMod.Check (
+    checkSyntax
+  , check
+  , expandTemplate
+  , expand
+  ) where
 
 import Control.Applicative ((<$>))
-import Control.Monad (void)
-import CoreMonad (liftIO)
-import GHC (Ghc, LoadHowMuch(LoadAllTargets))
-import qualified GHC as G
-import Language.Haskell.GhcMod.ErrMsg
+import GHC (Ghc)
 import Language.Haskell.GhcMod.GHCApi
+import qualified Language.Haskell.GhcMod.Gap as Gap
+import Language.Haskell.GhcMod.Logger
 import Language.Haskell.GhcMod.Types
 
 ----------------------------------------------------------------
@@ -17,8 +20,10 @@
             -> Cradle
             -> [FilePath]  -- ^ The target files.
             -> IO String
-checkSyntax _   _      []    = error "ghc-mod: checkSyntax: No files given"
-checkSyntax opt cradle files = unlines <$> withGHC sessionName (check opt cradle files)
+checkSyntax _   _      []    = return ""
+checkSyntax opt cradle files = withGHC sessionName $ do
+    initializeFlagsWithCradle opt cradle
+    either id id <$> check opt files
   where
     sessionName = case files of
       [file] -> file
@@ -29,18 +34,32 @@
 -- | Checking syntax of a target file using GHC.
 --   Warnings and errors are returned.
 check :: Options
-      -> Cradle
       -> [FilePath]  -- ^ The target files.
-      -> Ghc [String]
-check _   _      []        = error "ghc-mod: check: No files given"
-check opt cradle fileNames = checkIt `G.gcatch` handleErrMsg ls
+      -> Ghc (Either String String)
+check opt fileNames = withLogger opt setAllWaringFlags $
+    setTargetFiles fileNames
+
+----------------------------------------------------------------
+
+-- | Expanding Haskell Template.
+expandTemplate :: Options
+               -> Cradle
+               -> [FilePath]  -- ^ The target files.
+               -> IO String
+expandTemplate _   _      []    = return ""
+expandTemplate opt cradle files = withGHC sessionName $ do
+    initializeFlagsWithCradle opt cradle
+    either id id <$> expand opt files
   where
-    checkIt = do
-        (readLog,_) <- initializeFlagsWithCradle opt cradle options True
-        setTargetFiles fileNames
-        void $ G.load LoadAllTargets
-        liftIO readLog
-    options
-      | expandSplice opt = "-w:"   : ghcOpts opt
-      | otherwise        = "-Wall" : ghcOpts opt
-    ls = lineSeparator opt
+    sessionName = case files of
+      [file] -> file
+      _      -> "MultipleFiles"
+
+----------------------------------------------------------------
+
+-- | Expanding Haskell Template.
+expand :: Options
+      -> [FilePath]  -- ^ The target files.
+      -> Ghc (Either String String)
+expand opt fileNames = withLogger opt (Gap.setDumpSplices . setNoWaringFlags) $
+    setTargetFiles fileNames
diff --git a/Language/Haskell/GhcMod/Cradle.hs b/Language/Haskell/GhcMod/Cradle.hs
--- a/Language/Haskell/GhcMod/Cradle.hs
+++ b/Language/Haskell/GhcMod/Cradle.hs
@@ -1,25 +1,18 @@
-{-# LANGUAGE BangPatterns #-}
-
 module Language.Haskell.GhcMod.Cradle (
     findCradle
   , findCradleWithoutSandbox
-  , getPackageDbDir
-  , getPackageDbPackages
-  , userPackageDbOptsForGhc
-  , userPackageDbOptsForGhcPkg
-  , getSandboxDir
   ) where
 
+import Language.Haskell.GhcMod.Types
+import Language.Haskell.GhcMod.GhcPkg
+
 import Control.Applicative ((<$>))
-import Control.Exception (SomeException(..))
 import qualified Control.Exception as E
 import Control.Exception.IOChoice ((||>))
 import Control.Monad (filterM)
-import Data.Char (isSpace)
-import Data.List (isPrefixOf, isSuffixOf, tails)
-import Language.Haskell.GhcMod.Types
+import Data.List (isSuffixOf)
 import System.Directory (getCurrentDirectory, getDirectoryContents, doesFileExist)
-import System.FilePath ((</>), takeDirectory, takeFileName)
+import System.FilePath ((</>), takeDirectory)
 
 ----------------------------------------------------------------
 
@@ -35,25 +28,23 @@
 cabalCradle :: FilePath -> IO Cradle
 cabalCradle wdir = do
     (rdir,cfile) <- cabalDir wdir
-    pkgDbOpts <- getPackageDb rdir
+    pkgDbStack <- getPackageDbStack rdir
     return Cradle {
         cradleCurrentDir = wdir
       , cradleRootDir    = rdir
       , cradleCabalFile  = Just cfile
-      , cradlePackageDb  = pkgDbOpts
-      , cradlePackages   = []
+      , cradlePkgDbStack = pkgDbStack
       }
 
 sandboxCradle :: FilePath -> IO Cradle
 sandboxCradle wdir = do
     rdir <- getSandboxDir wdir
-    pkgDbOpts <- getPackageDb rdir
+    pkgDbStack <- getPackageDbStack rdir
     return Cradle {
         cradleCurrentDir = wdir
       , cradleRootDir    = rdir
       , cradleCabalFile  = Nothing
-      , cradlePackageDb  = pkgDbOpts
-      , cradlePackages   = []
+      , cradlePkgDbStack = pkgDbStack
       }
 
 plainCradle :: FilePath -> IO Cradle
@@ -61,15 +52,14 @@
         cradleCurrentDir = wdir
       , cradleRootDir    = wdir
       , cradleCabalFile  = Nothing
-      , cradlePackageDb  = Nothing
-      , cradlePackages   = []
+      , cradlePkgDbStack = [GlobalDb]
       }
 
 -- Just for testing
 findCradleWithoutSandbox :: IO Cradle
 findCradleWithoutSandbox = do
     cradle <- findCradle
-    return cradle { cradlePackageDb = Nothing, cradlePackages = [] }
+    return cradle { cradlePkgDbStack = [GlobalDb]}
 
 ----------------------------------------------------------------
 
@@ -103,121 +93,6 @@
 
 ----------------------------------------------------------------
 
-configFile :: String
-configFile = "cabal.sandbox.config"
-
-pkgDbKey :: String
-pkgDbKey = "package-db:"
-
-pkgDbKeyLen :: Int
-pkgDbKeyLen = length pkgDbKey
-
--- | Obtaining GHC options relating to a package db directory
-getPackageDb :: FilePath -> IO (Maybe FilePath)
-getPackageDb cdir = (Just <$> getPkgDb) `E.catch` handler
-  where
-    getPkgDb = getPackageDbDir (cdir </> configFile)
-    handler :: SomeException -> IO (Maybe FilePath)
-    handler _ = return Nothing
-
--- | Extract a package db directory from the sandbox config file.
---   Exception is thrown if the sandbox config file is broken.
-getPackageDbDir :: FilePath -> IO FilePath
-getPackageDbDir sconf = do
-    -- Be strict to ensure that an error can be caught.
-    !path <- extractValue . parse <$> readFile sconf
-    return path
-  where
-    parse = head . filter ("package-db:" `isPrefixOf`) . lines
-    extractValue = dropWhileEnd isSpace . dropWhile isSpace . drop pkgDbKeyLen
-    -- dropWhileEnd is not provided prior to base 4.5.0.0.
-    dropWhileEnd :: (a -> Bool) -> [a] -> [a]
-    dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
-
--- | Creating user package db options for GHC.
---
--- >>> userPackageDbOptsForGhc (Just "/foo/bar/i386-osx-ghc-7.6.3-packages.conf.d")
--- ["-no-user-package-db","-package-db","/foo/bar/i386-osx-ghc-7.6.3-packages.conf.d"]
--- >>> userPackageDbOptsForGhc (Just "/foo/bar/i386-osx-ghc-7.4.1-packages.conf.d")
--- ["-no-user-package-conf","-package-conf","/foo/bar/i386-osx-ghc-7.4.1-packages.conf.d"]
-userPackageDbOptsForGhc :: Maybe FilePath -> [String]
-userPackageDbOptsForGhc Nothing      = []
-userPackageDbOptsForGhc (Just pkgDb) = [noUserPkgDbOpt, pkgDbOpt, pkgDb]
-  where
-    ver = extractGhcVer pkgDb
-    (noUserPkgDbOpt,pkgDbOpt)
-      | ver < 706 = ("-no-user-package-conf", "-package-conf")
-      | otherwise = ("-no-user-package-db",   "-package-db")
-
--- | Creating user package db options for ghc-pkg.
---
--- >>> userPackageDbOptsForGhcPkg (Just "/foo/bar/i386-osx-ghc-7.6.3-packages.conf.d")
--- ["--no-user-package-db","--package-db=/foo/bar/i386-osx-ghc-7.6.3-packages.conf.d"]
--- >>> userPackageDbOptsForGhcPkg (Just "/foo/bar/i386-osx-ghc-7.4.1-packages.conf.d")
--- ["--no-user-package-conf","--package-conf=/foo/bar/i386-osx-ghc-7.4.1-packages.conf.d"]
-userPackageDbOptsForGhcPkg :: Maybe FilePath -> [String]
-userPackageDbOptsForGhcPkg Nothing      = []
-userPackageDbOptsForGhcPkg (Just pkgDb) = [noUserPkgDbOpt, pkgDbOpt]
-  where
-    ver = extractGhcVer pkgDb
-    (noUserPkgDbOpt,pkgDbOpt)
-      | ver < 706 = ("--no-user-package-conf", "--package-conf=" ++ pkgDb)
-      | otherwise = ("--no-user-package-db",   "--package-db="   ++ pkgDb)
-
--- | Extracting GHC version from the path of package db.
---   Exception is thrown if the string argument is incorrect.
---
--- >>> extractGhcVer "/foo/bar/i386-osx-ghc-7.6.3-packages.conf.d"
--- 706
-extractGhcVer :: String -> Int
-extractGhcVer dir = ver
-  where
-    file = takeFileName dir
-    findVer = drop 4 . head . filter ("ghc-" `isPrefixOf`) . tails
-    (verStr1,_:left) = break (== '.') $ findVer file
-    (verStr2,_)      = break (== '.') left
-    ver = read verStr1 * 100 + read verStr2
-
--- | Obtaining packages installed in a package db directory.
-getPackageDbPackages :: FilePath -> IO [Package]
-getPackageDbPackages cdir = (getPkgDb >>= listDbPackages) `E.catch` handler
-  where
-    getPkgDb = getPackageDbDir (cdir </> configFile)
-    handler :: SomeException -> IO [Package]
-    handler _ = return []
-
-listDbPackages :: FilePath -> IO [Package]
-listDbPackages pkgdir = do
-  files <- filter (".conf" `isSuffixOf`) <$> getDirectoryContents pkgdir
-  mapM (extractPackage . (pkgdir </>)) files
-
-extractPackage :: FilePath -> IO Package
-extractPackage pconf = do
-  contents <- lines <$> readFile pconf
-  -- Be strict to ensure that an error can be caught.
-  let !name = extractName $ parseName contents
-      !pid = extractId $ parseId contents
-  return (name, Just pid)
-  where
-    parseName = parse nameKey
-    extractName = extract nameKeyLength
-    parseId = parse idKey
-    extractId = extract idKeyLength
-    parse key = head . filter (key `isPrefixOf`)
-    extract keylen = takeWhile (not . isSpace) . dropWhile isSpace . drop keylen
-
-nameKey :: String
-nameKey = "name:"
-
-idKey :: String
-idKey = "id:"
-
-nameKeyLength :: Int
-nameKeyLength = length nameKey
-
-idKeyLength :: Int
-idKeyLength = length idKey
-
 getSandboxDir :: FilePath -> IO FilePath
 getSandboxDir dir = do
     exist <- doesFileExist sfile
@@ -228,5 +103,5 @@
       else
         getSandboxDir dir'
   where
-    sfile = dir </> configFile
+    sfile = dir </> "cabal.sandbox.config"
     dir' = takeDirectory dir
diff --git a/Language/Haskell/GhcMod/Debug.hs b/Language/Haskell/GhcMod/Debug.hs
--- a/Language/Haskell/GhcMod/Debug.hs
+++ b/Language/Haskell/GhcMod/Debug.hs
@@ -1,12 +1,10 @@
-module Language.Haskell.GhcMod.Debug (debugInfo, debug, rootInfo, root) where
+module Language.Haskell.GhcMod.Debug (debugInfo, rootInfo) where
 
 import Control.Applicative ((<$>))
 import Control.Exception.IOChoice ((||>))
-import Control.Monad (void)
 import CoreMonad (liftIO)
 import Data.List (intercalate)
 import Data.Maybe (fromMaybe, isJust, fromJust)
-import GHC (Ghc)
 import Language.Haskell.GhcMod.CabalApi
 import Language.Haskell.GhcMod.GHCApi
 import Language.Haskell.GhcMod.Types
@@ -16,30 +14,22 @@
 -- | Obtaining debug information.
 debugInfo :: Options
           -> Cradle
-          -> FilePath   -- ^ A target file.
           -> IO String
-debugInfo opt cradle fileName = unlines <$> withGHC fileName (debug opt cradle fileName)
-
--- | Obtaining debug information.
-debug :: Options
-      -> Cradle
-      -> FilePath     -- ^ A target file.
-      -> Ghc [String]
-debug opt cradle fileName = do
+debugInfo opt cradle = convert opt <$> do
     CompilerOptions gopts incDir pkgs <-
         if cabal then
             liftIO (fromCabalFile ||> return simpleCompilerOption)
           else
             return simpleCompilerOption
-    void $ initializeFlagsWithCradle opt cradle gopts True
-    setTargetFiles [fileName]
+    mglibdir <- liftIO getSystemLibDir
     return [
         "Root directory:      " ++ rootDir
       , "Current directory:   " ++ currentDir
       , "Cabal file:          " ++ cabalFile
       , "GHC options:         " ++ unwords gopts
       , "Include directories: " ++ unwords incDir
-      , "Dependent packages:  " ++ intercalate ", " (map fst pkgs)
+      , "Dependent packages:  " ++ intercalate ", " (map showPkg pkgs)
+      , "System libraries:    " ++ fromMaybe "" mglibdir
       ]
   where
     currentDir = cradleCurrentDir cradle
@@ -49,7 +39,9 @@
     cabalFile = fromMaybe "" mCabalFile
     origGopts = ghcOpts opt
     simpleCompilerOption = CompilerOptions origGopts [] []
-    fromCabalFile = parseCabalFile file >>= getCompilerOptions origGopts cradle
+    fromCabalFile = do
+        pkgDesc <- parseCabalFile file
+        getCompilerOptions origGopts cradle pkgDesc
       where
         file = fromJust mCabalFile
 
@@ -58,13 +50,5 @@
 -- | Obtaining root information.
 rootInfo :: Options
           -> Cradle
-          -> FilePath   -- ^ A target file.
           -> IO String
-rootInfo opt cradle fileName = withGHC fileName (root opt cradle fileName)
-
--- | Obtaining root information.
-root :: Options
-      -> Cradle
-      -> FilePath     -- ^ A target file.
-      -> Ghc String
-root _ cradle _ = return $ cradleRootDir cradle ++ "\n"
+rootInfo opt cradle = return $ convert opt $ cradleRootDir cradle
diff --git a/Language/Haskell/GhcMod/Doc.hs b/Language/Haskell/GhcMod/Doc.hs
--- a/Language/Haskell/GhcMod/Doc.hs
+++ b/Language/Haskell/GhcMod/Doc.hs
@@ -1,7 +1,6 @@
 module Language.Haskell.GhcMod.Doc where
 
-import DynFlags (DynFlags)
-import GHC (Ghc)
+import GHC (Ghc, DynFlags)
 import qualified GHC as G
 import Language.Haskell.GhcMod.Gap (withStyle, showDocWith)
 import Outputable (SDoc, PprStyle, mkUserStyle, Depth(AllTheWay), neverQualify)
diff --git a/Language/Haskell/GhcMod/ErrMsg.hs b/Language/Haskell/GhcMod/ErrMsg.hs
deleted file mode 100644
--- a/Language/Haskell/GhcMod/ErrMsg.hs
+++ /dev/null
@@ -1,101 +0,0 @@
-{-# LANGUAGE BangPatterns, CPP #-}
-
-module Language.Haskell.GhcMod.ErrMsg (
-    LogReader
-  , setLogger
-  , handleErrMsg
-  ) where
-
-import Bag (Bag, bagToList)
-import Control.Applicative ((<$>))
-import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef)
-import Data.Maybe (fromMaybe)
-import DynFlags (dopt)
-import ErrUtils (ErrMsg, errMsgShortDoc, errMsgExtraInfo)
-import GHC (Ghc, DynFlags, SrcSpan, Severity(SevError))
-import qualified GHC as G
-import HscTypes (SourceError, srcErrorMessages)
-import Language.Haskell.GhcMod.Doc (showPage, getStyle)
-import qualified Language.Haskell.GhcMod.Gap as Gap
-import Language.Haskell.GhcMod.Types (LineSeparator(..))
-import Outputable (PprStyle, SDoc)
-import System.FilePath (normalise)
-
-----------------------------------------------------------------
-
--- | A means to read the log.
-type LogReader = IO [String]
-
-----------------------------------------------------------------
-
-type Builder = [String] -> [String]
-
-newtype LogRef = LogRef (IORef Builder)
-
-newLogRef :: IO LogRef
-newLogRef = LogRef <$> newIORef id
-
-readAndClearLogRef :: LogRef -> IO [String]
-readAndClearLogRef (LogRef ref) = do
-    b <- readIORef ref
-    writeIORef ref id
-    return $! b []
-
-appendLogRef :: DynFlags -> LineSeparator -> LogRef -> DynFlags -> Severity -> SrcSpan -> PprStyle -> SDoc -> IO ()
-appendLogRef df ls (LogRef ref) _ sev src style msg = do
-        let !l = ppMsg src sev df ls style msg
-        modifyIORef ref (\b -> b . (l:))
-
-----------------------------------------------------------------
-
-setLogger :: Bool -> DynFlags -> LineSeparator -> IO (DynFlags, LogReader)
-setLogger False df _ = return (newdf, undefined)
-  where
-    newdf = Gap.setLogAction df $ \_ _ _ _ _ -> return ()
-setLogger True  df ls = do
-    logref <- newLogRef
-    let newdf = Gap.setLogAction df $ appendLogRef df ls logref
-    return (newdf, readAndClearLogRef logref)
-
-----------------------------------------------------------------
-
--- | Converting 'SourceError' to 'String'.
-handleErrMsg :: LineSeparator -> SourceError -> Ghc [String]
-handleErrMsg ls err = do
-    dflag <- G.getSessionDynFlags
-    style <- getStyle
-    return . errBagToStrList dflag ls style . srcErrorMessages $ err
-
-errBagToStrList :: DynFlags -> LineSeparator -> PprStyle -> Bag ErrMsg -> [String]
-errBagToStrList dflag ls style = map (ppErrMsg dflag ls style) . reverse . bagToList
-
-----------------------------------------------------------------
-
-ppErrMsg :: DynFlags -> LineSeparator -> PprStyle -> ErrMsg -> String
-ppErrMsg dflag ls style err = ppMsg spn SevError dflag ls style msg ++ ext
-   where
-     spn = Gap.errorMsgSpan err
-     msg = errMsgShortDoc err
-     ext = showMsg dflag ls style (errMsgExtraInfo err)
-
-ppMsg :: SrcSpan -> Severity-> DynFlags -> LineSeparator -> PprStyle -> SDoc -> String
-ppMsg spn sev dflag ls style msg = prefix ++ cts
-  where
-    cts  = showMsg dflag ls style msg
-    defaultPrefix
-      | dopt Gap.dumpSplicesFlag dflag = ""
-      | otherwise                      = "Dummy:0:0:Error:"
-    prefix = fromMaybe defaultPrefix $ do
-        (line,col,_,_) <- Gap.getSrcSpan spn
-        file <- normalise <$> Gap.getSrcFile spn
-        let severityCaption = Gap.showSeverityCaption sev
-        return $ file ++ ":" ++ show line ++ ":" ++ show col ++ ":" ++ severityCaption
-
-----------------------------------------------------------------
-
-showMsg :: DynFlags -> LineSeparator -> PprStyle -> SDoc -> String
-showMsg dflag (LineSeparator lsep) style sdoc = replaceNull $ showPage dflag style sdoc
-  where
-    replaceNull []        = []
-    replaceNull ('\n':xs) = lsep ++ replaceNull xs
-    replaceNull (x:xs)    = x : replaceNull xs
diff --git a/Language/Haskell/GhcMod/Find.hs b/Language/Haskell/GhcMod/Find.hs
new file mode 100644
--- /dev/null
+++ b/Language/Haskell/GhcMod/Find.hs
@@ -0,0 +1,56 @@
+{-# LANGUAGE CPP, BangPatterns #-}
+
+module Language.Haskell.GhcMod.Find where
+
+import Data.Function (on)
+import Data.List (groupBy, sort)
+import Data.Maybe (fromMaybe)
+import GHC (Ghc)
+import qualified GHC as G
+import Language.Haskell.GhcMod.Browse (browseAll)
+import Language.Haskell.GhcMod.GHCApi
+import Language.Haskell.GhcMod.Types
+
+#ifndef MIN_VERSION_containers
+#define MIN_VERSION_containers(x,y,z) 1
+#endif
+
+#if MIN_VERSION_containers(0,5,0)
+import Control.DeepSeq (force)
+import Data.Map.Strict (Map)
+import qualified Data.Map.Strict as M
+#else
+import Data.Map (Map)
+import qualified Data.Map as M
+#endif
+import Control.Applicative ((<$>))
+
+-- | Type of key for `SymMdlDb`.
+type Symbol = String
+-- | Database from 'Symbol' to modules.
+newtype SymMdlDb = SymMdlDb (Map Symbol [ModuleString])
+
+-- | Finding modules to which the symbol belong.
+findSymbol :: Options -> Cradle -> Symbol -> IO String
+findSymbol opt cradle sym = withGHC' $ do
+    initializeFlagsWithCradle opt cradle
+    lookupSym opt sym <$> getSymMdlDb
+
+-- | Creating 'SymMdlDb'.
+getSymMdlDb :: Ghc SymMdlDb
+getSymMdlDb = do
+    sm <- G.getSessionDynFlags >>= browseAll
+#if MIN_VERSION_containers(0,5,0)
+    let !sms = force $ map tieup $ groupBy ((==) `on` fst) $ sort sm
+        !m = force $ M.fromList sms
+#else
+    let !sms = map tieup $ groupBy ((==) `on` fst) $ sort sm
+        !m = M.fromList sms
+#endif
+    return (SymMdlDb m)
+  where
+    tieup x = (head (map fst x), map snd x)
+
+-- | Looking up 'SymMdlDb' with 'Symbol' to find modules.
+lookupSym :: Options -> Symbol -> SymMdlDb -> String
+lookupSym opt sym (SymMdlDb db) = convert opt $ fromMaybe [] (M.lookup sym db)
diff --git a/Language/Haskell/GhcMod/GHCApi.hs b/Language/Haskell/GhcMod/GHCApi.hs
--- a/Language/Haskell/GhcMod/GHCApi.hs
+++ b/Language/Haskell/GhcMod/GHCApi.hs
@@ -1,33 +1,33 @@
-{-# LANGUAGE ScopedTypeVariables #-}
+{-# LANGUAGE ScopedTypeVariables, RecordWildCards #-}
 
 module Language.Haskell.GhcMod.GHCApi (
     withGHC
-  , withGHCDummyFile
-  , initializeFlags
+  , withGHC'
   , initializeFlagsWithCradle
   , setTargetFiles
-  , addTargetFiles
   , getDynamicFlags
   , getSystemLibDir
+  , withDynFlags
+  , setNoWaringFlags
+  , setAllWaringFlags
   ) where
 
-import Control.Applicative (Alternative, (<$>))
-import Control.Monad (void, forM)
+import Language.Haskell.GhcMod.CabalApi
+import Language.Haskell.GhcMod.GHCChoice
+import Language.Haskell.GhcMod.GhcPkg
+
+import Control.Applicative ((<$>))
+import Control.Monad (forM, void)
 import CoreMonad (liftIO)
 import Data.Maybe (isJust, fromJust)
-import Distribution.PackageDescription (PackageDescription)
-import DynFlags (dopt_set)
 import Exception (ghandle, SomeException(..))
-import GHC (Ghc, GhcMonad, DynFlags(..), GhcLink(..), HscTarget(..))
+import GHC (Ghc, GhcMonad, DynFlags(..), GhcLink(..), HscTarget(..), LoadHowMuch(..))
 import qualified GHC as G
-import Language.Haskell.GhcMod.CabalApi
-import Language.Haskell.GhcMod.Cradle (userPackageDbOptsForGhc)
-import Language.Haskell.GhcMod.ErrMsg
-import Language.Haskell.GhcMod.GHCChoice
 import qualified Language.Haskell.GhcMod.Gap as Gap
 import Language.Haskell.GhcMod.Types
 import System.Exit (exitSuccess)
 import System.IO (hPutStr, hPrint, stderr)
+import System.IO.Unsafe (unsafePerformIO)
 import System.Process (readProcess)
 
 ----------------------------------------------------------------
@@ -43,26 +43,24 @@
 ----------------------------------------------------------------
 
 -- | Converting the 'Ghc' monad to the 'IO' monad.
-withGHCDummyFile :: Alternative m => Ghc (m a) -- ^ 'Ghc' actions created by the Ghc utilities.
-                                  -> IO (m a)
-withGHCDummyFile = withGHC "Dummy"
-
--- | Converting the 'Ghc' monad to the 'IO' monad.
-withGHC :: Alternative m => FilePath  -- ^ A target file displayed in an error message.
-                         -> Ghc (m a) -- ^ 'Ghc' actions created by the Ghc utilities.
-                         -> IO (m a)
-withGHC file body = do
-    mlibdir <- getSystemLibDir
-    ghandle ignore $ G.runGhc mlibdir $ do
-        dflags <- G.getSessionDynFlags
-        G.defaultCleanupHandler dflags body
+withGHC :: FilePath  -- ^ A target file displayed in an error message.
+        -> Ghc a -- ^ 'Ghc' actions created by the Ghc utilities.
+        -> IO a
+withGHC file body = ghandle ignore $ withGHC' body
   where
-    ignore :: Alternative m => SomeException -> IO (m a)
+    ignore :: SomeException -> IO a
     ignore e = do
         hPutStr stderr $ file ++ ":0:0:Error:"
         hPrint stderr e
         exitSuccess
 
+withGHC' :: Ghc a -> IO a
+withGHC' body = do
+    mlibdir <- getSystemLibDir
+    G.runGhc mlibdir $ do
+        dflags <- G.getSessionDynFlags
+        G.defaultCleanupHandler dflags body
+
 ----------------------------------------------------------------
 
 importDirs :: [IncludeDir]
@@ -73,104 +71,93 @@
 -- | Initialize the 'DynFlags' relating to the compilation of a single
 -- file or GHC session according to the 'Cradle' and 'Options'
 -- provided.
-initializeFlagsWithCradle :: GhcMonad m =>  Options -> Cradle -> [GHCOption] -> Bool -> m (LogReader, Maybe PackageDescription)
-initializeFlagsWithCradle opt cradle ghcopts logging
+initializeFlagsWithCradle :: GhcMonad m
+        => Options
+        -> Cradle
+        -> m ()
+initializeFlagsWithCradle opt cradle
   | cabal     = withCabal |||> withSandbox
   | otherwise = withSandbox
   where
     mCradleFile = cradleCabalFile cradle
     cabal = isJust mCradleFile
+    ghcopts = ghcOpts opt
     withCabal = do
         pkgDesc <- liftIO $ parseCabalFile $ fromJust mCradleFile
         compOpts <- liftIO $ getCompilerOptions ghcopts cradle pkgDesc
-        logger <- initSession CabalPkg opt compOpts logging
-        return (logger, Just pkgDesc)
-    withSandbox = do
-        logger <- initSession SingleFile opt compOpts logging
-        return (logger, Nothing)
+        initSession CabalPkg opt compOpts
+    withSandbox = initSession SingleFile opt compOpts
       where
-        pkgDb = userPackageDbOptsForGhc $ cradlePackageDb cradle
+        pkgOpts = ghcDbStackOpts $ cradlePkgDbStack cradle
         compOpts
-          | null pkgDb = CompilerOptions ghcopts importDirs []
-          | otherwise  = CompilerOptions (ghcopts ++ pkgDb) [wdir,rdir] []
+          | null pkgOpts = CompilerOptions ghcopts importDirs []
+          | otherwise    = CompilerOptions (ghcopts ++ pkgOpts) [wdir,rdir] []
         wdir = cradleCurrentDir cradle
         rdir = cradleRootDir    cradle
 
 ----------------------------------------------------------------
 
-initSession :: GhcMonad m => Build
+initSession :: GhcMonad m
+            => Build
             -> Options
             -> CompilerOptions
-            -> Bool
-            -> m LogReader
-initSession build opt compOpts logging = do
-    dflags0 <- G.getSessionDynFlags
-    (dflags1,readLog) <- setupDynamicFlags dflags0
-    _ <- G.setSessionDynFlags dflags1
-    return readLog
-  where
-    cmdOpts = ghcOptions compOpts
-    idirs   = includeDirs compOpts
-    depPkgs = depPackages compOpts
-    ls = lineSeparator opt
-    setupDynamicFlags df0 = do
-        df1 <- modifyFlagsWithOpts df0 cmdOpts
-        let df2 = modifyFlags df1 idirs depPkgs (expandSplice opt) build
-        df3 <- modifyFlagsWithOpts df2 $ ghcOpts opt
-        liftIO $ setLogger logging df3 ls
+            -> m ()
+initSession build Options {..} CompilerOptions {..} = do
+    df <- G.getSessionDynFlags
+    void $ G.setSessionDynFlags =<< (addCmdOpts ghcOptions
+      $ setLinkerOptions
+      $ setIncludeDirs includeDirs
+      $ setBuildEnv build
+      $ setEmptyLogger
+      $ Gap.addPackageFlags depPackages df)
 
+setEmptyLogger :: DynFlags -> DynFlags
+setEmptyLogger df = Gap.setLogAction df $ \_ _ _ _ _ -> return ()
+
 ----------------------------------------------------------------
 
--- | Initialize the 'DynFlags' relating to the compilation of a single
--- file or GHC session.
-initializeFlags :: GhcMonad m => Options -> m ()
-initializeFlags opt = do
-    dflags0 <- G.getSessionDynFlags
-    dflags1 <- modifyFlagsWithOpts dflags0 $ ghcOpts opt
-    void $ G.setSessionDynFlags dflags1
+-- we don't want to generate object code so we compile to bytecode
+-- (HscInterpreted) which implies LinkInMemory
+-- HscInterpreted
+setLinkerOptions :: DynFlags -> DynFlags
+setLinkerOptions df = df {
+    ghcLink   = LinkInMemory
+  , hscTarget = HscInterpreted
+  }
 
-----------------------------------------------------------------
+setIncludeDirs :: [IncludeDir] -> DynFlags -> DynFlags
+setIncludeDirs idirs df = df { importPaths = idirs }
 
-modifyFlags :: DynFlags -> [IncludeDir] -> [Package] -> Bool -> Build -> DynFlags
-modifyFlags d0 idirs depPkgs splice build
-  | splice    = setSplice d4
-  | otherwise = d4
-  where
-    d1 = d0 { importPaths = idirs }
-    d2 = d1 {
-        ghcLink   = LinkInMemory
-      , hscTarget = HscInterpreted
-      }
-    d3 = Gap.addDevPkgs d2 depPkgs
-    d4 | build == CabalPkg = Gap.setCabalPkg d3
-       | otherwise         = d3
+setBuildEnv :: Build -> DynFlags -> DynFlags
+setBuildEnv build = setHideAllPackages build . setCabalPackage build
 
-setSplice :: DynFlags -> DynFlags
-setSplice dflag = dopt_set dflag Gap.dumpSplicesFlag
+-- At the moment with this option set ghc only prints different error messages,
+-- suggesting the user to add a hidden package to the build-depends in his cabal
+-- file for example
+setCabalPackage :: Build -> DynFlags -> DynFlags
+setCabalPackage CabalPkg df = Gap.setCabalPkg df
+setCabalPackage _ df = df
 
-----------------------------------------------------------------
+-- | Enable hiding of all package not explicitly exposed (like Cabal does)
+setHideAllPackages :: Build -> DynFlags -> DynFlags
+setHideAllPackages CabalPkg df = Gap.setHideAllPackages df
+setHideAllPackages _ df = df
 
-modifyFlagsWithOpts :: GhcMonad m => DynFlags -> [GHCOption] -> m DynFlags
-modifyFlagsWithOpts dflags cmdOpts =
-    tfst <$> G.parseDynamicFlags dflags (map G.noLoc cmdOpts)
+-- | Parse command line ghc options and add them to the 'DynFlags' passed
+addCmdOpts :: GhcMonad m => [GHCOption] -> DynFlags -> m DynFlags
+addCmdOpts cmdOpts df =
+    tfst <$> G.parseDynamicFlags df (map G.noLoc cmdOpts)
   where
     tfst (a,_,_) = a
 
 ----------------------------------------------------------------
 
--- | Set the files that GHC will load / compile.
+-- | Set the files as targets and load them.
 setTargetFiles :: (GhcMonad m) => [FilePath] -> m ()
-setTargetFiles [] = error "ghc-mod: setTargetFiles: No target files given"
 setTargetFiles files = do
     targets <- forM files $ \file -> G.guessTarget file Nothing
     G.setTargets targets
-
--- | Adding the files to the targets.
-addTargetFiles :: (GhcMonad m) => [FilePath] -> m ()
-addTargetFiles [] = error "ghc-mod: addTargetFiles: No target files given"
-addTargetFiles files = do
-    targets <- forM files $ \file -> G.guessTarget file Nothing
-    mapM_ G.addTarget targets
+    void $ G.load LoadAllTargets
 
 ----------------------------------------------------------------
 
@@ -179,3 +166,30 @@
 getDynamicFlags = do
     mlibdir <- getSystemLibDir
     G.runGhc mlibdir G.getSessionDynFlags
+
+withDynFlags :: (DynFlags -> DynFlags) -> Ghc a -> Ghc a
+withDynFlags setFlag body = G.gbracket setup teardown (\_ -> body)
+  where
+    setup = do
+        dflag <- G.getSessionDynFlags
+        void $ G.setSessionDynFlags (setFlag dflag)
+        return dflag
+    teardown = void . G.setSessionDynFlags
+
+----------------------------------------------------------------
+
+-- | Set 'DynFlags' equivalent to "-w:".
+setNoWaringFlags :: DynFlags -> DynFlags
+setNoWaringFlags df = df { warningFlags = Gap.emptyWarnFlags}
+
+-- | Set 'DynFlags' equivalent to "-Wall".
+setAllWaringFlags :: DynFlags -> DynFlags
+setAllWaringFlags df = df { warningFlags = allWarningFlags }
+
+allWarningFlags :: Gap.WarnFlags
+allWarningFlags = unsafePerformIO $ do
+    mlibdir <- getSystemLibDir
+    G.runGhc mlibdir $ do
+        df <- G.getSessionDynFlags
+        df' <- addCmdOpts ["-Wall"] df
+        return $ G.warningFlags df'
diff --git a/Language/Haskell/GhcMod/Gap.hs b/Language/Haskell/GhcMod/Gap.hs
--- a/Language/Haskell/GhcMod/Gap.hs
+++ b/Language/Haskell/GhcMod/Gap.hs
@@ -5,15 +5,18 @@
   , mkTarget
   , withStyle
   , setLogAction
-  , supportedExtensions
   , getSrcSpan
   , getSrcFile
-  , setCtx
+  , withContext
   , fOptions
   , toStringBuffer
   , showSeverityCaption
   , setCabalPkg
-  , addDevPkgs
+  , setHideAllPackages
+  , addPackageFlags
+  , setDeferTypeErrors
+  , setDumpSplices
+  , isDumpSplices
   , filterOutChildren
   , infoThing
   , pprInfo
@@ -21,14 +24,12 @@
   , errorMsgSpan
   , typeForUser
   , deSugar
-#if __GLASGOW_HASKELL__ >= 702
-#else
-  , module Pretty
-#endif
   , showDocWith
   , GapThing(..)
   , fromTyThing
-  , dumpSplicesFlag
+  , fileModSummary
+  , WarnFlags
+  , emptyWarnFlags
   ) where
 
 import Control.Applicative hiding (empty)
@@ -55,7 +56,8 @@
 import qualified InstEnv
 import qualified Pretty
 import qualified StringBuffer as SB
-#if __GLASGOW_HASKELL__ >= 707
+
+#if __GLASGOW_HASKELL__ >= 708
 import FamInstEnv
 import ConLike (ConLike(..))
 import PatSyn (patSynType)
@@ -67,18 +69,14 @@
 import GHC hiding (ClsInst)
 #else
 import GHC hiding (Instance)
-#endif
-
-#if __GLASGOW_HASKELL__ < 702
-import CoreMonad (liftIO)
-import Pretty
-#endif
-
-#if __GLASGOW_HASKELL__ < 706
 import Control.Arrow hiding ((<+>))
 import Data.Convertible
 #endif
 
+#if __GLASGOW_HASKELL__ >= 704
+import qualified Data.IntSet as I (IntSet, empty)
+#endif
+
 ----------------------------------------------------------------
 ----------------------------------------------------------------
 --
@@ -116,7 +114,7 @@
 #endif
 
 showDocWith :: DynFlags -> Pretty.Mode -> Pretty.Doc -> String
-#if __GLASGOW_HASKELL__ >= 707
+#if __GLASGOW_HASKELL__ >= 708
 -- Pretty.showDocWith disappeard.
 -- https://github.com/ghc/ghc/commit/08a3536e4246e323fbcd8040e0b80001950fe9bc
 showDocWith dflags mode = Pretty.showDoc mode (pprCols dflags)
@@ -127,16 +125,6 @@
 ----------------------------------------------------------------
 ----------------------------------------------------------------
 
-supportedExtensions :: [String]
-#if __GLASGOW_HASKELL__ >= 700
-supportedExtensions = supportedLanguagesAndExtensions
-#else
-supportedExtensions = supportedLanguages
-#endif
-
-----------------------------------------------------------------
-----------------------------------------------------------------
-
 getSrcSpan :: SrcSpan -> Maybe (Int,Int,Int,Int)
 #if __GLASGOW_HASKELL__ >= 702
 getSrcSpan (RealSrcSpan spn)
@@ -173,41 +161,51 @@
 fOptions = [option | (option,_,_) <- fFlags]
         ++ [option | (option,_,_) <- fWarningFlags]
         ++ [option | (option,_,_) <- fLangFlags]
-#elif __GLASGOW_HASKELL__ == 702
+#else
 fOptions = [option | (option,_,_,_) <- fFlags]
         ++ [option | (option,_,_,_) <- fWarningFlags]
         ++ [option | (option,_,_,_) <- fLangFlags]
-#else
-fOptions = [option | (option,_,_) <- fFlags]
 #endif
 
 ----------------------------------------------------------------
 ----------------------------------------------------------------
 
-setCtx :: [ModSummary] -> Ghc Bool
+fileModSummary :: FilePath -> Ghc ModSummary
+fileModSummary file = do
+    mss <- getModuleGraph
+    let [ms] = filter (\m -> ml_hs_file (ms_location m) == Just file) mss
+    return ms
+
+withContext :: Ghc a -> Ghc a
+withContext action = gbracket setup teardown body
+  where
+    setup = getContext
+    teardown = setCtx
+    body _ = do
+        topImports >>= setCtx
+        action
+    topImports = do
+        mss <- getModuleGraph
+        ms <- map modName <$> filterM isTop mss
 #if __GLASGOW_HASKELL__ >= 704
-setCtx ms = do
-#if __GLASGOW_HASKELL__ >= 706
-    let modName = IIModule . moduleName . ms_mod
+        return ms
 #else
-    let modName = IIModule . ms_mod
+        return (ms,[])
 #endif
-    top <- map modName <$> filterM isTop ms
-    setContext top
-    return (not . null $ top)
+    isTop mos = lookupMod mos ||> returnFalse
+    lookupMod mos = lookupModule (ms_mod_name mos) Nothing >> return True
+    returnFalse = return False
+#if __GLASGOW_HASKELL__ >= 706
+    modName = IIModule . moduleName . ms_mod
+    setCtx = setContext
+#elif __GLASGOW_HASKELL__ >= 704
+    modName = IIModule . ms_mod
+    setCtx = setContext
 #else
-setCtx ms = do
-    top <- map ms_mod <$> filterM isTop ms
-    setContext top []
-    return (not . null $ top)
+    modName = ms_mod
+    setCtx = uncurry setContext
 #endif
-  where
-    isTop mos = lookupMod ||> returnFalse
-      where
-        lookupMod = lookupModule (ms_mod_name mos) Nothing >> return True
-        returnFalse = return False
 
-
 showSeverityCaption :: Severity -> String
 #if __GLASGOW_HASKELL__ >= 706
 showSeverityCaption SevWarning = "Warning: "
@@ -220,7 +218,7 @@
 ----------------------------------------------------------------
 
 setCabalPkg :: DynFlags -> DynFlags
-#if __GLASGOW_HASKELL__ >= 707
+#if __GLASGOW_HASKELL__ >= 708
 setCabalPkg dflag = gopt_set dflag Opt_BuildingCabalPackage
 #else
 setCabalPkg dflag = dopt_set dflag Opt_BuildingCabalPackage
@@ -228,20 +226,38 @@
 
 ----------------------------------------------------------------
 
-addDevPkgs :: DynFlags -> [Package] -> DynFlags
-addDevPkgs df []   = df
-addDevPkgs df pkgs = df''
+setHideAllPackages :: DynFlags -> DynFlags
+#if __GLASGOW_HASKELL__ >= 708
+setHideAllPackages df = gopt_set df Opt_HideAllPackages
+#else
+setHideAllPackages df = dopt_set df Opt_HideAllPackages
+#endif
+
+addPackageFlags :: [Package] -> DynFlags -> DynFlags
+addPackageFlags pkgs df =
+    df { packageFlags = packageFlags df ++ expose `map` pkgs }
   where
-#if __GLASGOW_HASKELL__ >= 707
-    df' = gopt_set df Opt_HideAllPackages
+    expose pkg = ExposePackageId $ showPkgId pkg
+
+----------------------------------------------------------------
+
+setDumpSplices :: DynFlags -> DynFlags
+setDumpSplices dflag = dopt_set dflag Opt_D_dump_splices
+
+isDumpSplices :: DynFlags -> Bool
+isDumpSplices dflag = dopt Opt_D_dump_splices dflag
+
+----------------------------------------------------------------
+
+
+setDeferTypeErrors :: DynFlags -> DynFlags
+#if __GLASGOW_HASKELL__ >= 708
+setDeferTypeErrors dflag = gopt_set dflag Opt_DeferTypeErrors
+#elif __GLASGOW_HASKELL__ >= 706
+setDeferTypeErrors dflag = dopt_set dflag Opt_DeferTypeErrors
 #else
-    df' = dopt_set df Opt_HideAllPackages
+setDeferTypeErrors = id
 #endif
-    df'' = df' {
-        packageFlags = map expose pkgs ++ packageFlags df
-      }
-    expose (pkg, Nothing) = ExposePackage pkg
-    expose (_, Just pid) = ExposePackageId pid
 
 ----------------------------------------------------------------
 ----------------------------------------------------------------
@@ -251,7 +267,7 @@
 
 
 instance HasType (LHsBind Id) where
-#if __GLASGOW_HASKELL__ >= 707
+#if __GLASGOW_HASKELL__ >= 708
     getType _ (L spn FunBind{fun_matches = MG _ in_tys out_typ}) = return $ Just (spn, typ)
       where typ = mkFunTys in_tys out_typ
 #else
@@ -272,7 +288,7 @@
 infoThing :: String -> Ghc SDoc
 infoThing str = do
     names <- parseName str
-#if __GLASGOW_HASKELL__ >= 707
+#if __GLASGOW_HASKELL__ >= 708
     mb_stuffs <- mapM (getInfo False) names
     let filtered = filterOutChildren (\(t,_f,_i,_fam) -> t) (catMaybes mb_stuffs)
 #else
@@ -281,7 +297,7 @@
 #endif
     return $ vcat (intersperse (text "") $ map (pprInfo False) filtered)
 
-#if __GLASGOW_HASKELL__ >= 707
+#if __GLASGOW_HASKELL__ >= 708
 pprInfo :: Bool -> (TyThing, GHC.Fixity, [ClsInst], [FamInst]) -> SDoc
 pprInfo _ (thing, fixity, insts, famInsts)
     = pprTyThingInContextLoc thing
@@ -308,14 +324,14 @@
 ----------------------------------------------------------------
 
 errorMsgSpan :: ErrMsg -> SrcSpan
-#if __GLASGOW_HASKELL__ >= 707
+#if __GLASGOW_HASKELL__ >= 708
 errorMsgSpan = errMsgSpan
 #else
 errorMsgSpan = head . errMsgSpans
 #endif
 
 typeForUser :: Type -> SDoc
-#if __GLASGOW_HASKELL__ >= 707
+#if __GLASGOW_HASKELL__ >= 708
 typeForUser = pprTypeForUser
 #else
 typeForUser = pprTypeForUser False
@@ -323,7 +339,7 @@
 
 deSugar :: TypecheckedModule -> LHsExpr Id -> HscEnv
          -> IO (Maybe CoreExpr)
-#if __GLASGOW_HASKELL__ >= 707
+#if __GLASGOW_HASKELL__ >= 708
 deSugar _   e hs_env = snd <$> deSugarExpr hs_env e
 #else
 deSugar tcm e hs_env = snd <$> deSugarExpr hs_env modu rn_env ty_env e
@@ -341,7 +357,7 @@
 
 fromTyThing :: TyThing -> GapThing
 fromTyThing (AnId i)                   = GtA $ varType i
-#if __GLASGOW_HASKELL__ >= 707
+#if __GLASGOW_HASKELL__ >= 708
 fromTyThing (AConLike (RealDataCon d)) = GtA $ dataConRepType d
 fromTyThing (AConLike (PatSynCon p))   = GtA $ patSynType p
 #else
@@ -351,10 +367,14 @@
 fromTyThing _                          = GtN
 
 ----------------------------------------------------------------
+----------------------------------------------------------------
 
-#if __GLASGOW_HASKELL__ >= 707
-dumpSplicesFlag :: DumpFlag
+#if __GLASGOW_HASKELL__ >= 704
+type WarnFlags = I.IntSet
+emptyWarnFlags :: WarnFlags
+emptyWarnFlags = I.empty
 #else
-dumpSplicesFlag :: DynFlag
+type WarnFlags = [WarningFlag]
+emptyWarnFlags :: WarnFlags
+emptyWarnFlags = []
 #endif
-dumpSplicesFlag = Opt_D_dump_splices
diff --git a/Language/Haskell/GhcMod/Ghc.hs b/Language/Haskell/GhcMod/Ghc.hs
new file mode 100644
--- /dev/null
+++ b/Language/Haskell/GhcMod/Ghc.hs
@@ -0,0 +1,25 @@
+module Language.Haskell.GhcMod.Ghc (
+  -- * Converting the 'Ghc' monad to the 'IO' monad
+    withGHC
+  , withGHC'
+  -- * 'Ghc' utilities
+  , boot
+  , browse
+  , check
+  , info
+  , types
+  , modules
+  -- * 'SymMdlDb'
+  , Symbol
+  , SymMdlDb
+  , getSymMdlDb
+  , lookupSym
+  ) where
+
+import Language.Haskell.GhcMod.Boot
+import Language.Haskell.GhcMod.Browse
+import Language.Haskell.GhcMod.Check
+import Language.Haskell.GhcMod.Find
+import Language.Haskell.GhcMod.GHCApi
+import Language.Haskell.GhcMod.Info
+import Language.Haskell.GhcMod.List
diff --git a/Language/Haskell/GhcMod/GhcPkg.hs b/Language/Haskell/GhcMod/GhcPkg.hs
new file mode 100644
--- /dev/null
+++ b/Language/Haskell/GhcMod/GhcPkg.hs
@@ -0,0 +1,153 @@
+{-# LANGUAGE BangPatterns, ScopedTypeVariables, TupleSections #-}
+module Language.Haskell.GhcMod.GhcPkg (
+    ghcPkgList
+  , ghcPkgListEx
+  , ghcPkgDbOpt
+  , ghcPkgDbStackOpts
+  , ghcDbStackOpts
+  , ghcDbOpt
+  , getSandboxDb
+  , getPackageDbStack
+  ) where
+
+import Config (cProjectVersionInt) -- ghc version
+import Control.Applicative ((<$>))
+import Control.Exception (SomeException(..))
+import qualified Control.Exception as E
+import Data.Char (isSpace,isAlphaNum)
+import Data.List (isPrefixOf, intercalate)
+import Data.Maybe (listToMaybe, maybeToList)
+import Language.Haskell.GhcMod.Types
+import Language.Haskell.GhcMod.Utils
+import System.Exit (ExitCode(..))
+import System.FilePath ((</>))
+import System.IO (hPutStrLn,stderr)
+import System.Process (readProcessWithExitCode)
+import Text.ParserCombinators.ReadP (ReadP, char, between, sepBy1, many1, string, choice, eof)
+import qualified Text.ParserCombinators.ReadP as P
+
+ghcVersion :: Int
+ghcVersion = read cProjectVersionInt
+
+-- | Get path to sandbox package db
+getSandboxDb :: FilePath -- ^ Path to the cabal package root directory
+                         -- (containing the @cabal.sandbox.config@ file)
+             -> IO FilePath
+getSandboxDb cdir = getSandboxDbDir (cdir </> "cabal.sandbox.config")
+
+-- | Extract the sandbox package db directory from the cabal.sandbox.config file.
+--   Exception is thrown if the sandbox config file is broken.
+getSandboxDbDir :: FilePath -- ^ Path to the @cabal.sandbox.config@ file
+                -> IO FilePath
+getSandboxDbDir sconf = do
+    -- Be strict to ensure that an error can be caught.
+    !path <- extractValue . parse <$> readFile sconf
+    return path
+  where
+    key = "package-db:"
+    keyLen = length key
+
+    parse = head . filter (key `isPrefixOf`) . lines
+    extractValue = dropWhileEnd isSpace . dropWhile isSpace . drop keyLen
+
+getPackageDbStack :: FilePath -- ^ Project Directory (where the
+                                 -- cabal.sandbox.config file would be if it
+                                 -- exists)
+                  -> IO [GhcPkgDb]
+getPackageDbStack cdir =
+    (getSandboxDb cdir >>= \db -> return [GlobalDb, PackageDb db])
+      `E.catch` \(_ :: SomeException) -> return [GlobalDb, UserDb]
+
+
+-- | List packages in one or more ghc package store
+ghcPkgList :: [GhcPkgDb] -> IO [PackageBaseName]
+ghcPkgList dbs = map fst3 <$> ghcPkgListEx dbs
+  where fst3 (x,_,_) = x
+
+ghcPkgListEx :: [GhcPkgDb] -> IO [Package]
+ghcPkgListEx dbs = do
+    (rv,output,err) <- readProcessWithExitCode "ghc-pkg" opts ""
+    case rv of
+      ExitFailure val -> do
+          hPutStrLn stderr err
+          fail $ "ghc-pkg " ++ unwords opts ++ " (exit " ++ show val ++ ")"
+      ExitSuccess -> return ()
+
+    return $ parseGhcPkgOutput $ lines output
+  where
+    opts = ["list", "-v"] ++ ghcPkgDbStackOpts dbs
+
+parseGhcPkgOutput :: [String] -> [Package]
+parseGhcPkgOutput [] = []
+parseGhcPkgOutput (l:ls) =
+    parseGhcPkgOutput ls ++ case l of
+      [] -> []
+      h:_ | isSpace h -> maybeToList $ packageLine l
+          | otherwise -> []
+
+packageLine :: String -> Maybe Package
+packageLine l =
+    case listToMaybe $ P.readP_to_S packageLineP l of
+      Just ((Normal,p),_) -> Just p
+      Just ((Hidden,p),_) -> Just p
+      _ -> Nothing
+
+data PackageState = Normal | Hidden | Broken deriving (Eq,Show)
+
+packageLineP :: ReadP (PackageState, Package)
+packageLineP = do
+    P.skipSpaces
+    p <- choice [ (Hidden,) <$> between (char '(') (char ')') packageP
+                , (Broken,) <$> between (char '{') (char '}') packageP
+                , (Normal,) <$> packageP ]
+    eof
+    return p
+
+packageP :: ReadP (PackageBaseName, PackageVersion, PackageId)
+packageP = do
+    pkgSpec@(name,ver) <- packageSpecP
+    P.skipSpaces
+    i <- between (char '(') (char ')') $ packageIdSpecP pkgSpec
+    return (name,ver,i)
+
+packageSpecP :: ReadP (PackageBaseName,PackageVersion)
+packageSpecP = do
+  fs <- many1 packageCompCharP `sepBy1` char '-'
+  return (intercalate "-" (init fs), last fs)
+
+packageIdSpecP :: (PackageBaseName,PackageVersion) -> ReadP PackageId
+packageIdSpecP (name,ver) = do
+    string name >> char '-' >> string ver >> char '-' >> return ()
+    many1 (P.satisfy isAlphaNum)
+
+packageCompCharP :: ReadP Char
+packageCompCharP =
+    P.satisfy $ \c -> isAlphaNum c || c `elem` "_-."
+
+-- | Get options needed to add a list of package dbs to ghc-pkg's db stack
+ghcPkgDbStackOpts :: [GhcPkgDb] -- ^ Package db stack
+                  -> [String]
+ghcPkgDbStackOpts dbs = ghcPkgDbOpt `concatMap` dbs
+
+-- | Get options needed to add a list of package dbs to ghc's db stack
+ghcDbStackOpts :: [GhcPkgDb] -- ^ Package db stack
+               -> [String]
+ghcDbStackOpts dbs = ghcDbOpt `concatMap` dbs
+
+ghcPkgDbOpt :: GhcPkgDb -> [String]
+ghcPkgDbOpt GlobalDb = ["--global"]
+ghcPkgDbOpt UserDb   = ["--user"]
+ghcPkgDbOpt (PackageDb pkgDb)
+  | ghcVersion < 706 = ["--no-user-package-conf", "--package-conf=" ++ pkgDb]
+  | otherwise        = ["--no-user-package-db",   "--package-db="   ++ pkgDb]
+
+ghcDbOpt :: GhcPkgDb -> [String]
+ghcDbOpt GlobalDb
+  | ghcVersion < 706 = ["-global-package-conf"]
+  | otherwise        = ["-global-package-db"]
+ghcDbOpt UserDb
+  | ghcVersion < 706 = ["-user-package-conf"]
+  | otherwise        = ["-user-package-db"]
+ghcDbOpt (PackageDb pkgDb)
+  | ghcVersion < 706 = ["-no-user-package-conf", "-package-conf", pkgDb]
+  | otherwise        = ["-no-user-package-db",   "-package-db",   pkgDb]
diff --git a/Language/Haskell/GhcMod/Info.hs b/Language/Haskell/GhcMod/Info.hs
--- a/Language/Haskell/GhcMod/Info.hs
+++ b/Language/Haskell/GhcMod/Info.hs
@@ -1,68 +1,56 @@
-{-# LANGUAGE TupleSections, FlexibleInstances, TypeSynonymInstances, CPP #-}
-{-# LANGUAGE Rank2Types #-}
+{-# LANGUAGE TupleSections, FlexibleInstances, Rank2Types #-}
 {-# OPTIONS_GHC -fno-warn-orphans #-}
 
 module Language.Haskell.GhcMod.Info (
     infoExpr
   , info
   , typeExpr
-  , typeOf
+  , types
   ) where
 
 import Control.Applicative ((<$>))
-import Control.Monad (void)
 import CoreMonad (liftIO)
 import CoreUtils (exprType)
 import Data.Function (on)
---import Data.Generics (Typeable, GenericQ, mkQ)
-import Data.Generics hiding (typeOf)
+import Data.Generics
 import Data.List (sortBy)
-import Data.Maybe (catMaybes, fromMaybe, listToMaybe)
+import Data.Maybe (catMaybes, fromMaybe)
 import Data.Ord as O
-import Data.Time.Clock (getCurrentTime)
-import GHC (Ghc, LHsBind, LHsExpr, LPat, Id, TypecheckedModule(..), DynFlags, SrcSpan, Type, Located, TypecheckedSource, GenLocated(L), LoadHowMuch(..), TargetId(..))
+import Exception (ghandle, SomeException(..))
+import GHC (Ghc, LHsBind, LHsExpr, LPat, Id, TypecheckedModule(..), DynFlags, SrcSpan, Type, Located, TypecheckedSource, GenLocated(L))
 import qualified GHC as G
 import GHC.SYB.Utils (Stage(TypeChecker), everythingStaged)
-import HscTypes (ms_imps)
 import Language.Haskell.GhcMod.Doc (showPage, showOneLine, getStyle)
 import Language.Haskell.GhcMod.GHCApi
-import Language.Haskell.GhcMod.GHCChoice ((||>), goNext)
-import Language.Haskell.GhcMod.Gap (HasType(..))
+import Language.Haskell.GhcMod.Gap (HasType(..), setDeferTypeErrors)
 import qualified Language.Haskell.GhcMod.Gap as Gap
 import Language.Haskell.GhcMod.Types
-import Outputable (PprStyle, ppr)
+import Outputable (PprStyle)
 import TcHsSyn (hsPatType)
 
 ----------------------------------------------------------------
 
-data Cmd = Info | Type deriving Eq
-
-----------------------------------------------------------------
-
 -- | Obtaining information of a target expression. (GHCi's info:)
 infoExpr :: Options
          -> Cradle
          -> FilePath     -- ^ A target file.
-         -> ModuleString -- ^ A module name.
          -> Expression   -- ^ A Haskell expression.
          -> IO String
-infoExpr opt cradle file modstr expr = (++ "\n") <$> withGHCDummyFile (info opt cradle file modstr expr)
+infoExpr opt cradle file expr = withGHC' $ do
+    initializeFlagsWithCradle opt cradle
+    info opt file expr
 
 -- | Obtaining information of a target expression. (GHCi's info:)
 info :: Options
-     -> Cradle
      -> FilePath     -- ^ A target file.
-     -> ModuleString -- ^ A module name.
      -> Expression   -- ^ A Haskell expression.
      -> Ghc String
-info opt cradle file modstr expr =
-    inModuleContext Info opt cradle file modstr exprToInfo "Cannot show info"
+info opt file expr = convert opt <$> ghandle handler body
   where
-    exprToInfo = do
-        dflag <- G.getSessionDynFlags
+    body = inModuleContext file $ \dflag style -> do
         sdoc <- Gap.infoThing expr
-        style <- getStyle
         return $ showPage dflag style sdoc
+    handler (SomeException _) = return "Cannot show info"
 
 ----------------------------------------------------------------
 
@@ -81,50 +69,38 @@
 typeExpr :: Options
          -> Cradle
          -> FilePath     -- ^ A target file.
-         -> ModuleString -- ^ A odule name.
          -> Int          -- ^ Line number.
          -> Int          -- ^ Column number.
          -> IO String
-typeExpr opt cradle file modstr lineNo colNo = withGHCDummyFile $ typeOf opt cradle file modstr lineNo colNo
+typeExpr opt cradle file lineNo colNo = withGHC' $ do
+    initializeFlagsWithCradle opt cradle
+    types opt file lineNo colNo
 
 -- | Obtaining type of a target expression. (GHCi's type:)
-typeOf :: Options
-       -> Cradle
-       -> FilePath     -- ^ A target file.
-       -> ModuleString -- ^ A odule name.
-       -> Int          -- ^ Line number.
-       -> Int          -- ^ Column number.
-       -> Ghc String
-typeOf opt cradle file modstr lineNo colNo =
-    inModuleContext Type opt cradle file modstr exprToType errmsg
+types :: Options
+      -> FilePath     -- ^ A target file.
+      -> Int          -- ^ Line number.
+      -> Int          -- ^ Column number.
+      -> Ghc String
+types opt file lineNo colNo = convert opt <$> ghandle handler body
   where
-    exprToType = do
-      modSum <- G.getModSummary $ G.mkModuleName modstr
-      p <- G.parseModule modSum
-      tcm@TypecheckedModule{tm_typechecked_source = tcs} <- G.typecheckModule p
-      let bs = listifySpans tcs (lineNo, colNo) :: [LHsBind Id]
-          es = listifySpans tcs (lineNo, colNo) :: [LHsExpr Id]
-          ps = listifySpans tcs (lineNo, colNo) :: [LPat Id]
-      bts <- mapM (getType tcm) bs
-      ets <- mapM (getType tcm) es
-      pts <- mapM (getType tcm) ps
-      dflag <- G.getSessionDynFlags
-      style <- getStyle
-      let sss = map (toTup dflag style) $ sortBy (cmp `on` fst) $ catMaybes $ concat [ets, bts, pts]
-      return $ convert opt sss
-
-    toTup :: DynFlags -> PprStyle -> (SrcSpan, Type) -> ((Int,Int,Int,Int),String)
-    toTup dflag style (spn, typ) = (fourInts spn, pretty dflag style typ)
-
-    fourInts :: SrcSpan -> (Int,Int,Int,Int)
-    fourInts = fromMaybe (0,0,0,0) . Gap.getSrcSpan
-
-    cmp a b
-      | a `G.isSubspanOf` b = O.LT
-      | b `G.isSubspanOf` a = O.GT
-      | otherwise = O.EQ
+    body = inModuleContext file $ \dflag style -> do
+        modSum <- Gap.fileModSummary file
+        srcSpanTypes <- getSrcSpanType modSum lineNo colNo
+        return $ map (toTup dflag style) $ sortBy (cmp `on` fst) srcSpanTypes
+    handler (SomeException _) = return []
 
-    errmsg = convert opt ([] :: [((Int,Int,Int,Int),String)])
+getSrcSpanType :: G.ModSummary -> Int -> Int -> Ghc [(SrcSpan, Type)]
+getSrcSpanType modSum lineNo colNo = do
+    p <- G.parseModule modSum
+    tcm@TypecheckedModule{tm_typechecked_source = tcs} <- G.typecheckModule p
+    let bs = listifySpans tcs (lineNo, colNo) :: [LHsBind Id]
+        es = listifySpans tcs (lineNo, colNo) :: [LHsExpr Id]
+        ps = listifySpans tcs (lineNo, colNo) :: [LPat Id]
+    bts <- mapM (getType tcm) bs
+    ets <- mapM (getType tcm) es
+    pts <- mapM (getType tcm) ps
+    return $ catMaybes $ concat [ets, bts, pts]
 
 listifySpans :: Typeable a => TypecheckedSource -> (Int, Int) -> [Located a]
 listifySpans tcs lc = listifyStaged TypeChecker p tcs
@@ -134,40 +110,28 @@
 listifyStaged :: Typeable r => Stage -> (r -> Bool) -> GenericQ [r]
 listifyStaged s p = everythingStaged s (++) [] ([] `mkQ` (\x -> [x | p x]))
 
+cmp :: SrcSpan -> SrcSpan -> Ordering
+cmp a b
+  | a `G.isSubspanOf` b = O.LT
+  | b `G.isSubspanOf` a = O.GT
+  | otherwise           = O.EQ
+
+toTup :: DynFlags -> PprStyle -> (SrcSpan, Type) -> ((Int,Int,Int,Int),String)
+toTup dflag style (spn, typ) = (fourInts spn, pretty dflag style typ)
+
+fourInts :: SrcSpan -> (Int,Int,Int,Int)
+fourInts = fromMaybe (0,0,0,0) . Gap.getSrcSpan
+
 pretty :: DynFlags -> PprStyle -> Type -> String
 pretty dflag style = showOneLine dflag style . Gap.typeForUser
 
 ----------------------------------------------------------------
 
-inModuleContext :: Cmd -> Options -> Cradle -> FilePath -> ModuleString -> Ghc String -> String -> Ghc String
-inModuleContext _ opt cradle file modstr action errmsg =
-    valid ||> invalid ||> return errmsg
-  where
-    valid = do
-        void $ initializeFlagsWithCradle opt cradle ["-w:"] False
-        setTargetFiles [file]
-        void $ G.load LoadAllTargets
-        doif setContextFromTarget action
-    invalid = do
-        void $ initializeFlagsWithCradle opt cradle ["-w:"] False
-        setTargetBuffer
-        void $ G.load LoadAllTargets
-        doif setContextFromTarget action
-    setTargetBuffer = do
-        modgraph <- G.depanal [G.mkModuleName modstr] True
+inModuleContext :: FilePath -> (DynFlags -> PprStyle -> Ghc a) -> Ghc a
+inModuleContext file action =
+    withDynFlags (setDeferTypeErrors . setNoWaringFlags) $ do
+    setTargetFiles [file]
+    Gap.withContext $ do
         dflag <- G.getSessionDynFlags
         style <- getStyle
-        let imports = concatMap (map (showPage dflag style . ppr . G.unLoc)) $
-                      map ms_imps modgraph ++ map G.ms_srcimps modgraph
-            moddef = "module " ++ sanitize modstr ++ " where"
-            header = moddef : imports
-        importsBuf <- Gap.toStringBuffer header
-        clkTime <- liftIO getCurrentTime
-        G.setTargets [Gap.mkTarget (TargetModule $ G.mkModuleName modstr)
-                                   True
-                                   (Just (importsBuf, clkTime))]
-    doif m t = m >>= \ok -> if ok then t else goNext
-    sanitize = fromMaybe "SomeModule" . listToMaybe . words
-
-setContextFromTarget :: Ghc Bool
-setContextFromTarget = G.depanal [] False >>= Gap.setCtx
+        action dflag style
diff --git a/Language/Haskell/GhcMod/Internal.hs b/Language/Haskell/GhcMod/Internal.hs
--- a/Language/Haskell/GhcMod/Internal.hs
+++ b/Language/Haskell/GhcMod/Internal.hs
@@ -2,14 +2,13 @@
 
 module Language.Haskell.GhcMod.Internal (
   -- * Types
-    LogReader
-  , GHCOption
+    GHCOption
   , Package
+  , PackageBaseName
+  , PackageVersion
+  , PackageId
   , IncludeDir
   , CompilerOptions(..)
-  -- * Cradle
-  , userPackageDbOptsForGhc
-  , userPackageDbOptsForGhcPkg
   -- * Cabal API
   , parseCabalFile
   , getCompilerOptions
@@ -21,13 +20,13 @@
   , getSystemLibDir
   , getDynamicFlags
   -- * Initializing 'DynFlags'
-  , initializeFlags
   , initializeFlagsWithCradle
-  -- * 'Ghc' Monad
+  -- * Targets
   , setTargetFiles
-  , addTargetFiles
-  , handleErrMsg
-  , browseAll
+  -- * Logging
+  , withLogger
+  , setNoWaringFlags
+  , setAllWaringFlags
   -- * 'Ghc' Choice
   , (||>)
   , goNext
@@ -36,10 +35,8 @@
   , (|||>)
   ) where
 
-import Language.Haskell.GhcMod.Browse
 import Language.Haskell.GhcMod.CabalApi
-import Language.Haskell.GhcMod.Cradle
-import Language.Haskell.GhcMod.ErrMsg
 import Language.Haskell.GhcMod.GHCApi
 import Language.Haskell.GhcMod.GHCChoice
+import Language.Haskell.GhcMod.Logger
 import Language.Haskell.GhcMod.Types
diff --git a/Language/Haskell/GhcMod/Lang.hs b/Language/Haskell/GhcMod/Lang.hs
--- a/Language/Haskell/GhcMod/Lang.hs
+++ b/Language/Haskell/GhcMod/Lang.hs
@@ -1,9 +1,9 @@
 module Language.Haskell.GhcMod.Lang where
 
-import qualified Language.Haskell.GhcMod.Gap as Gap
+import DynFlags (supportedLanguagesAndExtensions)
 import Language.Haskell.GhcMod.Types
 
 -- | Listing language extensions.
 
 listLanguages :: Options -> IO String
-listLanguages opt = return $ convert opt Gap.supportedExtensions
+listLanguages opt = return $ convert opt supportedLanguagesAndExtensions
diff --git a/Language/Haskell/GhcMod/Lint.hs b/Language/Haskell/GhcMod/Lint.hs
--- a/Language/Haskell/GhcMod/Lint.hs
+++ b/Language/Haskell/GhcMod/Lint.hs
@@ -1,38 +1,18 @@
 module Language.Haskell.GhcMod.Lint where
 
 import Control.Applicative ((<$>))
-import Control.Exception (finally)
-import Data.List (intercalate)
-import GHC.IO.Handle (hDuplicate, hDuplicateTo)
+import Control.Exception (handle, SomeException(..))
+import Language.Haskell.GhcMod.Logger (checkErrorPrefix)
 import Language.Haskell.GhcMod.Types
 import Language.Haskell.HLint (hlint)
-import System.Directory (getTemporaryDirectory, removeFile)
-import System.IO (hClose, openTempFile, stdout)
 
 -- | Checking syntax of a target file using hlint.
 --   Warnings and errors are returned.
 lintSyntax :: Options
            -> FilePath  -- ^ A target file.
            -> IO String
-lintSyntax opt file = pack <$> lint hopts file
+lintSyntax opt file = handle handler $ pack <$> hlint (file : "--quiet" : hopts)
   where
-    LineSeparator lsep = lineSeparator opt
-    pack = unlines . map (intercalate lsep . lines)
+    pack = convert opt . map (init . show) -- init drops the last \n.
     hopts = hlintOpts opt
-
--- | Checking syntax of a target file using hlint.
---   Warnings and errors are returned.
-lint :: [String]
-     -> FilePath    -- ^ A target file.
-     -> IO [String]
-lint hopts file = map show <$> suppressStdout (hlint (file : hopts))
-
-suppressStdout :: IO a -> IO a
-suppressStdout f = do
-    tmpdir <- getTemporaryDirectory
-    (path, handle) <- openTempFile tmpdir "ghc-mod-hlint"
-    removeFile path
-    dup <- hDuplicate stdout
-    hDuplicateTo handle stdout
-    hClose handle
-    f `finally` hDuplicateTo dup stdout
+    handler (SomeException e) = return $ checkErrorPrefix ++ show e ++ "\n"
diff --git a/Language/Haskell/GhcMod/List.hs b/Language/Haskell/GhcMod/List.hs
--- a/Language/Haskell/GhcMod/List.hs
+++ b/Language/Haskell/GhcMod/List.hs
@@ -1,7 +1,7 @@
-module Language.Haskell.GhcMod.List (listModules, listMods) where
+module Language.Haskell.GhcMod.List (listModules, modules) where
 
 import Control.Applicative ((<$>))
-import Control.Monad (void)
+import Control.Exception (SomeException(..))
 import Data.List (nub, sort)
 import GHC (Ghc)
 import qualified GHC as G
@@ -14,21 +14,23 @@
 
 -- | Listing installed modules.
 listModules :: Options -> Cradle -> IO String
-listModules opt cradle = convert opt . nub . sort . map dropPkgs <$> withGHCDummyFile (listMods opt cradle)
-  where
-    dropPkgs (name, pkg)
-      | detailed opt = name ++ " " ++ pkg
-      | otherwise = name
+listModules opt cradle = withGHC' $ do
+    initializeFlagsWithCradle opt cradle
+    modules opt
 
 -- | Listing installed modules.
-listMods :: Options -> Cradle -> Ghc [(String, String)]
-listMods opt cradle = do
-    void $ initializeFlagsWithCradle opt cradle [] False
-    getExposedModules <$> G.getSessionDynFlags
+modules :: Options -> Ghc String
+modules opt = convert opt . arrange <$> (getModules `G.gcatch` handler)
   where
+    getModules = getExposedModules <$> G.getSessionDynFlags
     getExposedModules = concatMap exposedModules'
                       . eltsUFM . pkgIdMap . G.pkgState
     exposedModules' p =
         map G.moduleNameString (exposedModules p)
     	`zip`
         repeat (display $ sourcePackageId p)
+    arrange = nub . sort . map dropPkgs
+    dropPkgs (name, pkg)
+      | detailed opt = name ++ " " ++ pkg
+      | otherwise = name
+    handler (SomeException _) = return []
diff --git a/Language/Haskell/GhcMod/Logger.hs b/Language/Haskell/GhcMod/Logger.hs
new file mode 100644
--- /dev/null
+++ b/Language/Haskell/GhcMod/Logger.hs
@@ -0,0 +1,95 @@
+{-# LANGUAGE BangPatterns, CPP #-}
+
+module Language.Haskell.GhcMod.Logger (
+    withLogger
+  , checkErrorPrefix
+  ) where
+
+import Bag (Bag, bagToList)
+import Control.Applicative ((<$>))
+import CoreMonad (liftIO)
+import Data.IORef (IORef, newIORef, readIORef, writeIORef, modifyIORef)
+import Data.Maybe (fromMaybe)
+import ErrUtils (ErrMsg, errMsgShortDoc, errMsgExtraInfo)
+import Exception (ghandle)
+import GHC (Ghc, DynFlags, SrcSpan, Severity(SevError))
+import qualified GHC as G
+import HscTypes (SourceError, srcErrorMessages)
+import Language.Haskell.GhcMod.Doc (showPage, getStyle)
+import Language.Haskell.GhcMod.GHCApi (withDynFlags)
+import qualified Language.Haskell.GhcMod.Gap as Gap
+import Language.Haskell.GhcMod.Types (Options, convert)
+import Outputable (PprStyle, SDoc)
+import System.FilePath (normalise)
+
+----------------------------------------------------------------
+
+type Builder = [String] -> [String]
+
+newtype LogRef = LogRef (IORef Builder)
+
+newLogRef :: IO LogRef
+newLogRef = LogRef <$> newIORef id
+
+readAndClearLogRef :: Options -> LogRef -> IO String
+readAndClearLogRef opt (LogRef ref) = do
+    b <- readIORef ref
+    writeIORef ref id
+    return $! convert opt (b [])
+
+appendLogRef :: DynFlags -> LogRef -> DynFlags -> Severity -> SrcSpan -> PprStyle -> SDoc -> IO ()
+appendLogRef df (LogRef ref) _ sev src style msg = do
+        let !l = ppMsg src sev df style msg
+        modifyIORef ref (\b -> b . (l:))
+
+----------------------------------------------------------------
+
+-- | Set the session flag (e.g. "-Wall" or "-w:") then
+--   executes a body. Log messages are returned as 'String'.
+--   Right is success and Left is failure.
+withLogger :: Options -> (DynFlags -> DynFlags) -> Ghc () -> Ghc (Either String String)
+withLogger opt setDF body = ghandle (sourceError opt) $ do
+    logref <- liftIO $ newLogRef
+    withDynFlags (setLogger logref . setDF) $ do
+        body
+        liftIO $ Right <$> readAndClearLogRef opt logref
+  where
+    setLogger logref df = Gap.setLogAction df $ appendLogRef df logref
+
+----------------------------------------------------------------
+
+-- | Converting 'SourceError' to 'String'.
+sourceError :: Options -> SourceError -> Ghc (Either String String)
+sourceError opt err = do
+    dflag <- G.getSessionDynFlags
+    style <- getStyle
+    let ret = convert opt . errBagToStrList dflag style . srcErrorMessages $ err
+    return (Left ret)
+
+errBagToStrList :: DynFlags -> PprStyle -> Bag ErrMsg -> [String]
+errBagToStrList dflag style = map (ppErrMsg dflag style) . reverse . bagToList
+
+----------------------------------------------------------------
+
+ppErrMsg :: DynFlags -> PprStyle -> ErrMsg -> String
+ppErrMsg dflag style err = ppMsg spn SevError dflag style msg ++ ext
+   where
+     spn = Gap.errorMsgSpan err
+     msg = errMsgShortDoc err
+     ext = showPage dflag style (errMsgExtraInfo err)
+
+ppMsg :: SrcSpan -> Severity-> DynFlags -> PprStyle -> SDoc -> String
+ppMsg spn sev dflag style msg = prefix ++ cts
+  where
+    cts  = showPage dflag style msg
+    defaultPrefix
+      | Gap.isDumpSplices dflag = ""
+      | otherwise               = checkErrorPrefix
+    prefix = fromMaybe defaultPrefix $ do
+        (line,col,_,_) <- Gap.getSrcSpan spn
+        file <- normalise <$> Gap.getSrcFile spn
+        let severityCaption = Gap.showSeverityCaption sev
+        return $ file ++ ":" ++ show line ++ ":" ++ show col ++ ":" ++ severityCaption
+
+checkErrorPrefix :: String
+checkErrorPrefix = "Dummy:0:0:Error:"
diff --git a/Language/Haskell/GhcMod/PkgDoc.hs b/Language/Haskell/GhcMod/PkgDoc.hs
--- a/Language/Haskell/GhcMod/PkgDoc.hs
+++ b/Language/Haskell/GhcMod/PkgDoc.hs
@@ -1,8 +1,9 @@
 module Language.Haskell.GhcMod.PkgDoc (packageDoc) where
 
-import Control.Applicative ((<$>))
 import Language.Haskell.GhcMod.Types
-import Language.Haskell.GhcMod.Cradle
+import Language.Haskell.GhcMod.GhcPkg
+
+import Control.Applicative ((<$>))
 import System.Process (readProcess)
 
 -- | Obtaining the package name and the doc path of a module.
@@ -22,6 +23,8 @@
         let ret = pkg ++ " " ++ drop 14 htmlpath
         return ret
   where
-    toModuleOpts = ["find-module", mdl, "--simple-output"] ++ userPackageDbOptsForGhcPkg (cradlePackageDb cradle)
-    toDocDirOpts pkg = ["field", pkg, "haddock-html"] ++ userPackageDbOptsForGhcPkg (cradlePackageDb cradle)
+    toModuleOpts = ["find-module", mdl, "--simple-output"]
+                   ++ ghcPkgDbStackOpts (cradlePkgDbStack cradle)
+    toDocDirOpts pkg = ["field", pkg, "haddock-html"]
+                       ++ ghcPkgDbStackOpts (cradlePkgDbStack cradle)
     trim = takeWhile (`notElem` " \n")
diff --git a/Language/Haskell/GhcMod/Types.hs b/Language/Haskell/GhcMod/Types.hs
--- a/Language/Haskell/GhcMod/Types.hs
+++ b/Language/Haskell/GhcMod/Types.hs
@@ -2,6 +2,8 @@
 
 module Language.Haskell.GhcMod.Types where
 
+import Data.List (intercalate)
+
 -- | Output style.
 data OutputStyle = LispStyle  -- ^ S expression style.
                  | PlainStyle -- ^ Plain textstyle.
@@ -12,19 +14,15 @@
 data Options = Options {
     outputStyle   :: OutputStyle
   , hlintOpts     :: [String]
-  , ghcOpts       :: [String]
+  , ghcOpts       :: [GHCOption]
   -- | If 'True', 'browse' also returns operators.
   , operators     :: Bool
   -- | If 'True', 'browse' also returns types.
   , detailed      :: Bool
   -- | If 'True', 'browse' will return fully qualified name
   , qualified     :: Bool
-  -- | Whether or not Template Haskell should be expanded.
-  , expandSplice  :: Bool
   -- | Line separator string.
   , lineSeparator :: LineSeparator
-  -- | Package id of module
-  , packageId :: Maybe String
   }
 
 -- | A default 'Options'.
@@ -36,47 +34,96 @@
   , operators     = False
   , detailed      = False
   , qualified     = False
-  , expandSplice  = False
   , lineSeparator = LineSeparator "\0"
-  , packageId     = Nothing
   }
 
 ----------------------------------------------------------------
 
+type Builder = String -> String
+
+-- |
+--
+-- >>> replace '"' "\\\"" "foo\"bar" ""
+-- "foo\\\"bar"
+replace :: Char -> String -> String -> Builder
+replace _ _  [] = id
+replace c cs (x:xs)
+  | x == c    = (cs ++) . replace c cs xs
+  | otherwise = (x :) . replace c cs xs
+
+inter :: Char -> [Builder] -> Builder
+inter _ [] = id
+inter c bs = foldr1 (\x y -> x . (c:) . y) bs
+
 convert :: ToString a => Options -> a -> String
-convert Options{ outputStyle = LispStyle  } = toLisp
-convert Options{ outputStyle = PlainStyle } = toPlain
+convert opt@Options { outputStyle = LispStyle  } x = toLisp  opt x "\n"
+convert opt@Options { outputStyle = PlainStyle } x = toPlain opt x "\n"
 
 class ToString a where
-    toLisp  :: a -> String
-    toPlain :: a -> String
+    toLisp  :: Options -> a -> Builder
+    toPlain :: Options -> a -> Builder
 
+lineSep :: Options -> String
+lineSep opt = lsep
+  where
+    LineSeparator lsep = lineSeparator opt
+
+-- |
+--
+-- >>> toLisp defaultOptions "fo\"o" ""
+-- "\"fo\\\"o\""
+-- >>> toPlain defaultOptions "foo" ""
+-- "foo"
+instance ToString String where
+    toLisp  opt = quote opt
+    toPlain opt = replace '\n' (lineSep opt)
+
+-- |
+--
+-- >>> toLisp defaultOptions ["foo", "bar", "ba\"z"] ""
+-- "(\"foo\" \"bar\" \"ba\\\"z\")"
+-- >>> toPlain defaultOptions ["foo", "bar", "baz"] ""
+-- "foo\nbar\nbaz"
 instance ToString [String] where
-    toLisp  = addNewLine . toSexp True
-    toPlain = unlines
+    toLisp  opt = toSexp1 opt
+    toPlain opt = inter '\n' . map (toPlain opt)
 
+-- |
+--
+-- >>> let inp = [((1,2,3,4),"foo"),((5,6,7,8),"bar")] :: [((Int,Int,Int,Int),String)]
+-- >>> toLisp defaultOptions inp ""
+-- "((1 2 3 4 \"foo\") (5 6 7 8 \"bar\"))"
+-- >>> toPlain defaultOptions inp ""
+-- "1 2 3 4 \"foo\"\n5 6 7 8 \"bar\""
 instance ToString [((Int,Int,Int,Int),String)] where
-    toLisp  = addNewLine . toSexp False . map toS
+    toLisp  opt = toSexp2 . map toS
       where
-        toS x = "(" ++ tupToString x ++ ")"
-    toPlain = unlines . map tupToString
+        toS x = ('(' :) . tupToString opt x . (')' :)
+    toPlain opt = inter '\n' . map (tupToString opt)
 
-toSexp :: Bool -> [String] -> String
-toSexp False ss = "(" ++ unwords ss ++ ")"
-toSexp True ss  = "(" ++ unwords (map quote ss) ++ ")"
+toSexp1 :: Options -> [String] -> Builder
+toSexp1 opt ss = ('(' :) . inter ' ' (map (quote opt) ss) . (')' :)
 
-tupToString :: ((Int,Int,Int,Int),String) -> String
-tupToString ((a,b,c,d),s) = show a ++ " "
-                         ++ show b ++ " "
-                         ++ show c ++ " "
-                         ++ show d ++ " "
-                         ++ quote s
+toSexp2 :: [Builder] -> Builder
+toSexp2 ss = ('(' :) . (inter ' ' ss) . (')' :)
 
-quote :: String -> String
-quote x = "\"" ++ x ++ "\""
+tupToString :: Options -> ((Int,Int,Int,Int),String) -> Builder
+tupToString opt ((a,b,c,d),s) = (show a ++) . (' ' :)
+                              . (show b ++) . (' ' :)
+                              . (show c ++) . (' ' :)
+                              . (show d ++) . (' ' :)
+                              . quote opt s -- fixme: quote is not necessary
 
-addNewLine :: String -> String
-addNewLine = (++ "\n")
+quote :: Options -> String -> Builder
+quote opt str = ("\"" ++) .  (quote' str ++) . ("\"" ++)
+  where
+    lsep = lineSep opt
+    quote' [] = []
+    quote' (x:xs)
+      | x == '\n' = lsep   ++ quote' xs
+      | x == '\\' = "\\\\" ++ quote' xs
+      | x == '"'  = "\\\"" ++ quote' xs
+      | otherwise = x       : quote' xs
 
 ----------------------------------------------------------------
 
@@ -88,14 +135,15 @@
   , cradleRootDir    :: FilePath
   -- | The file name of the found cabal file.
   , cradleCabalFile  :: Maybe FilePath
-  -- | User package db. (\"\/foo\/bar\/i386-osx-ghc-7.6.3-packages.conf.d\")
-  , cradlePackageDb  :: Maybe FilePath
-  -- | Dependent packages.
-  , cradlePackages   :: [Package]
+  -- | Package database stack
+  , cradlePkgDbStack  :: [GhcPkgDb]
   } deriving (Eq, Show)
 
 ----------------------------------------------------------------
 
+-- | GHC package database flags.
+data GhcPkgDb = GlobalDb | UserDb | PackageDb String deriving (Eq, Show)
+
 -- | A single GHC command line option.
 type GHCOption  = String
 
@@ -105,8 +153,29 @@
 -- | A package name.
 type PackageBaseName = String
 
--- | A package name and its ID.
-type Package    = (PackageBaseName, Maybe String)
+-- | A package version.
+type PackageVersion  = String
+
+-- | A package id.
+type PackageId  = String
+
+-- | A package's name, verson and id.
+type Package    = (PackageBaseName, PackageVersion, PackageId)
+
+pkgName :: Package -> PackageBaseName
+pkgName (n,_,_) = n
+
+pkgVer :: Package -> PackageVersion
+pkgVer (_,v,_) = v
+
+pkgId :: Package -> PackageId
+pkgId (_,_,i) = i
+
+showPkg :: Package -> String
+showPkg (n,v,_) = intercalate "-" [n,v]
+
+showPkgId :: Package -> String
+showPkgId (n,v,i) = intercalate "-" [n,v,i]
 
 -- | Haskell expression.
 type Expression = String
diff --git a/Language/Haskell/GhcMod/Utils.hs b/Language/Haskell/GhcMod/Utils.hs
new file mode 100644
--- /dev/null
+++ b/Language/Haskell/GhcMod/Utils.hs
@@ -0,0 +1,5 @@
+module Language.Haskell.GhcMod.Utils where
+
+-- dropWhileEnd is not provided prior to base 4.5.0.0.
+dropWhileEnd :: (a -> Bool) -> [a] -> [a]
+dropWhileEnd p = foldr (\x xs -> if p x && null xs then [] else x : xs) []
diff --git a/elisp/ghc-check.el b/elisp/ghc-check.el
--- a/elisp/ghc-check.el
+++ b/elisp/ghc-check.el
@@ -46,21 +46,22 @@
 
 (defun ghc-check-syntax ()
   (interactive)
-  (ghc-with-process 'ghc-check-send 'ghc-check-callback))
+  (ghc-with-process (ghc-check-send)
+		    'ghc-check-callback
+		    (lambda () (setq mode-line-process " -:-"))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (ghc-defstruct hilit-info file line msg err)
 
 (defun ghc-check-send ()
-  (with-current-buffer ghc-process-original-buffer
-    (setq mode-line-process " -:-"))
-  (if ghc-check-command
-      (let ((opts (ghc-haskell-list-of-string ghc-hlint-options)))
-	(if opts
-	    (concat "lint " opts " " ghc-process-original-file "\n")
-	  (concat "lint " ghc-process-original-file "\n")))
-    (concat "check " ghc-process-original-file "\n")))
+  (let ((file (buffer-file-name)))
+    (if ghc-check-command
+	(let ((opts (ghc-haskell-list-of-string ghc-hlint-options)))
+	  (if opts
+	      (format "lint %s %s\n" opts file)
+	    (format "lint %s\n" file)))
+      (format "check %s\n" file))))
 
 (defun ghc-haskell-list-of-string (los)
   (when los
@@ -68,40 +69,50 @@
 	    (mapconcat (lambda (x) (concat "\"" x "\"")) los ", ")
 	    "]")))
 
-(defun ghc-check-callback ()
-  (let ((regex "^\\([^\n\0]*\\):\\([0-9]+\\):\\([0-9]+\\): *\\(.+\\)")
-	info infos)
-    (while (re-search-forward regex nil t)
-      (let* ((file (expand-file-name (match-string 1))) ;; for Windows
-	     (line (string-to-number (match-string 2)))
-	     ;; don't take column to make multiple same errors to a single.
-	     (msg  (match-string 4))
-	     (err  (not (string-match "^Warning" msg)))
-	     (info (ghc-make-hilit-info
-		    :file file
-		    :line line
-		    :msg  msg
-		    :err  err)))
-	(unless (member info infos)
-	  (setq infos (cons info infos)))))
-    (setq infos (nreverse infos))
-    (cond
-     (infos
-      (let ((file ghc-process-original-file)
-	    (buf ghc-process-original-buffer))
-	(ghc-check-highlight-original-buffer file buf infos)))
-     (t
+(defun ghc-check-callback (status)
+  (cond
+   ((eq status 'ok)
+    (let* ((errs (ghc-read-lisp-this-buffer))
+	   (infos (ghc-to-info errs)))
+      (cond
+       (infos
+	(let ((file ghc-process-original-file)
+	      (buf ghc-process-original-buffer))
+	  (ghc-check-highlight-original-buffer file buf infos)))
+       (t
+	(with-current-buffer ghc-process-original-buffer
+	  (remove-overlays (point-min) (point-max) 'ghc-check t))))
       (with-current-buffer ghc-process-original-buffer
-	(remove-overlays (point-min) (point-max) 'ghc-check t))))
+	(let ((len (length infos)))
+	  (if (= len 0)
+	      (setq mode-line-process "")
+	    (let* ((errs (ghc-filter 'ghc-hilit-info-get-err infos))
+		   (elen (length errs))
+		   (wlen (- len elen)))
+	      (setq mode-line-process (format " %d:%d" elen wlen))))))))
+   (t
     (with-current-buffer ghc-process-original-buffer
-      (let ((len (length infos)))
-	(if (= len 0)
-	    (setq mode-line-process "")
-	  (let* ((errs (ghc-filter 'ghc-hilit-info-get-err infos))
-		 (elen (length errs))
-		 (wlen (- len elen)))
-	    (setq mode-line-process (format " %d:%d" elen wlen))))))))
+      (setq mode-line-process " failed")))))
 
+(defun ghc-to-info (errs)
+  ;; [^\t] to include \n.
+  (let ((regex "^\\([^\n]*\\):\\([0-9]+\\):\\([0-9]+\\): *\\([^\t]+\\)")
+	info infos)
+    (dolist (err errs (nreverse infos))
+      (when (string-match regex err)
+	(let* ((file (expand-file-name (match-string 1 err))) ;; for Windows
+	       (line (string-to-number (match-string 2 err)))
+	       ;; don't take column to make multiple same errors to a single.
+	       (msg (match-string 4 err))
+	       (wrn (string-match "^Warning" msg))
+	       (info (ghc-make-hilit-info
+		      :file file
+		      :line line
+		      :msg  msg
+		      :err  (not wrn))))
+	  (unless (member info infos)
+	    (ghc-add infos info)))))))
+
 (defun ghc-check-highlight-original-buffer (ofile buf infos)
   (with-current-buffer buf
     (remove-overlays (point-min) (point-max) 'ghc-check t)
@@ -131,8 +142,7 @@
 	  (overlay-put ovl 'ghc-check t)
 	  (overlay-put ovl 'ghc-file file)
 	  (overlay-put ovl 'ghc-msg msg)
-	  (let ((echo (ghc-replace-character msg ?\0 ?\n)))
-	    (overlay-put ovl 'help-echo echo))
+	  (overlay-put ovl 'help-echo msg)
 	  (let ((fringe (if err ghc-check-error-fringe ghc-check-warning-fringe))
 		(face (if err 'ghc-face-error 'ghc-face-warn)))
 	    (overlay-put ovl 'before-string fringe)
@@ -140,37 +150,50 @@
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
+(defun ghc-overlay-p (ovl)
+  (overlay-get ovl 'ghc-check))
+
+(defun ghc-check-overlay-at (p)
+  (ghc-filter 'ghc-overlay-p (overlays-at p)))
+
+(ghc-defstruct file-msgs file msgs)
+
+(defun ghc-get-errors-over-warnings ()
+  (let ((ovls (ghc-check-overlay-at (point))))
+    (when ovls
+      (let ((msgs (mapcar (lambda (ovl) (overlay-get ovl 'ghc-msg)) ovls))
+	    (file (overlay-get (car ovls) 'ghc-file))
+	    errs wrns)
+	(dolist (msg msgs)
+	  (if (string-match "^Warning" msg)
+	      (ghc-add wrns msg)
+	    (ghc-add errs msg)))
+	(ghc-make-file-msgs :file file :msgs (nconc errs wrns))))))
+
 (defun ghc-display-errors ()
   (interactive)
-  (let* ((ovls (ghc-check-overlay-at (point)))
-	 (errs (mapcar (lambda (ovl) (overlay-get ovl 'ghc-msg)) ovls)))
-    (if (null ovls)
+  (let ((file-msgs (ghc-get-errors-over-warnings)))
+    (if (null file-msgs)
 	(message "No errors or warnings")
-      (ghc-display
-       nil
-       (lambda ()
-	 (insert (overlay-get (car ovls) 'ghc-file) "\n\n")
-	 (mapc (lambda (x) (insert x "\n\n")) errs))))))
+      (let ((file (ghc-file-msgs-get-file file-msgs))
+	    (msgs (ghc-file-msgs-get-msgs file-msgs)))
+	(ghc-display
+	 nil
+	 (lambda ()
+	   (insert file "\n\n")
+	   (mapc (lambda (x) (insert x "\n\n")) msgs)))))))
 
 (defun ghc-display-errors-to-minibuf ()
-  (interactive)
-  (let* ((ovls (ghc-check-overlay-at (point)))
-	 (errs (mapcar (lambda (ovl) (overlay-get ovl 'ghc-msg)) ovls))
-         (old-max-mini-window-height max-mini-window-height))
-    (setq max-mini-window-height 0.95)
-    (if (null ovls)
+  (let ((file-msgs (ghc-get-errors-over-warnings)))
+    (if (null file-msgs)
 	(message "No errors or warnings")
-      (let* ((buffile buffer-file-name)
-             (ghcfile (overlay-get (car ovls) 'ghc-file))
-             (errmsg (mapconcat (lambda (x) (replace-regexp-in-string "\0" "\n" x)) errs "\n")))
-        (if (string-equal buffile ghcfile)
+      (let* ((file (ghc-file-msgs-get-file file-msgs))
+	     (msgs (ghc-file-msgs-get-msgs file-msgs))
+	     (errmsg (mapconcat 'identity msgs "\n"))
+	     (buffile buffer-file-name))
+        (if (string-equal buffile file)
             (message "%s" errmsg)
-          (message "%s\n\n%s" ghcfile errmsg))))
-    (setq old-max-mini-window-height)))
-
-(defun ghc-check-overlay-at (p)
-  (let ((ovls (overlays-at p)))
-    (ghc-filter (lambda (ovl) (overlay-get ovl 'ghc-check)) ovls)))
+          (message "%s\n\n%s" file errmsg))))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -218,11 +241,20 @@
 	    (if (not (bolp)) (insert "\n")))
 	  (insert (match-string 1) " = undefined\n")))
        ;; GHC 7.8 uses Unicode for single-quotes.
-       ((string-match "Not in scope: type constructor or class `\\([^'\n\0]+\\)'" data)
+       ((string-match "Not in scope: type constructor or class .\\([^\n]+\\)." data)
 	(let ((sym (match-string 1 data)))
 	  (ghc-ins-mod sym)))
-       ((string-match "Not in scope: `\\([^'\n\0]+\\)'" data)
+       ((string-match "Not in scope: data constructor .\\([^\n]+\\)." data)
+	;; if the type of data constructor, it would be nice.
 	(let ((sym (match-string 1 data)))
+	  (ghc-ins-mod sym)))
+       ((string-match "\n[ ]+.\\([^ ]+\\). is a data constructor of .\\([^\n]+\\).\n" data)
+	(let* ((old (match-string 1 data))
+	       (type-const (match-string 2 data))
+	       (new (format "%s(%s)" type-const old)))
+	  (ghc-check-replace old new)))
+       ((string-match "Not in scope: .\\([^\n]+\\)." data)
+	(let ((sym (match-string 1 data)))
 	  (if (or (string-match "\\." sym) ;; qualified
 		  (y-or-n-p (format "Import module for %s?" sym)))
 	      (ghc-ins-mod sym)
@@ -234,27 +266,30 @@
 	(let* ((fn (ghc-get-function-name))
 	       (arity (ghc-get-function-arity fn)))
 	  (ghc-insert-underscore fn arity)))
-       ((string-match "Found:\0[ ]*\\([^\0]+\\)\0Why not:\0[ ]*\\([^\0]+\\)" data)
+       ((string-match "Found:\n[ ]+\\([^\t]+\\)\nWhy not:\n[ ]+\\([^\t]+\\)" data)
 	(let ((old (match-string 1 data))
 	      (new (match-string 2 data)))
-	  (beginning-of-line)
-	  (when (search-forward old nil t)
-	    (let ((end (point)))
-	      (search-backward old nil t)
-	      (delete-region (point) end))
-	    (insert new))))
+	  (ghc-check-replace old new)))
        (t
 	(message "Nothing was done"))))))
 
+(defun ghc-check-replace (old new)
+  (beginning-of-line)
+  (when (search-forward old nil t)
+    (let ((end (point)))
+      (search-backward old nil t)
+      (delete-region (point) end))
+    (insert new)))
+
 (defun ghc-extract-type (str)
   (with-temp-buffer
     (insert str)
     (goto-char (point-min))
-    (when (re-search-forward "Inferred type: \\|no type signature:\\( \\|\0 +\\)?" nil t)
+    (when (re-search-forward "Inferred type: \\|no type signature:\\( \\|\n +\\)?" nil t)
       (delete-region (point-min) (point)))
     (when (re-search-forward " forall [^.]+\\." nil t)
       (replace-match ""))
-    (while (re-search-forward "\0 +" nil t)
+    (while (re-search-forward "\n +" nil t)
       (replace-match " "))
     (goto-char (point-min))
     (while (re-search-forward "\\[Char\\]" nil t)
@@ -292,7 +327,7 @@
 	(insert fn)
 	(dotimes (i arity)
 	  (insert " _"))
-	(insert  " = error \"" fn "\"")))))
+	(insert  " = error \"" fn "\"\n")))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
diff --git a/elisp/ghc-comp.el b/elisp/ghc-comp.el
--- a/elisp/ghc-comp.el
+++ b/elisp/ghc-comp.el
@@ -16,7 +16,7 @@
 ;;;
 
 (defvar ghc-idle-timer-interval 30
- "*Period of idele timer in second. When timeout, the names of
+ "*Period of idle timer in second. When timeout, the names of
 unloaded modules are loaded")
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -30,7 +30,7 @@
 ;; must be sorted
 (defconst ghc-reserved-keyword '("case" "deriving" "do" "else" "if" "in" "let" "module" "of" "then" "where"))
 
-(defconst ghc-extra-keywords '("ByteString"))
+(defconst ghc-extra-keywords '("ByteString" "Text"))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;
@@ -56,8 +56,8 @@
 (defconst ghc-keyword-prefix "ghc-keyword-")
 (defvar ghc-keyword-Prelude nil)
 (defvar ghc-keyword-Control.Applicative nil)
-(defvar ghc-keyword-Control.Monad nil)
 (defvar ghc-keyword-Control.Exception nil)
+(defvar ghc-keyword-Control.Monad nil)
 (defvar ghc-keyword-Data.Char nil)
 (defvar ghc-keyword-Data.List nil)
 (defvar ghc-keyword-Data.Maybe nil)
@@ -66,15 +66,14 @@
 (defvar ghc-loaded-module nil)
 
 (defun ghc-comp-init ()
-  (add-hook 'find-file-hook 'ghc-import-module)
   (let* ((syms '(ghc-module-names
 		 ghc-language-extensions
 		 ghc-option-flags
 		 ;; hard coded in GHCMod.hs
 		 ghc-keyword-Prelude
 		 ghc-keyword-Control.Applicative
-		 ghc-keyword-Control.Monad
 		 ghc-keyword-Control.Exception
+		 ghc-keyword-Control.Monad
 		 ghc-keyword-Data.Char
 		 ghc-keyword-Data.List
 		 ghc-keyword-Data.Maybe
@@ -86,13 +85,12 @@
   ;; hard coded in GHCMod.hs
   (ghc-merge-keywords '("Prelude"
 			"Control.Applicative"
-			"Control.Monad"
 			"Control.Exception"
+			"Control.Monad"
 			"Data.Char"
 			"Data.List"
 			"Data.Maybe"
-			"System.IO"))
-  (run-with-idle-timer ghc-idle-timer-interval 'repeat 'ghc-idle-timer))
+			"System.IO")))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;
@@ -100,28 +98,23 @@
 ;;;
 
 (defun ghc-boot (n)
-  (ghc-executable-find ghc-module-command
-    (ghc-read-lisp-list
-     (lambda ()
-       (message "Initializing...")
-       (ghc-call-process ghc-module-command nil t nil "-l" "boot")
-       (message "Initializing...done"))
-     n)))
+  (prog2
+      (message "Initializing...")
+      (ghc-sync-process "boot\n" n)
+    (message "Initializing...done")))
 
 (defun ghc-load-modules (mods)
-  (if (null mods)
-      (progn
-	(message "No new modules")
-	nil)
-    (ghc-executable-find ghc-module-command
-      (ghc-read-lisp-list
-       (lambda ()
-	 (message "Loading names...")
-	 (apply 'ghc-call-process ghc-module-command nil '(t nil) nil
-		`(,@(ghc-make-ghc-options) "-l" "browse" ,@mods))
-	 (message "Loading names...done"))
-       (length mods)))))
+  (if mods
+      (mapcar 'ghc-load-module mods)
+    (message "No new modules")
+    nil))
 
+(defun ghc-load-module (mod)
+  (prog2
+      (message "Loading symbols for %s..." mod)
+      (ghc-sync-process (format "browse %s\n" mod))
+    (message "Loading symbols for %s...done" mod)))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;
 ;;; Completion
@@ -236,8 +229,7 @@
 
 (defun ghc-import-module ()
   (interactive)
-  (when (eq major-mode 'haskell-mode)
-    (ghc-load-module-buffer)))
+  (ghc-load-module-buffer))
 
 (defun ghc-unloaded-modules (mods)
   (ghc-filter (lambda (mod)
@@ -245,9 +237,6 @@
 		     (not (member mod ghc-loaded-module))))
 	      mods))
 
-(defun ghc-load-module-all-buffers ()
-  (ghc-load-merge-modules (ghc-gather-import-modules-all-buffers)))
-
 (defun ghc-load-module-buffer ()
   (ghc-load-merge-modules (ghc-gather-import-modules-buffer)))
 
@@ -271,26 +260,6 @@
 (defun ghc-module-keyword (mod)
   (symbol-value (ghc-module-symbol mod)))
 
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
-(ghc-defstruct buffer name file)
-
-(defun ghc-buffer-name-file (buf)
-  (ghc-make-buffer
-   :name (buffer-name buf)
-   :file (buffer-file-name buf)))
-
-(defun ghc-gather-import-modules-all-buffers ()
-  (let ((bufs (mapcar 'ghc-buffer-name-file (buffer-list)))
-	ret file)
-    (save-excursion
-      (dolist (buf bufs (ghc-uniq-lol ret))
-	(setq file (ghc-buffer-get-file buf))
-	(when (and file (string-match "\\.hs$" file))
-	  (set-buffer (ghc-buffer-get-name buf))
-	  (ghc-add ret (ghc-gather-import-modules-buffer)))))))
-
 (defun ghc-gather-import-modules-buffer ()
   (let (ret)
     (save-excursion
@@ -304,9 +273,5 @@
 ;;;
 ;;; Background Idle Timer
 ;;;
-
-(defalias 'ghc-idle-timer 'ghc-load-module-all-buffer)
-
-(defun ghc-load-module-all-buffer () nil)
 
 (provide 'ghc-comp)
diff --git a/elisp/ghc-doc.el b/elisp/ghc-doc.el
--- a/elisp/ghc-doc.el
+++ b/elisp/ghc-doc.el
@@ -70,7 +70,7 @@
 	(i 0)
 	acc)
     (while (< i len)
-      (setq acc (cons (format "-%d-" (aref symbol i)) acc))
+      (ghc-add acc (format "-%d-" (aref symbol i)))
       (setq i (1+ i)))
     (apply 'concat (nreverse acc))))
 
diff --git a/elisp/ghc-func.el b/elisp/ghc-func.el
--- a/elisp/ghc-func.el
+++ b/elisp/ghc-func.el
@@ -63,14 +63,18 @@
 (defun ghc-read-lisp (func)
   (with-temp-buffer
     (funcall func)
+    (ghc-read-lisp-this-buffer)))
+
+;; OK/NG are ignored.
+(defun ghc-read-lisp-this-buffer ()
+  (save-excursion
     (goto-char (point-min))
     (condition-case nil
 	(read (current-buffer))
       (error ()))))
 
-(defun ghc-read-lisp-list (func n)
-  (with-temp-buffer
-    (funcall func)
+(defun ghc-read-lisp-list-this-buffer (n)
+  (save-excursion
     (goto-char (point-min))
     (condition-case nil
 	(let ((m (set-marker (make-marker) 1 (current-buffer)))
@@ -86,11 +90,6 @@
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defconst ghc-null 0)
-(defconst ghc-newline 10)
-
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-
 (defun ghc-things-at-point ()
   (thing-at-point 'sexp))
 
@@ -152,7 +151,6 @@
       (with-current-buffer buf
         (erase-buffer)
         (funcall ins-func)
-        (ghc-replace-character-buffer ghc-null ghc-newline)
         (goto-char (point-min))
         (if (not fontify)
             (turn-off-haskell-font-lock)
@@ -162,14 +160,15 @@
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
-(defun ghc-run-ghc-mod (cmds)
-  (ghc-executable-find ghc-module-command
-    (let ((cdir default-directory))
-      (with-temp-buffer
-	(cd cdir)
-	(apply 'ghc-call-process ghc-module-command nil t nil
-	       (append (ghc-make-ghc-options) cmds))
-	(buffer-substring (point-min) (1- (point-max)))))))
+(defun ghc-run-ghc-mod (cmds &optional prog)
+  (let ((target (or prog ghc-module-command)))
+    (ghc-executable-find target
+      (let ((cdir default-directory))
+	(with-temp-buffer
+	  (cd cdir)
+	  (apply 'ghc-call-process target nil t nil
+		 (append (ghc-make-ghc-options) cmds))
+	  (buffer-substring (point-min) (1- (point-max))))))))
 
 (defmacro ghc-executable-find (cmd &rest body)
   ;; (declare (indent 1))
diff --git a/elisp/ghc-info.el b/elisp/ghc-info.el
--- a/elisp/ghc-info.el
+++ b/elisp/ghc-info.el
@@ -9,6 +9,7 @@
 ;;; Code:
 
 (require 'ghc-func)
+(require 'ghc-process)
 
 (defun ghc-show-info (&optional ask)
   (interactive "P")
@@ -21,10 +22,9 @@
        (lambda () (insert info))))))
 
 (defun ghc-get-info (expr)
-  (let* ((modname (or (ghc-find-module-name) "Main"))
-	 (file (buffer-file-name))
-	 (cmds (list "info" file modname expr)))
-    (ghc-run-ghc-mod cmds)))
+  (let* ((file (buffer-file-name))
+	 (cmd (format "info %s %s\n" file expr)))
+    (ghc-sync-process cmd)))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;
@@ -77,13 +77,8 @@
 
 (defun ghc-show-type ()
   (interactive)
-  (ghc-executable-find ghc-module-command
-    (let ((modname (or (ghc-find-module-name) "Main")))
-      (ghc-show-type0 modname))))
-
-(defun ghc-show-type0 (modname)
-  (let* ((buf (current-buffer))
-	 (tinfos (ghc-type-get-tinfos modname)))
+  (let ((buf (current-buffer))
+	(tinfos (ghc-type-get-tinfos)))
     (if (null tinfos)
 	(progn
 	  (ghc-type-clear-overlay)
@@ -99,11 +94,11 @@
 	(move-overlay ghc-type-overlay (- left 1) (- right 1) buf)
 	(message type)))))
 
-(defun ghc-type-get-tinfos (modname)
+(defun ghc-type-get-tinfos ()
   (if (= (ghc-type-get-point) (point))
       (ghc-type-set-ix
        (mod (1+ (ghc-type-get-ix)) (length (ghc-type-get-types))))
-    (let ((types (ghc-type-obtain-tinfos modname)))
+    (let ((types (ghc-type-obtain-tinfos)))
       (if (not (listp types)) ;; main does not exist in Main
 	  (ghc-type-set-types nil)
 	(ghc-type-set-types types)
@@ -111,20 +106,19 @@
 	(ghc-type-set-ix 0))))
   (ghc-type-get-types))
 
-(defun ghc-type-obtain-tinfos (modname)
+(defun ghc-type-obtain-tinfos ()
   (let* ((ln (int-to-string (line-number-at-pos)))
 	 (cn (int-to-string (1+ (current-column))))
-	 (cdir default-directory)
-	 (file (buffer-file-name)))
-    (ghc-read-lisp
-     (lambda ()
-       (cd cdir)
-       (apply 'ghc-call-process ghc-module-command nil t nil
-	      `(,@(ghc-make-ghc-options) "-l" "type" ,file ,modname ,ln ,cn))
-       (goto-char (point-min))
-       (while (search-forward "[Char]" nil t)
-	 (replace-match "String"))))))
+	 (file (buffer-file-name))
+	 (cmd (format "type %s %s %s\n" file ln cn)))
+    (ghc-sync-process cmd nil 'ghc-type-fix-string)))
 
+(defun ghc-type-fix-string ()
+  (save-excursion
+    (goto-char (point-min))
+    (while (search-forward "[Char]" nil t)
+      (replace-match "String"))))
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;;;
 ;;; Expanding Template Haskell
@@ -133,7 +127,7 @@
 (defun ghc-expand-th ()
   (interactive)
   (let* ((file (buffer-file-name))
-	 (cmds (list "expand" file))
+	 (cmds (list "expand" file "-b" "\n"))
 	 (source (ghc-run-ghc-mod cmds)))
     (when source
       (ghc-display
diff --git a/elisp/ghc-ins-mod.el b/elisp/ghc-ins-mod.el
--- a/elisp/ghc-ins-mod.el
+++ b/elisp/ghc-ins-mod.el
@@ -10,9 +10,6 @@
 
 ;;; Code:
 
-(defvar ghc-ins-mod-rendezvous nil)
-(defvar ghc-ins-mod-results nil)
-
 (defun ghc-insert-module ()
   (interactive)
   (let* ((expr0 (ghc-things-at-point))
@@ -76,26 +73,7 @@
     (forward-line)))
 
 (defun ghc-function-to-modules (fun)
-  (setq ghc-ins-mod-rendezvous nil)
-  (setq ghc-ins-mod-results nil)
-  (ghc-with-process
-   (lambda () (ghc-ins-mod-send fun))
-   'ghc-ins-mod-callback)
-  (while (null ghc-ins-mod-rendezvous)
-    (sit-for 0.01))
-  ghc-ins-mod-results)
-
-(defun ghc-ins-mod-send (fun)
-  (concat "find " fun "\n"))
-
-(defun ghc-ins-mod-callback ()
-  (let (lines line beg)
-    (while (not (eobp))
-      (setq beg (point))
-      (forward-line)
-      (setq line (buffer-substring-no-properties beg (1- (point))))
-      (setq lines (cons line lines)))
-    (setq ghc-ins-mod-rendezvous t)
-    (setq ghc-ins-mod-results (nreverse (cdr lines))))) ;; removing "OK"
+  (let ((cmd (format "find %s\n" fun)))
+    (ghc-sync-process cmd)))
 
 (provide 'ghc-ins-mod)
diff --git a/elisp/ghc-process.el b/elisp/ghc-process.el
--- a/elisp/ghc-process.el
+++ b/elisp/ghc-process.el
@@ -17,24 +17,20 @@
 (defvar-local ghc-process-original-buffer nil)
 (defvar-local ghc-process-original-file nil)
 (defvar-local ghc-process-callback nil)
+(defvar-local ghc-process-hook nil)
 
 (defvar ghc-interactive-command "ghc-modi")
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
 (defun ghc-get-project-root ()
-  (let ((file (buffer-file-name)))
-    (when file
-      (with-temp-buffer
-	(ghc-call-process ghc-module-command nil t nil "root" file)
-	(goto-char (point-min))
-	(when (looking-at "^\\(.*\\)$")
-	  (match-string-no-properties 1))))))
+  (ghc-run-ghc-mod '("root")))
 
-(defun ghc-with-process (send callback)
+(defun ghc-with-process (cmd callback &optional hook1 hook2)
   (unless ghc-process-process-name
     (setq ghc-process-process-name (ghc-get-project-root)))
   (when ghc-process-process-name
+    (if hook1 (funcall hook1))
     (let* ((cbuf (current-buffer))
 	   (name ghc-process-process-name)
 	   (buf (get-buffer-create (concat " ghc-modi:" name)))
@@ -46,13 +42,14 @@
 	  (setq ghc-process-original-buffer cbuf)
 	  (setq ghc-process-original-file file)
 	  (setq ghc-process-callback callback)
+	  (setq ghc-process-hook hook2)
 	  (erase-buffer)
-	  (let ((pro (ghc-get-process cpro name buf))
-		(cmd (funcall send)))
+	  (let ((pro (ghc-get-process cpro name buf)))
 	    (process-send-string pro cmd)
 	    (when ghc-debug
 	      (ghc-with-debug-buffer
-	       (insert (format "%% %s" cmd))))))))))
+	       (insert (format "%% %s" cmd))))
+	    pro))))))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -66,7 +63,7 @@
    (t cpro)))
 
 (defun ghc-start-process (name buf)
-  (let ((pro (start-file-process name buf ghc-interactive-command)))
+  (let ((pro (start-file-process name buf ghc-interactive-command "-b" "\n" "-l")))
     (set-process-filter pro 'ghc-process-filter)
     (set-process-query-on-exit-flag pro nil)
     pro))
@@ -76,14 +73,59 @@
     (goto-char (point-max))
     (insert string)
     (forward-line -1)
-    (when (looking-at "^\\(OK\\|NG\\)$")
+    (cond
+     ((looking-at "^OK$")
+      (if ghc-process-hook (funcall ghc-process-hook))
       (goto-char (point-min))
-      (funcall ghc-process-callback)
+      (funcall ghc-process-callback 'ok)
       (when ghc-debug
 	(let ((cbuf (current-buffer)))
 	  (ghc-with-debug-buffer
 	   (insert-buffer-substring cbuf))))
-      (setq ghc-process-running nil))))
+      (setq ghc-process-running nil))
+     ((looking-at "^NG ")
+      (funcall ghc-process-callback 'ng)
+      (when ghc-debug
+	(let ((cbuf (current-buffer)))
+	  (ghc-with-debug-buffer
+	   (insert-buffer-substring cbuf))))
+      (setq ghc-process-running nil)))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+(defvar ghc-process-rendezvous nil)
+(defvar ghc-process-num-of-results nil)
+(defvar ghc-process-results nil)
+
+(defun ghc-sync-process (cmd &optional n hook)
+  (setq ghc-process-rendezvous nil)
+  (setq ghc-process-results nil)
+  (setq ghc-process-num-of-results (or n 1))
+  (let ((pro (ghc-with-process cmd 'ghc-process-callback nil hook)))
+    (condition-case nil
+	(while (null ghc-process-rendezvous)
+	  ;; 0.1 is too fast for Emacs 24.4.
+	  ;; (sit-for 0.1 t) may get stuck when tooltip is displayed.
+	  (sit-for 0.1)
+	  ;; (discard-input) avoids getting stuck.
+	  (discard-input))
+      (quit
+       (with-current-buffer (process-buffer pro)
+	 (setq ghc-process-running nil)))))
+  ghc-process-results)
+
+(defun ghc-process-callback (status)
+  (cond
+   ((eq status 'ok)
+    (let* ((n ghc-process-num-of-results)
+	   (ret (if (= n 1)
+		    (ghc-read-lisp-this-buffer)
+		  (ghc-read-lisp-list-this-buffer n))))
+      (setq ghc-process-results ret)))
+   (t
+    (setq ghc-process-results nil)))
+  (setq ghc-process-num-of-results nil)
+  (setq ghc-process-rendezvous t))
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
diff --git a/elisp/ghc.el b/elisp/ghc.el
--- a/elisp/ghc.el
+++ b/elisp/ghc.el
@@ -7,6 +7,7 @@
 ;; Put the following code to your "~/.emacs".
 ;;
 ;; (autoload 'ghc-init "ghc" nil t)
+;; (autoload 'ghc-debug "ghc" nil t)
 ;; (add-hook 'haskell-mode-hook (lambda () (ghc-init)))
 ;;
 ;; Or if you wish to display error each goto next/prev error,
@@ -19,7 +20,7 @@
 
 ;;; Code:
 
-(defconst ghc-version "4.0.2")
+(defconst ghc-version "4.1.0")
 
 ;; (eval-when-compile
 ;;  (require 'haskell-mode))
@@ -97,9 +98,34 @@
     (define-key haskell-mode-map ghc-deeper-key      'ghc-make-indent-deeper)
     (ghc-comp-init)
     (setq ghc-initialized t))
+  (ghc-import-module)
   (ghc-check-syntax))
 
 (defun ghc-abbrev-init ()
   (set (make-local-variable 'dabbrev-case-fold-search) nil))
+
+;;;###autoload
+(defun ghc-debug ()
+  (interactive)
+  (let ((el-path (locate-file "ghc.el" load-path))
+	(ghc-path (executable-find "ghc"))
+	(ghc-mod-path (executable-find ghc-module-command))
+	(ghc-modi-path (executable-find ghc-interactive-command))
+	(el-ver ghc-version)
+	(ghc-ver (ghc-run-ghc-mod '("--version") "ghc"))
+	(ghc-mod-ver (ghc-run-ghc-mod '("version")))
+	(ghc-modi-ver (ghc-run-ghc-mod '("version") ghc-interactive-command)))
+    (switch-to-buffer (get-buffer-create "**GHC Debug**"))
+    (erase-buffer)
+    (insert "Path: check if you are using intended programs.\n")
+    (insert (format "\t  ghc.el path: %s\n" el-path))
+    (insert (format "\t ghc-mod path: %s\n" ghc-mod-path))
+    (insert (format "\tghc-modi path: %s\n" ghc-modi-path))
+    (insert (format "\t     ghc path: %s\n" ghc-path))
+    (insert "\nVersion: all versions must be the same.\n")
+    (insert (format "\t  ghc.el version %s\n" el-ver))
+    (insert (format "\t %s\n" ghc-mod-ver))
+    (insert (format "\t%s\n" ghc-modi-ver))
+    (insert (format "\t%s\n" ghc-ver))))
 
 (provide 'ghc)
diff --git a/ghc-mod.cabal b/ghc-mod.cabal
--- a/ghc-mod.cabal
+++ b/ghc-mod.cabal
@@ -1,5 +1,5 @@
 Name:                   ghc-mod
-Version:                4.0.2
+Version:                4.1.0
 Author:                 Kazu Yamamoto <kazu@iij.ad.jp>
 Maintainer:             Kazu Yamamoto <kazu@iij.ad.jp>
 License:                BSD3
@@ -26,8 +26,8 @@
 Extra-Source-Files:     ChangeLog
 			test/data/*.cabal
                         test/data/*.hs
-                        test/data/cabal.sandbox.config
-                        test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/dummy
+                        test/data/cabal.sandbox.config.in
+                        test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/Cabal-1.18.1.3-2b161c6bf77657aa17e1681d83cb051b.conf
                         test/data/broken-cabal/*.cabal
                         test/data/broken-sandbox/*.cabal
                         test/data/broken-sandbox/cabal.sandbox.config
@@ -35,6 +35,8 @@
                         test/data/check-test-subdir/src/Check/Test/*.hs
                         test/data/check-test-subdir/test/*.hs
                         test/data/check-test-subdir/test/Bar/*.hs
+                        test/data/check-packageid/cabal.sandbox.config.in
+                        test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c.conf
                         test/data/ghc-mod-check/*.cabal
                         test/data/ghc-mod-check/*.hs
                         test/data/ghc-mod-check/Data/*.hs
@@ -44,31 +46,37 @@
   Default-Language:     Haskell2010
   GHC-Options:          -Wall
   Exposed-Modules:      Language.Haskell.GhcMod
+                        Language.Haskell.GhcMod.Ghc
                         Language.Haskell.GhcMod.Internal
-  Other-Modules:        Language.Haskell.GhcMod.Browse
+  Other-Modules:        Language.Haskell.GhcMod.Boot
+                        Language.Haskell.GhcMod.Browse
                         Language.Haskell.GhcMod.CabalApi
                         Language.Haskell.GhcMod.Check
                         Language.Haskell.GhcMod.Cradle
                         Language.Haskell.GhcMod.Debug
                         Language.Haskell.GhcMod.Doc
-                        Language.Haskell.GhcMod.ErrMsg
+                        Language.Haskell.GhcMod.Find
                         Language.Haskell.GhcMod.Flag
                         Language.Haskell.GhcMod.GHCApi
                         Language.Haskell.GhcMod.GHCChoice
                         Language.Haskell.GhcMod.Gap
+                        Language.Haskell.GhcMod.GhcPkg
+                        Language.Haskell.GhcMod.Logger
                         Language.Haskell.GhcMod.Info
                         Language.Haskell.GhcMod.Lang
                         Language.Haskell.GhcMod.Lint
                         Language.Haskell.GhcMod.List
                         Language.Haskell.GhcMod.PkgDoc
+                        Language.Haskell.GhcMod.Utils
                         Language.Haskell.GhcMod.Types
   Build-Depends:        base >= 4.0 && < 5
                       , containers
+                      , deepseq
                       , directory
                       , filepath
                       , ghc
                       , ghc-syb-utils
-                      , hlint >= 1.8.58
+                      , hlint >= 1.8.61
                       , io-choice
                       , old-time
                       , process
@@ -117,10 +125,11 @@
 
 Test-Suite spec
   Default-Language:     Haskell2010
-  Main-Is:              Spec.hs
+  Main-Is:              Main.hs
   Hs-Source-Dirs:       test, .
   Type:                 exitcode-stdio-1.0
   Other-Modules:        Dir
+                        Spec
                         BrowseSpec
                         CabalApiSpec
                         CheckSpec
@@ -129,8 +138,10 @@
                         LangSpec
                         LintSpec
                         ListSpec
+                        GhcPkgSpec
   Build-Depends:        base >= 4.0 && < 5
                       , containers
+                      , deepseq
                       , directory
                       , filepath
                       , ghc
diff --git a/src/GHCMod.hs b/src/GHCMod.hs
--- a/src/GHCMod.hs
+++ b/src/GHCMod.hs
@@ -2,6 +2,7 @@
 
 module Main where
 
+import Config (cProjectVersion)
 import Control.Applicative ((<$>))
 import Control.Exception (Exception, Handler(..), ErrorCall(..))
 import qualified Control.Exception as E
@@ -18,26 +19,34 @@
 
 ----------------------------------------------------------------
 
+progVersion :: String
+progVersion = "ghc-mod version " ++ showVersion version ++ " compiled by GHC " ++ cProjectVersion ++ "\n"
+
 ghcOptHelp :: String
 ghcOptHelp = " [-g GHC_opt1 -g GHC_opt2 ...] "
 
 usage :: String
-usage =    "ghc-mod version " ++ showVersion version ++ "\n"
+usage =    progVersion
         ++ "Usage:\n"
         ++ "\t ghc-mod list" ++ ghcOptHelp ++ "[-l] [-d]\n"
         ++ "\t ghc-mod lang [-l]\n"
         ++ "\t ghc-mod flag [-l]\n"
-        ++ "\t ghc-mod browse" ++ ghcOptHelp ++ "[-l] [-o] [-d] [-q] [-p package] <module> [<module> ...]\n"
+        ++ "\t ghc-mod browse" ++ ghcOptHelp ++ "[-l] [-o] [-d] [-q] [<package>:]<module> [[<package>:]<module> ...]\n"
         ++ "\t ghc-mod check" ++ ghcOptHelp ++ "<HaskellFiles...>\n"
         ++ "\t ghc-mod expand" ++ ghcOptHelp ++ "<HaskellFiles...>\n"
-        ++ "\t ghc-mod debug" ++ ghcOptHelp ++ "<HaskellFile>\n"
+        ++ "\t ghc-mod debug" ++ ghcOptHelp ++ "\n"
         ++ "\t ghc-mod info" ++ ghcOptHelp ++ "<HaskellFile> <module> <expression>\n"
         ++ "\t ghc-mod type" ++ ghcOptHelp ++ "<HaskellFile> <module> <line-no> <column-no>\n"
+        ++ "\t ghc-mod find <symbol>\n"
         ++ "\t ghc-mod lint [-h opt] <HaskellFile>\n"
-        ++ "\t ghc-mod root <HaskellFile>\n"
+        ++ "\t ghc-mod root\n"
         ++ "\t ghc-mod doc <module>\n"
         ++ "\t ghc-mod boot\n"
+        ++ "\t ghc-mod version\n"
         ++ "\t ghc-mod help\n"
+        ++ "\n"
+        ++ "<module> for \"info\" and \"type\" is not used, anything is OK.\n"
+        ++ "It is necessary to maintain backward compatibility.\n"
 
 ----------------------------------------------------------------
 
@@ -60,9 +69,6 @@
           , Option "q" ["qualified"]
             (NoArg (\opts -> opts { qualified = True }))
             "show qualified names"
-          , Option "p" ["package"]
-            (ReqArg (\p opts -> opts { packageId = Just p, ghcOpts = ("-package " ++ p) : ghcOpts opts }) "package-id")
-            "specify package of module"
           , Option "b" ["boundary"]
             (ReqArg (\s opts -> opts { lineSeparator = LineSeparator s }) "sep")
             "specify line separator (default is Nul string)"
@@ -96,7 +102,6 @@
     cradle <- findCradle
     let cmdArg0 = cmdArg !. 0
         cmdArg1 = cmdArg !. 1
-        cmdArg2 = cmdArg !. 2
         cmdArg3 = cmdArg !. 3
         cmdArg4 = cmdArg !. 4
         remainingArgs = tail cmdArg
@@ -104,26 +109,23 @@
                         then f
                         else E.throw (TooManyArguments cmdArg0)
     res <- case cmdArg0 of
-      "list"   -> listModules opt cradle
-      "lang"   -> listLanguages opt
-      "flag"   -> listFlags opt
-      "browse" -> concat <$> mapM (browseModule opt cradle) remainingArgs
-      "check"  -> checkSyntax opt cradle remainingArgs
-      "expand" -> checkSyntax opt { expandSplice = True } cradle remainingArgs
-      "debug"  -> nArgs 1 $ debugInfo opt cradle cmdArg1
-      "info"   -> nArgs 3 infoExpr opt cradle cmdArg1 cmdArg2 cmdArg3
-      "type"   -> nArgs 4 $ typeExpr opt cradle cmdArg1 cmdArg2 (read cmdArg3) (read cmdArg4)
-      "lint"   -> nArgs 1 withFile (lintSyntax opt) cmdArg1
-      "root"   -> nArgs 1 $ rootInfo opt cradle cmdArg1
-      "doc"    -> nArgs 1 $ packageDoc opt cradle cmdArg1
-      "boot"   -> do
-         mods  <- listModules opt cradle
-         langs <- listLanguages opt
-         flags <- listFlags opt
-         pre   <- concat <$> mapM (browseModule opt cradle) preBrowsedModules
-         return $ mods ++ langs ++ flags ++ pre
-      "help"   -> return $ O.usageInfo usage argspec
-      cmd      -> E.throw (NoSuchCommand cmd)
+      "list"    -> listModules opt cradle
+      "lang"    -> listLanguages opt
+      "flag"    -> listFlags opt
+      "browse"  -> concat <$> mapM (browseModule opt cradle) remainingArgs
+      "check"   -> checkSyntax opt cradle remainingArgs
+      "expand"  -> expandTemplate opt cradle remainingArgs
+      "debug"   -> debugInfo opt cradle
+      "info"    -> nArgs 3 infoExpr opt cradle cmdArg1 cmdArg3
+      "type"    -> nArgs 4 $ typeExpr opt cradle cmdArg1 (read cmdArg3) (read cmdArg4)
+      "find"    -> nArgs 1 $ findSymbol opt cradle cmdArg1
+      "lint"    -> nArgs 1 withFile (lintSyntax opt) cmdArg1
+      "root"    -> rootInfo opt cradle
+      "doc"     -> nArgs 1 $ packageDoc opt cradle cmdArg1
+      "boot"    -> bootInfo opt cradle
+      "version" -> return progVersion
+      "help"    -> return $ O.usageInfo usage argspec
+      cmd       -> E.throw (NoSuchCommand cmd)
     putStr res
   where
     handlers = [Handler (handleThenExit handler1), Handler (handleThenExit handler2)]
@@ -153,17 +155,3 @@
     xs !. idx
       | length xs <= idx = E.throw SafeList
       | otherwise = xs !! idx
-
-----------------------------------------------------------------
-
-preBrowsedModules :: [String]
-preBrowsedModules = [
-    "Prelude"
-  , "Control.Applicative"
-  , "Control.Monad"
-  , "Control.Exception"
-  , "Data.Char"
-  , "Data.List"
-  , "Data.Maybe"
-  , "System.IO"
-  ]
diff --git a/src/GHCModi.hs b/src/GHCModi.hs
--- a/src/GHCModi.hs
+++ b/src/GHCModi.hs
@@ -1,12 +1,16 @@
-{-# LANGUAGE CPP #-}
 {-# LANGUAGE DeriveDataTypeable #-}
 
 -- Commands:
 --  check <file>
 --  find <symbol>
+--  info <file> <expr>
+--  type <file> <line> <column>
 --  lint [hlint options] <file>
 --     the format of hlint options is [String] because they may contain
---     spaces and aslo <file> may contain spaces.
+--     spaces and also <file> may contain spaces.
+--  boot
+--  browse [<package>:]<module>
+--  quit
 --
 -- Session separators:
 --   OK -- success
@@ -14,35 +18,23 @@
 
 module Main where
 
-#ifndef MIN_VERSION_containers
-#define MIN_VERSION_containers(x,y,z) 1
-#endif
-
+import Config (cProjectVersion)
 import Control.Applicative ((<$>))
 import Control.Concurrent (forkIO, MVar, newEmptyMVar, putMVar, readMVar)
-import Control.Exception (SomeException(..))
+import Control.Exception (SomeException(..), Exception)
 import qualified Control.Exception as E
 import Control.Monad (when, void)
 import CoreMonad (liftIO)
-import Data.Function (on)
-import Data.List (intercalate, groupBy, sort, find)
-#if MIN_VERSION_containers(0,5,0)
-import Data.Map.Strict (Map)
-import qualified Data.Map.Strict as M
-#else
-import Data.Map (Map)
-import qualified Data.Map as M
-#endif
+import Data.List (find)
 import Data.Maybe (fromMaybe)
 import Data.Set (Set)
 import qualified Data.Set as S
-import Data.Typeable
+import Data.Typeable (Typeable)
 import Data.Version (showVersion)
-import qualified Exception as GE
-import GHC (Ghc, LoadHowMuch(LoadAllTargets), TargetId(TargetFile))
+import GHC (Ghc)
 import qualified GHC as G
-import HscTypes (SourceError)
 import Language.Haskell.GhcMod
+import Language.Haskell.GhcMod.Ghc
 import Language.Haskell.GhcMod.Internal
 import Paths_ghc_mod
 import System.Console.GetOpt
@@ -52,35 +44,43 @@
 
 ----------------------------------------------------------------
 
-type DB = Map String [String]
-type Logger = IO [String]
+type Logger = IO String
 
 ----------------------------------------------------------------
 
+progVersion :: String
+progVersion = "ghc-modi version " ++ showVersion version ++ " compiled by GHC " ++ cProjectVersion ++ "\n"
+
 argspec :: [OptDescr (Options -> Options)]
 argspec = [ Option "b" ["boundary"]
             (ReqArg (\s opts -> opts { lineSeparator = LineSeparator s }) "sep")
             "specify line separator (default is Nul string)"
+          , Option "l" ["tolisp"]
+            (NoArg (\opts -> opts { outputStyle = LispStyle }))
+            "print as a list of Lisp"
+          , Option "g" []
+            (ReqArg (\s opts -> opts { ghcOpts = s : ghcOpts opts }) "flag") "specify a ghc flag"
           ]
 
 usage :: String
-usage =    "ghc-modi version " ++ showVersion version ++ "\n"
+usage =    progVersion
         ++ "Usage:\n"
-        ++ "\t ghc-modi [-b sep]\n"
+        ++ "\t ghc-modi [-l] [-b sep] [-g flag]\n"
+        ++ "\t ghc-modi version\n"
         ++ "\t ghc-modi help\n"
 
 parseArgs :: [OptDescr (Options -> Options)] -> [String] -> (Options, [String])
 parseArgs spec argv
     = case getOpt Permute spec argv of
         (o,n,[]  ) -> (foldr id defaultOptions o, n)
-        (_,_,errs) -> GE.throw (CmdArg errs)
+        (_,_,errs) -> E.throw (CmdArg errs)
 
 ----------------------------------------------------------------
 
 data GHCModiError = CmdArg [String]
                   deriving (Show, Typeable)
 
-instance GE.Exception GHCModiError
+instance Exception GHCModiError
 
 ----------------------------------------------------------------
 
@@ -88,133 +88,133 @@
 -- C-c since installSignalHandlers is called twice, sigh.
 
 main :: IO ()
-main = handle [GE.Handler cmdHandler, GE.Handler someHandler] $
+main = E.handle cmdHandler $
     go =<< parseArgs argspec <$> getArgs
   where
-    handle = flip GE.catches
-    LineSeparator lsc = lineSeparator defaultOptions
-    cmdHandler (CmdArg e) = do
-        putStr "ghc-modi:0:0:"
-        let x = intercalate lsc e
-        putStrLn x
-        putStr $ usageInfo usage argspec
-        putStrLn "NG"
-    someHandler (SomeException e) = do
-        putStr "ghc-modi:0:0:"
-        let x = intercalate lsc $ lines $ show e
-        putStrLn x
-        putStrLn "NG"
-    go (_,"help":_) = do
-        putStr $ usageInfo usage argspec
-        putStrLn "NG"
-    go (opt,_) = do
+    cmdHandler (CmdArg _) = putStr $ usageInfo usage argspec
+    go (_,"help":_) = putStr $ usageInfo usage argspec
+    go (_,"version":_) = putStr progVersion
+    go (opt,_) = E.handle someHandler $ do
         cradle0 <- findCradle
         let rootdir = cradleRootDir cradle0
             cradle = cradle0 { cradleCurrentDir = rootdir }
-            ls = lineSeparator opt
         setCurrentDirectory rootdir
         mvar <- liftIO newEmptyMVar
         mlibdir <- getSystemLibDir
         void $ forkIO $ setupDB cradle mlibdir opt mvar
-        run cradle mlibdir opt $ loop S.empty ls mvar
+        run cradle mlibdir opt $ loop opt S.empty mvar
+      where
+        -- this is just in case.
+        -- If an error is caught here, it is a bug of GhcMod library.
+        someHandler (SomeException e) = do
+            putStrLn $ "NG " ++ replace (show e)
 
+replace :: String -> String
+replace [] = []
+replace ('\n':xs) = ';' : replace xs
+replace (x:xs)    =  x  : replace xs
+
 ----------------------------------------------------------------
 
-run :: Cradle -> Maybe FilePath -> Options -> (Logger -> Ghc a) -> IO a
+run :: Cradle -> Maybe FilePath -> Options -> Ghc a -> IO a
 run cradle mlibdir opt body = G.runGhc mlibdir $ do
-    (readLog,_) <- initializeFlagsWithCradle opt cradle ["-Wall"] True
+    initializeFlagsWithCradle opt cradle
     dflags <- G.getSessionDynFlags
-    G.defaultCleanupHandler dflags $ body readLog
+    G.defaultCleanupHandler dflags body
 
 ----------------------------------------------------------------
 
-setupDB :: Cradle -> Maybe FilePath -> Options -> MVar DB -> IO ()
+setupDB :: Cradle -> Maybe FilePath -> Options -> MVar SymMdlDb -> IO ()
 setupDB cradle mlibdir opt mvar = E.handle handler $ do
-    sm <- run cradle mlibdir opt $ \_ -> G.getSessionDynFlags >>= browseAll
-    let sms = map tieup $ groupBy ((==) `on` fst) $ sort sm
-        m = M.fromList sms
-    putMVar mvar m
+    db <- run cradle mlibdir opt getSymMdlDb
+    putMVar mvar db
   where
-    tieup x = (head (map fst x), map snd x)
-    handler (SomeException _) = return ()
+    handler (SomeException _) = return () -- fixme: put emptyDb?
 
 ----------------------------------------------------------------
 
-loop :: Set FilePath -> LineSeparator -> MVar DB -> Logger -> Ghc ()
-loop set ls mvar readLog  = do
+loop :: Options -> Set FilePath -> MVar SymMdlDb -> Ghc ()
+loop opt set mvar = do
     cmdArg <- liftIO getLine
     let (cmd,arg') = break (== ' ') cmdArg
         arg = dropWhile (== ' ') arg'
-    (msgs,ok,set') <- case cmd of
-        "check" -> checkStx set ls readLog arg
-        "find"  -> findSym set mvar arg
-        "lint"  -> lintStx set ls arg
-        _       -> return ([], False, set)
-    mapM_ (liftIO . putStrLn) msgs
-    liftIO $ putStrLn $ if ok then "OK" else "NG"
+    (ret,ok,set') <- case cmd of
+        "check"  -> checkStx opt set arg
+        "find"   -> findSym  opt set arg mvar
+        "lint"   -> lintStx  opt set arg
+        "info"   -> showInfo opt set arg
+        "type"   -> showType opt set arg
+        "boot"   -> bootIt   opt set
+        "browse" -> browseIt opt set arg
+        "quit"   -> return ("quit", False, set)
+        ""       -> return ("quit", False, set)
+        _        -> return ([], True, set)
+    if ok then do
+        liftIO $ putStr ret
+        liftIO $ putStrLn "OK"
+      else do
+        liftIO $ putStrLn $ "NG " ++ replace ret
     liftIO $ hFlush stdout
-    when ok $ loop set' ls mvar readLog
+    when ok $ loop opt set' mvar
 
 ----------------------------------------------------------------
 
-checkStx :: Set FilePath
-         -> LineSeparator
-         -> Logger
+checkStx :: Options
+         -> Set FilePath
          -> FilePath
-         -> Ghc ([String], Bool, Set FilePath)
-checkStx set ls readLog file = do
-    let add = not $ S.member file set
-    GE.ghandle handler $ do
-        mdel <- removeMainTarget
-        when add $ addTargetFiles [file]
-        void $ G.load LoadAllTargets
-        msgs <- liftIO readLog
-        let set1 = if add then S.insert file set else set
-            set2 = case mdel of
-                Nothing    -> set1
-                Just delfl -> S.delete delfl set1
-        return (msgs, True, set2)
+         -> Ghc (String, Bool, Set FilePath)
+checkStx opt set file = do
+    set' <- newFileSet set file
+    let files = S.toList set'
+    eret <- check opt files
+    case eret of
+        Right ret -> return (ret, True, set')
+        Left ret  -> return (ret, True, set) -- fxime: set
+
+newFileSet :: Set FilePath -> FilePath -> Ghc (Set FilePath)
+newFileSet set file = do
+    let set1
+         | S.member file set = set
+         | otherwise         = S.insert file set
+    mx <- isSameMainFile file <$> getModSummaryForMain
+    return $ case mx of
+        Nothing       -> set1
+        Just mainfile -> S.delete mainfile set1
+
+getModSummaryForMain :: Ghc (Maybe G.ModSummary)
+getModSummaryForMain = find isMain <$> G.getModuleGraph
   where
-    handler :: SourceError -> Ghc ([String], Bool, Set FilePath)
-    handler err = do
-        errmsgs <- handleErrMsg ls err
-        return (errmsgs, False, set)
-    removeMainTarget = do
-        mx <- find isMain <$> G.getModuleGraph
-        case mx of
-            Nothing -> return Nothing
-            Just x  -> do
-                let mmainfile = G.ml_hs_file (G.ms_location x)
-                    -- G.ms_hspp_file x is a temporary file with CPP.
-                    -- this is a just fake.
-                    mainfile = fromMaybe (G.ms_hspp_file x) mmainfile
-                if mainfile == file then
-                    return Nothing
-                  else do
-                    let target = TargetFile mainfile Nothing
-                    G.removeTarget target
-                    return $ Just mainfile
     isMain m = G.moduleNameString (G.moduleName (G.ms_mod m)) == "Main"
 
-findSym :: Set FilePath -> MVar DB -> String
-        -> Ghc ([String], Bool, Set FilePath)
-findSym set mvar sym = do
+isSameMainFile :: FilePath -> (Maybe G.ModSummary) -> Maybe FilePath
+isSameMainFile _    Nothing  = Nothing
+isSameMainFile file (Just x)
+    | mainfile == file = Nothing
+    | otherwise        = Just mainfile
+  where
+    mmainfile = G.ml_hs_file (G.ms_location x)
+    -- G.ms_hspp_file x is a temporary file with CPP.
+    -- this is a just fake.
+    mainfile = fromMaybe (G.ms_hspp_file x) mmainfile
+
+----------------------------------------------------------------
+
+findSym :: Options -> Set FilePath -> String -> MVar SymMdlDb
+        -> Ghc (String, Bool, Set FilePath)
+findSym opt set sym mvar = do
     db <- liftIO $ readMVar mvar
-    let ret = fromMaybe [] (M.lookup sym db)
+    let ret = lookupSym opt sym db
     return (ret, True, set)
 
-lintStx :: Set FilePath -> LineSeparator -> FilePath
-        -> Ghc ([String], Bool, Set FilePath)
-lintStx set (LineSeparator lsep) optFile = liftIO $ E.handle handler $ do
-    msgs <- map (intercalate lsep . lines) <$> lint hopts file
-    return (msgs, True, set)
+lintStx :: Options -> Set FilePath -> FilePath
+        -> Ghc (String, Bool, Set FilePath)
+lintStx opt set optFile = liftIO $ do
+    ret <-lintSyntax opt' file
+    return (ret, True, set)
   where
-    (opt,file) = parseLintOptions optFile
-    hopts = if opt == "" then [] else read opt
-    -- let's continue the session
-    handler (SomeException e) = do
-        print e
-        return ([], True, set)
+    (opts,file) = parseLintOptions optFile
+    hopts = if opts == "" then [] else read opts
+    opt' = opt { hlintOpts = hopts }
 
 -- |
 -- >>> parseLintOptions "[\"--ignore=Use camelCase\", \"--ignore=Eta reduce\"] file name"
@@ -230,3 +230,42 @@
     brk p (x:xs')
         | p x        =  ([x],xs')
         | otherwise  =  let (ys,zs) = brk p xs' in (x:ys,zs)
+
+----------------------------------------------------------------
+
+showInfo :: Options
+         -> Set FilePath
+         -> FilePath
+         -> Ghc (String, Bool, Set FilePath)
+showInfo opt set fileArg = do
+    let [file, expr] = words fileArg
+    set' <- newFileSet set file
+    ret <- info opt file expr
+    return (ret, True, set')
+
+showType :: Options
+         -> Set FilePath
+         -> FilePath
+         -> Ghc (String, Bool, Set FilePath)
+showType opt set fileArg  = do
+    let [file, line, column] = words fileArg
+    set' <- newFileSet set file
+    ret <- types opt file (read line) (read column)
+    return (ret, True, set')
+
+----------------------------------------------------------------
+
+bootIt :: Options
+       -> Set FilePath
+       -> Ghc (String, Bool, Set FilePath)
+bootIt opt set = do
+    ret <- boot opt
+    return (ret, True, set)
+
+browseIt :: Options
+         -> Set FilePath
+         -> ModuleString
+         -> Ghc (String, Bool, Set FilePath)
+browseIt opt set mdl = do
+    ret <- browse opt mdl
+    return (ret, True, set)
diff --git a/test/CabalApiSpec.hs b/test/CabalApiSpec.hs
--- a/test/CabalApiSpec.hs
+++ b/test/CabalApiSpec.hs
@@ -9,9 +9,17 @@
 import Language.Haskell.GhcMod.Cradle
 import Language.Haskell.GhcMod.Types
 import Test.Hspec
+import System.Directory
+import System.FilePath
 
 import Dir
 
+import Config (cProjectVersionInt) -- ghc version
+
+ghcVersion :: Int
+ghcVersion = read cProjectVersionInt
+
+
 spec :: Spec
 spec = do
     describe "parseCabalFile" $ do
@@ -20,6 +28,7 @@
 
     describe "getCompilerOptions" $ do
         it "gets necessary CompilerOptions" $ do
+            cwd <- getCurrentDirectory
             withDirectory "test/data/subdir1/subdir2" $ \dir -> do
                 cradle <- findCradle
                 pkgDesc <- parseCabalFile $ fromJust $ cradleCabalFile cradle
@@ -28,7 +37,12 @@
                         ghcOptions  = ghcOptions res
                       , includeDirs = map (toRelativeDir dir) (includeDirs res)
                       }
-                res' `shouldBe` CompilerOptions {ghcOptions = ["-no-user-package-db","-package-db","/home/me/work/ghc-mod/test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d","-XHaskell98"], includeDirs = ["test/data","test/data/dist/build","test/data/dist/build/autogen","test/data/subdir1/subdir2","test/data/test"], depPackages = [("Cabal", Nothing), ("base", Nothing) , ("template-haskell", Nothing)]}
+                if ghcVersion < 706
+                  then ghcOptions res' `shouldBe` ["-global-package-conf", "-no-user-package-conf","-package-conf",cwd </> "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d","-XHaskell98"]
+                  else ghcOptions res' `shouldBe` ["-global-package-db", "-no-user-package-db","-package-db",cwd </> "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d","-XHaskell98"]
+                includeDirs res' `shouldBe` ["test/data","test/data/dist/build","test/data/dist/build/autogen","test/data/subdir1/subdir2","test/data/test"]
+                depPackages res' `shouldSatisfy` (("Cabal", "1.18.1.3", "2b161c6bf77657aa17e1681d83cb051b")`elem`)
+
 
     describe "cabalDependPackages" $ do
         it "extracts dependent packages" $ do
diff --git a/test/GhcPkgSpec.hs b/test/GhcPkgSpec.hs
new file mode 100644
--- /dev/null
+++ b/test/GhcPkgSpec.hs
@@ -0,0 +1,28 @@
+module GhcPkgSpec where
+
+import Language.Haskell.GhcMod.Types
+import Language.Haskell.GhcMod.GhcPkg
+
+import Control.Applicative
+import System.Directory
+import System.FilePath ((</>))
+import Test.Hspec
+
+import Dir
+
+spec :: Spec
+spec = do
+    describe "getSandboxDb" $ do
+        it "parses a config file and extracts sandbox package db" $ do
+            cwd <- getCurrentDirectory
+            pkgDb <- getSandboxDb "test/data/"
+            pkgDb `shouldBe` (cwd </> "test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d")
+
+        it "throws an error if a config file is broken" $ do
+            getSandboxDb "test/data/broken-sandbox" `shouldThrow` anyException
+
+    describe "getPackageDbPackages" $ do
+        it "find a config file and extracts packages" $ do
+            sdb <- getSandboxDb "test/data/check-packageid"
+            pkgs <- ghcPkgListEx [PackageDb sdb]
+            pkgs `shouldBe` [("template-haskell","2.8.0.0","32d4f24abdbb6bf41272b183b2e23e9c")]
diff --git a/test/InfoSpec.hs b/test/InfoSpec.hs
--- a/test/InfoSpec.hs
+++ b/test/InfoSpec.hs
@@ -23,38 +23,38 @@
         it "shows types of the expression and its outers" $ do
             withDirectory_ "test/data/ghc-mod-check" $ do
                 cradle <- findCradleWithoutSandbox
-                res <- typeExpr defaultOptions cradle "Data/Foo.hs" "Data.Foo" 9 5
+                res <- typeExpr defaultOptions cradle "Data/Foo.hs" 9 5
                 res `shouldBe` "9 5 11 40 \"Int -> a -> a -> a\"\n7 1 11 40 \"Int -> Integer\"\n"
 
         it "works with a module using TemplateHaskell" $ do
             withDirectory_ "test/data" $ do
                 cradle <- findCradleWithoutSandbox
-                res <- typeExpr defaultOptions cradle "Bar.hs" "Bar" 5 1
+                res <- typeExpr defaultOptions cradle "Bar.hs" 5 1
                 res `shouldBe` unlines ["5 1 5 20 \"[Char]\""]
 
         it "works with a module that imports another module using TemplateHaskell" $ do
             withDirectory_ "test/data" $ do
                 cradle <- findCradleWithoutSandbox
-                res <- typeExpr defaultOptions cradle "Main.hs" "Main" 3 8
+                res <- typeExpr defaultOptions cradle "Main.hs" 3 8
                 res `shouldBe` unlines ["3 8 3 16 \"String -> IO ()\"", "3 8 3 20 \"IO ()\"", "3 1 3 20 \"IO ()\""]
 
     describe "infoExpr" $ do
         it "works for non-export functions" $ do
             withDirectory_ "test/data" $ do
                 cradle <- findCradleWithoutSandbox
-                res <- infoExpr defaultOptions cradle "Info.hs" "Info" "fib"
+                res <- infoExpr defaultOptions cradle "Info.hs" "fib"
                 res `shouldSatisfy` ("fib :: Int -> Int" `isPrefixOf`)
 
         it "works with a module using TemplateHaskell" $ do
             withDirectory_ "test/data" $ do
                 cradle <- findCradleWithoutSandbox
-                res <- infoExpr defaultOptions cradle "Bar.hs" "Bar" "foo"
+                res <- infoExpr defaultOptions cradle "Bar.hs" "foo"
                 res `shouldSatisfy` ("foo :: ExpQ" `isPrefixOf`)
 
         it "works with a module that imports another module using TemplateHaskell" $ do
             withDirectory_ "test/data" $ do
                 cradle <- findCradleWithoutSandbox
-                res <- infoExpr defaultOptions cradle "Main.hs" "Main" "bar"
+                res <- infoExpr defaultOptions cradle "Main.hs" "bar"
                 res `shouldSatisfy` ("bar :: [Char]" `isPrefixOf`)
 
         it "doesn't fail on unicode output" $ do
diff --git a/test/Main.hs b/test/Main.hs
new file mode 100644
--- /dev/null
+++ b/test/Main.hs
@@ -0,0 +1,12 @@
+import Spec
+import Dir
+
+import Test.Hspec
+import System.Process
+
+main = do
+  let sandboxes = [ "test/data", "test/data/check-packageid" ]
+      genSandboxCfg dir = withDirectory dir $ \cwd -> do
+         system ("sed 's|@CWD@|" ++ cwd ++ "|g' cabal.sandbox.config.in > cabal.sandbox.config")
+  genSandboxCfg `mapM` sandboxes
+  hspec spec
diff --git a/test/Spec.hs b/test/Spec.hs
--- a/test/Spec.hs
+++ b/test/Spec.hs
@@ -1,1 +1,1 @@
-{-# OPTIONS_GHC -F -pgmF hspec-discover #-}
+{-# OPTIONS_GHC -F -pgmF hspec-discover -optF --no-main #-}
diff --git a/test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/Cabal-1.18.1.3-2b161c6bf77657aa17e1681d83cb051b.conf b/test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/Cabal-1.18.1.3-2b161c6bf77657aa17e1681d83cb051b.conf
new file mode 100644
--- /dev/null
+++ b/test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/Cabal-1.18.1.3-2b161c6bf77657aa17e1681d83cb051b.conf
@@ -0,0 +1,4 @@
+name: Cabal
+version: 1.18.1.3
+id: Cabal-1.18.1.3-2b161c6bf77657aa17e1681d83cb051b
+exposed: True
diff --git a/test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/dummy b/test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/dummy
deleted file mode 100644
--- a/test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/dummy
+++ /dev/null
@@ -1,1 +0,0 @@
-dummy
diff --git a/test/data/Bs.hs b/test/data/Bs.hs
deleted file mode 100644
--- a/test/data/Bs.hs
+++ /dev/null
@@ -1,11 +0,0 @@
-{-# LANGUAGE OverloadedStrings #-}
-
-module Bs where
-
-import Data.ByteString.Lazy (ByteString)
-import qualified Data.ByteString as B
-
-foo :: ByteString
-foo = "foo"
-
-bar = B.putStrLn foo
diff --git a/test/data/cabal.sandbox.config b/test/data/cabal.sandbox.config
deleted file mode 100644
--- a/test/data/cabal.sandbox.config
+++ /dev/null
@@ -1,25 +0,0 @@
--- This is a Cabal package environment file.
--- THIS FILE IS AUTO-GENERATED. DO NOT EDIT DIRECTLY.
--- Please create a 'cabal.config' file in the same directory
--- if you want to change the default settings for this sandbox.
-
-
-local-repo: /home/me/work/ghc-mod/test/data/.cabal-sandbox/packages
-logs-dir: /home/me/work/ghc-mod/test/data/.cabal-sandbox/logs
-world-file: /home/me/work/ghc-mod/test/data/.cabal-sandbox/world
-user-install: False
-package-db: /home/me/work/ghc-mod/test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d
-build-summary: /home/me/work/ghc-mod/test/data/.cabal-sandbox/logs/build.log
-
-install-dirs 
-  prefix: /home/me/work/ghc-mod/test/data/.cabal-sandbox
-  bindir: $prefix/bin
-  libdir: $prefix/lib
-  libsubdir: $arch-$os-$compiler/$pkgid
-  libexecdir: $prefix/libexec
-  datadir: $prefix/share
-  datasubdir: $arch-$os-$compiler/$pkgid
-  docdir: $datadir/doc/$arch-$os-$compiler/$pkgid
-  htmldir: $docdir/html
-  haddockdir: $htmldir
-  sysconfdir: $prefix/etc
diff --git a/test/data/cabal.sandbox.config.in b/test/data/cabal.sandbox.config.in
new file mode 100644
--- /dev/null
+++ b/test/data/cabal.sandbox.config.in
@@ -0,0 +1,25 @@
+-- This is a Cabal package environment file.
+-- THIS FILE IS AUTO-GENERATED. DO NOT EDIT DIRECTLY.
+-- Please create a 'cabal.config' file in the same directory
+-- if you want to change the default settings for this sandbox.
+
+
+local-repo: @CWD@/test/data/.cabal-sandbox/packages
+logs-dir: @CWD@/test/data/.cabal-sandbox/logs
+world-file: @CWD@/test/data/.cabal-sandbox/world
+user-install: False
+package-db: @CWD@/test/data/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d
+build-summary: @CWD@/test/data/.cabal-sandbox/logs/build.log
+
+install-dirs
+  prefix: @CWD@/test/data/.cabal-sandbox
+  bindir: $prefix/bin
+  libdir: $prefix/lib
+  libsubdir: $arch-$os-$compiler/$pkgid
+  libexecdir: $prefix/libexec
+  datadir: $prefix/share
+  datasubdir: $arch-$os-$compiler/$pkgid
+  docdir: $datadir/doc/$arch-$os-$compiler/$pkgid
+  htmldir: $docdir/html
+  haddockdir: $htmldir
+  sysconfdir: $prefix/etc
diff --git a/test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c.conf b/test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c.conf
new file mode 100644
--- /dev/null
+++ b/test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d/template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c.conf
@@ -0,0 +1,4 @@
+name: template-haskell
+version: 2.8.0.0
+id: template-haskell-2.8.0.0-32d4f24abdbb6bf41272b183b2e23e9c
+exposed: True
diff --git a/test/data/check-packageid/cabal.sandbox.config.in b/test/data/check-packageid/cabal.sandbox.config.in
new file mode 100644
--- /dev/null
+++ b/test/data/check-packageid/cabal.sandbox.config.in
@@ -0,0 +1,25 @@
+-- This is a Cabal package environment file.
+-- THIS FILE IS AUTO-GENERATED. DO NOT EDIT DIRECTLY.
+-- Please create a 'cabal.config' file in the same directory
+-- if you want to change the default settings for this sandbox.
+
+
+local-repo: @CWD@/test/data/.cabal-sandbox/packages
+logs-dir: @CWD@/test/data/.cabal-sandbox/logs
+world-file: @CWD@/test/data/.cabal-sandbox/world
+user-install: False
+package-db: test/data/check-packageid/.cabal-sandbox/i386-osx-ghc-7.6.3-packages.conf.d
+build-summary: @CWD@/test/data/.cabal-sandbox/logs/build.log
+
+install-dirs
+  prefix: @CWD@/test/data/.cabal-sandbox
+  bindir: $prefix/bin
+  libdir: $prefix/lib
+  libsubdir: $arch-$os-$compiler/$pkgid
+  libexecdir: $prefix/libexec
+  datadir: $prefix/share
+  datasubdir: $arch-$os-$compiler/$pkgid
+  docdir: $datadir/doc/$arch-$os-$compiler/$pkgid
+  htmldir: $docdir/html
+  haddockdir: $htmldir
+  sysconfdir: $prefix/etc
diff --git a/test/doctests.hs b/test/doctests.hs
--- a/test/doctests.hs
+++ b/test/doctests.hs
@@ -6,5 +6,8 @@
 main = doctest [
     "-package"
   , "ghc"
+  , "-idist/build/autogen/"
+  , "-optP-include"
+  , "-optPdist/build/autogen/cabal_macros.h"
   , "Language/Haskell/GhcMod.hs"
   ]
