1 {-# LANGUAGE DuplicateRecordFields #-}
2 {-# LANGUAGE FlexibleInstances #-}
3 {-# LANGUAGE FlexibleContexts #-}
4 {-# LANGUAGE OverloadedStrings #-}
5 {-# OPTIONS_GHC -fno-warn-orphans #-}
6 module Hdoc.DTC.Anchor where
8 import Control.Applicative (Applicative(..))
9 import Control.Category
10 import Control.Monad (Monad(..))
12 import Data.Char (Char)
13 import Data.Default.Class (Default(..))
14 import Data.Foldable (Foldable(..), concat)
15 import Data.Function (($), const)
16 import Data.Functor ((<$>))
17 import Data.Map.Strict (Map)
18 import Data.Maybe (Maybe(..), maybe)
19 import Data.Monoid (Monoid(..))
20 import Data.Semigroup (Semigroup(..))
21 import Data.Sequence ((|>))
22 import Data.Traversable (Traversable(..))
23 import Data.TreeMap.Strict (TreeMap(..))
24 import Data.TreeSeq.Strict (Tree(..), tree0)
25 import qualified Control.Monad.Trans.State as S
26 import qualified Data.Char as Char
27 import qualified Data.List as List
28 import qualified Data.Map.Strict as Map
29 import qualified Data.Sequence as Seq
30 import qualified Data.Strict.Maybe as Strict
31 import qualified Data.Text.Lazy as TL
32 import qualified Data.TreeMap.Strict as TreeMap
33 -- import qualified Data.TreeSeq.Strict as TreeSeq
35 import Hdoc.DTC.Document
39 type Rrefs = Map Ident [Anchor]
42 -- | 'Note' by 'BodySection'.
43 type Notes = Map PosPath [Note]
48 , note_content :: [Para]
49 } -- deriving (Eq,Show)
53 { state_section :: Pos
54 , state_irefs :: Irefs
55 , state_rrefs :: Rrefs
56 , state_notes :: Notes
59 instance Default State where
62 , state_irefs = mempty
68 -- * Class 'Anchorify'
69 class Anchorify a where
70 anchorify :: a -> S.State State a
71 instance Anchorify a => Anchorify (Maybe a) where
72 anchorify = traverse anchorify
73 instance Anchorify Body where
74 anchorify = traverse anchorify
75 instance Anchorify (Tree BodyNode) where
80 before@State{state_section} <- S.get
81 S.put before{state_section = pos}
82 t <- Tree <$> anchorify n <*> anchorify ts
84 S.put after{state_section}
86 BodyBlock{} -> tree0 <$> anchorify n
87 instance Anchorify BodyNode where
93 <*> traverse anchorify judgments
94 BodyBlock b -> BodyBlock <$> anchorify b
95 instance Anchorify Block where
97 BlockPara p -> BlockPara <$> anchorify p
98 b@BlockBreak{} -> return b
99 b@BlockToC{} -> return b
100 b@BlockToF{} -> return b
101 b@BlockIndex{} -> return b
104 <$> traverse anchorify blocks
106 BlockFigure pos type_ attrs
107 <$> anchorify mayTitle
108 <*> traverse anchorify paras
109 BlockReferences{..} ->
110 BlockReferences pos attrs
111 <$> traverse anchorify refs
113 BlockJudges pos attrs
114 <$> traverse anchorify jury
116 BlockGrades pos attrs
117 <$> traverse anchorify scale
118 instance Anchorify Para where
120 ParaItem{..} -> ParaItem <$> anchorify item
121 ParaItems{..} -> ParaItems pos attrs <$> traverse anchorify items
122 instance Anchorify ParaItem where
124 ParaPlain plain -> ParaPlain <$> anchorify plain
125 ParaOL items -> ParaOL <$> traverse anchorify items
126 ParaUL items -> ParaUL <$> traverse (traverse anchorify) items
127 ParaQuote{..} -> ParaQuote type_ <$> traverse anchorify paras
128 p@ParaArtwork{} -> return p
129 p@ParaComment{} -> return p
130 ParaJudgment j -> ParaJudgment <$> anchorify j
131 instance Anchorify ListItem where
132 anchorify ListItem{..} = ListItem name <$> traverse anchorify paras
133 instance Anchorify Judgment where
134 anchorify Judgment{..} =
135 Judgment judges grades importance
136 <$> anchorify question
137 <*> traverse anchorify choices
138 instance Anchorify Plain where
139 anchorify = traverse anchorify
140 instance Anchorify (Tree PlainNode) where
141 anchorify (Tree n ts) = do
145 | not $ null state_irefs
146 , Just words <- pathFromWords term
147 , Strict.Just anchs <- TreeMap.lookup words state_irefs -> do
148 let count = case anchs of [] -> def; Anchor{count=c}:_ -> succNat1 c
149 let anch = Anchor{count, section=state_section}
151 { state_irefs = TreeMap.insert const words (anch:anchs) state_irefs }
152 Tree PlainIref{term, anchor=Just anch}
153 <$> traverse anchorify ts
155 | not $ null state_irefs -> do
156 let (irefs,para) = indexifyWords state_section state_irefs (wordify txt)
158 { state_irefs = irefs }
159 return $ Tree PlainGroup para
161 let notes = Map.findWithDefault [] (pos_Ancestors state_section) state_notes
163 { state_notes = Map.insert (pos_Ancestors state_section) (Note state_note note:notes) state_notes
164 , state_note = succNat1 state_note }
165 Tree PlainNote{number=Just state_note, note}
166 <$> traverse anchorify ts -- NOTE: normally ts is empty anyway
168 let anchs = Map.findWithDefault [] to state_rrefs
169 let count = case anchs of [] -> def; Anchor{count=c}:_ -> succNat1 c
170 let anch = Anchor{count, section=state_section}
172 { state_rrefs = Map.insert to (anch:anchs) state_rrefs }
173 Tree PlainRref{anchor=Just anch, to}
174 <$> traverse anchorify ts
175 _ -> Tree n <$> traverse anchorify ts
176 instance Anchorify Title where
177 anchorify (Title p) = Title <$> anchorify p
178 instance Anchorify Reference where
180 instance Anchorify Choice where
181 anchorify Choice{..} =
184 <*> traverse anchorify opinions
185 instance Anchorify Opinion where
186 anchorify Opinion{..} =
187 Opinion judge grade importance
188 <$> anchorify comment
189 instance Anchorify Grade where
190 anchorify Grade{..} =
191 Grade pos name color isDefault
193 instance Anchorify Judge where
194 anchorify Judge{..} =
197 <*> pure defaultGrades