First rough outline using folder interface.
authorChris Hanson <org/chris-hanson/cph>
Fri, 14 Jan 2000 22:43:01 +0000 (22:43 +0000)
committerChris Hanson <org/chris-hanson/cph>
Fri, 14 Jan 2000 22:43:01 +0000 (22:43 +0000)
v7/src/imail/imail-top.scm

index c7e610795bd55137784410eded3bfc1afb724648..7be622ec9816138edb7268723576a7feb50e1dd2 100644 (file)
@@ -1,8 +1,8 @@
 ;;; -*-Scheme-*-
 ;;;
-;;; $Id: imail-top.scm,v 1.1 2000/01/04 22:51:05 cph Exp $
+;;; $Id: imail-top.scm,v 1.2 2000/01/14 22:43:01 cph Exp $
 ;;;
-;;; Copyright (c) 1999 Massachusetts Institute of Technology
+;;; Copyright (c) 1999-2000 Massachusetts Institute of Technology
 ;;;
 ;;; This program is free software; you can redistribute it and/or
 ;;; modify it under the terms of the GNU General Public License as
 
 (declare (usual-integrations))
 \f
+(define-variable imail-last-output-url
+  "Last URL used by \\[imail-output]."
+  "umail:xmail"
+  string?)
+
 (define-command imail
-  "Read and edit incoming mail."
-  ()
+  "Read and edit incoming mail.
+May be called with an imail folder URL as argument;
+ then performs imail editing on that folder,
+ but does not copy any new mail into the folder."
   (lambda ()
-    (let ((connection
-          (let ((backend (get-backend (ref-variable imail-backend-type))))
-            (open-connection
-             backend
-             (and (backend-requires-hostname? backend)
-                  (ref-variable imail-backend-server))))))
-      (authenticate-connection connection
-                              (or (ref-variable imail-user-name)
-                                  (current-user-name))
-       (lambda (prompt-string)
-         (call-with-pass-phrase prompt-string string-copy)))
-      (let ((name (ref-variable imail-primary-folder)))
-       (let ((folder (get-folder connection name)))
-         (let ((buffer
-                (or (imail-folder->buffer folder)
-                    (let ((buffer
-                           (new-buffer
-                            (imail-folder-name->buffer-name name))))
-                      (buffer-put! buffer 'IMAIL-FOLDER folder)
-                      (select-message
-                       buffer
-                       (let ((count (count-messages folder)))
-                         (if (= 0 count)
-                             count
-                             (- count 1))))
-                      buffer))))
-           (select-buffer buffer)))))
-    ((ref-command imail-get-new-mail) #f)))
+    (list (and (command-argument)
+              (prompt-for-string "Run imail on folder" #f))))
+  (lambda (url-string)
+    (bind-authenticator imail-authenticator
+      (lambda ()
+       (let* ((url
+               (->url (or url-string (ref-variable imail-primary-folder))))
+              (folder (open-folder url)))
+         (select-buffer
+          (or (imail-folder->buffer folder)
+              (let ((buffer (new-buffer (imail-url->buffer-name url))))
+                (buffer-put! buffer 'IMAIL-FOLDER folder)
+                (select-message buffer (first-unseen-message-index folder))
+                buffer))))))
+    (if (not url-string)
+       ((ref-command imail-get-new-mail) #f))))
+
+(define (imail-authenticator url)
+  (let ((user-name
+        (or (ref-variable imail-user-name)
+            (current-user-name))))
+    (values user-name
+           (call-with-pass-phrase
+            (string-append "Password for user "
+                           user-name
+                           " to access imail folder "
+                           (url->string url))
+            string-copy))))
 
 (define (imail-folder->buffer folder)
-  )
+  (list-search-positive (buffer-list)
+    (lambda (buffer)
+      (eq? folder (buffer-get buffer 'IMAIL-FOLDER #f)))))
 
-(define (imail-folder-name->buffer-name folder)
-  )
+(define (imail-buffer->folder buffer error?)
+  (or (buffer-get buffer 'IMAIL-FOLDER #f)
+      (and error? (error:bad-range-argument buffer 'IMAIL-BUFFER->FOLDER))))
 
+(define (imail-url->buffer-name url)
+  (url-body url))
+
+(define (first-unseen-message-index folder)
+  (let ((n (count-messages folder)))
+    (let loop ((i 0))
+      (if (or (>= i n)
+             (not (message-seen? (get-message folder i))))
+         i
+         (loop (+ i 1))))))
+\f
 (define-command imail-get-new-mail
   "Get new mail from this folder's inbox."
   ()
   (lambda ()
-    (let ((buffer (current-buffer)))
-      (rmail-find-file-revert buffer)
-      (let ((n-messages
-            (let ((memo (buffer-msg-memo buffer)))
-              (if (msg-memo? memo)
-                  (msg-memo/number (msg-memo/last memo))
-                  0))))
-       (with-buffer-open buffer
-         (lambda ()
-           (with-buffer-undo-disabled buffer
-             (lambda ()
-               (get-new-mail buffer
-                             (ref-variable rmail-inbox-list)
-                             #t)))))
-       (show-message
-        buffer
-        (let ((memo (buffer-msg-memo buffer)))
-          (cond ((not (msg-memo? memo)) 0)
-                ((> (msg-memo/number (msg-memo/last memo)) n-messages)
-                 (+ n-messages 1))
-                (else (msg-memo/number memo)))))
-       (event-distributor/invoke! (ref-variable rmail-new-mail-hook))))))
\ No newline at end of file
+    (let ((buffer (selected-buffer)))
+      (let ((folder (imail-buffer->folder buffer #t)))
+       (maybe-revert-folder folder
+         (lambda (folder)
+           (prompt-for-yes-or-no?
+            (string-append
+             "Persistent copy of folder has changed since last read.  "
+             (if (folder-modified? folder)
+                 "Discard your changes"
+                 "Re-read folder")))))
+       (let ((n-new (poll-folder folder)))
+         (cond ((not n-new)
+                (message "(This folder has no associated inbox.)"))
+               ((= 0 n-new)
+                (message "(No new mail has arrived.)"))
+               (else
+                (select-message buffer (- (count-messages folder) n-new))
+                (event-distributor/invoke! (ref-variable imail-new-mail-hook))
+                (message n-new
+                         " new message"
+                         (if (= n-new 1) "" "s")
+                         " read"))))))))
+
+(define-variable imail-new-mail-hook
+  "An event distributor that is invoked when IMAIL incorporates new mail."
+  (make-event-distributor))
+\f
+(define (select-message buffer index)
+  (if (not (exact-nonnegative-integer? index))
+      (error:wrong-type-argument index "exact non-negative integer"
+                                'SELECT-MESSAGE))
+  (let ((folder (imail-buffer->folder buffer #t)))
+    (let ((count (count-messages folder)))
+      (let ((index
+            (cond ((< index count) index)
+                  ((< 0 count) (- count 1))
+                  (else 0))))
+       (buffer-reset! buffer)
+       (buffer-put! buffer 'IMAIL-INDEX index)
+       (let ((mark (mark-left-inserting-copy (buffer-start buffer))))
+         (if (< index count)
+             (let ((message (get-message folder index)))
+               (for-each (lambda (line)
+                           (insert-string line mark)
+                           (insert-newline mark))
+                         (let ((displayed
+                                (get-message-property
+                                 message
+                                 "displayed-header-fields"
+                                 '())))
+                           (if (eq? '() displayed)
+                               (message-header-fields message)
+                               displayed)))
+               (insert-newline mark)
+               (insert-string (message-body message) mark))
+             (insert-string "[This folder has no messages in it.]" mark))
+         (guarantee-newline mark)
+         (mark-temporary! mark))
+       (set-buffer-major-mode! buffer (ref-mode-object imail))))))
+\f
+(define-major-mode imail read-only "IMAIL"
+  "IMAIL Mode is used by \\[imail] for editing IMAIL files.
+All normal editing commands are turned off.
+Instead, these commands are available:
+
+.      Move point to front of this message (same as \\[beginning-of-buffer]).
+SPC    Scroll to next screen of this message.
+DEL    Scroll to previous screen of this message.
+\\[imail-next-undeleted-message]       Move to next non-deleted message.
+\\[imail-previous-undeleted-message]   Move to previous non-deleted message.
+\\[imail-next-message] Move to next message whether deleted or not.
+\\[imail-previous-message]     Move to previous message whether deleted or not.
+\\[imail-last-message] Move to the last message in folder.
+\\[imail-select-message]       Jump to message specified by numeric position in file.
+\\[imail-search]       Search for string and show message it is found in.
+
+\\[imail-delete-forward]       Delete this message, move to next nondeleted.
+\\[imail-delete-backward]      Delete this message, move to previous nondeleted.
+\\[imail-undelete-previous-message]    Undelete message.  Tries current message, then earlier messages
+       until a deleted message is found.
+\\[imail-expunge]      Expunge deleted messages.
+\\[imail-synchronize]  Synchonize the folder with the server.
+       For file folders, synchronizes with the file.
+
+\\[imail-quit]       Quit imail: save, then switch to another buffer.
+
+\\[imail-get-new-mail] Read any new mail from the associated inbox into this folder.
+
+\\[imail-mail] Mail a message (same as \\[mail-other-window]).
+\\[imail-reply]        Reply to this message.  Like \\[imail-mail] but initializes some fields.
+\\[imail-forward]      Forward this message to another user.
+\\[imail-continue]     Continue composing outgoing message started before.
+
+\\[imail-output]       Output this message to a specified folder (append it).
+\\[imail-input]        Append messages from a specified folder.
+
+\\[imail-add-label]    Add label to message.  It will be displayed in the mode line.
+\\[imail-kill-label]   Remove a label from current message.
+\\[imail-next-labeled-message] Move to next message with specified label
+          (label defaults to last one specified).
+          Standard labels:
+           answered, deleted, edited, filed, forwarded, resent, seen.
+          Any other label is present only if you add it with `\\[imail-add-label]'.
+\\[imail-previous-labeled-message]   Move to previous message with specified label.
+
+\\[imail-summary]      Show headers buffer, with a one line summary of each message.
+\\[imail-summary-by-labels]    Like \\[imail-summary] only just messages with particular label(s) are summarized.
+\\[imail-summary-by-recipients]   Like \\[imail-summary] only just messages with particular recipient(s) are summarized.
+
+\\[imail-toggle-header]        Toggle between full headers and reduced headers.
+         Normally only reduced headers are shown.
+\\[imail-edit-current-message] Edit the current message.  C-c C-c to return to Rmail."
+  (lambda (buffer)
+    (local-set-variable! mode-line-modified "--- " buffer)
+    (local-set-variable! imail-last-output-url
+                        (ref-variable imail-last-output-url buffer)
+                        buffer)
+    (buffer-put! buffer 'REVERT-BUFFER-METHOD imail-revert-buffer)
+    (add-kill-buffer-hook buffer imail-kill-buffer)
+    (set-buffer-read-only! buffer)
+    (disable-group-undo! (buffer-group buffer))
+    (event-distributor/invoke! (ref-variable imail-mode-hook buffer) buffer)))
+
+(define-variable imail-mode-hook
+  "An event distributor that is invoked when entering IMAIL mode."
+  (make-event-distributor))
+\f
+(define-key 'imail #\.         'beginning-of-buffer)
+(define-key 'imail #\space     'scroll-up)
+(define-key 'imail #\rubout    'scroll-down)
+(define-key 'imail #\n         'imail-next-undeleted-message)
+(define-key 'imail #\p         'imail-previous-undeleted-message)
+(define-key 'imail #\m-n       'imail-next-message)
+(define-key 'imail #\m-p       'imail-previous-message)
+(define-key 'imail #\j         'imail-select-message)
+(define-key 'imail #\>         'imail-last-message)
+
+(define-key 'imail #\a         'imail-add-label)
+(define-key 'imail #\k         'imail-kill-label)
+(define-key 'imail #\c-m-n     'imail-next-labeled-message)
+(define-key 'imail #\c-m-p     'imail-previous-labeled-message)
+
+(define-key 'imail #\d         'imail-delete-forward)
+(define-key 'imail #\c-d       'imail-delete-backward)
+(define-key 'imail #\u         'imail-undelete-previous-message)
+(define-key 'imail #\x         'imail-expunge)
+
+(define-key 'imail #\s         'imail-synchronize)
+(define-key 'imail #\g         'imail-get-new-mail)
+
+(define-key 'imail #\c-m-h     'imail-summary)
+(define-key 'imail #\c-m-l     'imail-summary-by-labels)
+(define-key 'imail #\c-m-r     'imail-summary-by-recipients)
+
+(define-key 'imail #\m         'imail-mail)
+(define-key 'imail #\r         'imail-reply)
+(define-key 'imail #\c         'imail-continue)
+(define-key 'imail #\f         'imail-forward)
+
+(define-key 'imail #\t         'imail-toggle-header)
+(define-key 'imail #\m-s       'imail-search)
+(define-key 'imail #\o         'imail-output)
+(define-key 'imail #\i         'imail-input)
+(define-key 'imail #\q         'imail-quit)
+(define-key 'imail #\?         'describe-mode)
+(define-key 'imail #\w         'imail-edit-current-message)
+
+(define-key 'imail-edit '(#\c-c #\c-c) 'imail-cease-edit)
+(define-key 'imail-edit '(#\c-c #\c-]) 'imail-abort-edit)
+\f
+(define (imail-revert-buffer buffer dont-use-auto-save? dont-confirm?)
+  )
+
+(define (imail-kill-buffer buffer)
+  )
+
+(define-command imail-input
+  "Append messages to this folder from a specified folder."
+  "sInput from imail folder"
+  (lambda (url-string)
+    ))
+
+(define-command imail-quit
+  )
+
+(define-command imail-synchronize
+  "Synchronize the current folder with the master copy on the server.
+Currently meaningless for file-based folders."
+  ()
+  (lambda ()
+    (synchronize-folder (imail-buffer->folder (selected-buffer) #t))))
+\f
+;;; Edwin Variables:
+;;; scheme-environment: '(edwin)
+;;; scheme-syntax-table: edwin-syntax-table
+;;; End: