1 {-# LANGUAGE OverloadedStrings #-}
2 {-# LANGUAGE ViewPatterns #-}
3 {-# OPTIONS_GHC -fno-warn-orphans #-}
4 -- | Render a TCT file in plain Text.
5 module Language.TCT.Write.Plain where
7 import Control.Monad (Monad(..), mapM)
9 import Data.Default.Class (Default(..))
10 import Data.Eq (Eq(..))
11 import Data.Foldable (Foldable(..))
12 import Data.Function (($), (.))
13 import Data.Functor ((<$>))
14 import Data.Int (Int,Int64)
15 import Data.Monoid (Monoid(..))
16 import Data.Ord (Ord(..))
17 import Data.Semigroup (Semigroup(..))
18 import Data.Sequence (ViewL(..), ViewR(..))
19 import Data.Text (Text)
20 import Data.TreeSeq.Strict (Tree(..),Trees)
21 import Prelude (Num(..), undefined, Integral(..))
22 import Text.Show (Show(..))
23 import qualified Control.Monad.Trans.State as S
24 import qualified Data.List as L
25 import qualified Data.Sequence as Seq
26 import qualified Data.Text as Text
27 import qualified Data.Text.Lazy as TL
29 import Language.TCT.Tree
30 import Language.TCT.Cell
31 import Language.TCT.Token
32 import Language.TCT.Elem
42 instance Default Inh where
47 plainify :: Inh -> Trees (Cell Key) Tokens -> TL.Text
48 plainify inh = plainifyTreesCell inh . treePosLastCell
50 treeRackUpLeft :: Tree (Cell k) (Cell a) -> Tree (Cell k) (Cell a)
51 treeRackUpLeft t = go t
56 (linePos pos - l0 + 1)
57 (columnPos pos - c0 + 1)
58 go :: Tree (Cell k) (Cell a) -> Tree (Cell k) (Cell a)
59 go (Tree0 (Cell pos posEnd c)) =
60 Tree0 $ Cell (rackUpLeft pos) (rackUpLeft posEnd) c
61 go (TreeN (Cell pos posEnd c) ts) =
63 (Cell (rackUpLeft pos) (rackUpLeft posEnd) c)
67 Trees (Cell k) Tokens ->
68 Trees (Pos,Cell k) (Pos,Tokens)
69 treePosLastCell t = S.evalState (go`mapM`t) (Pos 1 1)
71 go :: Tree (Cell k) Tokens ->
72 S.State Pos (Tree (Pos,Cell k) (Pos,Tokens))
77 return $ Tree0 (lastPos,ts)
79 S.put $ posEndCell cell
80 return $ Tree0 (lastPos,ts)
81 go (TreeN cell ts) = do
83 S.put $ posEndCell cell
85 return $ TreeN (lastPos,cell) ts'
87 int64 :: Integral i => i -> Int64
88 int64 = fromInteger . toInteger
92 Tree (Pos,Cell Key) (Pos,Tokens) ->
94 plainifyTreeCell inh (TreeN (posEnd, Cell pos _ (KeySection lvl)) ts) =
95 plainifyIndentCell (posEnd,pos) <>
96 TL.replicate (int64 lvl) "#" <> " " <>
98 Tree0 (_,title) :< _ ->
99 plainifyIndentToken inh title
101 plainifyTreesCell inh
102 (case Seq.viewl ts of
103 Tree0{} :< ts' -> ts'
105 plainifyTreeCell inh (Tree0 (posEnd,toks)) =
106 case Seq.viewl toks of
107 EmptyL -> plainifyIndentToken inh toks
108 t0:<_ -> plainifyIndentCell (posEnd,posCell t0) <> plainifyIndentToken inh toks
109 plainifyTreeCell inh (TreeN (posEnd,cell@(Cell pos _ _)) cs) =
110 plainifyIndentCell (posEnd,pos) <>
111 plainifyCellKey inh cell cs
113 plainifyIndentCell :: (Pos,Pos) -> TL.Text
114 plainifyIndentCell (Pos lineLast colLast,Pos line col)
116 TL.replicate (int64 $ line - (lineLast+1)) "\n" <>
117 TL.replicate (int64 $ col - 1) " "
118 | lineLast == line && colLast <= col =
119 TL.replicate (int64 $ col - colLast) " "
120 | otherwise = undefined
125 Trees (Pos,Cell Key) (Pos,Tokens) ->
127 plainifyCellKey inh (Cell _pos _posEnd key) cells = do
129 KeyColon n wh -> textKey n wh ":"
130 KeyGreat n wh -> textKey n wh ">"
131 KeyEqual n wh -> textKey n wh "="
132 KeyBar n wh -> textKey n wh "|"
133 KeyDash -> textKey "" "" "- "
134 KeyDashDash -> textKey "" "" "-- "
135 KeyLower name attrs ->
136 "<" <> tl name <> plainifyAttrs attrs <>
137 plainifyTreesCell inh cells
138 KeySection{} -> undefined
141 plainifyTreesCell inh cells
143 textKey :: Text -> White -> TL.Text -> TL.Text
144 textKey name wh mark =
145 tl name <> tl wh <> mark <>
146 plainifyTreesCell inh cells
150 Trees (Pos,Cell Key) (Pos,Tokens) ->
152 plainifyTreesCell inh = foldMap (plainifyTreeCell inh)
154 plainifyIndentToken :: Inh -> Tokens -> TL.Text
155 plainifyIndentToken _cfg (Seq.viewl -> EmptyL) = ""
156 plainifyIndentToken inh toks@(Seq.viewl -> Cell pos _ _ :< _) =
157 goTokens toks `S.evalState` linePos pos
159 indent = TL.replicate (int64 $ columnPos pos - 1) " "
160 go :: Cell Token -> S.State Int TL.Text
165 let lines = Text.splitOn "\n" txt
166 S.put (lnum - 1 + L.length lines)
170 (l0:ls) -> tl l0 <> mconcat ((\l -> "\n"<>indent<>tl l)<$>ls)
171 TokenTag v -> return $ "#"<>tl v
175 then tl $ Text.pack ['\\',c]
177 TokenLink lnk -> return $ tl lnk
178 TokenPair grp ts -> do
180 return $ tl o<>ts'<>tl c
181 where (o,c) = pairBorders grp ts
182 goTokens :: Tokens -> S.State Int TL.Text
185 return $ foldr (<>) mempty ts'
187 plainifyAttrs :: Attrs -> TL.Text
188 plainifyAttrs = foldMap plainifyAttr
190 plainifyAttr :: (Text,Attr) -> TL.Text
191 plainifyAttr (attr_white,Attr{..}) =
200 plainifyToken :: Token -> TL.Text
201 plainifyToken (TokenPlain txt) = tl txt
202 plainifyToken (TokenTag v) = "#"<>tl v
203 plainifyToken (TokenEscape c) = TL.singleton c -- tl $ Text.pack ['\\',c]
204 plainifyToken (TokenLink lnk) = tl lnk
205 plainifyToken (TokenPair grp t) = tl o<>plainifyTokens t<>tl c
206 where (o,c) = pairBorders grp t
208 plainifyTokens :: Tokens -> TL.Text
209 plainifyTokens ts = foldMap (plainifyToken . unCell) ts