1
0
mirror of https://git.savannah.gnu.org/git/emacs/org-mode.git synced 2024-11-29 07:58:21 +00:00
org-mode/lisp/org-vm.el
Bastien Guerry ecd0562c5f Fix the master branch.
I started from the 78ec8e commit then cherry-picked and squashed
commits that have been done in master since then, except the bad
commits that overwrote the tree (in master) with the tree in maint.

This commit also bumps the version number to 7.8.06.

The only "fix" that was made between 78ec8e and the previous commit
is e0072f which has been reported to break stuff.
2012-03-19 22:01:29 +01:00

181 lines
7.1 KiB
EmacsLisp

;;; org-vm.el --- Support for links to VM messages from within Org-mode
;; Copyright (C) 2004-2012 Free Software Foundation, Inc.
;; Author: Carsten Dominik <carsten at orgmode dot org>
;; Keywords: outlines, hypermedia, calendar, wp
;; Homepage: http://orgmode.org
;;
;; Support for IMAP folders added
;; by Konrad Hinsen <konrad dot hinsen at fastmail dot net>
;; Requires VM 8.2.0a or later.
;;
;; This file is part of GNU Emacs.
;;
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;;; Commentary:
;; This file implements links to VM messages and folders from within Org-mode.
;; Org-mode loads this module by default - if this is not what you want,
;; configure the variable `org-modules'.
;;; Code:
(require 'org)
;; Declare external functions and variables
(declare-function vm-preview-current-message "ext:vm-page" ())
(declare-function vm-follow-summary-cursor "ext:vm-motion" ())
(declare-function vm-get-header-contents "ext:vm-summary"
(message header-name-regexp &optional clump-sep))
(declare-function vm-isearch-narrow "ext:vm-search" ())
(declare-function vm-isearch-update "ext:vm-search" ())
(declare-function vm-select-folder-buffer "ext:vm-macro" ())
(declare-function vm-su-message-id "ext:vm-summary" (m))
(declare-function vm-su-subject "ext:vm-summary" (m))
(declare-function vm-summarize "ext:vm-summary" (&optional display raise))
(declare-function vm-imap-folder-p "ext:vm-save" ())
(declare-function vm-imap-find-spec-for-buffer "ext:vm-imap" (buffer))
(declare-function vm-imap-folder-for-spec "ext:vm-imap" (spec))
(declare-function vm-imap-parse-spec-to-list "ext:vm-imap" (spec))
(declare-function vm-imap-spec-for-account "ext:vm-imap" (account))
(defvar vm-message-pointer)
(defvar vm-folder-directory)
;; Install the link type
(org-add-link-type "vm" 'org-vm-open)
(org-add-link-type "vm-imap" 'org-vm-imap-open)
(add-hook 'org-store-link-functions 'org-vm-store-link)
;; Implementation
(defun org-vm-store-link ()
"Store a link to a VM folder or message."
(when (and (or (eq major-mode 'vm-summary-mode)
(eq major-mode 'vm-presentation-mode))
(save-window-excursion
(vm-select-folder-buffer) buffer-file-name))
(and (eq major-mode 'vm-presentation-mode) (vm-summarize))
(vm-follow-summary-cursor)
(save-excursion
(vm-select-folder-buffer)
(let* ((message (car vm-message-pointer))
(subject (vm-su-subject message))
(to (vm-get-header-contents message "To"))
(from (vm-get-header-contents message "From"))
(message-id (vm-su-message-id message))
(link-type (if (vm-imap-folder-p) "vm-imap" "vm"))
(date (vm-get-header-contents message "Date"))
(date-ts (and date (format-time-string
(org-time-stamp-format t)
(date-to-time date))))
(date-ts-ia (and date (format-time-string
(org-time-stamp-format t t)
(date-to-time date))))
folder desc link)
(if (vm-imap-folder-p)
(let ((spec (vm-imap-find-spec-for-buffer (current-buffer))))
(setq folder (vm-imap-folder-for-spec spec)))
(progn
(setq folder (abbreviate-file-name buffer-file-name))
(if (and vm-folder-directory
(string-match (concat "^" (regexp-quote vm-folder-directory))
folder))
(setq folder (replace-match "" t t folder)))))
(setq message-id (org-remove-angle-brackets message-id))
(org-store-link-props :type link-type :from from :to to :subject subject
:message-id message-id)
(when date
(org-add-link-props :date date :date-timestamp date-ts
:date-timestamp-inactive date-ts-ia))
(setq desc (org-email-link-description))
(setq link (org-make-link (concat link-type ":") folder "#" message-id))
(org-add-link-props :link link :description desc)
link))))
(defun org-vm-open (path)
"Follow a VM message link specified by PATH."
(let (folder article)
(if (not (string-match "\\`\\([^#]+\\)\\(#\\(.*\\)\\)?" path))
(error "Error in VM link"))
(setq folder (match-string 1 path)
article (match-string 3 path))
;; The prefix argument will be interpreted as read-only
(org-vm-follow-link folder article current-prefix-arg)))
(defun org-vm-follow-link (&optional folder article readonly)
"Follow a VM link to FOLDER and ARTICLE."
(require 'vm)
(setq article (org-add-angle-brackets article))
(if (string-match "^//\\([a-zA-Z]+@\\)?\\([^:]+\\):\\(.*\\)" folder)
;; ange-ftp or efs or tramp access
(let ((user (or (match-string 1 folder) (user-login-name)))
(host (match-string 2 folder))
(file (match-string 3 folder)))
(cond
((featurep 'tramp)
;; use tramp to access the file
(if (featurep 'xemacs)
(setq folder (format "[%s@%s]%s" user host file))
(setq folder (format "/%s@%s:%s" user host file))))
(t
;; use ange-ftp or efs
(require (if (featurep 'xemacs) 'efs 'ange-ftp))
(setq folder (format "/%s@%s:%s" user host file))))))
(when folder
(funcall (cdr (assq 'vm org-link-frame-setup)) folder readonly)
(when article
(org-vm-select-message (org-add-angle-brackets article)))))
(defun org-vm-imap-open (path)
"Follow a VM link to an IMAP folder"
(require 'vm-imap)
(when (string-match "\\([^:]+\\):\\([^#]+\\)#?\\(.+\\)?" path)
(let* ((account-name (match-string 1 path))
(mailbox-name (match-string 2 path))
(message-id (match-string 3 path))
(account-spec (vm-imap-parse-spec-to-list
(vm-imap-spec-for-account account-name)))
(mailbox-spec (mapconcat 'identity
(append (butlast account-spec 4)
(cons mailbox-name
(last account-spec 3)))
":")))
(funcall (cdr (assq 'vm-imap org-link-frame-setup))
mailbox-spec)
(when message-id
(org-vm-select-message (org-add-angle-brackets message-id))))))
(defun org-vm-select-message (message-id)
"Go to the message with message-id in the current folder."
(require 'vm-search)
(sit-for 0.1)
(vm-select-folder-buffer)
(widen)
(let ((case-fold-search t))
(goto-char (point-min))
(if (not (re-search-forward
(concat "^" "message-id: *" (regexp-quote message-id))))
(error "Could not find the specified message in this folder"))
(vm-isearch-update)
(vm-isearch-narrow)
(vm-preview-current-message)
(vm-summarize)))
(provide 'org-vm)
;;; org-vm.el ends here