Scheme version checks
[geiser.git] / elisp / geiser-mode.el
blobb5c10fdc8a66d493c97c25d4669603083d2e8821
1 ;; geiser-mode.el -- minor mode for scheme buffers
3 ;; Copyright (C) 2009, 2010, 2011, 2012, 2013 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: Sun Feb 08, 2009 15:13
14 (require 'geiser-repl)
15 (require 'geiser-menu)
16 (require 'geiser-doc)
17 (require 'geiser-compile)
18 (require 'geiser-completion)
19 (require 'geiser-company)
20 (require 'geiser-xref)
21 (require 'geiser-edit)
22 (require 'geiser-autodoc)
23 (require 'geiser-debug)
24 (require 'geiser-syntax)
25 (require 'geiser-impl)
26 (require 'geiser-eval)
27 (require 'geiser-popup)
28 (require 'geiser-custom)
29 (require 'geiser-base)
32 ;;; Customization:
34 (defgroup geiser-mode nil
35 "Mode enabling Geiser abilities in Scheme buffers &co.."
36 :group 'geiser)
38 (geiser-custom--defcustom geiser-mode-auto-p t
39 "Whether `geiser-mode' should be active by default in all
40 scheme buffers."
41 :group 'geiser-mode
42 :type 'boolean)
44 (geiser-custom--defcustom geiser-mode-start-repl-p nil
45 "Whether a REPL should be automatically started if one is not
46 active when `geiser-mode' is activated in a buffer."
47 :group 'geiser-mode
48 :type 'boolean)
50 (geiser-custom--defcustom geiser-mode-autodoc-p t
51 "Whether `geiser-autodoc-mode' gets enabled by default in Scheme buffers."
52 :group 'geiser-mode
53 :group 'geiser-autodoc
54 :type 'boolean)
56 (geiser-custom--defcustom geiser-mode-company-p t
57 "Whether to use company-mode for completion, if available."
58 :group 'geiser-mode
59 :type 'boolean)
61 (geiser-custom--defcustom geiser-mode-smart-tab-p nil
62 "Whether `geiser-smart-tab-mode' gets enabled by default in Scheme buffers."
63 :group 'geiser-mode
64 :type 'boolean)
68 ;;; Evaluation commands:
70 (defun geiser--go-to-repl ()
71 (switch-to-geiser nil nil (current-buffer))
72 (push-mark)
73 (goto-char (point-max)))
75 (defun geiser-eval-region (start end &optional and-go raw nomsg)
76 "Eval the current region in the Geiser REPL.
78 With prefix, goes to the REPL buffer afterwards (as
79 `geiser-eval-region-and-go')"
80 (interactive "rP")
81 (save-restriction
82 (narrow-to-region start end)
83 (check-parens))
84 (geiser-debug--send-region nil
85 start
86 end
87 (and and-go 'geiser--go-to-repl)
88 (not raw)
89 nomsg))
91 (defun geiser-eval-region-and-go (start end)
92 "Eval the current region in the Geiser REPL and visit it afterwads."
93 (interactive "r")
94 (geiser-eval-region start end t))
96 (defun geiser-eval-buffer (&optional and-go raw nomsg)
97 "Eval the current buffer in the Geiser REPL.
99 With prefix, goes to the REPL buffer afterwards (as
100 `geiser-eval-buffer-and-go')"
101 (interactive "P")
102 (let ((start (point-min))
103 (end (point-max)))
104 (save-restriction
105 (narrow-to-region start end)
106 (check-parens))
107 (geiser-debug--send-region nil
108 start
110 (and and-go 'geiser--go-to-repl)
111 (not raw)
112 nomsg)))
114 (defun geiser-eval-buffer-and-go ()
115 "Eval the current buffer in the Geiser REPL and visit it afterwads."
116 (interactive)
117 (geiser-eval-buffer t))
119 (defun geiser-eval-definition (&optional and-go)
120 "Eval the current definition in the Geiser REPL.
122 With prefix, goes to the REPL buffer afterwards (as
123 `geiser-eval-definition-and-go')"
124 (interactive "P")
125 (save-excursion
126 (end-of-defun)
127 (let ((end (point)))
128 (beginning-of-defun)
129 (geiser-eval-region (point) end and-go t))))
131 (defun geiser-eval-definition-and-go ()
132 "Eval the current definition in the Geiser REPL and visit it afterwads."
133 (interactive)
134 (geiser-eval-definition t))
136 (defun geiser-eval-last-sexp (print-to-buffer-p)
137 "Eval the previous sexp in the Geiser REPL.
139 With a prefix, print the result of the evaluation to the buffer."
140 (interactive "P")
141 (let* ((ret (geiser-eval-region (save-excursion (backward-sexp) (point))
142 (point)
145 print-to-buffer-p))
146 (str (geiser-eval--retort-result-str ret (when print-to-buffer-p ""))))
147 (when (and print-to-buffer-p (not (string= "" str)))
148 (push-mark)
149 (insert str))))
151 (defun geiser-compile-definition (&optional and-go)
152 "Compile the current definition in the Geiser REPL.
154 With prefix, goes to the REPL buffer afterwards (as
155 `geiser-eval-definition-and-go')"
156 (interactive "P")
157 (save-excursion
158 (end-of-defun)
159 (let ((end (point)))
160 (beginning-of-defun)
161 (geiser-debug--send-region t
162 (point)
164 (and and-go 'geiser--go-to-repl)
165 t))))
167 (defun geiser-compile-definition-and-go ()
168 "Compile the current definition in the Geiser REPL and visit it afterwads."
169 (interactive)
170 (geiser-compile-definition t))
172 (defun geiser-expand-region (start end &optional all raw)
173 "Macro-expand the current region and display it in a buffer.
174 With prefix, recursively macro-expand the resulting expression."
175 (interactive "rP")
176 (geiser-debug--expand-region start end all (not raw)))
178 (defun geiser-expand-definition (&optional all)
179 "Macro-expand the current definition.
181 With prefix, recursively macro-expand the resulting expression."
182 (interactive "P")
183 (save-excursion
184 (end-of-defun)
185 (let ((end (point)))
186 (beginning-of-defun)
187 (geiser-expand-region (point) end all t))))
189 (defun geiser-expand-last-sexp (&optional all)
190 "Macro-expand the previous sexp.
192 With prefix, recursively macro-expand the resulting expression."
193 (interactive "P")
194 (geiser-expand-region (save-excursion (backward-sexp) (point))
195 (point)
199 (defun geiser-set-scheme ()
200 "Associates current buffer with a given Scheme implementation."
201 (interactive)
202 (let ((impl (geiser-impl--read-impl)))
203 (geiser-impl--set-buffer-implementation impl)
204 (geiser-repl--set-up-repl impl)))
206 (defun geiser-mode-switch-to-repl (arg)
207 "Switches to Geiser REPL.
209 With prefix, try to enter the current buffer's module."
210 (interactive "P")
211 (if arg
212 (switch-to-geiser-module (geiser-eval--get-module) (current-buffer))
213 (switch-to-geiser nil nil (current-buffer))))
215 (defun geiser-mode-switch-to-repl-and-enter ()
216 "Switches to Geiser REPL and enters current buffer's module."
217 (interactive)
218 (geiser-mode-switch-to-repl t))
220 (defun geiser-restart-repl ()
221 "Restarts the REPL associated with the current buffer."
222 (interactive)
223 (let ((b (current-buffer)))
224 (geiser-mode-switch-to-repl nil)
225 (comint-kill-subjob)
226 (sit-for 0.1) ;; ugly hack; but i don't care enough to fix it
227 (call-interactively 'run-geiser)
228 (sit-for 0.2) ;; ditto
229 (goto-char (point-max))
230 (pop-to-buffer b)))
232 (defun geiser-squarify (n)
233 "Toggle between () and [] for current form.
235 With numeric prefix, perform that many toggles, forward for
236 positive values and backward for negative."
237 (interactive "p")
238 (let ((pared (and (boundp 'paredit-mode) paredit-mode))
239 (fwd (> n 0))
240 (steps (abs n)))
241 (when (and pared (fboundp 'paredit-mode)) (paredit-mode -1))
242 (unwind-protect
243 (save-excursion
244 (unless (looking-at-p "\\s(") (backward-up-list))
245 (while (> steps 0)
246 (let ((p (point))
247 (round (looking-at-p "(")))
248 (forward-sexp)
249 (backward-delete-char 1)
250 (insert (if round "]" ")"))
251 (goto-char p)
252 (delete-char 1)
253 (insert (if round "[" "("))
254 (setq steps (1- steps))
255 (backward-char)
256 (condition-case nil
257 (progn (when fwd (forward-sexp 2))
258 (backward-sexp))
259 (error (setq steps 0))))))
260 (when (and pared (fboundp 'paredit-mode)) (paredit-mode 1)))))
262 (defun geiser-insert-lambda (&optional full)
263 "Insert λ at point. With prefix, inserts (λ ())."
264 (interactive "P")
265 (if (not full)
266 (insert (make-char 'greek-iso8859-7 107))
267 (insert "(" (make-char 'greek-iso8859-7 107) " ())")
268 (backward-char 2)))
271 ;;; Geiser mode:
273 (make-variable-buffer-local
274 (defvar geiser-mode-string nil
275 "Modeline indicator for geiser-mode"))
277 (defun geiser-mode--lighter ()
278 (or geiser-mode-string
279 (format " %s" (or (geiser-impl--impl-str) "G"))))
281 (defvar geiser-mode-map (make-sparse-keymap))
283 (define-minor-mode geiser-mode
284 "Toggle Geiser's mode.
286 With no argument, this command toggles the mode.
287 Non-null prefix argument turns on the mode.
288 Null prefix argument turns off the mode.
290 When Geiser mode is enabled, a host of nice utilities for
291 interacting with the Geiser REPL is at your disposal.
292 \\{geiser-mode-map}"
293 :init-value nil
294 :lighter (:eval (geiser-mode--lighter))
295 :group 'geiser-mode
296 :keymap geiser-mode-map
297 (when geiser-mode (geiser-impl--set-buffer-implementation nil t))
298 (setq geiser-autodoc-mode-string "/A")
299 (setq geiser-smart-tab-mode-string "/T")
300 (geiser-company--setup (and geiser-mode geiser-mode-company-p))
301 (geiser-completion--setup geiser-mode)
302 (when geiser-mode-autodoc-p
303 (geiser-autodoc-mode (if geiser-mode 1 -1)))
304 (when geiser-mode-smart-tab-p
305 (geiser-smart-tab-mode (if geiser-mode 1 -1)))
306 (geiser-syntax--add-kws)
307 (when (and geiser-mode
308 geiser-mode-start-repl-p
309 (not (geiser-repl--connection*)))
310 (save-window-excursion (run-geiser geiser-impl--implementation))))
312 (defun turn-on-geiser-mode ()
313 "Enable `geiser-mode' (in a Scheme buffer)."
314 (interactive)
315 (geiser-mode 1))
317 (defun turn-off-geiser-mode ()
318 "Disable `geiser-mode' (in a Scheme buffer)."
319 (interactive)
320 (geiser-mode -1))
322 (defun geiser-mode--maybe-activate ()
323 (when geiser-mode-auto-p (turn-on-geiser-mode)))
326 ;;; Keys:
328 (geiser-menu--defmenu geiserm geiser-mode-map
329 ("Eval sexp before point" "\C-x\C-e" geiser-eval-last-sexp)
330 ("Eval definition" "\M-\C-x" geiser-eval-definition)
331 ("Eval definition and go" "\C-c\M-e" geiser-eval-definition-and-go)
332 ("Eval region" "\C-c\C-r" geiser-eval-region :enable mark-active)
333 ("Eval region and go" "\C-c\M-r" geiser-eval-region-and-go
334 geiser-eval-region :enable mark-active)
335 ("Eval buffer" "\C-c\C-b" geiser-eval-buffer)
336 ("Eval buffer and go" "\C-c\M-b" geiser-eval-buffer-and-go)
337 ;; ("Compile definition" "\C-c\M-c" geiser-compile-definition)
338 ;; ("Compile definition and go" "\C-c\C-c" geiser-compile-definition-and-go)
339 (menu "Macroexpand"
340 ("Sexp before point" ("\C-c\C-m\C-e" "\C-c\C-me")
341 geiser-expand-last-sexp)
342 ("Region" ("\C-c\C-m\C-r" "\C-c\C-mr") geiser-expand-region)
343 ("Definition" ("\C-c\C-m\C-x" "\C-c\C-mx") geiser-expand-definition))
345 ("Symbol documentation" ("\C-c\C-d\C-d" "\C-c\C-dd")
346 geiser-doc-symbol-at-point :enable (geiser--symbol-at-point))
347 ("Short symbol documentation" ("\C-c\C-d\C-s" "\C-c\C-ds")
348 geiser-autodoc-show :enable (geiser--symbol-at-point))
349 ("Module documentation" ("\C-c\C-d\C-m" "\C-c\C-dm") geiser-doc-module)
350 ("Symbol manual lookup" ("\C-c\C-d\C-i" "\C-c\C-di")
351 geiser-doc-look-up-manual :enable (geiser-doc--manual-available-p))
352 (mode "Autodoc mode" ("\C-c\C-d\C-a" "\C-c\C-da") geiser-autodoc-mode)
354 ("Compile buffer" "\C-c\C-k" geiser-compile-current-buffer)
355 ("Switch to REPL" "\C-c\C-z" geiser-mode-switch-to-repl)
356 ("Switch to REPL and enter module" "\C-c\C-a"
357 geiser-mode-switch-to-repl-and-enter)
358 ("Set Scheme..." "\C-c\C-s" geiser-set-scheme)
360 ("Edit symbol at point" "\M-." geiser-edit-symbol-at-point
361 :enable (geiser--symbol-at-point))
362 ("Go to previous definition" "\M-," geiser-pop-symbol-stack)
363 ("Complete symbol" ((kbd "M-TAB")) completion-at-point
364 :enable (geiser--symbol-at-point))
365 ("Complete module name" ((kbd "M-`") (kbd "C-."))
366 geiser-completion--complete-module)
367 ("Edit module" ("\C-c\C-e\C-m" "\C-c\C-em") geiser-edit-module)
368 ("Add to load path..." ("\C-c\C-e\C-l" "\C-c\C-el") geiser-add-to-load-path)
369 ("Toggle ()/[]" ("\C-c\C-e\C-[" "\C-c\C-e[") geiser-squarify)
370 ("Insert λ" ("\C-c\\" "\C-c\C-\\") geiser-insert-lambda)
372 ("Callers" ((kbd "C-c <")) geiser-xref-callers
373 :enable (and (geiser-eval--supported-p 'callers)
374 (geiser--symbol-at-point)))
375 ("Callees" ((kbd "C-c >")) geiser-xref-callees
376 :enable (and (geiser-eval--supported-p 'callees)
377 (geiser--symbol-at-point)))
379 (mode "Smart TAB mode" nil geiser-smart-tab-mode)
381 (custom "Customize Geiser mode" geiser-mode))
383 (define-key geiser-mode-map [menu-bar scheme] 'undefined)
385 ;; (geiser-mode--triple-chord ?x ?m 'geiser-xref-generic-methods)
388 ;;; Reload support:
390 (defun geiser-mode--buffers ()
391 (let ((buffers))
392 (dolist (buffer (buffer-list))
393 (when (buffer-live-p buffer)
394 (set-buffer buffer)
395 (when geiser-mode
396 (push (cons buffer geiser-impl--implementation) buffers))))
397 buffers))
399 (defun geiser-mode--restore (buffers)
400 (dolist (b buffers)
401 (when (buffer-live-p (car b))
402 (set-buffer (car b))
403 (when (cdr b)
404 (geiser-impl--set-buffer-implementation (cdr b)))
405 (geiser-mode 1))))
407 (defun geiser-mode-unload-function ()
408 (dolist (b (geiser-mode--buffers))
409 (with-current-buffer (car b) (geiser-mode nil))))
412 (provide 'geiser-mode)