Cache CONTAINER-URL of every URL when it is created, so that the
authorChris Hanson <org/chris-hanson/cph>
Fri, 25 May 2001 18:16:56 +0000 (18:16 +0000)
committerChris Hanson <org/chris-hanson/cph>
Fri, 25 May 2001 18:16:56 +0000 (18:16 +0000)
heirarchy can be quickly traversed.

Rename URL-IS-SELECTABLE? as FOLDER-URL-IS-SELECTABLE?.

Implement new operation URL-IS-CONTAINER?  which returns the
equivalent container URL of a URL (which may be a folder URL).

v7/src/imail/imail-core.scm
v7/src/imail/imail-file.scm
v7/src/imail/imail-imap.scm
v7/src/imail/imail-top.scm

index bb9fd68c5c7451b6a040c4e3866ca05a7065029a..5aa7bcf589283df0b605ff0972bdc921b60f94e9 100644 (file)
@@ -1,6 +1,6 @@
 ;;; -*-Scheme-*-
 ;;;
-;;; $Id: imail-core.scm,v 1.137 2001/05/25 02:45:29 cph Exp $
+;;; $Id: imail-core.scm,v 1.138 2001/05/25 18:16:48 cph Exp $
 ;;;
 ;;; Copyright (c) 1999-2001 Massachusetts Institute of Technology
 ;;;
 \f
 ;;;; URL type
 
-(define-class <url> (<property-mixin>))
+(define-class <url> (<property-mixin>)
+  (container initial-value 'UNKNOWN))
+
 (define-class <folder-url> (<url>))
 (define-class <container-url> (<url>))
 
 ;; Return #T iff URL represents an existing folder.
 (define-generic url-exists? (url))
 
-;; Return #T iff URL both exists and can be opened.
-(define-generic url-is-selectable? (folder-url))
+;; Return #T iff FOLDER-URL both exists and can be opened.
+(define-generic folder-url-is-selectable? (folder-url))
+
+;; If URL both exists and can contain other resources, return a
+;; container URL for the same resource.  Otherwise return #F.
+(define-generic url-is-container? (url))
+(define-method url-is-container? ((url <container-url>)) url)
 
 ;; Return a locator for the container of URL.  E.g. the container URL
 ;; of "imap://localhost/inbox/foo" is "imap://localhost/inbox/".
 (define-generic container-url (url))
+(add-method container-url (slot-accessor-method <url> 'CONTAINER))
 
 ;; Like CONTAINER-URL except that the returned container URL is
 ;; allowed to be different from the true container URL when this
 ;; Return a URL that refers to the content NAME of the container
 ;; referred to by CONTAINER-URL.
 (define-generic make-content-url (container-url name))
-
+\f
 ;; Return the base name of FOLDER-URL.  This is the content name of
 ;; FOLDER-URL, but presented in a type-independent way.  For example,
 ;; if the content name of a file URL is "foo.mail", the base name is
 ;; mailbox information.  This string will be included in the
 ;; pass-phrase prompt, and also used as a key for memoization.
 (define-generic url-pass-phrase-key (url))
-\f
+
 ;; Convert STRING to a URL.  GET-DEFAULT-URL is a procedure of one
 ;; argument that returns a URL that is used to fill in defaults if
 ;; STRING is a specification for a partial URL.  GET-DEFAULT-URL is
 ;; STRING must cause an error to be signalled.
 (define-generic parse-url-body (string default-url))
 
-(define (intern-url url)
-  (let ((string (url->string url)))
-    (or (hash-table/get interned-urls string #f)
-       (begin
-         (hash-table/put! interned-urls string url)
-         url))))
+(define intern-url
+  (let ((modifier (slot-modifier <url> 'CONTAINER)))
+    (lambda (url compute-container)
+      (let ((string (url->string url)))
+       (or (hash-table/get interned-urls string #f)
+           (begin
+             (let ((finished? #f))
+               (dynamic-wind
+                (lambda ()
+                  (hash-table/put! interned-urls string url))
+                (lambda ()
+                  (modifier url (compute-container url))
+                  (set! finished? #t)
+                  unspecific)
+                (lambda ()
+                  (if (not finished?)
+                      (hash-table/remove! interned-urls string)))))
+             url))))))
 
 (define interned-urls
   (make-string-hash-table))
index 75a9795a6cdf787762a625bcaf34e5096ab85448..aef38b77f9108051e902bd5e1c4b56344d4926b3 100644 (file)
@@ -1,6 +1,6 @@
 ;;; -*-Scheme-*-
 ;;;
-;;; $Id: imail-file.scm,v 1.73 2001/05/25 02:45:33 cph Exp $
+;;; $Id: imail-file.scm,v 1.74 2001/05/25 18:16:51 cph Exp $
 ;;;
 ;;; Copyright (c) 1999-2001 Massachusetts Institute of Technology
 ;;;
@@ -34,7 +34,8 @@
   (let ((procedure
         (let ((constructor (instance-constructor class '(PATHNAME))))
           (lambda (pathname)
-            (intern-url (constructor (merge-pathnames pathname)))))))
+            (intern-url (constructor (merge-pathnames pathname))
+                        pathname-container-url)))))
     (register-pathname-url-constructor class procedure)
     procedure))
 
@@ -48,7 +49,7 @@
 (define pathname-url-constructors
   (make-eq-hash-table))
 
-(define-method container-url ((url <pathname-url>))
+(define (pathname-container-url url)
   (make-directory-url (pathname-container (pathname-url-pathname url))))
 
 (define-method container-url-for-prompt ((url <pathname-url>))
 
 (define pathname-url-predicates '())
 \f
-(define-method url-is-selectable? ((url <pathname-url>))
-  (and (find-pathname-url-constructor (pathname-url-pathname url) #t #f) #t))
-
 (define-method parse-url-body ((string <string>) (default-url <pathname-url>))
   (let ((pathname
         (parse-pathname-url-body string (pathname-url-pathname default-url))))
 (define-method url-exists? ((url <file-url>))
   (file-exists? (pathname-url-pathname url)))
 
+(define-method folder-url-is-selectable? ((url <file-url>))
+  (and (find-pathname-url-constructor (pathname-url-pathname url) #t #f) #t))
+
+(define-method url-is-container? ((url <file-url>))
+  url
+  #f)
+
 (define-method url-base-name ((url <file-url>))
   (pathname-name (pathname-url-pathname url)))
 
   (let ((constructor (instance-constructor <directory-url> '(PATHNAME))))
     (lambda (pathname)
       (intern-url
-       (constructor (pathname-as-directory (merge-pathnames pathname)))))))
+       (constructor (pathname-as-directory (merge-pathnames pathname)))
+       pathname-container-url))))
 
 (register-pathname-url-constructor <directory-url> make-directory-url)
 
index cebc0df76d64d20ddff85f5027dd28bf38f7842d..3b7af5701af2bf47f90c606bfaa1a62da8937d91 100644 (file)
@@ -1,6 +1,6 @@
 ;;; -*-Scheme-*-
 ;;;
-;;; $Id: imail-imap.scm,v 1.163 2001/05/25 02:45:41 cph Exp $
+;;; $Id: imail-imap.scm,v 1.164 2001/05/25 18:16:53 cph Exp $
 ;;;
 ;;; Copyright (c) 1999-2001 Massachusetts Institute of Technology
 ;;;
     (let ((make-folder (instance-constructor <imap-folder-url> fields))
          (make-container (instance-constructor <imap-container-url> fields)))
       (lambda (user-id host port mailbox)
-       (intern-url
-        ((if (or (string-null? mailbox) (string-suffix? "/" mailbox))
-             make-container
-             make-folder)
-         user-id
-         (string-downcase host)
-         port
-         (canonicalize-imap-mailbox mailbox)))))))
+       (intern-url ((if (or (string-null? mailbox)
+                            (string-suffix? "/" mailbox))
+                        make-container
+                        make-folder)
+                    user-id
+                    (string-downcase host)
+                    port
+                    (canonicalize-imap-mailbox mailbox))
+                   imap-container-url)))))
 
 (define (imap-url-new-mailbox url mailbox)
   (make-imap-url (imap-url-user-id url)
 (define-method url-exists? ((url <imap-url>))
   (and (imap-url-info url) #t))
 
-(define-method url-is-selectable? ((url <imap-folder-url>))
+(define-method folder-url-is-selectable? ((url <imap-folder-url>))
   (let ((response (imap-url-info url)))
     (and response
         (not (memq '\NOSELECT (imap:response:list-flags response))))))
 
+(define-method url-is-container? ((url <imap-folder-url>))
+  (let ((response (imap-url-info url)))
+    (and response
+        (not (memq '\NOINFERIORS (imap:response:list-flags response)))
+        (imap-url-new-mailbox url
+                              (string-append (imap-url-mailbox url) "/")))))
+
 (define (imap-url-info url)
   (let ((responses
         (with-open-imap-connection url
 \f
 ;;;; Container heirarchy
 
-(define-method container-url ((url <imap-url>))
+(define (imap-container-url url)
   (imap-url-new-mailbox url
                        (or (imap-url-container-mailbox url)
                            "")))
 (define (imap-mailbox-completions prefix url)
   (with-open-imap-connection url
     (lambda (connection)
-      (map (lambda (response)
-            (let ((flags (imap:response:list-flags response))
-                  (delimiter (imap:response:list-delimiter response))
-                  (mailbox
-                   (imap:decode-mailbox-name
-                    (imap:response:list-mailbox response))))
-              (if delimiter
-                  (let ((mailbox
-                         (string-replace mailbox
-                                         (string-ref delimiter 0)
-                                         #\/)))
-                    (if (and (memq '\NOSELECT flags)
-                             (not (memq '\NOINFERIORS flags)))
-                        (string-append mailbox "/")
-                        mailbox))
-                  mailbox)))
-          (imap:command:list
-           connection
-           ""
-           (string-append (imap-mailbox/url->server url prefix) "%"))))))
+      (append-map! (lambda (response)
+                    (let ((flags (imap:response:list-flags response))
+                          (delimiter (imap:response:list-delimiter response))
+                          (mailbox
+                           (imap:decode-mailbox-name
+                            (imap:response:list-mailbox response))))
+                      (if delimiter
+                          (let ((mailbox
+                                 (string-replace mailbox
+                                                 (string-ref delimiter 0)
+                                                 #\/)))
+                            (if (memq '\NOSELECT flags)
+                                (if (memq '\NOINFERIORS flags)
+                                    '()
+                                    (list (string-append mailbox "/")))
+                                (list mailbox)))
+                          (list mailbox))))
+                  (imap:command:list
+                   connection
+                   ""
+                   (string-append (imap-mailbox/url->server url prefix)
+                                  "%"))))))
 \f
 ;;;; URL->server delimiter conversion
 
index 271cec45cf98fe2c5f24246c661892b65f8b069b..2dd5ddaec844997d5be36eb0a93ba3c8718c2232 100644 (file)
@@ -1,6 +1,6 @@
 ;;; -*-Scheme-*-
 ;;;
-;;; $Id: imail-top.scm,v 1.251 2001/05/25 02:45:51 cph Exp $
+;;; $Id: imail-top.scm,v 1.252 2001/05/25 18:16:56 cph Exp $
 ;;;
 ;;; Copyright (c) 1999-2001 Massachusetts Institute of Technology
 ;;;
@@ -1660,7 +1660,7 @@ Negative argument means search in reverse."
   (%prompt-for-url prompt default options
                   (lambda (url)
                     (and (folder-url? url)
-                         (url-is-selectable? url)))))
+                         (folder-url-is-selectable? url)))))
 
 (define (prompt-for-container prompt default . options)
   (%prompt-for-url prompt default options