Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 811 lines (732 sloc) 35.445 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 …
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 …
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 warni…
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 excepti…
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 excepti…
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 excepti…
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. C…
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. C…
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. C…
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
8bebada @vvv make `inferior-haskell-find-project-root' respect export lists
vvv authored
306 "^module[ \t]+\\([^- \t\n]+\\.[^- \t\n]+\\)[ \t]+" 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 buf…
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 buf…
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 buf…
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 :{ ... :}."
7aac27a @apsk Initial support for send declaration'.
apsk authored
423 (concat ":{\n"
424 (if (string-match (concat "^\\s-*"
425 haskell-ds-start-keywords-re)
426 code)
427 ;; non-fun-decl
428 code
429 ;; fun-decl, wrapping into let { .. (; ..)* }
430 (concat "let {\n"
431 (mapconcat
432 ;; adding 2 whitespaces to each line
433 (lambda (decl)
434 (mapconcat (lambda (s)
435 (concat " " s))
436 (split-string decl "\n")
437 "\n"))
438 ;; splitting function case-decls
439 (let (decls)
440 (while (string-match "^\\(\\w+\\).*\n*\\(?:\\s-+.*\n+\\)*" code)
441 (push (match-string 0 code) decls)
442 (setq code (substring code (match-end 0))))
443 (reverse decls))
444 "\n;\n")
445 "\n}"))
446 "\n:}\n"))
447
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
448 (defun inferior-haskell-flash-decl (start end &optional timeout)
449 "Temporarily highlight declaration."
450 (let ((overlay (make-overlay start end)))
451 (overlay-put overlay 'face 'secondary-selection)
452 (run-with-timer (or timeout 0.2) nil 'delete-overlay overlay)))
453
7aac27a @apsk Initial support for send declaration'.
apsk authored
454 ;;;###autoload
455 (defun inferior-haskell-send-decl ()
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
456 "Send current declaration to inferior-haskell process."
7aac27a @apsk Initial support for send declaration'.
apsk authored
457 (interactive)
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
458 (require 'haskell-decl-scan)
7aac27a @apsk Initial support for send declaration'.
apsk authored
459 (save-excursion
460 (goto-char (1+ (point)))
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
461 (let* ((proc (inferior-haskell-process))
462 (start (or (haskell-ds-backward-decl) (point-min)))
463 (end (or (haskell-ds-forward-decl) (point-max)))
464 (raw-decl (buffer-substring start end)))
7aac27a @apsk Initial support for send declaration'.
apsk authored
465 ;; enter multiline-prompt-cutting-mode
466 (with-current-buffer (process-buffer proc)
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
467 (setq inferior-haskell-send-decl-post-filter-on t))
468 ;; flash decl
469 (inferior-haskell-flash-decl start end)
7aac27a @apsk Initial support for send declaration'.
apsk authored
470 ;; send decl
471 (comint-send-string proc (inferior-haskell-wrap-decl raw-decl))
472 ;; send preview
473 (inferior-haskell-send-command
474 proc
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
475 (let* ((str (remove ?\n raw-decl))
476 (len (min 15 (length str))))
477 (concat "-- evaluating {: "
478 (substring str 0 len)
479 (if (= 15 len) ".." "")
480 " :}"))))))
7aac27a @apsk Initial support for send declaration'.
apsk authored
481
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
482 ;;;###autoload
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
483 (defun inferior-haskell-type (expr &optional insert-value)
484 "Query the haskell process for the type of the given expression.
485 If optional argument `insert-value' is non-nil, insert the type above point
486 in the buffer. This can be done interactively with the \\[universal-argument] prefix.
487 The returned info is cached for reuse by `haskell-doc-mode'."
488 (interactive
489 (let ((sym (haskell-ident-at-point)))
490 (list (read-string (if (> (length sym) 0)
491 (format "Show type of (default %s): " sym)
492 "Show type of: ")
493 nil nil sym)
494 current-prefix-arg)))
495 (if (string-match "\\`\\s_+\\'" expr) (setq expr (concat "(" expr ")")))
496 (let* ((proc (inferior-haskell-process))
497 (type
498 (with-current-buffer (process-buffer proc)
499 (let ((parsing-end ; Remember previous spot.
500 (marker-position (process-mark proc))))
501 (inferior-haskell-send-command proc (concat ":type " expr))
502 ;; Find new point.
503 (inferior-haskell-wait-for-prompt proc)
d549980 (inferior-haskell-type, inferior-haskell-info):
monnier authored
504 (goto-char (point-max))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
505 ;; Back up to the previous end-of-line.
506 (end-of-line 0)
507 ;; Extract the type output
508 (buffer-substring-no-properties
509 (save-excursion (goto-char parsing-end)
510 (line-beginning-position 2))
511 (point))))))
f846b94 @Baughn Patch courtesy of Alex Ott
Baughn authored
512 (if (not (string-match (concat "^\\(" (regexp-quote expr) "[ \t\n]+::[ \t\n]*\\(.\\|\n\\)*\\)")
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
513 type))
514 (error "No type info: %s" type)
f846b94 @Baughn Patch courtesy of Alex Ott
Baughn authored
515 (progn
516 (setf type (match-string 1 type))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
517 ;; Cache for reuse by haskell-doc.
518 (when (and (boundp 'haskell-doc-mode) haskell-doc-mode
519 (boundp 'haskell-doc-user-defined-ids)
520 ;; Haskell-doc only works for idents, not arbitrary expr.
521 (string-match "\\`(?\\(\\s_+\\|\\(\\sw\\|\\s'\\)+\\)?[ \t]*::[ \t]*"
522 type))
523 (let ((sym (match-string 1 type)))
524 (setq haskell-doc-user-defined-ids
525 (cons (cons sym (substring type (match-end 0)))
ce971bb (inferior-haskell-spot-prompt): New function.
monnier authored
526 (delq (assoc sym haskell-doc-user-defined-ids)
527 haskell-doc-user-defined-ids)))))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
528
011c502 (inferior-haskell-type): Fix call to message.
monnier authored
529 (if (interactive-p) (message "%s" type))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
530 (when insert-value
531 (beginning-of-line)
532 (insert type "\n"))
f846b94 @Baughn Patch courtesy of Alex Ott
Baughn authored
533 type))))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
534
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
535 ;;;###autoload
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
536 (defun inferior-haskell-info (sym)
537 "Query the haskell process for the info of the given expression."
538 (interactive
539 (let ((sym (haskell-ident-at-point)))
540 (list (read-string (if (> (length sym) 0)
541 (format "Show info of (default %s): " sym)
542 "Show info of: ")
543 nil nil sym))))
544 (let ((proc (inferior-haskell-process)))
545 (with-current-buffer (process-buffer proc)
546 (let ((parsing-end ; Remember previous spot.
547 (marker-position (process-mark proc))))
548 (inferior-haskell-send-command proc (concat ":info " sym))
549 ;; Find new point.
550 (inferior-haskell-wait-for-prompt proc)
d549980 (inferior-haskell-type, inferior-haskell-info):
monnier authored
551 (goto-char (point-max))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
552 ;; Move to previous end-of-line
553 (end-of-line 0)
554 (let ((result
555 (buffer-substring-no-properties
556 (save-excursion (goto-char parsing-end)
557 (line-beginning-position 2))
558 (point))))
559 ;; Move back to end of process buffer
560 (goto-char (point-max))
561 (if (interactive-p) (message "%s" result))
562 result)))))
563
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
564 ;;;###autoload
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
565 (defun inferior-haskell-find-definition (sym)
566 "Attempt to locate and jump to the definition of the given expression."
567 (interactive
568 (let ((sym (haskell-ident-at-point)))
569 (list (read-string (if (> (length sym) 0)
570 (format "Find definition of (default %s): " sym)
571 "Find definition of: ")
572 nil nil sym))))
573 (let ((info (inferior-haskell-info sym)))
574 (if (not (string-match inferior-haskell-info-xref-re info))
575 (error "No source information available")
576 (let ((file (match-string-no-properties 1 info))
577 (line (string-to-number
578 (match-string-no-properties 2 info)))
579 (col (string-to-number
580 (match-string-no-properties 3 info))))
581 (when file
c6cbffc (inferior-haskell-wait-for-prompt): Add timeout arg.
monnier authored
582 (with-current-buffer (process-buffer (inferior-haskell-process))
583 ;; The file name is relative to the process's cwd.
584 (setq file (expand-file-name file)))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
585 ;; Push current location marker on the ring used by `find-tag'
586 (require 'etags)
587 (ring-insert find-tag-marker-ring (point-marker))
588 (pop-to-buffer (find-file-noselect file))
589 (when line
590 (goto-line line)
591 (when col (move-to-column col))))))))
592
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
593 ;;; Functions to find the documentation of a given function.
594 ;;
947a32d (inferior-haskell-info-xref-re): Allow a column-range.
monnier authored
595 ;; TODO for this section:
596 ;;
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
597 ;; * Support fetching of local Haddock docs pulled directly from source files.
598 ;; * Display docs locally? w3m?
599
600 (defcustom inferior-haskell-use-web-docs
601 'fallback
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
602 "Whether to use the online documentation. Possible values:
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
603 `never', meaning always use local documentation, unless the local
604 file doesn't exist, when do nothing, `fallback', which means only
605 use the online documentation when the local file doesn't exist,
606 or `always', meaning always use the online documentation,
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
607 regardless of existance of local files. Default is `fallback'."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
608 :group 'haskell
609 :type '(choice (const :tag "Never" never)
610 (const :tag "As fallback" fallback)
611 (const :tag "Always" always)))
612
613 (defcustom inferior-haskell-web-docs-base
614 "http://haskell.org/ghc/docs/latest/html/libraries/"
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
615 "The base URL of the online libraries documentation.
616 This will only be used if the value of `inferior-haskell-use-web-docs'
617 is `always' or `fallback'."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
618 :group 'haskell
619 :type 'string)
620
621 (defcustom haskell-package-manager-name "ghc-pkg"
622 "Name of the program to consult regarding package details."
623 :group 'haskell
624 :type 'string)
625
626 (defcustom haskell-package-conf-file
744f5ce (haskell-package-conf-file): Don't use `ignore-errors'
monnier authored
627 (condition-case nil
628 (with-temp-buffer
629 (call-process "ghc" nil t nil "--print-libdir")
630 (expand-file-name "package.conf"
631 (buffer-substring (point-min) (1- (point-max)))))
632 ;; Don't use `ignore-errors' because this form is not byte-compiled :-(
633 (error nil))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
634 "Where the package configuration file for the package manager resides.
635 By default this is set to `ghc --print-libdir`/package.conf."
636 :group 'haskell
637 :type 'string)
638
639 (defun inferior-haskell-get-module (sym)
640 "Fetch the module in which SYM is defined."
641 (let ((info (inferior-haskell-info sym)))
642 (unless (string-match inferior-haskell-module-re info)
947a32d (inferior-haskell-info-xref-re): Allow a column-range.
monnier authored
643 (error
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
644 "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
645 (let ((module-name (match-string-no-properties 1 info)))
646 ;; Handles GHC 7.4.1+ which quotes module names like
647 ;; `System.Random', whereas previous GHC did not quote at all.
648 (if (string= "`" (substring module-name 0 1))
649 (substring module-name 1 (- (length module-name) 1))
650 module-name))))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
651
652 (defun inferior-haskell-query-ghc-pkg (&rest args)
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
653 "Send ARGS to `haskell-package-manager-name'.
654 Insert the output into the current buffer."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
655 (apply 'call-process haskell-package-manager-name nil t nil args))
656
657 (defun inferior-haskell-get-package-list ()
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
658 "Get the list of packages from `haskell-package-manager-name'."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
659 (with-temp-buffer
660 (inferior-haskell-query-ghc-pkg "--simple-output" "list")
661 (split-string (buffer-substring (point-min) (point-max)))))
662
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
663 (defun inferior-haskell-compute-module-alist ()
664 "Compute a list mapping modules to package names and haddock URLs using ghc-pkg."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
665 (message "Generating module alist...")
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
666 (let ((module-alist ()))
667 (with-temp-buffer
668 (dolist (package (inferior-haskell-get-package-list))
669 (erase-buffer)
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
670 (inferior-haskell-query-ghc-pkg "describe" package)
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
671
672 (let ((package-w/o-version
673 (replace-regexp-in-string "[-.0-9]*\\'" "" package))
674 ;; Find the Haddock documentation URL for this package
675 (haddock
676 (progn
677 (goto-char (point-min))
bf80267 (inferior-haskell-compute-module-alist): Fix regexps.
monnier authored
678 (when (re-search-forward "haddock-html:[ \t]+\\(.*[^ \t\n]\\)"
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
679 nil t)
680 (match-string 1)))))
681
682 ;; Fetch the list of exposed modules for this package
683 (goto-char (point-min))
bf80267 (inferior-haskell-compute-module-alist): Fix regexps.
monnier authored
684 (when (re-search-forward "^exposed-modules:\\(.*\\(\n[ \t].*\\)*\\)"
685 nil t)
686 (dolist (module (split-string (match-string 1)))
687 (push (list module package-w/o-version haddock)
688 module-alist)))))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
689
690 (message "Generating module alist... done")
691 module-alist)))
692
693
694 (defcustom inferior-haskell-module-alist-file
695 ;; (expand-file-name "~/.inf-haskell-module-alist")
bf80267 (inferior-haskell-compute-module-alist): Fix regexps.
monnier authored
696 (expand-file-name (concat "inf-haskell-module-alist-"
697 (number-to-string (user-uid)))
439a89e (inferior-haskell-cabal-of-buf)
monnier authored
698 (if (fboundp 'temp-directory)
699 (temp-directory)
700 temporary-file-directory))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
701 "Where to save the module -> package lookup table.
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
702 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
703 :group 'haskell
704 :type '(choice (const :tag "Don't cache to file" nil) string))
705
706 (defvar inferior-haskell-module-alist nil
707 "Association list of modules to their packages.
708 Each element is of the form (MODULE PACKAGE HADDOCK), where
709 MODULE is the name of a module,
710 PACKAGE is the package it belongs to, and
711 HADDOCK is the path to that package's Haddock documentation.
712
713 This is calculated on-demand using `inferior-haskell-compute-module-alist'.
714 It's also cached in the file `inferior-haskell-module-alist-file',
715 so that it can be obtained more quickly next time.")
716
717 (defun inferior-haskell-module-alist ()
718 "Get the module alist from cache or ghc-pkg's info."
719 (or
720 ;; If we already have computed the alist, use it...
721 inferior-haskell-module-alist
722 (setq inferior-haskell-module-alist
723 (or
724 ;; ...otherwise try to read it from the cache file...
725 (and
726 inferior-haskell-module-alist-file
727 (file-readable-p inferior-haskell-module-alist-file)
728 (file-newer-than-file-p inferior-haskell-module-alist-file
729 haskell-package-conf-file)
730 (with-temp-buffer
731 (insert-file-contents inferior-haskell-module-alist-file)
732 (goto-char (point-min))
733 (prog1 (read (current-buffer))
734 (message "Read module alist from file cache."))))
735
736 ;; ...or generate it again and save it in a file for later.
737 (let ((alist (inferior-haskell-compute-module-alist)))
738 (when inferior-haskell-module-alist-file
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
739 (with-temp-buffer
740 (print alist (current-buffer))
741 ;; Do the write to a temp file first, then rename it.
742 ;; This makes it more atomic, and suffers from fewer security
743 ;; holes related to race conditions if the file is in /tmp.
744 (let ((tmp (make-temp-file inferior-haskell-module-alist-file)))
745 (write-region (point-min) (point-max) tmp)
746 (rename-file tmp inferior-haskell-module-alist-file
747 'ok-if-already-exists))))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
748 alist)))))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
749
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
750 (defvar inferior-haskell-ghc-internal-ident-alist
751 ;; FIXME: Fill this table, ideally semi-automatically.
752 '(("GHC.Base.return" . "Control.Monad.return")
753 ("GHC.List" . "Data.List")))
754
755 (defun inferior-haskell-map-internal-ghc-ident (ident)
756 "Try to translate some internal GHC identifier to its alter ego in haskell docs."
757 (let ((head ident)
758 (tail "")
759 remapped)
760 (while (and (not
761 (setq remapped
762 (cdr (assoc head
763 inferior-haskell-ghc-internal-ident-alist))))
764 (string-match "\\.[^.]+\\'" head))
765 (setq tail (concat (match-string 0 head) tail))
766 (setq head (substring head 0 (match-beginning 0))))
767 (concat (or remapped head) tail)))
768
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
769 ;;;###autoload
770 (defun inferior-haskell-find-haddock (sym)
771 "Find and open the Haddock documentation of SYM.
772 Make sure to load the file into GHCi or Hugs first by using C-c C-l.
773 Only works for functions in a package installed with ghc-pkg, or
774 whatever the value of `haskell-package-manager-name' is.
775
776 This function needs to find which package a given module belongs
777 to. In order to do this, it computes a module-to-package lookup
778 alist, which is expensive to compute (it takes upwards of five
779 seconds with more than about thirty installed packages). As a
780 result, we cache it across sessions using the cache file
781 referenced by `inferior-haskell-module-alist-file'. We test to
782 see if this is newer than `haskell-package-conf-file' every time
783 we load it."
784 (interactive
785 (let ((sym (haskell-ident-at-point)))
786 (list (read-string (if (> (length sym) 0)
787 (format "Find documentation of (default %s): " sym)
788 "Find documentation of: ")
789 nil nil sym))))
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
790 (setq sym (inferior-haskell-map-internal-ghc-ident sym))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
791 (let* (;; Find the module and look it up in the alist
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
792 (module (inferior-haskell-get-module sym))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
793 (alist-record (assoc module (inferior-haskell-module-alist)))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
794 (package (nth 1 alist-record))
795 (file-name (concat (subst-char-in-string ?. ?- module) ".html"))
796 (local-path (concat (nth 2 alist-record) "/" file-name))
797 (url (if (or (eq inferior-haskell-use-web-docs 'always)
798 (and (not (file-exists-p local-path))
799 (eq inferior-haskell-use-web-docs 'fallback)))
f2fd5e5 (inferior-haskell-find-haddock): Jump to the symbol anchor within Had…
monnier authored
800 (concat inferior-haskell-web-docs-base package "/" file-name
801 ;; Jump to the symbol anchor within Haddock.
802 "#v:" sym)
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
803 (and (file-exists-p local-path)
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
804 (concat "file://" local-path)))))
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
805 (if url (browse-url url) (error "Local file doesn't exist"))))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
806
4418871 New file.
monnier authored
807 (provide 'inf-haskell)
bfd15e1 (inferior-haskell-mode): Hide compilation-mode bindings.
monnier authored
808
809 ;; arch-tag: 61804287-63dd-4052-bc0e-90f691b34b40
4418871 New file.
monnier authored
810 ;;; inf-haskell.el ends here
Something went wrong with that request. Please try again.