packages feed

agda2lagda-0.2020.11.1: src/Render.hs

-- | Render the parsed items.

{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE PatternSynonyms #-}

module Render
  ( lagdaTex
  , gobbleTrailingBlockCommentClosers
  ) where

import Data.Char
  (isSpace)

import LexicalStructure
  (Item, pattern TextItem, pattern CommItem, pattern CodeItem)
import Util
  (updateLast)

-- | Render into plain literate LaTeX Agda.

lagdaTex :: [Item] -> String
-- lagdaTex = foldr (\ it s -> render it ++ "\n" ++ s) ""
lagdaTex its = unlines $ concat
   [ ["%% This file was automatically generated by agda2lagda."]
   , [""]
   , map render its
   ]
  where
  render = \case
    TextItem s -> renderHeadingsTex s
    CommItem s -> unlines $ map ("%% " ++) $ lines s
    CodeItem s -> concat
      [ "\\begin{code}\n"
      , s
      , "\\end{code}\n"
      ]

-- | Paragraphs followed by a line of dashes are turned into @\heading{}@s.

renderHeadingsTex :: String -> String
renderHeadingsTex = unlines . loop [] . lines
  where
  -- acc holds the current paragraph in reverse line order
  loop acc = \case
    [] -> reverse acc
    l : ls
      -- If we encounter a blank line, the paragraph ends: reset search for heading.
      | all isSpace l -> reverse ("":acc) ++ loop [] ls
      -- If we find a line of dashes, the current paragraph is a heading (unless it is empty).
      | all (=='-') l ->
          if null acc then loop [] ls
          else [ "\\heading{" ++ unwords (reverse acc) ++ "}" ] ++ loop [] ls
      -- Otherwise continue the current paragraph.
      | otherwise     -> loop (l:acc) ls

-- | Text lines at the end of file consisting solely of words "-}" are
-- discarded, to accommodate for a hack that makes it easy to comment
-- out everything to the end of the file.
-- https://github.com/agda/agda/issues/4953#issuecomment-702720296

gobbleTrailingBlockCommentClosers :: [Item] -> [Item]
gobbleTrailingBlockCommentClosers = updateLast $ \case
  TextItem s -> TextItem $ reverse $ loop $ reverse s
  i -> i
  where
  loop = \case
    -- Drop trailing spaces.
    c:cs | isSpace c -> loop cs
    -- Drop trailing block comment closers.
    '}':'-':cs -> loop cs
    -- Keep rest.
    s -> s