1 {-# LANGUAGE FlexibleInstances #-}
2 {-# LANGUAGE OverloadedStrings #-}
3 {-# LANGUAGE ViewPatterns #-}
4 {-# OPTIONS_GHC -fno-warn-orphans #-}
5 module Language.TCT.Write.Plain where
7 import Control.Applicative (liftA2)
8 import Control.Monad (Monad(..))
10 import Data.Char (Char)
11 import Data.Default.Class (Default(..))
12 import Data.Eq (Eq(..))
13 import Data.Foldable (Foldable(..))
14 import Data.Function (($), (.))
15 import Data.Functor ((<$>))
16 import Data.Int (Int64)
17 import Data.Monoid (Monoid(..))
18 import Data.Ord (Ord(..))
19 import Data.Semigroup (Semigroup(..))
20 import Data.Sequence (ViewL(..))
21 import Data.String (String, IsString(..))
22 import Data.Text (Text)
23 import Data.TreeSeq.Strict (Tree(..),Trees)
24 import Data.Tuple (fst)
25 import Prelude (Num(..), undefined, Integral(..))
26 import Text.Show (Show(..))
27 import qualified Control.Monad.Trans.State as S
28 import qualified Data.Sequence as Seq
29 import qualified Data.Text as Text
30 import qualified Data.Text.Lazy as TL
31 import qualified Data.Text.Lazy.Builder as TLB
33 -- import Language.TCT.Tree
34 -- import Language.TCT.Token
35 import Language.TCT.Cell
36 import Language.TCT.Elem
37 import Language.TCT.Read.Token
40 type Plain = S.State State TLB.Builder
41 -- NOTE: To get maximum performance when building lazy Text values using a builder,
42 -- associate mappend calls to the right.
43 -- NOTE: (Semigroup.<>) associates to the right.
44 instance IsString Plain where
45 fromString = return . fromString
46 instance Semigroup Plain where
48 instance Monoid Plain where
52 runPlain :: Plain -> State -> TL.Text
53 runPlain p s = TLB.toLazyText $ fst $ S.runState p s
55 text :: Plainify a => State -> a -> TL.Text
56 text st a = runPlain (plainify a) st
61 { state_escape :: Bool -- FIXME: useful?
64 instance Default State where
71 class Plainify a where
72 plainify :: a -> Plain
73 instance Plainify Char where
74 plainify = return . TLB.singleton
75 instance Plainify String where
76 plainify = return . fromString
77 instance Plainify Text where
78 plainify = plainify . TL.fromStrict
79 instance Plainify TL.Text where
80 plainify = return . TLB.fromLazyText
81 instance Plainify a => Plainify (Cell a) where
82 plainify (Cell _bp@(Pos line col) ep a) = do
83 Pos lineLast colLast <- S.gets state_pos
85 _ | lineLast < line -> do
86 plainify $ Text.replicate (line - lineLast - 1) "\n"
87 plainify $ Text.replicate (col - 1) " "
88 _ | lineLast == line && colLast <= col -> do
89 plainify $ Text.replicate (col - colLast) " "
91 -- S.modify $ \s -> s{state_pos=bp}
92 S.modify $ \s -> s{state_pos=ep}
94 instance Plainify (Trees (Cell Key) Tokens) where
95 plainify = foldMap plainify
96 instance Plainify (Tree (Cell Key) Tokens) where
98 TreeN (Cell bp ep k) ts -> plainify (Cell bp ep (k,ts))
99 Tree0 ts -> plainify ts
100 instance Plainify (Key, Trees (Cell Key) Tokens) where
103 KeyColon n wh -> textKey n wh ":"
104 KeyGreat n wh -> textKey n wh ">"
105 KeyEqual n wh -> textKey n wh "="
106 KeyBar n wh -> textKey n wh "|"
107 KeyDash -> textKey "" "" "- "
108 KeyDashDash -> textKey "" "" "-- "
109 KeyLower name attrs ->
115 plainify (TL.replicate (int64 lvl) "#") <> " " <>
117 Tree0 title :< ts' ->
122 plainify ("./"::TL.Text) <>
126 textKey :: Text -> White -> TL.Text -> Plain
127 textKey name wh mark =
132 instance Plainify Tokens where
133 plainify = foldMap plainify
134 instance Plainify Token where
136 TreeN (Cell bp ep k) ts -> plainify (Cell bp ep (k,ts))
137 Tree0 ts -> plainify ts
138 instance Plainify (TokenKey, Tokens) where
140 plainify o <> plainify ts <> plainify c
141 where (o,c) = pairBorders k ts
142 instance Plainify TokenValue where
144 TokenPlain txt -> plainify txt
147 let lines = Text.splitOn "\n" txt
148 S.put (lnum - 1 + List.length lines)
152 (l0:ls) -> plainify l0 <> mconcat ((\l -> "\n"<>indent<>plainify l)<$>ls)
154 TokenTag v -> plainify '#'<>plainify v
156 esc <- S.gets state_escape
158 then plainify ['\\',c]
160 TokenLink lnk -> plainify lnk
161 instance Plainify Attrs where
162 plainify = foldMap plainify
163 instance Plainify (Text,Attr) where
164 plainify (attr_white,Attr{..}) =
165 mconcat $ plainify <$>
175 class Textify a where
176 plainify :: a -> TL.Text
177 instance Textify Text where
178 plainify = TL.fromStrict
179 instance Textify TL.Text where
181 instance Textify Tokens where
182 plainify = foldMap plainify
183 instance Textify Token where
185 TreeN (unCell -> p) ts -> plainify o<>plainify ts<>plainify c
186 where (o,c) = pairBorders p ts
187 Tree0 (unCell -> t) ->
189 TokenPlain txt -> plainify txt
190 TokenTag v -> "#"<>plainify v
191 TokenEscape c -> TL.singleton c -- plainify $ Text.pack ['\\',c]
192 TokenLink lnk -> plainify lnk
197 plainifyIndentCell :: (Pos,Pos) -> Plain
198 plainifyIndentCell (Pos lineLast colLast,Pos line col)
201 TL.replicate (int64 $ line - (lineLast+1)) "\n" <>
202 TL.replicate (int64 $ col - 1) " "
203 | lineLast == line && colLast <= col =
205 TL.replicate (int64 $ col - colLast) " "
206 | otherwise = undefined
209 treeRackUpLeft :: Tree (Cell k) (Cell a) -> Tree (Cell k) (Cell a)
210 treeRackUpLeft t = go t
212 Pos l0 c0 = posTree t
215 (linePos pos - l0 + 1)
216 (columnPos pos - c0 + 1)
217 go :: Tree (Cell k) (Cell a) -> Tree (Cell k) (Cell a)
218 go (Tree0 (Cell pos posEnd c)) =
219 Tree0 $ Cell (rackUpLeft pos) (rackUpLeft posEnd) c
220 go (TreeN (Cell pos posEnd c) ts) =
222 (Cell (rackUpLeft pos) (rackUpLeft posEnd) c)
226 Trees (Cell k) Tokens ->
227 Trees (Pos,Cell k) (Pos,Tokens)
228 treePosLastCell t = S.evalState (go`mapM`t) (Pos 1 1)
230 go :: Tree (Cell k) Tokens ->
231 S.State Pos (Tree (Pos,Cell k) (Pos,Tokens))
236 return $ Tree0 (lastPos,ts)
239 return $ Tree0 (lastPos,ts)
244 return $ TreeN (lastPos,p) ts'
248 int64 :: Integral i => i -> Int64
249 int64 = fromInteger . toInteger