Hi,

I recently ran into an issue that caused me some confusion when trying to
use org-capture with a capture template that specifies a target of file+olp.

I was trying to capture into a file (in my case org-roam-dailies file,
however the issue is independent of org-roam) with the following headings:
* Today
* Maybe Today

However, when I try to run a capture that targets the "Today" heading I
receive the error "org-find-olp: Heading not unique on level 1: Today".

The problem is that I have also configured "MAYBE" as a keyword in
org-todo-keywords and this seems to be causing org-find-olp to consider the
headline "* Maybe Today" as a TODO with status MAYBE and a headline title
of "Today" and thus thinks there are two headlines with the title "Today".
This is inconsistent with the behaviour I get when I put point on that
headline and run (org-get-todo-state) which returns 'nil.

The logic in org-find-olp uses the regular expression
org-complex-heading-regexp-format to try to match the heading. This regular
expression is built to match headlines beginning with leading * followed by
optional keywords, optional statistics cookie and then the headline text
being searched for, and finally any optional tags.

The problem is that org-find-olp does not set case-fold-search to nil and
so the regular expression matching performs a case-insensitive match.

The org-complex-heading-regexp variable has a comment that indicates that
case-fold-search should be bound to nil when matching against the regexp.
The org-complex-heading-regexp-format variable does not have a similar
statement, however it does refer to "... match the headline of any node
which has the *exact headline* text that is put into the format, ..." which
indicates that perhaps uses of this regex should also have case-fold-search
bound to nil.

I suspect a similar issue is present for an org-capture target of
file+headline, as it also uses the org-complex-heading-regexp-format
variable without setting case-fold-search to nil.

Note that fixing this issue by binding case-fold-search to nil would be
potentially breaking for users that may rely on case-insensitive matching
of the headline text, however. If it is desired to perform a
case-insensitive match against the headline text then it should be possible
to build a regex that matches the text in a case-insensitive way. e.g. by
substituting "[Tt][Oo][Dd][Aa][Yy]" into org-complex-heading-regexp-format
instead of "Today" (ideally adhering to customizations of
char-fold-include,  char-fold-exclude, etc.). The function
char-fold-to-regexp should perform the necessary translation if required.

This should be reproducible by running:

(setq org-capture-templates
      '(("t" "Do today" entry
         (file+olp "daily.org" "Today")
         "* TODO %?")
        ("m" "Maybe do today" entry
         (file+olp "daily.org" "Maybe Today")
         "* TODO %?")))
(setq org-todo-keywords
      '((sequence "TODO(t)" "MAYBE(m)" "|" "DONE(d)")))

And then creating a daily.org file that contains the following contents:
* Today
* Maybe Today

And then running (org-capture nil "t")

Observe that the error (error "Heading not unique on level 1: Today") is
raised.

I am using org-mode 9.7.26 and emacs-30.1.

Thanks,
Lewis.

Reply via email to