    -- |
    -- Module    : Where
    -- Copyright : 2003 Shae Erisson
    --
    -- License:     lGPL
    --
    -- Slightly specialised version of Where for associating projects with their urls.
    -- Code almost all copied.
    module Lambdabot.Plugin.Reference.Where (wherePlugin) where

    import Lambdabot.Plugin
    import Lambdabot.Util
    import qualified Data.ByteString.Char8 as P
    import Data.Char
    import qualified Data.Map as M

    type WhereState         = M.Map P.ByteString P.ByteString
    type WhereWriter        = WhereState -> Cmd Where ()
    type Where              = ModuleT WhereState LB

    wherePlugin :: Module (M.Map P.ByteString P.ByteString)
    wherePlugin :: Module (Map ByteString ByteString)
    wherePlugin = Module (Map ByteString ByteString)
    forall st. Module st
    newModule
        { moduleDefState  = return M.empty
        , moduleSerialize = Just mapPackedSerial

        , moduleCmds = return
            [ (command "where")
                { help = say "where <key>. Return element associated with key"
                , process = doCmd "where"
                }
            , (command "url")
                { help = say "url <key>. Return element associated with key"
                , process = doCmd "url"
                }
            , (command "what")
                { help = say "what <key>. Return element associated with key"
                , process = doCmd "what"
                }
            , (command "where+")
                { help = say "where+ <key> <elem>. Define an association"
                , process = doCmd "where+"
                }
            ]
        }

    doCmd :: String -> String -> Cmd Where ()
    doCmd :: String -> String -> Cmd Where ()
    doCmd String
    cmd String
    rest = (String -> Cmd Where ()
    forall (m :: * -> *). Monad m => String -> Cmd m ()
    say (String -> Cmd Where ()) -> Cmd Where String -> Cmd Where ()
    forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
    =<<) (Cmd Where String -> Cmd Where ())
    -> ((Map ByteString ByteString -> WhereWriter -> Cmd Where String)
        -> Cmd Where String)
    -> (Map ByteString ByteString -> WhereWriter -> Cmd Where String)
    -> Cmd Where ()
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Map ByteString ByteString -> WhereWriter -> Cmd Where String)
    -> Cmd Where String
    (LBState (Cmd Where)
     -> (LBState (Cmd Where) -> Cmd Where ()) -> Cmd Where String)
    -> Cmd Where String
    forall a.
    (LBState (Cmd Where)
     -> (LBState (Cmd Where) -> Cmd Where ()) -> Cmd Where a)
    -> Cmd Where a
    forall (m :: * -> *) a.
    MonadLBState m =>
    (LBState m -> (LBState m -> m ()) -> m a) -> m a
    withMS ((Map ByteString ByteString -> WhereWriter -> Cmd Where String)
     -> Cmd Where ())
    -> (Map ByteString ByteString -> WhereWriter -> Cmd Where String)
    -> Cmd Where ()
    forall a b. (a -> b) -> a -> b
    $ \Map ByteString ByteString
    factFM WhereWriter
    writer ->
        case String -> [String]
    words String
    rest of
            []         -> String -> Cmd Where String
    forall a. a -> Cmd Where a
    forall (m :: * -> *) a. Monad m => a -> m a
    return String
    "@where <key>, return element associated with key"
            (String
    fact:[String]
    dat) -> Map ByteString ByteString
    -> WhereWriter -> String -> String -> String -> Cmd Where String
    processCommand Map ByteString ByteString
    factFM WhereWriter
    writer
                                ((Char -> Char) -> String -> String
    forall a b. (a -> b) -> [a] -> [b]
    map Char -> Char
    toLower String
    fact) String
    cmd ([String] -> String
    unwords [String]
    dat)

    ------------------------------------------------------------------------

    processCommand :: WhereState -> WhereWriter
                   -> String -> String -> String -> Cmd Where String

    processCommand :: Map ByteString ByteString
    -> WhereWriter -> String -> String -> String -> Cmd Where String
    processCommand Map ByteString ByteString
    factFM WhereWriter
    writer String
    fact String
    cmd String
    dat = case String
    cmd of
            String
    "where"     -> String -> Cmd Where String
    forall a. a -> Cmd Where a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String -> Cmd Where String) -> String -> Cmd Where String
    forall a b. (a -> b) -> a -> b
    $ Map ByteString ByteString -> String -> String
    getWhere Map ByteString ByteString
    factFM String
    fact
            String
    "what"      -> String -> Cmd Where String
    forall a. a -> Cmd Where a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String -> Cmd Where String) -> String -> Cmd Where String
    forall a b. (a -> b) -> a -> b
    $ Map ByteString ByteString -> String -> String
    getWhere Map ByteString ByteString
    factFM String
    fact -- an alias
            String
    "url"       -> String -> Cmd Where String
    forall a. a -> Cmd Where a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (String -> Cmd Where String) -> String -> Cmd Where String
    forall a b. (a -> b) -> a -> b
    $ Map ByteString ByteString -> String -> String
    getWhere Map ByteString ByteString
    factFM String
    fact -- an alias
            String
    "where+"    -> Bool
    -> Map ByteString ByteString
    -> WhereWriter
    -> String
    -> String
    -> Cmd Where String
    updateWhere Bool
    True Map ByteString ByteString
    factFM WhereWriter
    writer String
    fact String
    dat
            String
    _           -> String -> Cmd Where String
    forall a. a -> Cmd Where a
    forall (m :: * -> *) a. Monad m => a -> m a
    return String
    "Unknown command."

    getWhere :: WhereState -> String -> String
    getWhere :: Map ByteString ByteString -> String -> String
    getWhere Map ByteString ByteString
    fm String
    fact =
        case ByteString -> Map ByteString ByteString -> Maybe ByteString
    forall k a. Ord k => k -> Map k a -> Maybe a
    M.lookup (String -> ByteString
    P.pack String
    fact) Map ByteString ByteString
    fm of
            Maybe ByteString
    Nothing -> String
    "I know nothing about " String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    fact String -> String -> String
    forall a. [a] -> [a] -> [a]
    ++ String
    "."
            Just ByteString
    x  -> ByteString -> String
    P.unpack ByteString
    x

    updateWhere :: Bool -> WhereState -> WhereWriter -> String -> String -> Cmd Where String
    updateWhere :: Bool
    -> Map ByteString ByteString
    -> WhereWriter
    -> String
    -> String
    -> Cmd Where String
    updateWhere Bool
    _guard Map ByteString ByteString
    factFM WhereWriter
    writer String
    fact String
    dat
        | String -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null String
    dat = do
            WhereWriter
    writer WhereWriter -> WhereWriter
    forall a b. (a -> b) -> a -> b
    $ ByteString
    -> Map ByteString ByteString -> Map ByteString ByteString
    forall k a. Ord k => k -> Map k a -> Map k a
    M.delete (String -> ByteString
    P.pack String
    fact) Map ByteString ByteString
    factFM
            String -> Cmd Where String
    forall a. a -> Cmd Where a
    forall (m :: * -> *) a. Monad m => a -> m a
    return String
    "It is forgotten."
        | Bool
    otherwise = do
            WhereWriter
    writer WhereWriter -> WhereWriter
    forall a b. (a -> b) -> a -> b
    $ ByteString
    -> ByteString
    -> Map ByteString ByteString
    -> Map ByteString ByteString
    forall k a. Ord k => k -> a -> Map k a -> Map k a
    M.insert (String -> ByteString
    P.pack String
    fact) (String -> ByteString
    P.pack String
    dat) Map ByteString ByteString
    factFM
            Cmd Where String
    forall (m :: * -> *). MonadIO m => m String
    randomSuccessMsg