2010-04-10 Carsten Dominik <carsten.dominik@gmail.com>
[bpt/emacs.git] / lisp / org / org-archive.el
index dbcceea..b9bd8a4 100644 (file)
@@ -1,11 +1,12 @@
 ;;; org-archive.el --- Archiving for Org-mode
 
-;; Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+;; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010
+;;   Free Software Foundation, Inc.
 
 ;; Author: Carsten Dominik <carsten at orgmode dot org>
 ;; Keywords: outlines, hypermedia, calendar, wp
 ;; Homepage: http://orgmode.org
-;; Version: 6.15a
+;; Version: 6.35i
 ;;
 ;; This file is part of GNU Emacs.
 ;;
 ;;
 ;;; Commentary:
 
-;; This file contains the face definitons for Org.
+;; This file contains the face definitions for Org.
 
 ;;; Code:
 
 (require 'org)
 
+(declare-function org-inlinetask-remove-END-maybe "org-inlinetask" ())
+
+(defcustom org-archive-default-command 'org-archive-subtree
+  "The default archiving command."
+  :group 'org-archive
+  :type '(choice
+         (const org-archive-subtree)
+         (const org-archive-to-archive-sibling)
+         (const org-archive-set-tag)))
+
+(defcustom org-archive-reversed-order nil
+  "Non-nil means make the tree first child under the archive heading, not last."
+  :group 'org-archive
+  :type 'boolean)
+
 (defcustom org-archive-sibling-heading "Archive"
   "Name of the local archive sibling that is used to archive entries locally.
 Locally means: in the tree, under a sibling.
@@ -38,8 +54,8 @@ See `org-archive-to-archive-sibling' for more information."
   :group 'org-archive
   :type 'string)
 
-(defcustom org-archive-mark-done t
-  "Non-nil means, mark entries as DONE when they are moved to the archive file.
+(defcustom org-archive-mark-done nil
+  "Non-nil means mark entries as DONE when they are moved to the archive file.
 This can be a string to set the keyword to use.  When t, Org-mode will
 use the first keyword in its list that means done."
   :group 'org-archive
@@ -49,7 +65,7 @@ use the first keyword in its list that means done."
          (string :tag "Use this keyword")))
 
 (defcustom org-archive-stamp-time t
-  "Non-nil means, add a time stamp to entries moved to an archive file.
+  "Non-nil means add a time stamp to entries moved to an archive file.
 This variable is obsolete and has no effect anymore, instead add or remove
 `time' from the variable `org-archive-save-context-info'."
   :group 'org-archive
@@ -102,18 +118,19 @@ information."
         (t org-archive-location (match-string 1)))))))
 
 (defun org-add-archive-files (files)
-  "Splice the archive files into the list f files.
+  "Splice the archive files into the list of files.
 This implies visiting all these files and finding out what the
 archive file is."
-  (apply
-   'append
-   (mapcar
-    (lambda (f)
-      (if (not (file-exists-p f))
-         nil
-       (with-current-buffer (org-get-agenda-file-buffer f)
-         (cons f (org-all-archive-files)))))
-    files)))
+  (org-uniquify
+   (apply
+    'append
+    (mapcar
+     (lambda (f)
+       (if (not (file-exists-p f))
+          nil
+        (with-current-buffer (org-get-agenda-file-buffer f)
+          (cons f (org-all-archive-files)))))
+     files))))
 
 (defun org-all-archive-files ()
   "Get a list of all archive files used in the current buffer."
@@ -150,7 +167,8 @@ if LOCATION is not given, the value of `org-archive-location' is used."
 if LOCATION is not given, the value of `org-archive-location' is used."
   (setq location (or location org-archive-location))
   (if (string-match "\\(.*\\)::\\(.*\\)" location)
-      (match-string 2 location)))
+      (format (match-string 2 location)
+             (file-name-nondirectory buffer-file-name))))
 
 (defun org-archive-subtree (&optional find-done)
   "Move the current subtree to the archive.
@@ -160,7 +178,7 @@ heading be marked DONE, and the current time will be added.
 
 When called with prefix argument FIND-DONE, find whole trees without any
 open TODO items and archive them (after getting confirmation from the user).
-If the cursor is not at a headline when this comand is called, try all level
+If the cursor is not at a headline when this command is called, try all level
 1 trees.  If the cursor is on a headline, only try the direct children of
 this heading."
   (interactive "P")
@@ -260,14 +278,18 @@ this heading."
                  (end-of-line 0))
                ;; Make the subtree visible
                (show-subtree)
-               (org-end-of-subtree t)
+               (if org-archive-reversed-order
+                   (progn
+                     (org-back-to-heading t)
+                     (outline-next-heading))
+                 (org-end-of-subtree t))
                (skip-chars-backward " \t\r\n")
                (and (looking-at "[ \t\r\n]*")
                     (replace-match "\n\n")))
            ;; No specific heading, just go to end of file.
            (goto-char (point-max)) (insert "\n"))
          ;; Paste
-         (org-paste-subtree (org-get-valid-level level 1))
+         (org-paste-subtree (org-get-valid-level level (and heading 1)))
 
          ;; Mark the entry as done
          (when (and org-archive-mark-done
@@ -290,21 +312,21 @@ this heading."
 
          ;; Save and kill the buffer, if it is not the same buffer.
          (when (not (eq this-buffer buffer))
-           (save-buffer)
-           ;; Check if it is OK to kill the buffer
-           (unless
-               (or visiting
-                   (equal (marker-buffer org-clock-marker) (current-buffer)))
-             (kill-buffer buffer)))
+           (save-buffer))
          ))
       ;; Here we are back in the original buffer.  Everything seems to have
       ;; worked.  So now cut the tree and finish up.
       (let (this-command) (org-cut-subtree))
+      (when (featurep 'org-inlinetask)
+       (org-inlinetask-remove-END-maybe))
       (setq org-markers-to-move nil)
       (message "Subtree archived %s"
               (if (eq this-buffer buffer)
                   (concat "under heading: " heading)
-                (concat "in file: " (abbreviate-file-name afile)))))))
+                (concat "in file: " (abbreviate-file-name afile))))))
+  (org-reveal)
+  (if (looking-at "^[ \t]*$")
+      (outline-next-visible-heading 1)))
 
 (defun org-archive-to-archive-sibling ()
   "Archive the current heading by moving it under the archive sibling.
@@ -342,7 +364,9 @@ sibling does not exist, it will be created at the end of the subtree."
        (beginning-of-line 0)
        (org-toggle-tag org-archive-tag 'on))
       (beginning-of-line 1)
-      (org-end-of-subtree t t)
+      (if org-archive-reversed-order
+         (outline-next-heading)
+       (org-end-of-subtree t t))
       (save-excursion
        (goto-char pos)
        (let ((this-command this-command)) (org-cut-subtree)))
@@ -355,7 +379,10 @@ sibling does not exist, it will be created at the end of the subtree."
       (outline-up-heading 1 t)
       (hide-subtree)
       (org-cycle-show-empty-lines 'folded)
-      (goto-char pos))))
+      (goto-char pos)))
+  (org-reveal)
+  (if (looking-at "^[ \t]*$")
+      (outline-next-visible-heading 1)))
 
 (defun org-archive-all-done (&optional tag)
   "Archive sublevels of the current tree without open TODO items.
@@ -373,7 +400,8 @@ When TAG is non-nil, don't move trees, but mark them with the ARCHIVE tag."
        (progn
          (setq re1 (concat "^" (regexp-quote
                                 (make-string
-                                 (1+ (- (match-end 0) (match-beginning 0) 1))
+                                 (+ (- (match-end 0) (match-beginning 0) 1)
+                                    (if org-odd-levels-only 2 1))
                                  ?*))
                            " "))
          (move-marker begm (point))
@@ -415,6 +443,27 @@ the children that do not contain any open TODO items."
       (and set (beginning-of-line 1))
       (message "Subtree %s" (if set "archived" "unarchived")))))
 
+(defun org-archive-set-tag ()
+  "Set the ARCHIVE tag."
+  (interactive)
+  (org-toggle-tag org-archive-tag 'on))
+
+;;;###autoload
+(defun org-archive-subtree-default ()
+  "Archive the current subtree with the default command.
+This command is set with the variable `org-archive-default-command'."
+  (interactive)
+  (call-interactively org-archive-default-command))
+
+;;;###autoload
+(defun org-archive-subtree-default-with-confirmation ()
+  "Archive the current subtree with the default command.
+This command is set with the variable `org-archive-default-command'."
+  (interactive)
+  (if (y-or-n-p "Archive this subtree or entry? ")
+      (call-interactively org-archive-default-command)
+    (error "Abort")))
+
 (provide 'org-archive)
 
 ;; arch-tag: 0837f601-9699-43c3-8b90-631572ae6c85