packages feed

hoogle-4.0: src/Hoogle/DataBase/Items.hs

module Hoogle.DataBase.Items where

import Control.Monad.State
import Data.Binary.Defer.Index
import General.Code
import Hoogle.TextBase.All
import Hoogle.TypeSig.All
import Hoogle.Item.All
import Data.Binary.Defer hiding (get,put)
import qualified Data.Binary.Defer as D

-- Invariant: Index Entry is by order of EntryScore

data Items = Items
    {packages :: Index Package
    ,modules :: Index Module
    ,entries :: Index Entry
    }

instance BinaryDefer Items where
    put (Items a b c) = put3 a b c
    get = do
        res@(Items a b c) <- get3 Items
        getDeferPut a
        getDeferPut b
        getDeferPut c
        return res


instance Show Items where
    show (Items a b c) = f "Packages" a ++ "\n" ++ f "Modules" b ++ "\n" ++ f "Entries" c
        where f header x = "== " ++ header ++ " ==\n\n" ++ show x


-- temporary state structure
data S = S {pkg :: Package
           ,modId :: Int
           ,mods :: [Module]
           ,modCur :: Maybe (Link Module)
           ,entId :: Int
           ,ents :: [(TextItem, Maybe Entry)]
           }

createItems :: [(TextItem,String)] -> (Items, [(TextItem, Maybe (Link Entry))])
createItems xs = res
    where
        res = unS $ execState (mapM (uncurry f) xs) s0
        s0 = S (Package "" "" "" "") 0 [] Nothing 0 []

        unS s = (Items (newIndex [pkg s])
                       ms
                       (newIndex $ mapMaybe (liftM fromLink . snd) esJ2)
                ,map (id *** const Nothing) esN ++ esJ2)
            where
                ms = newIndex $ reverse $ mods s
                (esJ,esN) = partition (isJust . snd) $ ents s
                esJ2 = zipWith (\i (ti,Just e) -> (ti,Just $ newLink i e)) [0..] $
                       sortOn (entryScore . fromJust . snd) esJ

        f :: TextItem -> String -> State S ()
        f i@ItemInstance{} _ = addTextItem i

        f i@(ItemAttribute "keyword" name) d = addEntry i False EntryKeyword d
                [Keyword "keyword",Text " ",Focus name]

        f i@(ItemAttribute name val) _ = do
            addTextItem i
            when (name == "package") $ modify $ \s -> s{pkg = (pkg s){packageName = val}}
            when (name == "version") $ modify $ \s -> s{pkg = (pkg s){packageVersion = val}}

        f i@(ItemModule xs) d = do
            s <- get
            let modI = modId s
                m = Module xs (newLink 0 $ lookupIndex (newLookup 0) (packages $ fst res))
            put s{modId = modI + 1, mods = m : mods s
                 ,modCur = Just $ newLink modI m}
            addEntry i True EntryModule d
                [Keyword "module", Text $ ' ' : concatMap (++ ".") (init xs), Focus (last xs)]

        f i d = addEntry i True EntryOther d (renderTextItem i)

        addTextItem i = modify $ \s -> s{ents = (i,Nothing) : ents s}

        addEntry i modu typ doc txt = do
            s <- get
            let entI = entId s
                e = Entry (if modu then modCur s else Nothing)
                          (headDef "" [i | Focus i <- txt])
                          txt typ (newHaddock doc)
            put $ s{entId = entI + 1, ents = (i, Just e) : ents s}