@@ -57,6 +57,9 @@ import System.FilePath
57import System.IO.Extra
57import System.IO.Extra
58import Data.Char
58import Data.Char
60+import SysTools (Option (..), runUnlit)
60-- | Given a string buffer, return a pre-processed @ParsedModule@.
63-- | Given a string buffer, return a pre-processed @ParsedModule@.
61parseModule
64parseModule
62 :: IdeOptions
65 :: IdeOptions
@@ -267,6 +270,33 @@ getModSummaryFromBuffer fp contents dflags parsed = do
267 then (HsBootFile, \newExt -> stem <.> newExt ++ "-boot")
270 then (HsBootFile, \newExt -> stem <.> newExt ++ "-boot")
268 else (HsSrcFile , \newExt -> stem <.> newExt)
271 else (HsSrcFile , \newExt -> stem <.> newExt)
273+-- | Run (unlit) literate haskell preprocessor on a file, or buffer if set
274+runLhs :: DynFlags -> FilePath -> Maybe SB.StringBuffer -> IO SB.StringBuffer
275+runLhs dflags filename contents = withTempDir $ \dir -> do
276+ let fout = dir </> takeFileName filename <.> "unlit"
277+ filesrc <- case contents of
278+ Nothing -> return filename
280+ let fsrc = dir </> takeFileName filename <.> "literate"
281+ withBinaryFile fsrc WriteMode $ \h ->
282+ hPutStringBuffer h cnts
285+ SB.hGetStringBuffer fout
287+ unlit filein fileout = SysTools.runUnlit dflags (args filein fileout)
288+ args filein fileout = [
289+ SysTools.Option "-h"
290+ , SysTools.Option (escape filename) -- name this file
291+ , SysTools.FileOption "" filein -- input file
292+ , SysTools.FileOption "" fileout ] -- output file
293+ -- taken from ghc's DriverPipeline.hs
294+ escape ('\\':cs) = '\\':'\\': escape cs
295+ escape ('\"':cs) = '\\':'\"': escape cs
296+ escape ('\'':cs) = '\\':'\'': escape cs
297+ escape (c:cs) = c : escape cs
270-- | Run CPP on a file
300-- | Run CPP on a file
271runCpp :: DynFlags -> FilePath -> Maybe SB.StringBuffer -> IO SB.StringBuffer
301runCpp :: DynFlags -> FilePath -> Maybe SB.StringBuffer -> IO SB.StringBuffer
272runCpp dflags filename contents = withTempDir $ \dir -> do
302runCpp dflags filename contents = withTempDir $ \dir -> do
@@ -304,7 +334,6 @@ runCpp dflags filename contents = withTempDir $ \dir -> do
304 | otherwise = x
334 | otherwise = x
305 stringToStringBuffer . unlines . map tweak . lines <$> readFileUTF8' out
335 stringToStringBuffer . unlines . map tweak . lines <$> readFileUTF8' out
308-- | Given a buffer, flags, file path and module summary, produce a
337-- | Given a buffer, flags, file path and module summary, produce a
309-- parsed module (or errors) and any parse warnings.
338-- parsed module (or errors) and any parse warnings.
310parseFileContents
339parseFileContents
@@ -314,15 +343,24 @@ parseFileContents
314 -> Maybe SB.StringBuffer -- ^ Haskell module source text (full Unicode is supported)
343 -> Maybe SB.StringBuffer -- ^ Haskell module source text (full Unicode is supported)
315 -> ExceptT [FileDiagnostic] m ([FileDiagnostic], ParsedModule)
344 -> ExceptT [FileDiagnostic] m ([FileDiagnostic], ParsedModule)
316parseFileContents preprocessor filename mbContents = do
345parseFileContents preprocessor filename mbContents = do
317− contents <- liftIO $ maybe (hGetStringBuffer filename) return mbContents
318 let loc = mkRealSrcLoc (mkFastString filename) 1 1
346 let loc = mkRealSrcLoc (mkFastString filename) 1 1
319− dflags <- ExceptT $ parsePragmasIntoDynFlags filename contents
347+ contents <- liftIO $ maybe (hGetStringBuffer filename) return mbContents
348+ let isOnDisk = isNothing mbContents
350+ -- unlit content if literate Haskell ending
351+ (isOnDisk, contents) <- if ".lhs" `isSuffixOf` filename
353+ dflags <- getDynFlags
354+ newcontent <- liftIO $ runLhs dflags filename mbContents
355+ return (False, newcontent)
356+ else return (isOnDisk, contents)
358+ dflags <- ExceptT $ parsePragmasIntoDynFlags filename contents
321 (contents, dflags) <-
359 (contents, dflags) <-
322 if not $ xopt LangExt.Cpp dflags then
360 if not $ xopt LangExt.Cpp dflags then
323 return (contents, dflags)
361 return (contents, dflags)
325− contents <- liftIO $ runCpp dflags filename mbContents
363+ contents <- liftIO $ runCpp dflags filename $ if isOnDisk then Nothing else Just contents
326 dflags <- ExceptT $ parsePragmasIntoDynFlags filename contents
364 dflags <- ExceptT $ parsePragmasIntoDynFlags filename contents
327 return (contents, dflags)
365 return (contents, dflags)