module MagicHaskeller.ExpToHtml(expSigToString, refer, pprnn, annotateFree) where import Language.Haskell.TH as TH import Language.Haskell.TH.PprLib(to_HPJ_Doc) import Text.PrettyPrint import Network.URI(escapeURIString, isUnreserved) import Text.Html(stringToHtmlString) import MagicHaskeller.LibTH(fromPrelude, fromDataList, fromDataChar, fromDataMaybe, Primitive) import Data.Char(isAlpha, ord) import qualified Data.Map import Data.Generics expToString :: Exp -> String -- expToString = ('\n':) . pprint -- expToString = (\xs -> '(':xs++")
") . {- replaceRightArrow . -} pprint . annotateEverywhere -- simple and stupid expToString = (\xs -> '(':xs++")
") . filter (/='\n') . {- replaceRightArrow . -} pprint . annotateFree [] -- no buttons expSigToString predStr sig expr = mkButton predStr sig expr (pprnn (annotateFree [] expr)) -- with buttons pprnn = renderStyle style{mode=OneLineMode} . to_HPJ_Doc . pprExp 4 isAbsent :: TH.Exp -> Bool isAbsent (LamE pats e) = any (==WildP) pats || isAbsent e isAbsent (VarE name) = nameBase name == "const" isAbsent _ = False -- どうも ->をescapeする必要はないみたい.ま,<->みたいな演算子はescapeされているはずだし,みたいなコメントはないはずなので,→で置き換えても害はなさそう. -- と思ったけど,コピペするのに不便. replaceRightArrow "" = "" replaceRightArrow ('-':'>':xs) = "→"++replaceRightArrow xs replaceRightArrow (x:xs) = x : replaceRightArrow xs -- Unfortunately, w3m does not understand "++body ++ "
" mkButton predStr sig expr body = "   "++body++"" --
でやる場合、
をつけると改行しすぎ。 escapeQuote '\'' = "'" escapeQuote c = [c] annotateEverywhere = everywhere (mkT annotateName) annotateFree :: [String] -> TH.Exp -> TH.Exp annotateFree names v@(VarE name) | show name `elem` names = v | otherwise = VarE $ annotateName name annotateFree _ (ConE name) = ConE $ annotateName name annotateFree _ l@(LitE _) = l annotateFree names (AppE f e) = annotateFree names f `AppE` annotateFree names e annotateFree names (InfixE mbf op mbe) = InfixE (fmap (annotateFree names) mbf) (annotateFree names op) (fmap (annotateFree names) mbe) annotateFree names (LamE pats e) = LamE pats $ annotateFree (patsToNames pats names) e annotateFree names (TupE es) = TupE $ map (annotateFree names) es annotateFree names (CondE b t f) = CondE (annotateFree names b) (annotateFree names t) (annotateFree names f) annotateFree names (ListE es) = ListE $ map (annotateFree names) es annotateFree names (SigE e t) = SigE (annotateFree names e) t annotateFree names e = annotateEverywhere e -- bothered.... patsToNames [] = id patsToNames (p:ps) = patToNames p . patsToNames ps patToNames (VarP name) = (show name :) patToNames (TupP ps) = patsToNames ps patToNames (ConP _ ps) = patsToNames ps patToNames (InfixP p _ q) = patsToNames [p,q] patToNames (TildeP p) = patToNames p patToNames (AsP name p) = (show name :) . patToNames p patToNames (ListP ps) = patsToNames ps patToNames (SigP p _) = patToNames p patToNames _ = id -- 名前の1文字目が記号だとbinary operator扱いになってカッコがついてしまうので. annotateName :: TH.Name -> TH.Name annotateName name = case nameBase name of nameStr@(c:cs) | isAlpha c -> mkName $ c : refLink nameStr cs | c `elem` "=+!@#$%^&*-\\|:/?<>.~" -> mkName $ refLink nameStr $ stringToHtmlString nameStr _ -> name -- special names like [] and () refLink nameStr body = "" ++ body ++ "" refer str = case Data.Map.lookup str mapNameModule of Nothing -> referHoogle str Just f -> f str mapNameModule :: Data.Map.Map String (String->String) mapNameModule = Data.Map.fromList $ mkAssoc "base" "Prelude" preludeNameBases ++ mkAssoc "base" "Data-List" (primssToStrs fromDataList) ++ mkAssoc "base" "Data-Char" (primssToStrs fromDataChar) ++ mkAssoc "base" "Data-Maybe" (primssToStrs fromDataMaybe) mkAssoc package mod namebases = [ (str, referHackage package mod) | str <- namebases ] preludeNameBases = ["iterate", "!!", "id", "$", "const", ".", "flip", "subtract", "maybe", "foldr", "zipWith"] ++ -- These are not included in the component library, but introduced by MagicHaskeller.LibTH.postprocess. primssToStrs fromPrelude primssToStrs = map TH.nameBase . primsToNames . concat primsToNames :: [Primitive] -> [TH.Name] primsToNames ps = [ name | (_, VarE name, _) <- ps ] ++ [ name | (_, ConE name, _) <- ps ] ++ [ name | (_, _ `AppE` VarE name, _) <- ps ] -- ad hoc approach to the (flip foo) cases:) -- So far this should work: referHackage package modulename str = "http://hackage.haskell.org/packages/archive/"++package++"/latest/doc/html/"++modulename++".html#v:"++hackageEncode str hackageEncode cs@(a:_) | isAlpha a = cs | otherwise = concatMap (\c -> '-' : shows (ord c) "-") cs -- But this is more generic:) referHoogle str = "http://www.haskell.org/hoogle/?hoogle=" ++ escapeURIString isUnreserved str