File: Hoogle.hs

package info (click to toggle)
lambdabot 4.2.3.2-4
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 5,584 kB
  • sloc: haskell: 10,102; ansic: 76; makefile: 7
file content (62 lines) | stat: -rw-r--r-- 1,982 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
{-# LANGUAGE TemplateHaskell, MultiParamTypeClasses, TypeSynonymInstances, FlexibleInstances #-}

-- Copyright (c) 2004-5 Don Stewart - http://www.cse.unsw.edu.au/~dons
-- GPL version 2 or later (see http://www.gnu.org/copyleft/gpl.html)

-- | Talk to Neil Mitchell's `Hoogle' program
module Plugin.Hoogle (theModule) where

import Plugin

$(plugin "Hoogle")

type HoogleState = [String]

instance Module HoogleModule HoogleState where
    moduleDefState _ = return []
    moduleCmds   _ = ["hoogle", "hoogle+"]
    moduleHelp _ _ = "hoogle <expr>. Haskell API Search for either names, or types."

    process_ _ "hoogle" s = do
        o <- io (hoogle s)
        let (this,that) = splitAt 3 o
        writeMS that
        return [unlines this]

    process_ _ "hoogle+" _ = do
        this <- withMS $ \st write -> do
                        let (this,that) = splitAt 3 st
                        write that
                        return this
        return [unlines this]

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

hoogleBinary :: FilePath
hoogleBinary = "hoogle"

-- arbitrary cutoff point
cutoff :: Int
cutoff = -10

-- | Actually run the hoogle binary
hoogle :: String -> IO [String]
hoogle s = do
        let args = ["--count=20", s]
        (out,err,_) <- popen hoogleBinary args (Just "")
        return $ result out err

    where result [] [] = ["A Hoogle error occurred."]
          result [] ys = [ys]
          result xs _  =
                let xs' = map toPair $ lines xs
                    res = map snd $ filter ((>=cutoff) . fst) xs'
                in if null res
                   then ["No matches, try a more general search"]
                   else res

          toPair s' = let (res, meta)  = break (=='@') s'
                          rank = takeWhile (/=' ') . drop 2 $ meta
                      in case readM rank :: Maybe Int of
                         Just n  -> (n,res)
                         Nothing -> (0,res)