summaryrefslogtreecommitdiff
path: root/lisp/org/org-attach.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/org/org-attach.el')
-rw-r--r--lisp/org/org-attach.el154
1 files changed, 72 insertions, 82 deletions
diff --git a/lisp/org/org-attach.el b/lisp/org/org-attach.el
index 1ed305c9ff3..e6aa97e0080 100644
--- a/lisp/org/org-attach.el
+++ b/lisp/org/org-attach.el
@@ -4,7 +4,6 @@
;; Author: John Wiegley <johnw@newartisans.com>
;; Keywords: org data attachment
-
;; This file is part of GNU Emacs.
;;
;; GNU Emacs is free software: you can redistribute it and/or modify
@@ -41,6 +40,8 @@
(require 'org-id)
(declare-function dired-dwim-target-directory "dired-aux")
+(declare-function org-element-property "org-element" (property element))
+(declare-function org-element-type "org-element" (element))
(defgroup org-attach nil
"Options concerning attachments in Org mode."
@@ -129,8 +130,7 @@ Selective means to respect the inheritance setting in
:type '(choice
(const :tag "Don't use inheritance" nil)
(const :tag "Inherit parent node attachments" t)
- (const :tag "Respect org-use-property-inheritance" selective))
- :type 'boolean)
+ (const :tag "Respect org-use-property-inheritance" selective)))
(defcustom org-attach-store-link-p nil
"Non-nil means store a link to a file when attaching it."
@@ -139,7 +139,8 @@ Selective means to respect the inheritance setting in
:type '(choice
(const :tag "Don't store link" nil)
(const :tag "Link to origin location" t)
- (const :tag "Link to the attach-dir location" attached)))
+ (const :tag "Attachment link to the attach-dir location" attached)
+ (const :tag "File link to the attach-dir location" file)))
(defcustom org-attach-archive-delete nil
"Non-nil means attachments are deleted upon archiving a subtree.
@@ -254,16 +255,16 @@ Shows a list of commands and prompts for another key to execute a command."
(get-text-property (point) 'org-marker)))
(unless marker
(error "No item in current line")))
- (save-excursion
- (when marker
- (set-buffer (marker-buffer marker))
- (goto-char marker))
- (org-back-to-heading t)
+ (org-with-point-at marker
+ (org-back-to-heading-or-point-min t)
(save-excursion
(save-window-excursion
(unless org-attach-expert
- (with-output-to-temp-buffer "*Org Attach*"
- (princ
+ (org-switch-to-buffer-other-window "*Org Attach*")
+ (erase-buffer)
+ (setq cursor-type nil
+ header-line-format "Use C-v, M-v, C-n or C-p to navigate.")
+ (insert
(concat "Attachment folder:\n"
(or dir
"Can't find an existing attachment-folder")
@@ -286,11 +287,14 @@ Shows a list of commands and prompts for another key to execute a command."
"Invalid `org-attach-commands' item: %S"
entry))))
org-attach-commands
- "\n"))))))
+ "\n")))))
(org-fit-window-to-buffer (get-buffer-window "*Org Attach*"))
- (message "Select command: [%s]"
- (concat (mapcar #'caar org-attach-commands)))
- (setq c (read-char-exclusive))
+ (let ((msg (format "Select command: [%s]"
+ (concat (mapcar #'caar org-attach-commands)))))
+ (message msg)
+ (while (and (setq c (read-char-exclusive))
+ (memq c '(14 16 22 134217846)))
+ (org-scroll c t)))
(and (get-buffer "*Org Attach*") (kill-buffer "*Org Attach*"))))
(let ((command (cl-some (lambda (entry)
(and (memq c (nth 0 entry)) (nth 1 entry)))
@@ -457,14 +461,6 @@ DIR-property exists (that is different from the unset one)."
"Turn the autotag off."
(org-attach-tag 'off))
-(defun org-attach-store-link (file)
- "Add a link to `org-stored-link' when attaching a file.
-Only do this when `org-attach-store-link-p' is non-nil."
- (setq org-stored-links
- (cons (list (org-attach-expand-link file)
- (file-name-nondirectory file))
- org-stored-links)))
-
(defun org-attach-url (url)
(interactive "MURL of the file to attach: \n")
(let ((org-attach-method 'url))
@@ -491,7 +487,7 @@ METHOD may be `cp', `mv', `ln', `lns' or `url' default taken from
`org-attach-method'."
(interactive
(list
- (read-file-name "File to keep as an attachment:"
+ (read-file-name "File to keep as an attachment: "
(or (progn
(require 'dired-aux)
(dired-dwim-target-directory))
@@ -501,22 +497,30 @@ METHOD may be `cp', `mv', `ln', `lns' or `url' default taken from
(setq method (or method org-attach-method))
(let ((basename (file-name-nondirectory file)))
(let* ((attach-dir (org-attach-dir 'get-create))
- (fname (expand-file-name basename attach-dir)))
+ (attach-file (expand-file-name basename attach-dir)))
(cond
- ((eq method 'mv) (rename-file file fname))
- ((eq method 'cp) (copy-file file fname))
- ((eq method 'ln) (add-name-to-file file fname))
- ((eq method 'lns) (make-symbolic-link file fname))
- ((eq method 'url) (url-copy-file file fname)))
+ ((eq method 'mv) (rename-file file attach-file))
+ ((eq method 'cp) (copy-file file attach-file))
+ ((eq method 'ln) (add-name-to-file file attach-file))
+ ((eq method 'lns) (make-symbolic-link file attach-file))
+ ((eq method 'url) (url-copy-file file attach-file)))
(run-hook-with-args 'org-attach-after-change-hook attach-dir)
(org-attach-tag)
(cond ((eq org-attach-store-link-p 'attached)
- (org-attach-store-link fname))
+ (push (list (concat "attachment:" (file-name-nondirectory attach-file))
+ (file-name-nondirectory attach-file))
+ org-stored-links))
((eq org-attach-store-link-p t)
- (org-attach-store-link file)))
+ (push (list (concat "file:" file)
+ (file-name-nondirectory file))
+ org-stored-links))
+ ((eq org-attach-store-link-p 'file)
+ (push (list (concat "file:" attach-file)
+ (file-name-nondirectory attach-file))
+ org-stored-links)))
(if visit-dir
(dired attach-dir)
- (message "File %S is now an attachment." basename)))))
+ (message "File %S is now an attachment" basename)))))
(defun org-attach-attach-cp ()
"Attach a file by copying it."
@@ -569,13 +573,18 @@ The attachment is created as an Emacs buffer."
(defun org-attach-delete-all (&optional force)
"Delete all attachments from the current outline node.
This actually deletes the entire attachment directory.
-A safer way is to open the directory in dired and delete from there."
+A safer way is to open the directory in dired and delete from there.
+
+With prefix argument FORCE, directory will be recursively deleted
+with no prompts."
(interactive "P")
(let ((attach-dir (org-attach-dir)))
(when (and attach-dir
(or force
(yes-or-no-p "Really remove all attachments of this entry? ")))
- (delete-directory attach-dir (yes-or-no-p "Recursive?") t)
+ (delete-directory attach-dir
+ (or force (yes-or-no-p "Recursive?"))
+ t)
(message "Attachment directory removed")
(run-hook-with-args 'org-attach-after-change-hook attach-dir)
(org-attach-untag))))
@@ -642,37 +651,37 @@ See `org-attach-open'."
Basically, this adds the path to the attachment directory."
(expand-file-name file (org-attach-dir)))
-(defun org-attach-expand-link (file)
- "Return a file link pointing to the current entry's attachment file FILE.
-Basically, this adds the path to the attachment directory, and a \"file:\"
-prefix."
- (concat "file:" (org-attach-expand file)))
+(defun org-attach-expand-links (_)
+ "Expand links in current buffer.
+It is meant to be added to `org-export-before-parsing-hook'."
+ (save-excursion
+ (while (re-search-forward "attachment:" nil t)
+ (let ((link (org-element-context)))
+ (when (and (eq 'link (org-element-type link))
+ (string-equal "attachment"
+ (org-element-property :type link)))
+ (let* ((description (and (org-element-property :contents-begin link)
+ (buffer-substring-no-properties
+ (org-element-property :contents-begin link)
+ (org-element-property :contents-end link))))
+ (file (org-element-property :path link))
+ (new-link (org-link-make-string
+ (concat "file:" (org-attach-expand file))
+ description)))
+ (goto-char (org-element-property :end link))
+ (skip-chars-backward " \t")
+ (delete-region (org-element-property :begin link) (point))
+ (insert new-link)))))))
+
+(defun org-attach-follow (file arg)
+ "Open FILE attachment.
+See `org-open-file' for details about ARG."
+ (org-link-open-as-file (org-attach-expand file) arg))
(org-link-set-parameters "attachment"
- :follow #'org-attach-open-link
- :export #'org-attach-export-link
+ :follow #'org-attach-follow
:complete #'org-attach-complete-link)
-(defun org-attach-open-link (link &optional in-emacs)
- "Attachment link type LINK is expanded with the attached directory and opened.
-
-With optional prefix argument IN-EMACS, Emacs will visit the file.
-With a double \\[universal-argument] \\[universal-argument] \
-prefix arg, Org tries to avoid opening in Emacs
-and to use an external application to visit the file."
- (interactive "P")
- (let (line search)
- (cond
- ((string-match "::\\([0-9]+\\)\\'" link)
- (setq line (string-to-number (match-string 1 link))
- link (substring link 0 (match-beginning 0))))
- ((string-match "::\\(.+\\)\\'" link)
- (setq search (match-string 1 link)
- link (substring link 0 (match-beginning 0)))))
- (if (string-match "[*?{]" (file-name-nondirectory link))
- (dired (org-attach-expand link))
- (org-open-file (org-attach-expand link) in-emacs line search))))
-
(defun org-attach-complete-link ()
"Advise the user with the available files in the attachment directory."
(let ((attach-dir (org-attach-dir)))
@@ -691,26 +700,6 @@ and to use an external application to visit the file."
(t (concat "attachment:" file))))
(error "No attachment directory exist"))))
-(defun org-attach-export-link (link description format)
- "Translate attachment LINK from Org mode format to exported FORMAT.
-Also includes the DESCRIPTION of the link in the export."
- (save-excursion
- (let (path desc)
- (cond
- ((string-match "::\\([0-9]+\\)\\'" link)
- (setq link (substring link 0 (match-beginning 0))))
- ((string-match "::\\(.+\\)\\'" link)
- (setq link (substring link 0 (match-beginning 0)))))
- (setq path (file-relative-name (org-attach-expand link))
- desc (or description link))
- (pcase format
- (`html (format "<a target=\"_blank\" href=\"%s\">%s</a>" path desc))
- (`latex (format "\\href{%s}{%s}" path desc))
- (`texinfo (format "@uref{%s,%s}" path desc))
- (`ascii (format "%s (%s)" desc path))
- (`md (format "[%s](%s)" desc path))
- (_ path)))))
-
(defun org-attach-archive-delete-maybe ()
"Maybe delete subtree attachments when archiving.
This function is called by `org-archive-hook'. The option
@@ -758,6 +747,7 @@ Idea taken from `gnus-dired-attach'."
(add-hook 'org-archive-hook 'org-attach-archive-delete-maybe)
+(add-hook 'org-export-before-parsing-hook 'org-attach-expand-links)
(provide 'org-attach)