diff --git a/CONTRIB/README b/CONTRIB/README index 2e2d039af..1bc49d9d5 100644 --- a/CONTRIB/README +++ b/CONTRIB/README @@ -5,13 +5,35 @@ package. But the git repository for Org-mode is glad to provide useful way to distribute and develop them as long as they are distributed under a free software license. -Please put your contribution in one of these three directories: +Please put your contribution in one of these three directories: lisp, +package, scripts. -LISP - contains emacs-lisp code +LISP (emacs-lisp code) +====================== + +This directory contains emacs-lisp code. + +org-annotate-file.el --- Annotate a file with org syntax +org2rem.el --- Convert org appointments into reminders +org-bibtex.el --- Org links to BibTeX entries +org-depend.el --- TODO dependencies for Org-mode +org-elisp-symbol.el --- Org links to emacs-lisp symbols +org-expiry.el --- expiry mechanism for Org entries +org-irc.el --- Store links to IRC sessions. +org-iswitchb.el --- use iswitchb to select Org buffer +org-man.el --- Support for links to manpages in Org-mode +org-panel.el --- Simple routines for us with bad memory +org-registry.el --- a registry for Org links +org-toc.el --- Table of contents for Org-mode buffer +org-mairix.el --- Hook mairix search into Org for different MUAs -SCRIPTS - contains scripts (shell, bash, python, perl, makefiles, etc.) PACKAGE - contains code requiring more than one file +======= + +org-export-freemind --- exporting utilities from org-mode to freemind + + +SCRIPTS (shell, bash, etc.) +=========================== + diff --git a/CONTRIB/lisp/org-export-freemind.el b/CONTRIB/lisp/org-export-freemind.el deleted file mode 100644 index 58791413a..000000000 --- a/CONTRIB/lisp/org-export-freemind.el +++ /dev/null @@ -1,196 +0,0 @@ -;;; org-export-freemind - exporting utilities from org-mode to freemind - -;; Copyright (C) 2007 Marco Vezzoli - -;; Author: marco vezzoli -;; Created: -;; Version: 0.1.0 -;; Keywords: org-mode export freemind -;; Commentary: - -;; This file is *not* part of GNU Emacs. -;; This program 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 2 of -;; the License, or (at your option) any later version. - -;; This program 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 this program; if not, write to the Free -;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301 USA - -;;; Code: -(defgroup org-export-freemind () - "This group let you customize your own export into freemind format" - :group 'org-export) - -(defcustom org-freemind-icons-alist - '(("TODO" . "button_cancel") - ("SPEC" . "pencil") - ("WIP" . "pencil") - ("TEST" . "xmag") - ("DONE" . "button_ok")) - "change the icon according to a regular expression" - :type '(alist :key-type regexp - :value-type string) - :group 'org-export-freemind) - -(defcustom org-freemind-cloud-alist - '((":PROJECT:" . "ccffcc") - (":MEETING:" . "ccccff")) - "create a cloud with the defined color if title match a regexp" - :type '(alist :key-type regexp :value-type string) - :group 'org-export-freemind) - -(defun org-export-as-freemind (&optional buffer outbuffer) - "Export the org buffer as FreeMind XML. -" - (interactive (list (current-buffer) ())) - ;; A quickie abstraction - - ;; Output everything as FreeMind - (with-current-buffer (get-buffer buffer) - (goto-char (point-min)) ;; CD: beginning-of-buffer is not allowed. - (let* ((opt-plist (org-combine-plists (org-default-export-plist) - (org-infile-export-plist))) - (title (or (plist-get opt-plist :title) - (file-name-sans-extension - (file-name-nondirectory buffer-file-name)))) - (filename (concat (file-name-as-directory - (org-export-directory :xoxo opt-plist)) - title - ".mm")) - (out (if (bufferp outbuffer) - outbuffer - (find-file-noselect filename))) - (last-level 0) - (hanging-li nil)) - - ;; Check the output buffer is empty. - ;; Kick off the output - (unless (bufferp outbuffer) - (progn - (with-current-buffer out (erase-buffer)) - (org-export-as-xoxo-insert-into out "\n"))) - (org-export-as-xoxo-insert-into out - "\n") - (if (bufferp outbuffer) - (org-export-as-xoxo-insert-into out "\n")) - (while (re-search-forward "^\\(\\*+\\) \\(.+\\)" (point-max) 't) - (let* ((hd (match-string-no-properties 1)) - (level (length hd)) - (text (match-string-no-properties 2))) - (save-excursion - (goto-char (match-end 0)) - (catch 'loop - (while 't - (forward-line) - (if (looking-at "^[ \t]\\(.*\\)") - () - (throw 'loop ""))))) - - ;; Handle level rendering - (cond - ((> level last-level) - (let ((rept (- level last-level 1)) - (value ())) - (dotimes (i rept value) - (org-export-as-xoxo-insert-into out "\n"))) - (org-export-as-xoxo-insert-into out "\n" x "")) - text) - "")) - (html-quoted-heading (org-html-expand heading)) - (exp-quote-heading (replace-regexp-in-string "'" """ html-quoted-heading))) - (org-export-as-xoxo-insert-into out exp-quote-heading "'>\n")) - - (dolist (rule org-freemind-icons-alist) - (if (string-match (car rule) text) - (org-export-as-xoxo-insert-into out "\n"))) - (dolist (rule org-freemind-cloud-alist) - (when (string-match (car rule) text) - (progn - (org-export-as-xoxo-insert-into out - "\n") - (message (cdr rule)) - ))) - )) - - ;; Finally finish off the map - (let ((value ())) - (org-export-as-xoxo-insert-into out "\n") - (dotimes (i last-level value) - (org-export-as-xoxo-insert-into out "\n"))) - (org-export-as-xoxo-insert-into out "\n") - - ;; Finish the buffer off and clean it up. - (unless (bufferp outbuffer) - (progn - (org-export-as-xoxo-insert-into out "\n") - (switch-to-buffer-other-window out) - (indent-region (point-min) (point-max) nil) - (save-buffer) - (goto-char (point-min)) - ))))) - -(defun org-export-as-freemind-agenda-files () - "Export all agenda files into Freemind format -each files is saved with .mm extension -into the XOXO publishing directory" - (interactive) - (dolist (file org-agenda-files) - (org-check-agenda-file file) - (set-buffer (org-get-agenda-file-buffer file)) - (org-export-as-freemind (current-buffer)) - )) - -(defun org-export-as-freemind-agenda-files-one-file (filename) - "Export all agenda files into FreeMind format. -All results are grouped in a single .mm file" - (interactive "FFile to save: ") - (let* ((title (file-name-sans-extension - (file-name-nondirectory filename))) - (out (find-file-noselect filename))) - (with-current-buffer out (erase-buffer)) - (org-export-as-xoxo-insert-into out "\n") - (dolist (file org-agenda-files) - (org-check-agenda-file file) - (set-buffer (org-get-agenda-file-buffer file)) - (org-export-as-freemind (current-buffer) out) - ) - (org-export-as-xoxo-insert-into out "\n") - (switch-to-buffer-other-window out) - (indent-region (point-min) (point-max) nil) - (save-buffer) - (goto-char (point-min)) - )) - -(define-key org-mode-map "\C-c\C-xf" 'org-export-as-freemind) -;;; org-export-freemind ends here \ No newline at end of file diff --git a/CONTRIB/lisp/org-mairix.el b/CONTRIB/lisp/org-mairix.el index ede278e7e..22078f999 100644 --- a/CONTRIB/lisp/org-mairix.el +++ b/CONTRIB/lisp/org-mairix.el @@ -1,153 +1,232 @@ -;;; org-mairix.el --- - -;; Copyright 2007 Bastien Guerry +;;; org-mairix.el - Support for hooking mairix search into Org for different MUAs ;; -;; Author: Bastien.Guerry@ens.fr -;; Version: $Id: org-mairix.el,v 0.0 2007/08/11 17:23:40 guerry Exp $ -;; Keywords: -;; X-URL: not distributed yet - -;; This program is free software; you can redistribute it and/or modify +;; Copyright (C) 2007 Georg C. F. Greve +;; +;; Author: Georg C. F. Greve +;; Keywords: outlines, hypermedia, calendar, wp, email, mairix +;; Purpose: Integrate mairix email searching into Org mode +;; See http://orgmode.org and http://www.rpcurnow.force9.co.uk/mairix/ +;; Version: 0.4 +;; +;; This file 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 2, or (at your option) +;; the Free Software Foundation; either version 3, or (at your option) ;; any later version. -;; -;; This program 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. -;; + +;; It 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 this program; if not, write to the Free Software -;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -;;; Commentary: - -;; Code and ideas from Carsten Dominik, Adam Spiers and Georg C. F. Greve. - -;; Put this file into your load-path and the following into your ~/.emacs: -;; (require 'org-mairix) - -;;; Code: +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; USAGE NOTE +;; +;; You will need to configure mairix first, which involves setting up your +;; .mairixrc in your home directory. Once it is working, you should set up +;; your way to display results in your favorite way -- usually a MUA, in my +;; case gnus. +;; +;; After both steps are done, all you should need to hook mairix, org +;; and your MUA together is to do (require 'org-mairix) in your +;; startup file. Everything can then be configured normally through +;; Emacs customisation. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (require 'org) +;;; The custom variables + (defgroup org-mairix nil - "Mairix link support for Org." + "Mairix support/integration in org." :tag "Org Mairix" :group 'org) -(defcustom mairix-results-group "nnmaildir+index:mfolder" - "Gnus groupe where to list mairix search results." +(defcustom org-mairix-threaded-links t + "Should new links be created as threaded links? +If t, links will be stored as threaded searches. +If nil, links will be stored as non-threaded searches." :group 'org-mairix - :type '(string)) + :type 'boolean) -(defun org-add-link-type (type &optional follow publish) - "Add TYPE to the list of `org-link-types'. -Re-compute all regular expressions depending on `org-link-types'." - (add-to-list 'org-link-types type t) - (setq org-link-re-with-space - (concat - "?")) - (setq org-link-re-with-space2 - (concat - "?")) - (setq org-angle-link-re - (concat - "<\\(" (mapconcat 'identity org-link-types "\\|") "\\):" - "\\([^" org-non-link-chars " ]" - "[^" org-non-link-chars "]*" - "\\)>")) - (setq org-plain-link-re - (concat - "\\(" (mapconcat 'identity org-link-types "\\|") "\\):" - "\\([^]\t\n\r<>,;() ]+\\)")) - (setq org-bracket-link-analytic-regexp - (concat - "\\[\\[" - "\\(\\(" (mapconcat 'identity org-link-types "\\|") "\\):\\)?" - "\\([^]]+\\)" - "\\]" - "\\(\\[" "\\([^]]+\\)" "\\]\\)?" - "\\]")) - (add-hook 'org-follow-link-functions follow) - (add-hook 'org-publish-link-functions publish)) +(defcustom org-mairix-augmented-links nil + "Should new links be created as augmenting searches? +If t, links will be stored as augmenting searches. +If nil, links will be stored as normal searches. -(defun org-mairix-follow-link (path) - "Follow a Mairix link." - (require 'gnus) - (funcall (cdr (assq 'gnus org-link-frame-setup))) - (if gnus-other-frame-object (select-frame gnus-other-frame-object)) - (mairix-search path)) +Attention: When activating this option, you will need +to remove old articles from your mairix results group +in some other way, mairix will not do it for you." + :group 'org-mairix + :type 'boolean) -(defun org-mairix-publish-link (path) - "Convert mairix PATH into a (dummy) raw link." - ;; FIXME: should we have a format argument for HTML/LaTeX publishing? - (if (string-match org-bracket-link-analytic-regexp path) - (match-string 5 path) path)) +(defcustom org-mairix-display-hook 'org-mairix-gnus-display-results + "Hook to call to display the results of a successful mairix search. +Defaults to Gnus, feel free to add your own MUAs or methods." + :group 'org-mairix + :type 'hook) -(defun org-mairix-store-link (path) - "Store a mairix link." +(defcustom org-mairix-executable "mairix" + "The mairix executable to call. If your paths are set up +correctly, you should not need to change this." + :group 'org-mairix + :type 'string) + +(defgroup org-mairix-gnus nil + "Use gnus for mairix support in org." + :tag "Org Mairix Gnus" + :group 'org-mairix) + +(defcustom org-mairix-gnus-results-group "nnmaildir:mairix" + "The group that is configured to hold the mairix search results, +which needs to be setup independently of the org-mairix integration, +along with general mairix configuration." + :group 'org-mairix-gnus + :type 'string) + +(defcustom org-mairix-gnus-select-display-group-function 'org-mairix-gnus-select-display-group-function-gg + "Hook to call to select the group that contains the matching articles. +We should not need this, it is owed to a problem of gnus that people were +not yet able to figure out, see + http://article.gmane.org/gmane.emacs.gnus.general/65248 + http://article.gmane.org/gmane.emacs.gnus.general/65265 + http://article.gmane.org/gmane.emacs.gnus.user/9596 +for reference. + +It seems gnus needs a 'forget/ignore everything you think you +know about that group' function. Volunteers?" + :group 'org-mairix-gnus + :type 'hook) + + +;;; The hooks to integrate mairix into org + +(org-add-link-type "mairix" 'org-mairix-open) +(add-hook 'org-store-link-functions 'org-mairix-store-link) + + +;;; Generic org-mairix functions + +(defun org-mairix-store-link () + "Store a link to the current message as a Mairix search for its +Message ID." + + ;; gnus integration (when (memq major-mode '(gnus-summary-mode gnus-article-mode)) - (let* ((group gnus-newsgroup-name) - (article (gnus-summary-article-number)) + (and (eq major-mode 'gnus-article-mode) (gnus-article-show-summary)) + (let* ((article (gnus-summary-article-number)) (header (gnus-summary-article-header article)) (from (mail-header-from header)) (message-id (mail-header-id header)) - (date (mail-header-date header)) (subject (gnus-summary-subject-string))) - (org-store-link-props :type "mairix" - :from from - :subject subject - :message-id message-id - :group group) -;; FIXME: what about cpltxt and link vars we used so far? -;; (setq cpltxt (org-email-link-description)) -;; (setq link (org-make-link "mairix:m:" -;; (substring message-id 1 -1)))))) - (org-make-link "mairix:m:" (substring message-id 1 -1))))) + (org-store-link-props :type "mairix" :from from :subject subject + :message-id message-id) + (setq cpltxt (org-email-link-description)) + (org-store-link-props :link (concat "mairix:" + (if org-mairix-threaded-links "t:") + (if org-mairix-augmented-links "a:") + "@@" (org-remove-angle-brackets message-id)) + :description cpltxt)))) -;; mairix internals -(defun mairix-result-evaluate (string) - "Display search results of previous mairix process." - (let ((mmatches (string-to-number (substring string 7 -8)))) - (if (eq mmatches 0) - (message "Mairix returned no matches, sorry.") - (message "Mairix returned %d matches." mmatches) - (gnus-group-quick-select-group 0 mairix-results-group) - (gnus-summary-reselect-current-group t t)))) +(defun org-mairix-message-send-and-exit-with-link () + "Function that can be assigned as an alternative sending function, +it sends the message and then stores a mairix link to it before burying +the buffer just like 'message-send-and-exit' does." + (interactive) + (message-send) + (let* ((message-id (message-fetch-field "Message-Id")) + (subject (message-fetch-field "Subject")) + (link (concat "mairix:" + (if org-mairix-threaded-links "t:") + (if org-mairix-augmented-links "a:") + "@@" (org-remove-angle-brackets message-id))) + (desc (concat "Email: '" subject "'"))) + (setq org-stored-links + (cons (list link desc) org-stored-links))) + (message-bury (current-buffer))) + +(defun org-mairix-open (path) + "Function to open mairix link. + +We first need to split it into its individual parts, and then +extract the message-id to be passed on to the display function +before call mairix, evaluate the number of matches returned, and +make sure to only call display of mairix succeeded in matching." + (let* ((cmdline org-mairix-executable)) + (if (string< "t:" path) + (progn (setq path (substring path 2 nil)) + (setq cmdline (concat cmdline " --threads")))) + (if (string< "a:" path) + (progn (setq path (substring path 2 nil)) + (setq cmdline (concat cmdline " --augment")))) + (let* ((message-id (substring path 2 nil))) + (setq cmdline (concat cmdline " m:" message-id)) + + (print cmdline) + + (setq retval (shell-command-to-string + (concat cmdline " m:" message-id))) + (string-match "\[0-9\]+" retval) + (setq matches (string-to-number (match-string 0 retval))) + (if (eq matches 0) (message "Link failed: no matches, sorry") + (message "Link returned %d matches" matches) + (run-hook-with-args 'org-mairix-display-hook message-id))))) -(org-add-link-type "mairix" - 'org-mairix-follow-link - 'org-mairix-publish-link) +;;; Functions necessary for gnus integration -(add-hook 'org-store-link-functions 'org-mairix-store-link) +(defun org-mairix-gnus-display-results (message-id) + "Display results of mairix search in Gnus. -(defun mairix-search (string) - "Uses mairix to search through my mail, replacing current search results." - (interactive "MMairix search: ") - (mairix-result-evaluate - (shell-command-to-string (concat "mairix " string)))) +Note: This does not work as cleanly as I would like it to. The +problem being that Gnus should simply reread the group cleanly, +without remembering anything. At the moment it seems to be unable +to do that -- so you're likely to see zombies floating around. + +If you can improve this, please do!" + (require 'gnus) + (require 'gnus-sum) + ;; FIXME: (bzg/gg) We might need to make sure gnus is running here, + ;; and to start it in case it isn't running already. Does + ;; anyone know a function to do that? It seems main org mode + ;; does not do this, either. + (funcall (cdr (assq 'gnus org-link-frame-setup))) + (if gnus-other-frame-object (select-frame gnus-other-frame-object)) + + ;; FIXME: This is horribly broken. Please see + ;; http://article.gmane.org/gmane.emacs.gnus.general/65248 + ;; http://article.gmane.org/gmane.emacs.gnus.general/65265 + ;; http://article.gmane.org/gmane.emacs.gnus.user/9596 + ;; for reference. + ;; + ;; It seems gnus needs a "forget/ignore everything you think you + ;; know about that group" function. Volunteers? + ;; + ;; For now different methods seem to work differently well for + ;; different people. So we're playing hook-selection here to make + ;; it easy to play around until we found a proper solution. + (run-hook-with-args 'org-mairix-gnus-select-display-group-function) + (gnus-summary-select-article + nil t t (car (gnus-find-matching-articles "message-id" message-id)))) (provide 'org-mairix) -(eval-when-compile - (require 'cl)) - - - -;;;;########################################################################## -;;;; User Options, Variables -;;;;########################################################################## - - +(defun org-mairix-gnus-select-display-group-function-gg () + "Georg's hack to select a group that gnus (falsely) believes to be +empty to then call rebuilding of the summary. It leaves zombies of +old searches around, though." + (gnus-group-quick-select-group 0 org-mairix-gnus-results-group) + (gnus-group-clear-data) + (gnus-summary-reselect-current-group t t)) +(defun org-mairix-gnus-select-display-group-function-bzg () + "This is the classic way the org mode is using, and it seems to be +using better for Bastien, so it may work for you." + (gnus-group-clear-data org-mairix-gnus-results-group) + (gnus-group-read-group t nil org-mairix-gnus-results-group)) ;;; org-mairix.el ends here