2017-05-31 22:20:56 +03:00
|
|
|
{-# LANGUAGE RankNTypes, ScopedTypeVariables #-}
|
2017-04-20 21:00:02 +03:00
|
|
|
module Renderer.SExpression
|
2017-05-29 23:51:32 +03:00
|
|
|
( renderSExpressionDiff
|
|
|
|
, renderSExpressionTerm
|
2017-04-20 21:00:02 +03:00
|
|
|
) where
|
2016-12-09 19:31:13 +03:00
|
|
|
|
|
|
|
import Data.Bifunctor.Join
|
2017-03-08 22:05:49 +03:00
|
|
|
import Data.ByteString hiding (foldr, spanEnd)
|
2017-03-31 23:12:26 +03:00
|
|
|
import Data.Record
|
2017-03-08 22:05:49 +03:00
|
|
|
import Prologue hiding (replicate, encodeUtf8)
|
2016-12-09 19:31:13 +03:00
|
|
|
import Diff
|
|
|
|
import Patch
|
|
|
|
import Info
|
|
|
|
import Term
|
|
|
|
|
2017-04-21 01:13:28 +03:00
|
|
|
-- | Returns a ByteString SExpression formatted diff.
|
2017-05-29 23:51:32 +03:00
|
|
|
renderSExpressionDiff :: (HasField fields Category, Foldable f) => Diff f (Record fields) -> ByteString
|
|
|
|
renderSExpressionDiff diff = printDiff diff 0 <> "\n"
|
2017-02-22 01:01:39 +03:00
|
|
|
|
2017-04-21 01:13:28 +03:00
|
|
|
-- | Returns a ByteString SExpression formatted term.
|
2017-05-29 23:51:32 +03:00
|
|
|
renderSExpressionTerm :: (HasField fields Category, Foldable f) => Term f (Record fields) -> ByteString
|
|
|
|
renderSExpressionTerm term = printTerm term 0 <> "\n"
|
2017-04-20 21:00:02 +03:00
|
|
|
|
2017-05-29 21:18:10 +03:00
|
|
|
printDiff :: (HasField fields Category, Foldable f) => Diff f (Record fields) -> Int -> ByteString
|
2017-05-26 17:15:15 +03:00
|
|
|
printDiff diff level = case runFree diff of
|
2017-05-29 21:36:34 +03:00
|
|
|
Pure patch -> case patch of
|
2017-05-26 17:15:15 +03:00
|
|
|
Insert term -> pad (level - 1) <> "{+" <> printTerm term level <> "+}"
|
|
|
|
Delete term -> pad (level - 1) <> "{-" <> printTerm term level <> "-}"
|
|
|
|
Replace a b -> pad (level - 1) <> "{ " <> printTerm a level <> pad (level - 1) <> "->" <> printTerm b level <> " }"
|
2017-05-29 21:36:34 +03:00
|
|
|
Free (Join (_, annotation) :< syntax) -> pad' level <> "(" <> showAnnotation annotation <> foldr (\d acc -> printDiff d (level + 1) <> acc) "" syntax <> ")"
|
2016-12-09 20:47:51 +03:00
|
|
|
where
|
2017-03-08 22:05:49 +03:00
|
|
|
pad' :: Int -> ByteString
|
2017-02-17 22:36:50 +03:00
|
|
|
pad' n = if n < 1 then "" else pad n
|
2017-03-08 22:05:49 +03:00
|
|
|
pad :: Int -> ByteString
|
2017-02-18 00:54:20 +03:00
|
|
|
pad n | n < 0 = ""
|
|
|
|
| n < 1 = "\n"
|
2017-03-08 22:05:49 +03:00
|
|
|
| otherwise = "\n" <> replicate (2 * n) space
|
|
|
|
|
2017-05-29 21:18:10 +03:00
|
|
|
printTerm :: (HasField fields Category, Foldable f) => Term f (Record fields) -> Int -> ByteString
|
2017-05-26 17:15:15 +03:00
|
|
|
printTerm term level = go term level 0
|
2016-12-09 22:30:37 +03:00
|
|
|
where
|
2017-03-08 22:05:49 +03:00
|
|
|
pad :: Int -> Int -> ByteString
|
2016-12-10 01:47:00 +03:00
|
|
|
pad p n | n < 1 = ""
|
2017-03-08 22:05:49 +03:00
|
|
|
| otherwise = "\n" <> replicate (2 * (p + n)) space
|
2017-05-29 21:18:10 +03:00
|
|
|
go :: (HasField fields Category, Foldable f) => Term f (Record fields) -> Int -> Int -> ByteString
|
2016-12-09 22:30:37 +03:00
|
|
|
go term parentLevel level = case runCofree term of
|
2017-05-26 17:15:15 +03:00
|
|
|
(annotation :< syntax) -> pad parentLevel level <> "(" <> showAnnotation annotation <> foldr (\t acc -> go t parentLevel (level + 1) <> acc) "" syntax <> ")"
|
2016-12-09 22:30:37 +03:00
|
|
|
|
2017-05-29 21:18:10 +03:00
|
|
|
showAnnotation :: HasField fields Category => Record fields -> ByteString
|
2017-05-26 17:15:15 +03:00
|
|
|
showAnnotation = toS . category
|
2017-03-08 22:05:49 +03:00
|
|
|
|
|
|
|
space :: Word8
|
|
|
|
space = fromIntegral $ ord ' '
|