This example looks for lines like
%include "lib/md/load-tutorial-cabal-incl.md"
on its input and replaces them with the contents of the names file.
The tool is self-testing: run it with no arguments (or cabal test
).
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE OverloadedStrings #-}
module Main
( mainwhere
)
import Control.Applicative
import qualified Data.ByteString.Lazy.Char8 as LBS
import Data.Maybe
import qualified Data.Text as T
import Prelude.Compat
import System.Environment
import TestKit
import Text.RE.Replace
import Text.RE.TDFA.ByteString.Lazy
import Text.RE.Tools.Edit
import Text.RE.Tools.Grep
import Text.RE.Tools.Sed
main :: IO ()
= do
main <- getArgs
as case as of
-> test
[] "test"] -> test
[| is_file fn -> loop fn fn'
[fn,fn'] -> usage
_ where
= not . (== "--") . take 2
is_file
= do
usage <- getProgName
prg putStr $ unlines
"usage:"
[ " "++prg++" [test]"
, " "++prg++" (-|<in-file>) (-|<out-file>)"
, ]
loop :: FilePath -> FilePath -> IO ()
=
loop $ Select
sed Function [re|^%include ${file}(@{%string}) ${rex}(@{%string})$|] TOP include_file
[ Function [re|^.*$|] TOP $ \_ _ _ _->return Nothing
, ]
include_file :: LineNo
-> Match LBS.ByteString
-> RELocation
-> Capture LBS.ByteString
-> IO (Maybe LBS.ByteString)
= fmap Just $
include_file _ mtch _ _ =<< compileRegex re_s
extract fp where
= prs_s $ captureText [cp|file|] mtch
fp = prs_s $ captureText [cp|rex|] mtch
re_s
= maybe (error "includeDoc") T.unpack . parseString prs_s
extract :: FilePath -> RE -> IO LBS.ByteString
= extr . LBS.lines <$> LBS.readFile fp
extract fp rex where
=
extr lns case parse $ scan rex lns of
Nothing -> oops
Just (lno,n) -> LBS.unlines $ (hdr :) $ (take n $ drop i lns) ++ [ftr]
where
= getZeroBasedLineNo lno
i
= error $ concat
oops "failed to locate fragment matching "
[ show $ reSource rex
, " in file "
, show fp
,
]
= "<div class='includedcodeblock'>"
hdr = "</div>" ftr
parse :: [Token] -> Maybe (LineNo,Int)
= Nothing
parse [] :tks) = case (tk,tks) of
parse (tkBra b_ln,Hit:Ket k_ln:_) -> Just (b_ln,count_lines_incl b_ln k_ln)
(-> parse tks _
count_lines_incl :: LineNo -> LineNo -> Int
=
count_lines_incl b_ln k_ln + 1 - getZeroBasedLineNo b_ln getZeroBasedLineNo k_ln
data Token = Bra LineNo | Hit | Ket LineNo deriving (Show)
scan :: RE -> [LBS.ByteString] -> [Token]
= grepWithScript
scan rex $ \i -> chk $ Bra i
[ (,) [re|\\begin\{code\}|] $ \_ -> chk Hit
, (,) rex $ \i -> chk $ Ket i
, (,) [re|\\end\{code\}|]
]where
= case anyMatches mtchs of
chk x mtchs True -> Just x
False -> Nothing
test :: IO ()
= do
test "include" loop "data/pp-test.lhs" "data/include-result.lhs"
test_pp putStrLn "tests passed"