[slime-cvs] CVS update: slime/present.lisp

Alan Ruttenberg aruttenberg at common-lisp.net
Sun May 22 06:55:59 UTC 2005


Update of /project/slime/cvsroot/slime
In directory common-lisp.net:/tmp/cvs-serv1115/slime

Modified Files:
	present.lisp 
Log Message:

Date: Sun May 22 08:55:59 2005
Author: aruttenberg

Index: slime/present.lisp
diff -u slime/present.lisp:1.1 slime/present.lisp:1.2
--- slime/present.lisp:1.1	Fri May 20 20:04:48 2005
+++ slime/present.lisp	Sun May 22 08:55:59 2005
@@ -9,7 +9,16 @@
 ;; and adds the necessary text properties to the output.
 
 (defvar *can-print-presentation* nil 
-  "set this to t in contexts where it is ok to print presentations")
+  "set this to t in contexts where it is ok to print presentations at all")
+ 
+(defvar *can-present-readable-objects* nil
+  "set this to t in context where it is ok to automatically print presentations 
+for some subset of readable objects, such as pathnames. Generally, this is unsafe
+(since you might not be printing to the listener and expecting to read
+them later) but can be appropriate in specific circumstances, such as
+when you know your output is going to the listener, or where you know
+you wouldn't be later reading the objects printed"
+  )
 
 (defvar *object-to-presentation-id* (make-hash-table :test 'eq #+openmcl :weak #+openmcl :key)
   "Store the mapping of objects to numeric identifiers")
@@ -22,6 +31,7 @@
 (defun clear-presentation-tables ()
   (clrhash *object-to-presentation-id*)
   (clrhash *presentation-id-to-object*)
+  (setq *presentation-counter* 0)
   )
 
 (defun lookup-presented-object (id)
@@ -42,6 +52,19 @@
 be sensitive and remember what object it is in the repl"
   `(presenting-object-1 ,object ,stream #'(lambda () , at body)))
 
+(defmacro presenting-object-if (predicate object stream &body body)
+  "What you use in your code. Wrap this around some printing and that text will
+be sensitive and remember what object it is in the repl if predicate is true"
+  (let ((continue (gensym)))
+  `(let ((,continue #'(lambda () , at body)))
+    (if ,predicate
+	(presenting-object-1 ,object ,stream ,continue)
+	(funcall ,continue)))))
+
+(defun can-present-readable-objects (&optional stream)
+  (declare (ignore stream))
+  *can-present-readable-objects*)
+
 (defun presenting-object-1 (object stream continue)
   "Uses the bridge mechanism with two messages >id and <id. The first one
 says that I am starting to print an object with this id. The second says I am finished"
@@ -113,6 +136,97 @@
 	  for i from start
 	  collect (list i (frame-for-emacs i frame)))))
 
+;; ditto inspector - isn't needed
+(defslimefun init-inspector (string)
+  (let ((*can-print-presentation* nil))
+    (with-buffer-syntax ()
+      (reset-inspector)
+      (inspect-object (eval (read-from-string string))))))
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; menu protocol
+;;
+;; To define a menu for a type of object, define a method
+;; menu-choices-for-presentation on that object type.  This function
+;; should return a list of two element lists where the first element is
+;; The name of the menu action and the second is a function that will be
+;; called if the menu is chosen. The function will be called with 3
+;; arguments:
+;;
+;; choice: The string naming the action from above
+;;
+;; object: The object 
+;;
+;; id: The presentation id of the object
+;;
+;; You might want append (when (next-method-p) (call-next-method)) to
+;; pick up the Menu actions of superclasses.
+;;
+;; The function should return a form which will be evaluated on the emacs side.
+
+(defvar *presentation-active-menu* nil)
+
+(defun menu-choices-for-presentation-id (id)
+  (let ((ob (lookup-presented-object id)))
+    (if (eq ob :not-present)
+	'not-present
+	(let ((menu-and-actions (menu-choices-for-presentation ob)))
+	  (setq *presentation-active-menu* (cons id menu-and-actions))
+	  (mapcar 'car menu-and-actions)))))
+
+(defun swank-ioify (thing)
+  (cond ((keywordp thing) thing)
+	((and (symbolp thing)(not (find #\: (symbol-name thing))))
+	 (intern (symbol-name thing) 'swank-io-package))
+	((consp thing) (cons (swank-ioify (car thing)) (swank-ioify (cdr thing))))
+	(t thing)))
+
+(defun execute-menu-choice-for-presentation-id (id count item)
+  (let ((ob (lookup-presented-object id)))
+    (assert (eql id (car *presentation-active-menu*)) () 
+	    "Bug: Execute menu call for id ~a  but menu has id ~a"
+	    id (car *presentation-active-menu*))
+    (let ((action (second (nth (1- count) (cdr *presentation-active-menu*)))))
+      (swank-ioify (funcall action item ob id)))))
+
+;; Default method
+(defmethod menu-choices-for-presentation (ob)
+  (declare (ignore ob))
+  (list 
+   (list "Inspect" (lambda(choice object id) (declare (ignore choice object)) 
+			  `(slime-inspect-presented-object ,id)))
+   (list "Describe" (lambda(choice object id) (declare (ignore id choice)) 
+			   (describe object) 
+			   nil))
+   (list "Copy to input" (lambda(choice object id) (declare (ignore choice object id)) 
+			  `(slime-copy-presentation-at-point event)))))
+
+;; Pathname
+(defmethod menu-choices-for-presentation ((ob pathname))
+  (let* ((file-exists (ignore-errors (probe-file ob)))
+	 (source-file (and (not (equal (pathname-type ob) "lisp"))
+			   (let ((source (merge-pathnames ".lisp" ob)))
+			     (and (ignore-errors (probe-file source))
+				  source)))))
+    (remove nil 
+	    (list*
+	     (and file-exists
+		  (list "Edit this file" 
+			(lambda(choice object id) 
+			  (declare (ignore choice id)) (ed object) nil)))
+	     (and file-exists
+		  (list "Dired containing directory"
+			(lambda (choice object id)
+			  (declare (ignore choice id))
+			  `(dired ,(namestring (truename (merge-pathnames (make-pathname :name "" :type "") object)))))))
+	     (and source-file 
+		  (list "Edit lisp source file" 
+			(lambda(choice object id) 
+			  (declare (ignore choice id object)) (ed source-file) nil)))
+	     (and (next-method-p) (call-next-method))))))
+  
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
 ;; Example: Tell openmcl and cmucl to always present unreadable objects. try (describe 'class) 
 #+openmcl
 (in-package :ccl)
@@ -132,7 +246,10 @@
       (if id
 	  (%write-address object stream #\>)
 	  (pp-end-block stream ">"))
-      nil)))
+      nil))
+  ;(defmethod print-object :around ((pathname pathname) stream)
+  ;  (swank::presenting-object-if (swank::can-present-readable-objects stream) pathname stream (call-next-method)))
+)
 
 #+openmcl
 (ccl::def-load-pointers clear-presentations ()




More information about the slime-cvs mailing list