[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/denote 00c4e70dfa 5/5: Add denote-templates user option
From: |
ELPA Syncer |
Subject: |
[elpa] externals/denote 00c4e70dfa 5/5: Add denote-templates user option |
Date: |
Sun, 7 Aug 2022 01:57:29 -0400 (EDT) |
branch: externals/denote
commit 00c4e70dfac0fec647cf6961340539cc0823b3ed
Author: Protesilaos Stavrou <info@protesilaos.com>
Commit: Protesilaos Stavrou <info@protesilaos.com>
Add denote-templates user option
---
README.org | 103 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
denote.el | 81 ++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 174 insertions(+), 10 deletions(-)
diff --git a/README.org b/README.org
index 16d89160af..1eab8bbcbe 100644
--- a/README.org
+++ b/README.org
@@ -133,11 +133,14 @@ Obligations, Tasks, and Engagements.
#+findex: denote-org-capture
#+findex: denote-date
#+findex: denote-subdirectory
+#+findex: denote-template
There are five ways to write a note with Denote: invoke the ~denote~,
-~denote-type~, ~denote-date~, ~denote-subdirectory~ commands, or
-leverage the ~org-capture-templates~ by setting up a template which
-calls the function ~denote-org-capture~. We explain all of those in the
-subsequent sections.
+~denote-type~, ~denote-date~, ~denote-subdirectory~, ~denote-template~
+commands, or leverage the ~org-capture-templates~ by setting up a
+template which calls the function ~denote-org-capture~. We explain all
+of those in the subsequent sections.
+
+[ The ~denote-template~ is part of {{{development-version}}} ]
** Standard note creation
:PROPERTIES:
@@ -212,6 +215,12 @@ The value is a list of symbols, which includes any of the
following:
like 2022-06-16 or a date plus time: 2022-06-16 14:30. Without the
=date= prompt, the ~denote~ command uses the ~current-time~.
+- =template=: Prompts for a KEY among the ~denote-templates~. The value
+ of that KEY is used to populate the new note with content, which is
+ added after the front matter ([[#h:f635a490-d29e-4608-9372-7bd13b34d56c][The
denote-templates option]]).
+
+ [ The =template= is part of {{{development-version}}} ]
+
The prompts occur in the given order.
If the value of this user option is nil, no prompts are used. The
@@ -240,6 +249,73 @@ interactive actions that do not change the default
behaviour of the
~denote-type~, ~denote-subdirectory~, ~denote-date~. They are described
in the subsequent section
([[#h:887bdced-9686-4e80-906f-789e407f2e8f][Convenience commands for note
creation]]).
+*** The ~denote-templates~ option
+:PROPERTIES:
+:CUSTOM_ID: h:f635a490-d29e-4608-9372-7bd13b34d56c
+:END:
+
+[ Part of {{{development-version}}} ]
+
+#+vindex: denote-templates
+The user option ~denote-templates~ is an alist of content templates for
+new notes. A template is arbitrary text that Denote will add to a newly
+created note right below the front matter.
+
+Templates are expressed as a =(KEY . STRING)= association.
+
+- The =KEY= is the name which identifies the template. It is an
+ arbitrary symbol, such as =report=, =memo=, =statement=.
+
+- The =STRING= is ordinary text that Denote will insert as-is. It can
+ contain newline characters to add spacing. Below we show some
+ concrete examples.
+
+The user can choose a template either by invoking the command
+~denote-template~ or by changing the user option ~denote-prompts~ to
+always prompt for a template when calling the ~denote~ command.
+
+[[#h:f9204f1f-fcee-49b1-8081-16a08a338099][The denote-prompts option]].
+
+[[#h:887bdced-9686-4e80-906f-789e407f2e8f][Convenience commands for note
creation]].
+
+Templates can be written directly as one large string. For example (the
+=\n= character is read as a newline):
+
+#+begin_src emacs-lisp
+(setq denote-templates
+ '((report . "* Some heading\n\n* Another heading")
+ (memo . "* Some heading
+
+,* Another heading
+
+")))
+#+end_src
+
+Long strings may be easier to type but interpret indentation literally.
+Also, they do not scale well. A better way is to use some Elisp code to
+construct the string. This would typically be the ~concat~ function,
+which joins multiple strings into one. The following is the same as the
+previous example:
+
+#+begin_src emacs-lisp
+(setq denote-templates
+ `((report . "* Some heading\n\n* Another heading")
+ (memo . ,(concat "* Some heading"
+ "\n\n"
+ "* Another heading"
+ "\n\n"))))
+#+end_src
+
+Notice that to evaluate a function inside of an alist we use the
+backtick to quote the alist (NOT the straight quote) and then prepend a
+comma to the expression that should be evaluated. The ~concat~ form
+here is not sensitive to indentation, so it is easier to adjust for
+legibility.
+
+DEV NOTE: We do not provide more examples at this point, though feel
+welcome to ask for help if the information provided herein is not
+sufficient. We shall expand the manual accordingly.
+
*** Convenience commands for note creation
:PROPERTIES:
:CUSTOM_ID: h:887bdced-9686-4e80-906f-789e407f2e8f
@@ -292,6 +368,20 @@ commands for note creation:
The ~denote-create-note-in-subdirectory~ is a more descriptive alias
of ~denote-subdirectory~.
+ [ Templates are part of {{{development-version}}} ]
+
++ Create note and add a template :: The ~denote-template~ command
+ creates a new note and inserts the specified template below the front
+ matter ([[#h:f635a490-d29e-4608-9372-7bd13b34d56c][The denote-templates
option]]). Available candidates for
+ templates are specified in the user option ~denote-templates~.
+
+ This is equivalent to calling ~denote~ when ~denote-prompts~ is
+ set to ='(template title keywords)=.
+
+ #+findex: denote-create-note-with-template
+ The ~denote-create-note-with-template~ is an alias of the command
+ ~denote-template~, meant to help with discoverability.
+
** Create note using Org capture
:PROPERTIES:
:CUSTOM_ID: h:656c70cd-cf9a-4471-a0b5-4f0aaf60f881
@@ -1673,6 +1763,10 @@ Everything is in place to set up the package.
(setq denote-file-type nil) ; Org is the default, set others here
(setq denote-prompts '(title keywords))
+;; Read this manual for how to specify `denote-templates'. We do not
+;; include an example here to avoid potential confusion.
+
+
;; We allow multi-word keywords by default. The author's personal
;; preference is for single-word keywords for a more rigid workflow.
(setq denote-allow-multi-word-keywords t)
@@ -1719,6 +1813,7 @@ Everything is in place to set up the package.
(define-key map (kbd "C-c n N") #'denote-type)
(define-key map (kbd "C-c n d") #'denote-date)
(define-key map (kbd "C-c n s") #'denote-subdirectory)
+ (define-key map (kbd "C-c n t") #'denote-template)
;; If you intend to use Denote with a variety of file types, it is
;; easier to bind the link-related commands to the `global-map', as
;; shown here. Otherwise follow the same pattern for `org-mode-map',
diff --git a/denote.el b/denote.el
index 0a024ac263..589eaea1de 100644
--- a/denote.el
+++ b/denote.el
@@ -204,6 +204,10 @@ The value is a list of symbols, which includes any of the
following:
Without the `date' prompt, the `denote' command uses the
`current-time'.
+- `template': Prompts for a KEY among `denote-templates'. The
+ value of that KEY is used to populate the new note with
+ content, which is added after the front matter.
+
The prompts occur in the given order.
If the value of this user option is nil, no prompts are used.
@@ -233,6 +237,7 @@ behaviour of the `denote' command, users can invoke these
convenience commands: `denote-type', `denote-subdirectory',
`denote-date'."
:group 'denote
+ :package-version '(denote . "0.5.0")
:link '(info-link "(denote) The denote-prompts option")
:type '(radio (const :tag "Use no prompts" nil)
(set :tag "Available prompts" :greedy t
@@ -240,7 +245,8 @@ convenience commands: `denote-type', `denote-subdirectory',
(const :tag "Keywords" keywords)
(const :tag "Date" date)
(const :tag "File type extension" file-type)
- (const :tag "Subdirectory" subdirectory))))
+ (const :tag "Subdirectory" subdirectory)
+ (const :tag "Template" template))))
(defcustom denote-sort-keywords t
"Whether to sort keywords in new files.
@@ -313,6 +319,29 @@ are described in the doc string of `format-time-string'."
:package-version '(denote . "0.2.0")
:group 'denote)
+(defcustom denote-templates nil
+ "Alist of content templates for new notes.
+A template is arbitrary text that Denote will add to a newly
+created note right below the front matter.
+
+Templates are expressed as a (KEY . STRING) association.
+
+- The KEY is the name which identifies the template. It is an
+ arbitrary symbol, such as `report', `memo', `statement'.
+
+- The STRING is ordinary text that Denote will insert as-is. It
+ can contain newline characters to add spacing. The manual of
+ Denote contains examples on how to use the `concat' function,
+ beside writing a generic string.
+
+The user can choose a template either by invoking the command
+`denote-template' or by changing the user option `denote-prompts'
+to always prompt for a template when calling the `denote'
+command."
+ :type '(alist :key-type symbol :value-type string)
+ :package-version '(denote . "0.5.0")
+ :group 'denote)
+
;;;; Main variables
;; For character classes, evaluate: (info "(elisp) Char Classes")
@@ -906,7 +935,7 @@ where the former does not read dates without a time
component."
;;;;; The `denote' command and its prompts
;;;###autoload
-(defun denote (&optional title keywords file-type subdirectory date)
+(defun denote (&optional title keywords file-type subdirectory date template)
"Create a new note with the appropriate metadata and file name.
When called interactively, the metadata and file name are prompted
@@ -929,16 +958,21 @@ When called from Lisp, all arguments are optional.
- DATE is a string representing a date like 2022-06-30 or a date
and time like 2022-06-16 14:30. A nil value or an empty string
- is interpreted as the `current-time'."
+ is interpreted as the `current-time'.
+
+- TEMPLATE is a symbol which represents the key of a cons cell in
+ the user option `denote-template'. The value of that key is
+ inserted to the newly created buffer after the front matter."
(interactive
- (let ((args (make-vector 5 nil)))
+ (let ((args (make-vector 6 nil)))
(dolist (prompt denote-prompts)
(pcase prompt
('title (aset args 0 (denote--title-prompt)))
('keywords (aset args 1 (denote--keywords-prompt)))
('file-type (aset args 2 (denote--file-type-prompt)))
('subdirectory (aset args 3 (denote--subdirs-prompt)))
- ('date (aset args 4 (denote--date-prompt)))))
+ ('date (aset args 4 (denote--date-prompt)))
+ ('template (aset args 5 (denote--template-prompt)))))
(append args nil)))
(let* ((file-type (denote--file-type-symbol (or file-type denote-file-type)))
(date (if (or (null date) (string-empty-p date))
@@ -947,9 +981,14 @@ When called from Lisp, all arguments are optional.
(id (format-time-string denote--id-format date))
(directory (if (denote--dir-in-denote-directory-p subdirectory)
(file-name-as-directory subdirectory)
- (denote-directory))))
+ (denote-directory)))
+ (template (if (stringp template) template (alist-get template
denote-templates))))
(denote--barf-duplicate-id id)
(denote--prepare-note (or title "") keywords date id directory file-type)
+ (when template
+ (with-current-buffer (get-file-buffer denote-last-path)
+ (goto-char (point-max))
+ (insert template)))
(denote--keywords-add-to-history keywords)))
(defvar denote--title-history nil
@@ -1005,6 +1044,19 @@ here for clarity."
(dirs (push root subdirs)))
(denote--subdirs-completion-table dirs)))
+(defvar denote--template-history nil
+ "Minibuffer history of `denote--template-prompt'.")
+
+(defun denote--template-prompt ()
+ "Prompt for template KEY from `denote-templates'."
+ (let ((templates denote-templates))
+ (alist-get
+ (intern
+ (completing-read
+ "Select template KEY: " (mapcar #'car templates)
+ nil t nil 'denote--template-history))
+ templates)))
+
;;;;; Convenience commands as `denote' variants
(defalias 'denote-create-note (symbol-function 'denote))
@@ -1054,6 +1106,23 @@ set to \\='(subdirectory title keywords)."
(defalias 'denote-create-note-in-subdirectory (symbol-function
'denote-subdirectory))
+;;;###autoload
+(defun denote-template ()
+ "Create note while prompting for a template.
+
+Available candidates include the keys in the `denote-templates'
+alist. The value of the selected key is inserted in the newly
+created note after the front matter.
+
+This is equivalent to calling `denote' when `denote-prompts' is
+set to \\='(template title keywords)."
+ (declare (interactive-only t))
+ (interactive)
+ (let ((denote-prompts '(template title keywords)))
+ (call-interactively #'denote)))
+
+(defalias 'denote-create-note-with-template (symbol-function 'denote-template))
+
;;;; Note modification
;;;;; Common helpers for note modifications