Initial Commit
[packages] / xemacs-packages / haskell-mode / haskell-doc.el
1 ;;; haskell-doc.el --- show function types in echo area
2
3 ;; Copyright (C) 2004, 2005  Free Software Foundation, Inc.
4 ;; Copyright (C) 1997 Hans-Wolfgang Loidl
5
6 ;; Author: Hans-Wolfgang Loidl <hwloidl@dcs.glasgow.ac.uk>
7 ;; Temporary Maintainer and Hacker: Graeme E Moss <gem@cs.york.ac.uk>
8 ;; Keywords: extensions, minor mode, language mode, Haskell
9 ;; Created: 1997-06-17
10 ;; URL: http://cvs.haskell.org/cgi-bin/cvsweb.cgi/fptools/CONTRIB/haskell-modes/emacs/haskell-doc.el?rev=HEAD
11
12 ;;; Copyright:
13 ;;  ==========
14
15 ;; This program is free software; you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation; either version 2, or (at your option)
18 ;; any later version.
19 ;;
20 ;; This program is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 ;; GNU General Public License for more details.
24 ;;
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with this program; if not, you can either send email to this
27 ;; program's maintainer or write to: The Free Software Foundation,
28 ;; Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA.
29
30 ;;; Commentary:
31 ;;  ===========
32
33 ;; This program shows the type of the Haskell function under the cursor in the
34 ;; minibuffer.  It acts as a kind of "emacs background process", by regularly
35 ;; checking the word under the cursor and matching it against a list of
36 ;; prelude, library, local and global functions.
37
38 ;; The preferred usage of this package is in combination with
39 ;; `haskell-hugs-mode'.
40 ;; In that case `haskell-doc-mode' checks an internal variable updated by
41 ;; `imenu' to access the types of all local functions.  In `haskell-mode' this
42 ;; is not possible.  However, types of prelude functions are still shown.
43
44 ;; To show types of global functions, i.e. functions defined in a module
45 ;; imported by the current module, call the function
46 ;; `turn-on-haskell-doc-global-types'.  This automatically loads all modules
47 ;; and builds `imenu' tables to get the types of all functions (again this
48 ;; currently requires `haskell-hugs-mode').
49 ;; Note: The modules are loaded recursively, so you might pull in
50 ;;       many modules by just turning on global function support.
51 ;; This features is currently not very well supported.
52
53 ;; This program was inspired by the `eldoc.el' package by Noah Friedman.
54
55 ;;; Installation:
56 ;;  =============
57
58 ;; One useful way to enable this minor mode is to put the following in your
59 ;; .emacs:
60 ;;
61 ;;      (autoload 'turn-on-haskell-doc-mode "haskell-doc" nil t)
62
63 ;;   and depending on the major mode you use for your Haskell programs:
64 ;;      (add-hook 'hugs-mode-hook 'turn-on-haskell-doc-mode)    ; hugs-mode
65 ;;     or
66 ;;      (add-hook 'haskell-mode-hook 'turn-on-haskell-doc-mode) ; haskell-mode
67
68 ;;; Customisation:
69 ;;  ==============
70
71 ;; You can control what exactly is shown by setting the following variables to
72 ;; either t or nil:
73 ;;  `haskell-doc-show-global-types' (default: nil)
74 ;;  `haskell-doc-show-reserved'     (default: t)
75 ;;  `haskell-doc-show-prelude'      (default: t)
76 ;;  `haskell-doc-show-strategy'     (default: t)
77 ;;  `haskell-doc-show-user-defined' (default: t)
78
79 ;; If you want to define your own strings for some identifiers define an
80 ;; alist of (ID . STRING) and set `haskell-doc-show-user-defined' to t.
81 ;; E.g:
82 ;;
83 ;;   (setq haskell-doc-show-user-defined t)
84 ;;   (setq haskell-doc-user-defined-ids
85 ;;      (list
86 ;;         '("main" . "just another pathetic main function")
87 ;;         '("foo" . "a very dummy name")
88 ;;         '("bar" . "another dummy name")))
89
90 ;;  The following two variables are useful to make the type fit on one line:
91 ;;  If `haskell-doc-chop-off-context' is non-nil the context part of the type
92 ;;  of a local fct will be eliminated (default: t).
93 ;;  If `haskell-doc-chop-off-fctname' is non-nil the function name is not
94 ;;  shown together with the type (default: nil).
95
96 ;;; Internals:
97 ;;  ==========
98
99 ;; `haskell-doc-mode' is implemented as a minor-mode. So, you can combine it
100 ;; with any other mode. To enable it just type
101 ;;   M-x turn-on-haskell-doc-mode
102
103 ;; These are the names of the functions that can be called directly by the
104 ;; user (with keybindings in `haskell-hugs-mode' and `haskell-mode'):
105 ;;  `haskell-doc-mode' ... toggle haskell-doc-mode; with prefix turn it on
106 ;;                        unconditionally if the prefix is greater 0 otherwise
107 ;;                        turn it off
108 ;;                        Key: CTRL-c CTRL-o (CTRL-u CTRL-c CTRL-o)
109 ;;  `haskell-doc-ask-mouse-for-type' ... show the type of the id under the mouse
110 ;;                                      Key: C-S-M-mouse-3
111 ;;  `haskell-doc-show-reserved'     ... toggle echoing of reserved id's types
112 ;;  `haskell-doc-show-prelude'      ... toggle echoing of prelude id's types
113 ;;  `haskell-doc-show-strategy'     ... toggle echoing of strategy id's types
114 ;;  `haskell-doc-show-user-defined' ... toggle echoing of user def id's types
115 ;;  `haskell-doc-check-active' ... check whether haskell-doc is active via the
116 ;;                                `post-command-idle-hook' (for testing);
117 ;;                                 Key: CTRL-c ESC-/
118
119 ;;; ToDo:
120 ;;  =====
121
122 ;;   - Fix byte-compile problems in `haskell-doc-prelude-types' for getArgs etc
123 ;;   - Write a parser for .hi files and make haskell-doc independent from
124 ;;     hugs-mode. Read library interfaces via this parser.
125 ;;   - Indicate kind of object with colours
126 ;;   - Handle multi-line types
127 ;;   - Encode i-am-fct info in the alist of ids and types.
128 ;;   - Replace the usage of `post-command-idle-hook' with idle timers
129
130 ;;; Bugs:
131 ;;  =====
132
133 ;;   - Some prelude fcts aren't displayed properly. This might be due to a
134 ;;     name clash of Haskell and Elisp functions (e.g. length) which
135 ;;     confuses emacs when reading `haskell-doc-prelude-types'
136
137 ;;; Changelog:
138 ;;  ==========
139 ;;  haskell-doc.el,v
140 ;;  Revision 1.16  2005/11/07 01:28:16  monnier
141 ;;  (haskell-doc-xemacs-p, haskell-doc-emacs-p)
142 ;;  (haskell-doc-message): Remove.
143 ;;  (haskell-doc-is-id-char-at): Remove.
144 ;;  (haskell-doc-get-current-word): Rewrite.
145 ;;
146 ;;  Revision 1.15  2005/11/04 17:11:12  monnier
147 ;;  Add arch-tag.
148 ;;
149 ;;  Revision 1.14  2005/08/24 11:36:32  monnier
150 ;;  (haskell-doc-message): Paren typo.
151 ;;
152 ;;  Revision 1.13  2005/08/23 19:23:27  monnier
153 ;;  (haskell-doc-show-type): Assume that the availability
154 ;;  of display-message won't change at runtime.
155 ;;
156 ;;  Revision 1.12  2005/07/18 21:04:14  monnier
157 ;;  (haskell-doc-message): Remove.
158 ;;  (haskell-doc-show-type): inline it.  Do nothing for if there's no doc to show.
159 ;;
160 ;;  Revision 1.11  2004/12/10 17:33:18  monnier
161 ;;  (haskell-doc-minor-mode-string): Make it dynamic.
162 ;;  (haskell-doc-install-keymap): Remove conflicting C-c C-o binding.
163 ;;  (haskell-doc-mode): Make a nil arg turn the mode ON.
164 ;;  (turn-on-haskell-doc-mode): Make it an alias for haskell-doc-mode.
165 ;;  (haskell-doc-mode): Don't touch haskell-doc-minor-mode-string.
166 ;;  (haskell-doc-show-global-types): Don't touch
167 ;;  haskell-doc-minor-mode-string.  Call haskell-doc-make-global-fct-index.
168 ;;  (haskell-doc-check-active): Fix message.
169 ;;  (define-key-after): Don't define.
170 ;;  (haskell-doc-install-keymap): Check existence of define-key-after.
171 ;;
172 ;;  Revision 1.10  2004/11/25 23:03:23  monnier
173 ;;  (haskell-doc-sym-doc): Make even the last char bold.
174 ;;
175 ;;  Revision 1.9  2004/11/24 22:14:36  monnier
176 ;;  (haskell-doc-install-keymap): Don't blindly assume there's a Hugs menu.
177 ;;
178 ;;  Revision 1.8  2004/11/22 10:45:35  simonmar
179 ;;  Fix type of getLine
180 ;;
181 ;;  Revision 1.7  2004/10/14 22:27:47  monnier
182 ;;  (turn-off-haskell-doc-mode, haskell-doc-current-info): Don't autoload.
183 ;;
184 ;;  Revision 1.6  2004/10/13 22:45:22  monnier
185 ;;  (haskell-doc): New group.
186 ;;  (haskell-doc-show-reserved, haskell-doc-show-prelude)
187 ;;  (haskell-doc-show-strategy, haskell-doc-show-user-defined)
188 ;;  (haskell-doc-chop-off-context, haskell-doc-chop-off-fctname):
189 ;;  Make them custom vars.
190 ;;  (haskell-doc-keymap): Declare and fill it right there.
191 ;;  (haskell-doc-mode): Simplify.
192 ;;  (haskell-doc-toggle-var): Make it into what it was supposed to be.
193 ;;  (haskell-doc-mode-print-current-symbol-info): Simplify.
194 ;;  (haskell-doc-current-info): New autoloaded function.
195 ;;  (haskell-doc-sym-doc): New fun extracted from haskell-doc-show-type.
196 ;;  (haskell-doc-show-type): Use it.
197 ;;  (haskell-doc-wrapped-type-p): Remove unused var `lim'.
198 ;;  (haskell-doc-forward-sexp-safe, haskell-doc-current-symbol): Remove.  Unused.
199 ;;  (haskell-doc-visit-home): Don't require ange-ftp, it's autoloaded.
200 ;;  (haskell-doc-install-keymap): Simplify.
201 ;;
202 ;;  Revision 1.5  2003/01/09 11:56:26  simonmar
203 ;;  Patches from Ville Skyttä <scop@xemacs.org>, the XEmacs maintainer of
204 ;;  the haskell-mode:
205 ;;
206 ;;   - Make the auto-mode-alist modifications autoload-only.
207 ;;
208 ;;  Revision 1.4  2002/10/14 09:55:03  simonmar
209 ;;  Patch to update the Prelude/libraries function names and to remove
210 ;;  support for older versions of Haskell.
211 ;;
212 ;;  Submitted by: Anders Lau Olsen <alauo@mip.sdu.dk>
213 ;;
214 ;;  Revision 1.3  2002/04/30 09:34:37  rrt
215 ;;  Remove supporting Haskell 1.4 and 1.2 from the ToDo list. It's Far Too Late.
216 ;;
217 ;;  Add (require 'imenu). Thanks to N. Y. Kwok.
218 ;;
219 ;;  Revision 1.2  2002/04/23 14:45:10  simonmar
220 ;;  Tweaks to the doc strings and support for customization, from
221 ;;  Ville Skyttä <scop@xemacs.org>.
222 ;;
223 ;;  Revision 1.1  2001/07/19 16:17:36  rrt
224 ;;  Add the current version of the Moss/Thorn/Marlow Emacs mode, along with its
225 ;;  web pages and sample files. This is now the preferred mode, and the
226 ;;  haskell.org pages are being changed to reflect that. Also includes the new
227 ;;  GHCi mode from Chris Webb.
228 ;;
229 ;;  Revision 1.6  1998/12/10 16:27:25  hwloidl
230 ;;  Minor changes ("Doc" as modeline string, mouse-3 moved to C-S-M-mouse-3)
231 ;;
232 ;;  Revision 1.5  1998/09/24 14:25:46  gem
233 ;;  Fixed minor compatibility bugs with Haskell mode of Moss&Thorn.
234 ;;  Disabled M-/ binding.
235 ;;
236 ;;  Revision 1.4  1997/11/12 23:51:19  hwloidl
237 ;;  Fixed start-up problem under emacs-19.34.
238 ;;  Added support for wrapped (multi-line) types and 2 vars to control the
239 ;;  behaviour with long fct types
240 ;;
241 ;;  Revision 1.3  1997/11/03 00:48:03  hwloidl
242 ;;  Major revision for first release.
243 ;;  Added alists for showing prelude fcts, haskell syntax, and strategies
244 ;;  Added mouse interface to show type under mouse
245 ;;  Fixed bug which causes demon to fall over
246 ;;  Works now with hugs-mode and haskell-mode under emacs 19.34,20 and xemacs 19.15
247 ;;
248
249 ;;; Code:
250 ;;  =====
251
252 ;;@menu
253 ;;* Constants and Variables::
254 ;;* Install as minor mode::
255 ;;* Menubar Support::
256 ;;* Haskell Doc Mode::
257 ;;* Switch it on or off::
258 ;;* Check::
259 ;;* Top level function::
260 ;;* Mouse interface::
261 ;;* Print fctsym::
262 ;;* Movement::
263 ;;* Bug Reports::
264 ;;* Visit home site::
265 ;;* Index::
266 ;;* Token::
267 ;;@end menu
268
269 ;;@node top, Constants and Variables, (dir), (dir)
270 ;;@top
271
272 ;;@node Constants and Variables, Install as minor mode, top, top
273 ;;@section Constants and Variables
274
275 ;;@menu
276 ;;* Emacs portability::
277 ;;* Maintenance stuff::
278 ;;* Mode Variable::
279 ;;* Variables::
280 ;;* Prelude types::
281 ;;* Test membership::
282 ;;@end menu
283
284 ;;@node Emacs portability, Maintenance stuff, Constants and Variables, Constants and Variables
285 ;;@subsection Emacs portability
286
287 (defgroup haskell-doc nil
288   "Show Haskell function types in echo area."
289   :group 'haskell
290   :prefix "haskell-doc-")
291
292 ;;@node Maintenance stuff, Mode Variable, Emacs portability, Constants and Variables
293 ;;@subsection Maintenance stuff
294
295 (defconst haskell-doc-version "1.16"
296  "Version of `haskell-doc-mode' as RCS Revision.")
297
298 (defconst haskell-doc-maintainer
299   "Hans-Wolfgang Loidl <hwloidl@dcs.glasgow.ac.uk>"
300   "Maintainer of `haskell-doc-mode'.")
301
302 (defconst haskell-doc-ftp-site
303   "/ftp@ftp.dcs.gla.ac.uk:/pub/glasgow-fp/authors/Hans_Loidl/Elisp/"
304   "Main FTP site with latest version of `haskell-doc-mode' and sample files.")
305
306 ;;@node Mode Variable, Variables, Maintenance stuff, Constants and Variables
307 ;;@subsection Mode Variable
308
309 (defvar haskell-doc-mode nil
310   "*If non-nil, show the type of the function near point or a related comment.
311
312 If the identifier near point is a Haskell keyword and the variable
313 `haskell-doc-show-reserved' is non-nil show a one line summary
314 of the syntax.
315
316 If the identifier near point is a Prelude or one of the standard library
317 functions and `haskell-doc-show-prelude' is non-nil show its type.
318
319 If the identifier near point is local \(i.e. defined in this module\) check
320 the `imenu' list of functions for the type. This obviously requires that
321 your language mode uses `imenu' \(`haskell-hugs-mode' 0.6 for example\).
322
323 If the identifier near point is global \(i.e. defined in an imported module\)
324 and the variable `haskell-doc-show-global-types' is non-nil show the type of its
325 function.
326
327 If the identifier near point is a standard strategy or a function, type related
328 related to strategies and `haskell-doc-show-strategy' is non-nil show the type
329 of the function. Strategies are special to the parallel execution of Haskell.
330 If you're not interested in that just turn it off.
331
332 If the identifier near point is a user defined function that occurs as key
333 in the alist `haskell-doc-user-defined-ids' and the variable
334 `haskell-doc-show-user-defined' is non-nil show the type of the function.
335
336 This variable is buffer-local.")
337 (make-variable-buffer-local 'haskell-doc-mode)
338
339 (defvar haskell-doc-mode-hook nil
340  "Hook invoked when entering `haskell-doc-mode'.")
341
342 (defvar haskell-doc-index nil
343  "Variable holding an alist matching file names to fct-type alists.
344 The function `haskell-doc-make-global-fct-index' rebuilds this variables \(similar to an
345 `imenu' rescan\).
346 This variable is buffer-local.")
347 (make-variable-buffer-local 'haskell-doc-index)
348
349 (defcustom haskell-doc-show-global-types nil
350   "If non-nil, search for the types of global functions by loading the files.
351 This variable is buffer-local."
352   :type 'boolean)
353 (make-variable-buffer-local 'haskell-doc-show-global-types)
354
355 (defcustom haskell-doc-show-reserved t
356   "If non-nil, show a documentation string for reserved ids.
357 This variable is buffer-local."
358   :type 'boolean)
359 (make-variable-buffer-local 'haskell-doc-show-reserved)
360
361 (defcustom haskell-doc-show-prelude t
362   "If non-nil, show a documentation string for prelude functions.
363 This variable is buffer-local."
364   :type 'boolean)
365 (make-variable-buffer-local 'haskell-doc-show-prelude)
366
367 (defcustom haskell-doc-show-strategy t
368   "If non-nil, show a documentation string for strategies.
369 This variable is buffer-local."
370   :type 'boolean)
371 (make-variable-buffer-local 'haskell-doc-show-strategy)
372
373 (defcustom haskell-doc-show-user-defined t
374   "If non-nil, show a documentation string for user defined ids.
375 This variable is buffer-local."
376   :type 'boolean)
377 (make-variable-buffer-local 'haskell-doc-show-user-defined)
378
379 (defcustom haskell-doc-chop-off-context t
380  "If non-nil eliminate the context part in a Haskell type."
381  :type 'boolean)
382
383 (defcustom haskell-doc-chop-off-fctname nil
384   "If non-nil omit the function name and show only the type."
385   :type 'boolean)
386
387 (defvar haskell-doc-search-distance 40  ; distance in characters
388  "*How far to search when looking for the type declaration of fct under cursor.")
389
390 ;;@node Variables, Prelude types, Mode Variable, Constants and Variables
391 ;;@subsection Variables
392
393 (defvar haskell-doc-idle-delay 0.50
394   "*Number of seconds of idle time to wait before printing.
395 If user input arrives before this interval of time has elapsed after the
396 last input, no documentation will be printed.
397
398 If this variable is set to 0, no idle time is required.")
399
400 (defvar haskell-doc-argument-case 'identity ; 'upcase
401   "Case to display argument names of functions, as a symbol.
402 This has two preferred values: `upcase' or `downcase'.
403 Actually, any name of a function which takes a string as an argument and
404 returns another string is acceptable.")
405
406 (defvar haskell-doc-mode-message-commands nil
407   "*Obarray of command names where it is appropriate to print in the echo area.
408
409 This is not done for all commands since some print their own
410 messages in the echo area, and these functions would instantly overwrite
411 them.  But `self-insert-command' as well as most motion commands are good
412 candidates.
413
414 It is probably best to manipulate this data structure with the commands
415 `haskell-doc-add-command' and `haskell-doc-remove-command'.")
416
417 ;;(cond ((null haskell-doc-mode-message-commands)
418 ;;       ;; If you increase the number of buckets, keep it a prime number.
419 ;;       (setq haskell-doc-mode-message-commands (make-vector 31 0))
420 ;;       (let ((list '("self-insert-command"
421 ;;                     "next-"         "previous-"
422 ;;                     "forward-"      "backward-"
423 ;;                     "beginning-of-" "end-of-"
424 ;;                     "goto-"
425 ;;                     "recenter"
426 ;;                     "scroll-"))
427 ;;             (syms nil))
428 ;;         (while list
429 ;;           (setq syms (all-completions (car list) obarray 'fboundp))
430 ;;           (setq list (cdr list))
431 ;;           (while syms
432 ;;             (set (intern (car syms) haskell-doc-mode-message-commands) t)
433 ;;             (setq syms (cdr syms)))))))
434
435 ;; Bookkeeping; the car contains the last symbol read from the buffer.
436 ;; The cdr contains the string last displayed in the echo area, so it can
437 ;; be printed again if necessary without reconsing.
438 (defvar haskell-doc-last-data '(nil . nil))
439
440 (defvar haskell-doc-minor-mode-string
441   '(haskell-doc-show-global-types " DOC" " Doc")
442   "*String to display in mode line when Haskell-Doc Mode is enabled.")
443
444 (defconst haskell-doc-varlist
445   (list
446    'haskell-doc-version
447    'haskell-doc-mode
448    'haskell-doc-mode-hook
449    'haskell-doc-index
450    'haskell-doc-show-global-types
451    'haskell-doc-show-reserved
452    'haskell-doc-show-prelude
453    'haskell-doc-show-strategy
454    'haskell-doc-show-user-defined
455    'haskell-doc-idle-delay
456    'haskell-doc-argument-case
457    'haskell-doc-mode-message-commands
458   )
459   "List of variables sent via `haskell-doc-submit-bug-report'.")
460
461 ;;@node Prelude types, Test membership, Variables, Constants and Variables
462 ;;@subsection Prelude types
463
464 ;;@cindex haskell-doc-reserved-ids
465
466 (defvar haskell-doc-reserved-ids
467  (list
468   '("case" . "case exp of { alts [;] }")
469   '("class" . "class [context =>] simpleclass [where { cbody [;] }]")
470   '("data" . "data [context =>] simpletype = constrs [deriving]")
471   '("default" . "default (type1 , ... , typen)")
472   '("deriving" . "deriving (dclass | (dclass1, ... , dclassn))") ; used with data or newtype
473   '("do" . "do { stmts [;] }  stmts -> exp [; stmts] | pat <- exp ; stmts | let decllist ; stmts")
474   '("else" . "if exp then exp else exp")
475   '("if" . "if exp then exp else exp")
476   '("import" . "import [qualified] modid [as modid] [impspec]")
477   '("in" . "let decllist in exp")
478   '("infix" . "infix [digit] ops")
479   '("infixl" . "infixl [digit] ops")
480   '("infixr" . "infixr [digit] ops")
481   '("instance" . "instance [context =>] qtycls inst [where { valdefs [;] }]")
482   '("let" . "let { decl; ...; decl [;] } in exp")
483   '("module" . "module modid [exports] where body")
484   '("newtype" . "newtype [context =>] simpletype = con atype [deriving]")
485   '("of" . "case exp of { alts [;] }")
486   '("then" . "if exp then exp else exp")
487   '("type" . "type simpletype = type")
488   '("where" . "exp where { decl; ...; decl [;] }") ; check that ; see also class, instance, module
489   '("as" . "import [qualified] modid [as modid] [impspec]")
490   '("qualified" . "import [qualified] modid [as modid] [impspec]")
491   '("hiding" . "hiding ( import1 , ... , importn [ , ] )")
492  )
493  "An alist of reserved identifiers and a string describing the construct they are used in.")
494
495 ;;@cindex haskell-doc-prelude-types
496
497 (defvar haskell-doc-prelude-types
498   (list
499    ;; Prelude
500    '("!!" . "[a] -> Int -> a")
501    '("$" . "(a -> b) -> a -> b")
502    '("$!" . "(a -> b) -> (a -> b)")
503    '("&&" . "Bool -> Bool -> Bool")
504    '("||" . "Bool -> Bool -> Bool")
505    '("*" . "Num a => a -> a -> a")
506    '("**" . "Floating a => a -> a -> a")
507    '("+" . "Num a => a -> a -> a")
508    '("++" . "[a] -> [a] -> [a]")
509    '("-" . "Num a => a -> a -> a")
510    '("." . "(b -> c) -> (a -> b) -> a -> c")
511    '("/" . "Fractional a => a -> a -> a")
512    '("/=" . "Eq a => a -> a -> Bool")
513    '("<" . "Ord a => a -> a -> Bool")
514    '("<=" . "Ord a => a -> a -> Bool")
515    '("==" . "Eq a => a -> a -> Bool")
516    '("=<<" . "Monad a => (a -> m b) -> m a -> m b")
517    '(">" . "Ord a => a -> a -> Bool")
518    '(">=" . "Ord a => a -> a -> Bool")
519    '(">>" . "Monad m => m a -> m b -> m b")
520    '(">>=" . "Monad m => m a -> (a -> m b) -> m b")
521    '("^" . "(Num a, Integral b) => a -> b -> a")
522    '("^^" . "(Fractional a, Integral b) => a -> b -> a")
523    '("abs" . "Num a => a -> a")
524    '("sequence" . "Monad m => [m a] -> m [a]")
525    '("acos" . "Floating a => a -> a")
526    '("acosh" . "Floating a => a -> a")
527    '("all" . "(a -> Bool) -> [a] -> Bool")
528    '("and" . "[Bool] -> Bool")
529    '("any" . "(a -> Bool) -> [a] -> Bool")
530    '("appendFile" . "FilePath -> String -> IO ()")
531    '("applyM" . "Monad m => (a -> m b) -> m a -> m b")
532    '("asTypeOf" . "a -> a -> a")
533    '("asin" . "Floating a => a -> a")
534    '("asinh" . "Floating a => a -> a")
535    '("atan" . "Floating a => a -> a")
536    '("atan2" . "RealFrac a => a -> a")
537    '("atanh" . "Floating a => a -> a")
538    '("break" . "(a -> Bool) -> [a] -> ([a], [a])")
539    '("catch" . "IO a -> (IOError -> IO a) -> IO a")
540    '("ceiling" . "(RealFrac a, Integral b) => a -> b")
541    '("compare" . "Ord a => a -> a -> Ordering")
542    '("concat" . "MonadPlus m => [m a] -> m a")
543    '("concatMap" . "(a -> [b]) -> [a] -> [b]")
544    '("const" . "a -> b -> a")
545    '("cos" . "Floating a => a -> a")
546    '("cosh" . "Floating a => a -> a")
547    '("curry" . "((a, b) -> c) -> a -> b -> c")
548    '("cycle" . "[a] -> [a]")
549    '("decodeFloat" . "RealFloat a => a -> (Integer, Int)")
550    '("div" . "Integral a => a -> a -> a")
551    '("divMod" . "Integral a => a -> a -> (a, a)")
552    '("drop" . "Int -> [a] -> [a]")
553    '("dropWhile" . "(a -> Bool) -> [a] -> [a]")
554    '("elem" . "Eq a => a -> [a] -> Bool")
555    '("encodeFloat" . "RealFloat a => Integer -> Int -> a")
556    '("enumFrom" . "Enum a => a -> [a]")
557    '("enumFromThen" . "Enum a => a -> a -> [a]")
558    '("enumFromThenTo" . "Enum a => a -> a -> a -> [a]")
559    '("enumFromTo" . "Enum a => a -> a -> [a]")
560    '("error" . "String -> a")
561    '("even" . "Integral a => a -> Bool")
562    '("exp" . "Floating a => a -> a")
563    '("exponent" . "RealFloat a => a -> Int")
564    '("fail" . "Monad m => String -> m a")
565    '("flip" . "(a -> b -> c) -> (b -> a -> c)")
566    '("floatDigits" . "RealFloat a => a -> Int")
567    '("floatRadix" . "RealFloat a => a -> Integer")
568    '("floatRange" . "RealFloat a => a -> (Int, Int)")
569    '("floor" . "(RealFrac a, Integral b) => a -> b")
570    '("foldl" . "(a -> b -> a) -> a -> [b] -> a")
571    '("foldl1" . "(a -> a -> a) -> [a] -> a")
572    '("foldr" . "(a -> b -> b) -> b -> [a] -> b")
573    '("foldr1" . "(a -> a -> a) -> [a] -> a")
574    '("fromEnum" . "Enum a => a -> Int")
575    '("fromInteger" . "Num a => Integer -> a")
576    '("fromIntegral" . "(Integral a, Num b) => a -> b")
577    '("fromRational" . "Fractional a => Rational -> a")
578    '("fst" . "(a, b) -> a")
579    '("gcd" . "(Integral a) => a -> a -> a")
580    '("getChar" . "IO Char")
581    '("getContents" . "IO String")
582    '("getLine" . "IO String")
583    '("head" . "[a] -> a")
584    '("id" . "a -> a")
585    '("init" . "[a] -> [a]")
586    '("interact" . "(String -> String) -> IO ()")
587    '("ioError" . "IOError -> IO a")
588    '("isDenormalized" . "RealFloat a => a -> Bool")
589    '("isIEEE" . "RealFloat a => a -> Bool")
590    '("isInfinite" . "RealFloat a => a -> Bool")
591    '("isNaN" . "RealFloat a => a -> Bool")
592    '("isNegativeZero" . "RealFloat a => a -> Bool")
593    '("iterate" . "(a -> a) -> a -> [a]")
594    '("last" . "[a] -> a")
595    '("lcm" . "Integral a => a -> a -> a")
596    '("length" . "[a] -> Int")
597    '("lex" . "ReadS String")
598    '("lines" . "String -> [String]")
599    '("log" . "Floating a => a -> a")
600    '("logBase" . "Floating a => a -> a -> a")
601    '("lookup" . "Eq a => a -> [(a, b)] -> Maybe b")
602    '("map" . "Functor f => (a -> b) -> f a -> f b")
603    '("mapM" . "Monad m => (a -> m b) -> [a] -> m [b]")
604    '("mapM_" . "Monad m => (a -> m b) -> [a] -> m ()")
605    '("max" . "Ord a => a -> a -> a")
606    '("maxBound" . "Bounded a => a")
607    '("maximum" . "Ord a => [a] -> a")
608    '("maybe" . "b -> (a -> b) -> Maybe a -> b")
609    '("min" . "Ord a => a -> a -> a")
610    '("minBound" . "Bounded a => a")
611    '("minimum" . "Ord a => [a] -> a")
612    '("mod" . "Integral a => a -> a -> a")
613    '("negate" . "Num a => a -> a")
614    '("not" . "Bool -> Bool")
615    '("notElem" . "Eq a => a -> [a] -> Bool")
616    '("null" . "[a] -> Bool")
617    '("odd" . "Integral a => a -> Bool")
618    '("or" . "[Bool] -> Bool")
619    '("otherwise" . "Bool")
620    '("pi" . "Floating a => a")
621    '("pred" . "Enum a => a -> a")
622    '("print" . "Show a => IO ()")
623    '("product" . "Num a => [a] -> a")
624    '("properFraction" . "(RealFrac a, Integral b) => a -> (b, a)")
625    '("putChar" . "Char -> IO ()")
626    '("putStr" . "String -> IO ()")
627    '("putStrLn" . "String -> IO ()")
628    '("quot" . "Integral a => a -> a -> a")
629    '("quotRem" . "Integral a => a -> a -> (a, a)")
630    '("read" . "Read a => String -> a")
631    '("readFile" . "FilePath -> IO String")
632    '("readIO" . "Read a => String -> IO a")
633    '("readList" . "Read a => ReadS [a]")
634    '("readLn" . "Read a => IO a")
635    '("readParen" . "Bool -> ReadS a -> ReadS a")
636    '("reads" . "Read a => ReadS a")
637    '("readsPrec" . "Read a => Int -> ReadS a")
638    '("realToFrac" . "(Real a, Fractional b) => a -> b")
639    '("recip" . "Fractional a => a -> a")
640    '("rem" . "Integral a => a -> a -> a")
641    '("repeat" . "a -> [a]")
642    '("replicate" . "Int -> a -> [a]")
643    '("return" . "Monad m => a -> m a")
644    '("reverse" . "[a] -> [a]")
645    '("round" . "(RealFrac a, Integral b) => a -> b")
646    '("scaleFloat" . "RealFloat a => Int -> a -> a")
647    '("scanl" . "(a -> b -> a) -> a -> [b] -> [a]")
648    '("scanl1" . "(a -> a -> a) -> [a] -> [a]")
649    '("scanr" . "(a -> b -> b) -> b -> [a] -> [b]")
650    '("scanr1" . "(a -> a -> a) -> [a] -> [a]")
651    '("seq" . "Eval a => a -> a -> b")
652    '("sequence_" . "Monad m => [m a] -> m ()")
653    '("show" . "Show a => a -> String")
654    '("showChar" . "Char -> ShowS")
655    '("showList" . "Show a => [a] -> ShowS")
656    '("showParen" . "Bool -> ShowS -> ShowS")
657    '("showString" . "String -> ShowS")
658    '("shows" . "Show a => a -> ShowS")
659    '("showsPrec" . "Show a => Int -> a -> ShowS")
660    '("significand" . "RealFloat a => a -> a")
661    '("signum" . "Num a => a -> a")
662    '("sin" . "Floating a => a -> a")
663    '("sinh" . "Floating a => a -> a")
664    '("snd" . "(a, b) -> b")
665    '("span" . "(a -> Bool) -> [a] -> ([a], [a])")
666    '("splitAt" . "Int -> [a] -> ([a], [a])")
667    '("sqrt" . "Floating a => a -> a")
668    '("subtract" . "Num a => a -> a -> a")
669    '("succ" . "Enum a => a -> a")
670    '("sum" . "Num a => [a] -> a")
671    '("tail" . "[a] -> [a]")
672    '("take" . "Int -> [a] -> [a]")
673    '("takeWhile" . "(a -> Bool) -> [a] -> [a]")
674    '("tan" . "Floating a => a -> a")
675    '("tanh" . "Floating a => a -> a")
676    '("toEnum" . "Enum a => Int -> a")
677    '("toInteger" . "Integral a => a -> Integer")
678    '("toRational" . "Real a => a -> Rational")
679    '("truncate" . "(RealFrac a, Integral b) => a -> b")
680    '("uncurry" . "(a -> b -> c) -> ((a, b) -> c)")
681    '("undefined" . "a")
682    '("unlines" . "[String] -> String")
683    '("until" . "(a -> Bool) -> (a -> a) -> a -> a")
684    '("unwords" . "[String] -> String")
685    '("unzip" . "[(a, b)] -> ([a], [b])")
686    '("unzip3" . "[(a, b, c)] -> ([a], [b], [c])")
687    '("userError" . "String -> IOError")
688    '("words" . "String -> [String]")
689    '("writeFile" . "FilePath -> String -> IO ()")
690    '("zip" . "[a] -> [b] -> [(a, b)]")
691    '("zip3" . "[a] -> [b] -> [c] -> [(a, b, c)]")
692    '("zipWith" . "(a -> b -> c) -> [a] -> [b] -> [c]")
693    '("zipWith3" . "(a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]")
694    ;; Ratio
695    '("%" . "(Integral a) => a -> a -> Ratio a")
696    '("numerator" . "(Integral a) => Ratio a -> a")
697    '("denominator" . "(Integral a) => Ratio a -> a")
698    '("approxRational" . "(RealFrac a) => a -> a -> Rational")
699    ;; Complex
700    '("realPart" . "(RealFloat a) => Complex a -> a")
701    '("imagPart" . "(RealFloat a) => Complex a -> a")
702    '("conjugate" . "(RealFloat a) => Complex a -> Complex a")
703    '("mkPolar" . "(RealFloat a) => a -> a -> Complex a")
704    '("cis" . "(RealFloat a) => a -> Complex a")
705    '("polar" . "(RealFloat a) => Complex a -> (a,a)")
706    '("magnitude" . "(RealFloat a) => Complex a -> a")
707    '("phase" . "(RealFloat a) => Complex a -> a")
708    ;; Numeric
709    '("fromRat" . "(RealFloat a) => Rational -> a")
710    '("showSigned" . "(Real a) => (a -> ShowS) -> Int -> a -> ShowS")
711    '("showInt" . "Integral a => a -> ShowS")
712    '("readSigned" . "(Real a) => ReadS a -> ReadS a")
713    '("readInt" . "(Integral a) => a -> (Char -> Bool) -> (Char -> Int) -> ReadS a")
714    '("readDec" . "(Integral a) => ReadS a")
715    '("readOct" . "(Integral a) => ReadS a")
716    '("readHex" . "(Integral a) => ReadS a")
717    '("showEFloat" . "(RealFloat a) => Maybe Int -> a -> ShowS")
718    '("showFFloat" . "(RealFloat a) => Maybe Int -> a -> ShowS")
719    '("showGFloat" . "(RealFloat a) => Maybe Int -> a -> ShowS")
720    '("showFloat" . "(RealFloat a) => a -> ShowS")
721    '("floatToDigits" . "(RealFloat a) => Integer -> a -> ([Int], Int)")
722    '("readFloat" . "(RealFloat a) => ReadS a")
723    '("lexDigits" . "ReadS String")
724    ;; Ix
725    '("range" . "(Ix a) => (a,a) -> [a]")
726    '("index" . "(Ix a) => (a,a) -> a -> Int")
727    '("inRange" . "(Ix a) => (a,a) -> a -> Bool")
728    '("rangeSize" . "(Ix a) => (a,a) -> Int")
729    ;; Array
730    '("array" . "(Ix a) => (a,a) -> [(a,b)] -> Array a b")
731    '("listArray" . "(Ix a) => (a,a) -> [b] -> Array a b")
732    '("!" . "(Ix a) => Array a b -> a -> b")
733    '("bounds" . "(Ix a) => Array a b -> (a,a)")
734    '("indices" . "(Ix a) => Array a b -> [a]")
735    '("elems" . "(Ix a) => Array a b -> [b]")
736    '("assocs" . "(Ix a) => Array a b -> [(a,b)]")
737    '("accumArray" . "(Ix a) => (b -> c -> b) -> b -> (a,a) -> [(a,c)] -> Array a b")
738    '("//" . "(Ix a) => Array a b -> [(a,b)] -> Array a b")
739    '("accum" . "(Ix a) => (b -> c -> b) -> Array a b -> [(a,c)] -> Array a b")
740    '("ixmap" . "(Ix a, Ix b) => (a,a) -> (a -> b) -> Array b c -> Array a c")
741    ;; List
742    '("elemIndex" . "Eq a => a -> [a] -> Maybe Int")
743    '("elemIndices" . "Eq a => a -> [a] -> [Int]")
744    '("find" . "(a -> Bool) -> [a] -> Maybe a")
745    '("findIndex" . "(a -> Bool) -> [a] -> Maybe Int")
746    '("findIndices" . "(a -> Bool) -> [a] -> [Int]")
747    '("nub" . "Eq a => [a] -> [a]")
748    '("nubBy" . "(a -> a -> Bool) -> [a] -> [a]")
749    '("delete" . "Eq a => a -> [a] -> [a]")
750    '("deleteBy" . "(a -> a -> Bool) -> a -> [a] -> [a]")
751    '("\\\\" . "Eq a => [a] -> [a] -> [a]")
752    '("deleteFirstsBy" . "(a -> a -> Bool) -> [a] -> [a] -> [a]")
753    '("union" . "Eq a => [a] -> [a] -> [a]")
754    '("unionBy" . "(a -> a -> Bool) -> [a] -> [a] -> [a]")
755    '("intersect" . "Eq a => [a] -> [a] -> [a]")
756    '("intersectBy" . "(a -> a -> Bool) -> [a] -> [a] -> [a]")
757    '("intersperse" . "a -> [a] -> [a]")
758    '("transpose" . "[[a]] -> [[a]]")
759    '("partition" . "(a -> Bool) -> [a] -> ([a],[a])")
760    '("group" . "Eq a => [a] -> [[a]]")
761    '("groupBy" . "(a -> a -> Bool) -> [a] -> [[a]]")
762    '("inits" . "[a] -> [[a]]")
763    '("tails" . "[a] -> [[a]]")
764    '("isPrefixOf" . "Eq a => [a] -> [a] -> Bool")
765    '("isSuffixOf" . "Eq a => [a] -> [a] -> Bool")
766    '("mapAccumL" . "(a -> b -> (a, c)) -> a -> [b] -> (a, [c])")
767    '("mapAccumR" . "(a -> b -> (a, c)) -> a -> [b] -> (a, [c])")
768    '("unfoldr" . "(b -> Maybe (a,b)) -> b -> [a]")
769    '("sort" . "Ord a => [a] -> [a]")
770    '("sortBy" . "(a -> a -> Ordering) -> [a] -> [a]")
771    '("insert" . "Ord a => a -> [a] -> [a]")
772    '("insertBy" . "(a -> a -> Ordering) -> a -> [a] -> [a]")
773    '("maximumBy" . "(a -> a -> Ordering) -> [a] -> a")
774    '("minimumBy" . "(a -> a -> Ordering) -> [a] -> a")
775    '("genericLength" . "Integral a => [b] -> a")
776    '("genericTake" . "Integral a => a -> [b] -> [b]")
777    '("genericDrop" . "Integral a => a -> [b] -> [b]")
778    '("genericSplitAt" . "Integral a => a -> [b] -> ([b],[b])")
779    '("genericIndex" . "Integral a => [b] -> a -> b")
780    '("genericReplicate" . "Integral a => a -> b -> [b]")
781    '("zip4" . "[a] -> [b] -> [c] -> [d] -> [(a,b,c,d)]")
782    '("zip5" . "[a] -> [b] -> [c] -> [d] -> [e] -> [(a,b,c,d,e)]")
783    '("zip6" . "[a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [(a,b,c,d,e,f)]")
784    '("zip7" . "[a] -> [b] -> [c] -> [d] -> [e] -> [f] -> [g] -> [(a,b,c,d,e,f,g)]")
785    '("zipWith4" . "(a->b->c->d->e) -> [a]->[b]->[c]->[d]->[e]")
786    '("zipWith5" . "(a->b->c->d->e->f) -> [a]->[b]->[c]->[d]->[e]->[f]")
787    '("zipWith6" . "(a->b->c->d->e->f->g) -> [a]->[b]->[c]->[d]->[e]->[f]->[g]")
788    '("zipWith7" . "(a->b->c->d->e->f->g->h) -> [a]->[b]->[c]->[d]->[e]->[f]->[g]->[h]")
789    '("unzip4" . "[(a,b,c,d)] -> ([a],[b],[c],[d])")
790    '("unzip5" . "[(a,b,c,d,e)] -> ([a],[b],[c],[d],[e])")
791    '("unzip6" . "[(a,b,c,d,e,f)] -> ([a],[b],[c],[d],[e],[f])")
792    '("unzip7" . "[(a,b,c,d,e,f,g)] -> ([a],[b],[c],[d],[e],[f],[g])")
793    ;; Maybe
794    '("isJust" . "Maybe a -> Bool")
795    '("isNothing" . "Maybe a -> Bool")
796    '("fromJust" . "Maybe a -> a")
797    '("fromMaybe" . "a -> Maybe a -> a")
798    '("listToMaybe" . "[a] -> Maybe a")
799    '("maybeToList" . "Maybe a -> [a]")
800    '("catMaybes" . "[Maybe a] -> [a]")
801    '("mapMaybe" . "(a -> Maybe b) -> [a] -> [b]")
802    ;; Char
803    '("isAscii" . "Char -> Bool")
804    '("isLatin1" . "Char -> Bool")
805    '("isControl" . "Char -> Bool")
806    '("isPrint" . "Char -> Bool")
807    '("isSpace" . "Char -> Bool")
808    '("isUpper" . "Char -> Bool")
809    '("isLower" . "Char -> Bool")
810    '("isAlpha" . "Char -> Bool")
811    '("isDigit" . "Char -> Bool")
812    '("isOctDigit" . "Char -> Bool")
813    '("isHexDigit" . "Char -> Bool")
814    '("isAlphaNum" . "Char -> Bool")
815    '("toUpper" . "Char -> Char")
816    '("toLower" . "Char -> Char")
817    '("digitToInt" . "Char -> Int")
818    '("intToDigit" . "Int -> Char")
819    '("ord" . "Char -> Int")
820    '("chr" . "Int -> Char")
821    '("lexLitChar" . "ReadS String")
822    '("readLitChar" . "ReadS Char")
823    '("showLitChar" . "Char -> ShowS")
824    ;; Monad
825    '("mzero" . "(MonadPlus m) => m a")
826    '("mplus" . "(MonadPlus m) => m a -> m a -> m a")
827    '("join" . "Monad m => m (m a) -> m a")
828    '("guard" . "MonadPlus m => Bool -> m ()")
829    '("when" . "Monad m => Bool -> m () -> m ()")
830    '("unless" . "Monad m => Bool -> m () -> m ()")
831    '("ap" . "Monad m => m (a -> b) -> m a -> m b")
832    '("mapAndUnzipM" . "Monad m => (a -> m (b,c)) -> [a] -> m ([b], [c])")
833    '("zipWithM" . "Monad m => (a -> b -> m c) -> [a] -> [b] -> m [c]")
834    '("zipWithM_" . "Monad m => (a -> b -> m c) -> [a] -> [b] -> m ()")
835    '("foldM" . "Monad m => (a -> b -> m a) -> a -> [b] -> m a")
836    '("filterM" . "Monad m => (a -> m Bool) -> [a] -> m [a]")
837    '("msum" . "MonadPlus m => [m a] -> m a")
838    '("liftM" . "Monad m => (a -> b) -> (m a -> m b)")
839    '("liftM2" . "Monad m => (a -> b -> c) -> (m a -> m b -> m c)")
840    '("liftM3" . "Monad m => (a -> b -> c -> d) -> (m a -> m b -> m c -> m d)")
841    '("liftM4" . "Monad m => (a -> b -> c -> d -> e) -> (m a -> m b -> m c -> m d -> m e)")
842    '("liftM5" . "Monad m => (a -> b -> c -> d -> e -> f) -> (m a -> m b -> m c -> m d -> m e -> m f)")
843    ;; IO
844    '("stdin" . "Handle")
845    '("stdout" . "Handle")
846    '("stderr" . "Handle")
847    '("openFile" . "FilePath -> IOMode -> IO Handle")
848    '("hClose" . "Handle -> IO ()")
849    '("hFileSize" . "Handle -> IO Integer")
850    '("hIsEOF" . "Handle -> IO Bool")
851    '("isEOF" . "IO Bool")
852    '("hSetBuffering" . "Handle -> BufferMode -> IO ()")
853    '("hGetBuffering" . "Handle -> IO BufferMode")
854    '("hFlush" . "Handle -> IO ()")
855    '("hGetPosn" . "Handle -> IO HandlePosn")
856    '("hSetPosn" . "HandlePosn -> IO ()")
857    '("hSeek" . "Handle -> SeekMode -> Integer -> IO ()")
858    '("hWaitForInput" . "Handle -> Int -> IO Bool")
859    '("hReady" . "Handle -> IO Bool")
860    '("hGetChar" . "Handle -> IO Char")
861    '("hGetLine" . "Handle -> IO String")
862    '("hLookAhead" . "Handle -> IO Char")
863    '("hGetContents" . "Handle -> IO String")
864    '("hPutChar" . "Handle -> Char -> IO ()")
865    '("hPutStr" . "Handle -> String -> IO ()")
866    '("hPutStrLn" . "Handle -> String -> IO ()")
867    '("hPrint" . "Show a => Handle -> a -> IO ()")
868    '("hIsOpen" . "Handle -> IO Bool")
869    '("hIsClosed" . "Handle -> IO Bool")
870    '("hIsReadable" . "Handle -> IO Bool")
871    '("hIsWritable" . "Handle -> IO Bool")
872    '("hIsSeekable" . "Handle -> IO Bool")
873    '("isAlreadyExistsError" . "IOError -> Bool")
874    '("isDoesNotExistError" . "IOError -> Bool")
875    '("isAlreadyInUseError" . "IOError -> Bool")
876    '("isFullError" . "IOError -> Bool")
877    '("isEOFError" . "IOError -> Bool")
878    '("isIllegalOperation" . "IOError -> Bool")
879    '("isPermissionError" . "IOError -> Bool")
880    '("isUserError" . "IOError -> Bool")
881    '("ioeGetErrorString" . "IOError -> String")
882    '("ioeGetHandle" . "IOError -> Maybe Handle")
883    '("ioeGetFileName" . "IOError -> Maybe FilePath")
884    '("try" . "IO a -> Either IOError a")
885    '("bracket" . "IO a -> (a -> IO b) -> (a -> IO c) -> IO c")
886    '("bracket_" . "IO a -> (a -> IO b) -> IO c -> IO c")
887    ;; Directory
888    '("readable" . "Permissions -> Bool")
889    '("writable" . "Permissions -> Bool")
890    '("executable" . "Permissions -> Bool")
891    '("searchable" . "Permissions -> Bool")
892    '("createDirectory" . "FilePath -> IO ()")
893    '("removeDirectory" . "FilePath -> IO ()")
894    '("removeFile" . "FilePath -> IO ()")
895    '("renameDirectory" . "FilePath -> FilePath -> IO ()")
896    '("renameFile" . "FilePath -> FilePath -> IO ()")
897    '("getDirectoryContents" . "FilePath -> IO [FilePath]")
898    '("getCurrentDirectory" . "IO FilePath")
899    '("setCurrentDirectory" . "FilePath -> IO ()")
900    '("doesFileExist" . "FilePath -> IO Bool")
901    '("doesDirectoryExist" . "FilePath -> IO Bool")
902    '("getPermissions" . "FilePath -> IO Permissions")
903    '("setPermissions" . "FilePath -> Permissions -> IO ()")
904    '("getModificationTime" . "FilePath -> IO ClockTime")
905    ;; System
906    '("getArgs" . "IO [String]")
907    '("getProgName" . "IO String")
908    '("getEnv" . "String -> IO String")
909    '("system" . "String -> IO ExitCode")
910    '("exitWith" . "ExitCode -> IO a")
911    '("exitFailure" . "IO a")
912    ;; Time
913    '("ctYear" . "CalendarTime -> Int")
914    '("ctMonth" . "CalendarTime -> Month")
915    '("ctDay" . "CalendarTime -> Int")
916    '("ctHour" . "CalendarTime -> Int")
917    '("ctMin" . "CalendarTime -> Int")
918    '("ctSec" . "CalendarTime -> Int")
919    '("ctPicosec" . "CalendarTime -> Integer")
920    '("ctWDay" . "CalendarTime -> Day")
921    '("ctYDay" . "CalendarTime -> Int")
922    '("ctTZName" . "CalendarTime -> String")
923    '("ctTZ" . "CalendarTime -> Int")
924    '("ctIsDST" . "CalendarTime -> Bool")
925    '("tdYear" . "TimeDiff -> Int")
926    '("tdMonth" . "TimeDiff -> Int")
927    '("tdDay" . "TimeDiff -> Int")
928    '("tdHour" . "TimeDiff -> Int")
929    '("tdMin" . "TimeDiff -> Int")
930    '("tdSec" . "TimeDiff -> Int")
931    '("tdPicosec" . "TimeDiff -> Integer")
932    '("getClockTime" . "IO ClockTime")
933    '("addToClockTime" . "TimeDiff -> ClockTime -> ClockTime")
934    '("diffClockTimes" . "ClockTime -> ClockTime -> TimeDiff")
935    '("toCalendarTime" . "ClockTime -> IO CalendarTime")
936    '("toUTCTime" . "ClockTime -> CalendarTime")
937    '("toClockTime" . "CalendarTime -> ClockTime")
938    '("calendarTimeToString" . "CalendarTime -> String")
939    '("formatCalendarTime" . "TimeLocale -> String -> CalendarTime -> String")
940    ;; Locale
941    '("wDays" . "TimeLocale -> [(String, String)]")
942    '("months" . "TimeLocale -> [(String, String)]")
943    '("amPm" . "TimeLocale -> (String, String)")
944    '("dateTimeFmt" . "TimeLocale -> String")
945    '("dateFmt" . "TimeLocale -> String")
946    '("timeFmt" . "TimeLocale -> String")
947    '("time12Fmt" . "TimeLocale -> String")
948    '("defaultTimeLocale" . "TimeLocale")
949    ;; CPUTime
950    '("getCPUTime" . "IO Integer")
951    '("cpuTimePrecision" . "Integer")
952    ;; Random
953    '("next" . "(RandomGen g) => g -> (Int, g)")
954    '("split" . "(RandomGen g) => g -> (g, g)")
955    '("mkStdGen" . "Int -> StdGen")
956    '("randomR" . "(Random a, RandomGen g) => (a, a) -> g -> (a, g)")
957    '("random" . "(Random a, RandomGen g) => g -> (a, g)")
958    '("randomRs" . "(Random a, RandomGen g) => (a, a) -> g -> [a]")
959    '("randoms" . "(Random a, RandomGen g) => g -> [a]")
960    '("randomRIO" . "(Random a) => (a,a) -> IO a")
961    '("randomIO" . "(Random a) => IO a")
962    '("newStdGen" . "IO StdGen")
963    '("setStdGen" . "StdGen -> IO ()")
964    '("getStdGen" . "IO StdGen")
965    '("getStdRandom" . "(StdGen -> (a, StdGen)) -> IO a"))
966   "alist of prelude functions and their types.")
967
968 ;;@cindex haskell-doc-strategy-ids
969
970 (defvar haskell-doc-strategy-ids
971  (list
972   '("par"  . "Done -> Done -> Done ; [infixr 0]")
973   '("seq"  . "Done -> Done -> Done ; [infixr 1]")
974
975   '("using"      . "a -> Strategy a -> a ; [infixl 0]")
976   '("demanding"  . "a -> Done -> a ; [infixl 0]")
977   '("sparking"   . "a -> Done -> a ; [infixl 0]")
978
979   '(">||" . "Done -> Done -> Done ; [infixr 2]")
980   '(">|" .  "Done -> Done -> Done ; [infixr 3]")
981   '("$||" . "(a -> b) -> Strategy a -> a -> b ; [infixl 6]")
982   '("$|"  . "(a -> b) -> Strategy a -> a -> b ; [infixl 6]")
983   '(".|"  . "(b -> c) -> Strategy b -> (a -> b) -> (a -> c) ; [infixl 9]")
984   '(".||" . "(b -> c) -> Strategy b -> (a -> b) -> (a -> c) ; [infixl 9]")
985   '("-|"  . "(a -> b) -> Strategy b -> (b -> c) -> (a -> c) ; [infixl 9]")
986   '("-||" . "(a -> b) -> Strategy b -> (b -> c) -> (a -> c) ; [infixl 9]")
987
988   '("Done" . "type Done = ()")
989   '("Strategy" . "type Strategy a = a -> Done")
990
991   '("r0"    . "Strategy a")
992   '("rwhnf" . "Eval a => Strategy a")
993   '("rnf" . "Strategy a")
994   '("NFData" . "class Eval a => NFData a where rnf :: Strategy a")
995   '("NFDataIntegral" ."class (NFData a, Integral a) => NFDataIntegral a")
996   '("NFDataOrd" . "class (NFData a, Ord a) => NFDataOrd a")
997
998   '("markStrat" . "Int -> Strategy a -> Strategy a")
999
1000   '("seqPair" . "Strategy a -> Strategy b -> Strategy (a,b)")
1001   '("parPair" . "Strategy a -> Strategy b -> Strategy (a,b)")
1002   '("seqTriple" . "Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)")
1003   '("parTriple" . "Strategy a -> Strategy b -> Strategy c -> Strategy (a,b,c)")
1004
1005   '("parList"  . "Strategy a -> Strategy [a]")
1006   '("parListN"  . "(Integral b) => b -> Strategy a -> Strategy [a]")
1007   '("parListNth"  . "Int -> Strategy a -> Strategy [a]")
1008   '("parListChunk"  . "Int -> Strategy a -> Strategy [a]")
1009   '("parMap"  . "Strategy b -> (a -> b) -> [a] -> [b]")
1010   '("parFlatMap"  . "Strategy [b] -> (a -> [b]) -> [a] -> [b]")
1011   '("parZipWith"  . "Strategy c -> (a -> b -> c) -> [a] -> [b] -> [c]")
1012   '("seqList"  . "Strategy a -> Strategy [a]")
1013   '("seqListN"  . "(Integral a) => a -> Strategy b -> Strategy [b]")
1014   '("seqListNth"  . "Int -> Strategy b -> Strategy [b]")
1015
1016   '("parBuffer"  . "Int -> Strategy a -> [a] -> [a]")
1017
1018   '("seqArr"  . "(Ix b) => Strategy a -> Strategy (Array b a)")
1019   '("parArr"  . "(Ix b) => Strategy a -> Strategy (Array b a)")
1020
1021   '("fstPairFstList"  . "(NFData a) => Strategy [(a,b)]")
1022   '("force"  . "(NFData a) => a -> a ")
1023   '("sforce"  . "(NFData a) => a -> b -> b")
1024   )
1025 "alist of strategy functions and their types as defined in Strategies.lhs.")
1026
1027 (defvar haskell-doc-user-defined-ids nil
1028  "alist of functions and strings defined by the user.")
1029
1030 ;;@node Test membership,  , Prelude types, Constants and Variables
1031 ;;@subsection Test membership
1032
1033 ;;@cindex haskell-doc-is-of
1034 (defsubst haskell-doc-is-of (fn types)
1035   "Check whether FN is one of the functions in the alist TYPES and return the type."
1036   (assoc fn types) )
1037
1038 ;;@node Install as minor mode, Menubar Support, Constants and Variables, top
1039 ;;@section Install as minor mode
1040
1041 ;; Put this minor mode on the global minor-mode-alist.
1042 (or (assq 'haskell-doc-mode (default-value 'minor-mode-alist))
1043     (setq-default minor-mode-alist
1044                   (append (default-value 'minor-mode-alist)
1045                           '((haskell-doc-mode haskell-doc-minor-mode-string)))))
1046
1047 \f
1048 ;;@node Menubar Support, Haskell Doc Mode, Install as minor mode, top
1049 ;;@section Menubar Support
1050
1051 ;; get imenu
1052 (require 'imenu)
1053
1054 ;; a dummy definition needed for xemacs (I know, it's horrible :-(
1055
1056 ;;@cindex haskell-doc-install-keymap
1057
1058 (defvar haskell-doc-keymap
1059   (let ((map (make-sparse-keymap)))
1060     (define-key map [visit]
1061       '("Visit FTP home site" . haskell-doc-visit-home))
1062     (define-key map [submit]
1063       '("Submit bug report" . haskell-doc-submit-bug-report))
1064     (define-key map [dummy] '("---" . nil))
1065     (define-key map [make-index]
1066       '("Make global fct index" . haskell-doc-make-global-fct-index))
1067     (define-key map [global-types-on]
1068       '("Toggle display of global types" . haskell-doc-show-global-types))
1069     (define-key map [strategy-on]
1070       '("Toggle display of strategy ids" . haskell-doc-show-strategy))
1071     (define-key map [user-defined-on]
1072       '("Toggle display of user defined ids" . haskell-doc-show-user-defined))
1073     (define-key map [prelude-on]
1074       '("Toggle display of prelude functions" . haskell-doc-show-prelude))
1075     (define-key map [reserved-ids-on]
1076       '("Toggle display of reserved ids" . haskell-doc-show-reserved))
1077     (define-key map [haskell-doc-on]
1078       '("Toggle haskell-doc mode" . haskell-doc-mode))
1079     map))
1080
1081 (defun haskell-doc-install-keymap ()
1082   "Install a menu for `haskell-doc-mode' as a submenu of \"Hugs\"."
1083   (interactive)
1084   ;; Add the menu to the hugs menu as last entry.
1085   (let ((hugsmap (lookup-key (current-local-map) [menu-bar Hugs])))
1086     (if (not (or (featurep 'xemacs) ; XEmacs has problems here
1087                  (not (keymapp hugsmap))
1088                  (lookup-key hugsmap [haskell-doc])))
1089         (if (functionp 'define-key-after)
1090             (define-key-after hugsmap [haskell-doc]
1091               (cons "Haskell-doc" haskell-doc-keymap)
1092               [Haskell-doc mode]))))
1093   ;; Add shortcuts for these commands.
1094   (local-set-key "\C-c\e/" 'haskell-doc-check-active)
1095   ;; Conflicts with the binding of haskell-insert-otherwise.
1096   ;; (local-set-key "\C-c\C-o" 'haskell-doc-mode)
1097   (local-set-key [(control shift meta mouse-3)]
1098                  'haskell-doc-ask-mouse-for-type))
1099
1100 \f
1101 ;;@node Haskell Doc Mode, Switch it on or off, Menubar Support, top
1102 ;;@section Haskell Doc Mode
1103
1104 ;;@cindex haskell-doc-mode
1105
1106 ;;;###autoload
1107 (defun haskell-doc-mode (&optional arg)
1108   "Enter `haskell-doc-mode' for showing fct types in the echo area.
1109 See variable docstring."
1110   (interactive (list (or current-prefix-arg 'toggle)))
1111
1112   ;; Make sure it's on the post-command-idle-hook if defined, otherwise put
1113   ;; it on post-command-hook.  The former first appeared in Emacs 19.30.
1114   (setq haskell-doc-mode
1115         (cond
1116          ((eq arg 'toggle) (not haskell-doc-mode))
1117          (arg (> (prefix-numeric-value arg) 0))
1118          (t)))
1119
1120   (cond
1121    (haskell-doc-mode
1122     ;; Turning the mode ON.
1123
1124     ;; ToDo: replace binding of `post-command-idle-hook' by
1125     ;; `run-with-idle-timer'
1126     (add-hook (if (boundp 'post-command-idle-hook)
1127                   'post-command-idle-hook
1128                 'post-command-hook)
1129               'haskell-doc-mode-print-current-symbol-info nil 'local)
1130     (and haskell-doc-show-global-types
1131          (haskell-doc-make-global-fct-index)) ; build type index for global fcts
1132
1133     (haskell-doc-install-keymap)
1134
1135     (run-hooks 'haskell-doc-mode-hook))
1136
1137    ((not haskell-doc-mode)
1138
1139     (remove-hook (if (boundp 'post-command-idle-hook)
1140                      'post-command-idle-hook
1141                    'post-command-hook)
1142                  'haskell-doc-mode-print-current-symbol-info 'local)))
1143
1144   (and (interactive-p)
1145        (message "haskell-doc-mode is %s"
1146                 (if haskell-doc-mode "enabled" "disabled")))
1147   haskell-doc-mode)
1148
1149 (defmacro haskell-doc-toggle-var (id prefix)
1150   ;; toggle variable or set it based on prefix value
1151   `(setq ,id
1152          (if ,prefix
1153              (>= (prefix-numeric-value ,prefix) 0)
1154            (not ,id))) )
1155
1156 ;;@cindex haskell-doc-show-global-types
1157 (defun haskell-doc-show-global-types (&optional prefix)
1158   "Turn on global types information in `haskell-doc-mode'."
1159   (interactive "P")
1160   (haskell-doc-toggle-var haskell-doc-show-global-types prefix)
1161   (if haskell-doc-show-global-types
1162       (haskell-doc-make-global-fct-index)))
1163
1164 ;;@cindex haskell-doc-show-reserved
1165 (defun haskell-doc-show-reserved (&optional prefix)
1166   "Toggle the automatic display of a doc string for reserved ids."
1167   (interactive "P")
1168   (haskell-doc-toggle-var haskell-doc-show-reserved prefix))
1169
1170 ;;@cindex haskell-doc-show-prelude
1171 (defun haskell-doc-show-prelude (&optional prefix)
1172   "Toggle the automatic display of a doc string for reserved ids."
1173   (interactive "P")
1174   (haskell-doc-toggle-var haskell-doc-show-prelude prefix))
1175
1176 ;;@cindex haskell-doc-show-strategy
1177 (defun haskell-doc-show-strategy (&optional prefix)
1178   "Toggle the automatic display of a doc string for strategy ids."
1179   (interactive "P")
1180   (haskell-doc-toggle-var haskell-doc-show-strategy prefix))
1181
1182 ;;@cindex haskell-doc-show-user-defined
1183 (defun haskell-doc-show-user-defined (&optional prefix)
1184   "Toggle the automatic display of a doc string for user defined ids."
1185   (interactive "P")
1186   (haskell-doc-toggle-var haskell-doc-show-user-defined prefix))
1187
1188 ;;@node Switch it on or off, Check, Haskell Doc Mode, top
1189 ;;@section Switch it on or off
1190
1191 ;;@cindex turn-on-haskell-doc-mode
1192
1193 ;;;###autoload
1194 (defalias 'turn-on-haskell-doc-mode 'haskell-doc-mode)
1195
1196 ;;@cindex  turn-off-haskell-doc-mode
1197
1198 (defun turn-off-haskell-doc-mode ()
1199   "Unequivocally turn off `haskell-doc-mode' (see variable documentation)."
1200   (interactive)
1201   (haskell-doc-mode 0))
1202
1203 ;;@node Check, Top level function, Switch it on or off, top
1204 ;;@section Check
1205
1206 ;;@cindex haskell-doc-check-active
1207
1208 (defun haskell-doc-check-active ()
1209   "Check whether the print function is hooked in.
1210 Should be the same as the value of `haskell-doc-mode' but alas currently it
1211 is not."
1212   (interactive)
1213   (message
1214    (if (memq 'haskell-doc-mode-print-current-symbol-info
1215              (if (boundp 'post-command-idle-hook)
1216                  post-command-idle-hook
1217                post-command-hook))
1218        "haskell-doc is ACTIVE"
1219      (substitute-command-keys
1220       "haskell-doc is not ACTIVE \(Use C-u \\[haskell-doc-mode] to turn it on\)"))))
1221
1222 ;;@node Top level function, Mouse interface, Check, top
1223 ;;@section Top level function
1224
1225 ;;@cindex haskell-doc-mode-print-current-symbol-info
1226 ;; This is the function hooked into the elisp command engine
1227 (defun haskell-doc-mode-print-current-symbol-info ()
1228  "Print the type of the symbol under the cursor.
1229
1230 This function is hooked into the `post-command-idle-hook' to print the type
1231 automatically if `haskell-doc-mode' is turned on. It can also be called
1232 directly to ask for the type of a function."
1233   (interactive)
1234   (and haskell-doc-mode
1235        (not executing-kbd-macro)
1236        ;; Having this mode operate in the minibuffer makes it impossible to
1237        ;; see what you're doing.
1238        (not (eq (selected-window) (minibuffer-window)))
1239        ;; take a nap
1240        (sit-for haskell-doc-idle-delay)
1241        ;; good morning! read the word under the cursor for breakfast
1242        (haskell-doc-show-type)))
1243        ;; ;; ToDo: find surrounding fct
1244        ;; (cond ((eq current-symbol current-fnsym)
1245        ;;        (haskell-doc-show-type current-fnsym))
1246        ;;       (t
1247        ;;        (or nil ; (haskell-doc-print-var-docstring current-symbol)
1248        ;;            (haskell-doc-show-type current-fnsym)))))))
1249
1250 (defun haskell-doc-current-info ()
1251   "Return the info about symbol at point.
1252 Meant for `eldoc-print-current-symbol-info-function'."
1253   (haskell-doc-sym-doc (haskell-doc-get-current-word)))
1254
1255 \f
1256 ;;@node Mouse interface, Print fctsym, Top level function, top
1257 ;;@section Mouse interface for interactive query
1258
1259 ;;@cindex haskell-doc-ask-mouse-for-type
1260 (defun haskell-doc-ask-mouse-for-type (event)
1261  "Read the identifier under the mouse and echo its type.
1262 This uses the same underlying function `haskell-doc-show-type' as the hooked
1263 function. Only the user interface is different."
1264  (interactive "e")
1265  (save-excursion
1266    (select-window (posn-window (event-end event)))
1267    (goto-char (posn-point (event-end event)))
1268    (haskell-doc-show-type)))
1269
1270
1271 ;;@node Print fctsym, Movement, Mouse interface, top
1272 ;;@section Print fctsym
1273
1274 ;;@menu
1275 ;;* Show type::
1276 ;;* Aux::
1277 ;;* Global fct type::
1278 ;;* Local fct type::
1279 ;;@end menu
1280
1281 ;;@node Show type, Aux, Print fctsym, Print fctsym
1282 ;;@subsection Show type
1283
1284 ;;@cindex haskell-doc-show-type
1285
1286 ;;;###autoload
1287 (defun haskell-doc-show-type (&optional sym)
1288   "Show the type of the function near point.
1289 For the function under point, show the type in the echo area.
1290 This information is extracted from the `haskell-doc-prelude-types' alist
1291 of prelude functions and their types, or from the local functions in the
1292 current buffer."
1293   (interactive)
1294   (unless sym (setq sym (haskell-doc-get-current-word)))
1295   ;; if printed before do not print it again
1296   (unless (string= sym (car haskell-doc-last-data))
1297     (let ((doc (haskell-doc-sym-doc sym)))
1298       (when doc
1299         ;; In emacs 19.29 and later, and XEmacs 19.13 and later, all
1300         ;; messages are recorded in a log.  Do not put haskell-doc messages
1301         ;; in that log since they are legion.
1302         (if (eval-when-compile (fboundp 'display-message))
1303             ;; XEmacs 19.13 way of preventing log messages.
1304             ;;(display-message 'no-log (format <args>))
1305             ;; XEmacs 19.15 seems to be a bit different.
1306             (display-message 'message (format "%s" doc))
1307           (let ((message-log-max nil))
1308             (message "%s" doc)))))))
1309
1310
1311 (defun haskell-doc-sym-doc (sym)
1312   "Show the type of the function near point.
1313 For the function under point, show the type in the echo area.
1314 This information is extracted from the `haskell-doc-prelude-types' alist
1315 of prelude functions and their types, or from the local functions in the
1316 current buffer."
1317   (let ((i-am-prelude nil)
1318         (i-am-fct nil)
1319         (type nil)
1320         (is-reserved (haskell-doc-is-of sym haskell-doc-reserved-ids))
1321         (is-prelude  (haskell-doc-is-of sym haskell-doc-prelude-types))
1322         (is-strategy (haskell-doc-is-of sym haskell-doc-strategy-ids))
1323         (is-user-defined (haskell-doc-is-of sym haskell-doc-user-defined-ids))
1324         (is-prelude  (haskell-doc-is-of sym haskell-doc-prelude-types)))
1325    (cond
1326           ;; if reserved id (i.e. Haskell keyword
1327           ((and haskell-doc-show-reserved
1328                is-reserved)
1329            (setq type (cdr is-reserved))
1330            (setcdr haskell-doc-last-data type))
1331           ;; if built-in function get type from docstring
1332           ((and (not (null haskell-doc-show-prelude))
1333                 is-prelude)
1334            (setq type (cdr is-prelude)) ; (cdr (assoc sym haskell-doc-prelude-types)))
1335            (if (= 2 (length type)) ; horrible hack to remove bad formatting
1336                (setq type (car (cdr type))))
1337            (setq i-am-prelude t)
1338            (setq i-am-fct t)
1339            (setcdr haskell-doc-last-data type))
1340           ((and haskell-doc-show-strategy
1341                is-strategy)
1342            (setq i-am-fct t)
1343            (setq type (cdr is-strategy))
1344            (setcdr haskell-doc-last-data type))
1345           ((and haskell-doc-show-user-defined
1346                is-user-defined)
1347            ;; (setq i-am-fct t)
1348            (setq type (cdr is-user-defined))
1349            (setcdr haskell-doc-last-data type))
1350           (t
1351            (let ( (x (haskell-doc-get-and-format-fct-type sym)) )
1352              (if (null x)
1353                  (setcdr haskell-doc-last-data nil) ; if not found reset last data
1354                (setq type (car x))
1355                (setq i-am-fct (string= "Variables" (cdr x)))
1356                (if (and haskell-doc-show-global-types (null type))
1357                    (setq type (haskell-doc-get-global-fct-type sym)))
1358                (setcdr haskell-doc-last-data type)))) )
1359     ;; ToDo: encode i-am-fct info into alist of types
1360     (and type
1361          ;; drop `::' if it's not a fct
1362          (let ( (str (cond ((and i-am-fct (not haskell-doc-chop-off-fctname))
1363                             (format "%s :: %s" sym type))
1364                            (t
1365                             (format "%s" type)))) )
1366            (if i-am-prelude
1367                (add-text-properties 0 (length str) '(face bold) str))
1368            str))))
1369
1370
1371 ;; ToDo: define your own notion of `near' to find surrounding fct
1372 ;;(defun haskell-doc-fnsym-in-current-sexp ()
1373 ;;  (let* ((p (point))
1374 ;;         (sym (progn
1375 ;;              (forward-word -1)
1376 ;;                (while (and (forward-word -1) ; (haskell-doc-forward-sexp-safe -1)
1377 ;;                            (> (point) (point-min))))
1378 ;;                (cond ((or (= (point) (point-min))
1379 ;;                           (memq (or (char-after (point)) 0)
1380 ;;                                 '(?\( ?\"))
1381 ;;                           ;; If we hit a quotation mark before a paren, we
1382 ;;                           ;; are inside a specific string, not a list of
1383 ;;                           ;; symbols.
1384 ;;                           (eq (or (char-after (1- (point))) 0) ?\"))
1385 ;;                       nil)
1386 ;;                      (t (condition-case nil
1387 ;;                             (read (current-buffer))
1388 ;;                           (error nil)))))))
1389 ;;    (goto-char p)
1390 ;;    (if sym
1391 ;;      (format "%s" sym)
1392 ;;      sym)))
1393
1394 ;;    (and (symbolp sym)
1395 ;;         sym)))
1396
1397 ;;@node Aux, Global fct type, Show type, Print fctsym
1398 ;;@subsection Aux
1399
1400 ;; ToDo: handle open brackets to decide if it's a wrapped type
1401
1402 ;;@cindex haskell-doc-grab-line
1403 (defun haskell-doc-grab-line (fct-and-pos)
1404  "Get the type of an \(FCT POSITION\) pair from the current buffer."
1405  ;; (if (null fct-and-pos)
1406  ;;     "" ; fn is not a local fct
1407   (let ( (str ""))
1408    (goto-char (cdr fct-and-pos))
1409    (beginning-of-line)
1410    ;; search for start of type (phsp give better bound?)
1411    (if (null (search-forward "::" (+ (point) haskell-doc-search-distance) t))
1412        ""
1413      (setq str (haskell-doc-grab))        ; leaves point at end of line
1414      (while (haskell-doc-wrapped-type-p)  ; while in a multi-line type expr
1415        (forward-line 1)
1416        (beginning-of-line)
1417        (skip-chars-forward " \t")
1418        (setq str (concat str (haskell-doc-grab))))
1419      (haskell-doc-string-nub-ws           ; squeeze string
1420       (if haskell-doc-chop-off-context    ; no context
1421           (haskell-doc-chop-off-context str)
1422         str)))))
1423  ;; (concat (car fct-and-pos) "::" (haskell-doc-string-nub-ws str))))
1424
1425 ;;@cindex haskell-doc-wrapped-type-p
1426 (defun haskell-doc-wrapped-type-p ()
1427  "Check whether the type under the cursor is wrapped over several lines.
1428 The cursor must be at the end of a line, which contains the type.
1429 Currently, only the following is checked:
1430 If this line ends with a `->' or the next starts with an `->' it is a
1431 multi-line type \(same for `=>'\).
1432 `--' comments are ignored.
1433 ToDo: Check for matching parenthesis!. "
1434  (save-excursion
1435    (let ( (here (point))
1436           (lim (progn (beginning-of-line) (point)))
1437           ;; (foo "")
1438           (res nil)
1439           )
1440    (goto-char here)
1441    (search-backward "--" lim t) ; skip over `--' comment
1442    (skip-chars-backward " \t")
1443    (if (bolp)                   ; skip empty lines
1444       (progn
1445        (forward-line 1)
1446        (end-of-line)
1447        (setq res (haskell-doc-wrapped-type-p)))
1448    (forward-char -1)
1449    ;; (setq foo (concat foo (char-to-string (preceding-char)) (char-to-string (following-char))))
1450    (if (or (and (or (char-equal (preceding-char) ?-) (char-equal (preceding-char) ?=))
1451                 (char-equal (following-char) ?>)) ; (or -!> =!>
1452            (char-equal (following-char) ?,))      ;     !,)
1453        (setq res t)
1454      (forward-line)
1455      (let ((here (point)))
1456        (goto-char here)
1457        (skip-chars-forward " \t")
1458        (if (looking-at "--")  ; it is a comment line
1459            (progn
1460              (forward-line 1)
1461              (end-of-line)
1462              (setq res (haskell-doc-wrapped-type-p)))
1463          (forward-char 1)
1464          ;; (setq foo (concat foo (char-to-string (preceding-char)) (char-to-string (following-char))))
1465          ;; (message "|%s|" foo)
1466          (if (and (or (char-equal (preceding-char) ?-) (char-equal (preceding-char) ?=))
1467                   (char-equal (following-char) ?>)) ; -!> or =!>
1468              (setq res t))))))
1469    res)))
1470
1471 ;;@cindex haskell-doc-grab
1472 (defun haskell-doc-grab ()
1473  "Return the text from point to the end of the line, chopping off comments.
1474 Leaves point at end of line."
1475  (let* ( (str (buffer-substring-no-properties (point) (progn (end-of-line) (point))))
1476          (i (string-match "--" str)) )
1477    (if (null i)
1478        str
1479      (substring str 0 i))))
1480
1481 ;;@cindex haskell-doc-string-nub-ws
1482 (defun haskell-doc-string-nub-ws (str)
1483   "Replace all sequences of whitespaces in STR by just one whitespace.
1484 ToDo: Also eliminate leading and trainling whitespace."
1485  (interactive)
1486  (let (
1487        (res str)
1488        (i 0)
1489        )
1490   (setq i (string-match "\\(\\s-+\\)" res i))
1491   (while (not (null i))
1492     (setq res (replace-match " " t t res))
1493     (setq i (string-match "\\(\\s-+\\)" res (1+ i))) )
1494   res) )
1495
1496 ;; ToDo: make this more efficient!!
1497 ;;(defun haskell-doc-string-nub-ws (str)
1498 ;;  "Replace all sequences of whitespaces in STR by just one whitespace."
1499 ;;  (let ( (res "")
1500 ;;       (l (length str))
1501 ;;       (i 0)
1502 ;;       (j 0)
1503 ;;       (in-ws nil))
1504 ;;   (while (< i l)
1505 ;;     (let* ( (c (string-to-char (substring str i (1+ i))))
1506 ;;          (is-ws (eq (char-syntax c) ? )) )
1507 ;;       (if (not (and in-ws is-ws))
1508 ;;           (setq res (concat res (char-to-string c))))
1509 ;;       (setq in-ws is-ws)
1510 ;;       (setq i (1+ i))))
1511 ;;   res))
1512
1513 ;;@cindex haskell-doc-chop-off-context
1514 (defun haskell-doc-chop-off-context (str)
1515  "Eliminate the contex in a type represented by the string STR."
1516  (let ((i (string-match "=>" str)) )
1517    (if (null i)
1518        str
1519      (substring str (+ i 2)))))
1520
1521 ;;@cindex haskell-doc-get-imenu-info
1522 (defun haskell-doc-get-imenu-info (obj kind)
1523   "Returns a string describing OBJ of KIND \(Variables, Types, Data\)."
1524   (cond ((or (eq major-mode 'haskell-hugs-mode)
1525              ;; GEM: Haskell Mode does not work with Haskell Doc
1526              ;;      under XEmacs 20.x
1527              (and (eq major-mode 'haskell-mode)
1528                   (not (and (featurep 'xemacs)
1529                             (string-match "^20" emacs-version)))))
1530          (let* ((imenu-info-alist (cdr (assoc kind imenu--index-alist)))
1531                 ;; (names (mapcar 'car imenu-info-alist))
1532                 (x (assoc obj imenu-info-alist)))
1533              (if x
1534                  (haskell-doc-grab-line x)
1535                nil)))
1536           (t
1537            ;; (error "Cannot get local functions in %s mode, sorry" major-mode))) )
1538            nil)))
1539
1540 ;;@node Global fct type, Local fct type, Aux, Print fctsym
1541 ;;@subsection Global fct type
1542
1543 ;; ToDo:
1544 ;;  - modular way of defining a mapping of module name to file
1545 ;;  - use a path to search for file (not just current directory)
1546
1547 ;;@cindex haskell-doc-imported-list
1548
1549 (defun haskell-doc-imported-list (outer-file)
1550   "Return a list of the imported modules in OUTER-FILE."
1551   (interactive "fName of outer `include' file: ") ;  (buffer-file-name))
1552   (let ((imported-file-list (list outer-file))
1553         start)
1554     (save-excursion
1555       (switch-to-buffer (find-file-noselect outer-file))
1556       (widen)
1557       (goto-char (point-min))
1558       (while (re-search-forward "^\\s-*import\\s-+" nil t)
1559         (skip-chars-forward " \t")
1560         (setq start (point))
1561         (end-of-line)
1562         (skip-chars-backward " \t")
1563         (let ( (file (concat (buffer-substring start (point)) ".hs")) )
1564           (if (file-exists-p file)
1565               (setq imported-file-list
1566                     (cons file imported-file-list))))
1567         (let ( (file (concat (buffer-substring start (point)) ".lhs")) )
1568           (if (file-exists-p file)
1569               (setq imported-file-list
1570                     (cons file imported-file-list))))
1571       )
1572       (nreverse imported-file-list)
1573       ;;(message imported-file-list)
1574       )))
1575
1576 ;; ToDo: generalise this to "Types" etc (not just "Variables")
1577
1578 ;;@cindex haskell-doc-rescan-files
1579
1580 (defun haskell-doc-rescan-files (filelist)
1581  "Does an `imenu' rescan on every file in FILELIST and returns the fct-list.
1582 This function switches to and potentially loads many buffers."
1583    (mapcar (lambda (f)
1584              (switch-to-buffer (find-file-noselect f))
1585              (imenu--make-index-alist)
1586              (let ( (fn-alist (cdr (assoc "Variables" imenu--index-alist)) ) )
1587                (cons f
1588                      (mapcar (lambda (x)
1589                                `(,(car x) . ,(haskell-doc-grab-line x)) )
1590                              fn-alist)) ) )
1591    filelist ) )
1592
1593 ;;@cindex haskell-doc-make-global-fct-index
1594
1595 (defun haskell-doc-make-global-fct-index ()
1596  "Scan imported files for types of global fcts and update `haskell-doc-index'."
1597  (interactive)
1598  (let* ( (this-buffer (current-buffer))
1599          (this-file (buffer-file-name))
1600          (x (haskell-doc-rescan-files (haskell-doc-imported-list this-file) )) )
1601    (switch-to-buffer this-buffer)
1602    ;; haskell-doc-index is buffer local => switch-buffer before setq
1603    (setq haskell-doc-index x) ) )
1604
1605 ;; ToDo: use a separate munge-type function to format type concisely
1606
1607 ;;@cindex haskell-doc-get-global-fct-type
1608
1609 (defun haskell-doc-get-global-fct-type (&optional sym)
1610  "Get type for function symbol SYM by examining `haskell-doc-index'."
1611   (interactive) ;  "fName of outer `include' file: \nsFct:")
1612   (save-excursion
1613     ;; (switch-to-buffer "*scratch*")
1614     ;; (goto-char (point-max))
1615     ;; ;; Produces a list of fct-type alists
1616     ;; (if (null sym)
1617     ;;     (setq sym (progn (forward-word -1) (read (current-buffer)))))
1618   (or sym
1619       (current-word))
1620   (let* ( (fn sym) ; (format "%s" sym))
1621           (fal haskell-doc-index)
1622           (res "") )
1623     (while (not (null fal))
1624       (let* ( (l (car fal))
1625               (f (car l))
1626               (x (assoc fn (cdr l))) )
1627         (if (not (null x))
1628             (let* ( (ty (cdr x)) ; the type as string
1629                     (idx (string-match "::" ty))
1630                     (str (if (null idx)
1631                              ty
1632                            (substring ty (+ idx 2)))) )
1633               (setq res (format "[%s] %s" f str))))
1634           (setq fal (cdr fal))))
1635     res))) ; (message res)) )
1636
1637 ;;@node Local fct type,  , Global fct type, Print fctsym
1638 ;;@subsection Local fct type
1639
1640 ;;@cindex haskell-doc-get-and-format-fct-type
1641
1642 (defun haskell-doc-get-and-format-fct-type (fn)
1643  "Get the type and kind of FN by checking local and global functions."
1644  (save-excursion
1645    (save-match-data
1646      (let ((docstring "")
1647            (doc nil)
1648            )
1649        ;; is it a local function?
1650        (setq docstring (haskell-doc-get-imenu-info fn "Variables"))
1651        (if (not (null docstring))
1652                 ;; (string-match (format "^%s\\s-+::\\s-+\\(.*\\)$" fn) docstring))
1653            (setq doc `(,docstring . "Variables"))) ; `(,(match-string 1 docstring) . "Variables") ))
1654        ;; is it a type declaration?
1655        (setq docstring (haskell-doc-get-imenu-info fn "Types"))
1656        (if (not (null docstring))
1657                 ;; (string-match (format "^\\s-*type\\s-+%s.*$" fn) docstring))
1658              (setq doc `(,docstring . "Types"))) ; `(,(match-string 0 docstring) . "Types")) )
1659        (if (not (null docstring))
1660                 ;; (string-match (format "^\\s-*data.*%s.*$" fn) docstring))
1661          (setq doc `(,docstring . "Data"))) ; (setq doc `(,(match-string 0 docstring) . "Data")) )
1662        ;; return the result
1663        doc ))))
1664
1665 \f
1666 ;;@node Movement, Bug Reports, Print fctsym, top
1667 ;;@section Movement
1668 ;; Functions for moving in text and extracting the current word under the cursor
1669
1670 ;; HWL: my attempt at more efficient (current-word)
1671
1672 ;; NB: this function is called from within the hooked print function;
1673 ;;     therefore this function must not fail, otherwise the function will
1674 ;;     be de-installed;
1675 ;;     if no word under the cursor return an empty string
1676 ;;@cindex haskell-doc-get-current-word
1677 (defun haskell-doc-get-current-word ()
1678   "Return the word under the cursor, or empty string if no word found."
1679   (save-excursion
1680     (buffer-substring-no-properties
1681      (progn (skip-syntax-backward "w_") (point))
1682      (progn (skip-syntax-forward "w_") (point)))))
1683
1684 ;;@node Bug Reports, Visit home site, Movement, top
1685 ;;@section Bug Reports
1686
1687 ;;@cindex haskell-doc-submit-bug-report
1688 ;; send a bug report
1689 (defun haskell-doc-submit-bug-report ()
1690   "Send email to the maintainer of `haskell-doc-mode'."
1691   (interactive)
1692   ;; In case we can't find reporter...
1693   (condition-case err
1694       (progn
1695         (require 'reporter)
1696         (and (y-or-n-p "Do you really want to submit a bug report? ")
1697         (reporter-submit-bug-report
1698          haskell-doc-maintainer                               ; address
1699          (concat "haskell-doc.el " haskell-doc-version)       ; package
1700          haskell-doc-varlist                                  ; varlist
1701          nil nil                                        ; pre-/post-hooks
1702         "I have detected the following strange behaviour/bug in `haskell-doc-mode':\n")))
1703     ;; ...fail gracefully.
1704     (error
1705      (beep)
1706      (message "Sorry, reporter.el not found."))))
1707
1708 ;;@node Visit home site, Index, Bug Reports, top
1709 ;;@section Visit home site
1710
1711 ;;@cindex haskell-doc-visit-home
1712
1713 (defun haskell-doc-visit-home ()
1714  "Jump to the main FTP site for `haskell-doc-mode'."
1715  (interactive)
1716  (if (featurep 'xemacs)
1717      (require 'efs))
1718  (require 'dired)
1719  (dired-other-window haskell-doc-ftp-site))
1720
1721 ;;@appendix
1722
1723 ;;@node Index, Token, Visit home site, top
1724 ;;@section Index
1725
1726 ;;@index
1727 ;;* haskell-doc-ask-mouse-for-type::
1728 ;;* haskell-doc-check-active::
1729 ;;* haskell-doc-chop-off-context::
1730 ;;* haskell-doc-get-and-format-fct-type::
1731 ;;* haskell-doc-get-current-word::
1732 ;;* haskell-doc-get-global-fct-type::
1733 ;;* haskell-doc-get-imenu-info::
1734 ;;* haskell-doc-grab::
1735 ;;* haskell-doc-grab-line::
1736 ;;* haskell-doc-imported-list::
1737 ;;* haskell-doc-install-keymap::
1738 ;;* haskell-doc-is-of::
1739 ;;* haskell-doc-make-global-fct-index::
1740 ;;* haskell-doc-mode::
1741 ;;* haskell-doc-mode-print-current-symbol-info::
1742 ;;* haskell-doc-prelude-types::
1743 ;;* haskell-doc-rescan-files::
1744 ;;* haskell-doc-reserved-ids::
1745 ;;* haskell-doc-show-global-types::
1746 ;;* haskell-doc-show-prelude::
1747 ;;* haskell-doc-show-reserved::
1748 ;;* haskell-doc-show-strategy::
1749 ;;* haskell-doc-show-type::
1750 ;;* haskell-doc-show-user-defined::
1751 ;;* haskell-doc-strategy-ids::
1752 ;;* haskell-doc-string-nub-ws::
1753 ;;* haskell-doc-submit-bug-report::
1754 ;;* haskell-doc-visit-home::
1755 ;;* haskell-doc-wrapped-type-p::
1756 ;;* turn-off-haskell-doc-mode::
1757 ;;* turn-on-haskell-doc-mode::
1758 ;;@end index
1759
1760 ;;@node Token,  , Index, top
1761 ;;@section Token
1762
1763 (provide 'haskell-doc)
1764
1765 ;;; haskell-doc.el ends here