The guided-tour has a test application that's a file-browser. I wanted to try to figure out how to read pathnames in an application I'm writing, so I tried to fire up the file-browser. Unfortunately, it didn't work, mostly because it made assumptions about the way that CL pathnames work that didn't map onto either SBCL or ACL, the two applications on which I tried it.
I am attaching a patch which makes it work (if the patch about pathname presentations, that I sent earlier today, is also present). I am inclined to commit this, since (a) it's just part of an article, so can't be on anyone's critical path and (b) it seems like a Bad Thing to have a tutorial out there featuring exemplars that don't work. The downside is that CL pathnames are so intractable that the only good way I found to make this work was to use CL-FAD. Dependencies on libraries seems generally like a bad thing in a small tutorial like this, but importing enough code to make it work w/o the library would probably obscure the tutorial intent even worse.
BTW, I think a more elegant solution might be made that would use satisfies to define the dir-pathname presentation-type more declaratively. But I couldn't figure out how to do it...
best, Robert
On 1/5/07, Robert Goldman rpgoldman@real-time.com wrote:
I am attaching a patch which makes it work (if the patch about pathname presentations, that I sent earlier today, is also present).
Did you forget to attach the patch?
The downside is that CL pathnames are so intractable that the only good way I found to make this work was to use CL-FAD.
I hate pathnames. Even for something as seemingly trivial as Show Directory in the listener, they turned into an unpredictable, unportable mess. I vowed not to use them as the primary representation in the event I ever get around to adding serious shell-like features to the listener.
BTW, I think a more elegant solution might be made that would use satisfies to define the dir-pathname presentation-type more declaratively. But I couldn't figure out how to do it...
Good idea. '(and pathname (satisfies my-directory-p)) doesn't do it?
Andy Hefner wrote:
On 1/5/07, Robert Goldman rpgoldman@real-time.com wrote:
I am attaching a patch which makes it work (if the patch about pathname presentations, that I sent earlier today, is also present).
Did you forget to attach the patch?
Argh. Yes. I *always* do that! [I note that kmail actually scans your email and if you say "attach" anywhere in it, and there's no attachment, it prompts you before sending...]. I will attach here
The downside is that CL pathnames are so intractable that the only good way I found to make this work was to use CL-FAD.
I hate pathnames. Even for something as seemingly trivial as Show Directory in the listener, they turned into an unpredictable, unportable mess. I vowed not to use them as the primary representation in the event I ever get around to adding serious shell-like features to the listener.
Yes, unpredictable, unportable mess. That's the original file-browser in a nutshell...
BTW, I think a more elegant solution might be made that would use satisfies to define the dir-pathname presentation-type more declaratively. But I couldn't figure out how to do it...
Good idea. '(and pathname (satisfies my-directory-p)) doesn't do it?
Didn't for me, and I didn't have the foggiest idea how to debug it once it didn't.... Probably there's some way to mouse over something on the screen and figure out what kind of presentation it is? [Garnet had an integrated debugger for which I was often very grateful; I don't really have a clue how to debug CLIM yet...]
Probably for someone who groks the relationship of presentation objects and objects presented, this will be more obvious. I tried '(and pathname (satisfies cl-fad:directory-pathname-p)) and nothing worked. But perhaps I made some simple error.
BTW, the code itself is so short that I will attach it, as well. Might be easier to look at that than to read the patch.
(eval-when (:compile-toplevel) (asdf:oos 'asdf:load-op :clim) (asdf:oos 'asdf:load-op :clim-clx))
(eval-when (:compile-toplevel :load-toplevel :execute) (asdf:oos 'asdf:load-op :cl-fad))
(in-package :clim-user)
; LTAG-start:file-browser-all (define-application-frame file-browser () ((active-files :initform nil :accessor active-files)) (:panes (file-browser :application :display-function '(dirlist-display-files) ;; Call the display-function whenever the command ;; loop makes a ``full-cycle'' :display-time :command-loop) (interactor :interactor)) (:layouts (default (vertically () file-browser interactor))))
(define-presentation-type dir-pathname () :inherit-from 'pathname)
(defmethod dirlist-display-files ((frame file-browser) pane) ;; Clear old displayed entries (clear-output-record (stream-output-history pane))
(dolist (file (active-files frame)) ;; Instead of write-string, we use present so that the link to ;; object file and the semantic information that file is ;; pathname is retained. (present file (if (cl-fad:directory-pathname-p file) 'dir-pathname 'pathname) :stream pane) (terpri pane)))
(define-file-browser-command (com-edit-directory :name "Edit Directory") ((dir 'dir-pathname)) ;; the following was a previous attempt to deal with the oddities of ;; CL pathnames. Unfortunately, it does not work properly with all ;; lisp implementations. Because of these oddities, we really need ;; a layer like cl-fad to keep things straight. [2007/01/05:rpg] ;;; (let ((dir (make-pathname :directory (pathname-directory dir) ;;; :name :wild :type :wild :version :wild ;;; :defaults dir))) (setf (active-files *application-frame*) (cl-fad:list-directory dir)))
(define-presentation-to-command-translator pathname-to-edit-command (dir-pathname ; source presentation-type com-edit-directory ; target-command file-browser ; command-table :gesture :select ; use this translator for pointer clicks :documentation "Edit this path") ; used in context menu (object) ; argument List (list object)) ; arguments for target-command
(define-file-browser-command (com-quit :name t) () (frame-exit *application-frame*) )
(defmethod adopt-frame :after (frame-manager (frame file-browser)) (declare (ignore frame-manager)) (execute-frame-command frame `(com-edit-directory ,(make-pathname :directory '(:absolute)))))
; LTAG-end
Andy Hefner wrote:
On 1/5/07, Robert Goldman rpgoldman@real-time.com wrote:
[...snip...]
BTW, I think a more elegant solution might be made that would use satisfies to define the dir-pathname presentation-type more declaratively. But I couldn't figure out how to do it...
Good idea. '(and pathname (satisfies my-directory-p)) doesn't do it?
I made a stab at it, but no, it didn't seem to work. I am attaching two different versions of the file-browser: one that works, using a new presentation-type, dir-pathname, and one that tries to do the job with (and pathname (satisfies cl-fad:directory-pathname-p)), that doesn't work.
Probably there's some simple idiocy I've committed that makes this not work, either a bug, or a misunderstanding of presentation types and the relationship between presentation and the presented object. If anyone can correct this, I will appreciate it, and will see to it that the answer, duly credited, appears in the Guided-Tour paper, to enlighten future seekers after CLIMmy wisdom.
Best, R
(eval-when (:compile-toplevel) (asdf:oos 'asdf:load-op :clim) (asdf:oos 'asdf:load-op :clim-clx))
(eval-when (:compile-toplevel :load-toplevel :execute) (asdf:oos 'asdf:load-op :cl-fad))
(in-package :clim-user)
; LTAG-start:file-browser-all (define-application-frame file-browser () ((active-files :initform nil :accessor active-files)) (:panes (file-browser :application :display-function '(dirlist-display-files) ;; Call the display-function whenever the command ;; loop makes a ``full-cycle'' :display-time :command-loop) (interactor :interactor)) (:layouts (default (vertically () file-browser interactor))))
;;;(define-presentation-type dir-pathname () ;;; :inherit-from 'pathname)
(defmethod dirlist-display-files ((frame file-browser) pane) ;; Clear old displayed entries (clear-output-record (stream-output-history pane))
(dolist (file (active-files frame)) ;; Instead of write-string, we use present so that the link to ;; object file and the semantic information that file is ;; pathname is retained. (present file 'pathname ;; (if (cl-fad:directory-pathname-p file) 'dir-pathname 'pathname) :stream pane) (terpri pane)))
(define-file-browser-command (com-edit-directory :name "Edit Directory") ((dir '(and pathname (satisfies cl-fad:directory-pathname-p)))) ;; the following was a previous attempt to deal with the oddities of ;; CL pathnames. Unfortunately, it does not work properly with all ;; lisp implementations. Because of these oddities, we really need ;; a layer like cl-fad to keep things straight. [2007/01/05:rpg] ;;; (let ((dir (make-pathname :directory (pathname-directory dir) ;;; :name :wild :type :wild :version :wild ;;; :defaults dir))) (setf (active-files *application-frame*) (cl-fad:list-directory dir)))
(define-presentation-to-command-translator pathname-to-edit-command ((and pathname (satisfies cl-fad:directory-pathname-p)) ; source presentation-type com-edit-directory ; target-command file-browser ; command-table :gesture :select ; use this translator for pointer clicks :documentation "Edit this path") ; used in context menu (object) ; argument List (list object)) ; arguments for target-command
(define-file-browser-command (com-quit :name t) () (frame-exit *application-frame*) )
(defmethod adopt-frame :after (frame-manager (frame file-browser)) (declare (ignore frame-manager)) (execute-frame-command frame `(com-edit-directory ,(make-pathname :directory '(:absolute)))))
; LTAG-end
(eval-when (:compile-toplevel) (asdf:oos 'asdf:load-op :clim) (asdf:oos 'asdf:load-op :clim-clx))
(eval-when (:compile-toplevel :load-toplevel :execute) (asdf:oos 'asdf:load-op :cl-fad))
(in-package :clim-user)
; LTAG-start:file-browser-all (define-application-frame file-browser () ((active-files :initform nil :accessor active-files)) (:panes (file-browser :application :display-function '(dirlist-display-files) ;; Call the display-function whenever the command ;; loop makes a ``full-cycle'' :display-time :command-loop) (interactor :interactor)) (:layouts (default (vertically () file-browser interactor))))
(define-presentation-type dir-pathname () :inherit-from 'pathname)
(defmethod dirlist-display-files ((frame file-browser) pane) ;; Clear old displayed entries (clear-output-record (stream-output-history pane))
(dolist (file (active-files frame)) ;; Instead of write-string, we use present so that the link to ;; object file and the semantic information that file is ;; pathname is retained. (present file (if (cl-fad:directory-pathname-p file) 'dir-pathname 'pathname) :stream pane) (terpri pane)))
(define-file-browser-command (com-edit-directory :name "Edit Directory") ((dir 'dir-pathname)) ;; the following was a previous attempt to deal with the oddities of ;; CL pathnames. Unfortunately, it does not work properly with all ;; lisp implementations. Because of these oddities, we really need ;; a layer like cl-fad to keep things straight. [2007/01/05:rpg] ;;; (let ((dir (make-pathname :directory (pathname-directory dir) ;;; :name :wild :type :wild :version :wild ;;; :defaults dir))) (setf (active-files *application-frame*) (cl-fad:list-directory dir)))
(define-presentation-to-command-translator pathname-to-edit-command (dir-pathname ; source presentation-type com-edit-directory ; target-command file-browser ; command-table :gesture :select ; use this translator for pointer clicks :documentation "Edit this path") ; used in context menu (object) ; argument List (list object)) ; arguments for target-command
(define-file-browser-command (com-quit :name t) () (frame-exit *application-frame*) )
(defmethod adopt-frame :after (frame-manager (frame file-browser)) (declare (ignore frame-manager)) (execute-frame-command frame `(com-edit-directory ,(make-pathname :directory '(:absolute)))))
; LTAG-end
Robert Goldman rpgoldman@real-time.com writes:
I made a stab at it, but no, it didn't seem to work. I am attaching two different versions of the file-browser: one that works, using a new presentation-type, dir-pathname, and one that tries to do the job with (and pathname (satisfies cl-fad:directory-pathname-p)), that doesn't work.
It seems that the `and' type doesn't work at all. Try doing (present 2 'integer) and then (accept '(and integer)) - the previous output will not be selectable.