I have added SLIME-style keyboard shortcuts to the McCLIM debugger
(Apps/Debugger/clim-debugger.lisp), as well as a pointer-documentation
pane. These changes may be generally useful, so a patch is attached
to this post.
--
\ Troels "Athas" Henriksen
/\ sigkill.dk/blog (Danish)
Index: Apps/Debugger/clim-debugger.lisp
===================================================================
RCS file: /project/mcclim/cvsroot/mcclim/Apps/Debugger/clim-debugger.lisp,v
retrieving revision 1.1
diff -u -r1.1 clim-debugger.lisp
--- Apps/Debugger/clim-debugger.lisp 26 Apr 2005 03:19:34 -0000 1.1
+++ Apps/Debugger/clim-debugger.lisp 19 Jan 2006 22:01:28 -0000
@@ -151,7 +151,12 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defclass debugger-pane (application-pane)
- ((condition-info :reader condition-info :initarg :condition-info)))
+ ((condition-info :reader condition-info :initarg :condition-info)
+ (selected-stackframe
+ :accessor selected-stackframe
+ :initarg :selected-strackframe
+ :type 'integer
+ :initform 0)))
;; FIXME - These two variables should be removed!
;; Used to return the chosen reatart in the debugger.
@@ -173,9 +178,12 @@
(define-application-frame clim-debugger ()
()
(:panes
- (debugger-pane (make-debugger-pane)))
+ (debugger-pane (make-debugger-pane))
+ (pointer-doc :pointer-documentation))
(:layouts
- (default (vertically () (scrolling () debugger-pane))))
+ (default (vertically ()
+ (scrolling () debugger-pane)
+ pointer-doc)))
(:geometry :height 600 :width 800))
(defun run-debugger-frame ()
@@ -225,7 +233,133 @@
(setf (view stack-frame) +minimized-stack-frame-view+))
(change-space-requirements (frame-panes *application-frame*))))
+;;; We want to be able to invoke restarts with the 1-9 letters on the
+;;; keyboard.
+(define-clim-debugger-command
+ (com-invoke-restart-by-number
+ :name "Invoke numbered restart")
+ ((number 'integer))
+ ;; `number' is the number of the restart to invoke. This
+ ;; is simply used as an index into a list.
+ (let* ((debugger-pane
+ (get-frame-pane *application-frame* 'debugger-pane))
+ (restarts
+ (restarts
+ (condition-info debugger-pane)))
+ (selected-restart (nth number restarts)))
+ ;; If the restart is not valid, we just ignore the command.
+ (when selected-restart
+ (setf *returned-restart* selected-restart)
+ (frame-exit *application-frame*))))
+
+;;; We associate keystrokes in the interval 0-9 to calls to
+;;; `clim-invoke-restart' with the keystroke as argument. Is this a
+;;; kludge? I couln't find a better way to do it.
+
+;; Define a macro for convenience.
+
+(defmacro keybind-restart-commands (n)
+ "Associate the numeric keys in the interval 0-N with a call to
+`clim-invoke-restart' with the relevant number as argument."
+ `(progn
+ ,@(loop for r from 0 upto n
+ collecting
+ `(add-command-to-command-table
+ '(com-invoke-restart-by-number ,r)
+ 'clim-debugger
+ :keystroke '(,(code-char (+ (char-code #\0) r)))))))
+
+(keybind-restart-commands 9)
+
+;; We also define an abort-command to permit quick exit.
+
+(define-clim-debugger-command
+ (com-invoke-abort-restart
+ :name "Invoke abort restart"
+ :keystroke (#\q))
+ ()
+ (setf *returned-restart* nil)
+ (frame-exit *application-frame*))
+
+;; We want to be able to navigate the list of stack frames
+;; with the keyboard.
+
+(define-clim-debugger-command
+ (com-next-stackframe
+ :name "Next stackframe"
+ :keystroke (#\n :control))
+ ()
+ (let ((debugger-pane (get-frame-pane *application-frame* 'debugger-pane)))
+ (when (< (selected-stackframe debugger-pane)
+ (1- (length (backtrace (condition-info debugger-pane)))))
+ (incf (selected-stackframe debugger-pane)))))
+
+(add-command-to-command-table
+ 'com-next-stackframe
+ 'clim-debugger
+ :errorp nil
+ :keystroke '(#\n))
+
+(define-clim-debugger-command
+ (com-prev-stackframe
+ :name "Previous stackframe"
+ :keystroke (#\p :control))
+ ()
+ (let ((debugger-pane (get-frame-pane *application-frame* 'debugger-pane)))
+ (when (> (selected-stackframe debugger-pane) 0)
+ (decf (selected-stackframe debugger-pane)))))
+
+(add-command-to-command-table
+ 'com-prev-stackframe
+ 'clim-debugger
+ :errorp nil
+ :keystroke '(#\p))
+
+(define-clim-debugger-command
+ (com-toggle-selected-stackframe-view
+ :name "Toggle view of selected stackframe"
+ :keystroke (#\e))
+ ()
+ (let* ((debugger-pane (get-frame-pane *application-frame* 'debugger-pane))
+ (stackframe (nth (selected-stackframe debugger-pane)
+ (backtrace (condition-info debugger-pane)))))
+ (execute-frame-command *application-frame*
+ `(com-toggle-stack-frame-view ,stackframe))))
+
+(define-clim-debugger-command
+ (com-browse-next-stackframe
+ :name "Browse next stackframe"
+ :keystroke (#\N))
+ ()
+ ;; Minize current stackframe, select and expand next stackframe.
+ (let* ((debugger-pane (get-frame-pane *application-frame* 'debugger-pane))
+ (current-stackframe (nth (selected-stackframe debugger-pane)
+ (backtrace (condition-info debugger-pane)))))
+ (setf (view current-stackframe) +minimized-stack-frame-view+)
+ (com-next-stackframe)
+ ;; We have a new current stackframe (this shadowing may be a bit
+ ;; ugly)..
+ (let ((current-stackframe (nth (selected-stackframe debugger-pane)
+ (backtrace (condition-info debugger-pane)))))
+ (setf (view current-stackframe) +maximized-stack-frame-view+))))
+
+(define-clim-debugger-command
+ (com-browse-prev-stackframe
+ :name "Browse previous stackframe"
+ :keystroke (#\P))
+ ()
+ ;; Minize current stackframe, select and expand previous stackframe.
+ (let* ((debugger-pane (get-frame-pane *application-frame* 'debugger-pane))
+ (current-stackframe (nth (selected-stackframe debugger-pane)
+ (backtrace (condition-info debugger-pane)))))
+ (setf (view current-stackframe) +minimized-stack-frame-view+)
+ (com-prev-stackframe)
+ ;; We have a new current stackframe.
+ (let ((current-stackframe (nth (selected-stackframe debugger-pane)
+ (backtrace (condition-info debugger-pane)))))
+ (setf (view current-stackframe) +maximized-stack-frame-view+))))
+
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Command translators ;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -287,9 +421,12 @@
(formatting-table
(pane)
(loop for r in (restarts (condition-info pane))
+ for rcount from 0
do (formatting-row (pane)
(with-output-as-presentation (pane r 'restart)
(formatting-cell (pane)
+ (format pane "~A." rcount))
+ (formatting-cell (pane)
(format pane "~A" (restart-name r)))
(formatting-cell (pane)
@@ -314,6 +451,9 @@
for i from 0
do (formatting-row (pane)
(with-output-as-presentation (pane stack-frame 'stack-frame)
+ (formatting-cell (pane) (format t "~A" (if (=
(selected-stackframe pane) i)
+ ">"
+ "")))
(bold (pane) (formatting-cell (pane) (format t "~A: " i)))
(formatting-cell (pane)
(present stack-frame 'stack-frame