module Web.Action(actionWeb) where import CmdLine.All import Hoogle.All import Hoogle.Query.All import Hoogle.Item.All import Hoogle.Search.All import Numeric import General.Code import System.IO.Unsafe(unsafeInterleaveIO) import Web.Page import Web.Text import Text.ParserCombinators.Parsec import Data.TagStr import Data.Range import Data.Binary.Defer.Index import Data.Generics.Uniplate import Data.Time.Clock import Data.Time.Calendar import General.CGI(cgiArgs) import Paths_hoogle logFile = "log.txt" actionWeb :: CmdQuery -> IO () actionWeb q = do logMessage q res <- if Mode "suggest" `elem` queryFlags q then do putStr "Content-type: application/json\n\n" runSuggest q else do putStr "Content-type: text/html\n\n" (skipped,dbs) <- loadDataBases q return $ unlines $ header (escapeHTML $ queryText q) ++ runQuery dbs q ++ footer putStrLn res when (Debug `elem` queryFlags q) $ writeFile "temp.htm" res sequence_ [writeFile x res | Output x <- queryFlags q] logMessage :: CmdQuery -> IO () logMessage q = do time <- getCurrentTime cgi <- liftM (fromMaybe []) cgiArgs appendFile logFile $ (++ "\n") $ unwords $ [showGregorian (utctDay time) ,show (queryText q)] ++ ["?" ++ a ++ "=" ++ c ++ b ++ c | (a,b) <- cgi, let c = ['\"' | any isSpace b]] runSuggest :: CmdQuery -> IO String runSuggest CmdQuery{query=Right Query{scope=[], names=[x], typeSig=Nothing}} = do root <- getDataDir db <- loadDataBase $ root "default.hoo" let res = take 8 $ completions db x return $ "[" ++ show x ++ "," ++ show res ++ "]" runSuggest _ = return "" -- is the package not something that might go wrong safePackage :: String -> Bool safePackage = all $ \x -> isAlphaNum x || x `elem` "-_" -- return the databases you loaded, and those you can't -- guarantees not to actually load the databases unless necessary -- TODO: Should say which databases are ignored loadDataBases :: CmdQuery -> IO ([String], [DataBase]) loadDataBases CmdQuery{query=Right q} = do let pkgs = nub [x | PlusPackage x <- scope q, safePackage x] files = if null pkgs then ["default"] else pkgs root <- getDataDir files <- filterM doesFileExist $ map (\x -> root x <.> "hoo") files dbs <- unsafeInterleaveIO $ mapM loadDataBase files return ([], dbs) loadDataBases _ = return ([], []) -- TODO: Should escape the query text runQuery :: [DataBase] -> CmdQuery -> [String] runQuery dbs CmdQuery{queryText = text, query = Left err} = ["

Parse error in user query

" ,"

" ," Query: " +& pre ++ "" +& post2 ++ "
" ,"

" ," Error: " +& drop 1 (dropWhile (/= ':') $ show err) ++ "
" ,"

" ," For information on what queries should look like, see the" ," user manual." ,"

" ] where (pre,post) = splitAt (sourceColumn (errorPos err) - 1) text post2 = if null post then concat (replicate 3 " ") else post runQuery dbs q | not $ usefulQuery $ fromRight $ query q = welcome runQuery dbs cq@CmdQuery{query = Right q, queryFlags = flags} = ["

Searching for " ++ qstr ++ "

"] ++ ["

" ++ showTagHTML (transform qurl sug) ++ "

" | Just sug <- [suggestQuery dbs q]] ++ if null res then ["

No results found

"] else [""] ++ concatMap (uncurry renderRes) pre ++ insertMore (concatMap (uncurry renderRes) now) ++ [moreResults | not $ null post] ++ ["
"] where start = headDef 0 [i-1 | Start i <- flags] count = headDef 20 [n | Count n <- flags] res = zip [0..] $ searchRange (rangeStartCount 0 (start+count+1)) dbs q (pre,res2) = splitAt start res (now,post) = splitAt count res2 moreResults = "Show more results" urlMore = "?hoogle=" +% queryText cq ++ "&start=" ++ show (start+count+1) ++ "#more" qstr = unwords $ ["" +& n ++ "" | n <- names q] ++ ["::" | names q /= [] && isJust (typeSig q)] ++ [showTagHTML (renderEntryText view $ renderTypeSig t) | Just t <- [typeSig q]] view = [ArgPosNum i i | i <- [0..10]] qurl (TagHyperlink url x) | "query:" `isPrefixOf` url = TagHyperlink ("?hoogle=" +% drop 6 url) x qurl x = x -- insert where you can insertMore :: [String] -> [String] insertMore [] = [] insertMore (x:xs) = f x : xs where f ('>':xs) | not $ " Result -> [String] renderRes i r = [tr $ modname ++ td "ans" (href urlEnt $ showTagHTMLWith url text) ,tr $ pkgname ++ td "doc" docs] where ent = fromLink $ resultEntry r (modu,text,_) = renderResult r modname = td "mod" $ maybe "" (href urlMod . showModule) modu pkgname = td "pkg" $ href urlPkg $ packageName $ fromLink $ entryPackage ent docs = ("
" ++ "") +? (showTagHTML $ renderHaddock $ entryDocs ent) +? "
" urlPkg = entryPackageURL ent urlMod = entryModuleURL ent urlEnt = entryURL ent url (TagHyperlink _ x) | null urlEnt = Just $ "" ++ showTagHTML x ++ "" | otherwise = Just $ "" ++ showTagHTML x ++ "" url _ = Nothing tr x = "" ++ x ++ "" td c x = "" ++ x ++ "" href url x = if null url then x else "" ++ x ++ ""