Skip to content

Commit 44b1166

Browse files
authored
Merge pull request #31 from CodiePP/lhs-unlit-preprocessing
added unlit stage for literate Haskell source files
2 parents 5821516 + 67b4d40 commit 44b1166

File tree

6 files changed

+113
-6
lines changed

6 files changed

+113
-6
lines changed

extension/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@
2323
"id": "haskell",
2424
"extensions": [
2525
"hs",
26-
"hs-boot"
26+
"hs-boot",
27+
"lhs-boot",
28+
"lhs"
2729
]
2830
}],
2931
"configuration": {

src/Development/IDE/Core/Compile.hs

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ import System.FilePath
5757
import System.IO.Extra
5858
import Data.Char
5959

60+
import SysTools (Option (..), runUnlit)
61+
62+
6063
-- | Given a string buffer, return a pre-processed @ParsedModule@.
6164
parseModule
6265
:: IdeOptions
@@ -267,6 +270,33 @@ getModSummaryFromBuffer fp contents dflags parsed = do
267270
then (HsBootFile, \newExt -> stem <.> newExt ++ "-boot")
268271
else (HsSrcFile , \newExt -> stem <.> newExt)
269272

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
279+
Just cnts -> do
280+
let fsrc = dir </> takeFileName filename <.> "literate"
281+
withBinaryFile fsrc WriteMode $ \h ->
282+
hPutStringBuffer h cnts
283+
return fsrc
284+
unlit filesrc fout
285+
SB.hGetStringBuffer fout
286+
where
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
298+
escape [] = []
299+
270300
-- | Run CPP on a file
271301
runCpp :: DynFlags -> FilePath -> Maybe SB.StringBuffer -> IO SB.StringBuffer
272302
runCpp dflags filename contents = withTempDir $ \dir -> do
@@ -304,7 +334,6 @@ runCpp dflags filename contents = withTempDir $ \dir -> do
304334
| otherwise = x
305335
stringToStringBuffer . unlines . map tweak . lines <$> readFileUTF8' out
306336

307-
308337
-- | Given a buffer, flags, file path and module summary, produce a
309338
-- parsed module (or errors) and any parse warnings.
310339
parseFileContents
@@ -314,15 +343,24 @@ parseFileContents
314343
-> Maybe SB.StringBuffer -- ^ Haskell module source text (full Unicode is supported)
315344
-> ExceptT [FileDiagnostic] m ([FileDiagnostic], ParsedModule)
316345
parseFileContents preprocessor filename mbContents = do
317-
contents <- liftIO $ maybe (hGetStringBuffer filename) return mbContents
318346
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
320349

350+
-- unlit content if literate Haskell ending
351+
(isOnDisk, contents) <- if ".lhs" `isSuffixOf` filename
352+
then do
353+
dflags <- getDynFlags
354+
newcontent <- liftIO $ runLhs dflags filename mbContents
355+
return (False, newcontent)
356+
else return (isOnDisk, contents)
357+
358+
dflags <- ExceptT $ parsePragmasIntoDynFlags filename contents
321359
(contents, dflags) <-
322360
if not $ xopt LangExt.Cpp dflags then
323361
return (contents, dflags)
324362
else do
325-
contents <- liftIO $ runCpp dflags filename mbContents
363+
contents <- liftIO $ runCpp dflags filename $ if isOnDisk then Nothing else Just contents
326364
dflags <- ExceptT $ parsePragmasIntoDynFlags filename contents
327365
return (contents, dflags)
328366

src/Development/IDE/Types/Options.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ defaultIdeOptions :: IO (FilePath -> Action HscEnvEq) -> IdeOptions
5656
defaultIdeOptions session = IdeOptions
5757
{optPreprocessor = (,) []
5858
,optGhcSession = session
59-
,optExtensions = ["hs"]
59+
,optExtensions = ["hs", "lhs"]
6060
,optPkgLocationOpts = defaultIdePkgLocationOptions
6161
,optThreads = 0
6262
,optShakeProfiling = Nothing

test/manual/lhs/Bird.lhs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-- Copyright (c) 2019 The DAML Authors. All rights reserved.
2+
-- SPDX-License-Identifier: Apache-2.0
3+
4+
5+
\subsection{Bird-style LHS}
6+
7+
> module Bird
8+
> (
9+
> fly
10+
> ) where
11+
12+
13+
14+
what birds are able to do:
15+
16+
> fly :: IO ()
17+
> fly = putStrLn "birds fly."
18+
19+

test/manual/lhs/Main.hs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-- Copyright (c) 2019 The DAML Authors. All rights reserved.
2+
-- SPDX-License-Identifier: Apache-2.0
3+
4+
module Main
5+
(
6+
main
7+
) where
8+
9+
import Test (main)
10+
11+
12+

test/manual/lhs/Test.lhs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
-- Copyright (c) 2019 The DAML Authors. All rights reserved.
2+
-- SPDX-License-Identifier: Apache-2.0
3+
4+
5+
\subsection{Testing LHS}
6+
7+
\begin{code}
8+
{-# LANGUAGE CPP #-}
9+
10+
module Test
11+
(
12+
main
13+
) where
14+
15+
16+
import Bird
17+
18+
\end{code}
19+
20+
for this file, \emph{hlint} should be turned off.
21+
\begin{code}
22+
{-# ANN module ("HLint: ignore" :: String) #-}
23+
\end{code}
24+
25+
our main procedure
26+
27+
\begin{code}
28+
29+
main :: IO ()
30+
main = do
31+
putStrLn "hello world."
32+
fly
33+
34+
\end{code}
35+
36+

0 commit comments

Comments
 (0)