23 | module Text.Literate
29 | import Data.List.Views
34 | untilEOL : Recognise False
35 | untilEOL = manyUntil newline any
37 | line : String -> Lexer
38 | line s = exact s <+> (newline <|> space <+> untilEOL)
40 | block : String -> String -> Lexer
41 | block s e = surround (exact s <+> untilEOL) (exact e <+> untilEOL) any
44 | notCodeLine = newline
45 | <|> any <+> untilEOL
47 | data Token = CodeBlock String String String
49 | | CodeLine String String
52 | showPrec d (CodeBlock l r x) = showCon d "CodeBlock" $
showArg l ++ showArg r ++ showArg x
53 | showPrec d (Any x) = showCon d "Any" $
showArg x
54 | showPrec d (CodeLine m x) = showCon d "CodeLine" $
showArg m ++ showArg x
56 | rawTokens : (delims : List (String, String))
57 | -> (markers : List String)
59 | rawTokens delims ls =
60 | map (\(l,r) => (block l r, CodeBlock (trim l) (trim r))) delims
61 | ++ map (\m => (line m, CodeLine (trim m))) ls
62 | ++ [(notCodeLine, Any)]
68 | lines' : List Char -> List1 (List Char)
69 | lines' [] = singleton []
70 | lines' s = case break isNL s of
71 | (l, s') => l ::: case s' of
73 | _ :: s'' => forget $
lines' (assert_smaller s s'')
75 | lines : String -> List1 String
76 | lines s = map pack (lines' (unpack s))
79 | reduce : List (WithBounds Token) -> List String -> String
80 | reduce [] acc = concat (reverse acc)
81 | reduce (MkBounded (Any x) _ _ :: rest) acc =
84 | then reduce rest ("\n"::acc)
85 | else reduce rest acc
87 | reduce (MkBounded (CodeLine m src) _ _ :: rest) acc =
89 | then reduce rest ("\n"::acc)
90 | else reduce rest ((substr (length m + 1)
95 | reduce (MkBounded (CodeBlock l r src) _ _ :: rest) acc with (Compat.lines src)
96 | reduce (MkBounded (CodeBlock l r src) _ _ :: rest) acc | (s ::: ys) with (snocList ys)
97 | reduce (MkBounded (CodeBlock l r src) _ _ :: rest) acc | (s ::: []) | Empty = reduce rest acc
98 | reduce (MkBounded (CodeBlock l r src) _ _ :: rest) acc | (s ::: (srcs ++ [f])) | (Snoc f srcs rec) =
100 | reduce rest (((unlines srcs) ++ "\n") :: "\n" :: acc)
106 | record LiterateError where
107 | constructor MkLitErr
153 | record LiterateStyle where
154 | constructor MkLitStyle
156 | deliminators : List (String, String)
159 | line_markers : List String
164 | file_extensions : List String
176 | extractCode : (specification : LiterateStyle)
177 | -> (litStr : String)
178 | -> Either LiterateError String
179 | extractCode (MkLitStyle delims markers exts) str =
180 | case lex (rawTokens delims markers) str of
181 | (toks, (_,_,"")) => Right (reduce toks Nil)
182 | (_, (l,c,i)) => Left (MkLitErr l c i)
186 | unlit : (specification : LiterateStyle)
187 | -> (litStr : String)
188 | -> Either LiterateError String
189 | unlit = extractCode
197 | isLiterateLine : (specification : LiterateStyle)
199 | -> Pair (Maybe String) String
200 | isLiterateLine (MkLitStyle delims markers _) str with (lex (rawTokens delims markers) str)
201 | isLiterateLine (MkLitStyle delims markers _) str | ([MkBounded (CodeLine m str') _ _], (_,_, "")) = (Just m, str')
202 | isLiterateLine (MkLitStyle delims markers _) str | (_, _) = (Nothing, str)
218 | embedCode : (specification : LiterateStyle)
221 | embedCode (MkLitStyle ((s,e)::delims) _ _) str = unlines [s,str,e]
222 | embedCode (MkLitStyle Nil (m::markers) _) str = unwords [m, str]
223 | embedCode (MkLitStyle _ _ _) str = str
227 | relit : (specification : LiterateStyle)