branch: externals/org-transclusion commit 2064ea76e17dd081686f4c5bb0c6b04160b757d4 Author: Noboru Ota <m...@nobiot.com> Commit: Noboru Ota <m...@nobiot.com>
add: #145 new property and filter to expand links (Org only) use :expand-links per transclusion to convert relative file names in links to the absolute ones. Nothing is done if a link is already absolute. --- NEWS | 9 ++++- docs/org-transclusion-manual.org | 33 ++++++++++++++++- org-transclusion.el | 77 +++++++++++++++++++++------------------- 3 files changed, 81 insertions(+), 38 deletions(-) diff --git a/NEWS b/NEWS index ebb3d3d3c4..921a70d1b0 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,13 @@ * Current - - Fix: #131. For non-Org files, now the transcluded text respects the indent + - Feature :: + + - add: #145 a new property and filter to expand links to absolute file names (Org only) + use :expand-links per transclusion + + - Fix :: + + - fix: #131. For non-Org files, now the transcluded text respects the indent level of the #+transclude keyword. This does not affect Org files. * Version 1.2.0 diff --git a/docs/org-transclusion-manual.org b/docs/org-transclusion-manual.org index 042a9c8a0e..c3524743cf 100644 --- a/docs/org-transclusion-manual.org +++ b/docs/org-transclusion-manual.org @@ -1,7 +1,7 @@ #+title: Org-transclusion User Manual #+author: Noboru Ota <m...@nobiot.com> #+macro: version 1.2.x -#+macro: modified 23 January 2022 +#+macro: modified 27 May 2022 #+language: en #+export_file_name: org-transclusion.texi @@ -272,6 +272,37 @@ In addition to the global user options above, you can fine-tune the default excl You can combine =:only-contents= and =:exclude-elements= to control how you transclude a subtree. With these properties, you can really have great control over what to include and exclude. It might be a little overwhelming at a time but the changes via properties are easy to change -- simply press =d= to remove the transclusion, change the properties, and transclude again to see a new result. +- =:expand-links= :: + This property lets you expand the file names in links to absolute file names. + +You can use the property in the following way. + +#+begin_example +#+transclude: [[file:path/to/file.org]] :expand-links +#+end_example + +As an exanmple if you have the content of this source file like this: + +#+begin_example +Content of path/to/file.org + +* Heading + +[[file:test2.org]] +#+end_example + +For this source file, you will get the following transclusion with the link expanded [fn:1] + +#+begin_example +Content of path/to/file.org + +* Heading + +[[file:/home/user/org/test2.org]] +#+end_example + +[fn:1] "Expanding" in Emacs means converting a relative file name to an absolute one. Info node `(elisp) File-Name-Expansion' + *** Notes on excluding the headline element If you add =headline= as a list of elements to exclude, you exclude sub-headlines within your subtrees and you will still transclude the content of the top-most headline of the subtrees. diff --git a/org-transclusion.el b/org-transclusion.el index 8668b89a1c..61dbbac0c3 100644 --- a/org-transclusion.el +++ b/org-transclusion.el @@ -205,6 +205,7 @@ that consists of the following properties: org-transclusion-keyword-value-disable-auto org-transclusion-keyword-value-only-contents org-transclusion-keyword-value-exclude-elements + org-transclusion-keyword-value-expand-links org-transclusion-keyword-current-indentation) "Define a list of functions used to parse a #+transclude keyword. These functions take a single argument, the whole keyword value @@ -827,6 +828,15 @@ It needs to be set in `org-transclusion-keyword-value-functions'." (list :current-indentation (current-indentation))) +(defun org-transclusion-keyword-value-expand-links (string) + "It is a utility function used converting a keyword STRING to plist. +It is meant to be used by `org-transclusion-get-string-to-plist'. +It needs to be set in +`org-transclusion-keyword-value-functions'." + (when (string-match ":expand-links" string) + (list :expand-links + (org-strip-quotes (match-string 0 string))))) + (defun org-transclusion-keyword-remove () "Remove the keyword element at point. Returns t if successful. It checks if the element at point is a @@ -849,6 +859,7 @@ keyword. If not, returns nil." (disable-auto (plist-get plist :disable-auto)) (only-contents (plist-get plist :only-contents)) (exclude-elements (plist-get plist :exclude-elements)) + (expand-links (plist-get plist :expand-links)) (custom-properties-string nil)) (setq custom-properties-string (dolist (fn org-transclusion-keyword-plist-to-string-functions @@ -863,6 +874,7 @@ keyword. If not, returns nil." (when only-contents (format " :only-contents")) (when exclude-elements (format " :exclude-elements \"%s\"" exclude-elements)) + (when expand-links (format " :expand-links")) custom-properties-string "\n"))) @@ -1062,17 +1074,14 @@ work to (if (and marker (marker-buffer marker) (buffer-live-p (marker-buffer marker))) (progn - (let ((only-contents (plist-get plist :only-contents)) - (exclude-elements - (org-transclusion-keyword-plist-to-exclude-elements plist))) - (with-current-buffer (marker-buffer marker) - (org-with-wide-buffer - (goto-char marker) - (if (org-before-first-heading-p) - (org-transclusion-content-org-buffer-or-element - nil only-contents exclude-elements) + (with-current-buffer (marker-buffer marker) + (org-with-wide-buffer + (goto-char marker) + (if (org-before-first-heading-p) (org-transclusion-content-org-buffer-or-element - 'only-element only-contents exclude-elements)))))) + nil plist) + (org-transclusion-content-org-buffer-or-element + 'only-element plist))))) (message "Nothing done. Cannot find marker for the ID."))) (defun org-transclusion-content-org-link (link plist) @@ -1085,23 +1094,18 @@ work to ;; search-option is present. (let* ((path (org-element-property :path link)) (search-option (org-element-property :search-option link)) - (buf (find-file-noselect path)) - (only-contents (plist-get plist :only-contents)) - (exclude-elements - (org-transclusion-keyword-plist-to-exclude-elements plist))) + (buf (find-file-noselect path))) (with-current-buffer buf (org-with-wide-buffer (if search-option (progn (org-link-search search-option) (org-transclusion-content-org-buffer-or-element - 'only-element only-contents exclude-elements)) + 'only-element plist)) (org-transclusion-content-org-buffer-or-element - nil only-contents exclude-elements))))))) + nil plist))))))) -(defun org-transclusion-content-org-buffer-or-element (&optional only-element - only-contents - exclude-elements) +(defun org-transclusion-content-org-buffer-or-element (only-element plist) "Return a list of playload for transclusion. Tis function assumes the point is at the beginning of the org element to transclude. @@ -1116,19 +1120,9 @@ When ONLY-ELEMENT is non-nil, this function looks at only the element at point; if nil, the whole buffer. This function applies multiple filters on the Org elements before -construting the payload based on relevant user options and -optional arguments as below: - -EXCLUDE-ELEMENTS adds elements to be excluded onto user option -`org-transclusion-exclude-elements'. The user option applies -globally, the optional arguments can be applied for each -transcluion. - -First section - -ONLY-CONTENTS applies filter to remove headline titles of the -subtree, extracting only sections (including paragraphs, tables, -etc.)." +construting the payload based on PLIST. It is the +\"keyword-plist\" for the transclusion being worked on; each +property controls the filter applied to the transclusion." (let* ((el (org-element-context)) (type (when el (org-element-type el)))) (if (or (not el)(not type)) @@ -1140,6 +1134,10 @@ etc.)." (setq el (org-element-property :parent el))) (let ((beg (org-element-property :begin el)) (end (org-element-property :end el)) + (only-contents (plist-get plist :only-contents)) + (exclude-elements + (org-transclusion-keyword-plist-to-exclude-elements plist)) + (expand-links (plist-get plist :expand-links)) obj) (when only-element (narrow-to-region beg end)) @@ -1162,16 +1160,23 @@ etc.)." (setq obj (org-element-map obj org-element-all-elements #'org-transclusion-content-filter-org-only-contents nil nil '(section) nil))) - ;; Convert relative filename in links to absolute (abbreviated) - (org-element-map obj 'link #'org-transclusion-content-absolute-links) + + ;; Expand file names in all the links + (when expand-links + (org-element-map obj 'link #'org-transclusion-content-filter-expand-links)) (list :src-content (org-element-interpret-data obj) :src-buf (current-buffer) :src-beg (point-min) :src-end (point-max)))))) -(defun org-transclusion-content-absolute-links (link) - "." +(defun org-transclusion-content-filter-expand-links (link) + "Convert LINK to an absolute filename. +LINK is assumed to be an Org element. This function does nothing +to LINK if the link is already absolute. + +The current buffer is assumed to be the source buffer for the +transclusion." (when (string-equal "file" (org-element-property :type link)) (let ((raw-link (org-element-property :raw-link link))) (unless (file-name-absolute-p raw-link)