Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 812 lines (733 sloc) 35.468 kb
4418871 New file.
monnier authored
1 ;;; inf-haskell.el --- Interaction with an inferior Haskell process.
2
d549980 (inferior-haskell-type, inferior-haskell-info):
monnier authored
3 ;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
4418871 New file.
monnier authored
4
5 ;; Author: Stefan Monnier <monnier@iro.umontreal.ca>
6 ;; Keywords: Haskell
7
8 ;; This file is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
30d658f (displayed-month): Remove declaration since it's not used here.
monnier authored
10 ;; the Free Software Foundation; either version 3, or (at your option)
4418871 New file.
monnier authored
11 ;; any later version.
12
13 ;; This file is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GNU Emacs; see the file COPYING. If not, write to
20 ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 ;; Boston, MA 02111-1307, USA.
22
23 ;;; Commentary:
24
25 ;; The code is made of 2 parts: a major mode for the buffer that holds the
225a7c5 (inferior-haskell-load-file): Quote file name.
monnier authored
26 ;; inferior process's session and a minor mode for use in source buffers.
4418871 New file.
monnier authored
27
3e6c2e0 *** empty log message ***
monnier authored
28 ;; Todo:
29
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
30 ;; - Check out Shim for ideas.
9ed46b1 (inferior-haskell-load-file): Re-add the `reload' arg.
monnier authored
31 ;; - i-h-load-buffer and i-h-send-region.
3e6c2e0 *** empty log message ***
monnier authored
32
4418871 New file.
monnier authored
33 ;;; Code:
34
35 (require 'comint)
36 (require 'shell) ;For directory tracking.
37 (require 'compile)
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
38 (require 'haskell-mode)
7410480 (inferior-haskell-wait-for-prompt): New fun, extracted
monnier authored
39 (eval-when-compile (require 'cl))
4418871 New file.
monnier authored
40
4456be9 (subst-char-in-string, make-temp-file): Add fallback definitions for XEm...
monnier authored
41 ;; XEmacs compatibility.
42
43 (unless (fboundp 'subst-char-in-string)
44 (defun subst-char-in-string (fromchar tochar string &optional inplace)
45 ;; This is Haskell-mode, we don't want no stinkin' `aset'.
46 (apply 'string (mapcar (lambda (c) (if (eq c fromchar) tochar c)) string))))
47
48 (unless (fboundp 'make-temp-file)
49 (defun make-temp-file (prefix &optional dir-flag)
50 (catch 'done
51 (while t
52 (let ((f (make-temp-name (expand-file-name prefix (temp-directory)))))
53 (condition-case ()
54 (progn
55 (if dir-flag (make-directory f)
56 (write-region "" nil f nil 'silent nil))
57 (throw 'done f))
58 (file-already-exists t)))))))
947a32d (inferior-haskell-info-xref-re): Allow a column-range.
monnier authored
59
94ad4fc (inferior-haskell-cabal-of-buf): Don't return
monnier authored
60 (unless (fboundp 'replace-regexp-in-string)
61 (defun replace-regexp-in-string (regexp rep string)
62 (replace-in-string string regexp rep)))
4456be9 (subst-char-in-string, make-temp-file): Add fallback definitions for XEm...
monnier authored
63
4418871 New file.
monnier authored
64 ;; Here I depart from the inferior-haskell- prefix.
65 ;; Not sure if it's a good idea.
27cc26c (haskell-program-name): Use ghci if hugs is absent.
monnier authored
66 (defcustom haskell-program-name
67 ;; Arbitrarily give preference to hugs over ghci.
68 (or (cond
69 ((not (fboundp 'executable-find)) nil)
70 ((executable-find "hugs") "hugs \"+.\"")
71 ((executable-find "ghci") "ghci"))
72 "hugs \"+.\"")
4418871 New file.
monnier authored
73 "The name of the command to start the inferior Haskell process.
74 The command can include arguments."
8b661ca (haskell-program-name): Fix defcustom delcaration.
monnier authored
75 ;; Custom only supports the :options keyword for a few types, e.g. not
76 ;; for string.
77 ;; :options '("hugs \"+.\"" "ghci")
4418871 New file.
monnier authored
78 :group 'haskell
79 :type '(choice string (repeat string)))
80
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
81 (defconst inferior-haskell-info-xref-re
947a32d (inferior-haskell-info-xref-re): Allow a column-range.
monnier authored
82 "\t-- Defined at \\(.+\\):\\([0-9]+\\):\\([0-9]+\\)\\(?:-\\([0-9]+\\)\\)?$")
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
83
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
84 (defconst inferior-haskell-module-re
85 "\t-- Defined in \\(.+\\)$"
86 "Regular expression for matching module names in :info.")
87
7aac27a @apsk Initial support for send declaration'.
apsk authored
88 (defvar inferior-haskell-multiline-prompt-re
89 "^\\*?[[:upper:]][\\._[:alnum:]]*\\(?: \\*?[[:upper:]][\\._[:alnum:]]*\\)*| "
90 "Regular expression for matching multiline prompt (the one inside :{ ... :} blocks).")
91
4418871 New file.
monnier authored
92 (defconst inferior-haskell-error-regexp-alist
93 ;; The format of error messages used by Hugs.
e19bf49 (inferior-haskell-error-regexp-alist): Fix GHCi regexp, support warnings...
monnier authored
94 `(("^ERROR \"\\(.+?\\)\"\\(:\\| line \\)\\([0-9]+\\) - " 1 3)
4418871 New file.
monnier authored
95 ;; Format of error messages used by GHCi.
a9fe15b (inferior-haskell-error-regexp-alist): Be more careful
monnier authored
96 ("^\\(.+?\\):\\([0-9]+\\):\\(\\([0-9]+\\):\\)?\\( \\|\n *\\)\\(Warning\\)?"
97 1 2 4 ,@(if (fboundp 'compilation-fake-loc)
98 '((6) nil (5 '(face nil font-lock-multiline t)))))
5a72afa (inferior-haskell-error-regexp-alist): Add entries for GHCI's exceptions...
monnier authored
99 ;; Runtime exceptions, from ghci.
100 ("^\\*\\*\\* Exception: \\(.+?\\):(\\([0-9]+\\),\\([0-9]+\\))-(\\([0-9]+\\),\\([0-9]+\\)): .*"
101 1 ,@(if (fboundp 'compilation-fake-loc) '((2 . 4) (3 . 5)) '(2 3)))
a9fe15b (inferior-haskell-error-regexp-alist): Be more careful
monnier authored
102 ;; GHCi uses two different forms for line/col ranges, depending on
ff46f40 (inferior-haskell-error-regexp-alist):
monnier authored
103 ;; whether it's all on the same line or not :-( In Emacs-23, I could use
104 ;; explicitly numbered subgroups to merge the two patterns.
5a72afa (inferior-haskell-error-regexp-alist): Add entries for GHCI's exceptions...
monnier authored
105 ("^\\*\\*\\* Exception: \\(.+?\\):\\([0-9]+\\):\\([0-9]+\\)-\\([0-9]+\\): .*"
106 1 2 ,(if (fboundp 'compilation-fake-loc) '(3 . 4) 3))
a9fe15b (inferior-haskell-error-regexp-alist): Be more careful
monnier authored
107 ;; Info messages. Not errors per se.
ff46f40 (inferior-haskell-error-regexp-alist):
monnier authored
108 ,@(when (fboundp 'compilation-fake-loc)
109 `(;; Other GHCi patterns used in type errors.
110 ("^[ \t]+at \\(.+\\):\\([0-9]+\\):\\([0-9]+\\)-\\([0-9]+\\)$"
111 1 2 (3 . 4) 0)
112 ;; Foo.hs:318:80:
113 ;; Ambiguous occurrence `Bar'
114 ;; It could refer to either `Bar', defined at Zork.hs:311:5
115 ;; or `Bar', imported from Bars at Frob.hs:32:0-16
116 ;; (defined at Location.hs:97:5)
117 ("[ (]defined at \\(.+\\):\\([0-9]+\\):\\([0-9]+\\))?$" 1 2 3 0)
118 ("imported from .* at \\(.+\\):\\([0-9]+\\):\\([0-9]+\\)-\\([0-9]+\\)$"
119 1 2 (3 . 4) 0)
120 ;; Info xrefs.
947a32d (inferior-haskell-info-xref-re): Allow a column-range.
monnier authored
121 (,inferior-haskell-info-xref-re 1 2 (3 . 4) 0))))
4418871 New file.
monnier authored
122 "Regexps for error messages generated by inferior Haskell processes.
123 The format should be the same as for `compilation-error-regexp-alist'.")
124
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
125 (defcustom inferior-haskell-find-project-root t
126 "If non-nil, try and find the project root directory of this file.
127 This will either look for a Cabal file or a \"module\" statement in the file."
68daaf2 @loveshack Add missing `:group's to defcustoms.
loveshack authored
128 :group 'haskell
c7c6278 (inferior-haskell-use-cabal): New custom var.
monnier authored
129 :type 'boolean)
130
4418871 New file.
monnier authored
131 (define-derived-mode inferior-haskell-mode comint-mode "Inf-Haskell"
132 "Major mode for interacting with an inferior Haskell process."
133 (set (make-local-variable 'comint-prompt-regexp)
1d2f932 @loveshack Allow non-ASCII names.
loveshack authored
134 ;; Whay the backslash in [\\._[:alnum:]]?
08a3028 @pheaver tweak comint-prompt-regexp to avoid locking in certain situations.
pheaver authored
135 "^\\*?[[:upper:]][\\._[:alnum:]]*\\(?: \\*?[[:upper:]][\\._[:alnum:]]*\\)*> \\|^> $")
4418871 New file.
monnier authored
136 (set (make-local-variable 'comint-input-autoexpand) nil)
7aac27a @apsk Initial support for send declaration'.
apsk authored
137 (add-hook 'comint-preoutput-filter-functions
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
138 'inferior-haskell-send-decl-post-filter)
ce971bb (inferior-haskell-spot-prompt): New function.
monnier authored
139 (add-hook 'comint-output-filter-functions 'inferior-haskell-spot-prompt nil t)
4418871 New file.
monnier authored
140
141 ;; Setup directory tracking.
142 (set (make-local-variable 'shell-cd-regexp) ":cd")
bbbe054 (inferior-haskell-mode): Use shell-dirtrack-mode if possible.
monnier authored
143 (condition-case nil
144 (shell-dirtrack-mode 1)
145 (error ;The minor mode function may not exist or not accept an arg.
146 (set (make-local-variable 'shell-dirtrackp) t)
147 (add-hook 'comint-input-filter-functions 'shell-directory-tracker
148 nil 'local)))
4418871 New file.
monnier authored
149
150 ;; Setup `compile' support so you can just use C-x ` and friends.
151 (set (make-local-variable 'compilation-error-regexp-alist)
152 inferior-haskell-error-regexp-alist)
5a72afa (inferior-haskell-error-regexp-alist): Add entries for GHCI's exceptions...
monnier authored
153 (set (make-local-variable 'compilation-first-column) 0) ;GHCI counts from 0.
bfd15e1 (inferior-haskell-mode): Hide compilation-mode bindings.
monnier authored
154 (if (and (not (boundp 'minor-mode-overriding-map-alist))
155 (fboundp 'compilation-shell-minor-mode))
156 ;; If we can't remove compilation-minor-mode bindings, at least try to
157 ;; use compilation-shell-minor-mode, so there are fewer
158 ;; annoying bindings.
159 (compilation-shell-minor-mode 1)
160 ;; Else just use compilation-minor-mode but without its bindings because
161 ;; things like mouse-2 are simply too annoying.
162 (compilation-minor-mode 1)
163 (let ((map (make-sparse-keymap)))
164 (dolist (keys '([menu-bar] [follow-link]))
165 ;; Preserve some of the bindings.
166 (define-key map keys (lookup-key compilation-minor-mode-map keys)))
167 (add-to-list 'minor-mode-overriding-map-alist
168 (cons 'compilation-minor-mode map)))))
4418871 New file.
monnier authored
169
6784a8b (inferior-haskell-string-to-strings): Remove `separator' argument. Call...
monnier authored
170 (defun inferior-haskell-string-to-strings (string)
171 "Split the STRING into a list of strings."
172 (let ((i (string-match "[\"]" string)))
173 (if (null i) (split-string string) ; no quoting: easy
174 (append (unless (eq i 0) (split-string (substring string 0 i)))
4418871 New file.
monnier authored
175 (let ((rfs (read-from-string string i)))
176 (cons (car rfs)
177 (inferior-haskell-string-to-strings
6784a8b (inferior-haskell-string-to-strings): Remove `separator' argument. Call...
monnier authored
178 (substring string (cdr rfs)))))))))
4418871 New file.
monnier authored
179
180 (defun inferior-haskell-command (arg)
181 (inferior-haskell-string-to-strings
182 (if (null arg) haskell-program-name
6dd0f3a (inferior-haskell-command): Provide a default.
monnier authored
183 (read-string "Command to run haskell: " haskell-program-name))))
4418871 New file.
monnier authored
184
185 (defvar inferior-haskell-buffer nil
186 "The buffer in which the inferior process is running.")
187
188 (defun inferior-haskell-start-process (command)
189 "Start an inferior haskell process.
6784a8b (inferior-haskell-string-to-strings): Remove `separator' argument. Call...
monnier authored
190 With universal prefix \\[universal-argument], prompts for a COMMAND,
4418871 New file.
monnier authored
191 otherwise uses `haskell-program-name'.
192 It runs the hook `inferior-haskell-hook' after starting the process and
193 setting up the inferior-haskell buffer."
194 (interactive (list (inferior-haskell-command current-prefix-arg)))
195 (setq inferior-haskell-buffer
196 (apply 'make-comint "haskell" (car command) nil (cdr command)))
197 (with-current-buffer inferior-haskell-buffer
198 (inferior-haskell-mode)
199 (run-hooks 'inferior-haskell-hook)))
200
201 (defun inferior-haskell-process (&optional arg)
202 (or (if (buffer-live-p inferior-haskell-buffer)
203 (get-buffer-process inferior-haskell-buffer))
204 (progn
205 (let ((current-prefix-arg arg))
206 (call-interactively 'inferior-haskell-start-process))
207 ;; Try again.
208 (inferior-haskell-process arg))))
209
210 ;;;###autoload
211 (defalias 'run-haskell 'switch-to-haskell)
212 ;;;###autoload
213 (defun switch-to-haskell (&optional arg)
214 "Show the inferior-haskell buffer. Start the process if needed."
215 (interactive "P")
216 (let ((proc (inferior-haskell-process arg)))
217 (pop-to-buffer (process-buffer proc))))
218
ce51306 (with-selected-window): Define while compiling.
monnier authored
219 (eval-when-compile
220 (unless (fboundp 'with-selected-window)
221 (defmacro with-selected-window (win &rest body)
222 `(save-selected-window
223 (select-window ,win)
224 ,@body))))
6dd0f3a (inferior-haskell-command): Provide a default.
monnier authored
225
7410480 (inferior-haskell-wait-for-prompt): New fun, extracted
monnier authored
226 (defcustom inferior-haskell-wait-and-jump nil
227 "If non-nil, wait for file loading to terminate and jump to the error."
228 :type 'boolean
229 :group 'haskell)
230
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
231 (defvar inferior-haskell-send-decl-post-filter-on nil)
232 (make-variable-buffer-local 'inferior-haskell-send-decl-post-filter-on)
7aac27a @apsk Initial support for send declaration'.
apsk authored
233
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
234 (defun inferior-haskell-send-decl-post-filter (string)
235 (when (and inferior-haskell-send-decl-post-filter-on
7aac27a @apsk Initial support for send declaration'.
apsk authored
236 #1=(string-match inferior-haskell-multiline-prompt-re string))
237 ;; deleting sequence of `%s|' multiline promts
238 (while #1#
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
239 (setq string (substring string (match-end 0))))
240 ;; deleting regular prompts
241 (setq string (replace-regexp-in-string comint-prompt-regexp "" string)
242 ;; turning off this post-filter
243 inferior-haskell-send-decl-post-filter-on nil))
7aac27a @apsk Initial support for send declaration'.
apsk authored
244 string)
245
ce971bb (inferior-haskell-spot-prompt): New function.
monnier authored
246 (defvar inferior-haskell-seen-prompt nil)
247 (make-variable-buffer-local 'inferior-haskell-seen-prompt)
248
249 (defun inferior-haskell-spot-prompt (string)
250 (let ((proc (get-buffer-process (current-buffer))))
251 (when proc
252 (save-excursion
253 (goto-char (process-mark proc))
254 (if (re-search-backward comint-prompt-regexp
255 (line-beginning-position) t)
256 (setq inferior-haskell-seen-prompt t))))))
257
c6cbffc (inferior-haskell-wait-for-prompt): Add timeout arg.
monnier authored
258 (defun inferior-haskell-wait-for-prompt (proc &optional timeout)
7410480 (inferior-haskell-wait-for-prompt): New fun, extracted
monnier authored
259 "Wait until PROC sends us a prompt.
260 The process PROC should be associated to a comint buffer."
261 (with-current-buffer (process-buffer proc)
ce971bb (inferior-haskell-spot-prompt): New function.
monnier authored
262 (while (progn
263 (goto-char comint-last-input-end)
264 (not (or inferior-haskell-seen-prompt
265 (setq inferior-haskell-seen-prompt
266 (re-search-forward comint-prompt-regexp nil t))
267 (not (accept-process-output proc timeout))))))
268 (unless inferior-haskell-seen-prompt
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
269 (error "Can't find the prompt"))))
7410480 (inferior-haskell-wait-for-prompt): New fun, extracted
monnier authored
270
c7c6278 (inferior-haskell-use-cabal): New custom var.
monnier authored
271 (defvar inferior-haskell-cabal-buffer nil)
272
273 (defun inferior-haskell-cabal-of-buf (buf)
274 (require 'haskell-cabal)
275 (with-current-buffer buf
94ad4fc (inferior-haskell-cabal-of-buf): Don't return
monnier authored
276 (or (and (buffer-live-p inferior-haskell-cabal-buffer)
277 inferior-haskell-cabal-buffer)
439a89e (inferior-haskell-cabal-of-buf)
monnier authored
278 (and (not (local-variable-p 'inferior-haskell-cabal-buffer
279 ;; XEmacs needs this argument.
837c948 (inferior-haskell-cabal-of-buf): Fix typo.
monnier authored
280 (current-buffer)))
c7c6278 (inferior-haskell-use-cabal): New custom var.
monnier authored
281 (set (make-local-variable 'inferior-haskell-cabal-buffer)
282 (haskell-cabal-find-file))))))
283
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
284 (defun inferior-haskell-find-project-root (buf)
285 (with-current-buffer buf
286 (let ((cabal (inferior-haskell-cabal-of-buf buf)))
287 (or (when cabal
288 (with-current-buffer cabal
f11a557 (inferior-haskell-find-project-root): Use it.
monnier authored
289 (let ((hsd (haskell-cabal-get-setting "hs-source-dirs")))
290 (if (null hsd)
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
291 ;; If there's a Cabal file with no Hs-Source-Dirs, then
292 ;; just use the Cabal file's directory.
293 default-directory
294 ;; If there is an HSD, then check that it's an existing
295 ;; dir (otherwise, it may be a list of dirs and we don't
296 ;; know what to do with those). If it doesn't exist, then
297 ;; give up.
3afce2f (inferior-haskell-find-project-root): Minor simplification.
monnier authored
298 (if (file-directory-p hsd) (expand-file-name hsd))))))
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
299 ;; If there's no Cabal file or it's not helpful, try to look for
300 ;; a "module" statement and count the number of "." in the
301 ;; module name.
302 (save-excursion
303 (goto-char (point-min))
304 (let ((case-fold-search nil))
305 (when (re-search-forward
21bcba1 @gracjan Better regexp to match module name in inf-haskell
gracjan authored
306 "^module[ \t]+\\(\\(?:\\sw\\|[.]\\)+\\)" nil t)
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
307 (let* ((dir default-directory)
308 (module (match-string 1))
309 (pos 0))
310 (while (string-match "\\." module pos)
311 (setq pos (match-end 0))
312 (setq dir (expand-file-name ".." dir)))
313 ;; Let's check that the module name matches the file name,
314 ;; otherwise the project root is probably not what we think.
315 (if (eq t (compare-strings
316 (file-name-sans-extension buffer-file-name)
317 nil nil
318 (expand-file-name
319 (replace-regexp-in-string "\\." "/" module)
320 dir)
321 nil nil t))
322 dir
323 ;; If they're not equal, it means the local directory
324 ;; hierarchy doesn't match the module name. This seems
325 ;; odd, so let's warn the user about it. May help us
326 ;; debug this code as well.
327 (message "Ignoring inconsistent `module' info: %s in %s"
328 module buffer-file-name)
329 nil)))))))))
947a32d (inferior-haskell-info-xref-re): Allow a column-range.
monnier authored
330
331
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
332
4418871 New file.
monnier authored
333 ;;;###autoload
9ed46b1 (inferior-haskell-load-file): Re-add the `reload' arg.
monnier authored
334 (defun inferior-haskell-load-file (&optional reload)
0294d90 (inferior-haskell-load-file): Do reload if prefix arg.
monnier authored
335 "Pass the current buffer's file to the inferior haskell process.
336 If prefix arg \\[universal-argument] is given, just reload the previous file."
8af5157 (inferior-haskell-load-file): Typo.
monnier authored
337 (interactive "P")
2eaced4 (inferior-haskell-load-file): Save buffer before using buffer-file-name.
monnier authored
338 ;; Save first, so we're sure that `buffer-file-name' is non-nil afterward.
339 (save-buffer)
c7c6278 (inferior-haskell-use-cabal): New custom var.
monnier authored
340 (let ((buf (current-buffer))
341 (file buffer-file-name)
4418871 New file.
monnier authored
342 (proc (inferior-haskell-process)))
2702f77 @Baughn Print a proper error if inferior-haskell-load-file is called on a buffer...
Baughn authored
343 (if file
344 (with-current-buffer (process-buffer proc)
345 (compilation-forget-errors)
346 (let ((parsing-end (marker-position (process-mark proc)))
347 root)
348 ;; Go to the root of the Cabal project, if applicable.
349 (when (and inferior-haskell-find-project-root
350 (setq root (inferior-haskell-find-project-root buf)))
351 ;; Not sure if it's useful/needed and if it actually works.
352 (unless (equal default-directory root)
353 (setq default-directory root)
354 (inferior-haskell-send-command
355 proc (concat ":cd " default-directory)))
356 (setq file (file-relative-name file)))
c7c6278 (inferior-haskell-use-cabal): New custom var.
monnier authored
357 (inferior-haskell-send-command
2702f77 @Baughn Print a proper error if inferior-haskell-load-file is called on a buffer...
Baughn authored
358 proc (if reload ":reload"
359 (concat ":load \""
360 ;; Espace the backslashes that may occur in file names.
361 (replace-regexp-in-string "[\\\"]" "\\\\\&" file)
362 "\"")))
363 ;; Move the parsing-end marker *after* sending the command so
364 ;; that it doesn't point just to the insertion point.
365 ;; Otherwise insertion may move the marker (if done with
366 ;; insert-before-markers) and we'd then miss some errors.
367 (if (boundp 'compilation-parsing-end)
368 (if (markerp compilation-parsing-end)
369 (set-marker compilation-parsing-end parsing-end)
370 (setq compilation-parsing-end parsing-end))))
371 (with-selected-window (display-buffer (current-buffer) nil 'visible)
1da6412 @Baughn New major mode: GHC-core
Baughn authored
372 (end-of-buffer))
2702f77 @Baughn Print a proper error if inferior-haskell-load-file is called on a buffer...
Baughn authored
373 ;; Use compilation-auto-jump-to-first-error if available.
374 ;; (if (and (boundp 'compilation-auto-jump-to-first-error)
375 ;; compilation-auto-jump-to-first-error
376 ;; (boundp 'compilation-auto-jump-to-next))
377 ;; (setq compilation-auto-jump-to-next t)
378 (when inferior-haskell-wait-and-jump
379 (inferior-haskell-wait-for-prompt proc)
380 (ignore-errors ;Don't beep if there were no errors.
381 (next-error))))
382 (error "No file associated with buffer"))))
8512ba1 (inferior-haskell-mode): Typo.
monnier authored
383
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
384 (defvar inferior-haskell-run-command ":main")
385
1da6412 @Baughn New major mode: GHC-core
Baughn authored
386 ;;;###autoload
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
387 (defun inferior-haskell-load-and-run (command)
9ed46b1 (inferior-haskell-load-file): Re-add the `reload' arg.
monnier authored
388 "Pass the current buffer's file to haskell and then run a COMMAND."
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
389 (interactive
390 (list
391 (if (and inferior-haskell-run-command (not current-prefix-arg))
392 inferior-haskell-run-command
393 (read-string "Command to run: " nil nil inferior-haskell-run-command))))
394 (setq inferior-haskell-run-command command)
40fa207 * inf-haskell.el (inferior-haskell-load-and-run): Don't run if there
monnier authored
395 (let* ((inferior-haskell-errors nil)
396 (neh (lambda () (setq inferior-haskell-errors t))))
397 (unwind-protect
398 (let ((inferior-haskell-wait-and-jump t))
399 (add-hook 'next-error-hook neh)
400 (inferior-haskell-load-file))
401 (remove-hook 'next-error-hook neh))
402 (unless inferior-haskell-errors
403 (inferior-haskell-send-command (inferior-haskell-process) command)
404 (switch-to-haskell))))
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
405
8512ba1 (inferior-haskell-mode): Typo.
monnier authored
406 (defun inferior-haskell-send-command (proc str)
407 (setq str (concat str "\n"))
408 (with-current-buffer (process-buffer proc)
7410480 (inferior-haskell-wait-for-prompt): New fun, extracted
monnier authored
409 (inferior-haskell-wait-for-prompt proc)
8512ba1 (inferior-haskell-mode): Typo.
monnier authored
410 (goto-char (process-mark proc))
411 (insert-before-markers str)
412 (move-marker comint-last-input-end (point))
ce971bb (inferior-haskell-spot-prompt): New function.
monnier authored
413 (setq inferior-haskell-seen-prompt nil)
8512ba1 (inferior-haskell-mode): Typo.
monnier authored
414 (comint-send-string proc str)))
4418871 New file.
monnier authored
415
9ed46b1 (inferior-haskell-load-file): Re-add the `reload' arg.
monnier authored
416 (defun inferior-haskell-reload-file ()
417 "Tell the inferior haskell process to reread the current buffer's file."
418 (interactive)
419 (inferior-haskell-load-file 'reload))
420
7aac27a @apsk Initial support for send declaration'.
apsk authored
421 (defun inferior-haskell-wrap-decl (code)
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
422 "Wrap declaration code into :{ ... :}."
0a72157 @apsk Added concatenation of newline to declaration-code before wrapping into ...
apsk authored
423 (setq code (concat code "\n"))
7aac27a @apsk Initial support for send declaration'.
apsk authored
424 (concat ":{\n"
425 (if (string-match (concat "^\\s-*"
426 haskell-ds-start-keywords-re)
427 code)
428 ;; non-fun-decl
429 code
430 ;; fun-decl, wrapping into let { .. (; ..)* }
431 (concat "let {\n"
432 (mapconcat
433 ;; adding 2 whitespaces to each line
434 (lambda (decl)
435 (mapconcat (lambda (s)
436 (concat " " s))
437 (split-string decl "\n")
438 "\n"))
439 ;; splitting function case-decls
440 (let (decls)
441 (while (string-match "^\\(\\w+\\).*\n*\\(?:\\s-+.*\n+\\)*" code)
442 (push (match-string 0 code) decls)
443 (setq code (substring code (match-end 0))))
444 (reverse decls))
445 "\n;\n")
446 "\n}"))
447 "\n:}\n"))
448
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
449 (defun inferior-haskell-flash-decl (start end &optional timeout)
450 "Temporarily highlight declaration."
451 (let ((overlay (make-overlay start end)))
452 (overlay-put overlay 'face 'secondary-selection)
453 (run-with-timer (or timeout 0.2) nil 'delete-overlay overlay)))
454
7aac27a @apsk Initial support for send declaration'.
apsk authored
455 ;;;###autoload
456 (defun inferior-haskell-send-decl ()
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
457 "Send current declaration to inferior-haskell process."
7aac27a @apsk Initial support for send declaration'.
apsk authored
458 (interactive)
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
459 (require 'haskell-decl-scan)
7aac27a @apsk Initial support for send declaration'.
apsk authored
460 (save-excursion
461 (goto-char (1+ (point)))
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
462 (let* ((proc (inferior-haskell-process))
463 (start (or (haskell-ds-backward-decl) (point-min)))
464 (end (or (haskell-ds-forward-decl) (point-max)))
465 (raw-decl (buffer-substring start end)))
7aac27a @apsk Initial support for send declaration'.
apsk authored
466 ;; enter multiline-prompt-cutting-mode
467 (with-current-buffer (process-buffer proc)
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
468 (setq inferior-haskell-send-decl-post-filter-on t))
469 ;; flash decl
470 (inferior-haskell-flash-decl start end)
7aac27a @apsk Initial support for send declaration'.
apsk authored
471 ;; send decl
472 (comint-send-string proc (inferior-haskell-wrap-decl raw-decl))
473 ;; send preview
474 (inferior-haskell-send-command
475 proc
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
476 (let* ((str (remove ?\n raw-decl))
477 (len (min 15 (length str))))
478 (concat "-- evaluating {: "
479 (substring str 0 len)
480 (if (= 15 len) ".." "")
481 " :}"))))))
7aac27a @apsk Initial support for send declaration'.
apsk authored
482
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
483 ;;;###autoload
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
484 (defun inferior-haskell-type (expr &optional insert-value)
485 "Query the haskell process for the type of the given expression.
486 If optional argument `insert-value' is non-nil, insert the type above point
487 in the buffer. This can be done interactively with the \\[universal-argument] prefix.
488 The returned info is cached for reuse by `haskell-doc-mode'."
489 (interactive
490 (let ((sym (haskell-ident-at-point)))
491 (list (read-string (if (> (length sym) 0)
492 (format "Show type of (default %s): " sym)
493 "Show type of: ")
494 nil nil sym)
495 current-prefix-arg)))
496 (if (string-match "\\`\\s_+\\'" expr) (setq expr (concat "(" expr ")")))
497 (let* ((proc (inferior-haskell-process))
498 (type
499 (with-current-buffer (process-buffer proc)
500 (let ((parsing-end ; Remember previous spot.
501 (marker-position (process-mark proc))))
502 (inferior-haskell-send-command proc (concat ":type " expr))
503 ;; Find new point.
504 (inferior-haskell-wait-for-prompt proc)
d549980 (inferior-haskell-type, inferior-haskell-info):
monnier authored
505 (goto-char (point-max))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
506 ;; Back up to the previous end-of-line.
507 (end-of-line 0)
508 ;; Extract the type output
509 (buffer-substring-no-properties
510 (save-excursion (goto-char parsing-end)
511 (line-beginning-position 2))
512 (point))))))
f846b94 @Baughn Patch courtesy of Alex Ott
Baughn authored
513 (if (not (string-match (concat "^\\(" (regexp-quote expr) "[ \t\n]+::[ \t\n]*\\(.\\|\n\\)*\\)")
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
514 type))
515 (error "No type info: %s" type)
f846b94 @Baughn Patch courtesy of Alex Ott
Baughn authored
516 (progn
517 (setf type (match-string 1 type))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
518 ;; Cache for reuse by haskell-doc.
519 (when (and (boundp 'haskell-doc-mode) haskell-doc-mode
520 (boundp 'haskell-doc-user-defined-ids)
521 ;; Haskell-doc only works for idents, not arbitrary expr.
522 (string-match "\\`(?\\(\\s_+\\|\\(\\sw\\|\\s'\\)+\\)?[ \t]*::[ \t]*"
523 type))
524 (let ((sym (match-string 1 type)))
525 (setq haskell-doc-user-defined-ids
526 (cons (cons sym (substring type (match-end 0)))
ce971bb (inferior-haskell-spot-prompt): New function.
monnier authored
527 (delq (assoc sym haskell-doc-user-defined-ids)
528 haskell-doc-user-defined-ids)))))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
529
011c502 (inferior-haskell-type): Fix call to message.
monnier authored
530 (if (interactive-p) (message "%s" type))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
531 (when insert-value
532 (beginning-of-line)
533 (insert type "\n"))
f846b94 @Baughn Patch courtesy of Alex Ott
Baughn authored
534 type))))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
535
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
536 ;;;###autoload
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
537 (defun inferior-haskell-info (sym)
538 "Query the haskell process for the info of the given expression."
539 (interactive
540 (let ((sym (haskell-ident-at-point)))
541 (list (read-string (if (> (length sym) 0)
542 (format "Show info of (default %s): " sym)
543 "Show info of: ")
544 nil nil sym))))
545 (let ((proc (inferior-haskell-process)))
546 (with-current-buffer (process-buffer proc)
547 (let ((parsing-end ; Remember previous spot.
548 (marker-position (process-mark proc))))
549 (inferior-haskell-send-command proc (concat ":info " sym))
550 ;; Find new point.
551 (inferior-haskell-wait-for-prompt proc)
d549980 (inferior-haskell-type, inferior-haskell-info):
monnier authored
552 (goto-char (point-max))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
553 ;; Move to previous end-of-line
554 (end-of-line 0)
555 (let ((result
556 (buffer-substring-no-properties
557 (save-excursion (goto-char parsing-end)
558 (line-beginning-position 2))
559 (point))))
560 ;; Move back to end of process buffer
561 (goto-char (point-max))
562 (if (interactive-p) (message "%s" result))
563 result)))))
564
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
565 ;;;###autoload
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
566 (defun inferior-haskell-find-definition (sym)
567 "Attempt to locate and jump to the definition of the given expression."
568 (interactive
569 (let ((sym (haskell-ident-at-point)))
570 (list (read-string (if (> (length sym) 0)
571 (format "Find definition of (default %s): " sym)
572 "Find definition of: ")
573 nil nil sym))))
574 (let ((info (inferior-haskell-info sym)))
575 (if (not (string-match inferior-haskell-info-xref-re info))
576 (error "No source information available")
577 (let ((file (match-string-no-properties 1 info))
578 (line (string-to-number
579 (match-string-no-properties 2 info)))
580 (col (string-to-number
581 (match-string-no-properties 3 info))))
582 (when file
c6cbffc (inferior-haskell-wait-for-prompt): Add timeout arg.
monnier authored
583 (with-current-buffer (process-buffer (inferior-haskell-process))
584 ;; The file name is relative to the process's cwd.
585 (setq file (expand-file-name file)))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
586 ;; Push current location marker on the ring used by `find-tag'
587 (require 'etags)
588 (ring-insert find-tag-marker-ring (point-marker))
589 (pop-to-buffer (find-file-noselect file))
590 (when line
591 (goto-line line)
592 (when col (move-to-column col))))))))
593
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
594 ;;; Functions to find the documentation of a given function.
595 ;;
947a32d (inferior-haskell-info-xref-re): Allow a column-range.
monnier authored
596 ;; TODO for this section:
597 ;;
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
598 ;; * Support fetching of local Haddock docs pulled directly from source files.
599 ;; * Display docs locally? w3m?
600
601 (defcustom inferior-haskell-use-web-docs
602 'fallback
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
603 "Whether to use the online documentation. Possible values:
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
604 `never', meaning always use local documentation, unless the local
605 file doesn't exist, when do nothing, `fallback', which means only
606 use the online documentation when the local file doesn't exist,
607 or `always', meaning always use the online documentation,
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
608 regardless of existance of local files. Default is `fallback'."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
609 :group 'haskell
610 :type '(choice (const :tag "Never" never)
611 (const :tag "As fallback" fallback)
612 (const :tag "Always" always)))
613
614 (defcustom inferior-haskell-web-docs-base
615 "http://haskell.org/ghc/docs/latest/html/libraries/"
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
616 "The base URL of the online libraries documentation.
617 This will only be used if the value of `inferior-haskell-use-web-docs'
618 is `always' or `fallback'."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
619 :group 'haskell
620 :type 'string)
621
622 (defcustom haskell-package-manager-name "ghc-pkg"
623 "Name of the program to consult regarding package details."
624 :group 'haskell
625 :type 'string)
626
627 (defcustom haskell-package-conf-file
744f5ce (haskell-package-conf-file): Don't use `ignore-errors'
monnier authored
628 (condition-case nil
629 (with-temp-buffer
630 (call-process "ghc" nil t nil "--print-libdir")
631 (expand-file-name "package.conf"
632 (buffer-substring (point-min) (1- (point-max)))))
633 ;; Don't use `ignore-errors' because this form is not byte-compiled :-(
634 (error nil))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
635 "Where the package configuration file for the package manager resides.
636 By default this is set to `ghc --print-libdir`/package.conf."
637 :group 'haskell
638 :type 'string)
639
640 (defun inferior-haskell-get-module (sym)
641 "Fetch the module in which SYM is defined."
642 (let ((info (inferior-haskell-info sym)))
643 (unless (string-match inferior-haskell-module-re info)
947a32d (inferior-haskell-info-xref-re): Allow a column-range.
monnier authored
644 (error
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
645 "No documentation information available. Did you forget to C-c C-l?"))
7682f99 @chrisdone inferior-haskell-get-module now handles GHC 7.4's `LaTeX
chrisdone authored
646 (let ((module-name (match-string-no-properties 1 info)))
647 ;; Handles GHC 7.4.1+ which quotes module names like
648 ;; `System.Random', whereas previous GHC did not quote at all.
649 (if (string= "`" (substring module-name 0 1))
650 (substring module-name 1 (- (length module-name) 1))
651 module-name))))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
652
653 (defun inferior-haskell-query-ghc-pkg (&rest args)
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
654 "Send ARGS to `haskell-package-manager-name'.
655 Insert the output into the current buffer."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
656 (apply 'call-process haskell-package-manager-name nil t nil args))
657
658 (defun inferior-haskell-get-package-list ()
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
659 "Get the list of packages from `haskell-package-manager-name'."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
660 (with-temp-buffer
661 (inferior-haskell-query-ghc-pkg "--simple-output" "list")
662 (split-string (buffer-substring (point-min) (point-max)))))
663
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
664 (defun inferior-haskell-compute-module-alist ()
665 "Compute a list mapping modules to package names and haddock URLs using ghc-pkg."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
666 (message "Generating module alist...")
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
667 (let ((module-alist ()))
668 (with-temp-buffer
669 (dolist (package (inferior-haskell-get-package-list))
670 (erase-buffer)
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
671 (inferior-haskell-query-ghc-pkg "describe" package)
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
672
673 (let ((package-w/o-version
674 (replace-regexp-in-string "[-.0-9]*\\'" "" package))
675 ;; Find the Haddock documentation URL for this package
676 (haddock
677 (progn
678 (goto-char (point-min))
bf80267 (inferior-haskell-compute-module-alist): Fix regexps.
monnier authored
679 (when (re-search-forward "haddock-html:[ \t]+\\(.*[^ \t\n]\\)"
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
680 nil t)
681 (match-string 1)))))
682
683 ;; Fetch the list of exposed modules for this package
684 (goto-char (point-min))
bf80267 (inferior-haskell-compute-module-alist): Fix regexps.
monnier authored
685 (when (re-search-forward "^exposed-modules:\\(.*\\(\n[ \t].*\\)*\\)"
686 nil t)
687 (dolist (module (split-string (match-string 1)))
688 (push (list module package-w/o-version haddock)
689 module-alist)))))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
690
691 (message "Generating module alist... done")
692 module-alist)))
693
694
695 (defcustom inferior-haskell-module-alist-file
696 ;; (expand-file-name "~/.inf-haskell-module-alist")
bf80267 (inferior-haskell-compute-module-alist): Fix regexps.
monnier authored
697 (expand-file-name (concat "inf-haskell-module-alist-"
698 (number-to-string (user-uid)))
439a89e (inferior-haskell-cabal-of-buf)
monnier authored
699 (if (fboundp 'temp-directory)
700 (temp-directory)
701 temporary-file-directory))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
702 "Where to save the module -> package lookup table.
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
703 Set this to nil to never cache to a file."
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
704 :group 'haskell
705 :type '(choice (const :tag "Don't cache to file" nil) string))
706
707 (defvar inferior-haskell-module-alist nil
708 "Association list of modules to their packages.
709 Each element is of the form (MODULE PACKAGE HADDOCK), where
710 MODULE is the name of a module,
711 PACKAGE is the package it belongs to, and
712 HADDOCK is the path to that package's Haddock documentation.
713
714 This is calculated on-demand using `inferior-haskell-compute-module-alist'.
715 It's also cached in the file `inferior-haskell-module-alist-file',
716 so that it can be obtained more quickly next time.")
717
718 (defun inferior-haskell-module-alist ()
719 "Get the module alist from cache or ghc-pkg's info."
720 (or
721 ;; If we already have computed the alist, use it...
722 inferior-haskell-module-alist
723 (setq inferior-haskell-module-alist
724 (or
725 ;; ...otherwise try to read it from the cache file...
726 (and
727 inferior-haskell-module-alist-file
728 (file-readable-p inferior-haskell-module-alist-file)
729 (file-newer-than-file-p inferior-haskell-module-alist-file
730 haskell-package-conf-file)
731 (with-temp-buffer
732 (insert-file-contents inferior-haskell-module-alist-file)
733 (goto-char (point-min))
734 (prog1 (read (current-buffer))
735 (message "Read module alist from file cache."))))
736
737 ;; ...or generate it again and save it in a file for later.
738 (let ((alist (inferior-haskell-compute-module-alist)))
739 (when inferior-haskell-module-alist-file
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
740 (with-temp-buffer
741 (print alist (current-buffer))
742 ;; Do the write to a temp file first, then rename it.
743 ;; This makes it more atomic, and suffers from fewer security
744 ;; holes related to race conditions if the file is in /tmp.
745 (let ((tmp (make-temp-file inferior-haskell-module-alist-file)))
746 (write-region (point-min) (point-max) tmp)
747 (rename-file tmp inferior-haskell-module-alist-file
748 'ok-if-already-exists))))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
749 alist)))))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
750
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
751 (defvar inferior-haskell-ghc-internal-ident-alist
752 ;; FIXME: Fill this table, ideally semi-automatically.
753 '(("GHC.Base.return" . "Control.Monad.return")
754 ("GHC.List" . "Data.List")))
755
756 (defun inferior-haskell-map-internal-ghc-ident (ident)
757 "Try to translate some internal GHC identifier to its alter ego in haskell docs."
758 (let ((head ident)
759 (tail "")
760 remapped)
761 (while (and (not
762 (setq remapped
763 (cdr (assoc head
764 inferior-haskell-ghc-internal-ident-alist))))
765 (string-match "\\.[^.]+\\'" head))
766 (setq tail (concat (match-string 0 head) tail))
767 (setq head (substring head 0 (match-beginning 0))))
768 (concat (or remapped head) tail)))
769
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
770 ;;;###autoload
771 (defun inferior-haskell-find-haddock (sym)
772 "Find and open the Haddock documentation of SYM.
773 Make sure to load the file into GHCi or Hugs first by using C-c C-l.
774 Only works for functions in a package installed with ghc-pkg, or
775 whatever the value of `haskell-package-manager-name' is.
776
777 This function needs to find which package a given module belongs
778 to. In order to do this, it computes a module-to-package lookup
779 alist, which is expensive to compute (it takes upwards of five
780 seconds with more than about thirty installed packages). As a
781 result, we cache it across sessions using the cache file
782 referenced by `inferior-haskell-module-alist-file'. We test to
783 see if this is newer than `haskell-package-conf-file' every time
784 we load it."
785 (interactive
786 (let ((sym (haskell-ident-at-point)))
787 (list (read-string (if (> (length sym) 0)
788 (format "Find documentation of (default %s): " sym)
789 "Find documentation of: ")
790 nil nil sym))))
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
791 (setq sym (inferior-haskell-map-internal-ghc-ident sym))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
792 (let* (;; Find the module and look it up in the alist
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
793 (module (inferior-haskell-get-module sym))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
794 (alist-record (assoc module (inferior-haskell-module-alist)))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
795 (package (nth 1 alist-record))
796 (file-name (concat (subst-char-in-string ?. ?- module) ".html"))
797 (local-path (concat (nth 2 alist-record) "/" file-name))
798 (url (if (or (eq inferior-haskell-use-web-docs 'always)
799 (and (not (file-exists-p local-path))
800 (eq inferior-haskell-use-web-docs 'fallback)))
f2fd5e5 (inferior-haskell-find-haddock): Jump to the symbol anchor within Haddoc...
monnier authored
801 (concat inferior-haskell-web-docs-base package "/" file-name
802 ;; Jump to the symbol anchor within Haddock.
803 "#v:" sym)
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
804 (and (file-exists-p local-path)
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
805 (concat "file://" local-path)))))
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
806 (if url (browse-url url) (error "Local file doesn't exist"))))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
807
4418871 New file.
monnier authored
808 (provide 'inf-haskell)
bfd15e1 (inferior-haskell-mode): Hide compilation-mode bindings.
monnier authored
809
810 ;; arch-tag: 61804287-63dd-4052-bc0e-90f691b34b40
4418871 New file.
monnier authored
811 ;;; inf-haskell.el ends here
Something went wrong with that request. Please try again.