branch: externals/org-mem
commit 5d8baaf0c5e4f480887794731cfa60e054042696
Author: Martin Edström <[email protected]>
Commit: Martin Edström <[email protected]>
Doc
---
README.org | 60 +++++++++++++++++++++++++++-------------------
org-mem-updater.el | 4 +++-
org-mem.el | 4 ++--
org-mem.texi | 70 +++++++++++++++++++++++++++++++++++-------------------
4 files changed, 87 insertions(+), 51 deletions(-)
diff --git a/README.org b/README.org
index a4895caae1..3b4774da58 100644
--- a/README.org
+++ b/README.org
@@ -28,7 +28,7 @@ And they must do this, because Org ships no tool to query
across lots of files.
Well---Org does ship the agenda, which has tools. But you know what happens
if you put 2,000 files into =org-agenda-files=! It needs to open each file in
real-time to check anything in them, so everyday commands grind to a halt, or
even crash: many OSes have a cap of 1,024 simultaneous file handles.
-** Quick start
+* Quick start
Example setup:
@@ -43,7 +43,7 @@ See an example in detail by typing =M-x org-mem-list-example=.
You do not even need to configure =org-mem-watch-dirs=, if Org is loaded.
Org-mem will guess where to look for Org files anyway! That is controlled by
the user option =org-mem-do-look-everywhere= (default t).
-** Two APIs
+* Two APIs
You get two different APIs to pick from, to access the same data.
- Emacs Lisp
@@ -53,7 +53,7 @@ Why two? It's free. When the data has been gathered anyway,
there is no reason
Famously, org-roam uses a SQLite DB. My package org-node used simple hash
tables. Now you get both, without having to install either.
-** Data only
+* Data only
A design choice: Org-mem *only* delivers data. It could easily ship
conveniences like, let's call it a function "org-mem-goto":
@@ -68,7 +68,7 @@ but in my experience, that will spiral into dozens of lines
over time, to handle
So, it is up to you to write your own "goto" function, and all else to do with
user interaction.
-** No Org at init
+* No Org at init
A design choice: Org-mem does not use Org code to analyze your files, but a
[[https://github.com/meedstrom/org-mem/blob/main/org-mem-parser.el][custom,
more dumb parser]]. That's for three reasons:
@@ -88,13 +88,13 @@ A design choice: Org-mem does not use Org code to analyze
your files, but a [[ht
In fact, =org-mem-updater-mode= does a bit of both, because it is still
important that saving a file does not lag; it does its best to update only the
necessary tables on save, and an idle timer triggers a full reset every now and
then.
-** A SQLite database, for free
+* A SQLite database, for free
Included is a drop-in for [[https://github.com/org-roam/org-roam][org-roam's]]
=(org-roam-db)=, called =(org-mem-roamy-db)=.
In the future we may also create something that fits
[[https://github.com/ndwarshuis/org-sql/blob/80bea9996de7fa8bc7ff891a91cfaff91111dcd8/org-sql.el#L141][org-sql]]'s
DB schemata, or something custom, but we'll see!
-*** Without org-roam installed
+** Without org-roam installed
Activating the mode creates an in-memory database by default.
@@ -110,8 +110,8 @@ Test that it works:
For more tips, see section [[https://github.com/meedstrom/org-mem#sql-api][SQL
API]].
-** Elisp API
-*** Example: Let org-agenda cast its net wide
+* Elisp API
+** Example: Let org-agenda cast its net wide
You can't put 2,000 files in =org-agenda-files=, but most contain nothing of
interest for the agenda anyway, right?
@@ -136,7 +136,7 @@ Turns out I have only about 30 files worth checking, the
challenge was always kn
(org-mem-updater-mode)
#+end_src
-*** Example: Warn about dangling clocks at init
+** Example: Warn about dangling clocks at init
While Org can warn about dangling clocks through the =org-clock-persist=
setting, that requires loading Org at some point during your session. Which
means that if it is a matter of concern for you to forget you had a clock
going, that you effectively have to put =(require 'org)= in your initfiles,
/just in case/.
@@ -155,7 +155,7 @@ Now the following is an alternative:
(org-mem-updater-mode)
#+end_src
-*** Force an update
+** Force an update
If you want to force-update the cache in synchronous code, you should now
(since version 0.28.0) be able to do it like this.
@@ -170,7 +170,7 @@ To do a full reset:
(org-mem-await "Manually resetting..." 60)
#+END_SRC
-*** Entries and links
+** Entries and links
We use two types of objects to help represent file contents: =org-mem-entry=
objects and =org-mem-link= objects. They involve some simplifications:
@@ -190,7 +190,7 @@ We use two types of objects to help represent file
contents: =org-mem-entry= obj
That is hopefully intuitive. Opinions on API design are very welcome!
-*** Full list of functions
+** Full list of functions
Updated [2026-02-26].
Getters taking no arguments
@@ -363,8 +363,8 @@ Some API for actually activating & using org-mem as a
library:
- =org-mem-reset=
- =org-mem-updater-update=
-** SQL API
-*** With org-roam installed
+* SQL API
+** With org-roam installed
You can use this to end your dependence on =org-roam-db-sync=. Set the
following to let org-mem overwrite the "org-roam.db" file.
@@ -389,7 +389,7 @@ N/B: because =(equal (org-roam-db) (org-mem-roamy-db))=,
the above is equivalent
(emacsql (org-mem-roamy-db) [:select * :from files :limit 10])
#+end_src
-*** To developers
+** To developers
If you write a package that actually only needed to use org-roam's DB and not
its other utilities like =org-roam-capture=, you should be able to stop
requiring org-roam, and do e.g.
@@ -410,18 +410,18 @@ In theory, anyway ;-)
Please report any issues!
-*** Known issue
+** Known issue
Error "attempt to write a readonly database" can happen when when you run
multiple Emacs instances. Get unstuck with =M-: (org-roam-db--close-all)=.
-*** View what info is in the DB
+** View what info is in the DB
Use =M-x org-mem-list-db-contents=.
Or the new =M-x org-roam-db-explore=, with exactly the same UI.
-** Tips
-*** Encrypted files (=.org.gpg= =.org.age=)
+* Tips
+** Encrypted files (=.org.gpg= =.org.age=)
Suppose you use [[https://github.com/anticomputer/age.el][age.el]] to keep
files encrypted.
@@ -434,22 +434,34 @@ This needs extra config to tell org-mem's subprocesses
how to open them. The fol
#+end_src
-** Current limitations
-*** Limitation: TRAMP
+* Current limitations
+** Limitation: TRAMP
Files over TRAMP are excluded from org-mem's database, so as far as org-mem is
concerned, it is as if they do not exist.
This limitation comes from the fact that org-mem parses your files in many
parallel subprocesses that do not inherit your TRAMP connections. It is
fixable in theory.
-*** Limitation: Encrypted entries
+** Limitation: Encrypted entries
The body text of specific entries may be encrypted by =org-crypt=. If so,
org-mem cannot find links nor timestamps inside.
-*** Limitation: SETUPFILE
+** Limitation: SETUPFILE
No support yet for buffer settings from =#+SETUPFILE:=.
-** Future work
+** Limitation: diary-sexps
+
+If you have a timestamp that's not a plain
+
+: SCHEDULED: [2026-03-06 Fri 06:11]
+
+but a diary-sexp like
+
+: SCHEDULED: <%%(memq (calendar-day-of-week date) (1 2 3 4 5)))>
+
+then =(org-mem-entry-scheduled ENTRY)= returns nil, unfortunately.
+
+* Future work
Use Org's own parser.
diff --git a/org-mem-updater.el b/org-mem-updater.el
index 6783d8bbce..6328b40486 100644
--- a/org-mem-updater.el
+++ b/org-mem-updater.el
@@ -176,7 +176,7 @@ for every FILE, but wait and do a massed invocation
afterwards."
(cancel-timer org-mem-updater--reset-timer)))
-;;; Instant placeholders
+;;; Instant placeholders (OBSOLETE)
(declare-function org-current-level "org")
(declare-function org-element-context "org-element")
@@ -258,6 +258,7 @@ Use this if you cannot wait for `org-mem-updater-mode' to
pick it up."
(point-max))
org-mem--truename<>metadata)))))
+;; Obsolete but good to keep as reference
(defun org-mem-updater-mk-link-atpt ()
"Return an `org-mem-link' object appropriate for link at point.
It is not associated with any entries or files, however.
@@ -289,6 +290,7 @@ No support for citations."
entry-text)))
(error "No link at point %d in %s" (point) (current-buffer))))
+;; Obsolete but good to keep as reference
(defun org-mem-updater-mk-entry-atpt ()
"Return an `org-mem-entry' object appropriate for entry at point.
It is not associated with any links or files, however.
diff --git a/org-mem.el b/org-mem.el
index 4480160e01..d066773a17 100644
--- a/org-mem.el
+++ b/org-mem.el
@@ -793,7 +793,7 @@ Combines `org-mem-entry-tags-local' and
`org-mem-entry-tags-inherited'."
(defun org-mem-entry-deadline (entry)
"DEADLINE-timestamp of ENTRY, suitable for `iso8601-parse'.
WARNING: If the timestamp is expressed as a diary-sexp,
-such as <%%\(memq (calendar-day-of-week date) \\='(1 2 3 4 5)))>,
+such as <%%(memq (calendar-day-of-week date) \\='(1 2 3 4 5)))>,
this returns nil!"
(with-memoization (org-mem--table 46 entry)
(let ((ts (org-mem-entry-deadline-int entry)))
@@ -802,7 +802,7 @@ this returns nil!"
(defun org-mem-entry-scheduled (entry)
"SCHEDULED-timestamp of ENTRY, suitable for `iso8601-parse'.
WARNING: If the timestamp is expressed as a diary-sexp,
-such as <%%\(memq (calendar-day-of-week date) \\='(1 2 3 4 5)))>,
+such as <%%(memq (calendar-day-of-week date) \\='(1 2 3 4 5)))>,
this returns nil!"
(with-memoization (org-mem--table 47 entry)
(let ((ts (org-mem-entry-scheduled-int entry)))
diff --git a/org-mem.texi b/org-mem.texi
index 7b459aa2e8..a6f4a6d559 100644
--- a/org-mem.texi
+++ b/org-mem.texi
@@ -1,7 +1,7 @@
\input texinfo @c -*- texinfo -*-
@c %**start of header
@setfilename org-mem.info
-@settitle Org-mem
+@settitle
@documentencoding UTF-8
@documentlanguage en
@c %**end of header
@@ -13,37 +13,17 @@
@finalout
@titlepage
-@title Org-mem
+@title
@author Martin Edström
@end titlepage
@ifnottex
@node Top
-@top Org-mem
-
-A cache of metadata about the contents of all your Org files --
headings@comma{} links@comma{} timestamps and so on.
-
-Builds quickly@comma{} so that there is no need to persist data across
sessions.
-
-My @samp{M-x org-mem-reset}:
-
-@example
-Org-mem saw 2418 files@comma{} 8388 headings@comma{} 8624 links (3418
IDs@comma{} 4874 ID-links) in 1.95s
-@end example
-
-This library came from asking myself "what could I move out of
@uref{https://github.com/meedstrom/org-node, org-node}@comma{} that'd make
sense in core?" Maybe a proposal for upstream@comma{} or at least a
proof-of-concept.
-
-Many notetaking packages now reinvent the wheel@comma{} when it comes to
keeping track of some or many files and what may be in them.
-
-Example: org-roam's DB@comma{} org-node's hash tables@comma{} and other
packages just re-run grep all the time@comma{} which still leads to writing
elisp to cross-reference the results.
-
-And they must do this@comma{} because Org ships no tool to query across lots
of files.
-
-Well---Org does ship the agenda@comma{} which has tools. But you know what
happens if you put 2@comma{}000 files into @samp{org-agenda-files}! It needs
to open each file in real-time to check anything in them@comma{} so everyday
commands grind to a halt@comma{} or even crash: many OSes have a cap of
1@comma{}024 simultaneous file handles.
-
+@top
@end ifnottex
@menu
+* Org-mem::
* Quick start::
* Two APIs::
* Data only::
@@ -86,10 +66,34 @@ Current limitations
* Limitation TRAMP::
* Limitation Encrypted entries::
* Limitation SETUPFILE::
+* Limitation diary-sexps::
@end detailmenu
@end menu
+@node Org-mem
+@chapter Org-mem
+
+A cache of metadata about the contents of all your Org files --
headings@comma{} links@comma{} timestamps and so on.
+
+Builds quickly@comma{} so that there is no need to persist data across
sessions.
+
+My @samp{M-x org-mem-reset}:
+
+@example
+Org-mem saw 2418 files@comma{} 8388 headings@comma{} 8624 links (3418
IDs@comma{} 4874 ID-links) in 1.95s
+@end example
+
+This library came from asking myself "what could I move out of
@uref{https://github.com/meedstrom/org-node, org-node}@comma{} that'd make
sense in core?" Maybe a proposal for upstream@comma{} or at least a
proof-of-concept.
+
+Many notetaking packages now reinvent the wheel@comma{} when it comes to
keeping track of some or many files and what may be in them.
+
+Example: org-roam's DB@comma{} org-node's hash tables@comma{} and other
packages just re-run grep all the time@comma{} which still leads to writing
elisp to cross-reference the results.
+
+And they must do this@comma{} because Org ships no tool to query across lots
of files.
+
+Well---Org does ship the agenda@comma{} which has tools. But you know what
happens if you put 2@comma{}000 files into @samp{org-agenda-files}! It needs
to open each file in real-time to check anything in them@comma{} so everyday
commands grind to a halt@comma{} or even crash: many OSes have a cap of
1@comma{}024 simultaneous file handles.
+
@node Quick start
@chapter Quick start
@@ -734,6 +738,7 @@ This needs extra config to tell org-mem's subprocesses how
to open them. The fol
* Limitation TRAMP::
* Limitation Encrypted entries::
* Limitation SETUPFILE::
+* Limitation diary-sexps::
@end menu
@node Limitation TRAMP
@@ -753,6 +758,23 @@ The body text of specific entries may be encrypted by
@samp{org-crypt}. If so@
No support yet for buffer settings from @samp{#+SETUPFILE:}.
+@node Limitation diary-sexps
+@section Limitation: diary-sexps
+
+If you have a timestamp that's not a plain
+
+@example
+SCHEDULED: [2026-03-06 Fri 06:11]
+@end example
+
+but a diary-sexp like
+
+@example
+SCHEDULED: <%%(memq (calendar-day-of-week date) (1 2 3 4 5)))>
+@end example
+
+then @samp{(org-mem-entry-scheduled ENTRY)} returns nil@comma{} unfortunately.
+
@node Future work
@chapter Future work