{-# LANGUAGE CPP #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} module Text.Pandoc.Filter.EmphasizeCode.Latex ( Latex(Latex) ) where #if MIN_VERSION_base(4,8,0) import Data.Semigroup ((<>)) #else import Control.Applicative import Data.Monoid #endif import Data.Char (isSpace) import Data.Text (Text) import qualified Data.Text as Text import qualified Text.Pandoc.Definition as Pandoc import Text.Pandoc.Filter.EmphasizeCode.Chunking import Text.Pandoc.Filter.EmphasizeCode.Range import Text.Pandoc.Filter.EmphasizeCode.Renderable data Latex = Latex escaped :: Char -> Text escaped = \case '\\' -> "\\textbackslash{}" '#' -> "\\#" '&' -> "\\&" '{' -> "\\{" '}' -> "\\}" '$' -> "\\$" '_' -> "\\_" '%' -> "\\%" '¶' -> "\\P" '§' -> "\\S" '£' -> "\\£" '\'' -> "\\textquotesingle{}" '<' -> "\\textless{}" '>' -> "\\textgreater{}" c -> Text.singleton c instance Renderable Latex where renderEmphasized _ (_, classes, _) lines' = Pandoc.RawBlock (Pandoc.Format "latex") (Text.unpack (encloseInVerbatim emphasized)) where languageAttr = case classes of [lang] -> ",language=" <> Text.pack lang _ -> "" encloseInTextIt style t | Text.null t = t | otherwise = case style of Inline -> "£\\CodeEmphasis{" <> t <> "}£" Block -> "£\\CodeEmphasisLine{" <> t <> "}£" emphasizeNonSpace style t | Text.null t = t | otherwise = let (nonSpace, rest) = Text.break isSpace t (spaces, rest') = Text.span isSpace rest in mconcat [ encloseInTextIt style nonSpace , spaces , emphasizeNonSpace style rest' ] emphasizeChunk chunk = case chunk of Literal t -> t Emphasized style t -> emphasizeNonSpace style (Text.concatMap escaped t) emphasized = Text.unlines (map (foldMap emphasizeChunk) lines') encloseInVerbatim t = mconcat [ "\\begin{lstlisting}[escapechar=£" , languageAttr , "]\n" , t , "\\end{lstlisting}\n" ]