branch: externals/denote
commit b00a8230cdb9750c05722914cc8ab8ea94383eb1
Author: Protesilaos Stavrou <[email protected]>
Commit: Protesilaos Stavrou <[email protected]>
Greatly expand the capabilities of the 'denote-files' Org dynamic block
1. The :no-front-matter parameter can now read a number value to
omit that many lines from the top of the file.
2. A new :add-links parameter formats the inserted files as a
typographic list and creates a link to each file.
---
README.org | 70 +++++++++++++++++++++++++++++++++-------------------
denote-org-dblock.el | 60 ++++++++++++++++++++++++++++++++------------
2 files changed, 89 insertions(+), 41 deletions(-)
diff --git a/README.org b/README.org
index 5046329e4d..4990b7c4c1 100644
--- a/README.org
+++ b/README.org
@@ -2461,7 +2461,7 @@ reflect on the status of earlier notes
([[#h:6060a7e6-f179-4d42-a9de-a9968aaebec
Denote can optionally use Org's dynamic blocks facility to produce a
section that lists entire file contents
([[#h:8b542c50-dcc9-4bca-8037-a36599b22779][Use Org dynamic blocks]]).
This works by instrucing Org to match a regular expression of Denote
-files, the same way we do with Denote links
([[#h:9bec2c83-36ca-4951-aefc-7187c5463f90][Insert links matching a regexp]]).
+files, the same way we do with Denote links
([[#h:9bec2c83-36ca-4951-aefc-7187c5463f90][Insert links matching a regexp]]).
This is useful to, for example, compile a dynamically concatenated
list of scattered thoughts on a given topic, like =^2023.*_emacs= for
@@ -2472,35 +2472,55 @@ To produce such a block, use the following syntax in an
Org file and
type =C-c C-x C-u= (~org-dblock-update~) on the =#+BEGIN= line (type
=C-c C-x C-u= again to recalculate the block):
-: #+BEGIN: denote-files :regexp "YOUR-REGEXP-HERE"
+: #+BEGIN: denote-files :regexp "^2023.*_journal"
:
: #+END:
-The =:regexp= parameter is mandatory. Its value is a string,
-representing a regular expression to match Denote file names. Its
-value may also be an ~rx~ expression instead of a string, as noted in
-the previous section about Org dynamic blocks.
+Or to fully control the output, include these parameters, which are
+described further below:
+
+: #+BEGIN: denote-files :regexp "^2023.*_journal" :no-front-matter nil
:file-separator t :add-links nil
+:
+: #+END:
+
+- The =:regexp= parameter is mandatory. Its value is a string,
+ representing a regular expression to match Denote file names. Its
+ value may also be an ~rx~ expression instead of a string, as noted
+ in the previous section about Org dynamic blocks.
#+vindex: denote-org-dblock-file-contents-separator
-File contents are inserted verbatim. They are separated by the
-~denote-org-dblock-file-contents-separator~, which introduces some
-empty lines and a horizontal rule between them to visually distinguish
-individual files. Though the block accepts an optional parameter of
-=:file-separator=, which takes a string as a value. It is recommended
-to include newline characters (=\n=) in the string for better results.
-The value of =:file-separator= may also be =none=, in which case no
-separator is used.
-
-An optional =:block-name= parameter adds a =#+name= to the results for
-further processing using Org facilities (this is outside Denote's
-purview).
-
-The optional =:no-front-matter= parameter with a ~t~ value instructs
-Denote to try to remove front matter from the files it is inserting in
-the dynamic block. The technique used to perform this operation is by
-removing all lines from the top of the file until the first empty
-line. This works with the default front matter that Denote adds, but
-is not 100% reliable with all sorts of user-level modifications.
+- The =:file-separator= parameter is optional. If it is omitted, then
+ Denote will use the ~denote-org-dblock-file-contents-separator~: it
+ introduces some empty lines and a horizontal rule between them to
+ visually distinguish individual files. If the =:file-separator=
+ value is a string, it is used as the file separator (e.g. use ="\n"=
+ to insert just one empty new line). If the =:file-separator= value
+ is set to =none=, no separator is used.
+
+- The =:no-front-matter= parameter is optional. When set to a ~t~
+ value Denote tries to remove front matter from the files it is
+ inserting in the dynamic block. The technique used to perform this
+ operation is by removing all lines from the top of the file until
+ the first empty line. This works with the default front matter that
+ Denote adds, but is not 100% reliable with all sorts of user-level
+ modifications and edits to the file. When the =:no-front-matter= is
+ set to a natural number, Denote will omit that many lines from the
+ top of the file.
+
+- The =:add-links= parameter is optional. When it is set to a ~t~
+ value, all files are inserted as a typographic list and are indented
+ accordingly. The first line in each list item is a link to the file
+ whose contents are inserted in the following lines. When the value
+ is =id-only=, then links are inserted without a description text but
+ only with the identifier of the given file. This has the same
+ meaning as with the ~denote-link~ command and related facilities
+ ([[#h:fc913d54-26c8-4c41-be86-999839e8ad31][Linking notes]]). Remember that
Org can fold the items in a
+ typographic list the same way it does with headings. So even long
+ files can be presented in this format without much trouble.
+
+- The =:block-name= parameter is optional. It adds a =#+name= to the
+ results for further processing using Org facilities (this is outside
+ Denote's purview).
* Minibuffer histories
:PROPERTIES:
diff --git a/denote-org-dblock.el b/denote-org-dblock.el
index 981f88e9f1..d16f667987 100644
--- a/denote-org-dblock.el
+++ b/denote-org-dblock.el
@@ -151,18 +151,38 @@ Used by `org-dblock-update' with PARAMS provided by the
dynamic block."
;;;; Dynamic block with entire file contents
-(defun denote-org-dblock--get-file-contents (file &optional no-front-matter)
+(defun denote-org-dblock--get-file-contents (file &optional no-front-matter
add-links)
"Insert the contents of FILE.
With optional NO-FRONT-MATTER as non-nil, try to remove the front
-matter from the top of the file. Do it by finding the first
-blank line, starting from the top of the buffer."
+matter from the top of the file. If NO-FRONT-MATTER is a number,
+remove that many lines starting from the top. If it is any other
+non-nil value, delete from the top until the first blank line.
+
+With optional ADD-LINKS as non-nil, first insert a link to the
+file and then insert its contents. In this case, format the
+contents as a typographic list. If ADD-LINKS is `id-only', then
+insert links as `denote-link' does when supplied with an ID-ONLY
+argument."
(with-temp-buffer
- (insert-file-contents file)
- (when no-front-matter
- (let ((min (point-min)))
- (goto-char min)
- (re-search-forward "^$" nil :no-error 1)
- (delete-region (1+ (point)) min)))
+ (when add-links
+ (insert
+ (format "- %s\n\n"
+ (denote-format-link
+ file
+ (if (eq add-links 'id-only)
+ denote-id-only-link-format
+ denote-org-link-format)
+ nil))))
+ (let ((beginning-of-contents (point)))
+ (insert-file-contents file)
+ (when no-front-matter
+ (delete-region
+ (if (natnump no-front-matter)
+ (progn (forward-line no-front-matter) (line-beginning-position))
+ (1+ (re-search-forward "^$" nil :no-error 1)))
+ beginning-of-contents))
+ (when add-links
+ (indent-region beginning-of-contents (point-max) 2)))
(buffer-string)))
(defvar denote-org-dblock-file-contents-separator
@@ -173,17 +193,21 @@ blank line, starting from the top of the buffer."
"Return appropriate value of SEPARATOR for `denote-org-dblock-add-files'."
(cond
((eq separator 'none) "")
- (separator separator)
+ ((stringp separator) separator)
(t denote-org-dblock-file-contents-separator)))
-(defun denote-org-dblock-add-files (regexp &optional separator no-front-matter)
+(defun denote-org-dblock-add-files (regexp &optional separator no-front-matter
add-links)
"Insert files matching REGEXP.
Seaprate them with the optional SEPARATOR. If SEPARATOR is nil,
use the `denote-org-dblock-file-contents-separator'.
If optional NO-FRONT-MATTER is non-nil try to remove the front
matter from the top of the file. Do it by finding the first
-blank line, starting from the top of the buffer."
+blank line, starting from the top of the buffer.
+
+If optional ADD-LINKS is non-nil, first insert a link to the file
+and then insert its contents. In this case, format the contents
+as a typographic list."
(let ((files (denote-directory-files-matching-regexp regexp)))
;; FIXME 2023-11-23: Do not use a separator for the last file.
;; Not a big issue, but is worth checking.
@@ -192,7 +216,7 @@ blank line, starting from the top of the buffer."
;; NOTE 2023-11-23: I tried to just do `insert-file-contents'
;; without the temporary buffer, but it seems that the point is
;; not moved, so the SEPARATOR does not follow the contents.
- (let ((contents (denote-org-dblock--get-file-contents file
no-front-matter)))
+ (let ((contents (denote-org-dblock--get-file-contents file
no-front-matter add-links)))
(insert (concat contents (denote-org-dblock--separator separator)))))
files)))
@@ -203,7 +227,10 @@ blank line, starting from the top of the buffer."
(list
(read-regexp "Search for notes matching REGEX: " nil
'denote--file-history)))
(org-create-dblock (list :name "denote-files"
- :regexp regexp))
+ :regexp regexp
+ :no-front-matter nil
+ :file-separator t
+ :add-links nil))
(org-update-dblock))
(defun org-dblock-write:denote-files (params)
@@ -213,10 +240,11 @@ Used by `org-dblock-update' with PARAMS provided by the
dynamic block."
(rx (if (listp regexp) (macroexpand `(rx ,regexp)) regexp))
(block-name (plist-get params :block-name))
(separator (plist-get params :file-separator))
- (no-front-matter (plist-get params :no-front-matter)))
+ (no-front-matter (plist-get params :no-front-matter))
+ (add-links (plist-get params :add-links)))
(when block-name
(insert "#+name: " block-name "\n"))
- (when rx (denote-org-dblock-add-files rx separator no-front-matter))))
+ (when rx (denote-org-dblock-add-files rx separator no-front-matter
add-links))))
(provide 'denote-org-dblock)
;;; denote-org-dblock.el ends here