Attached to this post is a patch to the debugger in Apps/Debugger/clim-debugger.lisp. It adds keyboard support and a simple-minded (and almost useless) `eval-in-frame' command.
/etc/host.conf: line 24: bad command `mdns off' 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 28 Apr 2006 14:41:33 -0000 @@ -132,14 +132,14 @@
(defun compute-backtrace (start end) (loop for frame in (swank-backend::compute-backtrace start end) - for frame-no from 0 - collect (make-instance - 'stack-frame - :frame-string (let ((*print-pretty* nil)) - (with-output-to-string (stream) - (swank-backend::print-frame frame stream))) - :frame-no frame-no - :frame-variables (swank-backend::frame-locals frame-no)))) + for frame-no from 0 + collect (make-instance + 'stack-frame + :frame-string (let ((*print-pretty* nil)) + (with-output-to-string (stream) + (swank-backend::print-frame frame stream))) + :frame-no frame-no + :frame-variables (swank-backend::frame-locals frame-no))))
(defmethod expand-backtrace ((info debugger-info) (value integer)) (with-slots (backtrace) info @@ -151,7 +151,19 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(defclass debugger-pane (application-pane) - ((condition-info :reader condition-info :initarg :condition-info))) + ((condition-info + :reader condition-info + :initarg :condition-info) + (selected-stack-frame-index + :accessor selected-stack-frame-index + :initarg :selected-strackframe-index + :type 'integer + :initform 0) + (presentation-hashmap + :accessor presentation-hash-table + :initarg :presentation-hash-tablen + :type 'hash-table + :initform (make-hash-table))))
;; FIXME - These two variables should be removed! ;; Used to return the chosen reatart in the debugger. @@ -173,9 +185,15 @@ (define-application-frame clim-debugger () () (:panes - (debugger-pane (make-debugger-pane))) + (debugger-pane (make-debugger-pane)) + (interactor :interactor + :max-height 100) + (pointer-doc :pointer-documentation)) (:layouts - (default (vertically () (scrolling () debugger-pane)))) + (default (vertically () + (scrolling () debugger-pane) + interactor + pointer-doc))) (:geometry :height 600 :width 800))
(defun run-debugger-frame () @@ -192,26 +210,119 @@ (define-presentation-type more-type ()) (define-presentation-type inspect ())
+(defun highlight-selected-stack-frame (debugger-pane) + "Highlight the presentation associated with the currently + selected stack frame." + (funcall-presentation-generic-function + highlight-presentation + 'stack-frame + (gethash (elt (backtrace + (condition-info debugger-pane)) + (selected-stack-frame-index + debugger-pane)) + (presentation-hash-table debugger-pane)) + debugger-pane + :highlight)) + +(defun unhighlight-selected-stack-frame (debugger-pane) + "Unhighlight the presentation associated with the currently + selected stack frame." + (funcall-presentation-generic-function + highlight-presentation + 'stack-frame + (gethash (elt (backtrace + (condition-info debugger-pane)) + (selected-stack-frame-index + debugger-pane)) + (presentation-hash-table debugger-pane)) + debugger-pane + :unhighlight)) + +(define-presentation-method highlight-presentation ((type stack-frame) record (stream debugger-pane) (state (eql :highlight))) + (declare (ignore state stream)) + (unhighlight-selected-stack-frame stream) + ;; List this presentation as the currently selected. + (setf (selected-stack-frame-index stream) + (position (presentation-object record) + (backtrace (condition-info stream)))) + ;; Unhighlight all other presentations. + + (call-next-method)) + +(define-presentation-method present (object (type stack-frame) stream + (view minimized-stack-frame-view) + &key acceptably for-context-type) + (declare (ignore acceptably for-context-type)) + (format t "~A " (frame-string object))) + +(define-presentation-method present (object (type stack-frame) stream + (view maximized-stack-frame-view) + &key acceptably for-context-type) + (declare (ignore acceptably for-context-type)) + (progn + (princ (frame-string object) stream) + (fresh-line) + (with-text-family (stream :sans-serif) + (bold (stream) (format t " Locals:"))) + (fresh-line) + (format t " ") + (formatting-table + (stream) + (loop for (name n identifier id value val) in (frame-variables object) + do (formatting-row + (stream) + (formatting-cell (stream) (format t "~A" n)) + (formatting-cell (stream) (format t "=")) + (formatting-cell (stream) (present val 'inspect))))) + (terpri stream))) + +(define-presentation-method present (object (type restart) stream + (view textual-view) + &key acceptably for-context-type) + (declare (ignore acceptably for-context-type)) + (bold (stream) (format t "~A" (restart-name object)))) + +(define-presentation-method present (object (type more-type) stream + (view textual-view) + &key acceptably for-context-type) + (declare (ignore acceptably for-context-type)) + (bold (stream) (format t "--- MORE ---"))) + +(define-presentation-method present (object (type inspect) stream + (view textual-view) + &key acceptably for-context-type) + (declare (ignore acceptably for-context-type)) + (format t "~A" object)) +
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Commands ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
-(define-clim-debugger-command (com-more :name "More backtraces") +(define-clim-debugger-command (com-more + :name "More backtraces") ((pane 'more-type)) (expand-backtrace (condition-info pane) 10))
-(define-clim-debugger-command (com-invoke-inspector :name "Invoke inspector") +(define-clim-debugger-command (com-invoke-inspector + :name "Invoke inspector") ((obj 'inspect)) - (clouseau:inspector obj)) + (clouseau:inspector obj :new-process t))
-(define-clim-debugger-command (com-refresh :name "Refresh" :menu t) () +(define-clim-debugger-command (com-refresh + :name "Refresh" + :menu t) + () (change-space-requirements (frame-panes *application-frame*)))
-(define-clim-debugger-command (com-quit :name "Quit" :menu t) () +(define-clim-debugger-command (com-quit + :name "Quit" + :menu t) + () (frame-exit *application-frame*))
-(define-clim-debugger-command (com-invoke-restart :name "Invoke restart") +(define-clim-debugger-command (com-invoke-restart + :name "Invoke restart") ((restart 'restart)) (setf *returned-restart* restart) (frame-exit *application-frame*)) @@ -225,6 +336,148 @@ (setf (view stack-frame) +minimized-stack-frame-view+)) (change-space-requirements (frame-panes *application-frame*))))
+(define-clim-debugger-command (com-eval-in-frame + :name "Eval in frame") + ((stack-frame 'stack-frame) + &key + (code 'expression + :prompt "code" + :default (accept 'expression))) + (setf swank::*buffer-package* + *package* + swank::*buffer-readtable* + *readtable*) + (print (swank:eval-string-in-frame + (write-to-string code) + (frame-no stack-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-stack-frame + :name "Next stack-frame" + :keystroke (#\n :control)) + () + (let ((debugger-pane (get-frame-pane *application-frame* 'debugger-pane))) + (when (< (selected-stack-frame-index debugger-pane) + (1- (length (backtrace (condition-info debugger-pane))))) + (incf (selected-stack-frame-index debugger-pane))))) + +(add-command-to-command-table + 'com-next-stack-frame + 'clim-debugger + :errorp nil + :keystroke '(#\n)) + +(define-clim-debugger-command + (com-prev-stack-frame + :name "Previous stack-frame" + :keystroke (#\p :control)) + () + (let ((debugger-pane (get-frame-pane *application-frame* 'debugger-pane))) + (when (> (selected-stack-frame-index debugger-pane) 0) + (decf (selected-stack-frame-index debugger-pane))))) + +(add-command-to-command-table + 'com-prev-stack-frame + 'clim-debugger + :errorp nil + :keystroke '(#\p)) + +(define-clim-debugger-command + (com-toggle-selected-stack-frame-index-view + :name "Toggle view of selected stack-frame" + :keystroke (#\e)) + () + (let* ((debugger-pane (get-frame-pane *application-frame* 'debugger-pane)) + (stack-frame (nth (selected-stack-frame-index debugger-pane) + (backtrace (condition-info debugger-pane))))) + (execute-frame-command *application-frame* + `(com-toggle-stack-frame-view ,stack-frame)))) + +(define-clim-debugger-command + (com-browse-next-stack-frame + :name "Browse next stack-frame" + :keystroke (#\N)) + () + ;; Minize current stack-frame, select and expand next stack-frame. + (let* ((debugger-pane (get-frame-pane *application-frame* 'debugger-pane)) + (current-stack-frame (nth (selected-stack-frame-index debugger-pane) + (backtrace (condition-info debugger-pane))))) + (setf (view current-stack-frame) +minimized-stack-frame-view+) + (com-next-stack-frame) + ;; We have a new current stack-frame (this shadowing may be a bit + ;; ugly).. + (let ((current-stack-frame (nth (selected-stack-frame-index debugger-pane) + (backtrace (condition-info debugger-pane))))) + (setf (view current-stack-frame) +maximized-stack-frame-view+)))) + +(define-clim-debugger-command + (com-browse-prev-stack-frame + :name "Browse previous stack-frame" + :keystroke (#\P)) + () + ;; Minize current stack-frame, select and expand previous stack-frame. + (let* ((debugger-pane (get-frame-pane *application-frame* 'debugger-pane)) + (current-stack-frame (nth (selected-stack-frame-index debugger-pane) + (backtrace (condition-info debugger-pane))))) + (setf (view current-stack-frame) +minimized-stack-frame-view+) + (com-prev-stack-frame) + ;; We have a new current stack-frame. + (let ((current-stack-frame (nth (selected-stack-frame-index debugger-pane) + (backtrace (condition-info debugger-pane))))) + (setf (view current-stack-frame) +maximized-stack-frame-view+)))) +
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Command translators ;;;;;;;;;;;;;;;;;;;;; @@ -241,7 +494,16 @@ (list object))
(define-presentation-to-command-translator toggle-stack-frame-view - (stack-frame com-toggle-stack-frame-view clim-debugger :gesture :select) + (stack-frame com-toggle-stack-frame-view clim-debugger + :gesture :select + :documentation "Toggle stack frame view") + (object) + (list object)) + +(define-presentation-to-command-translator eval-in-frame + (stack-frame com-eval-in-frame clim-debugger + :gesture :edit + :documentation "Eval in frame") (object) (list object))
@@ -262,15 +524,15 @@ (formatting-cell (pane) (bold (pane) (format t "~A" first)))) (formatting-cell (pane) (with-text-family (pane family) - (format t "~A" second))))) + (format t "~A" second)))))
(defun display-debugger (frame pane) (let ((*standard-output* pane)) (formatting-table (pane) (std-form pane "Condition type:" (type-of-condition (condition-info - pane))) + pane))) (std-form pane "Description:" (condition-message (condition-info - pane))) + pane))) (when (condition-extra (condition-info pane)) (std-form pane "Extra:" (condition-extra (condition-info pane)) :family :fix)) @@ -287,9 +549,12 @@ (formatting-table (pane) (loop for r in (restarts (condition-info pane)) - do (formatting-row (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) @@ -298,8 +563,9 @@ (fresh-line) (display-backtrace frame pane) (change-space-requirements pane - :width (bounding-rectangle-width (stream-output-history pane)) - :height (bounding-rectangle-height (stream-output-history pane))))) + :width (bounding-rectangle-width (stream-output-history pane)) + :height (bounding-rectangle-height (stream-output-history pane)))) + (highlight-selected-stack-frame pane))
(defun display-backtrace (frame pane) @@ -311,13 +577,16 @@ (formatting-table (pane) (loop for stack-frame in (backtrace (condition-info pane)) - for i from 0 - do (formatting-row (pane) - (with-output-as-presentation (pane stack-frame 'stack-frame) - (bold (pane) (formatting-cell (pane) (format t "~A: " i))) - (formatting-cell (pane) - (present stack-frame 'stack-frame - :view (view stack-frame)))))) + for i from 0 + do (formatting-row (pane) + (with-output-as-presentation (pane stack-frame 'stack-frame) + (bold (pane) + (formatting-cell (pane) (format t "~A: " i))) + (formatting-cell (pane) + (setf (gethash stack-frame (presentation-hash-table pane)) + (present stack-frame 'stack-frame + :view (view stack-frame) + :single-box t)))))) (when (>= (length (backtrace (condition-info pane))) 20) (formatting-row (pane) (formatting-cell (pane)) @@ -325,53 +594,6 @@ (bold (pane) (present pane 'more-type)))))))
- -(define-presentation-method present (object (type stack-frame) stream - (view minimized-stack-frame-view) - &key acceptably for-context-type) - (declare (ignore acceptably for-context-type)) - (format t "~A " (frame-string object))) - -(define-presentation-method present (object (type stack-frame) stream - (view maximized-stack-frame-view) - &key acceptably for-context-type) - (declare (ignore acceptably for-context-type)) - (progn - (princ (frame-string object) stream) - (fresh-line) - (with-text-family (stream :sans-serif) - (bold (stream) (format t " Locals:"))) - (fresh-line) - (format t " ") - (formatting-table - (stream) - (loop for (name n identifier id value val) in (frame-variables object) - do (formatting-row - (stream) - (formatting-cell (stream) (format t "~A" n)) - (formatting-cell (stream) (format t "=")) - (formatting-cell (stream) (present val 'inspect))))) - (fresh-line))) - -(define-presentation-method present (object (type restart) stream - (view textual-view) - &key acceptably for-context-type) - (declare (ignore acceptably for-context-type)) - (bold (stream) (format t "~A" (restart-name object)))) - -(define-presentation-method present (object (type more-type) stream - (view textual-view) - &key acceptably for-context-type) - (declare (ignore acceptably for-context-type)) - (bold (stream) (format t "--- MORE ---"))) - -(define-presentation-method present (object (type inspect) stream - (view textual-view) - &key acceptably for-context-type) - (declare (ignore acceptably for-context-type)) - (format t "~A" object)) - - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Starting the debugger ;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -412,4 +634,3 @@ (invoke-debugger (make-condition 'simple-error :format-control "Debugger test"))))) -