ghc-mod (empty) → 0.1.0
raw patch · 9 files changed
+685/−0 lines, 9 filesdep +basedep +haskell-src-extsdep +parsecsetup-changed
Dependencies added: base, haskell-src-exts, parsec, process
Files
- GHCMod.hs +234/−0
- LICENSE +29/−0
- Setup.hs +2/−0
- elisp/Makefile +17/−0
- elisp/ghc-comp.el +218/−0
- elisp/ghc-doc.el +59/−0
- elisp/ghc-func.el +52/−0
- elisp/ghc.el +45/−0
- ghc-mod.cabal +29/−0
+ GHCMod.hs view
@@ -0,0 +1,234 @@+module Main where++import Control.Exception hiding (try)+import Data.Char+import Data.List+import Language.Haskell.Exts.Extension+import Language.Haskell.Exts.Parser hiding (parse)+import Language.Haskell.Exts.Syntax+import Prelude hiding (catch)+import System.Console.GetOpt+import System.Environment+import System.IO+import System.Process+import Text.ParserCombinators.Parsec++----------------------------------------------------------------++usage :: String+usage = "ghc-mod version 0.1.0\n"+ ++ "Usage:\n"+ ++ "\t ghc-mod list\n"+ ++ "\t ghc-mod browse <module>\n"+ ++ "\t ghc-mod help\n"++----------------------------------------------------------------++data Options = Options { optToLisp :: Bool+ } deriving Show++defaultOptions :: Options+defaultOptions = Options { optToLisp = False+ }++argspec :: [OptDescr (Options -> Options)]+argspec = [ Option ['l'] ["tolisp"]+ (NoArg (\opts -> opts { optToLisp = True }))+ "print as a list of Lisp"+ ]++parseArgs :: [OptDescr (Options -> Options)] -> [String] -> (Options, [String])+parseArgs spec argv+ = case getOpt Permute spec argv of+ (o,n,[] ) -> (foldl (flip id) defaultOptions o, n)+ (_,_,errs) -> error (concat errs ++ usageInfo usage argspec)++----------------------------------------------------------------++main :: IO ()+main = flip catch handler $ do+ args <- getArgs+ let (opt,cmdArg) = parseArgs argspec args+ transform = if optToLisp opt then toLisp else toPlain+ ll <- case cmdArg !! 0 of+ cmd | cmd == "browse" -> browseModule $ cmdArg !! 1+ | cmd == "list" -> listModules+ _ -> error usage+ putStr $ transform $ nub $ sort $ ll+ where+ handler :: ErrorCall -> IO ()+ handler _ = putStr usage++----------------------------------------------------------------++browseModule :: String -> IO [String]+browseModule mname = do+ xs <- getSyntax mname+ let ys = preprocess xs+ return $ parseSyntax ys++getSyntax :: String -> IO String+getSyntax mname = do+ (inp,out,_,_) <- runInteractiveProcess "ghci" [] Nothing Nothing+ mapM_ setFD [inp,out]+ hPutStrLn inp ":set prompt \"\""+ hPutStrLn inp "1"+ hPutStrLn inp $ ":browse " ++ mname+ hPutStrLn inp ":set prompt \"Prelude>\""+ hPutStrLn inp ":quit"+ cs <- hGetContents out+ return $ unlines $ dropTailer $ dropHeader $ lines $ cs+ where+ isNotPrefixOf x y = not (x `isPrefixOf` y)+ dropHeader xs = tail $ dropWhile (isNotPrefixOf "Prelude>") xs+ dropTailer = takeWhile (isNotPrefixOf "Prelude>")+ setFD h = do+ hSetBinaryMode h False+ hSetBuffering h LineBuffering++parseSyntax :: String -> [String]+parseSyntax xs = do+ let mode = defaultParseMode { extensions = NewQualifiedOperators : ExplicitForall : glasgowExts }+ res = parseModuleWithMode mode xs+ case res of+ ParseOk x -> identifiers x+-- e -> error $ show e+ _ -> []++----------------------------------------------------------------++listModules :: IO [String]+listModules = do+ cs <- getDump+ return $ exposedModules cs++getDump :: IO String+getDump = do+ (_,hout,_,_) <- runInteractiveProcess "ghc-pkg" ["dump"] Nothing Nothing+ hGetContents hout++exposedModules :: String -> [String]+exposedModules cs = let ls = unfoldLines cs+ ns = values "name: " ls+ ms = values "exposed-modules: " ls+ zs = zip ns ms+ xs = filter (\(nm,_) -> nm `notElem` ["ghc", "ghc-prim", "rts", "integer"]) zs+ ss = map snd xs+ in filter (\x -> not ("GHC" `isPrefixOf` x)) $ concatMap words ss++values :: String -> [String] -> [String]+values tag ls = let len = length tag+ fs = filter (tag `isPrefixOf`) ls+ in map (drop len) fs++----------------------------------------------------------------++unfoldLines :: String -> [String]+unfoldLines xs = self xs+ where+ splitNL = break (== '\n')+ self "" = []+ self s = let (l, s') = splitNL s+ in case s' of+ [] -> [l]+ (_:' ':s'') -> cont s'' l+ (_:s'') -> l : self s''+ cont s a = let (l, s') = splitNL $ dropWhile (== ' ') s+ a' = a ++ " " ++ l+ in case s' of+ [] -> [a']+ (_:' ':s'') -> cont s'' a'+ (_:s'') -> a' : self s''++toLisp :: [String] -> String+toLisp ms = "(" ++ unwords quoted ++ ")\n"+ where+ quote x = "\"" ++ x ++ "\""+ quoted = map quote ms++toPlain :: [String] -> String+toPlain = unlines++----------------------------------------------------------------++preprocess :: String -> String+preprocess cs = case parse remove "remove" cs of+ Right a -> a+ Left e -> error $ show e++modName :: Parser String+modName = do c <- oneOf ['A'..'Z']+ cs <- many1 $ oneOf $ ['A'..'Z'] ++ ['a'..'z'] ++ ['0'..'9'] ++ "_'#"+ return $ c:cs++anyName :: Parser String+anyName = many1 $ oneOf $ ['A'..'Z'] ++ ['a'..'z'] ++ ['0'..'9'] ++ "_'#"++manyBefore :: Show tok => GenParser tok st a -> GenParser tok st [tok] -> GenParser tok st [a]+manyBefore p anchor = manyTill p (eof <|> try anc)+ where+ anc = do pos <- getPosition+ s <- anchor+ ss <- getInput+ setInput $ s ++ ss+ setPosition pos+ return ()++keyword :: Parser String+keyword = do ms <- modName+ char '.'+ return $ ms ++ ['.']++ghcName :: Parser String+ghcName = do keyword+ try sep <|> end+ where+ sep = do+ ws <- sepBy1 anyName (char '.')+ return $ last ws+ end = do+ endBy1 anyName (char '.')+ return ""++nonGhcName :: Parser String+nonGhcName = do c <- anyChar -- making this func non-empty+ cs <- manyBefore anyChar keyword+ return $ c:cs++remove :: Parser String+remove = do l1 <- try ghcName <|> return ""+ l2 <- nonGhcName+ ll <- many (do x <- ghcName+ y <- nonGhcName+ return $ x ++ y)+ return $ concat $ l1 : l2 : ll++----------------------------------------------------------------++identifiers :: Module -> [String]+identifiers (Module _ _ _ _ _ _ x) = filter hid $ concatMap decl x+ where+ hid = all (\c -> isAlphaNum c || elem c "_'")++decl :: Decl -> [String]+decl (TypeSig _ [x] _) = [name x]+decl (DataDecl _ _ _ x _ y _) = name x : (map qualConDecl y)+decl (ClassDecl _ _ x _ _ y) = name x : (map classDecl y)+decl (TypeDecl _ x _ _) = [name x]+decl x = [show x]++qualConDecl :: QualConDecl -> String+qualConDecl (QualConDecl _ _ _ x) = conDecl x++conDecl :: ConDecl -> String+conDecl (ConDecl (Ident x) _) = x+conDecl (InfixConDecl _ (Ident x) _) = x+conDecl x = show x++classDecl :: ClassDecl -> String+classDecl (ClsDecl x) = concat $ decl x -- xxx+classDecl x = show x++name :: Name -> String+name (Symbol x) = x+name (Ident x) = x
+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2009, IIJ Innovation Institute Inc.+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.+ * Redistributions in binary form must reproduce the above copyright+ notice, this list of conditions and the following disclaimer in+ the documentation and/or other materials provided with the+ distribution.+ * Neither the name of the copyright holders nor the names of its+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE+COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE+POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ elisp/Makefile view
@@ -0,0 +1,17 @@+SRCS = ghc.el ghc-func.el ghc-doc.el ghc-comp.el+EMACS = emacs+++TEMPFILE = temp.el++all: $(TEMPFILE) ghc.el+ $(EMACS) -batch -q -no-site-file -l ./$(TEMPFILE) -f ghc-compile++$(TEMPFILE):+ @echo '(setq load-path (cons "." load-path))' >> $(TEMPFILE)+ @echo '(defun ghc-compile () (mapcar (lambda (x) (byte-compile-file x)) (list ' >> $(TEMPFILE)+ @echo $(SRCS)| sed -e 's/\(ghc[^ ]*\.el\)/"\1"/g' >> $(TEMPFILE)+ @echo ')))' >> $(TEMPFILE)++clean:+ rm -f *.elc $(TEMPFILE)
+ elisp/ghc-comp.el view
@@ -0,0 +1,218 @@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; ghc-comp.el+;;;++;; Author: Kazu Yamamoto <Kazu@Mew.org>+;; Created: Sep 25, 2009++;;; Code:++(require 'ghc-func)++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; Customize Variables+;;;++(defvar ghc-module-command "ghc-mod")++(defvar ghc-idle-timer-interval 30)++;; must be sorted+(defvar ghc-reserved-keyword-for-bol '("class" "data" "default" "import" "infix" "infixl" "infixr" "instance" "main" "module" "newtype" "type"))++;; must be sorted+(defvar ghc-reserved-keyword '("case" "deriving" "do" "else" "if" "in" "let" "module" "of" "then" "where"))++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; Local Variables+;;;++(defvar ghc-window-configuration nil)++(mapc 'make-variable-buffer-local+ '(ghc-window-configuration))++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; Initializer+;;;++(defvar ghc-module-names nil) ;; completion for "import"+(defvar ghc-merged-keyword nil) ;; completion for type/func/...++(defvar ghc-keyword-prefix "ghc-keyword-")+(defvar ghc-keyword-Prelude nil)+(defvar ghc-loaded-module nil)++(defun ghc-comp-init ()+ (setq ghc-module-names (ghc-load-keyword "list"))+ (setq ghc-keyword-Prelude (ghc-load-keyword "browse" "Prelude"))+ (setq ghc-loaded-module '("Prelude"))+ (ghc-merge-keywords)+ (run-with-idle-timer ghc-idle-timer-interval 'repeat 'ghc-idle-timer))++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; Executing command+;;;++(defun ghc-load-keyword (&rest args)+ (if (not (ghc-which ghc-module-command))+ (message "%s not found" ghc-module-command)+ (ghc-read-lisp+ (lambda ()+ (let ((msg (mapconcat 'identity (cons ghc-module-command args) " ")))+ (message "Executing \"%s\"..." msg)+ (apply 'call-process-shell-command+ ghc-module-command nil t nil (cons "-l" args))+ (message "Executing \"%s\"...done" msg))))))++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; Completion+;;;++(defvar ghc-completion-buffer-name "*Completions*")++(defun ghc-complete ()+ (interactive)+ (if (ghc-should-scroll)+ (ghc-scroll-completion-buffer)+ (ghc-try-complete)))++(defun ghc-should-scroll ()+ (let ((window (ghc-completion-window)))+ (and (eq last-command this-command)+ window (window-live-p window) (window-buffer window)+ (buffer-name (window-buffer window)))))++(defun ghc-scroll-completion-buffer ()+ (let ((window (ghc-completion-window)))+ (with-current-buffer (window-buffer window)+ (if (pos-visible-in-window-p (point-max) window)+ (set-window-start window (point-min))+ (save-selected-window+ (select-window window)+ (scroll-up))))))++(defun ghc-completion-window ()+ (get-buffer-window ghc-completion-buffer-name 0))++(defun ghc-try-complete ()+ (let* ((end (point))+ (symbols (ghc-select-completion-symbol))+ (beg (ghc-completion-start-point))+ (pattern (buffer-substring-no-properties beg end))+ (completion (try-completion pattern symbols)))+ (cond+ ((eq completion t) ;; completed+ ) ;; do nothing+ ((null completion) ;; no completions+ (ding))+ ((not (string= pattern completion)) ;; ???+ (delete-region beg end)+ (insert completion)+ (ghc-reset-window-configuration))+ (t ;; multiple completions+ (let* ((list0 (all-completions pattern symbols))+ (list (sort list0 'string<)))+ (if (= (length list) 1)+ (ghc-reset-window-configuration)+ (ghc-save-window-configuration)+ (with-output-to-temp-buffer ghc-completion-buffer-name+ (display-completion-list list pattern))))))))++(defun ghc-save-window-configuration ()+ (unless (get-buffer-window ghc-completion-buffer-name)+ (setq ghc-window-configuration (current-window-configuration))))++(defun ghc-reset-window-configuration ()+ (when ghc-window-configuration+ (set-window-configuration ghc-window-configuration)+ (setq ghc-window-configuration nil)))++(defun ghc-select-completion-symbol ()+ (cond+ ((or (minibufferp)+ (save-excursion+ (beginning-of-line)+ (looking-at "import ")))+ ghc-module-names)+ ((or (bolp)+ (let ((end (point)))+ (save-excursion+ (beginning-of-line)+ (not (search-forward " " end t)))))+ ghc-reserved-keyword-for-bol)+ (t ghc-merged-keyword)))++(defun ghc-completion-start-point ()+ (save-excursion+ (let ((beg (save-excursion (beginning-of-line) (point))))+ (if (re-search-backward "[ (,`]" beg t)+ (1+ (point))+ beg))))+++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; Loading keywords+;;;++(add-hook 'find-file-hook 'ghc-load-module-buffer)++(defun ghc-load-module-buffer ()+ (interactive)+ (when (eq major-mode 'haskell-mode)+ (mapc 'ghc-load-module (ghc-gather-import-modules-buffer))))++(defun ghc-load-module (mod)+ (when (and (member mod ghc-module-names)+ (not (member mod ghc-loaded-module)))+ (let ((keywords (ghc-load-keyword "browse" mod)))+ (when (or (consp keywords) (null keywords))+ (set (intern (concat ghc-keyword-prefix mod)) keywords)+ (setq ghc-loaded-module (cons mod ghc-loaded-module))))))++(defun ghc-merge-keywords ()+ (let* ((modkeys (mapcar 'ghc-module-keyword ghc-loaded-module))+ (keywords (cons ghc-reserved-keyword modkeys))+ (uniq-sorted (sort (ghc-uniq-lol keywords) 'string<)))+ (setq ghc-merged-keyword uniq-sorted)))++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; Background Idle Timer+;;;++(defun ghc-idle-timer ()+ (dolist (mod (ghc-gather-import-modules))+ (ghc-load-module mod))+ (ghc-merge-keywords))++(defun ghc-gather-import-modules ()+ (let ((bufs (mapcar 'buffer-name (buffer-list)))+ ret)+ (save-excursion+ (dolist (buf bufs)+ (when (string-match "\\.hs$" buf)+ (set-buffer buf)+ (setq ret (cons (ghc-gather-import-modules-buffer) ret)))))+ (ghc-uniq-lol ret)))++(defun ghc-gather-import-modules-buffer ()+ (let (ret)+ (save-excursion+ (goto-char (point-min))+ (while (re-search-forward "^import *\\([^\n ]+\\)" nil t)+ (setq ret (cons (match-string-no-properties 1) ret))+ (forward-line)))+ ret))++(defun ghc-module-keyword (mod)+ (symbol-value (intern (concat ghc-keyword-prefix mod))))++(provide 'ghc-comp)
+ elisp/ghc-doc.el view
@@ -0,0 +1,59 @@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; ghc.el+;;;++;; Author: Kazu Yamamoto <Kazu@Mew.org>+;; Created: Sep 25, 2009++(require 'ghc-func)+(require 'ghc-comp)++;;; Code:++(defun ghc-browse-document (&optional haskell-org)+ (interactive "P")+ (let* ((mod0 (ghc-extract-module))+ (mod (ghc-read-module-name mod0))+ (pkg (ghc-resolve-package-name mod)))+ (ghc-display-document pkg mod haskell-org)))++(defun ghc-resolve-package-name (mod)+ (with-temp-buffer+ (call-process "ghc-pkg" nil t nil "find-module" "--simple-output" mod)+ (goto-char (point-min))+ (when (looking-at "^\\([^-]+\\)-")+ (match-string-no-properties 1))))++(defun ghc-resolve-document-path (pkg)+ (with-temp-buffer+ (call-process "ghc-pkg" nil t nil "field" pkg "haddock-html")+ (goto-char (point-min))+ (when (looking-at "^haddock-html: \\([^ \n]+\\)$")+ (match-string-no-properties 1))))++(defvar ghc-doc-local-format "file://%s/%s.html")+(defvar ghc-doc-hackage-format+ "http://hackage.haskell.org/packages/archive/%s/latest/doc/html/%s.html")++(defun ghc-display-document (pkg mod haskell-org)+ (when (and pkg mod)+ (let* ((mod- (ghc-replace-character mod ?. ?-))+ (url (if haskell-org+ (format ghc-doc-hackage-format pkg mod-)+ (format ghc-doc-local-format+ (ghc-resolve-document-path pkg) mod-))))+ (browse-url url))))++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;++(defvar ghc-input-map nil)++(unless ghc-input-map+ (setq ghc-input-map+ (if (boundp 'minibuffer-local-map)+ (copy-keymap minibuffer-local-map)+ (make-sparse-keymap)))+ (define-key ghc-input-map "\t" 'ghc-complete))++(provide 'ghc-doc)
+ elisp/ghc-func.el view
@@ -0,0 +1,52 @@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; ghc-func.el+;;;++;; Author: Kazu Yamamoto <Kazu@Mew.org>+;; Created: Sep 25, 2009++;;; Code:++(defun ghc-replace-character (string from to)+ "Replace characters equal to FROM to TO in STRING."+ (let ((ret (copy-sequence string)))+ (dotimes (cnt (length ret) ret)+ (if (char-equal (aref ret cnt) from)+ (aset ret cnt to)))))++(defun ghc-which (cmd)+ (catch 'loop+ (dolist (dir exec-path)+ (let ((path (expand-file-name cmd dir)))+ (if (file-exists-p path)+ (throw 'loop path))))))++(defun ghc-uniq-lol (lol)+ (let ((hash (make-hash-table :test 'equal))+ ret)+ (dolist (lst lol)+ (dolist (key lst)+ (puthash key key hash)))+ (maphash (lambda (key val) (setq ret (cons key ret))) hash)+ ret))++(defun ghc-read-lisp (func)+ (with-temp-buffer+ (funcall func)+ (goto-char (point-min))+ (condition-case nil+ (read (current-buffer))+ (error ()))))++(defun ghc-extract-module ()+ (interactive)+ (save-excursion+ (beginning-of-line)+ (if (looking-at "^\\(import\\|module\\) +\\(qualified +\\)?\\([^ (\n]+\\)")+ (match-string-no-properties 3))))++(defun ghc-read-module-name (def)+ (read-from-minibuffer "Module name: " def ghc-input-map))++(provide 'ghc-func)
+ elisp/ghc.el view
@@ -0,0 +1,45 @@+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; ghc.el+;;;++;; Author: Kazu Yamamoto <Kazu@Mew.org>+;; Created: Sep 25, 2009+;; Revised:++;; Put the following code to your "~/.emacs".+;;+;; (autoload 'ghc-init "ghc" nil t)+;; (add-hook 'haskell-mode-hook (lambda () (ghc-init)))++;;; Code:++(defvar ghc-version "0.1")++;; (require 'haskell-mode)+(require 'ghc-comp)+(require 'ghc-doc)++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; Customize Variables+;;;++(defvar ghc-completion-key "\e\t")+(defvar ghc-document-key "\e\C-d")+(defvar ghc-import-key "\e\C-m")++;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;+;;;+;;; Initializer+;;;++(defvar ghc-initialized nil)++(defun ghc-init ()+ (unless ghc-initialized+ (define-key haskell-mode-map ghc-completion-key 'ghc-complete)+ (define-key haskell-mode-map ghc-document-key 'ghc-browse-document)+ (define-key haskell-mode-map ghc-import-key 'ghc-load-module-buffer)+ (ghc-comp-init)+ (setq ghc-initialized t)))
+ ghc-mod.cabal view
@@ -0,0 +1,29 @@+Name: ghc-mod+Version: 0.1.0+Author: Kazu Yamamoto <kazu@iij.ad.jp>+Maintainer: Kazu Yamamoto <kazu@iij.ad.jp>+License: BSD3+License-File: LICENSE+Homepage: http://www.mew.org/~kazu/proj/ghc-mod/+Synopsis: Happy Haskell programming on Emacs+Description: This packages includes Elisp files+ and a Haskell command, "ghc-mod".+ "ghc*.el" enable completion of+ Haskell symbols on Emacs.+ "ghc-mod" is a backend of "ghc*.el".+ It lists up all installed modules+ or extracts names of functions, classes,+ and data declarations.+Category: Development+Cabal-Version: >= 1.6+Build-Type: Simple+Data-Dir: elisp+Data-Files: Makefile ghc.el ghc-func.el ghc-doc.el ghc-comp.el+Executable ghc-mod+ Main-Is: GHCMod.hs+ GHC-Options: -Wall+ Build-Depends: base >= 4.0 && < 10,+ parsec, process, haskell-src-exts+Source-Repository head+ Type: git+ Location: git://github.com/kazu-yamamoto/ghc-mod.git