Skip to content
Newer
Older
100644 569 lines (450 sloc) 19.7 KB
0768eb0 @mark-moseley SVN RubyForge pull
mark-moseley authored
1 ;;; rdebug-source.el --- Ruby debugger user interface.
2
3 ;; Copyright (C) 2006, 2007, 2008 Rocky Bernstein (rocky@gnu.org)
4 ;; Copyright (C) 2007, 2008 Anders Lindgren
5
6 ;; $Id: rdebug-source.el 821 2008-04-25 02:54:44Z rockyb $
7
8 ;; This program is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2, or (at your option)
11 ;; any later version.
12
13 ;; This program 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 the
20 ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21 ;; Boston, MA 02111-1307, USA.
22
23 ;;; Commentary:
24
25 ;; See the manual and the file `rdebug.el' for more information.
26
27 ;; This file is loaded when a Ruby source buffer is loaded. It
28 ;; contains, among else, the Debugger menu.
29
30 ;;; Code:
31
32 ;; -------------------------------------------------------------------
33 ;; Consistency checks.
34 ;;
35
36 (if (< emacs-major-version 22)
37 (error
38 "Rdebug needs at least Emacs 22 or greater - you have version %d."
39 emacs-major-version))
40
41
42 ;; -------------------------------------------------------------------
43 ;; Dependencies.
44 ;;
45
46 (require 'cl)
47
48 (require 'gud) ; For gud-key-prefix, sigh...
49 (require 'rdebug)
50 (require 'rdebug-vars)
51
52
53 ;; -------------------------------------------------------------------
54 ;; Key bindings
55 ;;
56
57 (defun rdebug-populate-common-keys-standard (map)
58 "Bind the basic debugger key layout used by many debuggers.
59
60 \\{rdebug-example-map-standard}"
61 (define-key map [f5] 'gud-cont)
62 (define-key map [S-f5] 'rdebug-quit)
63 (define-key map [f9] 'rdebug-toggle-source-breakpoint)
64 (define-key map [C-f9] 'rdebug-toggle-source-breakpoint-enabled)
65 (define-key map [f10] 'rdebug-next)
66 (define-key map [f11] 'rdebug-step)
67 (define-key map [S-f11] 'gud-finish))
68
69
70 ;; TODO: Verify and complement.
71 (defun rdebug-populate-common-keys-eclipse (map)
72 "Bind the basic debugger key layout used by Eclipse.
73
74 \\{rdebug-example-map-eclipse}"
75 ;;(define-key map [] 'gud-cont)
76 ;;(define-key map [] 'rdebug-quit)
77 (define-key map [S-C-b] 'rdebug-toggle-source-breakpoint)
78 (define-key map [f6] 'rdebug-next)
79 (define-key map [f5] 'rdebug-step)
80 (define-key map [f7] 'gud-finish))
81
82
83 ;; TODO: Verify and complement.
84 (defun rdebug-populate-common-keys-netbeans (map)
85 "Bind the basic debugger key layout used by NetBeans.
86
87 \\{rdebug-example-map-netbeans}"
88 ;;(define-key map [] 'gud-cont)
89 ;;(define-key map [] 'rdebug-quit)
90 ;; F4 - Run to cursor.
91 (define-key map [S-f8] 'rdebug-toggle-source-breakpoint)
92 (define-key map [f8] 'rdebug-next)
93 (define-key map [f7] 'rdebug-step)
94 (define-key map [M-S-f7] 'gud-finish))
95
96
97 ;; Note: This is only used in doc-strings.
98 (defvar rdebug-example-map-standard
99 (let ((map (make-sparse-keymap)))
100 (rdebug-populate-common-keys-standard map)
101 map)
102 "Rdebug Standard common keymap used only in doc-string.")
103
104
105 (defvar rdebug-example-map-eclipse
106 (let ((map (make-sparse-keymap)))
107 (rdebug-populate-common-keys-eclipse map)
108 map)
109 "Rdebug Eclipse compatibility common keymap used only in doc-string.")
110
111
112 (defvar rdebug-example-map-netbeans
113 (let ((map (make-sparse-keymap)))
114 (rdebug-populate-common-keys-netbeans map)
115 map)
116 "Rdebug NetBeans compatibility common keymap used only in doc-string.")
117
118
119 (defun rdebug-populate-common-keys (map)
120 "Define the keys that are used by all debugger windows, even by the source.
121
122 The variable `rdebug-populate-common-keys-function' controls the layout."
123 (define-key map "\C-x\C-a\C-q" 'rdebug-short-key-mode)
124 (if rdebug-populate-common-keys-function
125 (funcall rdebug-populate-common-keys-function map)))
126
127
128 (defun rdebug-populate-digit-keys (map)
129 (define-key map "0" 'rdebug-goto-entry-n)
130 (define-key map "1" 'rdebug-goto-entry-n)
131 (define-key map "2" 'rdebug-goto-entry-n)
132 (define-key map "3" 'rdebug-goto-entry-n)
133 (define-key map "4" 'rdebug-goto-entry-n)
134 (define-key map "5" 'rdebug-goto-entry-n)
135 (define-key map "6" 'rdebug-goto-entry-n)
136 (define-key map "7" 'rdebug-goto-entry-n)
137 (define-key map "8" 'rdebug-goto-entry-n)
138 (define-key map "9" 'rdebug-goto-entry-n))
139
140
141 ;; -------------------------------------------------------------------
142 ;; Menu support.
143 ;;
144
145
146 ;; Note: We want the key binding to show in the menu. However, our
147 ;; situation is a little bit complex:
148 ;;
149 ;; 1) We want the binding of the `common' man (i.e. the function key
150 ;; the user has selected.)
151 ;;
152 ;; 2) We want this even when the menu is disabled and the key isn't
153 ;; bound, typically when the debugger isn't running.
154 ;;
155 ;; This has been solved by setting up an explicit ":keys" properly.
156 (defun rdebug-menu-item (common-map name cmd &rest args)
157 "Return a menu item entry with the correct key bindings.
158
159 A command can be bound to a number of different key sequences. If
160 the rdebug common map contains a binding it is displayed in the
161 menu. (The common map typically contains function key bindings.)"
162 (let ((key-binding (where-is-internal cmd (list common-map) t))
163 (hint '()))
164 (if key-binding
165 (setq hint (list :keys (key-description key-binding))))
166 (append (list 'menu-item name cmd)
167 hint
168 args)))
169
170
171 ;; Note, we re-populate the menus of the different minor and major
172 ;; modes. The reason is that Emacs caches the key bindings, which
173 ;; means that wrong ones are shown when buffers are changed.
174
175 ;; Remember, all menu items are added in the reverse order!
176
177 (defun rdebug-populate-debugger-menu (map)
178 "Populate the Rdebug 'Debugger' menu."
179 (let ((menu (make-sparse-keymap))
180 (common-map (make-sparse-keymap)))
181 ;; Use a simple common map to find the best key sequence to
182 ;; display in menu.
183 (rdebug-populate-common-keys common-map)
184
185 (define-key map [menu-bar debugger] (cons "Debugger" menu))
186
187 (define-key menu [break-delete]
188 (rdebug-menu-item common-map "Enable/disable breakpoint"
189 'rdebug-toggle-source-breakpoint-enabled
190 :enable '(get-buffer-process gud-comint-buffer)))
191
192 (define-key menu [break]
193 (rdebug-menu-item common-map "Toggle breakpoint"
194 'rdebug-toggle-source-breakpoint
195 :enable '(get-buffer-process gud-comint-buffer)))
196
197 (define-key menu [finish]
198 (rdebug-menu-item common-map "Step out" 'gud-finish
199 :enable '(get-buffer-process gud-comint-buffer)))
200
201 (define-key menu [step]
202 (rdebug-menu-item common-map "Step into" 'rdebug-step
203 :enable '(get-buffer-process gud-comint-buffer)))
204
205 (define-key menu [next]
206 (rdebug-menu-item common-map "Step over" 'rdebug-next
207 :enable '(get-buffer-process gud-comint-buffer)))
208
209 (define-key menu [cont]
210 (rdebug-menu-item common-map "Continue" 'rdebug-continue
211 :enable '(get-buffer-process gud-comint-buffer)))
212
213 (define-key map [menu-bar debugger line1] '(menu-item "--"))
214
215 (define-key menu [stop]
216 (rdebug-menu-item
217 common-map "Stop the debugger" 'rdebug-quit
218 :enable '(get-buffer-process gud-comint-buffer)))
219
220 (define-key menu [start]
221 (rdebug-menu-item common-map "Start the debugger" 'rdebug))
222
223 (define-key map [menu-bar debugger line2] '(menu-item "--"))
224
225 ;; --------------------
226 ;; The "Options" submenu.
227
228 (let ((submenu (make-sparse-keymap)))
229 (define-key menu [options] (cons "Options" submenu)))
230
231 (define-key map [menu-bar debugger options customize]
232 (rdebug-menu-item common-map
233 "Customize Rdebug" 'rdebug-customize))
234
235 (define-key map [menu-bar debugger options line1] '(menu-item "--"))
236
237
238
239 ;; ----------------
240 ;; The "short key" toggle.
241
242 (define-key map [menu-bar debugger options short-key-mode]
243 (rdebug-menu-item common-map
244 "Short keys in source" 'rdebug-short-key-mode
245 :button
246 '(:toggle
247 . rdebug-short-key-mode)))
248
249 (define-key map [menu-bar debugger options line2] '(menu-item "--"))
250
251 ;; ----------------
252 ;; Separate I/O buffer.
253
254 (define-key map [menu-bar debugger options io-buffer]
255 (rdebug-menu-item common-map
256 "Separate I/O buffer"
257 'rdebug-toggle-use-separate-io-buffer
258 :button
259 '(:toggle
260 . rdebug-use-separate-io-buffer)))
261
262 ;; --------------------
263 ;; The optional secondary windows submenu.
264
265
266 ;; Placeholder used when populating the menu of the secondary buffers.
267 (define-key menu [placeholder] nil)
268
269 ;; --------------------
270 ;; The "Window Layout" submenu.
271 (let ((submenu (make-sparse-keymap)))
272 (define-key menu [layout] (cons "Window Layout" submenu)))
273
274 ;; ----------------
275 ;; The "Window Layout" submenu.
276
277
278 ;; TODO: The following is a somewhat clumsy implementation. Maybe we can
279 ;; automatically generate the entries, or use the `dynamic' menu kind?
280 ;;
281 ;; Also, there might be other situations where the list might be
282 ;; handy, e.g. completion.
283 (let ((predefined '(rdebug-window-layout-standard
284 rdebug-window-layout-no-shell
285 rdebug-window-layout-conservative
286 rdebug-window-layout-stack-of-windows
287 rdebug-window-layout-rocky
288 rdebug-window-layout-rocky2)))
289
290 (define-key map [menu-bar debugger layout other]
291 (rdebug-menu-item
292 common-map
293 "Other"
294 'rdebug-set-window-layout
295 :button
296 `(:radio
297 . (not (memq rdebug-window-layout-function (quote ,predefined))))))
298
299 (define-key map [menu-bar debugger layout rocky]
300 (rdebug-menu-item
301 common-map
302 "Rocky's Own"
303 (lambda ()
304 (interactive)
305 (rdebug-set-window-layout 'rdebug-window-layout-rocky))
306 :button
307 '(:radio
308 . (eq rdebug-window-layout-function
309 'rdebug-window-layout-rocky))))
310
311 (define-key map [menu-bar debugger layout rocky2]
312 (rdebug-menu-item
313 common-map
314 "Rocky II"
315 (lambda ()
316 (interactive)
317 (rdebug-set-window-layout 'rdebug-window-layout-rocky2))
318 :button
319 '(:radio
320 . (eq rdebug-window-layout-function
321 'rdebug-window-layout-rocky2))))
322
323 (define-key map [menu-bar debugger layout stack]
324 (rdebug-menu-item
325 common-map
326 "Stack of Windows"
327 (lambda ()
328 (interactive)
329 (rdebug-set-window-layout 'rdebug-window-layout-stack-of-windows))
330 :button
331 '(:radio
332 . (eq rdebug-window-layout-function
333 'rdebug-window-layout-stack-of-windows))))
334
335 (define-key map [menu-bar debugger layout conservative]
336 (rdebug-menu-item
337 common-map
338 "Conservative"
339 (lambda ()
340 (interactive)
341 (rdebug-set-window-layout 'rdebug-window-layout-conservative))
342 :button
343 '(:radio
344 . (eq rdebug-window-layout-function
345 'rdebug-window-layout-conservative))))
346
347 (define-key map [menu-bar debugger layout no-shell]
348 (rdebug-menu-item
349 common-map
350 "No Shell"
351 (lambda ()
352 (interactive)
353 (rdebug-set-window-layout 'rdebug-window-layout-no-shell))
354 :button
355 '(:radio
356 . (eq rdebug-window-layout-function
357 'rdebug-window-layout-no-shell))))
358
359 (define-key map [menu-bar debugger layout standard]
360 (rdebug-menu-item
361 common-map
362 "Standard"
363 (lambda ()
364 (interactive)
365 (rdebug-set-window-layout 'rdebug-window-layout-standard))
366 :button
367 '(:radio
368 . (eq rdebug-window-layout-function
369 'rdebug-window-layout-standard)))))
370
371 (define-key map [menu-bar debugger layout line3] '(menu-item "--"))
372
373 (define-key map [menu-bar debugger layout initial]
374 (rdebug-menu-item common-map
375 "Restore Debugger Layout"
376 'rdebug-restore-debugger-window-layout
377 :enable '(fboundp 'rdebug-restore-debugger-window-layout)))
378
379 (define-key map [menu-bar debugger layout line1] '(menu-item "--"))
380
381 ;; Note: It seems as though :enable doesn't work when :button is used.
382 (define-key map [menu-bar debugger layout debugger]
383 (rdebug-menu-item common-map "Current Debugger Layout"
384 'rdebug-display-debugger-window-configuration
385 :button
386 '(:radio
387 . (eq rdebug-window-configuration-state 'debugger))))
388
389 (define-key map [menu-bar debugger layout original]
390 (rdebug-menu-item common-map "Original Layout"
391 'rdebug-display-original-window-configuration
392 :button
393 '(:radio
394 . (eq rdebug-window-configuration-state 'original))))
395
396 ;; --------------------
397 ;; The "View" submenu.
398 (let ((submenu (make-sparse-keymap)))
399 (define-key menu [view] (cons "View" submenu)))
400
401 (define-key map [menu-bar debugger view output]
402 (rdebug-menu-item common-map "Output" 'rdebug-display-output-buffer
403 :enable '(get-buffer-process gud-comint-buffer)))
404
405 (define-key map [menu-bar debugger view watch]
406 (rdebug-menu-item common-map "Watch" 'rdebug-display-watch-buffer
407 :enable '(get-buffer-process gud-comint-buffer)))
408
409 (define-key map [menu-bar debugger view stack]
410 (rdebug-menu-item common-map "Stack-Frame trace"
411 'rdebug-display-frame-buffer
412 :enable '(get-buffer-process gud-comint-buffer)))
413
414 (define-key map [menu-bar debugger view shell]
415 (rdebug-menu-item common-map "Debugger Shell" 'rdebug-display-cmd-buffer
416 :enable '(get-buffer-process gud-comint-buffer)))
417
418 (define-key map [menu-bar debugger view variables]
419 (rdebug-menu-item common-map "Variables" 'rdebug-display-variables-buffer
420 :enable '(get-buffer-process gud-comint-buffer)))
421
422 (define-key map [menu-bar debugger view breakpoints]
423 (rdebug-menu-item common-map
424 "Breakpoints" 'rdebug-display-breakpoints-buffer
425 :enable '(get-buffer-process gud-comint-buffer)))
426
427 (define-key map [menu-bar debugger view source]
428 (rdebug-menu-item common-map
429 "Source" 'rdebug-display-source-buffer
430 :enable '(get-buffer-process gud-comint-buffer)))
431 menu))
432
433
434 ;; -----------------------------------------------
435 ;; Key bindings and menu for secondary buffers.
436 ;;
437
438 (defun rdebug-populate-secondary-buffer-map-plain (map)
439 "Bind the plain keys used in rdebug secondary buffers.
440
441 This does not menus or prefix keys."
442 ;; Keys to view other buffers.
443 (let ((prefix-map (make-sparse-keymap)))
444 (define-key map "?" 'rdebug-display-secondary-window-help-buffer)
445 (define-key map "B" 'rdebug-display-breakpoints-buffer)
446 (define-key map "C" 'rdebug-display-cmd-buffer)
447 (define-key map "E" 'rdebug-display-error-buffer)
448 (define-key map "F" 'rdebug-display-frame-buffer)
449 (define-key map "I" 'rdebug-display-info-buffer)
450 (define-key map "O" 'rdebug-display-output-buffer)
451 (define-key map "S" 'rdebug-display-source-buffer)
452 (define-key map "V" 'rdebug-display-variables-buffer)
453 (define-key map "W" 'rdebug-display-watch-buffer)
454 ;; Common debugger commands.
455 (define-key map " " 'rdebug-step)
456 (define-key map "_" 'rdebug-set-stepping-prefix)
457 (define-key map "+" 'rdebug-set-stepping-prefix)
458 (define-key map "-" 'rdebug-set-stepping-prefix)
459 (define-key map "<" 'rdebug-newer-frame)
460 (define-key map ">" 'rdebug-older-frame)
461 ;; (define-key map "a" 'gud-args)
462 ;; (define-key map "b" 'gud-break)
463 (define-key map "c" 'rdebug-continue)
464 ;; (define-key map "d" 'gud-remove)
465 (define-key map "f" 'gud-finish)
466 (define-key map "n" 'rdebug-next)
467 (define-key map "p" prefix-map)
468 (define-key map "q" 'rdebug-quit)
469 (define-key map "r" 'rdebug-restart)
470 (define-key map "R" 'rdebug-restart)
471 (define-key map "s" 'rdebug-step)
472 (define-key map [M-down] 'rdebug-locring-newer)
473 (define-key map [M-up] 'rdebug-locring-older)
474 (define-key map [M-S-down] 'rdebug-locring-newest)
475 (define-key map [M-S-up] 'rdebug-locring-oldest)
476 (define-key map [mouse-3] 'rdebug-variables-pretty-print-mouse)
477 (define-key prefix-map "l" 'rdebug-print-list-region)
478 (define-key prefix-map "p" 'rdebug-pretty-print-region)
479 (define-key prefix-map "s" 'rdebug-print-sorted-region)
480 ))
481
482
483 ;; -------------------------------------------------------------------
484 ;; Window layout.
485 ;;
486
487 ;; This function is intended for the Options submenu.
488 (defun rdebug-set-window-layout (func)
489 "Set and, if the debugger is running, display the window layout."
490 (interactive "aWindow layout function: ")
491 (setq rdebug-window-layout-function func)
492 (if gud-comint-buffer
493 (with-no-warnings
494 (rdebug-setup-windows))))
495
496
497 ;; -------------------------------------------------------------------
498 ;; The source buffer rdebug support mode.
499 ;;
500 ;; This is a minor mode that is active in Ruby source buffers. It
501 ;; provides the menu and, when the debugger is active, the debugger
502 ;; key bindings.
503
504 (defvar rdebug-debugger-support-minor-mode-map-when-deactive
505 (let ((map (make-sparse-keymap))
506 (prefix-map (make-sparse-keymap)))
507 (rdebug-populate-debugger-menu map)
508 (rdebug-populate-secondary-buffer-map-plain prefix-map)
509 (define-key map gud-key-prefix prefix-map)
510 map)
511 "Keymap used by rdebugs support minor mode when the debugger is active.")
512
513 (defvar rdebug-debugger-support-minor-mode-map-when-active
514 (let ((map (make-sparse-keymap))
515 (prefix-map (make-sparse-keymap)))
516 (rdebug-populate-debugger-menu map)
517 (rdebug-populate-secondary-buffer-map-plain prefix-map)
518 (define-key prefix-map [insert] 'rdebug-short-key-mode)
519 (define-key map gud-key-prefix prefix-map)
520 (rdebug-populate-common-keys map)
521 map)
522 "Keymap used by rdebugs support minor mode when the debugger not active.")
523
524
525 (define-minor-mode rdebug-debugger-support-minor-mode
526 "Minor mode active in source buffers that use the `rdebug' Ruby debugger."
527 :group rdebug
528 :global nil
529 :init-value nil
530 :keymap rdebug-debugger-support-minor-mode-map-when-deactive
531 (setq mode-line-process (and rdebug-debugger-support-minor-mode
532 'rdebug-mode-line-process)))
533
534
535 ;;;###autoload
536 (defun rdebug-turn-on-debugger-support ()
537 "Enable extra source buffer support for the `rdebug' Ruby debugger.
538
539 This includes a 'Debugger' menu and special key bindings when the
540 debugger is active."
541 (rdebug-debugger-support-minor-mode 1))
542
543
544 ;; -------------------------------------------------------------------
545 ;; Use separate I/O buffer
546 ;;
547
548 (defun rdebug-toggle-use-separate-io-buffer ()
549 "Toggle `rdebug-use-separate-io-buffer'.
550 This is used by the menu."
551 (interactive)
552 (setq rdebug-use-separate-io-buffer (not rdebug-use-separate-io-buffer))
553 (if (interactive-p)
554 (message "Issue M-x rdebug-restore-debugger-window-layout \
555 RET to update display.")))
556
557
558 ;; -------------------------------------------------------------------
559 ;; The end.
560 ;;
561
562 (provide 'rdebug-source)
563
564 ;;; Local variables:
565 ;;; eval:(put 'rdebug-debug-enter 'lisp-indent-hook 1)
566 ;;; End:
567
568 ;;; rdebug-source.el ends here
Something went wrong with that request. Please try again.