From: "Gustav Wikström" <gustav@whil.se>
To: Nicolas Goaziou <mail@nicolasgoaziou.fr>
Cc: emacs-orgmode <emacs-orgmode@gnu.org>
Subject: Re: [RFC] Link-type for attachments, more attach options
Date: Sun, 25 Nov 2018 21:13:00 +0000 [thread overview]
Message-ID: <PR1PR02MB4732B95D15A405B39B6D039DDAD60@PR1PR02MB4732.eurprd02.prod.outlook.com> (raw)
In-Reply-To: <877eh8vd52.fsf_-_@nicolasgoaziou.fr>
[-- Attachment #1: Type: text/plain, Size: 18838 bytes --]
Hi again,
> -----Original Message-----
> From: Nicolas Goaziou <mail@nicolasgoaziou.fr>
> Sent: den 20 november 2018 00:52
> To: Gustav Wikström <gustav@whil.se>
> Cc: Org Mode List <emacs-orgmode@gnu.org>
> Subject: Re: [RFC] Link-type for attachments, more attach options
>
> > Yeah - I liked "attached" because I prefer clear keywords. But sure,
> > we can keep it shorter. I'd suggest "@" instead in that case. Patch
> > updated with that.
>
> "@" syntax is a reserved syntax for citations in the "wip-cite" branch.
> I'd rather not use it here. Also, years ago, "att" link type was used to
> link to attachments, hence my proposal.
Too bad, "@" was growing on me. @ is currently automatically set as a tag when attaching files to nodes. So it was fitting to use it also in links in my opinion. Is the cite-syntax the same as the regular link-pattern? [[@: ...]] ? Otherwise I'd suggest them to coexist. Or to change the cite-symbol to ... "c" maybe? @ is a pretty standard symbol for attachments. Just have a look at Gmail, Outlook etc.
I didn't change this in the attached patch. I'm hoping for second thoughts! :) The future ease of use (i.e. clarity and standardization of symbols in this case) should have precedence over current work in progress...
> >> > When working with ATTACH_DIR there are now a couple of new options available:
> >> > - org-attach-dir-inherit-by-default
> >>
> >> What is the difference between this and
> >> `org-attach-allow-inheritance'?
>
> You didn't answer this question, did you?
No, seems I missed it.
> Something is fishy here anyways. Why is "ATTACH_DIR_INHERIT" needed at
> all? If `org-attach-allow-inheritance', "ATTACH_DIR" should be
> inherited. Why depend on another property?
Yeah, I don't know why it's configured like that from the start. A bit convoluted. Not sure of what way to go forward though. I can see at least two paths:
1) Rename `org-attach-allow-inheritance' to `org-attach-enable-inheritance' and always make attachments inherited when that is set to "t". Deprecate "ATTACH_DIR_INHERIT". With this I'd also change the precedence-logic between ATTACH_DIR & ID properties and make ID-based attachment inherit as well. The properties ATTACH_DIR and ID should be inherited from the closest node when resolving attachments, with ATTACH_DIR having precedence over ID if both exist for the same node.
2) remove `org-attach-allow-inheritance' and only rely on the "ATTACH_DIR_INHERIT" property of any of the parent nodes to decide if the "ATTACH_DIR" property should be inherited. This would be a smaller change from the user's perspective, where we're basically saying you cannot disable inheritance, but it's only active when a node has the ATTACH_DIR_INHERIT-property.
I prefer path (1). That would be a great default. But that change is bigger and should be separated from this patch anyways. To not increase the complexity I've removed the `org-attach-dir-inherit-by-default' customization.
> >> > - org-attach-dir-create-if-not-exist
> >>
> >> What is the use-case for this one? It doesn't seem terribly useful at
> >> first glance.
> >
> > If you try to open attachments on a node where there is no ID or
> >> ATTACH_DIR, the default behavior is to add an ID and create a folder
> >> based on that ID. I would like Org-mode to not do that. This
> >> customization give the user the option to change that. Instead of
> >> providing this customization one could just change the default
> >> behavior of org-attach, since it's a bit offensive to create folders
> >> when I didn't ask for it. But instead of changing the default,
> >> I thought this way was more graceful. I wouldn't mind skipping this
> >> customization though, if the behavior was changed to what
> >> I implemented with org-attach-dir-create-if-not-exist set to nil.
>
> Considering attaching is about moving, or copying files somewhere,
> creating a folder doesn't sound terribly offensive. You don't even have
> to know the name of the folder.
>
> Do you suggest to raise an error if there is no folder available for the
> attached documents? If so, wouldn't it be better to ask the user first?
Agreed, the parameter can be removed and a "do you want to create a folder?" question could be raised instead, when it's not intuitive for the program to create the folder by itself.
> >> > +This list shows the full set of built-in external link types:
> >> > +| http | web |
> >> > +| https | secure web |
> >> > +| doi | DOI for electronic resources |
> >> > +| file | file-links |
> >> > +| file+sys | file-links forced to open via OS |
> >> > +| file+emacs | file-links forced to open via emacs |
> >> > +| attached | links to attachments for nodes |
> >> > +| docview | doc-view mode |
> >> > +| id | Link to heading by id |
> >> > +| news | Usenet link |
> >> > +| mailto | mail link |
> >> > +| mhe | MH-E folder link |
> >> > +| rmail | Rmail link |
> >> > +| gnus | Gnus link |
> >> > +| bbdb | BBDB link |
> >> > +| irc | IRC link |
> >> > +| info | Info link |
> >> > +| shell | shell command |
> >> > +| elisp | interactive elisp command link |
> >> > +
> >> > +The following list shows examples for each link type.
> >> > +
> >> > +| =http://www.astro.uva.nl/=dominik= | on the web |
> >> > +| =doi:10.1000/182= | DOI for an electronic resource |
> >> > +| =file:/home/dominik/images/jupiter.jpg= | file, absolute path |
> >> > +| =/home/dominik/images/jupiter.jpg= | same as above |
> >> > +| =file:papers/last.pdf= | file, relative path |
> >> > +| =./papers/last.pdf= | same as above |
> >> > +| =file:/ssh:me@some.where:papers/last.pdf= | file, path on remote machine |
> >> > +| =/ssh:me@some.where:papers/last.pdf= | same as above |
> >> > +| =file:sometextfile::NNN= | file, jump to line number |
> >> > +| =file:projects.org= | another Org file |
> >> > +| =file:projects.org::some words= | text search in Org file[fn:28] |
> >> > +| =file:projects.org::*task title= | heading search in Org file |
> >> > +| =file+sys:/path/to/file= | open via OS, like double-click |
> >> > +| =file+emacs:/path/to/file= | force opening by Emacs |
> >> > +| =attached:projects.org= | file in folder attached to headline |
> >> > +| =attached:projects.org::some words= | text search in attached file |
> >> > +| =docview:papers/last.pdf::NNN= | open in doc-view mode at page |
> >> > +| =id:B7423F4D-2E8A-471B-8810-C40F074717E9= | link to heading by ID |
> >> > +| =news:comp.emacs= | Usenet link |
> >> > +| =mailto:adent@galaxy.net= | mail link |
> >> > +| =mhe:folder= | MH-E folder link |
> >> > +| =mhe:folder#id= | MH-E message link |
> >> > +| =rmail:folder= | Rmail folder link |
> >> > +| =rmail:folder#id= | Rmail message link |
> >> > +| =gnus:group= | Gnus group link |
> >> > +| =gnus:group#id= | Gnus article link |
> >> > +| =bbdb:R.*Stallman= | BBDB link (with regexp) |
> >> > +| =irc:/irc.com/#emacs/bob= | IRC link |
> >> > +| =info:org#External links= | Info node link |
> >> > +| =shell:ls *.org= | shell command |
> >> > +| =elisp:org-agenda= | interactive Elisp command |
> >> > +| =elisp:(find-file "Elisp.org")= | Elisp form to evaluate |
> >>
> >> I'm not sure to like the change above. It introduces a lot of
> >> redundancy.
> >>
> >
> > Currently the list in the documentation is just a bunch of examples.
> >> I've looked at it a couple of times asking myself "What is the
> >> complete list of built in link types?". This commit "fixes" that.
> >> I wouldn't say its redundant since all the rows in the second list
> >> are just examples.
>
> It is still redundant. For example, the first table has
>
> | info | Info link |
>
> whereas the second one tells us
>
> | info:org#External links | Info node link |
>
> In this case,
>
> | Info link | info:org#External links |
>
> would be sufficient enough. I have the feeling documentation can be
> improved here.
The problem I had with the second list is that it's just a list of examples. Nowhere does it say it's the complete list of commands. Anyways, I've tried to merge the two lists. Hope you'll find it more to your liking.
>
> Also, file+sys and file+emacs are deprecated. They can be removed.
Ok, removed.
>
> > I can't say I understand the use of :safe here. But added it anyways.
> > If you care, please explain why it's needed. Package-version is added.
> > I set it to 9.2. Correct?
>
> If :safe is not set, Emacs will warn every time the variable is set as
> a local file variable.
Ok
>
> It should be 9.3, not 9.2.
Ok, fixed
>
> >> > +(defun org-attach-open-link (link &optional in-emacs)
> >> > + "LINK is expanded with the attached directory and opened the same
> >> > +way as file-links are."
> >>
> >> You need to expound the arguments in the docstring.
> >
> > Sorry, I don't understand what I'm supposed to do here... I changed
> > the comment to (maybe?) make it read better. Other than that, I'm at
> > a loss.
>
> Every argument needs to be documented in the docstring. What is LINK
> type? What is IN-EMACS?
Ok, got it.
>
> >> > + (file-types-re (format "[][]\\[\\(?:file\\|attached\\|[./~]%s\\)"
> >> > (if (not link-abbrevs) ""
> >> > (format "\\|\\(?:%s:\\)"
> >> > (regexp-opt link-abbrevs))))))
> >>
> >> Why is it needed? "attached" link type is already registered, so you
> >> don't need to also hard-code it here.
> >
> > This is when parsing the buffer for images. I couldn't get org-mode to
> > display images without this.
>
> This is still a hack, and clearly not the way to go, IMO. If not already
> possible, we could add a new parameter in `org-link-parameters' or some
> such. This is another issue, tho.
Ok, sure. Although to be fair it's an existing hack, which was expanded just a tiny bit. Removed anyways.
>
> > +(defcustom org-attach-dir-create-if-not-exists t
> > + "Choose whether ATTACH_DIR-directories should be created if they do
> > not exist since before.
>
> Too long. Maybe:
>
> When non-nil, ATTACH_DIR is created automatically if it doesn't exist.
> Otherwise, ...
>
> > +Default is to create them."
> > + :group 'org-attach
> > + :type 'boolean
> > + :package-version '(Org . "9.2")
> > + :safe #'booleanp)
> > +
> > +(defcustom org-attach-dir-relative nil
> > + "Choose whether ATTACH_DIR-directories should be added as relative links or not.
>
> Too long. Maybe something like:
>
> Non-nil means ATTACH_DIR is relative to the attachment node directory.
>
> > +Defaults to not relative."
>
> Defaults to absolute location.
Yeah, that's better. Fixed.
>
> > + (let ((old (org-attach-dir nil))
> > + (new
> > + (progn
> > + (if arg (org-entry-delete nil "ATTACH_DIR")
> > + (let* ((attach-dir (read-directory-name
> > + "Attachment directory: "
> > + (org-entry-get nil
> > + "ATTACH_DIR")))
> > + (current-dir (file-name-directory (or default-directory
> > + buffer-file-name)))
> > + (attach-dir-relative (file-relative-name attach-dir current-dir)))
> > + (if org-attach-dir-relative
> > + (org-entry-put nil "ATTACH_DIR" attach-dir-relative)
> > + (org-entry-put nil "ATTACH_DIR" attach-dir))))
>
> (org-entry-put nil "ATTACH_DIR" (if org-attach-dir-relative
> attach-dir-relative
> attach-dir))
Yeah, that's nicer. Changed.
>
> > +(defun org-attach-open-link (link &optional in-emacs)
> > + "Attach link type LINK is expanded with the attached directory and opened.
> > +This is done in the same way as file-links are opened."
> > + (interactive "P")
> > + (let (line search)
> > + (if (string-match "::\\([0-9]+\\)\\'" link)
> > + (setq line (string-to-number (match-string 1 link))
> > + link (substring link 0 (match-beginning 0)))
> > + (if (string-match "::\\(.+\\)\\'" link)
> > + (setq search (match-string 1 link)
> > + link (substring link 0 (match-beginning 0)))))
>
> Use `cond' instead.
Ok.
>
> > + (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 (file link attached-dir)
> > + (setq attached-dir (expand-file-name (org-attach-dir)))
> > + (setq file (read-file-name "File: " attached-dir))
> > + (let ((pwd (file-name-as-directory attached-dir))
> > + (pwd1 (file-name-as-directory (abbreviate-file-name
> > + attached-dir))))
> > + (cond
> > + ((string-match (concat "^" (regexp-quote pwd1) "\\(.+\\)") file)
> > + (setq link (concat "@:" (match-string 1 file))))
> > + ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)")
> > + (expand-file-name file))
> > + (setq link (concat
> > + "@:" (match-string 1 (expand-file-name file)))))
> > + (t (setq link (concat "@:" file)))))
> > + link))
>
> I suggest:
>
> (let* ((attached-dir (expand-file-name (org-attach-dir)))
> (file (read-file-name "File: " attached-dir))
> (pwd (file-name-as-directory attached-dir))
> (pwd-relative (file-name-as-directory
> (abbreviate-file-name attached-dir))))
> (cond
> ((string-match ...)
> (concat ...))
> ...
> (t (concat ...))))
Yeah, clearly an improvement.
>
> > +(defun org-attach-export-link (link description format)
> > + "Translate \"attached\" (@) LINK from Org mode format to exported FORMAT.
> > +Also includes the DESCRIPTION of the link in the export."
> > + (save-excursion
> > + (let (path desc)
> > + (if (string-match "::\\([0-9]+\\)\\'" link)
> > + (setq link (substring link 0 (match-beginning 0)))
> > + (if (string-match "::\\(.+\\)\\'" link)
> > + (setq link (substring link 0 (match-beginning 0)))))
>
> Use `cond' instead.
Ok.
>
> > + (search-forward (concat "@:" (org-link-escape link)))
>
> What is the use for the line above?
Hmm, good question. Looking through my commit history I find no reason to justify it... I wonder how that got there. Effectively, I guess that row does nothing except stealing a few CPU-cycles... Removed.
> > diff --git a/lisp/org.el b/lisp/org.el
> > index eb1affbc7..9ed663bb9 100644
> > --- a/lisp/org.el
> > +++ b/lisp/org.el
> > @@ -4428,6 +4428,7 @@ This is needed for font-lock setup.")
> > (beg end))
> > (declare-function org-agenda-set-restriction-lock "org-agenda" (&optional type))
> > (declare-function org-agenda-skip "org-agenda" ())
> > +(declare-function org-attach-expand "org-attach" (&optional if-exists))
> > (declare-function org-attach-reveal "org-attach" (&optional if-exists))
> > (declare-function org-gnus-follow-link "org-gnus" (&optional group article))
> > (declare-function org-indent-mode "org-indent" (&optional arg))
> > @@ -18721,7 +18722,7 @@ boundaries."
> > ;; Check absolute, relative file names and explicit
> > ;; "file:" links. Also check link abbreviations since
> > ;; some might expand to "file" links.
> > - (file-types-re (format "[][]\\[\\(?:file\\|[./~]%s\\)"
> > + (file-types-re (format "[][]\\[\\(?:file\\|@\\|[./~]%s\\)"
> > (if (not link-abbrevs) ""
> > (format "\\|\\(?:%s:\\)"
> > (regexp-opt link-abbrevs))))))
> > @@ -18730,14 +18731,20 @@ boundaries."
> > ;; Check if we're at an inline image, i.e., an image file
> > ;; link without a description (unless INCLUDE-LINKED is
> > ;; non-nil).
> > - (when (and (equal "file" (org-element-property :type link))
> > + (when (and (or (equal "file" (org-element-property :type link))
> > + (equal "@" (org-element-property :type link)))
> > (or include-linked
> > (null (org-element-contents link)))
> > (string-match-p file-extension-re
> > (org-element-property :path link)))
> > - (let ((file (expand-file-name
> > - (org-link-unescape
> > - (org-element-property :path link)))))
> > + (let ((file (if (equal "@" (org-element-property :type link))
> > + (require 'org-attach)
> > + (org-attach-expand
> > + (org-link-unescape
> > + (org-element-property :path link)))
> > + (expand-file-name
> > + (org-link-unescape
> > + (org-element-property :path link))))))
> > (when (file-exists-p file)
> > (let ((width
> > ;; Apply `org-image-actual-width' specifications.
>
> This part can be omitted for now. Something better has to be found.
Ok, sure. I'll keep it on my local branch but it's omitted from the patch.
>
> Thank you.
>
> Regards,
>
> --
> Nicolas Goaziou
New patch attached updated according to the comments.
Regards,
Gustav
[-- Attachment #2: 0001-org-attach-org-manual-org-New-link-type-new-option.patch --]
[-- Type: application/octet-stream, Size: 20080 bytes --]
From 88e23fd0d7bf8321dc5ea8e396a97500b1035b73 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gustav=20Wikstr=C3=B6m?= <gustav.erik@gmail.com>
Date: Sun, 25 Nov 2018 21:38:44 +0100
Subject: [PATCH] org-attach, org-manual, org: New link-type, new option
* Add new linktype "@" for attachments
A new linktype "@" is added in order to reduce link-duplication when
wanting to link to files in attached folders of nodes. This works for
both ID-based attachments and ATTACH_DIR. The goal is to make the
functionality for attached-links mirror file-links.
* Add further options for ATTACH_DIR
When working with ATTACH_DIR there are now a new option available:
- org-attach-dir-relative
With that option set to t ATTACH_DIR is stored as relative to the
file-location.
* Documentation in org-manual
Org-manual is updated with the new link-type as well as some minor
cleanup in the documentation related to external links and attachments.
---
doc/org-manual.org | 114 ++++++++++++++++++++-----------------
lisp/org-attach.el | 137 ++++++++++++++++++++++++++++++++++++---------
2 files changed, 172 insertions(+), 79 deletions(-)
diff --git a/doc/org-manual.org b/doc/org-manual.org
index 5e4effb6f..0b626a1a8 100644
--- a/doc/org-manual.org
+++ b/doc/org-manual.org
@@ -3141,6 +3141,7 @@ point on or at a target.
#+cindex: irc links
#+cindex: URL links
#+cindex: file links
+#+cindex: @ links
#+cindex: Rmail links
#+cindex: MH-E links
#+cindex: Usenet links
@@ -3152,38 +3153,43 @@ Org supports links to files, websites, Usenet and email messages, BBDB
database entries and links to both IRC conversations and their logs.
External links are URL-like locators. They start with a short
identifying string followed by a colon. There can be no space after
-the colon. The following list shows examples for each link type.
-
-| =http://www.astro.uva.nl/=dominik= | on the web |
-| =doi:10.1000/182= | DOI for an electronic resource |
-| =file:/home/dominik/images/jupiter.jpg= | file, absolute path |
-| =/home/dominik/images/jupiter.jpg= | same as above |
-| =file:papers/last.pdf= | file, relative path |
-| =./papers/last.pdf= | same as above |
-| =file:/ssh:me@some.where:papers/last.pdf= | file, path on remote machine |
-| =/ssh:me@some.where:papers/last.pdf= | same as above |
-| =file:sometextfile::NNN= | file, jump to line number |
-| =file:projects.org= | another Org file |
-| =file:projects.org::some words= | text search in Org file[fn:28] |
-| =file:projects.org::*task title= | heading search in Org file |
-| =file+sys:/path/to/file= | open via OS, like double-click |
-| =file+emacs:/path/to/file= | force opening by Emacs |
-| =docview:papers/last.pdf::NNN= | open in doc-view mode at page |
-| =id:B7423F4D-2E8A-471B-8810-C40F074717E9= | link to heading by ID |
-| =news:comp.emacs= | Usenet link |
-| =mailto:adent@galaxy.net= | mail link |
-| =mhe:folder= | MH-E folder link |
-| =mhe:folder#id= | MH-E message link |
-| =rmail:folder= | Rmail folder link |
-| =rmail:folder#id= | Rmail message link |
-| =gnus:group= | Gnus group link |
-| =gnus:group#id= | Gnus article link |
-| =bbdb:R.*Stallman= | BBDB link (with regexp) |
-| =irc:/irc.com/#emacs/bob= | IRC link |
-| =info:org#External links= | Info node link |
-| =shell:ls *.org= | shell command |
-| =elisp:org-agenda= | interactive Elisp command |
-| =elisp:(find-file "Elisp.org")= | Elisp form to evaluate |
+the colon.
+
+This list shows the full set of built-in external link types,
+including examples for each:
+
+| Link Type | Description | Example |
+|-----------+------------------------------+-------------------------------------------------------|
+| http | web | =http://www.astro.uva.nl/=dominik= |
+| https | secure web | =https://orgmode.org/= |
+| doi | DOI for electronic resources | =doi:10.1000/182= |
+| file | file-links | =file:/home/dominik/images/jupiter.jpg= |
+| | | =/home/dominik/images/jupiter.jpg= (same as above) |
+| | | =file:papers/last.pdf= |
+| | | =./papers/last.pdf= (same as above) |
+| | | =file:/ssh:me@some.where:papers/last.pdf= (remote) |
+| | | =/ssh:me@some.where:papers/last.pdf= (same as above) |
+| | | =file:sometextfile::NNN= (jump to line number) |
+| | | =file:projects.org= |
+| | | =file:projects.org::some words= (text search) [fn:28] |
+| | | =file:projects.org::*task title= (headline search) |
+| @ | links to attachments | =@:projects.org= |
+| | | =@:projects.org::some words= (text search) |
+| docview | doc-view mode | =docview:papers/last.pdf::NNN= |
+| id | Link to heading by id | =id:B7423F4D-2E8A-471B-8810-C40F074717E9= |
+| news | Usenet link | =news:comp.emacs= |
+| mailto | mail link | =mailto:adent@galaxy.net= |
+| mhe | MH-E folder link | =mhe:folder= (folder link) |
+| | | =mhe:folder#id= (message link) |
+| rmail | Rmail link | =rmail:folder= (folder link) |
+| | | =rmail:folder#id= (message link) |
+| gnus | Gnus link | =gnus:group= (group link) |
+| | | =gnus:group#id= (article link) |
+| bbdb | BBDB link | =bbdb:R.*Stallman= (link with regexp) |
+| irc | IRC link | =irc:/irc.com/#emacs/bob= |
+| info | Info link | =info:org#External links= |
+| shell | shell command | =shell:ls *.org= |
+| elisp | interactive elisp command | =elisp:(find-file "Elisp.org")= |
#+cindex: VM links
#+cindex: Wanderlust links
@@ -3538,14 +3544,15 @@ the link completion function like this:
:END:
#+cindex: search option in file links
#+cindex: file links, searching
+#+cindex: @ links, searching
-File links can contain additional information to make Emacs jump to
-a particular location in the file when following a link. This can be
-a line number or a search option after a double colon[fn:35]. For
-example, when the command ~org-store-link~ creates a link (see
-[[*Handling Links]]) to a file, it encodes the words in the current line
-as a search string that can be used to find this line back later when
-following the link with {{{kbd(C-c C-o)}}}.
+File links and attached (@) links can contain additional information
+to make Emacs jump to a particular location in the file when following
+a link. This can be a line number or a search option after a double
+colon[fn:35]. For example, when the command ~org-store-link~ creates
+a link (see [[*Handling Links]]) to a file, it encodes the words in the
+current line as a search string that can be used to find this line
+back later when following the link with {{{kbd(C-c C-o)}}}.
Here is the syntax of the different ways to attach a search to a file
link, together with explanations for each:
@@ -3556,6 +3563,7 @@ link, together with explanations for each:
[[file:~/xx.org::*My Target]]
[[file:~/xx.org::#my-custom-id]]
[[file:~/xx.org::/regexp/]]
+[[@:~/code/main.c::255]]
#+end_example
- =255= ::
@@ -7533,18 +7541,22 @@ node/task. Small chunks of plain text can simply be stored in the
subtree of a project. Hyperlinks (see [[*Hyperlinks]]) can establish
associations with files that live elsewhere on your computer or in the
cloud, like emails or source code files belonging to a project.
-Another method is /attachments/, which are files located in
-a directory belonging to an outline node. Org uses directories named
-by the unique ID of each entry. These directories are located in the
-~data~ directory which lives in the same directory where your Org file
-lives[fn:86]. If you initialize this directory with =git init=, Org
-automatically commits changes when it sees them. The attachment
-system has been contributed to Org by John Wiegley.
-
-In cases where it seems better to do so, you can 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.
+Another method is /attachments/, which are files located in a
+directory belonging to an outline node. Org uses directories either
+named by the unique ID of each entry, or by the =ATTACH_DIR= property.
+ID-based directories are by default located in the =data/= directory,
+which lives in the same directory where your Org file lives[fn:86].
+If you initialize this directory with =git init=, Org automatically
+commits changes when it sees them. The attachment system has been
+contributed to Org by John Wiegley.
+
+In cases where =ATTACH_DIR= property is used to declare attachments,
+you can choose to either use absolute (default) or relative links.
+You can also make children inherit the attachment directory from a
+parent, so that an entire subtree uses the same attached directory.
+
+See customization group =Org Attach= if you want to change the default
+settings for attachments.
The following commands deal with attachments:
diff --git a/lisp/org-attach.el b/lisp/org-attach.el
index e827d3721..4054a8044 100644
--- a/lisp/org-attach.el
+++ b/lisp/org-attach.el
@@ -57,6 +57,14 @@ where the Org file lives."
:type 'directory
:safe #'stringp)
+(defcustom org-attach-dir-relative nil
+ "Choose whether ATTACH_DIR-directories should be added as relative links or not.
+Defaults to absolute location."
+ :group 'org-attach
+ :type 'boolean
+ :package-version '(Org . "9.3")
+ :safe #'booleanp)
+
(defcustom org-attach-commit t
"If non-nil commit attachments with git.
This is only done if the Org file is in a git repository."
@@ -224,14 +232,18 @@ i Make children of the current entry inherit its attachment directory.")))
'org-attach-set-inherit))
(t (error "No such attachment command %c" c))))))
-(defun org-attach-dir (&optional create-if-not-exists-p)
+(defun org-attach-dir (&optional create-if-not-exists-p verify-create-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 (if necessary) the corresponding ID will be created."
+the directory and (if necessary) the corresponding ID will be created.
+
+If VERIFY-CREATE is non-nil, ask for verification from the user
+before directory is created."
(let (attach-dir uuid)
(setq org-attach-inherited (org-entry-get nil "ATTACH_DIR_INHERIT"))
(cond
@@ -245,7 +257,7 @@ the directory and (if necessary) the corresponding ID will be created."
(goto-char org-entry-property-inherited-from)
(org-back-to-heading t))
(let (org-attach-allow-inheritance)
- (org-attach-dir create-if-not-exists-p))))
+ (org-attach-dir create-if-not-exists-p verify-create-p))))
(org-attach-check-absolute-path attach-dir)
(setq org-attach-inherited t))
(t ; use the ID
@@ -260,7 +272,10 @@ the directory and (if necessary) the corresponding ID will be created."
(expand-file-name org-attach-directory))))))
(when attach-dir
(if (and create-if-not-exists-p
- (not (file-directory-p attach-dir)))
+ (not (file-directory-p attach-dir))
+ (if verify-create-p
+ (yes-or-no-p "Create attachment directory?")
+ t))
(make-directory attach-dir t))
(and (file-exists-p attach-dir)
attach-dir))))
@@ -280,20 +295,24 @@ Throw an error if we cannot root the directory."
"Set the ATTACH_DIR node property and ask to move files there.
The property defines the directory that is used for attachments
of the entry. When called with `\\[universal-argument]', reset \
-the directory to
-the default ID based one."
+the directory to the default ID based one. Creates relative
+links if ORG-ATTACH-DIR-RELATIVE is t."
(interactive "P")
(let ((old (org-attach-dir))
- (new
- (progn
- (if arg (org-entry-delete nil "ATTACH_DIR")
- (let ((dir (read-directory-name
- "Attachment directory: "
- (org-entry-get nil
- "ATTACH_DIR"
- (and org-attach-allow-inheritance t)))))
- (org-entry-put nil "ATTACH_DIR" dir)))
- (org-attach-dir t))))
+ (new
+ (progn
+ (if arg (org-entry-delete nil "ATTACH_DIR")
+ (let* ((attach-dir (read-directory-name
+ "Attachment directory: "
+ (org-entry-get nil
+ "ATTACH_DIR")))
+ (current-dir (file-name-directory (or default-directory
+ buffer-file-name)))
+ (attach-dir-relative (file-relative-name attach-dir current-dir)))
+ (org-entry-put nil "ATTACH_DIR" (if org-attach-dir-relative
+ attach-dir-relative
+ attach-dir))))
+ (org-attach-dir t))))
(unless (or (string= old new)
(not old))
(when (yes-or-no-p "Copy over attachments from old directory? ")
@@ -527,14 +546,14 @@ This ignores files ending in \"~\"."
"Show the attachment directory of the current task.
This will attempt to use an external program to show the directory."
(interactive "P")
- (let ((attach-dir (org-attach-dir (not if-exists))))
+ (let ((attach-dir (org-attach-dir (not if-exists) t)))
(and attach-dir (org-open-file attach-dir))))
(defun org-attach-reveal-in-emacs ()
"Show the attachment directory of the current task in dired."
(interactive)
- (let ((attach-dir (org-attach-dir t)))
- (dired attach-dir)))
+ (let ((attach-dir (org-attach-dir t t)))
+ (when attach-dir (dired attach-dir))))
(defun org-attach-open (&optional in-emacs)
"Open an attachment of the current task.
@@ -543,15 +562,17 @@ This command will open the file using the settings in `org-file-apps'
and in the system-specific variants of this variable.
If IN-EMACS is non-nil, force opening in Emacs."
(interactive "P")
- (let* ((attach-dir (org-attach-dir t))
- (files (org-attach-file-list attach-dir))
- (file (if (= (length files) 1)
- (car files)
- (completing-read "Open attachment: "
- (mapcar #'list files) nil t)))
- (path (expand-file-name file attach-dir)))
- (org-attach-annex-get-maybe path)
- (org-open-file path in-emacs)))
+ (let ((attach-dir (org-attach-dir t t)))
+ (if attach-dir
+ (let* ((files (org-attach-file-list attach-dir))
+ (file (if (= (length files) 1)
+ (car files)
+ (completing-read "Open attachment: "
+ (mapcar #'list files) nil t)))
+ (path (expand-file-name file attach-dir)))
+ (org-attach-annex-get-maybe path)
+ (org-open-file path in-emacs))
+ (message "No attachment exist!"))))
(defun org-attach-open-in-emacs ()
"Open attachment, force opening in Emacs.
@@ -570,6 +591,66 @@ Basically, this adds the path to the attachment directory, and a \"file:\"
prefix."
(concat "file:" (org-attach-expand file)))
+(defun org-attach-open-link (link &optional in-emacs)
+ "Attach 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* ((attached-dir (expand-file-name (org-attach-dir)))
+ (file (read-file-name "File: " attached-dir))
+ (pwd (file-name-as-directory attached-dir))
+ (pwd-relative (file-name-as-directory
+ (abbreviate-file-name attached-dir))))
+ (cond
+ ((string-match (concat "^" (regexp-quote pwd-relative) "\\(.+\\)") file)
+ (concat "@:" (match-string 1 file)))
+ ((string-match (concat "^" (regexp-quote pwd) "\\(.+\\)")
+ (expand-file-name file))
+ (concat "@:" (match-string 1 (expand-file-name file))))
+ (t (concat "@:" file)))))
+
+(defun org-attach-export-link (link description format)
+ "Translate \"attached\" (@) 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)))))
+
+(org-link-set-parameters "@"
+ :follow 'org-attach-open-link
+ :export 'org-attach-export-link
+ :complete 'org-attach-complete-link)
+
(defun org-attach-archive-delete-maybe ()
"Maybe delete subtree attachments when archiving.
This function is called by `org-archive-hook'. The option
--
2.19.1.windows.1
next prev parent reply other threads:[~2018-11-25 21:13 UTC|newest]
Thread overview: 113+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-10-21 7:53 FW: [RFC] Link-type for attachments, more attach options Gustav Wikström
2018-11-01 1:45 ` tumashu
2018-11-02 22:40 ` Gustav Wikström
2018-11-01 16:00 ` Marco Wahl
2018-11-02 23:07 ` Gustav Wikström
2018-11-03 3:37 ` Ihor Radchenko
2018-11-17 12:13 ` Gustav Wikström
2018-11-18 0:42 ` Ihor Radchenko
2018-11-18 8:57 ` Gustav Wikström
2018-11-20 14:00 ` Ihor Radchenko
2018-11-24 13:56 ` Gustav Wikström
2018-12-14 2:16 ` Ihor Radchenko
2019-05-26 22:24 ` Gustav Wikström
2018-11-04 22:37 ` Nicolas Goaziou
2018-11-17 11:58 ` Gustav Wikström
[not found] ` <PR1PR02MB47322711B7F7B7142D156F54DADE0@PR1PR02MB4732.eurprd02.prod.outlook.com>
2018-11-19 23:52 ` Nicolas Goaziou
2018-11-25 21:13 ` Gustav Wikström [this message]
2018-11-27 9:39 ` Nicolas Goaziou
2019-05-26 23:05 ` Gustav Wikström
2019-06-15 13:29 ` Nicolas Goaziou
2019-06-15 15:38 ` Bastien
2019-06-30 6:03 ` Gustav Wikström
2019-07-06 21:46 ` Nicolas Goaziou
2019-07-07 18:38 ` Gustav Wikström
2019-07-08 10:47 ` Marco Wahl
2019-07-09 10:16 ` Nicolas Goaziou
2019-07-27 14:56 ` Ihor Radchenko
2019-07-28 20:39 ` Gustav Wikström
2019-07-28 23:20 ` Ihor Radchenko
2019-01-04 12:21 ` FW: " Feng Shu
2019-05-26 23:15 ` Gustav Wikström
2019-12-12 5:21 ` stardiviner
2019-12-12 6:12 ` Gustav Wikström
2019-12-12 9:52 ` stardiviner
2019-12-12 19:42 ` Gustav Wikström
2019-12-13 13:38 ` stardiviner
2019-12-13 21:37 ` Gustav Wikström
2019-12-13 22:15 ` Gustav Wikström
2019-12-15 4:14 ` stardiviner
2019-12-15 9:29 ` stardiviner
2019-12-15 10:06 ` Gustav Wikström
2019-12-15 14:26 ` stardiviner
2019-12-15 20:41 ` Gustav Wikström
2019-12-16 3:38 ` stardiviner
2019-12-16 11:21 ` stardiviner
2019-12-17 4:27 ` stardiviner
2020-01-13 12:24 ` attachment: link type export to HTML invalid attach dir stardiviner
2020-01-14 3:27 ` Gustav Wikström
2020-01-14 5:04 ` stardiviner
2020-01-14 20:58 ` Gustav Wikström
2020-01-15 5:53 ` stardiviner
2020-01-15 19:48 ` Gustav Wikström
2020-01-16 11:06 ` stardiviner
2020-01-16 13:18 ` Nicolas Goaziou
2020-01-16 21:42 ` Gustav Wikström
2020-01-16 23:07 ` Gustav Wikström
2020-01-17 0:39 ` Nicolas Goaziou
2020-01-17 14:29 ` Gustav Wikström
2020-01-17 18:36 ` Gustav Wikström
2020-01-18 1:13 ` Gustav Wikström
2020-01-18 11:34 ` Nicolas Goaziou
2020-01-18 15:14 ` Gustav Wikström
2020-01-19 21:12 ` Nicolas Goaziou
2020-01-19 23:29 ` Gustav Wikström
2020-01-20 1:25 ` Nicolas Goaziou
2020-01-25 11:34 ` Gustav Wikström
2020-02-05 16:54 ` Nicolas Goaziou
2020-02-06 20:55 ` Gustav Wikström
2020-02-07 14:28 ` Nicolas Goaziou
2020-02-08 15:39 ` Gustav Wikström
2020-02-13 20:41 ` Nicolas Goaziou
2020-02-13 21:11 ` Gustav Wikström
2020-02-13 21:37 ` Nicolas Goaziou
2020-02-13 22:07 ` Gustav Wikström
2020-02-14 0:16 ` Nicolas Goaziou
2020-02-14 7:23 ` Gustav Wikström
2020-02-14 2:42 ` Kyle Meyer
2020-02-14 7:35 ` Gustav Wikström
2020-02-14 7:41 ` Gustav Wikström
2020-02-14 11:06 ` Bastien
2020-02-14 17:12 ` Nicolas Goaziou
2020-02-14 20:33 ` Bastien
2020-02-15 18:08 ` Nicolas Goaziou
2020-02-15 23:04 ` Kyle Meyer
2020-02-16 8:51 ` Nicolas Goaziou
2020-02-16 23:59 ` Bastien
2020-02-17 9:37 ` Nicolas Goaziou
2020-02-17 10:25 ` Bastien
2020-02-16 23:58 ` Bastien
2020-02-17 10:32 ` Nicolas Goaziou
2020-02-17 10:53 ` Bastien
2020-02-20 9:20 ` Nicolas Goaziou
2020-02-20 10:20 ` Bastien
2020-02-22 12:58 ` Nicolas Goaziou
2020-02-22 13:32 ` Bastien
2020-02-25 23:36 ` Gustav Wikström
2020-02-26 15:22 ` Nicolas Goaziou
2020-02-27 19:02 ` Gustav Wikström
2020-02-28 0:37 ` Nicolas Goaziou
2020-02-13 21:57 ` Gustav Wikström
2020-02-14 10:02 ` Bastien
2020-01-13 13:41 ` FW: [RFC] Link-type for attachments, more attach options stardiviner
2020-01-14 21:17 ` Gustav Wikström
2020-01-15 6:20 ` stardiviner
2020-01-15 22:42 ` Gustav Wikström
2020-01-16 11:15 ` stardiviner
2020-01-18 14:56 ` stardiviner
2020-01-18 15:30 ` Gustav Wikström
2020-01-19 4:28 ` stardiviner
2020-01-19 9:53 ` Gustav Wikström
2020-01-17 7:39 ` Missing `org-attach-set-inherit' function stardiviner
2020-01-17 16:31 ` Gustav Wikström
2020-01-18 14:54 ` stardiviner
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.orgmode.org/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=PR1PR02MB4732B95D15A405B39B6D039DDAD60@PR1PR02MB4732.eurprd02.prod.outlook.com \
--to=gustav@whil.se \
--cc=emacs-orgmode@gnu.org \
--cc=mail@nicolasgoaziou.fr \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.savannah.gnu.org/cgit/emacs/org-mode.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).