1 ;; geiser-racket.el -- geiser support for Racket scheme
3 ;; Copyright (C) 2009, 2010 Jose Antonio Ortega Ruiz
5 ;; This program is free software; you can redistribute it and/or
6 ;; modify it under the terms of the Modified BSD License. You should
7 ;; have received a copy of the license along with this program. If
8 ;; not, see <http://www.xfree86.org/3.3.6/COPYRIGHT2.html#5>.
10 ;; Start date: Sat Apr 25, 2009 21:13
14 (require 'geiser-edit
)
16 (require 'geiser-eval
)
17 (require 'geiser-syntax
)
18 (require 'geiser-custom
)
19 (require 'geiser-base
)
24 (defgroup geiser-racket nil
25 "Customization for Geiser's Racket flavour."
28 (geiser-custom--defcustom geiser-racket-binary
29 (cond ((eq system-type
'windows-nt
) "Racket.exe")
30 ((eq system-type
'darwin
) "racket")
32 "Name to use to call the mzscheme executable when starting a REPL."
33 :type
'(choice string
(repeat string
))
34 :group
'geiser-racket
)
36 (geiser-custom--defcustom geiser-racket-collects nil
37 "A list of paths to be added to mzscheme's collection directories."
39 :group
'geiser-racket
)
41 (geiser-custom--defcustom geiser-racket-init-file
"~/.racket-geiser"
42 "Initialization file with user code for the mzscheme REPL."
44 :group
'geiser-racket
)
50 (defun geiser-racket--binary ()
51 (if (listp geiser-racket-binary
)
52 (car geiser-racket-binary
)
53 geiser-racket-binary
))
55 (defun geiser-racket--parameters ()
56 "Return a list with all parameters needed to start mzscheme.
57 This function uses `geiser-racket-init-file' if it exists."
58 (let ((init-file (and (stringp geiser-racket-init-file
)
59 (expand-file-name geiser-racket-init-file
))))
61 "-S" ,(expand-file-name "racket/" geiser-scheme-dir
)
62 ,@(apply 'append
(mapcar (lambda (p) (list "-S" p
)) geiser-racket-collects
))
63 ,@(and (listp geiser-racket-binary
) (cdr geiser-racket-binary
))
64 ,@(and init-file
(file-readable-p init-file
) (list "-f" init-file
))
65 "-f" ,(expand-file-name "racket/geiser.rkt" geiser-scheme-dir
))))
67 (defconst geiser-racket--prompt-regexp
"^=?\\(mzscheme\\|racket\\)@[^ ]*?> ")
70 ;;; Evaluation support:
72 (defun geiser-racket--language ()
74 (goto-char (point-min))
75 (if (re-search-forward
76 "^\\(?:#lang\\|(module +[^ ]+?\\) +\\([^ ]+?\\|([^)]+)\\) *$" nil t
)
77 (car (geiser-syntax--read-from-string (match-string-no-properties 1)))
80 (defun geiser-racket--geiser-procedure (proc)
81 (if (memq proc
'(eval compile
))
82 `((dynamic-require 'geiser
'geiser
:eval
) ',(geiser-racket--language))
83 `(dynamic-require 'geiser
',(intern (format "geiser:%s" proc
)))))
85 (defconst geiser-racket--module-re
86 "^(module +\\([^ ]+\\)")
88 (defun geiser-racket--explicit-module ()
90 (goto-char (point-min))
91 (and (re-search-forward geiser-racket--module-re nil t
)
93 (car (geiser-syntax--read-from-string
94 (match-string-no-properties 1)))))))
96 (defsubst geiser-racket--implicit-module
()
98 (goto-char (point-min))
99 (if (re-search-forward "^#lang " nil t
)
103 (defun geiser-racket--get-module (&optional module
)
104 (cond ((and (null module
) (buffer-file-name)))
105 ;; (geiser-racket--explicit-module)
106 ((null module
) (geiser-racket--implicit-module))
107 ((symbolp module
) module
)
108 ((and (stringp module
) (file-name-absolute-p module
)) module
)
109 ((stringp module
) (intern module
))
112 (defun geiser-racket--symbol-begin (module)
113 (save-excursion (skip-syntax-backward "^-()>") (point)))
115 (defun geiser-racket--enter-command (module)
116 (when (stringp module
)
117 (cond ((zerop (length module
)) "(enter! #f)")
118 ((file-name-absolute-p module
) (format "(enter! (file %S))" module
))
119 (t (format "(enter! %s)" module
)))))
121 (defun geiser-racket--import-command (module)
122 (and (stringp module
)
123 (not (zerop (length module
)))
124 (format "(require %s)" module
)))
126 (defconst geiser-racket--binding-forms
127 '(for for
/list for
/hash for
/hasheq for
/and for
/or
128 for
/lists for
/first for
/last for
/fold
))
130 (defconst geiser-racket--binding-forms
*
131 '(for* for
*/list for
*/lists for
*/hash for
*/hasheq for
*/and
132 for
*/or for
*/first for
*/last for
*/fold
))
136 (defsubst geiser-racket--get-help
(symbol module
)
137 (geiser-eval--send/wait
138 `(:eval
(get-help ',symbol
(:module
,module
)) geiser
/autodoc
)))
140 (defun geiser-racket--external-help (id module
)
141 (message "Requesting help for '%s'..." id
)
142 (let ((out (geiser-eval--retort-output
143 (geiser-racket--get-help id module
))))
144 (when (and out
(string-match " but provided by:\n +\\(.+\\)\n" out
))
145 (geiser-racket--get-help id
(match-string 1 out
))))
146 (minibuffer-message "%s done" (current-message))
152 (defconst geiser-racket--file-rxs
153 '("^\\([^:\n\"]+\\):\\([0-9]+\\):\\([0-9]+\\)"
154 "path:\"?\\([^>\"\n]+\\)\"?>"
155 "module: \"\\([^>\"\n]+\\)\""))
157 (defun geiser-racket--find-files (rx)
159 (while (re-search-forward rx nil t
)
160 (geiser-edit--make-link (match-beginning 1)
167 (defun geiser-racket--display-error (module key msg
)
170 (geiser-doc--insert-button key nil
'racket
)
178 (mapc 'geiser-racket--find-files geiser-racket--file-rxs
)
184 ;;; Trying to ascertain whether a buffer is mzscheme scheme:
186 (defun geiser-racket--guess ()
188 (goto-char (point-min))
189 (re-search-forward "#lang " nil t
))
190 (geiser-racket--explicit-module)))
193 ;;; Implementation definition:
195 (define-geiser-implementation racket
196 (unsupported-procedures '(callers callees generic-methods
))
197 (binary geiser-racket--binary
)
198 (arglist geiser-racket--parameters
)
200 (prompt-regexp geiser-racket--prompt-regexp
)
201 (marshall-procedure geiser-racket--geiser-procedure
)
202 (find-module geiser-racket--get-module
)
203 (enter-command geiser-racket--enter-command
)
204 (import-command geiser-racket--import-command
)
205 (find-symbol-begin geiser-racket--symbol-begin
)
206 (display-error geiser-racket--display-error
)
207 (display-help geiser-racket--external-help
)
208 (check-buffer geiser-racket--guess
)
209 (binding-forms geiser-racket--binding-forms
)
210 (binding-forms* geiser-racket--binding-forms
*))
212 (geiser-impl--add-to-alist 'regexp
213 "\\.\\(mzscheme\\|racket\\)\\.sl?s$" 'racket t
)
214 (geiser-impl--add-to-alist 'regexp
"\\.ss$" 'racket t
)
215 (geiser-impl--add-to-alist 'regexp
"\\.rkt$" 'racket t
)
218 (provide 'geiser-racket
)
219 ;;; geiser-racket.el ends here