diff --git a/ORGWEBPAGE/Changes.org b/ORGWEBPAGE/Changes.org index bd8bb3610..5d0d0f2a3 100644 --- a/ORGWEBPAGE/Changes.org +++ b/ORGWEBPAGE/Changes.org @@ -26,6 +26,21 @@ empty except for the colon. ** Details +*** The attachment directory may now be chosen by the user + + Instead of using the automatic, unique directory related to + the entry ID, you can also use a chosen directory for the + attachments of an entry. This directory is specified by the + ATTACH_DIR property. You can use `C-c C-a s' to set this + property. + +*** You can use a single attachment directory for a subtree + + By setting the property ATTACH_DIR_INHERIT, you can now tell + Org that children of the entry should use the same directory + for attachments, unless a child explicitly defines its own + directory with the ATTACH_DIR property. You can use the + command `C-c C-a i' to set this property in an entry. *** Better handling of inlined images in different backends diff --git a/doc/org.texi b/doc/org.texi index 762e7bc24..7ad219830 100644 --- a/doc/org.texi +++ b/doc/org.texi @@ -5410,6 +5410,11 @@ to contain an absolute path.}. If you initialize this directory with @code{git-init}, Org will automatically commit changes when it sees them. The attachment system has been contributed to Org by John Wiegley. +In cases where this seems better, you can also attach a directory of your +choice to an entry. You can also make children inherit the attachment +directory from a parent, so that an entire subtree uses the same attached +directory. + @noindent The following commands deal with attachments. @table @kbd @@ -5470,6 +5475,16 @@ Select and delete a single attachment. @item D Delete all of a task's attachments. A safer way is to open the directory in dired and delete from there. + +@kindex C-c C-a s +@item C-c C-a s +Set a specific directory as the entry's attachment directory. This works by +putting the directory path into the @code{ATTACH_DIR} property. + +@kindex C-c C-a i +@item C-c C-a i +Set the @code{ATTACH_DIR_INHERIT} property, so that children will use the +same directory for attachments as the parent. @end table @end table diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 7357c6bef..ab9d55427 100755 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,13 @@ +2009-01-19 Carsten Dominik + + * org-attach.el (org-attach-allow-inheritance): New option. + (org-attach-inherited): New variable. + (org-attach-dir): Handle properties related to the attachment + directory. + (org-attach-check-absolute-path): New function. + (org-attach-set-directory, org-attach-set-inherit): New commands. + (org-attach): Accommodate the new commands in the dispatcher. + 2009-01-18 Carsten Dominik * org-compat.el (org-fit-window-to-buffer): Fix bug with using diff --git a/lisp/org-attach.el b/lisp/org-attach.el index a1ce91d8a..b2ca106fc 100644 --- a/lisp/org-attach.el +++ b/lisp/org-attach.el @@ -64,7 +64,9 @@ where the Org file lives." (defcustom org-attach-file-list-property "Attachments" "The property used to keep a list of attachment belonging to this entry. -This is not really needed, so you may set this to nil if you don't want it." +This is not really needed, so you may set this to nil if you don't want it. +Also, for entries where children inherit the directory, the list of +attachments is not kept in this property." :group 'org-attach :type '(choice (const :tag "None" nil) @@ -89,6 +91,15 @@ ln create a hard link. Note that this is not supported :group 'org-attach :type 'boolean) +(defcustom org-attach-allow-inheritance t + "Non-nil means, allow attachment directories be inherited." + :group 'org-attach + :type 'boolean) + + +(defvar org-attach-inherited nil + "Indicates if the last access to the attachment directory was inherited.") + ;;;###autoload (defun org-attach () "The dispatcher for attachment commands. @@ -124,7 +135,10 @@ F Like \"f\", but force using dired in Emacs. d Delete one attachment, you will be prompted for a file name. D Delete all of a task's attachments. A safer way is - to open the directory in dired and delete from there."))) + to open the directory in dired and delete from there. + +s Set a specific attachment directory for this entry. +i Make children of the current entry inherit its attachment directory."))) (org-fit-window-to-buffer (get-buffer-window "*Org Attach*")) (message "Select command: [acmlzoOfFdD]") (setq c (read-char-exclusive)) @@ -147,29 +161,81 @@ D Delete all of a task's attachments. A safer way is 'org-attach-delete-one)) ((eq c ?D) (call-interactively 'org-attach-delete-all)) ((eq c ?q) (message "Abort")) + ((memq c '(?s ?\C-s)) (call-interactively + 'org-attach-set-directory)) + ((memq c '(?i ?\C-i)) (call-interactively + 'org-attach-set-inherit)) (t (error "No such attachment command %c" c)))))) (defun org-attach-dir (&optional create-if-not-exists-p) "Return the directory associated with the current entry. +This first checks for a local property ATTACH_DIR, and then for an inherited +property ATTACH_DIR_INHERIT. If neither exists, the default mechanism +using the entry ID will be invoked to access the unique directory for the +current entry. If the directory does not exist and CREATE-IF-NOT-EXISTS-P is non-nil, -the directory and the corresponding ID will be created." - (when (and (not (buffer-file-name (buffer-base-buffer))) - (not (file-name-absolute-p org-attach-directory))) - (error "Need absolute `org-attach-directory' to attach in buffers without filename.")) - (let ((uuid (org-id-get (point) create-if-not-exists-p))) - (when (or uuid create-if-not-exists-p) - (unless uuid - (error "ID retrieval/creation failed")) - (let ((attach-dir (expand-file-name - (format "%s/%s" - (substring uuid 0 2) - (substring uuid 2)) - (expand-file-name org-attach-directory)))) - (if (and create-if-not-exists-p - (not (file-directory-p attach-dir))) - (make-directory attach-dir t)) - (and (file-exists-p attach-dir) - attach-dir))))) +the directory and (if necessary) the corresponding ID will be created." + (let (attach-dir uuid inherit) + (setq org-attach-inherited (org-entry-get nil "ATTACH_DIR_INHERIT")) + (cond + ((setq attach-dir (org-entry-get nil "ATTACH_DIR")) + (org-attach-check-absolute-path attach-dir)) + ((and org-attach-allow-inheritance + (setq inherit (org-entry-get nil "ATTACH_DIR_INHERIT" t))) + (setq attach-dir + (save-excursion + (save-restriction + (widen) + (goto-char org-entry-property-inherited-from) + (let (org-attach-allow-inheritance) + (org-attach-dir create-if-not-exists-p))))) + (org-attach-check-absolute-path attach-dir) + (setq org-attach-inherited t)) + (t ; use the ID + (org-attach-check-absolute-path nil) + (setq uuid (org-id-get (point) create-if-not-exists-p)) + (when (or uuid create-if-not-exists-p) + (unless uuid (error "ID retrieval/creation failed")) + (setq attach-dir (expand-file-name + (format "%s/%s" + (substring uuid 0 2) + (substring uuid 2)) + (expand-file-name org-attach-directory)))))) + (when attach-dir + (if (and create-if-not-exists-p + (not (file-directory-p attach-dir))) + (make-directory attach-dir t)) + (and (file-exists-p attach-dir) + attach-dir)))) + +(defun org-attach-check-absolute-path (dir) + "Check if we have enough information to root the atachment directory. +When DIR is given, check also if it is already absolute. Otherwise, +assume that it will be relative, and check if `org-attach-directory' is +absolute, or if at least the current buffer has a file name. +Throw an error if we cannot root the directory." + (or (and dir (file-name-absolute-p dir)) + (file-name-absolute-p org-attach-directory) + (buffer-file-name (buffer-base-buffer)) + (error "Need absolute `org-attach-directory' to attach in buffers without filename."))) + +(defun org-attach-set-directory () + "Set the ATTACH_DIR property of the current entry. +The property defines the directory that is used for attachments +of the entry." + (interactive) + (let ((dir (org-entry-get nil "ATTACH_DIR"))) + (setq dir (read-directory-name "Attachment directory: " dir)) + (org-entry-put nil "ATTACH_DIR" dir))) + +(defun org-attach-set-inherit () + "Set the ATTACH_DIR_INHERIT property of the current entry. +The property defines the directory that is used for attachments +of the entry and any children that do not explicitly define (by setting +the ATTACH_DIR property) their own attachment directory." + (interactive) + (org-entry-put nil "ATTACH_DIR_INHERIT" "t") + (message "Children will inherit attachment directory")) (defun org-attach-commit () "Commit changes to git if `org-attach-directory' is properly initialized. @@ -200,7 +266,7 @@ METHOD may be `cp', `mv', or `ln', default taken from `org-attach-method'." (interactive "fFile to keep as an attachment: \nP") (setq method (or method org-attach-method)) (let ((basename (file-name-nondirectory file))) - (when org-attach-file-list-property + (when (and org-attach-file-list-property (not org-attach-inherited)) (org-entry-add-to-multivalued-property (point) org-attach-file-list-property basename)) (let* ((attach-dir (org-attach-dir t)) @@ -234,7 +300,7 @@ On some systems, this apparently does copy the file instead." "Create a new attachment FILE for the current task. The attachment is created as an Emacs buffer." (interactive "sCreate attachment named: ") - (when org-attach-file-list-property + (when (and org-attach-file-list-property (not org-attach-inherited)) (org-entry-add-to-multivalued-property (point) org-attach-file-list-property file)) (let ((attach-dir (org-attach-dir t))) @@ -263,7 +329,7 @@ The attachment is created as an Emacs buffer." This actually deletes the entire attachment directory. A safer way is to open the directory in dired and delete from there." (interactive "P") - (when org-attach-file-list-property + (when (and org-attach-file-list-property (not org-attach-inherited)) (org-entry-delete (point) org-attach-file-list-property)) (let ((attach-dir (org-attach-dir))) (when @@ -280,7 +346,7 @@ A safer way is to open the directory in dired and delete from there." This can be used after files have been added externally." (interactive) (org-attach-commit) - (when org-attach-file-list-property + (when (and org-attach-file-list-property (not org-attach-inherited)) (org-entry-delete (point) org-attach-file-list-property)) (let ((attach-dir (org-attach-dir))) (when attach-dir