[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/denote 10f8195352 2/3: Revise all journal-related docum
From: |
ELPA Syncer |
Subject: |
[elpa] externals/denote 10f8195352 2/3: Revise all journal-related documentation; expand denote-journal-extras |
Date: |
Mon, 18 Sep 2023 09:57:42 -0400 (EDT) |
branch: externals/denote
commit 10f819535285f6f7ed7148a5db36e70b321db3d7
Author: Protesilaos Stavrou <info@protesilaos.com>
Commit: Protesilaos Stavrou <info@protesilaos.com>
Revise all journal-related documentation; expand denote-journal-extras
This is a follow-up to the discussion on the mailing list with the
participation of Vedang Manerikar:
<https://lists.sr.ht/~protesilaos/denote/patches/43255#%3C20230803170935.60833-2-ved.manerikar@gmail.com%3E>.
---
README.org | 179 +++++++++++++++++++++--------------------------
denote-journal-extra.el | 86 -----------------------
denote-journal-extras.el | 153 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 233 insertions(+), 185 deletions(-)
diff --git a/README.org b/README.org
index 717a7df4f2..d84800dd15 100644
--- a/README.org
+++ b/README.org
@@ -2215,78 +2215,62 @@ specialised third-party packages. This section covers
the details.
:CUSTOM_ID: h:4a6d92dd-19eb-4fcc-a7b5-05ce04da3a92
:END:
-While there are subtle technical differences between a journal and a
-diary, we will consider those equivalent in the interest of brevity:
-they both describe a personal space that holds a record of your thoughts
-about your experiences and/or view of events in the world.
-
-Suppose you are committed to writing an entry every day. Unlike what we
-demonstrated before, your writing will follow a regular naming pattern.
-You know that the title of the new note must always look like =Tuesday
-14 June 2022= and the keyword has to be =journal= or =diary=. As such,
-you want to automate the task instead of being prompted each time, as is
-the norm with ~denote~ and the relevant commands
([[#h:17896c8c-d97a-4faa-abf6-31df99746ca6][Points of entry]]).
-This is easy to accomplish because ~denote~ can be called from Lisp and
-given the required arguments of =TITLE= and =KEYWORDS= directly. All
-you need is a simple wrapper function:
+[ Rewritten as part of {{{development-version}}}, which now includes
+ the optional =denote-journal-extras.el= file that the user can load
+ as part of their Denote setup. ]
-#+begin_src emacs-lisp
-(defun my-denote-journal ()
- "Create an entry tagged 'journal' with the date as its title."
- (interactive)
- (denote
- (format-time-string "%A %e %B %Y") ; format like Tuesday 14 June 2022
- '("journal"))) ; multiple keywords are a list of strings: '("one" "two")
-#+end_src
-
-By invoking ~my-denote-journal~ you will go straight into the newly
-created note and commit to your writing outright.
-
-Of course, you can always set up the function so that it asks for a
-=TITLE= but still automatically applies the =journal= tag:
+Denote provides a general-purpose mechanism to create new files that
+broadly count as "notes" ([[#h:17896c8c-d97a-4faa-abf6-31df99746ca6][Points of
entry]]). Such files can be daily
+entries in a journal. While it is possible to use the generic
+~denote~ command to maintain a journal, we provide an optional set of
+convenience options and commands as part of =denote-journal-extras.el=.
+To use those, add the following the Denote configuration:
#+begin_src emacs-lisp
-(defun denote-journal-with-title ()
- "Create an entry tagged 'journal', while prompting for a title."
- (interactive)
- (denote
- (denote-title-prompt) ; ask for title, instead of using human-readable date
- '("journal")))
+(require 'denote-journal-extras.el)
#+end_src
-The above snippets do not check if a daily entry exists: they always
-create a new one. The idea is that one may want to write multiple
-journal entries per day. Another approach is to create a single entry
-on a given day, in which case the command must be repurposed to
-surface the existing note, if present. As with ~my-denote-journal~
-above, the title is formatted as =Tuesday 14 June 2022=.
-
-#+begin_src emacs-lisp
-(defun my-denote-journal ()
- "Create an entry tagged 'journal' with the date as its title.
-If a journal for the current day exists, visit it. If multiple
-entries exist, prompt with completion for a choice between them.
-Else create a new file."
- (interactive)
- (let* ((today (format-time-string "%A %e %B %Y"))
- (string (denote-sluggify today))
- (files (denote-directory-files-matching-regexp string)))
- (cond
- ((> (length files) 1)
- (find-file (completing-read "Select file: " files nil :require-match)))
- (files
- (find-file (car files)))
- (t
- (denote
- today
- '("journal"))))))
-#+end_src
+#+findex: denote-journal-extras-new-entry
+#+vindex: denote-journal-extras-keyword
+#+vindex: denote-journal-extras-directory
+The command ~denote-journal-extras-new-entry~ creates a new entry in
+the journal. Such a file has the ~denote-journal-extras-keyword~,
+which is =journal= by default ([[#h:4e9c7512-84dc-4dfb-9fa9-e15d51178e5d][The
file-naming scheme]]). The user can
+set this keyword to an arbitrary string (single word is preferred).
+New journal entries can be stored in the ~denote-directory~ or
+subdirectory thereof. To make it easier for the user, the new journal
+entry will be placed in ~denote-journal-extras-directory~, which
+defaults to a subdirectory of ~denote-directory~ called =journal=.
+
+#+vindex: denote-journal-extras-title-format
+Furthermore, the command ~denote-journal-extras-new-entry~ will use
+the current date as the title of the new entry. The exact format is
+controlled by the user option ~denote-journal-extras-title-format~.
+Refer to its documentation for the available formats. If the value of
+this user option is ~nil~, then ~denote-journal-extras-new-entry~ will
+prompt for a title.
+
+In terms of workflow, using the current date as the title is better
+for maintaining a daily journal. A prompt for an arbitrary title is
+more suitable for those who like to keep a record of something like a
+thought or event (though this can also be achieved by the regular
+~denote~ command or maybe ~denote-subdirectory~).
+
+#+vindex: denote-journa-extras-hook
+The ~denote-journal-extras-new-entry~ command calls the normal hook
+~denote-journa-extras-hook~ after it is done. The user can leverage
+this to produce consequences therefrom, such as to set a timer with
+the ~tmr~ package from GNU ELPA
([[#h:4af1f81e-e93a-43cc-b344-960032a16d42][Journaling with a timer]]).
*** Journaling with a timer
:PROPERTIES:
:CUSTOM_ID: h:4af1f81e-e93a-43cc-b344-960032a16d42
:END:
+[ Revised as part of {{{development-version}}} to conform with how we
+ now tend to the needs of users who use Denote for journaling
+ purposes ([[#h:4a6d92dd-19eb-4fcc-a7b5-05ce04da3a92][Keep a journal or
diary]]). ]
+
Sometimes journaling is done with the intent to hone one's writing
skills. Perhaps you are learning a new language or wish to communicate
your ideas with greater clarity and precision. As with everything that
@@ -2295,29 +2279,49 @@ write, write!
One way to test your progress is to set a timer. It helps you gauge
your output and its quality. To use a timer with Emacs, consider the
-=tmr= package:
+~tmr~ package. A new timer can be set with something like this:
#+begin_src emacs-lisp
-(defun my-denote-journal-with-tmr ()
- "Like `my-denote-journal', but also set a 10-minute timer.
-The `tmr' command is part of the `tmr' package."
- (interactive)
- (denote
- (format-time-string "%A %e %B %Y")
- '("journal"))
- (tmr "10" "Practice writing in my journal")) ; set 10 minute timer with a
description
+;; Set 10 minute timer with the given description
+(tmr "10" "Practice writing in my journal")
+#+end_src
+
+To make this timer start as soon as a new journal entry is created
+with the command ~denote-journal-extras-new-entry~, add a function to
+the ~denote-journa-extras-hook~. For example:
+
+#+begin_src emacs-lisp
+;; Add an anonymous function, which is more difficult to modify after
+;; the fact:
+(add-hook 'denote-journa-extras-hook (lambda ()
+ (tmr "10" "Practice writing in my
journal")))
+
+;; Or write a small function that you can then modify without
+;; revaluating the hook:
+(defun my-denote-tmr ()
+ (tmr "10" "Practice writing in my journal"))
+
+(add-hook 'denote-journa-extras-hook 'my-denote-tmr)
+
+;; Or to make it fully featured, define variables for the duration and
+;; the description and set it up so that you only need to modify
+;; those:
+(defvar my-denote-tmr-duration "10")
+
+(defvar my-denote-tmr-description "Practice writing in my journal")
+
+(defun my-denote-tmr ()
+ (tmr my-denote-tmr-duration my-denote-tmr-description))
+
+(add-hook 'denote-journa-extras-hook 'my-denote-tmr)
#+end_src
Once the timer elapses, stop writing and review your performance.
Practice makes perfect!
-[ As Denote matures, we may add hooks to control what happens before or
- after the creation of a new note. We shall also document more
- examples of tasks that can be accomplished with this package. ]
+Sources for ~tmr~:
-Sources for =tmr=:
-
-+ Package name (GNU ELPA): =tmr=
++ Package name (GNU ELPA): ~tmr~
+ Official manual: <https://protesilaos.com/emacs/tmr>
+ Change log: <https://protesilaos.com/emacs/denote-changelog>
+ Git repo on SourceHut: <https://git.sr.ht/~protesilaos/tmr>
@@ -3303,32 +3307,9 @@ Everything is in place to set up the package.
;; OR if only want it in `denote-dired-directories':
(add-hook 'dired-mode-hook #'denote-dired-mode-in-directories)
-;; Here is a custom, user-level command from one of the examples we
-;; showed in this manual. We define it here and add it to a key binding
-;; below.
-(defun my-denote-journal ()
- "Create an entry tagged 'journal' with the date as its title.
-If a journal for the current day exists, visit it. If multiple
-entries exist, prompt with completion for a choice between them.
-Else create a new file."
- (interactive)
- (let* ((today (format-time-string "%A %e %B %Y"))
- (string (denote-sluggify today))
- (files (denote-directory-files-matching-regexp string)))
- (cond
- ((> (length files) 1)
- (find-file (completing-read "Select file: " files nil :require-match)))
- (files
- (find-file (car files)))
- (t
- (denote
- today
- '("journal"))))))
-
;; Denote DOES NOT define any key bindings. This is for the user to
;; decide. For example:
(let ((map global-map))
- (define-key map (kbd "C-c n j") #'my-denote-journal) ; our custom command
(define-key map (kbd "C-c n n") #'denote)
(define-key map (kbd "C-c n N") #'denote-type)
(define-key map (kbd "C-c n d") #'denote-date)
diff --git a/denote-journal-extra.el b/denote-journal-extra.el
deleted file mode 100644
index e6ee94513c..0000000000
--- a/denote-journal-extra.el
+++ /dev/null
@@ -1,86 +0,0 @@
-;;; denote-journal-extra.el --- Convenience functions for daily journaling
-*- lexical-binding: t; -*-
-
-;; Copyright (C) 2023 Free Software Foundation, Inc.
-
-;; Author: Protesilaos Stavrou <info@protesilaos.com>
-;; Maintainer: Denote Development <~protesilaos/denote@lists.sr.ht>
-;; URL: https://git.sr.ht/~protesilaos/denote
-;; Mailing-List: https://lists.sr.ht/~protesilaos/denote
-
-;; This file is NOT part of GNU Emacs.
-
-;; This program is free software; you can redistribute it and/or modify
-;; it under the terms of the GNU General Public License as published by
-;; the Free Software Foundation, either version 3 of the License, or
-;; (at your option) any later version.
-
-;; This program is distributed in the hope that it will be useful,
-;; but WITHOUT ANY WARRANTY; without even the implied warranty of
-;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-;; GNU General Public License for more details.
-
-;; You should have received a copy of the GNU General Public License
-;; along with this program. If not, see <https://www.gnu.org/licenses/>.
-
-;;; Commentary:
-
-;;
-
-;;; Code:
-
-(require 'denote)
-
-(defgroup denote-journal-extra nil
- "Denote for daily journaling."
- :group 'denote
- :link '(info-link "(denote) Top")
- :link '(url-link :tag "Homepage" "https://protesilaos.com/emacs/denote"))
-
-(defcustom denote-journal-extra-directory
- (expand-file-name "journal" denote-directory)
- "Directory for storing daily journal entries."
- :group 'denote-journal-extra
- :type 'directory)
-
-(defun denote-journal-extra--make-journal-directory ()
- "Make the variable `denote-journal-extra-directory' and its parents."
- (when (and (stringp denote-journal-extra-directory)
- (not (file-directory-p denote-journal-extra-directory)))
- (make-directory denote-journal-extra-directory :parents)))
-
-(defcustom denote-journal-extra-templates
- '((journal-morningpage . "* The Morning Journaling Routine
-
-Stream of consciousness writing to empty your mind.")
- (journal-emotion . "* I am feeling <emotion>
-
-- Capture your emotion here.")
- (journal-insight . "* I had an insight! :insight:
-
-- Capture your insight here")
- (journal-checkin . "* The Daily Ongoing Check-in
-
-- Capture your generic check-in here"))
- "Templates for your daily journal entries."
- :type '(alist :key-type symbol :value-type string)
- :link '(info-link "(denote) The denote-templates option")
- :group 'denote-journal-extra)
-
-(dolist (tem denote-journal-extra-templates)
- (add-to-list 'denote-templates tem))
-
-(defun denote-journal-extra-new-stand-alone-journal-entry ()
- "Create a new stand-alone journal entry in `denote-journal-extra-directory`."
- (interactive)
- (denote-journal-extra--make-journal-directory)
- (let ((denote-user-enforced-denote-directory denote-journal-extra-directory))
- (denote
- ;; format like Tuesday 14 June 2022 05:49:37 PM
- (format-time-string "%A %e %B %Y %I:%M:%S %p")
- ;; No need to specify `keywords`, `file-type`, `subdirectory` or `date`
- nil nil nil nil
- ;; Pick the right template for your journal.
- (denote-template-prompt))))
-
-(provide 'denote-journal-extra)
-;;; denote-journal-extra.el ends here
diff --git a/denote-journal-extras.el b/denote-journal-extras.el
new file mode 100644
index 0000000000..28e2c5942e
--- /dev/null
+++ b/denote-journal-extras.el
@@ -0,0 +1,153 @@
+;;; denote-journal-extras.el --- Convenience functions for daily journaling
-*- lexical-binding: t; -*-
+
+;; Copyright (C) 2023 Free Software Foundation, Inc.
+
+;; Author: Protesilaos Stavrou <info@protesilaos.com>
+;; Maintainer: Denote Development <~protesilaos/denote@lists.sr.ht>
+;; URL: https://git.sr.ht/~protesilaos/denote
+;; Mailing-List: https://lists.sr.ht/~protesilaos/denote
+
+;; This file is NOT part of GNU Emacs.
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This is a set of optional convenience functions that used to be
+;; provided in the Denote manual. They facilitate the use of Denote
+;; for daily journaling.
+
+;;; Code:
+
+(require 'denote)
+
+(defgroup denote-journal-extras nil
+ "Denote for daily journaling."
+ :group 'denote
+ :link '(info-link "(denote) Top")
+ :link '(url-link :tag "Homepage" "https://protesilaos.com/emacs/denote"))
+
+(defcustom denote-journal-extras-directory
+ (expand-file-name "journal" denote-directory)
+ "Directory for storing daily journal entries.
+This can either be the same as the variable `denote-directory' or
+a subdirectory of it."
+ :group 'denote-journal-extras
+ :type 'directory)
+
+(defcustom denote-journal-extras-keyword "journal"
+ "Single word keyword to tag journal entries.
+It is used by `denote-journal-extras-new-entry' to add a keyword
+to the newly created file."
+ :group 'denote-journal-extras
+ :type 'string)
+
+(defcustom denote-journal-extras-title-format 'day-date-month-year-24h
+ "Date format to construct the title with `denote-journal-extras-new-entry'.
+The value is either a symbol or an arbitrary string that is
+passed to `format-time-string' (consult its documentation for the
+technicalities).
+
+Acceptable symbols and their corresponding styles are:
+
+| Symbol | Style |
+|-------------------------+-----------------------------------|
+| day-date-month-year | Monday 19 September 2023 |
+| day-date-month-year-24h | Monday 19 September 2023 20:49 |
+| day-date-month-year-12h | Monday 19 September 2023 08:49 PM |
+
+With a nil value, make `denote-journal-extras-new-entry' prompt
+for a title."
+ :group 'denote-journal-extras
+ :type '(choice
+ (const :tag "Prompt for title with
`denote-journal-extras-new-entry'" nil)
+ (const :tag "Monday 19 September 2023" :value "%A %e %B %Y"
day-date-month-year)
+ (const :tag "Monday 19 September 2023 20:49" :value "%A %e %B %Y
%H:%M" day-date-month-year-24h)
+ (const :tag "Monday 19 September 2023 08:49 PM" :value "%A %e %B %Y
%I:%M %^p" day-date-month-year-12h)
+ (string :tag "Custom string with `format-time-string' specifiers")))
+
+(defcustom denote-journa-extras-hook nil
+ "Normal hook called after `denote-journal-extras-new-entry'.
+Use this to, for example, set a timer after starting a new
+journal entry (refer to the `tmr' package on GNU ELPA)."
+ :group 'denote-journal-extras
+ :type 'hook)
+
+(defun denote-journal-extras-directory ()
+ "Make the variable `denote-journal-extras-directory' and its parents."
+ (when-let (((stringp denote-journal-extras-directory))
+ (directory (file-name-as-directory (expand-file-name
denote-journal-extras-directory))))
+ (when (not (file-directory-p denote-journal-extras-directory))
+ (make-directory directory :parents))
+ directory))
+
+(defun denote-journal-extras-daily--title-format ()
+ "Return `denote-journal-extras-title-format' or prompt for title."
+ (cond
+ ((stringp denote-journal-extras-title-format)
+ (format-time-string denote-journal-extras-title-format))
+ ((symbolp denote-journal-extras-title-format)
+ (format-time-string
+ (pcase denote-journal-extras-title-format
+ ('day-date-month-year "%A %e %B %Y")
+ ('day-date-month-year-24h "%A %e %B %Y %H:%M")
+ ('day-date-month-year-12h "%A %e %B %Y %I:%M %^p"))))
+ (t (denote-title-prompt (format-time-string "%F")))))
+
+;;;###autoload
+(defun denote-journal-extras-new-entry ()
+ "Create a new journal entry in variable `denote-journal-extras-directory'.
+Use `denote-journal-extras-keyword' as a keyword for the newly
+created file."
+ (interactive)
+ (let ((denote-user-enforced-denote-directory
(denote-journal-extras-directory)))
+ ;; TODO 2023-09-18: Let's see how best to incorporate templates.
+ ;; I think it is better to use the `denote-templates' variable,
+ ;; since this is what we have it for. Perhaps we can make the
+ ;; behaviour do-what-I-mean, such that the user is prompted for a
+ ;; template only if one exists. Otherwise, no template is used.
+ (denote
+ (denote-journal-extras-daily--title-format)
+ `(,denote-journal-extras-keyword))
+ (run-hooks 'denote-journa-extras-hook)))
+
+(defun denote-journal-extras--entry-today ()
+ "Return list of files matching a journal for today."
+ (denote-directory-files-matching-regexp
+ (format "%sT[0-9]\\{6\\}.*_%s"
+ (format-time-string "%Y%m%d")
+ denote-journal-extras-keyword)))
+
+;;;###autoload
+(defun denote-journal-extras-new-or-existing-entry ()
+ "Locate an existing journal entry or create a new one.
+A journal entry is one that has `denote-journal-extras-keyword' as
+part of its file name.
+
+If there are multiple journal entries for the current date,
+prompt for one using minibuffer completion. If there is only
+one, visit it outright. If there is no journal entry, create one
+by calling `denote-journal-extra-new-entry'."
+ (interactive)
+ (let ((files (denote-journal-extras--entry-today)))
+ (cond
+ ((length> files 1)
+ (find-file (completing-read "Select journal entry: " files nil
:require-match)))
+ (files
+ (find-file (car files)))
+ (t
+ (call-interactively 'denote-journal-extras-new-entry)))))
+
+(provide 'denote-journal-extras)
+;;; denote-journal-extras.el ends here