I am using org-mode and org-attach extensively which means that there can be many attachment directories associated with one org file.
On worg I found a function from Matt Lundi which allows to see all attachments that belong to the whole file and browse them with ido.
I would like to restrict this function to a subtree which would make it much more useful for my use case.
Since I am not new to emacs but almost completely elisp illiterate I am asking here.
This is the function:
(defun my-ido-find-org-attach ()
"Find files in org-attachment directory"
(interactive)
(let* ((enable-recursive-minibuffers t)
(files (find-lisp-find-files org-attach-directory "."))
(file-assoc-list
(mapcar (lambda (x)
(cons (file-name-nondirectory x)
x))
files))
(filename-list
(remove-duplicates (mapcar #'car file-assoc-list)
:test #'string=))
(filename (ido-completing-read "Org attachments: " filename-list nil t))
(longname (cdr (assoc filename file-assoc-list))))
(ido-set-current-directory
(if (file-directory-p longname)
longname
(file-name-directory longname)))
(setq ido-exit 'refresh
ido-text-init ido-text
ido-rotate-temp t)
(exit-minibuffer)))
Maybe I'm missing something, but calling org-narrow-to-subtree
first should do what you want (call widen
afterwards to revert that).
I thought this would be pretty darned useful myself so, inspired by your question, I wrote a version that does what you want plus a couple other bells and whistles. To invoke it you have to type C-c o. NOTE: This is NOT on the usual org-attach
key prefix because that function is oddly written without a keymap so it is difficult to add the functionality onto the key prefix.
(autoload 'org-attach-dir "org-attach")
(autoload 'find-lisp-find-files "find-lisp")
(defcustom ido-locate-org-attach-all-files nil
"Non-nil means `ido-locate-org-attach' returns all files.
Otherwise the default behavior only returns files attached to the
current entry."
:group 'ido
:type 'boolean)
(defun ido-locate-org-attach (&optional find-all)
"Find files in org-attachment directory for current entry.
When called with a prefix argument, include all files in
`org-attach-directory'. With a double `C-u' prefix arg the value
of `ido-locate-org-attach-all-files' will be toggled for the
session. If you want to save it permanently for future session
then customize the variable `ido-locate-org-attach-all-files'."
(interactive "P")
(when (org-attach-dir nil)
(when (equal find-all '(16))
(setq ido-locate-org-attach-all-files
(not ido-locate-org-attach-all-files)))
(let* ((enable-recursive-minibuffers t)
(dir (if (org-xor ido-locate-org-attach-all-files
(equal find-all '(4)))
org-attach-directory
(org-attach-dir nil)))
(files (find-lisp-find-files dir "."))
(file-assoc-list
(mapcar (lambda (x)
(cons (file-name-nondirectory x)
x))
files))
(filename-list
(remove-duplicates (mapcar #'car file-assoc-list)
:test #'string=))
(filename (ido-completing-read "Org attachments: " filename-list nil t))
(longname (cdr (assoc filename file-assoc-list))))
(ido-set-current-directory
(if (file-directory-p longname)
longname
(file-name-directory longname)))
(setq ido-exit 'refresh
ido-text-init ido-text
ido-rotate-temp t)
(exit-minibuffer))))
;; Run ido-locate-org-attach when using org-open-at-point (C-c C-o) in
;; the current entry (except if you're on the header line itself it
;; will use the default behavior to open/close the entry.
(add-hook 'org-open-at-point-functions 'ido-locate-org-attach)
;; C-c o will locate files for the current entry
;; C-u C-c o will locate files for the whole file
;; C-u C-u C-c o will toggle the default current entry / whole file
(define-key org-mode-map "\C-co" 'ido-locate-org-attach)
I'll look into submitting this to be an official part of org-attach.el
.
As an aside, the '(4)
and '(16)
are magic numbers that mean prefix arg once C-u and prefix arg twice C-u C-u before the key sequence that invoked the command interactively.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With