Better EOT token for more robust communication
[geiser.git] / elisp / geiser-mode.el
blob719176d8ac9cd5aa3a68d08f9b9626e980856158
1 ;; geiser-mode.el -- minor mode for scheme buffers
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: 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-impl)
25 (require 'geiser-eval)
26 (require 'geiser-popup)
27 (require 'geiser-custom)
28 (require 'geiser-base)
31 ;;; Customization:
33 (defgroup geiser-mode nil
34 "Mode enabling Geiser abilities in Scheme buffers &co.."
35 :group 'geiser)
37 (geiser-custom--defcustom geiser-mode-autodoc-p t
38 "Whether `geiser-autodoc-mode' gets enabled by default in Scheme buffers."
39 :group 'geiser-mode
40 :group 'geiser-autodoc
41 :type 'boolean)
43 (geiser-custom--defcustom geiser-mode-company-p t
44 "Whether to use company-mode for completion, if available."
45 :group 'geiser-mode
46 :type 'boolean)
48 (geiser-custom--defcustom geiser-mode-smart-tab-p nil
49 "Whether `geiser-smart-tab-mode' gets enabled by default in Scheme buffers."
50 :group 'geiser-mode
51 :type 'boolean)
55 ;;; Evaluation commands:
57 (defun geiser--go-to-repl ()
58 (switch-to-geiser nil nil (current-buffer))
59 (push-mark)
60 (goto-char (point-max)))
62 (defun geiser-eval-region (start end &optional and-go raw)
63 "Eval the current region in the Geiser REPL.
64 With prefix, goes to the REPL buffer afterwards (as
65 `geiser-eval-region-and-go')"
66 (interactive "rP")
67 (geiser-debug--send-region nil
68 start
69 end
70 (and and-go 'geiser--go-to-repl)
71 (not raw)))
73 (defun geiser-eval-region-and-go (start end)
74 "Eval the current region in the Geiser REPL and visit it afterwads."
75 (interactive "r")
76 (geiser-eval-region start end t))
78 (defun geiser-eval-definition (&optional and-go)
79 "Eval the current definition in the Geiser REPL.
80 With prefix, goes to the REPL buffer afterwards (as
81 `geiser-eval-definition-and-go')"
82 (interactive "P")
83 (save-excursion
84 (end-of-defun)
85 (let ((end (point)))
86 (beginning-of-defun)
87 (geiser-eval-region (point) end and-go t))))
89 (defun geiser-eval-definition-and-go ()
90 "Eval the current definition in the Geiser REPL and visit it afterwads."
91 (interactive)
92 (geiser-eval-definition t))
94 (defun geiser-eval-last-sexp ()
95 "Eval the previous sexp in the Geiser REPL."
96 (interactive)
97 (geiser-eval-region (save-excursion (backward-sexp) (point))
98 (point)
99 nil
102 (defun geiser-compile-definition (&optional and-go)
103 "Compile the current definition in the Geiser REPL.
104 With prefix, goes to the REPL buffer afterwards (as
105 `geiser-eval-definition-and-go')"
106 (interactive "P")
107 (save-excursion
108 (end-of-defun)
109 (let ((end (point)))
110 (beginning-of-defun)
111 (geiser-debug--send-region t
112 (point)
114 (and and-go 'geiser--go-to-repl)
115 t))))
117 (defun geiser-compile-definition-and-go ()
118 "Compile the current definition in the Geiser REPL and visit it afterwads."
119 (interactive)
120 (geiser-compile-definition t))
122 (defun geiser-expand-region (start end &optional all raw)
123 "Macro-expand the current region and display it in a buffer.
124 With prefix, recursively macro-expand the resulting expression."
125 (interactive "rP")
126 (geiser-debug--expand-region start end all (not raw)))
128 (defun geiser-expand-definition (&optional all)
129 "Macro-expand the current definition.
130 With prefix, recursively macro-expand the resulting expression."
131 (interactive "P")
132 (save-excursion
133 (end-of-defun)
134 (let ((end (point)))
135 (beginning-of-defun)
136 (geiser-expand-region (point) end all t))))
138 (defun geiser-expand-last-sexp (&optional all)
139 "Macro-expand the previous sexp.
140 With prefix, recursively macro-expand the resulting expression."
141 (interactive "P")
142 (geiser-expand-region (save-excursion (backward-sexp) (point))
143 (point)
147 (defun geiser-set-scheme ()
148 "Associates current buffer with a given Scheme implementation."
149 (interactive)
150 (let ((impl (geiser-impl--read-impl)))
151 (geiser-impl--set-buffer-implementation impl)
152 (geiser-repl--set-up-repl impl)))
154 (defun geiser-mode-switch-to-repl (arg)
155 "Switches to Geiser REPL.
156 With prefix, try to enter the current's buffer module."
157 (interactive "P")
158 (if arg
159 (switch-to-geiser-module (geiser-eval--get-module) (current-buffer))
160 (switch-to-geiser nil nil (current-buffer))))
162 (defun geiser-mode-switch-to-repl-and-enter ()
163 "Switches to Geiser REPL and enters current's buffer module."
164 (interactive)
165 (geiser-mode-switch-to-repl t))
167 (defun geiser-restart-repl ()
168 "Restarts the REPL associated with the current buffer."
169 (interactive)
170 (let ((b (current-buffer)))
171 (geiser-mode-switch-to-repl nil)
172 (comint-kill-subjob)
173 (sit-for 0.1) ;; ugly hack; but i don't care enough to fix it
174 (call-interactively 'run-geiser)
175 (sit-for 0.2) ;; ditto
176 (goto-char (point-max))
177 (pop-to-buffer b)))
179 (defun geiser-squarify (n)
180 "Toggle between () and [] for current form.
181 With numeric prefix, perform that many toggles, forward for
182 positive values and backward for negative."
183 (interactive "p")
184 (let ((pared (and (boundp 'paredit-mode) paredit-mode))
185 (fwd (> n 0))
186 (steps (abs n)))
187 (when (and pared (fboundp 'paredit-mode)) (paredit-mode -1))
188 (unwind-protect
189 (save-excursion
190 (unless (looking-at-p "\\s(") (backward-up-list))
191 (while (> steps 0)
192 (let ((p (point))
193 (round (looking-at-p "(")))
194 (forward-sexp)
195 (backward-delete-char 1)
196 (insert (if round "]" ")"))
197 (goto-char p)
198 (delete-char 1)
199 (insert (if round "[" "("))
200 (setq steps (1- steps))
201 (backward-char)
202 (condition-case nil
203 (progn (when fwd (forward-sexp 2))
204 (backward-sexp))
205 (error (setq steps 0))))))
206 (when (and pared (fboundp 'paredit-mode)) (paredit-mode 1)))))
209 ;;; Geiser mode:
211 (make-variable-buffer-local
212 (defvar geiser-mode-string nil
213 "Modeline indicator for geiser-mode"))
215 (defun geiser-mode--lighter ()
216 (or geiser-mode-string
217 (format " %s" (or (geiser-impl--impl-str) "G"))))
219 (defvar geiser-mode-map (make-sparse-keymap))
221 (define-minor-mode geiser-mode
222 "Toggle Geiser's mode.
223 With no argument, this command toggles the mode.
224 Non-null prefix argument turns on the mode.
225 Null prefix argument turns off the mode.
227 When Geiser mode is enabled, a host of nice utilities for
228 interacting with the Geiser REPL is at your disposal.
229 \\{geiser-mode-map}"
230 :init-value nil
231 :lighter (:eval (geiser-mode--lighter))
232 :group 'geiser-mode
233 :keymap geiser-mode-map
234 (when geiser-mode (geiser-impl--set-buffer-implementation nil t))
235 (setq geiser-autodoc-mode-string "/A")
236 (setq geiser-smart-tab-mode-string "/T")
237 (geiser-company--setup (and geiser-mode geiser-mode-company-p))
238 (when geiser-mode-autodoc-p
239 (geiser-autodoc-mode (if geiser-mode 1 -1)))
240 (when geiser-mode-smart-tab-p
241 (geiser-smart-tab-mode (if geiser-mode 1 -1))))
243 (defun turn-on-geiser-mode ()
244 "Enable `geiser-mode' (in a Scheme buffer)."
245 (interactive)
246 (geiser-mode 1))
248 (defun turn-off-geiser-mode ()
249 "Disable `geiser-mode' (in a Scheme buffer)."
250 (interactive)
251 (geiser-mode -1))
254 ;;; Keys:
256 (geiser-menu--defmenu geiserm geiser-mode-map
257 ("Eval sexp before point" "\C-x\C-e" geiser-eval-last-sexp)
258 ("Eval definition" "\M-\C-x" geiser-eval-definition)
259 ("Eval definition and go" "\C-c\M-e" geiser-eval-definition-and-go)
260 ("Eval region" "\C-c\C-r" geiser-eval-region :enable mark-active)
261 ("Eval region and go" "\C-c\M-r" geiser-eval-region-and-go
262 geiser-eval-region :enable mark-active)
263 ;; ("Compile definition" "\C-c\M-c" geiser-compile-definition)
264 ;; ("Compile definition and go" "\C-c\C-c" geiser-compile-definition-and-go)
265 (menu "Macroexpand"
266 ("Sexp before point" ("\C-c\C-m\C-e" "\C-c\C-me")
267 geiser-expand-last-sexp)
268 ("Region" ("\C-c\C-m\C-r" "\C-c\C-mr") geiser-expand-region)
269 ("Definition" ("\C-c\C-m\C-x" "\C-c\C-mx") geiser-expand-definition))
271 ("Symbol documentation" ("\C-c\C-d\C-d" "\C-c\C-dd")
272 geiser-doc-symbol-at-point :enable (symbol-at-point))
273 ("Module documentation" ("\C-c\C-d\C-m" "\C-c\C-dm") geiser-doc-module)
274 (mode "Autodoc mode" ("\C-c\C-d\C-a" "\C-c\C-da") geiser-autodoc-mode)
276 ("Compile buffer" "\C-c\C-k" geiser-compile-current-buffer)
277 ("Switch to REPL" "\C-c\C-z" geiser-mode-switch-to-repl)
278 ("Switch to REPL and enter module" "\C-c\C-Z"
279 geiser-mode-switch-to-repl-and-enter)
280 ("Set Scheme..." "\C-c\C-s" geiser-set-scheme)
282 ("Edit symbol at point" "\M-." geiser-edit-symbol-at-point
283 :enable (symbol-at-point))
284 ("Go to previous definition" "\M-," geiser-pop-symbol-stack)
285 ("Complete symbol" ((kbd "M-TAB")) geiser-completion--complete-symbol
286 :enable (symbol-at-point))
287 ("Complete module name" ((kbd "M-`") (kbd "C-."))
288 geiser-completion--complete-module)
289 ("Edit module" ("\C-c\C-e\C-m" "\C-c\C-em") geiser-edit-module)
290 ("Toggle ()/[]" ("\C-c\C-e\C-[" "\C-c\C-e[") geiser-squarify)
292 ("Callers" ((kbd "C-c <")) geiser-xref-callers
293 :enable (and (geiser-eval--supported-p 'callers) (symbol-at-point)))
294 ("Callees" ((kbd "C-c >")) geiser-xref-callees
295 :enable (and (geiser-eval--supported-p 'callees) (symbol-at-point)))
297 (mode "Smart TAB mode" nil geiser-smart-tab-mode)
299 (custom "Customize Geiser mode" geiser-mode))
301 (define-key geiser-mode-map [menu-bar scheme] 'undefined)
303 ;; (geiser-mode--triple-chord ?x ?m 'geiser-xref-generic-methods)
306 ;;; Reload support:
308 (defun geiser-mode--buffers ()
309 (let ((buffers))
310 (dolist (buffer (buffer-list))
311 (when (buffer-live-p buffer)
312 (set-buffer buffer)
313 (when geiser-mode
314 (push (cons buffer geiser-impl--implementation) buffers))))
315 buffers))
317 (defun geiser-mode--restore (buffers)
318 (dolist (b buffers)
319 (when (buffer-live-p (car b))
320 (set-buffer (car b))
321 (when (cdr b)
322 (geiser-impl--set-buffer-implementation (cdr b)))
323 (geiser-mode 1))))
325 (defun geiser-mode-unload-function ()
326 (dolist (b (geiser-mode--buffers))
327 (with-current-buffer (car b) (geiser-mode nil))))
330 (provide 'geiser-mode)
331 ;;; geiser-mode.el ends here