Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 817 lines (736 sloc) 35.548 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
3758409 @suhailshergill Fix inferior-haskell-load-file crash
suhailshergill authored
286 (let* (
287 (cabal-file (inferior-haskell-cabal-of-buf buf))
288 (cabal (when cabal-file
289 (find-file-noselect cabal-file)))
290 )
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
291 (or (when cabal
292 (with-current-buffer cabal
f11a557 (inferior-haskell-find-project-root): Use it.
monnier authored
293 (let ((hsd (haskell-cabal-get-setting "hs-source-dirs")))
294 (if (null hsd)
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
295 ;; If there's a Cabal file with no Hs-Source-Dirs, then
296 ;; just use the Cabal file's directory.
297 default-directory
298 ;; If there is an HSD, then check that it's an existing
299 ;; dir (otherwise, it may be a list of dirs and we don't
300 ;; know what to do with those). If it doesn't exist, then
301 ;; give up.
3afce2f (inferior-haskell-find-project-root): Minor simplification.
monnier authored
302 (if (file-directory-p hsd) (expand-file-name hsd))))))
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
303 ;; If there's no Cabal file or it's not helpful, try to look for
304 ;; a "module" statement and count the number of "." in the
305 ;; module name.
306 (save-excursion
307 (goto-char (point-min))
308 (let ((case-fold-search nil))
309 (when (re-search-forward
21bcba1 @gracjan Better regexp to match module name in inf-haskell
gracjan authored
310 "^module[ \t]+\\(\\(?:\\sw\\|[.]\\)+\\)" nil t)
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
311 (let* ((dir default-directory)
312 (module (match-string 1))
313 (pos 0))
314 (while (string-match "\\." module pos)
315 (setq pos (match-end 0))
316 (setq dir (expand-file-name ".." dir)))
317 ;; Let's check that the module name matches the file name,
318 ;; otherwise the project root is probably not what we think.
319 (if (eq t (compare-strings
320 (file-name-sans-extension buffer-file-name)
321 nil nil
322 (expand-file-name
323 (replace-regexp-in-string "\\." "/" module)
324 dir)
325 nil nil t))
326 dir
327 ;; If they're not equal, it means the local directory
328 ;; hierarchy doesn't match the module name. This seems
329 ;; odd, so let's warn the user about it. May help us
330 ;; debug this code as well.
331 (message "Ignoring inconsistent `module' info: %s in %s"
332 module buffer-file-name)
333 nil)))))))))
947a32d (inferior-haskell-info-xref-re): Allow a column-range.
monnier authored
334
335
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
336
4418871 New file.
monnier authored
337 ;;;###autoload
9ed46b1 (inferior-haskell-load-file): Re-add the `reload' arg.
monnier authored
338 (defun inferior-haskell-load-file (&optional reload)
0294d90 (inferior-haskell-load-file): Do reload if prefix arg.
monnier authored
339 "Pass the current buffer's file to the inferior haskell process.
340 If prefix arg \\[universal-argument] is given, just reload the previous file."
8af5157 (inferior-haskell-load-file): Typo.
monnier authored
341 (interactive "P")
2eaced4 (inferior-haskell-load-file): Save buffer before using buffer-file-name.
monnier authored
342 ;; Save first, so we're sure that `buffer-file-name' is non-nil afterward.
343 (save-buffer)
c7c6278 (inferior-haskell-use-cabal): New custom var.
monnier authored
344 (let ((buf (current-buffer))
345 (file buffer-file-name)
4418871 New file.
monnier authored
346 (proc (inferior-haskell-process)))
2702f77 @Baughn Print a proper error if inferior-haskell-load-file is called on a buf…
Baughn authored
347 (if file
348 (with-current-buffer (process-buffer proc)
349 (compilation-forget-errors)
350 (let ((parsing-end (marker-position (process-mark proc)))
351 root)
352 ;; Go to the root of the Cabal project, if applicable.
353 (when (and inferior-haskell-find-project-root
354 (setq root (inferior-haskell-find-project-root buf)))
355 ;; Not sure if it's useful/needed and if it actually works.
356 (unless (equal default-directory root)
357 (setq default-directory root)
358 (inferior-haskell-send-command
359 proc (concat ":cd " default-directory)))
360 (setq file (file-relative-name file)))
c7c6278 (inferior-haskell-use-cabal): New custom var.
monnier authored
361 (inferior-haskell-send-command
2702f77 @Baughn Print a proper error if inferior-haskell-load-file is called on a buf…
Baughn authored
362 proc (if reload ":reload"
363 (concat ":load \""
364 ;; Espace the backslashes that may occur in file names.
365 (replace-regexp-in-string "[\\\"]" "\\\\\&" file)
366 "\"")))
367 ;; Move the parsing-end marker *after* sending the command so
368 ;; that it doesn't point just to the insertion point.
369 ;; Otherwise insertion may move the marker (if done with
370 ;; insert-before-markers) and we'd then miss some errors.
371 (if (boundp 'compilation-parsing-end)
372 (if (markerp compilation-parsing-end)
373 (set-marker compilation-parsing-end parsing-end)
374 (setq compilation-parsing-end parsing-end))))
375 (with-selected-window (display-buffer (current-buffer) nil 'visible)
1da6412 @Baughn New major mode: GHC-core
Baughn authored
376 (end-of-buffer))
2702f77 @Baughn Print a proper error if inferior-haskell-load-file is called on a buf…
Baughn authored
377 ;; Use compilation-auto-jump-to-first-error if available.
378 ;; (if (and (boundp 'compilation-auto-jump-to-first-error)
379 ;; compilation-auto-jump-to-first-error
380 ;; (boundp 'compilation-auto-jump-to-next))
381 ;; (setq compilation-auto-jump-to-next t)
382 (when inferior-haskell-wait-and-jump
383 (inferior-haskell-wait-for-prompt proc)
384 (ignore-errors ;Don't beep if there were no errors.
385 (next-error))))
386 (error "No file associated with buffer"))))
8512ba1 (inferior-haskell-mode): Typo.
monnier authored
387
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
388 (defvar inferior-haskell-run-command ":main")
389
1da6412 @Baughn New major mode: GHC-core
Baughn authored
390 ;;;###autoload
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
391 (defun inferior-haskell-load-and-run (command)
9ed46b1 (inferior-haskell-load-file): Re-add the `reload' arg.
monnier authored
392 "Pass the current buffer's file to haskell and then run a COMMAND."
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
393 (interactive
394 (list
395 (if (and inferior-haskell-run-command (not current-prefix-arg))
396 inferior-haskell-run-command
397 (read-string "Command to run: " nil nil inferior-haskell-run-command))))
398 (setq inferior-haskell-run-command command)
40fa207 * inf-haskell.el (inferior-haskell-load-and-run): Don't run if there
monnier authored
399 (let* ((inferior-haskell-errors nil)
400 (neh (lambda () (setq inferior-haskell-errors t))))
401 (unwind-protect
402 (let ((inferior-haskell-wait-and-jump t))
403 (add-hook 'next-error-hook neh)
404 (inferior-haskell-load-file))
405 (remove-hook 'next-error-hook neh))
406 (unless inferior-haskell-errors
407 (inferior-haskell-send-command (inferior-haskell-process) command)
408 (switch-to-haskell))))
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
409
8512ba1 (inferior-haskell-mode): Typo.
monnier authored
410 (defun inferior-haskell-send-command (proc str)
411 (setq str (concat str "\n"))
412 (with-current-buffer (process-buffer proc)
7410480 (inferior-haskell-wait-for-prompt): New fun, extracted
monnier authored
413 (inferior-haskell-wait-for-prompt proc)
8512ba1 (inferior-haskell-mode): Typo.
monnier authored
414 (goto-char (process-mark proc))
415 (insert-before-markers str)
416 (move-marker comint-last-input-end (point))
ce971bb (inferior-haskell-spot-prompt): New function.
monnier authored
417 (setq inferior-haskell-seen-prompt nil)
8512ba1 (inferior-haskell-mode): Typo.
monnier authored
418 (comint-send-string proc str)))
4418871 New file.
monnier authored
419
9ed46b1 (inferior-haskell-load-file): Re-add the `reload' arg.
monnier authored
420 (defun inferior-haskell-reload-file ()
421 "Tell the inferior haskell process to reread the current buffer's file."
422 (interactive)
423 (inferior-haskell-load-file 'reload))
424
7aac27a @apsk Initial support for send declaration'.
apsk authored
425 (defun inferior-haskell-wrap-decl (code)
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
426 "Wrap declaration code into :{ ... :}."
0a72157 @apsk Added concatenation of newline to declaration-code before wrapping in…
apsk authored
427 (setq code (concat code "\n"))
7aac27a @apsk Initial support for send declaration'.
apsk authored
428 (concat ":{\n"
429 (if (string-match (concat "^\\s-*"
430 haskell-ds-start-keywords-re)
431 code)
432 ;; non-fun-decl
433 code
434 ;; fun-decl, wrapping into let { .. (; ..)* }
435 (concat "let {\n"
436 (mapconcat
437 ;; adding 2 whitespaces to each line
438 (lambda (decl)
439 (mapconcat (lambda (s)
440 (concat " " s))
441 (split-string decl "\n")
442 "\n"))
443 ;; splitting function case-decls
444 (let (decls)
445 (while (string-match "^\\(\\w+\\).*\n*\\(?:\\s-+.*\n+\\)*" code)
446 (push (match-string 0 code) decls)
447 (setq code (substring code (match-end 0))))
448 (reverse decls))
449 "\n;\n")
450 "\n}"))
451 "\n:}\n"))
452
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
453 (defun inferior-haskell-flash-decl (start end &optional timeout)
454 "Temporarily highlight declaration."
455 (let ((overlay (make-overlay start end)))
456 (overlay-put overlay 'face 'secondary-selection)
457 (run-with-timer (or timeout 0.2) nil 'delete-overlay overlay)))
458
7aac27a @apsk Initial support for send declaration'.
apsk authored
459 ;;;###autoload
460 (defun inferior-haskell-send-decl ()
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
461 "Send current declaration to inferior-haskell process."
7aac27a @apsk Initial support for send declaration'.
apsk authored
462 (interactive)
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
463 (require 'haskell-decl-scan)
7aac27a @apsk Initial support for send declaration'.
apsk authored
464 (save-excursion
465 (goto-char (1+ (point)))
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
466 (let* ((proc (inferior-haskell-process))
467 (start (or (haskell-ds-backward-decl) (point-min)))
468 (end (or (haskell-ds-forward-decl) (point-max)))
469 (raw-decl (buffer-substring start end)))
7aac27a @apsk Initial support for send declaration'.
apsk authored
470 ;; enter multiline-prompt-cutting-mode
471 (with-current-buffer (process-buffer proc)
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
472 (setq inferior-haskell-send-decl-post-filter-on t))
473 ;; flash decl
474 (inferior-haskell-flash-decl start end)
7aac27a @apsk Initial support for send declaration'.
apsk authored
475 ;; send decl
476 (comint-send-string proc (inferior-haskell-wrap-decl raw-decl))
477 ;; send preview
478 (inferior-haskell-send-command
479 proc
16fabab @apsk Some refactoring, fixes, and highlighting for 'send-decl'.
apsk authored
480 (let* ((str (remove ?\n raw-decl))
481 (len (min 15 (length str))))
482 (concat "-- evaluating {: "
483 (substring str 0 len)
484 (if (= 15 len) ".." "")
485 " :}"))))))
7aac27a @apsk Initial support for send declaration'.
apsk authored
486
d1dd80c @jwiegley Factored common code, added inferior-haskell-kind
jwiegley authored
487 (defun inferior-haskell-get-result (inf-expr)
488 "Submit the expression `inf-expr' to ghci and read the result."
489 (let ((proc (inferior-haskell-process)))
490 (with-current-buffer (process-buffer proc)
491 (let ((parsing-end ; Remember previous spot.
492 (marker-position (process-mark proc))))
493 (inferior-haskell-send-command proc inf-expr)
494 ;; Find new point.
495 (inferior-haskell-wait-for-prompt proc)
496 (goto-char (point-max))
497 ;; Back up to the previous end-of-line.
498 (end-of-line 0)
499 ;; Extract the output
500 (buffer-substring-no-properties
501 (save-excursion (goto-char parsing-end)
502 (line-beginning-position 2))
503 (point))))))
504
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
505 ;;;###autoload
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
506 (defun inferior-haskell-type (expr &optional insert-value)
507 "Query the haskell process for the type of the given expression.
508 If optional argument `insert-value' is non-nil, insert the type above point
509 in the buffer. This can be done interactively with the \\[universal-argument] prefix.
510 The returned info is cached for reuse by `haskell-doc-mode'."
511 (interactive
512 (let ((sym (haskell-ident-at-point)))
513 (list (read-string (if (> (length sym) 0)
514 (format "Show type of (default %s): " sym)
515 "Show type of: ")
516 nil nil sym)
517 current-prefix-arg)))
518 (if (string-match "\\`\\s_+\\'" expr) (setq expr (concat "(" expr ")")))
d1dd80c @jwiegley Factored common code, added inferior-haskell-kind
jwiegley authored
519 (let ((type (inferior-haskell-get-result (concat ":type " expr))))
520 (if (not (string-match (concat "^\\(" (regexp-quote expr)
521 "[ \t\n]+::[ \t\n]*\\(.\\|\n\\)*\\)")
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
522 type))
523 (error "No type info: %s" type)
f846b94 @Baughn Patch courtesy of Alex Ott
Baughn authored
524 (progn
525 (setf type (match-string 1 type))
d1dd80c @jwiegley Factored common code, added inferior-haskell-kind
jwiegley authored
526 ;; Cache for reuse by haskell-doc.
527 (when (and (boundp 'haskell-doc-mode) haskell-doc-mode
528 (boundp 'haskell-doc-user-defined-ids)
529 ;; Haskell-doc only works for idents, not arbitrary expr.
530 (string-match "\\`(?\\(\\s_+\\|\\(\\sw\\|\\s'\\)+\\)?[ \t]*::[ \t]*"
531 type))
532 (let ((sym (match-string 1 type)))
533 (setq haskell-doc-user-defined-ids
534 (cons (cons sym (substring type (match-end 0)))
535 (delq (assoc sym haskell-doc-user-defined-ids)
536 haskell-doc-user-defined-ids)))))
537
538 (if (interactive-p) (message "%s" type))
539 (when insert-value
540 (beginning-of-line)
541 (insert type "\n"))
f846b94 @Baughn Patch courtesy of Alex Ott
Baughn authored
542 type))))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
543
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
544 ;;;###autoload
d1dd80c @jwiegley Factored common code, added inferior-haskell-kind
jwiegley authored
545 (defun inferior-haskell-kind (type)
546 "Query the haskell process for the kind of the given expression."
547 (interactive
548 (let ((type (haskell-ident-at-point)))
549 (list (read-string (if (> (length type) 0)
550 (format "Show kind of (default %s): " type)
551 "Show kind of: ")
552 nil nil type))))
553 (let ((result (inferior-haskell-get-result (concat ":kind " type))))
554 (if (interactive-p) (message "%s" result))
555 result))
556
557 ;;;###autoload
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
558 (defun inferior-haskell-info (sym)
559 "Query the haskell process for the info of the given expression."
560 (interactive
561 (let ((sym (haskell-ident-at-point)))
562 (list (read-string (if (> (length sym) 0)
563 (format "Show info of (default %s): " sym)
564 "Show info of: ")
565 nil nil sym))))
d1dd80c @jwiegley Factored common code, added inferior-haskell-kind
jwiegley authored
566 (let ((result (inferior-haskell-get-result (concat ":info " sym))))
567 (if (interactive-p) (message "%s" result))
568 result))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
569
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
570 ;;;###autoload
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
571 (defun inferior-haskell-find-definition (sym)
572 "Attempt to locate and jump to the definition of the given expression."
573 (interactive
574 (let ((sym (haskell-ident-at-point)))
575 (list (read-string (if (> (length sym) 0)
576 (format "Find definition of (default %s): " sym)
577 "Find definition of: ")
578 nil nil sym))))
579 (let ((info (inferior-haskell-info sym)))
580 (if (not (string-match inferior-haskell-info-xref-re info))
581 (error "No source information available")
582 (let ((file (match-string-no-properties 1 info))
583 (line (string-to-number
584 (match-string-no-properties 2 info)))
585 (col (string-to-number
586 (match-string-no-properties 3 info))))
587 (when file
c6cbffc (inferior-haskell-wait-for-prompt): Add timeout arg.
monnier authored
588 (with-current-buffer (process-buffer (inferior-haskell-process))
589 ;; The file name is relative to the process's cwd.
590 (setq file (expand-file-name file)))
36dd8bd (inferior-haskell-info-xref-re): New cst.
monnier authored
591 ;; Push current location marker on the ring used by `find-tag'
592 (require 'etags)
593 (ring-insert find-tag-marker-ring (point-marker))
594 (pop-to-buffer (find-file-noselect file))
595 (when line
596 (goto-line line)
597 (when col (move-to-column col))))))))
598
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
599 ;;; Functions to find the documentation of a given function.
600 ;;
947a32d (inferior-haskell-info-xref-re): Allow a column-range.
monnier authored
601 ;; TODO for this section:
602 ;;
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
603 ;; * Support fetching of local Haddock docs pulled directly from source files.
604 ;; * Display docs locally? w3m?
605
606 (defcustom inferior-haskell-use-web-docs
607 'fallback
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
608 "Whether to use the online documentation. Possible values:
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
609 `never', meaning always use local documentation, unless the local
610 file doesn't exist, when do nothing, `fallback', which means only
611 use the online documentation when the local file doesn't exist,
612 or `always', meaning always use the online documentation,
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
613 regardless of existance of local files. Default is `fallback'."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
614 :group 'haskell
615 :type '(choice (const :tag "Never" never)
616 (const :tag "As fallback" fallback)
617 (const :tag "Always" always)))
618
619 (defcustom inferior-haskell-web-docs-base
620 "http://haskell.org/ghc/docs/latest/html/libraries/"
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
621 "The base URL of the online libraries documentation.
622 This will only be used if the value of `inferior-haskell-use-web-docs'
623 is `always' or `fallback'."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
624 :group 'haskell
625 :type 'string)
626
627 (defcustom haskell-package-manager-name "ghc-pkg"
628 "Name of the program to consult regarding package details."
629 :group 'haskell
630 :type 'string)
631
632 (defcustom haskell-package-conf-file
744f5ce (haskell-package-conf-file): Don't use `ignore-errors'
monnier authored
633 (condition-case nil
634 (with-temp-buffer
635 (call-process "ghc" nil t nil "--print-libdir")
636 (expand-file-name "package.conf"
637 (buffer-substring (point-min) (1- (point-max)))))
638 ;; Don't use `ignore-errors' because this form is not byte-compiled :-(
639 (error nil))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
640 "Where the package configuration file for the package manager resides.
641 By default this is set to `ghc --print-libdir`/package.conf."
642 :group 'haskell
643 :type 'string)
644
645 (defun inferior-haskell-get-module (sym)
646 "Fetch the module in which SYM is defined."
647 (let ((info (inferior-haskell-info sym)))
648 (unless (string-match inferior-haskell-module-re info)
947a32d (inferior-haskell-info-xref-re): Allow a column-range.
monnier authored
649 (error
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
650 "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
651 (let ((module-name (match-string-no-properties 1 info)))
652 ;; Handles GHC 7.4.1+ which quotes module names like
653 ;; `System.Random', whereas previous GHC did not quote at all.
654 (if (string= "`" (substring module-name 0 1))
655 (substring module-name 1 (- (length module-name) 1))
656 module-name))))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
657
658 (defun inferior-haskell-query-ghc-pkg (&rest args)
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
659 "Send ARGS to `haskell-package-manager-name'.
660 Insert the output into the current buffer."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
661 (apply 'call-process haskell-package-manager-name nil t nil args))
662
663 (defun inferior-haskell-get-package-list ()
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
664 "Get the list of packages from `haskell-package-manager-name'."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
665 (with-temp-buffer
666 (inferior-haskell-query-ghc-pkg "--simple-output" "list")
667 (split-string (buffer-substring (point-min) (point-max)))))
668
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
669 (defun inferior-haskell-compute-module-alist ()
670 "Compute a list mapping modules to package names and haddock URLs using ghc-pkg."
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
671 (message "Generating module alist...")
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
672 (let ((module-alist ()))
673 (with-temp-buffer
674 (dolist (package (inferior-haskell-get-package-list))
675 (erase-buffer)
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
676 (inferior-haskell-query-ghc-pkg "describe" package)
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
677
678 (let ((package-w/o-version
679 (replace-regexp-in-string "[-.0-9]*\\'" "" package))
680 ;; Find the Haddock documentation URL for this package
681 (haddock
682 (progn
683 (goto-char (point-min))
bf80267 (inferior-haskell-compute-module-alist): Fix regexps.
monnier authored
684 (when (re-search-forward "haddock-html:[ \t]+\\(.*[^ \t\n]\\)"
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
685 nil t)
686 (match-string 1)))))
687
688 ;; Fetch the list of exposed modules for this package
689 (goto-char (point-min))
bf80267 (inferior-haskell-compute-module-alist): Fix regexps.
monnier authored
690 (when (re-search-forward "^exposed-modules:\\(.*\\(\n[ \t].*\\)*\\)"
691 nil t)
692 (dolist (module (split-string (match-string 1)))
693 (push (list module package-w/o-version haddock)
694 module-alist)))))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
695
696 (message "Generating module alist... done")
697 module-alist)))
698
699
700 (defcustom inferior-haskell-module-alist-file
701 ;; (expand-file-name "~/.inf-haskell-module-alist")
bf80267 (inferior-haskell-compute-module-alist): Fix regexps.
monnier authored
702 (expand-file-name (concat "inf-haskell-module-alist-"
703 (number-to-string (user-uid)))
439a89e (inferior-haskell-cabal-of-buf)
monnier authored
704 (if (fboundp 'temp-directory)
705 (temp-directory)
706 temporary-file-directory))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
707 "Where to save the module -> package lookup table.
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
708 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
709 :group 'haskell
710 :type '(choice (const :tag "Don't cache to file" nil) string))
711
712 (defvar inferior-haskell-module-alist nil
713 "Association list of modules to their packages.
714 Each element is of the form (MODULE PACKAGE HADDOCK), where
715 MODULE is the name of a module,
716 PACKAGE is the package it belongs to, and
717 HADDOCK is the path to that package's Haddock documentation.
718
719 This is calculated on-demand using `inferior-haskell-compute-module-alist'.
720 It's also cached in the file `inferior-haskell-module-alist-file',
721 so that it can be obtained more quickly next time.")
722
723 (defun inferior-haskell-module-alist ()
724 "Get the module alist from cache or ghc-pkg's info."
725 (or
726 ;; If we already have computed the alist, use it...
727 inferior-haskell-module-alist
728 (setq inferior-haskell-module-alist
729 (or
730 ;; ...otherwise try to read it from the cache file...
731 (and
732 inferior-haskell-module-alist-file
733 (file-readable-p inferior-haskell-module-alist-file)
734 (file-newer-than-file-p inferior-haskell-module-alist-file
735 haskell-package-conf-file)
736 (with-temp-buffer
737 (insert-file-contents inferior-haskell-module-alist-file)
738 (goto-char (point-min))
739 (prog1 (read (current-buffer))
740 (message "Read module alist from file cache."))))
741
742 ;; ...or generate it again and save it in a file for later.
743 (let ((alist (inferior-haskell-compute-module-alist)))
744 (when inferior-haskell-module-alist-file
6e300b7 (inferior-haskell-find-project-root): New var, to
monnier authored
745 (with-temp-buffer
746 (print alist (current-buffer))
747 ;; Do the write to a temp file first, then rename it.
748 ;; This makes it more atomic, and suffers from fewer security
749 ;; holes related to race conditions if the file is in /tmp.
750 (let ((tmp (make-temp-file inferior-haskell-module-alist-file)))
751 (write-region (point-min) (point-max) tmp)
752 (rename-file tmp inferior-haskell-module-alist-file
753 'ok-if-already-exists))))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
754 alist)))))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
755
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
756 (defvar inferior-haskell-ghc-internal-ident-alist
757 ;; FIXME: Fill this table, ideally semi-automatically.
758 '(("GHC.Base.return" . "Control.Monad.return")
759 ("GHC.List" . "Data.List")))
760
761 (defun inferior-haskell-map-internal-ghc-ident (ident)
762 "Try to translate some internal GHC identifier to its alter ego in haskell docs."
763 (let ((head ident)
764 (tail "")
765 remapped)
766 (while (and (not
767 (setq remapped
768 (cdr (assoc head
769 inferior-haskell-ghc-internal-ident-alist))))
770 (string-match "\\.[^.]+\\'" head))
771 (setq tail (concat (match-string 0 head) tail))
772 (setq head (substring head 0 (match-beginning 0))))
773 (concat (or remapped head) tail)))
774
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
775 ;;;###autoload
776 (defun inferior-haskell-find-haddock (sym)
777 "Find and open the Haddock documentation of SYM.
778 Make sure to load the file into GHCi or Hugs first by using C-c C-l.
779 Only works for functions in a package installed with ghc-pkg, or
780 whatever the value of `haskell-package-manager-name' is.
781
782 This function needs to find which package a given module belongs
783 to. In order to do this, it computes a module-to-package lookup
784 alist, which is expensive to compute (it takes upwards of five
785 seconds with more than about thirty installed packages). As a
786 result, we cache it across sessions using the cache file
787 referenced by `inferior-haskell-module-alist-file'. We test to
788 see if this is newer than `haskell-package-conf-file' every time
789 we load it."
790 (interactive
791 (let ((sym (haskell-ident-at-point)))
792 (list (read-string (if (> (length sym) 0)
793 (format "Find documentation of (default %s): " sym)
794 "Find documentation of: ")
795 nil nil sym))))
3afdf6b (inferior-haskell-run-command): New var.
monnier authored
796 (setq sym (inferior-haskell-map-internal-ghc-ident sym))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
797 (let* (;; Find the module and look it up in the alist
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
798 (module (inferior-haskell-get-module sym))
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
799 (alist-record (assoc module (inferior-haskell-module-alist)))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
800 (package (nth 1 alist-record))
801 (file-name (concat (subst-char-in-string ?. ?- module) ".html"))
802 (local-path (concat (nth 2 alist-record) "/" file-name))
803 (url (if (or (eq inferior-haskell-use-web-docs 'always)
804 (and (not (file-exists-p local-path))
805 (eq inferior-haskell-use-web-docs 'fallback)))
f2fd5e5 (inferior-haskell-find-haddock): Jump to the symbol anchor within Had…
monnier authored
806 (concat inferior-haskell-web-docs-base package "/" file-name
807 ;; Jump to the symbol anchor within Haddock.
808 "#v:" sym)
b74e553 (inferior-haskell-module-alist-file): Use a file in /tmp rather than ~/.
monnier authored
809 (and (file-exists-p local-path)
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
810 (concat "file://" local-path)))))
2b067d9 @loveshack Comment/doc/message fixes.
loveshack authored
811 (if url (browse-url url) (error "Local file doesn't exist"))))
c5f1425 (inferior-haskell-module-alist-file)
monnier authored
812
4418871 New file.
monnier authored
813 (provide 'inf-haskell)
bfd15e1 (inferior-haskell-mode): Hide compilation-mode bindings.
monnier authored
814
815 ;; arch-tag: 61804287-63dd-4052-bc0e-90f691b34b40
4418871 New file.
monnier authored
816 ;;; inf-haskell.el ends here
Something went wrong with that request. Please try again.