Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add haskell-mode, pulled from github.

  • Loading branch information...
commit 97eba6deec5009a182ac49c17eb1962c8e61dafd 1 parent c7b676d
@alang9 authored
Showing with 12,405 additions and 0 deletions.
  1. +1 −0  emacs.d/plugins/haskell-mode/.gitignore
  2. +71 −0 emacs.d/plugins/haskell-mode/Makefile
  3. +142 −0 emacs.d/plugins/haskell-mode/NEWS
  4. +149 −0 emacs.d/plugins/haskell-mode/README.md
  5. +101 −0 emacs.d/plugins/haskell-mode/examples/init.el
  6. +49 −0 emacs.d/plugins/haskell-mode/fontlock.hs
  7. +82 −0 emacs.d/plugins/haskell-mode/ghc-core.el
  8. +173 −0 emacs.d/plugins/haskell-mode/haskell-align-imports.el
  9. +47 −0 emacs.d/plugins/haskell-mode/haskell-c.el
  10. +228 −0 emacs.d/plugins/haskell-mode/haskell-cabal.el
  11. +158 −0 emacs.d/plugins/haskell-mode/haskell-checkers.el
  12. +719 −0 emacs.d/plugins/haskell-mode/haskell-decl-scan.el
  13. +1,972 −0 emacs.d/plugins/haskell-mode/haskell-doc.el
  14. +654 −0 emacs.d/plugins/haskell-mode/haskell-font-lock.el
  15. +334 −0 emacs.d/plugins/haskell-mode/haskell-ghci.el
  16. +316 −0 emacs.d/plugins/haskell-mode/haskell-hugs.el
  17. +1,583 −0 emacs.d/plugins/haskell-mode/haskell-indent.el
  18. +906 −0 emacs.d/plugins/haskell-mode/haskell-indentation.el
  19. +460 −0 emacs.d/plugins/haskell-mode/haskell-interactive-mode.el
  20. +847 −0 emacs.d/plugins/haskell-mode/haskell-mode.el
  21. +92 −0 emacs.d/plugins/haskell-mode/haskell-move-nested.el
  22. +110 −0 emacs.d/plugins/haskell-mode/haskell-navigate-imports.el
  23. +147 −0 emacs.d/plugins/haskell-mode/haskell-package.el
  24. +809 −0 emacs.d/plugins/haskell-mode/haskell-process.el
  25. +271 −0 emacs.d/plugins/haskell-mode/haskell-session.el
  26. +252 −0 emacs.d/plugins/haskell-mode/haskell-show.el
  27. +199 −0 emacs.d/plugins/haskell-mode/haskell-simple-indent.el
  28. +444 −0 emacs.d/plugins/haskell-mode/haskell-site-file.el
  29. +78 −0 emacs.d/plugins/haskell-mode/haskell-sort-imports.el
  30. +24 −0 emacs.d/plugins/haskell-mode/haskell-string.el
  31. +170 −0 emacs.d/plugins/haskell-mode/indent.hs
  32. +815 −0 emacs.d/plugins/haskell-mode/inf-haskell.el
  33. +2 −0  emacs.d/plugins/haskell-mode/test.hs
View
1  emacs.d/plugins/haskell-mode/.gitignore
@@ -0,0 +1 @@
+*.elc
View
71 emacs.d/plugins/haskell-mode/Makefile
@@ -0,0 +1,71 @@
+EMACS = emacs
+
+ELFILES = \
+ haskell-c.el \
+ haskell-cabal.el \
+ haskell-decl-scan.el \
+ haskell-doc.el \
+ haskell-font-lock.el \
+ haskell-ghci.el \
+ haskell-hugs.el \
+ haskell-indent.el \
+ haskell-indentation.el \
+ haskell-checkers.el \
+ haskell-mode.el \
+ haskell-simple-indent.el \
+ haskell-sort-imports.el \
+ haskell-align-imports.el \
+ haskell-move-nested.el \
+ haskell-navigate-imports.el \
+ haskell-interactive-mode.el \
+ haskell-package.el \
+ haskell-process.el \
+ haskell-session.el \
+ haskell-string.el \
+ ghc-core.el \
+ inf-haskell.el
+
+ELCFILES = $(ELFILES:.el=.elc)
+# AUTOLOADS = $(PACKAGE)-startup.el
+AUTOLOADS = haskell-site-file.el
+
+%.elc: %.el
+ $(EMACS) --batch --eval '(setq load-path (cons "." load-path))' \
+ -f batch-byte-compile $<
+
+all: $(AUTOLOADS)
+
+compile: $(ELCFILES)
+
+info:
+ # No Texinfo file, sorry.
+
+######################################################################
+### don't look below ###
+######################################################################
+
+PACKAGE=haskell-mode
+
+$(AUTOLOADS): $(ELFILES)
+ [ -f $@ ] || echo ' ' >$@
+ $(EMACS) --batch --eval '(setq generated-autoload-file "'`pwd`'/$@")' -f batch-update-autoloads "."
+
+##
+
+VERSION = $(shell darcs show tags | head -n 1)
+TAG = $(shell echo v$(VERSION) | sed 's/\./\\\./g')
+TMP = $(shell echo $(PACKAGE)-$(VERSION))
+
+dist:
+ darcs get --lazy . $(TMP) &&\
+ cd $(TMP) &&\
+ rm -r _darcs &&\
+ sed -i 's/\$$Name: \$$/$(TAG)/g' * &&\
+ make $(AUTOLOADS) &&\
+ rm *~ &&\
+ darcs changes > ChangeLog &&\
+ rm Makefile &&\
+ cd .. &&\
+ tar czf $(PACKAGE)-$(VERSION).tar.gz $(PACKAGE)-$(VERSION) &&\
+ rm -rf $(PACKAGE)-$(VERSION) &&\
+ mv $(PACKAGE)-$(VERSION).tar.gz ../haskellmode-emacs-web/
View
142 emacs.d/plugins/haskell-mode/NEWS
@@ -0,0 +1,142 @@
+Changes since 2.7.0
+
+* Minimal indentation support for arrow syntax
+
+* Avoid opening a new inf-haskell window if one is already visible.
+ Windows on other virtual desktops or iconified frames don't count.
+
+* Force comint-process-echoes to nil
+
+* Autolaunch haskell-mode for files starting with #!/usr/bin/runghc
+ and similar
+
+* Added minimal major mode for parsing GHC core files, courtesy of Johan Tibell.
+ There is a corresponding Haskell menu entry.
+
+* Allow configuration of where-clause indentation; M-x customize-group
+ haskell-indentation.
+
+Changes since 2.6.4
+
+* fill-paragraph (M-q) now only affects comments, and correctly
+ handles Haddock commentary. adaptive-fill-mode is turned off, as it
+ was interfering.
+
+* Yet more unicode symbols
+
+* Better support for unicode encoding of haskell source files
+
+* mdo correctly indented
+
+* Indentation fixes, fixes to the fixes, and fixes to the fixes to the
+ fixes
+
+* New command: M-x haskell-check, calls (by default) hlint on the
+ current file. Also bound to C-c C-v.
+
+ You can also use the flymake minor mode with this.
+
+Changes since 2.5.1
+
+* Parser corrections for haskell-indentation and haskell-decl-scan
+
+* haskell-indentation: Pressing tab in the rightmost position now
+ moves to the leftmost, by default with a warning.
+
+* Typo fix: One haskell-indentation variable had ended up in the
+ haskell-ntation customize group.
+
+* haskell-hoogle aliased to hoogle, haskell-hayoo aliased to hayoo
+
+* Courtesy of Alex Ott:
+ - Additional unicode symbols for font-lock-symbols: () == /= >= <= !! && || sqrt
+ - M-x haskell-hayoo search added, opens using browse-url
+ - Bug-fix for inferior-haskell-type
+
+* If haskell-indentation errors out, it now fail-safes to inserting
+ a literal newline or deleting one character, for return and
+ backspace respectively.
+
+Changes since 2.4:
+
+* haskell-indentation, a new minor mode for indentation.
+
+Changes since 2.3:
+
+* Update license to GPLv3.
+
+* New derived major mode for .hsc files.
+
+* Removed the C-c C-r binding to reload a file. You can still call
+ inferior-haskell-reload-file (and/or bind it to your favorite key,
+ including C-c C-r) or you can now use C-u C-c C-l.
+
+* C-c C-d looks up the symbol at point in the Haddock docs.
+
+* Haddock comments are highlighted with font-lock-doc-face if it exists.
+
+* Use `tex' rather than `latex' for haskell-literate.
+
+* inf-haskell.el tries to find the root of the module hierarchy to determine
+ the root of a project (either by looking for a Cabal file or relying on
+ the `module' declaration line). If all works well, this will make C-c C-l
+ automatically switch to the root dir, so that dependencies in other
+ directories are automatically found. If it doesn't, complain and/or set
+ inferior-haskell-find-project-root to nil.
+
+* The new command haskell-hoogle helps you query Hoogle from Emacs.
+
+Changes since 2.2:
+
+* Trivial support for Cabal package description files.
+
+* Minor bug fixes.
+
+Changes since 2.1:
+
+* There are now commands to find type and info of identifiers by querying an
+ inferior haskell process. Available under C-c C-t, C-c C-i, and C-c M-.
+
+* Indentation now looks back further, until a line that has no indentation.
+ To recover the earlier behavior of stopping at the first empty line
+ instead, configure haskell-indent-look-past-empty-line.
+
+* inf-haskell can wait until a file load completes and jump directly to the
+ first error, like haskell-ghci and haskell-hugs used to do. See the var
+ inferior-haskell-wait-and-jump.
+
+Changes since 2.0:
+
+* inf-haskell uses ghci if hugs is absent.
+
+* Fix up some binding conflicts (C-c C-o in haskell-doc)
+
+* Many (hopefully minor) changes to the indentation.
+
+* New symbols in haskell-font-lock-symbols-alist.
+
+Changes since 1.45:
+
+* keybindings C-c <char> have been replaced by C-c C-<char> so as not
+ to collide with minor modes.
+
+* The following modules are now automatically activated without having to
+ add anything to haskell-mode-hook:
+ haskell-font-lock (just turn on global-font-lock-mode).
+ haskell-decl-scan (just bind `imenu' to some key).
+
+* In recent Emacsen, haskell-doc hooks into eldoc-mode.
+
+* haskell-hugs and haskell-ghci are superceded by inf-haskell.
+
+* Indentation rules have been improved when using layout inside parens/braces.
+
+* Symbols like -> and \ can be displayed as actual arrows and lambdas.
+ See haskell-font-lock-symbols.
+
+* Tweaks to the font-lock settings. Among other things paren-matching
+ with things like \(x,y) should work correctly now.
+
+* New maintainer <monnier@gnu.org>.
+
+# arch-tag: e50204f2-98e4-438a-bcd1-a49afde5efa5
View
149 emacs.d/plugins/haskell-mode/README.md
@@ -0,0 +1,149 @@
+Haskell Mode for Emacs
+----------------------
+
+This is the Haskell mode package for Emacs. Its use should be mostly
+self-explanatory if you're accustomed to Emacs.
+
+When Emacs is started up, it normally runs a file called ~/.emacs located in
+your home directory. This file should contain all of your personal
+customisations written as a series of Elisp commands. In order to install
+the Haskell mode, you have to tell Emacs where to find it. This is done by
+adding some commands to the init file.
+
+Installation
+------------
+
+- If you are using XEmacs, the haskell-mode package may be available for
+ installation through the XEmacs package UI.
+
+- If you are using Debian, you may be able to install the package
+ haskell-mode with a command like "apt-get install haskell-mode".
+
+Otherwise:
+
+- Download and unpack the basic mode and modules into a suitable directory,
+ e.g. ~/lib/emacs/haskell-mode/ where ~ stands for your home directory.
+
+- If you are using Emacs 21, you need an additional library, "syntax", from
+ a later version of Emacs. The one you can get as
+ http://cvs.savannah.gnu.org/viewcvs/*checkout*/emacs/emacs/lisp/emacs-lisp/syntax.el?rev=1.16
+ definitely works.
+
+- Assuming you have placed the basic mode haskell-mode.el and the modules
+ you want to use in the directory ~/lib/emacs/haskell-mode/, add the
+ following command to your init file (~/.emacs):
+
+ (load "~/lib/emacs/haskell-mode/haskell-site-file")
+
+ This only loads the bare-bones haskell-mode. To make it useful, you
+ need additional modules; you can use the haskell `customize-group`
+ to edit the Haskell mode hook or, if you prefer manual setup, try
+ adding the following lines according to which modules you want to use:
+
+ (add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode)
+ (add-hook 'haskell-mode-hook 'turn-on-haskell-indentation)
+ ;;(add-hook 'haskell-mode-hook 'turn-on-haskell-indent)
+ ;;(add-hook 'haskell-mode-hook 'turn-on-haskell-simple-indent)
+
+ Note that the three indentation modules are mutually exclusive - add at
+ most one. Note that the line of code for simple indentation is commented
+ out (using a preceeding `;`) in preference for the more advanced
+ indentation module. Installation is now complete!
+
+The other modules are automatically loaded when needed in the following way:
+
+- Font locking: just turn it on via `global-font-lock-mode` or do
+ `(add-hook 'haskell-mode-hook 'font-lock-mode)`
+
+- Declaration scanning: just use M-x imenu or bind `imenu` to a key. E.g.
+ `(global-set-key [(control meta down-mouse-3)] 'imenu)` or you can also add
+ it to the menubar with `(add-hook 'haskell-mode-hook 'imenu-add-menubar-index)`
+
+- Interaction with inferior Haskell interpreter: just hit C-c C-z or C-c C-l.
+
+
+Setup
+-----
+
+Normally, inf-haskell automatically finds ghci or hugs in your PATH, but if
+that's not the case (common under Windows), or if you need to specify your
+preference, just tell Emacs which executable to use with:
+
+ (setq haskell-program-name "/some/where/ghci.exe")
+
+If you want to use different settings when you use Cygwin Emacs and NTEmacs,
+you can test the value of `system-type`:
+
+ (setq haskell-program-name
+ (if (eq system-type 'cygwin)
+ "/cygdrive/c/ghc/ghc-6.8.1/bin/ghcii.sh"
+ "c:/ghc/ghc-6.8.1/bin/ghci.exe"))
+
+Note that Cygwin binaries tend to interact poorly with NTEmacs, especially
+w.r.t signal-handling.
+
+Setup for new interactive mode
+------------------------------
+
+A new mode for the REPL and GHCi sessions is called
+haskell-interactive-mode, it intends to replace inferior-haskell-mode,
+but comes with different features.
+
+There are new modules for handling the following things:
+
+* Separate sessions per Cabal project (haskell-session.el).
+* A new inferior Haskell process handling code (haskell-process.el).
+* New REPL (haskell-interactive-mode.el).
+* Bunch of new features based upon the above three things.
+
+To make use of them, try out the instructions in
+`examples/init.el`. WARNING: The features expressed in here are new
+and many are Linux-specific.
+
+Note: These features are entirely orthogonal to the older
+inferior-haskell-mode, and therefore keybindings which work for
+inferior-haskell-mode will not magically work for the above new
+modules.
+
+
+Customization
+-------------
+
+Most customizations are on the functionality of a particular module.
+See the documentation of that module for information on its
+customisation.
+
+There is also a [wiki page listing tips and
+tricks](http://www.haskell.org/haskellwiki/Haskell_mode_for_Emacs).
+
+Known problems
+--------------
+
+It seems that some versions of XEmacs come without the fsf-compat package
+(which provides functions such as `line-end-position`) and it seems that
+even if your XEmacs does have the fsf-compat package installed it does not
+autoload its part. Thus you may have to install the fsf-compat package and
+add `(require 'goto-addr)` in your .emacs.
+
+
+Multi-mode editing
+------------------
+
+For LaTeX-based literate Haskell, you might be interested in the
+multiple major mode package haskell-latex.el (plus multi-mode.el) from
+http://www.loveshack.ukfsn.org/emacs/.
+
+
+Support
+-------
+
+- [Github homepage](https://github.com/haskell/haskell-mode)
+- [Mailing list](http://projects.haskell.org/cgi-bin/mailman/listinfo/haskellmode-emacs)
+
+Contributing
+------------
+
+For submitting pull requests, please see the wiki
+[page on contributing](https://github.com/haskell/haskell-mode/wiki/Contributing). You
+don't have to follow this guide, but please make sure your pull
+requests are at least properly rebased and up to date.
View
101 emacs.d/plugins/haskell-mode/examples/init.el
@@ -0,0 +1,101 @@
+;; Sample file for the new session/process stuff
+;; Based on my own configuration. Well, it IS my configuration.
+;;
+;; NOTE: If you don't have cabal-dev, or you don't want to use it, you
+;; should change haskell-process-type (see below) to 'ghci.
+;;
+;; To merely TRY this mode (and for debugging), do the below:
+;;
+;; cd into haskell-mode's directory, and run
+;; $ emacs --load examples/init.el
+;;
+;; To get started, open a .hs file in one of your projects, and hit…
+;;
+;; 1. F5 to load the current file (and start a repl session), or
+;; 2. C-` to just start a REPL associated with this project, or
+;; 3. C-c C-c to build the cabal project (and start a repl session).
+
+;; Add the current dir for loading haskell-site-file.
+(add-to-list 'load-path ".")
+;; Always load via this. If you contribute you should run `make all`
+;; to regenerate this.
+(load "haskell-site-file")
+
+;; Customization
+(custom-set-variables
+ ;; Use cabal-dev for the GHCi session. Ensures our dependencies are in scope.
+ '(haskell-process-type 'cabal-dev)
+
+ ;; Use notify.el (if you have it installed) at the end of running
+ ;; Cabal commands or generally things worth notifying.
+ '(haskell-notify-p t)
+
+ ;; To enable tags generation on save.
+ '(haskell-tags-on-save t)
+
+ ;; To enable stylish on save.
+ '(haskell-stylish-on-save t))
+
+(add-hook 'haskell-mode-hook 'haskell-hook)
+(add-hook 'haskell-cabal-mode-hook 'haskell-cabal-hook)
+
+;; Haskell main editing mode key bindings.
+(defun haskell-hook ()
+ ;; Use simple indentation.
+ (turn-on-haskell-simple-indent)
+ (define-key haskell-mode-map (kbd "<return>") 'haskell-simple-indent-newline-same-col)
+ (define-key haskell-mode-map (kbd "C-<return>") 'haskell-simple-indent-newline-indent)
+
+ ;; Load the current file (and make a session if not already made).
+ (define-key haskell-mode-map [?\C-c ?\C-l] 'haskell-process-load-file)
+ (define-key haskell-mode-map [f5] 'haskell-process-load-file)
+
+ ;; Switch to the REPL.
+ (define-key haskell-mode-map [?\C-c ?\C-z] 'haskell-interactive-switch)
+ ;; “Bring” the REPL, hiding all other windows apart from the source
+ ;; and the REPL.
+ (define-key haskell-mode-map (kbd "C-`") 'haskell-interactive-bring)
+
+ ;; Build the Cabal project.
+ (define-key haskell-mode-map (kbd "C-c C-c") 'haskell-process-cabal-build)
+ ;; Interactively choose the Cabal command to run.
+ (define-key haskell-mode-map (kbd "C-c c") 'haskell-process-cabal)
+
+ ;; Get the type and info of the symbol at point, print it in the
+ ;; message buffer.
+ (define-key haskell-mode-map (kbd "C-c C-t") 'haskell-process-do-type)
+ (define-key haskell-mode-map (kbd "C-c C-i") 'haskell-process-do-info)
+
+ ;; Contextually do clever things on the space key, in particular:
+ ;; 1. Complete imports, letting you choose the module name.
+ ;; 2. Show the type of the symbol after the space.
+ (define-key haskell-mode-map (kbd "SPC") 'haskell-mode-contextual-space)
+
+ ;; Jump to the imports. Keep tapping to jump between import
+ ;; groups. C-u f8 to jump back again.
+ (define-key haskell-mode-map [f8] 'haskell-navigate-imports)
+
+ ;; Jump to the definition of the current symbol.
+ (define-key haskell-mode-map (kbd "M-.") 'haskell-mode-tag-find)
+
+ ;; Save the current buffer and generate etags (a TAGS file) for the
+ ;; whole project.
+ (define-key haskell-mode-map (kbd "C-x C-s") 'haskell-mode-save-buffer)
+
+ ;; Indent the below lines on columns after the current column.
+ (define-key haskell-mode-map (kbd "C-<right>")
+ (lambda ()
+ (interactive)
+ (haskell-move-nested 1)))
+ ;; Same as above but backwards.
+ (define-key haskell-mode-map (kbd "C-<left>")
+ (lambda ()
+ (interactive)
+ (haskell-move-nested -1))))
+
+;; Useful to have these keybindings for .cabal files, too.
+(defun haskell-cabal-hook ()
+ (define-key haskell-cabal-mode-map (kbd "C-c C-c") 'haskell-process-cabal-build)
+ (define-key haskell-cabal-mode-map (kbd "C-c c") 'haskell-process-cabal)
+ (define-key haskell-cabal-mode-map (kbd "C-`") 'haskell-interactive-bring)
+ (define-key haskell-cabal-mode-map [?\C-c ?\C-z] 'haskell-interactive-switch))
View
49 emacs.d/plugins/haskell-mode/fontlock.hs
@@ -0,0 +1,49 @@
+-- Comments are coloured brightly and stand out clearly.
+
+import qualified Foo as F hiding (toto)
+import qualified Foo hiding (toto)
+import qualified Foo as F (toto)
+import Foo as F hiding (toto)
+import Foo hiding (toto)
+import Foo as F (toto)
+
+hiding = 1
+qualified = 3
+as = 2
+
+repeat :: a -> [a]
+repeat xs = xs where xs = x:xs -- Keywords are also bright.
+
+head :: [a] -> a
+head (x:_) = x
+head [] = error "PreludeList.head: empty list" -- Strings are coloured softly.
+
+data Maybe a = Nothing | Just a -- Type constructors, data
+ deriving (Eq, Ord, Read, Show) -- constructors, class names
+ -- and module names are coloured
+ -- closer to ordinary code.
+
+recognize +++ infix :: Operator Declarations
+as `well` as = This Form
+(+) and this one = as well
+
+instance Show Toto where
+ fun1 arg1 = foo -- FIXME: `fun1' should be highlighted.
+
+constStr = "hello \
+ \asdgfasgf\
+ \asf"
+
+{-
+map :: (a -> b) -> [a] -> [b] -- Commenting out large sections of
+map f [] = [] -- code can be misleading. Coloured
+map f (x:xs) = f x : map f xs -- comments reveal unused definitions.
+-}
+
+-- Note: the least significant bit is the first element of the list
+bdigits :: Int -> [Int]
+bdigits 0 = [0]
+bdigits 1 = [1]
+bdigits n | n>1 = n `mod` 2 :
+
+-- arch-tag: a0d08cc2-4a81-4139-93bc-b3c6be0b5fb2
View
82 emacs.d/plugins/haskell-mode/ghc-core.el
@@ -0,0 +1,82 @@
+;;; ghc-core.el --- Syntax highlighting module for GHC Core
+
+;; Copyright (C) 2010 Johan Tibell
+
+;; Author: Johan Tibell <johan.tibell@gmail.com>
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Purpose:
+;;
+;; To make it easier to read GHC Core output by providing highlighting
+;; and removal of commonly ignored annotations.
+
+;;; Code:
+
+(require 'haskell-mode)
+(require 'haskell-font-lock)
+
+(defun ghc-core-clean-region (start end)
+ "Remove commonly ignored annotations and namespace
+prefixes in the given region."
+ (interactive "r")
+ (save-restriction
+ (narrow-to-region start end)
+ (goto-char (point-min))
+ (while (search-forward-regexp "GHC\.[^\.]*\." nil t)
+ (replace-match "" nil t))
+ (goto-char (point-min))
+ (while (flush-lines "^ *GblId *$" nil))
+ (goto-char (point-min))
+ (while (flush-lines "^ *LclId *$" nil))
+ (goto-char (point-min))
+ (while (flush-lines (concat "^ *\\[\\(?:Arity [0-9]+\\|NoCafRefs\\|"
+ "Str: DmdType\\|Worker \\)"
+ "\\([^]]*\\n?\\).*\\] *$") nil))
+ (goto-char (point-min))
+ (while (search-forward "Main." nil t) (replace-match "" nil t))))
+
+(defun ghc-core-clean-buffer ()
+ "Remove commonly ignored annotations and namespace
+prefixes in the current buffer."
+ (interactive)
+ (ghc-core-clean-region (point-min) (point-max)))
+
+;;;###autoload
+(defun ghc-core-create-core ()
+ "Compiled and load the current buffer as tidy core"
+ (interactive)
+ (save-buffer)
+ (let ((core-buffer (generate-new-buffer "ghc-core"))
+ (neh (lambda () (kill-buffer core-buffer))))
+ (add-hook 'next-error-hook neh)
+ (call-process "ghc" nil core-buffer nil "-c" "-ddump-simpl" "-O2" (buffer-file-name))
+ (display-buffer core-buffer)
+ (with-current-buffer core-buffer
+ (ghc-core-mode))
+ (remove-hook 'next-error-hook neh)))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.hcr\\'" . ghc-core-mode))
+
+;;;###autoload
+(define-derived-mode ghc-core-mode haskell-mode "GHC-Core"
+ "Major mode for GHC Core files.")
+
+(provide 'ghc-core)
+;;; ghc-core.el ends here
View
173 emacs.d/plugins/haskell-mode/haskell-align-imports.el
@@ -0,0 +1,173 @@
+;; haskell-align-imports.el — Align the import lines in a Haskell file.
+;; Copyright (C) 2010 Chris Done <chrisdone@gmail.com>
+
+;; Consider the following imports list:
+;;
+;; import One
+;; import Two as A
+;; import qualified Three
+;; import qualified Four as PRELUDE
+;; import Five (A)
+;; import Six (A,B)
+;; import qualified Seven (A,B)
+;; import "abc" Eight
+;; import "abc" Nine as TWO
+;; import qualified "abc" Ten
+;; import qualified "defg" Eleven as PRELUDE
+;; import "barmu" Twelve (A)
+;; import "zotconpop" Thirteen (A,B)
+;; import qualified "z" Fourteen (A,B)
+;; import Fifteen hiding (A)
+;; import Sixteen as TWO hiding (A)
+;; import qualified Seventeen hiding (A)
+;; import qualified Eighteen as PRELUDE hiding (A)
+;; import "abc" Nineteen hiding (A)
+;; import "abc" Twenty as TWO hiding (A)
+;;
+;; When haskell-align-imports is run within the same buffer, the
+;; import list is transformed to:
+;;
+;; import One
+;; import Two as A
+;; import qualified Three
+;; import qualified Four as PRELUDE
+;; import Five (A)
+;; import Six (A,B)
+;; import qualified Seven (A,B)
+;; import "abc" Eight
+;; import "abc" Nine as TWO
+;; import qualified "abc" Ten
+;; import qualified "defg" Eleven as PRELUDE
+;; import "barmu" Twelve (A)
+;; import "zotconpop" Thirteen (A,B)
+;; import qualified "z" Fourteen (A,B)
+;; import Fifteen hiding (A)
+;; import Sixteen as TWO hiding (A)
+;; import qualified Seventeen hiding (A)
+;; import qualified Eighteen as PRELUDE hiding (A)
+;; import "abc" Nineteen hiding (A)
+;; import "abc" Twenty as TWO hiding (A)
+
+;; This program is free software: you can redistribute it and/or
+;; modify it under the terms of the GNU General Public License as
+;; published by the Free Software Foundation, either version 3 of
+;; the License, or (at your option) any later version.
+
+;; This program is distributed in the hope that it will be
+;; useful, but WITHOUT ANY WARRANTY; without even the implied
+;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+;; PURPOSE. See the GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public
+;; License along with this program. If not, see
+;; <http://www.gnu.org/licenses/>.
+
+(require 'cl)
+
+(defvar haskell-align-imports-regexp
+ (concat "^\\(import[ ]+\\)"
+ "\\(qualified \\)?"
+ "[ ]*\\(\"[^\"]*\" \\)?"
+ "[ ]*\\([A-Za-z0-9_.']*.*\\)"))
+
+;;;###autoload
+(defun haskell-align-imports ()
+ "Align all the imports in the buffer."
+ (interactive)
+ (when (haskell-align-imports-line-match)
+ (save-excursion
+ (goto-char (point-min))
+ (let* ((imports (haskell-align-imports-collect))
+ (padding (haskell-align-imports-padding imports)))
+ (mapc (lambda (x)
+ (goto-char (cdr x))
+ (delete-region (point) (line-end-position))
+ (insert (haskell-align-imports-chomp
+ (haskell-align-imports-fill padding (car x)))))
+ imports))))
+ nil)
+
+(defun haskell-align-imports-line-match ()
+ "Try to match the current line as a regexp."
+ (let ((line (buffer-substring-no-properties (line-beginning-position)
+ (line-end-position))))
+ (if (string-match "^import " line)
+ line
+ nil)))
+
+(defun haskell-align-imports-collect ()
+ "Collect a list of mark / import statement pairs."
+ (let ((imports '()))
+ (while (not (or (equal (point) (point-max)) (haskell-align-imports-after-imports-p)))
+ (let ((line (haskell-align-imports-line-match-it)))
+ (when line
+ (let ((match
+ (haskell-align-imports-merge-parts
+ (loop for i from 1 to 8
+ collect (haskell-align-imports-chomp (match-string i line))))))
+ (setq imports (cons (cons match (line-beginning-position))
+ imports)))))
+ (forward-line))
+ imports))
+
+(defun haskell-align-imports-merge-parts (l)
+ "Merge together parts of an import statement that shouldn't be separated."
+ (let ((parts (apply #'vector l))
+ (join (lambda (ls)
+ (reduce (lambda (a b)
+ (concat a
+ (if (and (> (length a) 0)
+ (> (length b) 0))
+ " "
+ "")
+ b))
+ ls))))
+ (list (funcall join (list (aref parts 0)
+ (aref parts 1)
+ (aref parts 2)))
+ (aref parts 3)
+ (funcall join (list (aref parts 4)
+ (aref parts 5)
+ (aref parts 6)))
+ (aref parts 7))))
+
+(defun haskell-align-imports-chomp (str)
+ "Chomp leading and tailing whitespace from STR."
+ (if str
+ (replace-regexp-in-string "\\(^[[:space:]\n]*\\|[[:space:]\n]*$\\)" ""
+ str)
+ ""))
+
+(defun haskell-align-imports-padding (imports)
+ "Find the padding for each part of the import statements."
+ (reduce (lambda (a b) (mapcar* #'max a b))
+ (mapcar (lambda (x) (mapcar #'length (car x)))
+ imports)))
+
+(defun haskell-align-imports-fill (padding line)
+ "Fill an import line using the padding worked out from all statements."
+ (mapconcat #'identity
+ (mapcar* (lambda (pad part)
+ (if (> (length part) 0)
+ (concat part (make-string (- pad (length part)) ? ))
+ (make-string pad ? )))
+ padding
+ line)
+ " "))
+
+(defun haskell-align-imports-line-match-it ()
+ "Try to match the current line as a regexp."
+ (let ((line (buffer-substring-no-properties (line-beginning-position)
+ (line-end-position))))
+ (if (string-match haskell-align-imports-regexp line)
+ line
+ nil)))
+
+(defun haskell-align-imports-after-imports-p ()
+ "Are we after the imports list?"
+ (save-excursion
+ (goto-char (line-beginning-position))
+ (not (not (search-forward-regexp "\\( = \\|\\<instance\\>\\| :: \\)"
+ (line-end-position) t 1)))))
+
+(provide 'haskell-align-imports)
View
47 emacs.d/plugins/haskell-mode/haskell-c.el
@@ -0,0 +1,47 @@
+;;; haskell-c.el --- Major mode for *.hsc files
+
+;; Copyright (C) 2007 Stefan Monnier
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;;
+
+;;; Code:
+
+(require 'haskell-mode)
+(require 'haskell-font-lock)
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.hsc\\'" . haskell-c-mode))
+
+(defvar haskell-c-font-lock-keywords
+ `(("^#[ \t]*[[:alnum:]]+" (0 font-lock-preprocessor-face))
+ ,@haskell-font-lock-symbols))
+
+;;;###autoload
+(define-derived-mode haskell-c-mode haskell-mode "Haskell-C"
+ "Major mode for Haskell FFI files."
+ (set (make-local-variable 'font-lock-keywords)
+ (cons 'haskell-c-font-lock-keywords
+ (cdr font-lock-keywords))))
+
+(provide 'haskell-c)
+;; arch-tag: 51294c41-29f0-4599-9ce8-47fe2e7d3fd5
+;;; haskell-c.el ends here
View
228 emacs.d/plugins/haskell-mode/haskell-cabal.el
@@ -0,0 +1,228 @@
+;;; haskell-cabal.el --- Support for Cabal packages
+
+;; Copyright (C) 2007, 2008 Stefan Monnier
+
+;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Todo:
+
+;; - distinguish continued lines from indented lines.
+;; - indent-line-function.
+;; - outline-minor-mode.
+
+;;; Code:
+
+;; (defun haskell-cabal-extract-fields-from-doc ()
+;; (require 'xml)
+;; (require 'cl)
+;; (let ((section (completing-read
+;; "Section: "
+;; '("general-fields" "library" "executable" "buildinfo"))))
+;; (goto-char (point-min))
+;; (search-forward (concat "<sect3 id=\"" section "\">")))
+;; (let* ((xml (xml-parse-region
+;; (progn (search-forward "<variablelist>") (match-beginning 0))
+;; (progn (search-forward "</variablelist>") (point))))
+;; (varlist (remove-if-not 'consp (cddar xml)))
+;; (syms (mapcar (lambda (entry) (caddr (assq 'literal (assq 'term entry))))
+;; varlist))
+;; (fields (mapcar (lambda (sym) (substring-no-properties sym 0 -1)) syms)))
+;; fields))
+
+(eval-when-compile (require 'cl))
+
+(defconst haskell-cabal-general-fields
+ ;; Extracted with (haskell-cabal-extract-fields-from-doc "general-fields")
+ '("name" "version" "cabal-version" "license" "license-file" "copyright"
+ "author" "maintainer" "stability" "homepage" "package-url" "synopsis"
+ "description" "category" "tested-with" "build-depends" "data-files"
+ "extra-source-files" "extra-tmp-files"))
+
+(defconst haskell-cabal-library-fields
+ ;; Extracted with (haskell-cabal-extract-fields-from-doc "library")
+ '("exposed-modules"))
+
+(defconst haskell-cabal-executable-fields
+ ;; Extracted with (haskell-cabal-extract-fields-from-doc "executable")
+ '("executable" "main-is"))
+
+(defconst haskell-cabal-buildinfo-fields
+ ;; Extracted with (haskell-cabal-extract-fields-from-doc "buildinfo")
+ '("buildable" "other-modules" "hs-source-dirs" "extensions" "ghc-options"
+ "ghc-prof-options" "hugs-options" "nhc-options" "includes"
+ "install-includes" "include-dirs" "c-sources" "extra-libraries"
+ "extra-lib-dirs" "cc-options" "ld-options" "frameworks"))
+
+(defvar haskell-cabal-mode-syntax-table
+ (let ((st (make-syntax-table)))
+ ;; The comment syntax can't be described simply in syntax-table.
+ ;; We could use font-lock-syntactic-keywords, but is it worth it?
+ ;; (modify-syntax-entry ?- ". 12" st)
+ (modify-syntax-entry ?\n ">" st)
+ st))
+
+(defvar haskell-cabal-font-lock-keywords
+ ;; The comment syntax can't be described simply in syntax-table.
+ ;; We could use font-lock-syntactic-keywords, but is it worth it?
+ '(("^[ \t]*--.*" . font-lock-comment-face)
+ ("^ *\\([^ \t:]+\\):" (1 font-lock-keyword-face))
+ ("^\\(Library\\)[ \t]*\\({\\|$\\)" (1 font-lock-keyword-face))
+ ("^\\(Executable\\|Test-Suite\\|Benchmark\\)[ \t]+\\([^\n \t]*\\)"
+ (1 font-lock-keyword-face) (2 font-lock-function-name-face))
+ ("^\\(Flag\\)[ \t]+\\([^\n \t]*\\)"
+ (1 font-lock-keyword-face) (2 font-lock-constant-face))
+ ("^\\(Source-Repository\\)[ \t]+\\(head\\|this\\)"
+ (1 font-lock-keyword-face) (2 font-lock-constant-face))
+ ("^ *\\(if\\)[ \t]+.*\\({\\|$\\)" (1 font-lock-keyword-face))
+ ("^ *\\(}[ \t]*\\)?\\(else\\)[ \t]*\\({\\|$\\)"
+ (2 font-lock-keyword-face))))
+
+(defvar haskell-cabal-buffers nil
+ "List of Cabal buffers.")
+
+;; (defsubst* inferior-haskell-string-prefix-p (str1 str2)
+;; "Return non-nil if STR1 is a prefix of STR2"
+;; (eq t (compare-strings str2 nil (length str1) str1 nil nil)))
+4
+(autoload 'derived-mode-p "derived") ; Emacs 21
+
+(defun haskell-cabal-buffers-clean (&optional buffer)
+ (let ((bufs ()))
+ (dolist (buf haskell-cabal-buffers)
+ (if (and (buffer-live-p buf) (not (eq buf buffer))
+ (with-current-buffer buf (derived-mode-p 'haskell-cabal-mode)))
+ (push buf bufs)))
+ (setq haskell-cabal-buffers bufs)))
+
+(defun haskell-cabal-unregister-buffer ()
+ (haskell-cabal-buffers-clean (current-buffer)))
+
+;;;###autoload
+(add-to-list 'auto-mode-alist '("\\.cabal\\'" . haskell-cabal-mode))
+
+;;;###autoload
+(define-derived-mode haskell-cabal-mode fundamental-mode "Haskell-Cabal"
+ "Major mode for Cabal package description files."
+ (set (make-local-variable 'font-lock-defaults)
+ '(haskell-cabal-font-lock-keywords t t nil nil))
+ (add-to-list 'haskell-cabal-buffers (current-buffer))
+ (add-hook 'change-major-mode-hook 'haskell-cabal-unregister-buffer nil 'local)
+ (add-hook 'kill-buffer-hook 'haskell-cabal-unregister-buffer nil 'local)
+ (set (make-local-variable 'comment-start) "-- ")
+ (set (make-local-variable 'comment-start-skip) "\\(^[ \t]*\\)--[ \t]*")
+ (set (make-local-variable 'comment-end) "")
+ (set (make-local-variable 'comment-end-skip) "[ ]*\\(\\s>\\|\n\\)")
+)
+
+(defun haskell-cabal-get-setting (name)
+ (save-excursion
+ (let ((case-fold-search t))
+ (goto-char (point-min))
+ (when (re-search-forward
+ (concat "^" (regexp-quote name)
+ ":[ \t]*\\(.*\\(\n[ \t]+[ \t\n].*\\)*\\)")
+ nil t)
+ (let ((val (match-string 1))
+ (start 1))
+ (when (match-end 2) ;Multiple lines.
+ ;; The documentation is not very precise about what to do about
+ ;; the \n and the indentation: are they part of the value or
+ ;; the encoding? I take the point of view that \n is part of
+ ;; the value (so that values can span multiple lines as well),
+ ;; and that only the first char in the indentation is part of
+ ;; the encoding, the rest is part of the value (otherwise, lines
+ ;; in the value cannot start with spaces or tabs).
+ (while (string-match "^[ \t]\\(?:\\.$\\)?" val start)
+ (setq start (1+ (match-beginning 0)))
+ (setq val (replace-match "" t t val))))
+ val)))))
+
+;;;###autoload
+(defun haskell-cabal-get-dir ()
+ "Get the Cabal dir for a new project. Various ways of figuring this out,
+ and indeed just prompting the user. Do them all."
+ (let* ((file (haskell-cabal-find-file))
+ (dir (when file (file-name-directory file))))
+ (read-from-minibuffer
+ (format "Cabal dir%s: " (if file (format " (%s)" (file-relative-name file)) ""))
+ (or dir default-directory))))
+
+(defun haskell-cabal-compute-checksum (cabal-dir)
+ "Computes a checksum of the .cabal configuration files."
+ (let* ((cabal-file-paths (directory-files cabal-dir t "\\.cabal$"))
+ (get-file-contents (lambda (path)
+ (with-temp-buffer (insert-file-contents path)
+ (buffer-string))))
+ (cabal-file-contents (map 'list get-file-contents cabal-file-paths))
+ (cabal-config (reduce 'concat cabal-file-contents)))
+ (md5 cabal-config)))
+
+(defun haskell-cabal-find-file ()
+ "Return a buffer visiting the cabal file of the current directory, or nil."
+ (catch 'found
+ (let ((user (nth 2 (file-attributes default-directory)))
+ ;; Abbreviate, so as to stop when we cross ~/.
+ (root (abbreviate-file-name default-directory))
+ files)
+ (while (and root (equal user (nth 2 (file-attributes root))))
+ (if (setq files (directory-files root 'full "\\.cabal\\'"))
+ ;; Avoid the .cabal directory.
+ (dolist (file files (throw 'found nil))
+ (unless (file-directory-p file)
+ (throw 'found file)))
+ (if (equal root
+ (setq root (file-name-directory
+ (directory-file-name root))))
+ (setq root nil))))
+ nil)))
+
+(defun haskell-cabal-find-dir ()
+ "Use the .cabal file-finding function to find the Cabal dir."
+ (let ((file (haskell-cabal-find-file)))
+ (when file
+ (file-name-directory file))))
+
+(defvar haskell-cabal-commands
+ '("install"
+ "update"
+ "list"
+ "info"
+ "upgrade"
+ "fetch"
+ "unpack"
+ "check"
+ "sdist"
+ "upload"
+ "report"
+ "init"
+ "configure"
+ "build"
+ "copy"
+ "haddock"
+ "clean"
+ "hscolour"
+ "register"
+ "test"
+ "help"))
+
+(provide 'haskell-cabal)
+
+;; arch-tag: d455f920-5e4d-42b6-a2c7-4a7e84a05c29
+;;; haskell-cabal.el ends here
View
158 emacs.d/plugins/haskell-mode/haskell-checkers.el
@@ -0,0 +1,158 @@
+;;; haskell-checkers.el --- Emacs interface to haskell lint and style checkers
+
+;; Copyright 2009-2011 (c) Alex Ott, Liam O'Reilly
+;;
+;; Author: Alex Ott <alexott@gmail.com>, Liam O'Reilly <csliam@swansea.ac.uk>
+;; Keywords: haskell, lint, hlint, style scanner
+;; Requirements: hlint, scan, haskell
+;; Status: distributed under terms of GPL2 or above
+
+(require 'compile)
+
+(defgroup haskell-checkers nil
+ "Run HLint as inferior of Emacs, parse error messages."
+ :group 'tools
+ :group 'haskell)
+
+(defcustom hs-lint-command "hlint"
+ "The default lint command for \\[hlint]."
+ :type 'string
+ :group 'haskell-checkers)
+
+(defcustom hs-scan-command "scan"
+ "The default scan command for \\[hs-scan]."
+ :type 'string
+ :group 'haskell-checkers)
+
+(defcustom hs-scan-options ""
+ "The default options for \\[hs-scan]."
+ :type 'string
+ :group 'haskell-checkers)
+
+(defcustom hs-lint-options ""
+ "The default options for \\[hlint]."
+ :type 'string
+ :group 'haskell-checkers)
+
+(defcustom hs-checkers-save-files t
+ "Save modified files when run checker or not (ask user)"
+ :type 'boolean
+ :group 'haskell-checkers)
+
+(defcustom hs-checkers-replace-with-suggestions nil
+ "Replace user's code with suggested replacements (hlint only)"
+ :type 'boolean
+ :group 'haskell-checkers)
+
+(defcustom hs-checkers-replace-without-ask nil
+ "Replace user's code with suggested replacements automatically (hlint only)"
+ :type 'boolean
+ :group 'haskell-checkers)
+
+;; regex for replace HLint's suggestions
+;;
+;; ^\(.*?\):\([0-9]+\):\([0-9]+\): .*
+;; Found:
+;; \s +\(.*\)
+;; Why not:
+;; \s +\(.*\)
+
+(defvar hs-lint-regex
+ "^\\(.*?\\):\\([0-9]+\\):\\([0-9]+\\): .*[\n\C-m]Found:[\n\C-m]\\s +\\(.*\\)[\n\C-m]Why not:[\n\C-m]\\s +\\(.*\\)[\n\C-m]"
+ "Regex for HLint messages")
+
+(defun hs-checkers-make-short-string (str maxlen)
+ (if (< (length str) maxlen)
+ str
+ (concat (substring str 0 (- maxlen 3)) "...")))
+
+;; TODO: check, is it possible to adopt it for hs-scan?
+(defun hs-lint-replace-suggestions ()
+ "Perform actual replacement of HLint's suggestions"
+ (goto-char (point-min))
+ (while (re-search-forward hs-lint-regex nil t)
+ (let* ((fname (match-string 1))
+ (fline (string-to-number (match-string 2)))
+ (old-code (match-string 4))
+ (new-code (match-string 5))
+ (msg (concat "Replace '" (hs-checkers-make-short-string old-code 30)
+ "' with '" (hs-checkers-make-short-string new-code 30) "'"))
+ (bline 0)
+ (eline 0)
+ (spos 0)
+ (new-old-code ""))
+ (save-excursion
+ (switch-to-buffer (get-file-buffer fname))
+ (goto-line fline)
+ (beginning-of-line)
+ (setf bline (point))
+ (when (or hs-checkers-replace-without-ask
+ (yes-or-no-p msg))
+ (end-of-line)
+ (setf eline (point))
+ (beginning-of-line)
+ (setf old-code (regexp-quote old-code))
+ (while (string-match "\\\\ " old-code spos)
+ (setf new-old-code (concat new-old-code
+ (substring old-code spos (match-beginning 0))
+ "\\ *"))
+ (setf spos (match-end 0)))
+ (setf new-old-code (concat new-old-code (substring old-code spos)))
+ (remove-text-properties bline eline '(composition nil))
+ (when (re-search-forward new-old-code eline t)
+ (replace-match new-code nil t)))))))
+
+(defun hs-lint-finish-hook (buf msg)
+ "Function, that is executed at the end of HLint or scan execution"
+ (if hs-checkers-replace-with-suggestions
+ (hs-lint-replace-suggestions)
+ (next-error 1 t)))
+
+(defun hs-scan-finish-hook (buf msg)
+ "Function, that is executed at the end of hs-scan execution"
+ (next-error 1 t))
+
+(defun hs-scan-make-command (file)
+ "Generates command line for scan"
+ (concat hs-scan-command " " hs-scan-options " \"" file "\""))
+
+(defun hs-lint-make-command (file)
+ "Generates command line for scan"
+ (concat hs-lint-command " \"" file "\"" " " hs-lint-options))
+
+(defmacro hs-checkers-setup (type name)
+ "Performs setup of corresponding checker. Receives two arguments:
+type - checker's type (lint or scan) that is expanded into functions and hooks names
+name - user visible name for this mode"
+ (let ((nm (concat "hs-" (symbol-name type))))
+ `(progn
+;;;###autoload
+ (defvar ,(intern (concat nm "-setup-hook")) nil
+ ,(concat "Hook, that will executed before running " name))
+ (defun ,(intern (concat nm "-process-setup")) ()
+ "Setup compilation variables and buffer for `hlint'."
+ (run-hooks ',(intern (concat nm "-setup-hook"))))
+;;;###autoload
+ (define-compilation-mode ,(intern (concat nm "-mode")) ,name
+ ,(concat "Mode to check Haskell source code using " name)
+ (set (make-local-variable 'compilation-process-setup-function)
+ ',(intern (concat nm "-process-setup")))
+ (set (make-local-variable 'compilation-disable-input) t)
+ (set (make-local-variable 'compilation-scroll-output) nil)
+ (set (make-local-variable 'compilation-finish-functions)
+ (list ',(intern (concat nm "-finish-hook")))))
+;;;###autoload
+ (defun ,(intern nm) ()
+ ,(concat "Run " name " for current buffer with haskell source")
+ (interactive)
+ (save-some-buffers hs-checkers-save-files)
+ (compilation-start (,(intern (concat nm "-make-command")) buffer-file-name)
+ ',(intern (concat nm "-mode")))))
+ ))
+
+(hs-checkers-setup lint "HLint")
+(hs-checkers-setup scan "HScan")
+
+(provide 'haskell-checkers)
+
+;;; haskell-checkers.el ends here
View
719 emacs.d/plugins/haskell-mode/haskell-decl-scan.el
@@ -0,0 +1,719 @@
+;;; haskell-decl-scan.el --- Declaration scanning module for Haskell Mode
+
+;; Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 1997-1998 Graeme E Moss
+
+;; Author: 1997-1998 Graeme E Moss <gem@cs.york.ac.uk>
+;; Maintainer: Stefan Monnier <monnier@gnu.org>
+;; Keywords: declarations menu files Haskell
+;; URL: http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/CONTRIB/haskell-modes/emacs/haskell-decl-scan.el?rev=HEAD
+
+;; This file is not part of GNU Emacs.
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+;; Boston, MA 02111-1307, USA.
+
+
+;;; Commentary:
+
+;; Purpose:
+;;
+;; Top-level declarations are scanned and placed in a menu. Supports
+;; full Latin1 Haskell 1.4 as well as literate scripts.
+;;
+;;
+;; Installation:
+;;
+;; To turn declaration scanning on for all Haskell buffers under the
+;; Haskell mode of Moss&Thorn, add this to .emacs:
+;;
+;; (add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan)
+;;
+;; Otherwise, call `turn-on-haskell-decl-scan'.
+;;
+;;
+;; Customisation:
+;;
+;; None available so far.
+;;
+;;
+;; History:
+;;
+;; If you have any problems or suggestions, after consulting the list
+;; below, email gem@cs.york.ac.uk quoting the version of the library
+;; you are using, the version of Emacs you are using, and a small
+;; example of the problem or suggestion. Note that this library
+;; requires a reasonably recent version of Emacs.
+;;
+;; Uses `imenu' under Emacs, and `func-menu' under XEmacs.
+;;
+;; Version 1.2:
+;; Added support for LaTeX-style literate scripts.
+;;
+;; Version 1.1:
+;; Use own syntax table. Fixed bug for very small buffers. Use
+;; markers instead of pointers (markers move with the text).
+;;
+;; Version 1.0:
+;; Brought over from Haskell mode v1.1.
+;;
+;;
+;; Present Limitations/Future Work (contributions are most welcome!):
+;;
+;; . Declarations requiring information extending beyond starting line
+;; don't get scanned properly, eg.
+;; > class Eq a =>
+;; > Test a
+;;
+;; . Comments placed in the midst of the first few lexemes of a
+;; declaration will cause havoc, eg.
+;; > infixWithComments :: Int -> Int -> Int
+;; > x {-nastyComment-} `infixWithComments` y = x + y
+;; but are not worth worrying about.
+;;
+;; . Would be nice to scan other top-level declarations such as
+;; methods of a class, datatype field labels... any more?
+;;
+;; . Support for GreenCard?
+;;
+;; . Re-running (literate-)haskell-imenu should not cause the problems
+;; that it does. The ability to turn off scanning would also be
+;; useful. (Note that re-running (literate-)haskell-mode seems to
+;; cause no problems.)
+;;
+;; . Inconsistency: we define the start of a declaration in `imenu' as
+;; the start of the line the declaration starts on, but in
+;; `func-menu' as the start of the name that the declaration is
+;; given (eg. "class Eq a => Ord a ..." starts at "class" in `imenu'
+;; but at "Ord" in `func-menu'). This avoids rescanning of the
+;; buffer by the goto functions of `func-menu' but allows `imenu' to
+;; have the better definition of the start of the declaration (IMO).
+;;
+;; . `func-menu' cannot cope well with spaces in declaration names.
+;; This is unavoidable in "instance Eq Int" (changing the spaces to
+;; underscores would cause rescans of the buffer). Note though that
+;; `fume-prompt-function-goto' (usually bound to "C-c g") does cope
+;; with spaces okay.
+;;
+;; . Would like to extend the goto functions given by `func-menu'
+;; under XEmacs to Emacs. Would have to implement these
+;; ourselves as `imenu' does not provide them.
+;;
+;; . `func-menu' uses its own syntax table when grabbing a declaration
+;; name to lookup (why doesn't it use the syntax table of the
+;; buffer?) so some declaration names will not be grabbed correctly,
+;; eg. "fib'" will be grabbed as "fib" since "'" is not a word or
+;; symbol constituent under the syntax table `func-menu' uses.
+
+;; All functions/variables start with
+;; `(turn-(on/off)-)haskell-decl-scan' or `haskell-ds-'.
+
+;; The imenu support is based on code taken from `hugs-mode',
+;; thanks go to Chris Van Humbeeck.
+
+;; Version.
+
+;;; Code:
+
+(require 'haskell-mode)
+(require 'syntax nil t) ; Emacs 21 add-on
+
+;;###autoload
+;; As `cl' defines macros that `imenu' uses, we must require them at
+;; compile time.
+(eval-when-compile
+ (require 'cl)
+ (condition-case nil
+ (require 'imenu)
+ (error nil))
+ ;; It makes a big difference if we don't copy the syntax table here,
+ ;; as Emacs 21 does, but Emacs 22 doesn't.
+ (unless (eq (syntax-table)
+ (with-syntax-table (syntax-table) (syntax-table)))
+ (defmacro with-syntax-table (table &rest body)
+ "Evaluate BODY with syntax table of current buffer set to a copy of TABLE.
+The syntax table of the current buffer is saved, BODY is evaluated, and the
+saved table is restored, even in case of an abnormal exit.
+Value is what BODY returns."
+ (let ((old-table (make-symbol "table"))
+ (old-buffer (make-symbol "buffer")))
+ `(let ((,old-table (syntax-table))
+ (,old-buffer (current-buffer)))
+ (unwind-protect
+ (progn
+ (set-syntax-table ,table)
+ ,@body)
+ (save-current-buffer
+ (set-buffer ,old-buffer)
+ (set-syntax-table ,old-table))))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; General declaration scanning functions.
+
+(defalias 'haskell-ds-match-string
+ (if (fboundp 'match-string-no-properties)
+ 'match-string-no-properties
+ (lambda (num)
+ "As `match-string' except that the string is stripped of properties."
+ (format "%s" (match-string num)))))
+
+(defvar haskell-ds-start-keywords-re
+ (concat "\\(\\<"
+ "class\\|data\\|i\\(mport\\|n\\(fix\\(\\|[lr]\\)\\|stance\\)\\)\\|"
+ "module\\|primitive\\|type\\|newtype"
+ "\\)\\>")
+ "Keywords that may start a declaration.")
+
+(defvar haskell-ds-syntax-table
+ (let ((table (copy-syntax-table haskell-mode-syntax-table)))
+ (modify-syntax-entry ?\' "w" table)
+ (modify-syntax-entry ?_ "w" table)
+ (modify-syntax-entry ?\\ "_" table)
+ table)
+ "Syntax table used for Haskell declaration scanning.")
+
+
+(defun haskell-ds-get-variable (prefix)
+ "Return variable involved in value binding or type signature.
+Assumes point is looking at the regexp PREFIX followed by the
+start of a declaration (perhaps in the middle of a series of
+declarations concerning a single variable). Otherwise return nil.
+Point is not changed."
+ ;; I think I can now handle all declarations bar those with comments
+ ;; nested before the second lexeme.
+ (save-excursion
+ (with-syntax-table haskell-ds-syntax-table
+ (if (looking-at prefix) (goto-char (match-end 0)))
+ ;; Keyword.
+ (if (looking-at haskell-ds-start-keywords-re)
+ nil
+ (or ;; Parenthesized symbolic variable.
+ (and (looking-at "(\\(\\s_+\\))") (haskell-ds-match-string 1))
+ ;; General case.
+ (if (looking-at
+ (if (eq ?\( (char-after))
+ ;; Skip paranthesised expression.
+ (progn
+ (forward-sexp)
+ ;; Repeating this code and avoiding moving point if
+ ;; possible speeds things up.
+ "\\(\\'\\)?\\s-*\\(\\s_+\\|`\\(\\sw+\\)`\\)")
+ "\\(\\sw+\\)?\\s-*\\(\\s_+\\|`\\(\\sw+\\)`\\)"))
+ (let ((match2 (haskell-ds-match-string 2)))
+ ;; Weed out `::', `∷',`=' and `|' from potential infix
+ ;; symbolic variable.
+ (if (member match2 '("::" "" "=" "|"))
+ ;; Variable identifier.
+ (haskell-ds-match-string 1)
+ (if (eq (aref match2 0) ?\`)
+ ;; Infix variable identifier.
+ (haskell-ds-match-string 3)
+ ;; Infix symbolic variable.
+ match2))))
+ ;; Variable identifier.
+ (and (looking-at "\\sw+") (haskell-ds-match-string 0)))))))
+
+(defun haskell-ds-move-to-start-regexp (inc regexp)
+ "Move to beginning of line that succeeds/precedes (INC = 1/-1)
+current line that starts with REGEXP and is not in `font-lock-comment-face'."
+ ;; Making this defsubst instead of defun appears to have little or
+ ;; no effect on efficiency. It is probably not called enough to do
+ ;; so.
+ (while (and (= (forward-line inc) 0)
+ (or (not (looking-at regexp))
+ (eq (get-text-property (point) 'face)
+ 'font-lock-comment-face)))))
+
+(defun haskell-ds-move-to-start-regexp-skipping-comments (inc regexp)
+ "Like haskell-ds-move-to-start-regexp, but uses syntax-ppss to
+ skip comments"
+ (let (p)
+ (loop
+ do (setq p (point))
+ (haskell-ds-move-to-start-regexp inc regexp)
+ while (and (nth 4 (syntax-ppss))
+ (/= p (point))))))
+
+(defvar literate-haskell-ds-line-prefix "> ?"
+ "Regexp matching start of a line of Bird-style literate code.
+Current value is \"> \" as we assume top-level declarations start
+at column 3. Must not contain the special \"^\" regexp as we may
+not use the regexp at the start of a regexp string. Note this is
+only for `imenu' support.")
+
+(defvar haskell-ds-start-decl-re "\\(\\sw\\|(\\)"
+ "The regexp that starts a Haskell declaration.")
+
+(defvar literate-haskell-ds-start-decl-re
+ (concat literate-haskell-ds-line-prefix haskell-ds-start-decl-re)
+ "The regexp that starts a Bird-style literate Haskell declaration.")
+
+(defun haskell-ds-move-to-decl (direction bird-literate fix)
+ "General function for moving to the start of a declaration,
+either forwards or backwards from point, with normal or with Bird-style
+literate scripts. If DIRECTION is t, then forward, else backward. If
+BIRD-LITERATE is t, then treat as Bird-style literate scripts, else
+normal scripts. Returns point if point is left at the start of a
+declaration, and nil otherwise, ie. because point is at the beginning
+or end of the buffer and no declaration starts there. If FIX is t,
+then point does not move if already at the start of a declaration."
+ ;; As `haskell-ds-get-variable' cannot separate an infix variable
+ ;; identifier out of a value binding with non-alphanumeric first
+ ;; argument, this function will treat such value bindings as
+ ;; separate from the declarations surrounding it.
+ (let ( ;; The variable typed or bound in the current series of
+ ;; declarations.
+ name
+ ;; The variable typed or bound in the new declaration.
+ newname
+ ;; Hack to solve hard problem for Bird-style literate scripts
+ ;; that start with a declaration. We are in the abyss if
+ ;; point is before start of this declaration.
+ abyss
+ (line-prefix (if bird-literate literate-haskell-ds-line-prefix ""))
+ ;; The regexp to match for the start of a declaration.
+ (start-decl-re (if bird-literate
+ literate-haskell-ds-start-decl-re
+ haskell-ds-start-decl-re))
+ (increment (if direction 1 -1))
+ (bound (if direction (point-max) (point-min))))
+ ;; Change syntax table.
+ (with-syntax-table haskell-ds-syntax-table
+ ;; move to beginning of line that starts the "current
+ ;; declaration" (dependent on DIRECTION and FIX), and then get
+ ;; the variable typed or bound by this declaration, if any.
+ (let ( ;; Where point was at call of function.
+ (here (point))
+ ;; Where the declaration on this line (if any) starts.
+ (start (progn
+ (beginning-of-line)
+ ;; Checking the face to ensure a declaration starts
+ ;; here seems to be the only addition to make this
+ ;; module support LaTeX-style literate scripts.
+ (if (and (looking-at start-decl-re)
+ (not (eq (get-text-property (point) 'face)
+ 'font-lock-comment-face)))
+ (match-beginning 1)))))
+ (if (and start
+ ;; This complicated boolean determines whether we
+ ;; should include the declaration that starts on the
+ ;; current line as the "current declaration" or not.
+ (or (and (or (and direction (not fix))
+ (and (not direction) fix))
+ (>= here start))
+ (and (or (and direction fix)
+ (and (not direction) (not fix)))
+ (> here start))))
+ ;; If so, we are already at start of the current line, so
+ ;; do nothing.
+ ()
+ ;; If point was before start of a declaration on the first
+ ;; line of the buffer (possible for Bird-style literate
+ ;; scripts) then we are in the abyss.
+ (if (and start (bobp))
+ (setq abyss t)
+ ;; Otherwise we move to the start of the first declaration
+ ;; on a line preceding the current one, skipping comments
+ (haskell-ds-move-to-start-regexp-skipping-comments -1 start-decl-re))))
+ ;; If we are in the abyss, position and return as appropriate.
+ (if abyss
+ (if (not direction)
+ nil
+ (re-search-forward (concat "\\=" line-prefix) nil t)
+ (point))
+ ;; Get the variable typed or bound by this declaration, if any.
+ (setq name (haskell-ds-get-variable line-prefix))
+ (if (not name)
+ ;; If no such variable, stop at the start of this
+ ;; declaration if moving backward, or move to the next
+ ;; declaration if moving forward.
+ (if direction
+ (haskell-ds-move-to-start-regexp-skipping-comments 1 start-decl-re))
+ ;; If there is a variable, find the first
+ ;; succeeding/preceding declaration that does not type or
+ ;; bind it. Check for reaching start/end of buffer and
+ ;; comments.
+ (haskell-ds-move-to-start-regexp-skipping-comments increment start-decl-re)
+ (while (and (/= (point) bound)
+ (and (setq newname (haskell-ds-get-variable line-prefix))
+ (string= name newname)))
+ (setq name newname)
+ (haskell-ds-move-to-start-regexp-skipping-comments increment start-decl-re))
+ ;; If we are going backward, and have either reached a new
+ ;; declaration or the beginning of a buffer that does not
+ ;; start with a declaration, move forward to start of next
+ ;; declaration (which must exist). Otherwise, we are done.
+ (if (and (not direction)
+ (or (and (looking-at start-decl-re)
+ (not (string= name
+ ;; Note we must not use
+ ;; newname here as this may
+ ;; not have been set if we
+ ;; have reached the beginning
+ ;; of the buffer.
+ (haskell-ds-get-variable
+ line-prefix))))
+ (and (not (looking-at start-decl-re))
+ (bobp))))
+ (haskell-ds-move-to-start-regexp-skipping-comments 1 start-decl-re)))
+ ;; Store whether we are at the start of a declaration or not.
+ ;; Used to calculate final result.
+ (let ((at-start-decl (looking-at start-decl-re)))
+ ;; If we are at the beginning of a line, move over
+ ;; line-prefix, if present at point.
+ (if (bolp)
+ (re-search-forward (concat "\\=" line-prefix) (point-max) t))
+ ;; Return point if at the start of a declaration and nil
+ ;; otherwise.
+ (if at-start-decl (point) nil))))))
+
+(defun haskell-ds-bird-p ()
+ (and (boundp 'haskell-literate) (eq haskell-literate 'bird)))
+
+(defun haskell-ds-backward-decl ()
+ "Move backward to the first character that starts a top-level declaration.
+A series of declarations concerning one variable is treated as one
+declaration by this function. So, if point is within a top-level
+declaration then move it to the start of that declaration. If point
+is already at the start of a top-level declaration, then move it to
+the start of the preceding declaration. Returns point if point is
+left at the start of a declaration, and nil otherwise, ie. because
+point is at the beginning of the buffer and no declaration starts
+there."
+ (interactive)
+ (haskell-ds-move-to-decl nil (haskell-ds-bird-p) nil))
+
+(defun haskell-ds-forward-decl ()
+ "As `haskell-ds-backward-decl' but forward."
+ (interactive)
+ (haskell-ds-move-to-decl t (haskell-ds-bird-p) nil))
+
+(defun haskell-ds-generic-find-next-decl (bird-literate)
+ "Find the name, position and type of the declaration at or after point.
+Return ((NAME . (START-POSITION . NAME-POSITION)) . TYPE)
+if one exists and nil otherwise. The start-position is at the start
+of the declaration, and the name-position is at the start of the name
+of the declaration. The name is a string, the positions are buffer
+positions and the type is one of the symbols \"variable\", \"datatype\",
+\"class\", \"import\" and \"instance\"."
+ (let (;; The name, type and name-position of the declaration to
+ ;; return.
+ name
+ type
+ name-pos
+ ;; Buffer positions marking the start and end of the space
+ ;; containing a declaration.
+ start
+ end)
+ ;; Change to declaration scanning syntax.
+ (with-syntax-table haskell-ds-syntax-table
+ ;; Stop when we are at the end of the buffer or when a valid
+ ;; declaration is grabbed.
+ (while (not (or (eobp) name))
+ ;; Move forward to next declaration at or after point.
+ (haskell-ds-move-to-decl t bird-literate t)
+ ;; Start and end of search space is currently just the starting
+ ;; line of the declaration.
+ (setq start (point)
+ end (line-end-position))
+ (cond
+ ;; If the start of the top-level declaration does not begin
+ ;; with a starting keyword, then (if legal) must be a type
+ ;; signature or value binding, and the variable concerned is
+ ;; grabbed.
+ ((not (looking-at haskell-ds-start-keywords-re))
+ (setq name (haskell-ds-get-variable ""))
+ (if name
+ (progn
+ (setq type 'variable)
+ (re-search-forward (regexp-quote name) end t)
+ (setq name-pos (match-beginning 0)))))
+ ;; User-defined datatype declaration.
+ ((re-search-forward "\\=\\(data\\|newtype\\|type\\)\\>" end t)
+ (re-search-forward "=>" end t)
+ (if (looking-at "[ \t]*\\(\\sw+\\)")
+ (progn
+ (setq name (haskell-ds-match-string 1))
+ (setq name-pos (match-beginning 1))
+ (setq type 'datatype))))
+ ;; Class declaration.
+ ((re-search-forward "\\=class\\>" end t)
+ (re-search-forward "=>" end t)
+ (if (looking-at "[ \t]*\\(\\sw+\\)")
+ (progn
+ (setq name (haskell-ds-match-string 1))
+ (setq name-pos (match-beginning 1))
+ (setq type 'class))))
+ ;; Import declaration.
+ ((looking-at "import[ \t]+\\(qualified[ \t]+\\)?\\(\\(?:\\sw\\|.\\)+\\)")
+ (setq name (haskell-ds-match-string 2))
+ (setq name-pos (match-beginning 2))
+ (setq type 'import))
+ ;; Instance declaration.
+ ((re-search-forward "\\=instance[ \t]+" end t)
+ (re-search-forward "=>[ \t]+" end t)
+ ;; The instance "title" starts just after the `instance' (and
+ ;; any context) and finishes just before the _first_ `where'
+ ;; if one exists. This solution is ugly, but I can't find a
+ ;; nicer one---a simple regexp will pick up the last `where',
+ ;; which may be rare but nevertheless...
+ (setq name-pos (point))
+ (setq name (format "%s"
+ (buffer-substring
+ (point)
+ (progn
+ ;; Look for a `where'.
+ (if (re-search-forward "\\<where\\>" end t)
+ ;; Move back to just before the `where'.
+ (progn
+ (re-search-backward "\\s-where")
+ (point))
+ ;; No `where' so move to last non-whitespace
+ ;; before `end'.
+ (progn
+ (goto-char end)
+ (skip-chars-backward " \t")
+ (point)))))))
+ ;; If we did not manage to extract a name, cancel this
+ ;; declaration (eg. when line ends in "=> ").
+ (if (string-match "^[ \t]*$" name) (setq name nil))
+ (setq type 'instance)))
+ ;; Move past start of current declaration.
+ (goto-char end))
+ ;; If we have a valid declaration then return it, otherwise return
+ ;; nil.
+ (if name
+ (cons (cons name (cons (copy-marker start t) (copy-marker name-pos t)))
+ type)
+ nil))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Declaration scanning via `imenu'.
+
+(defun haskell-ds-create-imenu-index ()
+ "Function for finding `imenu' declarations in Haskell mode.
+Finds all declarations (classes, variables, imports, instances and
+datatypes) in a Haskell file for the `imenu' package."
+ ;; Each list has elements of the form `(INDEX-NAME . INDEX-POSITION)'.
+ ;; These lists are nested using `(INDEX-TITLE . INDEX-ALIST)'.
+ (let* ((bird-literate (haskell-ds-bird-p))
+ (index-alist '())
+ (index-class-alist '()) ;; Classes
+ (index-var-alist '()) ;; Variables
+ (index-imp-alist '()) ;; Imports
+ (index-inst-alist '()) ;; Instances
+ (index-type-alist '()) ;; Datatypes
+ ;; Variables for showing progress.
+ (bufname (buffer-name))
+ (divisor-of-progress (max 1 (/ (buffer-size) 100)))
+ ;; The result we wish to return.
+ result)
+ (goto-char (point-min))
+ ;; Loop forwards from the beginning of the buffer through the
+ ;; starts of the top-level declarations.
+ (while (< (point) (point-max))
+ (message "Scanning declarations in %s... (%3d%%)" bufname
+ (/ (- (point) (point-min)) divisor-of-progress))
+ ;; Grab the next declaration.
+ (setq result (haskell-ds-generic-find-next-decl bird-literate))
+ (if result
+ ;; If valid, extract the components of the result.
+ (let* ((name-posns (car result))
+ (name (car name-posns))
+ (posns (cdr name-posns))
+ (start-pos (car posns))
+ (type (cdr result))
+ ;; Place `(name . start-pos)' in the correct alist.
+ (sym (cdr (assq type
+ '((variable . index-var-alist)
+ (datatype . index-type-alist)
+ (class . index-class-alist)
+ (import . index-imp-alist)
+ (instance . index-inst-alist))))))
+ (set sym (cons (cons name start-pos) (symbol-value sym))))))
+ ;; Now sort all the lists, label them, and place them in one list.
+ (message "Sorting declarations in %s..." bufname)
+ (and index-type-alist
+ (push (cons "Datatypes"
+ (sort index-type-alist 'haskell-ds-imenu-label-cmp))
+ index-alist))
+ (and index-inst-alist
+ (push (cons "Instances"
+ (sort index-inst-alist 'haskell-ds-imenu-label-cmp))
+ index-alist))
+ (and index-imp-alist
+ (push (cons "Imports"
+ (sort index-imp-alist 'haskell-ds-imenu-label-cmp))
+ index-alist))
+ (and index-var-alist
+ (push (cons "Variables"
+ (sort index-var-alist 'haskell-ds-imenu-label-cmp))
+ index-alist))
+ (and index-class-alist
+ (push (cons "Classes"
+ (sort index-class-alist 'haskell-ds-imenu-label-cmp))
+ index-alist))
+ (message "Sorting declarations in %s...done" bufname)
+ ;; Return the alist.
+ index-alist))
+
+(defun haskell-ds-imenu-label-cmp (el1 el2)
+ "Predicate to compare labels in lists from `haskell-ds-create-imenu-index'."
+ (string< (car el1) (car el2)))
+
+(defun haskell-ds-imenu ()
+ "Install `imenu' for Haskell scripts."
+ (setq imenu-create-index-function 'haskell-ds-create-imenu-index)
+ (if (fboundp 'imenu-add-to-menubar)
+ (imenu-add-to-menubar "Declarations")))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Declaration scanning via `func-menu'.
+
+(defun haskell-ds-func-menu-next (buffer)
+ "Non-literate Haskell version of `haskell-ds-generic-func-menu-next'."
+ (haskell-ds-generic-func-menu-next (haskell-ds-bird-p) buffer))
+
+(defun haskell-ds-generic-func-menu-next (bird-literate buffer)
+ "Return `(name . pos)' of next declaration."
+ (set-buffer buffer)
+ (let ((result (haskell-ds-generic-find-next-decl bird-literate)))
+ (if result
+ (let* ((name-posns (car result))
+ (name (car name-posns))
+ (posns (cdr name-posns))
+ (name-pos (cdr posns))
+ ;;(type (cdr result))
+ )
+ (cons ;(concat
+ ;; func-menu has problems with spaces, and adding a
+ ;; qualifying keyword will not allow the "goto fn"
+ ;; functions to work properly. Sigh.
+ ;; (cond
+ ;; ((eq type 'variable) "")
+ ;; ((eq type 'datatype) "datatype ")
+ ;; ((eq type 'class) "class ")
+ ;; ((eq type 'import) "import ")
+ ;; ((eq type 'instance) "instance "))
+ name;)
+ name-pos))
+ nil)))
+
+(defvar haskell-ds-func-menu-regexp
+ (concat "^" haskell-ds-start-decl-re)
+ "Regexp to match the start of a possible declaration.")
+
+(defvar literate-haskell-ds-func-menu-regexp
+ (concat "^" literate-haskell-ds-start-decl-re)
+ "As `haskell-ds-func-menu-regexp' but for Bird-style literate scripts.")
+
+(defvar fume-menubar-menu-name)
+(defvar fume-function-name-regexp-alist)
+(defvar fume-find-function-name-method-alist)
+
+(defun haskell-ds-func-menu ()
+ "Use `func-menu' to establish declaration scanning for Haskell scripts."
+ (require 'func-menu)
+ (set (make-local-variable 'fume-menubar-menu-name) "Declarations")
+ (set (make-local-variable 'fume-function-name-regexp-alist)
+ (if (haskell-ds-bird-p)
+ '((haskell-mode . literate-haskell-ds-func-menu-regexp))
+ '((haskell-mode . haskell-ds-func-menu-regexp))))
+ (set (make-local-variable 'fume-find-function-name-method-alist)
+ '((haskell-mode . haskell-ds-func-menu-next)))
+ (fume-add-menubar-entry)
+ (local-set-key "\C-cl" 'fume-list-functions)
+ (local-set-key "\C-cg" 'fume-prompt-function-goto)
+ (local-set-key [(meta button1)] 'fume-mouse-function-goto))
+
+;; The main functions to turn on declaration scanning.
+(defun turn-on-haskell-decl-scan ()
+ (interactive)
+ "Unconditionally activate `haskell-decl-scan-mode'."
+ (haskell-decl-scan-mode 1))
+
+(defvar haskell-decl-scan-mode nil)
+(make-variable-buffer-local 'haskell-decl-scan-mode)
+
+;;;###autoload
+(defun haskell-decl-scan-mode (&optional arg)
+ "Minor mode for declaration scanning for Haskell mode.
+Top-level declarations are scanned and listed in the menu item \"Declarations\".
+Selecting an item from this menu will take point to the start of the
+declaration.
+
+\\[haskell-ds-forward-decl] and \\[haskell-ds-backward-decl] move forward and backward to the start of a declaration.
+
+Under XEmacs, the following keys are also defined:
+
+\\[fume-list-functions] lists the declarations of the current buffer,
+\\[fume-prompt-function-goto] prompts for a declaration to move to, and
+\\[fume-mouse-function-goto] moves to the declaration whose name is at point.
+
+This may link with `haskell-doc' (only for Emacs currently).
+
+For non-literate and LaTeX-style literate scripts, we assume the
+common convention that top-level declarations start at the first
+column. For Bird-style literate scripts, we assume the common
+convention that top-level declarations start at the third column,
+ie. after \"> \".
+
+Anything in `font-lock-comment-face' is not considered for a
+declaration. Therefore, using Haskell font locking with comments
+coloured in `font-lock-comment-face' improves declaration scanning.
+
+To turn on declaration scanning for all Haskell buffers, add this to
+.emacs:
+
+ (add-hook 'haskell-mode-hook 'turn-on-haskell-decl-scan)
+
+To turn declaration scanning on for the current buffer, call
+`turn-on-haskell-decl-scan'.
+
+Literate Haskell scripts are supported: If the value of
+`haskell-literate' (automatically set by the Haskell mode of
+Moss&Thorn) is `bird', a Bird-style literate script is assumed. If it
+is nil or `tex', a non-literate or LaTeX-style literate script is
+assumed, respectively.
+
+Invokes `haskell-decl-scan-mode-hook'."
+ (interactive)
+ (if (boundp 'beginning-of-defun-function)
+ (if haskell-decl-scan-mode
+ (progn
+ (set (make-local-variable 'beginning-of-defun-function)
+ 'haskell-ds-backward-decl)
+ (set (make-local-variable 'end-of-defun-function)
+ 'haskell-ds-forward-decl))
+ (kill-local-variable 'beginning-of-defun-function)
+ (kill-local-variable 'end-of-defun-function))
+ (local-set-key "\M-\C-e"
+ (if haskell-decl-scan-mode 'haskell-ds-forward-decl))
+ (local-set-key "\M-\C-a"
+ (if haskell-decl-scan-mode 'haskell-ds-backward-decl)))
+ (if haskell-decl-scan-mode
+ (if (fboundp 'imenu)
+ (haskell-ds-imenu)
+ (haskell-ds-func-menu))
+ ;; How can we cleanly remove that menus?
+ (local-set-key [menu-bar index] nil))
+ (run-hooks 'haskell-decl-scan-mode-hook))
+
+;; Provide ourselves:
+
+(provide 'haskell-decl-scan)
+
+;; arch-tag: f4335fd8-4b6c-472e-9899-004d47d94818
+;;; haskell-decl-scan.el ends here
View
1,972 emacs.d/plugins/haskell-mode/haskell-doc.el
@@ -0,0 +1,1972 @@
+;;; haskell-doc.el --- show function types in echo area -*- coding: iso-8859-1 -*-
+
+;; Copyright (C) 2004, 2005, 2006, 2007, 2009 Free Software Foundation, Inc.
+;; Copyright (C) 1997 Hans-Wolfgang Loidl
+
+;; Author: Hans-Wolfgang Loidl <hwloidl@dcs.glasgow.ac.uk>
+;; Temporary Maintainer and Hacker: Graeme E Moss <gem@cs.york.ac.uk>
+;; Keywords: extensions, minor mode, language mode, Haskell
+;; Created: 1997-06-17
+;; URL: http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/CONTRIB/haskell-modes/emacs/haskell-doc.el?rev=HEAD
+
+;;; Copyright:
+;; ==========
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+;;
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+;;
+;; You should have received a copy of the GNU General Public License
+;; along with this program; if not, you can either send email to this
+;; program's maintainer or write to: The Free Software Foundation,
+;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
+
+;;; Commentary:
+;; ===========
+
+;; This program shows the type of the Haskell function under the cursor in the
+;; minibuffer. It acts as a kind of "Emacs background process", by regularly
+;; checking the word under the cursor and matching it against a list of
+;; prelude, library, local and global functions.
+
+;; To show types of global functions, i.e. functions defined in a module
+;; imported by the current module, call the function
+;; `turn-on-haskell-doc-global-types'. This automatically loads all modules
+;; and builds `imenu' tables to get the types of all functions.
+;; Note: The modules are loaded recursively, so you might pull in
+;; many modules by just turning on global function support.
+;; This features is currently not very well supported.
+
+;; This program was inspired by the `eldoc.el' package by Noah Friedman.
+
+;;; Installation:
+;; =============
+
+;; One useful way to enable this minor mode is to put the following in your
+;; .emacs:
+;;
+;; (autoload 'turn-on-haskell-doc-mode "haskell-doc" nil t)
+
+;; and depending on the major mode you use for your Haskell programs:
+;; (add-hook 'hugs-mode-hook 'turn-on-haskell-doc-mode) ; hugs-mode
+;; or
+;; (add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode) ; haskell-mode
+
+;;; Customisation:
+;; ==============
+
+;; You can control what exactly is shown by setting the following variables to
+;; either t or nil:
+;; `haskell-doc-show-global-types' (default: nil)
+;; `haskell-doc-show-reserved' (default: t)
+;; `haskell-doc-show-prelude' (default: t)
+;; `haskell-doc-show-strategy' (default: t)
+;; `haskell-doc-show-user-defined' (default: t)
+
+;; If you want to define your own strings for some identifiers define an
+;; alist of (ID . STRING) and set `haskell-doc-show-user-defined' to t.
+;; E.g:
+;;
+;; (setq haskell-doc-show-user-defined t)
+;; (setq haskell-doc-user-defined-ids
+;; (list
+;; '("main" . "just another pathetic main function")
+;; '("foo" . "a very dummy name")
+;; '("bar" . "another dummy name")))
+
+;; The following two variables are useful to make the type fit on one line:
+;; If `haskell-doc-chop-off-context' is non-nil the context part of the type
+;; of a local fct will be eliminated (default: t).
+;; If `haskell-doc-chop-off-fctname' is non-nil the function name is not
+;; shown together with the type (default: nil).
+
+;;; Internals:
+;; ==========
+
+;; `haskell-doc-mode' is implemented as a minor-mode. So, you can combine it
+;; with any other mode. To enable it just type
+;; M-x turn-on-haskell-doc-mode
+
+;; These are the names of the functions that can be called directly by the
+;; user (with keybindings in `haskell-hugs-mode' and `haskell-mode'):
+;; `haskell-doc-mode' ... toggle haskell-doc-mode; with prefix turn it on
+;; unconditionally if the prefix is greater 0 otherwise
+;; turn it off
+;; Key: CTRL-c CTRL-o (CTRL-u CTRL-c CTRL-o)
+;; `haskell-doc-ask-mouse-for-type' ... show the type of the id under the mouse
+;; Key: C-S-M-mouse-3
+;; `haskell-doc-show-reserved' ... toggle echoing of reserved id's types
+;; `haskell-doc-show-prelude' ... toggle echoing of prelude id's types
+;; `haskell-doc-show-strategy' ... toggle echoing of strategy id's types
+;; `haskell-doc-show-user-defined' ... toggle echoing of user def id's types
+;; `haskell-doc-check-active' ... check whether haskell-doc is active;
+;; Key: CTRL-c ESC-/
+
+;;; ToDo:
+;; =====
+
+;; - Fix byte-compile problems in `haskell-doc-prelude-types' for getArgs etc
+;; - Write a parser for .hi files and make haskell-doc independent from
+;; hugs-mode. Read library interfaces via this parser.
+;; - Indicate kind of object with colours
+;; - Handle multi-line types
+;; - Encode i-am-fct info in the alist of ids and types.
+
+;;; Bugs:
+;; =====
+
+;; - Some prelude fcts aren't displayed properly. This might be due to a
+;; name clash of Haskell and Elisp functions (e.g. length) which
+;; confuses Emacs when reading `haskell-doc-prelude-types'
+
+;;; Changelog:
+;; ==========
+;; $Log: haskell-doc.el,v $
+;; Revision 1.30 2009/02/02 21:00:33 monnier
+;; (haskell-doc-imported-list): Don't add current buffer
+;; to the imported file list if it is not (yet?) visiting a file.
+;;
+;; Revision 1.29 2007-12-12 04:04:19 monnier
+;; (haskell-doc-in-code-p): New function.
+;; (haskell-doc-show-type): Use it.
+;;
+;; Revision 1.28 2007/08/30 03:10:08 monnier
+;; Comment/docs fixes.
+;;
+;; Revision 1.27 2007/07/30 17:36:50 monnier
+;; (displayed-month): Remove declaration since it's not used here.
+;;
+;; Revision 1.26 2007/02/10 06:28:55 monnier
+;; (haskell-doc-get-current-word): Remove.
+;; Change all refs to it, to use haskell-ident-at-point instead.
+;;
+;; Revision 1.25 2007/02/09 21:53:42 monnier
+;; (haskell-doc-get-current-word): Correctly distinguish
+;; variable identifiers and infix identifiers.
+;; (haskell-doc-rescan-files): Avoid switch-to-buffer.
+;; (haskell-doc-imported-list): Operate on current buffer.
+;; (haskell-doc-make-global-fct-index): Adjust call.
+;;
+;; Revision 1.24 2006/11/20 20:18:24 monnier
+;; (haskell-doc-mode-print-current-symbol-info): Fix thinko.
+;;
+;; Revision 1.23 2006/10/20 03:12:31 monnier
+;; Drop post-command-idle-hook in favor of run-with-idle-timer.
+;; (haskell-doc-timer, haskell-doc-buffers): New vars.
+;; (haskell-doc-mode): Use them.
+;; (haskell-doc-check-active): Update the check.
+;; (haskell-doc-mode-print-current-symbol-info): Remove the interactive spec.
+;; Don't sit-for unless it's really needed.
+;;
+;; Revision 1.22 2006/09/20 18:42:35 monnier
+;; Doc fix.
+;;
+;; Revision 1.21 2005/11/21 21:48:52 monnier
+;; * haskell-doc.el (haskell-doc-extract-types): Get labelled data working.
+;; (haskell-doc-prelude-types): Update via auto-generation.
+;;
+;; * haskell-doc.el (haskell-doc-extract-types): Get it partly working.
+;; (haskell-doc-fetch-lib-urls): Don't use a literal if we apply
+;; `nreverse' on it later on.
+;; (haskell-doc-prelude-types): Update some parts by auto-generation.
+;; (haskell-doc-grab, haskell-doc-string-nub-ws): Simplify.
+;;
+;; * haskell-doc.el (haskell-doc-maintainer, haskell-doc-varlist)
+;; (haskell-doc-submit-bug-report, haskell-doc-ftp-site)
+;; (haskell-doc-visit-home): Remove.
+;; (haskell-doc-reserved-ids, haskell-doc-fetch-lib-urls)
+;; (haskell-doc-extract-and-insert-types): New funs.
+;; (haskell-doc-reserved-ids): Fix type of `map'.
+;;
+;; Revision 1.20 2005/11/21 21:27:57 monnier
+;; (haskell-doc-extract-types): Get labelled data working.
+;; (haskell-doc-prelude-types): Update via auto-generation.
+;;
+;; Revision 1.19 2005/11/21 20:44:13 monnier
+;; (haskell-doc-extract-types): Get it partly working.
+;; (haskell-doc-fetch-lib-urls): Don't use a literal if we apply
+;; `nreverse' on it later on.
+;; (haskell-doc-prelude-types): Update some parts by auto-generation.
+;; (haskell-doc-grab, haskell-doc-string-nub-ws): Simplify.
+;;
+;; Revision 1.18 2005/11/21 18:02:15 monnier
+;; (haskell-doc-maintainer, haskell-doc-varlist)
+;; (haskell-doc-submit-bug-report, haskell-doc-ftp-site)
+;; (haskell-doc-visit-home): Remove.
+;; (haskell-doc-reserved-ids, haskell-doc-fetch-lib-urls)
+;; (haskell-doc-extract-and-insert-types): New funs.
+;; (haskell-doc-reserved-ids): Fix type of `map'.
+;;
+;; Revision 1.17 2005/11/20 23:55:09 monnier
+;; Add coding cookie.
+;;
+;; Revision 1.16 2005/11/07 01:28:16 monnier
+;; (haskell-doc-xemacs-p, haskell-doc-emacs-p)
+;; (haskell-doc-message): Remove.
+;; (haskell-doc-is-id-char-at): Remove.
+;; (haskell-doc-get-current-word): Rewrite.
+;;
+;; Revision 1.15 2005/11/04 17:11:12 monnier
+;; Add arch-tag.
+;;
+;; Revision 1.14 2005/08/24 11:36:32 monnier
+;; (haskell-doc-message): Paren typo.
+;;
+;; Revision 1.13 2005/08/23 19:23:27 monnier
+;; (haskell-doc-show-type): Assume that the availability
+;; of display-message won't change at runtime.
+;;
+;; Revision 1.12 2005/07/18 21:04:14 monnier
+;; (haskell-doc-message): Remove.
+;; (haskell-doc-show-type): inline it. Do nothing for if there's no doc to show.
+;;
+;; Revision 1.11 2004/12/10 17:33:18 monnier
+;; (haskell-doc-minor-mode-string): Make it dynamic.
+;; (haskell-doc-install-keymap): Remove conflicting C-c C-o binding.
+;; (haskell-doc-mode): Make a nil arg turn the mode ON.
+;; (turn-on-haskell-doc-mode): Make it an alias for haskell-doc-mode.
+;; (haskell-doc-mode): Don't touch haskell-doc-minor-mode-string.
+;; (haskell-doc-show-global-types): Don't touch
+;; haskell-doc-minor-mode-string. Call haskell-doc-make-global-fct-index.
+;; (haskell-doc-check-active): Fix message.
+;; (define-key-after): Don't define.
+;; (haskell-doc-install-keymap): Check existence of define-key-after.
+;;
+;; Revision 1.10 2004/11/25 23:03:23 monnier
+;; (haskell-doc-sym-doc): Make even the last char bold.
+;;
+;; Revision 1.9 2004/11/24 22:14:36 monnier
+;; (haskell-doc-install-keymap): Don't blindly assume there's a Hugs menu.
+;;
+;; Revision 1.8 2004/11/22 10:45:35 simonmar
+;; Fix type of getLine
+;;
+;; Revision 1.7 2004/10/14 22:27:47 monnier
+;; (turn-off-haskell-doc-mode, haskell-doc-current-info): Don't autoload.
+;;
+;; Revision 1.6 2004/10/13 22:45:22 monnier
+;; (haskell-doc): New group.
+;; (haskell-doc-show-reserved, haskell-doc-show-prelude)
+;; (haskell-doc-show-strategy, haskell-doc-show-user-defined)
+;; (haskell-doc-chop-off-context, haskell-doc-chop-off-fctname):
+;; Make them custom vars.
+;; (haskell-doc-keymap): Declare and fill it right there.
+;; (haskell-doc-mode): Simplify.
+;; (haskell-doc-toggle-var): Make it into what it was supposed to be.
+;; (haskell-doc-mode-print-current-symbol-info): Simplify.
+;; (haskell-doc-current-info): New autoloaded function.
+;; (haskell-doc-sym-doc): New fun extracted from haskell-doc-show-type.
+;; (haskell-doc-show-type): Use it.
+;; (haskell-doc-wrapped-type-p): Remove unused var `lim'.
+;; (haskell-doc-forward-sexp-safe, haskell-doc-current-symbol): Remove. Unused.
+;; (haskell-doc-visit-home): Don't require ange-ftp, it's autoloaded.
+;; (haskell-doc-install-keymap): Simplify.
+;;
+;; Revision 1.5 2003/01/09 11:56:26 simonmar
+;; Patches from Ville Skyttä <scop@xemacs.org>, the XEmacs maintainer of
+;; the haskell-mode:
+;;
+;; - Make the auto-mode-alist modifications autoload-only.
+;;
+;; Revision 1.4 2002/10/14 09:55:03 simonmar
+;; Patch to update the Prelude/libraries function names and to remove
+;; support for older versions of Haskell.
+;;
+;; Submitted by: Anders Lau Olsen <alauo@mip.sdu.dk>
+;;
+;; Revision 1.3 2002/04/30 09:34:37 rrt
+;; Remove supporting Haskell 1.4 and 1.2 from the ToDo list. It's Far Too Late.
+;;
+;; Add (require 'imenu). Thanks to N. Y. Kwok.
+;;
+;; Revision 1.2 2002/04/23 14:45:10 simonmar
+;; Tweaks to the doc strings and support for customization, from
+;; Ville Skyttä <scop@xemacs.org>.
+;;
+;; Revision 1.1 2001/07/19 16:17:36 rrt
+;; Add the current version of the Moss/Thorn/Marlow Emacs mode, along with its
+;; web pages and sample files. This is now the preferred mode, and the
+;; haskell.org pages are being changed to reflect that. Also includes the new
+;; GHCi mode from Chris Webb.
+;;
+;; Revision 1.6 1998/12/10 16:27:25 hwloidl
+;; Minor changes ("Doc" as modeline string, mouse-3 moved to C-S-M-mouse-3)
+;;
+;; Revision 1.5 1998/09/24 14:25:46 gem
+;; Fixed minor compatibility bugs with Haskell mode of Moss&Thorn.
+;; Disabled M-/ binding.
+;;
+;; Revision 1.4 1997/11/12 23:51:19 hwloidl
+;; Fixed start-up problem under emacs-19.34.
+;; Added support for wrapped (multi-line) types and 2 vars to control the
+;; behaviour with long fct types
+;;
+;; Revision 1.3 1997/11/03 00:48:03 hwloidl
+;; Major revision for first release.
+;; Added alists for showing prelude fcts, haskell syntax, and strategies
+;; Added mouse interface to show type under mouse
+;; Fixed bug which causes demon to fall over
+;; Works now with hugs-mode and haskell-mode under emacs 19.34,20 and xemacs 19.15
+;;
+
+;;; Code:
+;; =====
+
+;;@menu
+;;* Constants and Variables::
+;;* Install as minor mode::
+;;* Menubar Support::
+;;* Haskell Doc Mode::
+;;* Switch it on or off::
+;;* Check::
+;;* Top level function::
+;;* Mouse interface::
+;;* Print fctsym::
+;;* Movement::
+;;* Bug Reports::
+;;* Visit home site::
+;;* Index::
+;;* Token::
+;;@end menu
+
+;;@node top, Constants and Variables, (dir), (dir)
+;;@top
+
+;;@node Constants and Variables, Install as minor mode, top, top
+;;@section Constants and Variables
+
+;;@menu
+;;* Emacs portability::
+;;* Maintenance stuff::
+;;* Mode Variable::
+;;* Variables::
+;;* Prelude types::
+;;* Test membership::
+;;@end menu
+
+;;@node Emacs portability, Maintenance stuff, Constants and Variables, Constants and Variables
+;;@subsection Emacs portability
+
+(require 'haskell-mode)
+(eval-when-compile (require 'cl))
+
+(defgroup haskell-doc nil
+ "Show Haskell function types in echo area."
+ :group 'haskell
+ :prefix "haskell-doc-")
+
+;;@node Mode Variable, Variables, Maintenance stuff, Constants and Variables
+;;@subsection Mode Variable
+
+(defvar haskell-doc-mode nil
+ "*If non-nil, show the type of the function near point or a related comment.
+
+If the identifier near point is a Haskell keyword and the variable
+`haskell-doc-show-reserved' is non-nil show a one line summary
+of the syntax.
+
+If the identifier near point is a Prelude or one of the standard library
+functions and `haskell-doc-show-prelude' is non-nil show its type.
+
+If the identifier near point is local \(i.e. defined in this module\) check
+the `imenu' list of functions for the type. This obviously requires that
+your language mode uses `imenu'.
+
+If the identifier near point is global \(i.e. defined in an imported module\)
+and the variable `haskell-doc-show-global-types' is non-nil show the type of its
+function.
+
+If the identifier near point is a standard strategy or a function, type related
+related to strategies and `haskell-doc-show-strategy' is non-nil show the type
+of the function. Strategies are special to the parallel execution of Haskell.
+If you're not interested in that just turn it off.
+
+If the identifier near point is a user defined function that occurs as key
+in the alist `haskell-doc-user-defined-ids' and the variable
+`haskell-doc-show-user-defined' is non-nil show the type of the function.
+
+This variable is buffer-local.")
+(make-variable-buffer-local 'haskell-doc-mode)
+
+(defvar haskell-doc-mode-hook nil
+ "Hook invoked when entering `haskell-doc-mode'.")
+
+(defvar haskell-doc-index nil
+ "Variable holding an alist matching file names to fct-type alists.
+The function `haskell-doc-make-global-fct-index' rebuilds this variables
+\(similar to an `imenu' rescan\).
+This variable is buffer-local.")
+(make-variable-buffer-local 'haskell-doc-index)
+
+(defcustom haskell-doc-show-global-types nil
+ "If non-nil, search for the types of global functions by loading the files.
+This variable is buffer-local."
+ :group 'haskell-doc
+ :type 'boolean)
+(make-variable-buffer-local 'haskell-doc-show-global-types)
+
+(defcustom haskell-doc-show-reserved t
+ "If non-nil, show a documentation string for reserved ids.
+This variable is buffer-local."
+ :group 'haskell-doc
+ :type 'boolean)
+(make-variable-buffer-local 'haskell-doc-show-reserved)
+
+(defcustom haskell-doc-show-prelude t
+ "If non-nil, show a documentation string for prelude functions.
+This variable is buffer-local."
+ :group 'haskell-doc
+ :type 'boolean)
+(make-variable-buffer-local 'haskell-doc-show-prelude)
+
+(defcustom haskell-doc-show-strategy t
+ "If non-nil, show a documentation string for strategies.
+This variable is buffer-local."
+ :group 'haskell-doc
+ :type 'boolean)
+(make-variable-buffer-local 'haskell-doc-show-strategy)
+
+(defcustom haskell-doc-show-user-defined t
+ "If non-nil, show a documentation string for user defined ids.
+This variable is buffer-local."
+ :group 'haskell-doc
+ :type 'boolean)
+(make-variable-buffer-local 'haskell-doc-show-user-defined)
+
+(defcustom haskell-doc-chop-off-context t
+ "If non-nil eliminate the context part in a Haskell type."
+ :group 'haskell-doc
+ :type 'boolean)
+
+(defcustom haskell-doc-chop-off-fctname nil
+ "If non-nil omit the function name and show only the type."
+ :group 'haskell-doc
+ :type 'boolean)
+
+(defvar haskell-doc-search-distance 40 ; distance in characters
+ "*How far to search when looking for the type declaration of fct under cursor.")
+
+;;@node Variables, Prelude types, Mode Variable, Constants and Variables
+;;@subsection Variables
+
+(defvar haskell-doc-idle-delay 0.50
+ "*Number of seconds of idle time to wait before printing.
+If user input arrives before this interval of time has elapsed after the
+last input, no documentation will be printed.
+
+If this variable is set to 0, no idle time is required.")
+
+(defvar haskell-doc-argument-case 'identity ; 'upcase
+ "Case to display argument names of functions, as a symbol.
+This has two preferred values: `upcase' or `downcase'.
+Actually, any name of a function which takes a string as an argument and
+returns another string is acceptable.")
+
+(defvar haskell-doc-mode-message-commands nil
+ "*Obarray of command names where it is appropriate to print in the echo area.
+
+This is not done for all commands since some print their own
+messages in the echo area, and these functions would instantly overwrite
+them. But `self-insert-command' as well as most motion commands are good
+candidates.
+
+It is probably best to manipulate this data structure with the commands
+`haskell-doc-add-command' and `haskell-doc-remove-command'.")
+
+;;(cond ((null haskell-doc-mode-message-commands)
+;; ;; If you increase the number of buckets, keep it a prime number.
+;; (setq haskell-doc-mode-message-commands (make-vector 31 0))
+;; (let ((list '("self-insert-command"
+;; "next-" "previous-"
+;; "forward-" "backward-"
+;; "beginning-of-" "end-of-"
+;; "goto-"
+;; "recenter"
+;; "scroll-"))
+;; (syms nil))
+;; (while list
+;; (setq syms (all-completions (car list) obarray 'fboundp))
+;; (setq list (cdr list))
+;; (while syms
+;; (set (intern (car syms) haskell-doc-mode-message-commands) t)
+;; (setq syms (cdr syms)))))))
+
+;; Bookkeeping; the car contains the last symbol read from the buffer.
+;; The cdr contains the string last displayed in the echo area, so it can
+;; be printed again if necessary without reconsing.
+(defvar haskell-doc-last-data '(nil . nil))
+
+(defvar haskell-doc-minor-mode-string
+ '(haskell-doc-show-global-types " DOC" " Doc")
+ "*String to display in mode line when Haskell-Doc Mode is enabled.")
+
+
+;;@node Prelude types, Test membership, Variables, Constants an