Print long expressions after errors in debug buffer.
[geiser.git] / elisp / geiser-debug.el
blob25391db218d661f658dc649b1d234767871c55fe
1 ;;; geiser-debug.el -- displaying debug information and evaluation results
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: Mon Feb 23, 2009 22:34
14 (require 'geiser-edit)
15 (require 'geiser-autodoc)
16 (require 'geiser-impl)
17 (require 'geiser-eval)
18 (require 'geiser-menu)
19 (require 'geiser-popup)
20 (require 'geiser-base)
23 ;;; Debug buffer mode:
25 (defvar geiser-debug-mode-map
26 (let ((map (make-sparse-keymap)))
27 (suppress-keymap map)
28 (set-keymap-parent map button-buffer-map)
29 map))
31 (defun geiser-debug-mode ()
32 "A major mode for displaying Scheme compilation and evaluation results.
33 \\{geiser-debug-mode-map}"
34 (interactive)
35 (kill-all-local-variables)
36 (buffer-disable-undo)
37 (use-local-map geiser-debug-mode-map)
38 (set-syntax-table scheme-mode-syntax-table)
39 (setq mode-name "Geiser DBG")
40 (setq major-mode 'geiser-debug-mode)
41 (setq next-error-function 'geiser-edit--open-next)
42 (setq buffer-read-only t))
44 (defun geiser-debug--button-p (nextp)
45 (let ((m (funcall (if nextp 'next-button 'previous-button) (point))))
46 (and m (funcall (if nextp '< '>) (point) (marker-position m)))))
48 (geiser-menu--defmenu debug geiser-debug-mode-map
49 ("Next error" "n" forward-button :enable (geiser-debug--button-p t))
50 ("Previous error" "p" backward-button :enable (geiser-debug--button-p t))
52 ("Quit" nil View-quit))
55 ;;; Buffer for displaying evaluation results:
57 (geiser-popup--define debug "*Geiser dbg*" geiser-debug-mode)
60 ;;; Displaying retorts
62 (geiser-impl--define-caller geiser-debug--display-error
63 display-error (module key message)
64 "This method takes 3 parameters (a module name, the error key,
65 and the accompanying error message) and should display
66 (in the current buffer) a formatted version of the error. If the
67 error was successfully displayed, the call should evaluate to a
68 non-null value.")
70 (geiser-impl--define-caller geiser-debug--enter-debugger
71 enter-debugger ()
72 "This method is called upon entering the debugger, in the REPL
73 buffer.")
75 (defun geiser-debug--display-retort (what ret &optional res)
76 (let* ((err (geiser-eval--retort-error ret))
77 (key (geiser-eval--error-key err))
78 (output (geiser-eval--retort-output ret))
79 (impl geiser-impl--implementation)
80 (module (geiser-eval--get-module))
81 (jump nil)
82 (dir default-directory)
83 (buffer (current-buffer))
84 (debug (eq key 'geiser-debugger))
85 (lines (with-temp-buffer
86 (insert what)
87 (count-lines (point-min) (point-max))))
88 (after (> lines 5)))
89 (when debug
90 (switch-to-geiser nil nil buffer)
91 (geiser-debug--enter-debugger impl))
92 (geiser-debug--with-buffer
93 (erase-buffer)
94 (when dir (setq default-directory dir))
95 (unless after
96 (insert what)
97 (newline 2))
98 (when (and res (not err))
99 (insert res)
100 (newline 2))
101 (setq jump (geiser-debug--display-error impl module key output))
102 (when after (insert "\nExpression evaluated was:\n\n" what))
103 (goto-char (point-min)))
104 (when jump (geiser-debug--pop-to-buffer))))
106 (defsubst geiser-debug--wrap-region (str)
107 (format "(begin %s)" str))
109 (defun geiser-debug--unwrap (str)
110 (if (string-match "(begin[ \t\n\v\r]+\\(.+\\)*)" str)
111 (match-string 1 str)
112 str))
114 (defun geiser-debug--send-region (compile start end and-go wrap)
115 (let* ((str (buffer-substring-no-properties start end))
116 (wrapped (if wrap (geiser-debug--wrap-region str) str))
117 (code `(,(if compile :comp :eval) (:scm ,wrapped)))
118 (ret (geiser-eval--send/wait code))
119 (res (geiser-eval--retort-result-str ret))
120 (err (geiser-eval--retort-error ret)))
121 (geiser-autodoc--clean-cache)
122 (when and-go (funcall and-go))
123 (when (not err) (message "%s" res))
124 (geiser-debug--display-retort (geiser-syntax--scheme-str str) ret res)))
126 (defun geiser-debug--expand-region (start end all wrap)
127 (let* ((str (buffer-substring-no-properties start end))
128 (wrapped (if wrap (geiser-debug--wrap-region str) str))
129 (code `(:eval (:ge macroexpand (quote (:scm ,wrapped))
130 ,(if all :t :f))))
131 (ret (geiser-eval--send/wait code))
132 (err (geiser-eval--retort-error ret))
133 (result (geiser-eval--retort-result ret)))
134 (if err
135 (geiser-debug--display-retort str ret)
136 (geiser-debug--with-buffer
137 (erase-buffer)
138 (insert (format "%s" (if wrap (geiser-debug--unwrap result) result)))
139 (goto-char (point-min)))
140 (geiser-debug--pop-to-buffer))))
143 (provide 'geiser-debug)
144 ;;; geiser-debug.el ends here