1 {-# LANGUAGE DuplicateRecordFields #-}
2 {-# LANGUAGE FlexibleInstances #-}
3 {-# LANGUAGE FlexibleContexts #-}
4 {-# LANGUAGE OverloadedStrings #-}
5 {-# OPTIONS_GHC -fno-warn-orphans #-}
6 module Hdoc.DTC.Index where
8 import Control.Category
9 import Control.Monad (Monad(..))
11 import Data.Char (Char)
12 import Data.Default.Class (Default(..))
13 import Data.Foldable (Foldable(..), concat)
14 import Data.Function (($), const)
15 import Data.Functor ((<$>))
16 import Data.Map.Strict (Map)
17 import Data.Maybe (Maybe(..), maybe)
18 import Data.Monoid (Monoid(..))
19 import Data.Semigroup (Semigroup(..))
20 import Data.Sequence ((|>))
21 import Data.TreeMap.Strict (TreeMap(..))
22 import Data.TreeSeq.Strict (Tree(..), tree0)
23 import qualified Data.Char as Char
24 import qualified Data.List as List
25 import qualified Data.Map.Strict as Map
26 import qualified Data.Sequence as Seq
27 import qualified Data.Strict.Maybe as Strict
28 import qualified Data.Text.Lazy as TL
29 import qualified Data.TreeMap.Strict as TreeMap
30 -- import qualified Data.TreeSeq.Strict as TreeSeq
32 import Hdoc.DTC.Document
33 import qualified Hdoc.XML as XML
36 type PathWord = TreeMap.Path Word
38 pathFromWords :: Words -> Maybe PathWord
40 case ws >>= unSpace of
41 p:ps | not (TL.null p) -> Just (TreeMap.path p ps)
49 type Irefs = TreeMap Word [Anchor]
51 irefsOfTerms :: Terms -> Irefs
52 irefsOfTerms = TreeMap.fromList const . (>>= f) . concat
55 f ws = maybe [] (\p -> [(p,[])]) $ pathFromWords ws
57 indexifyWords :: XML.Pos -> Irefs -> Words -> (Irefs, Plain)
58 indexifyWords section = go mempty
60 go :: Plain -> Irefs -> Words -> (Irefs, Plain)
65 go (acc |> tree0 (PlainText " ")) irefs next
67 case goWords irefs [] inp of
68 Nothing -> go (acc |> tree0 (PlainText w)) irefs next
69 Just (anch, ls, ns, rs) ->
70 let term = List.reverse ls in
71 let lines = Seq.fromList $ tree0 . PlainText . plainifyWord <$> term in
72 go (acc |> Tree PlainIref{term, anchor=Just anch} lines) rs ns
76 Maybe (Anchor, Words, Words, Irefs)
77 goWords m@(TreeMap irefsByWord) prev inp =
80 curr@Space : next -> goWords m (curr:prev) next
81 curr@(Word w) : next ->
82 case Map.lookup w irefsByWord of
84 Just nod@TreeMap.Node{..} ->
85 let prev' = curr:prev in
88 | null node_descendants -> Nothing
90 (<$> goWords node_descendants prev' next) $ \(anch, ls, ns, rs) ->
91 (anch, ls, ns, TreeMap $
92 Map.insert w nod{TreeMap.node_descendants = rs} irefsByWord)
94 case goWords node_descendants prev' next of
96 let count = case anchs of [] -> def; Anchor{count=c}:_ -> succNat1 c in
97 let anch = Anchor{count, section} in
98 Just (anch, prev', next, TreeMap $
99 Map.insert w nod{TreeMap.node_value = Strict.Just $ anch:anchs} irefsByWord)
100 Just (anch, ls, ns, rs) ->
101 Just (anch, ls, ns, TreeMap $
102 Map.insert w nod{TreeMap.node_descendants = rs} irefsByWord)
104 wordify :: TL.Text -> Words
105 wordify = List.reverse . go []
107 go :: Words -> TL.Text -> Words
109 case TL.span Char.isAlphaNum t of
111 case TL.span Char.isSpace t of
115 Just (c,r) -> go (Word (TL.singleton c) : acc) r
116 (_s,r) -> go (Space : acc) r
117 (w,r) -> go (Word w : acc) r
119 plainifyWord :: WordOrSpace -> TL.Text
124 plainifyWords :: Words -> TL.Text
125 plainifyWords = TL.concat . (plainifyWord <$>)
127 termsByChar :: Terms -> Map Char Terms
129 foldr (\aliases acc ->
131 (Word w:_):_ | not (TL.null w) ->
133 (Char.toUpper $ TL.index w 0)