> Thanks!
> Several comments:
>
> 1. You copy-paste org-test-with-temp-text-in-file almost in full,
>    removing (org-mode) call. Why not just doing something like
>    (org-test-with-temp-text-in-file ... (fundamental-mode) ...)?
>

Done.

> 2. Please add Reported-by: and Link: to the report in the commit message.
>

Done.

Le sam. 11 juil. 2026 à 03:57, Ihor Radchenko <[email protected]> a écrit :
>
> Earl Chase <[email protected]> writes:
>
> > I wrote the patch that caused this, so this is my bad. We can't just change
> > the order of "(append valid-symbols (list 'contiguous-spaces
> > 'leading-and-trailing-spaces)))" as you suggested since
> > `org-link--remove-statistics-cookies' and 'org-link--remove-pipe-chars' can
> > add spaces to the search string. So instead we just trim twice, before we
> > attempt to normalize the search string and after we finish normalizing the
> > search string. I added new tests to confirm that this approach works.
>
> Thanks!
> Several comments:
>
> 1. You copy-paste org-test-with-temp-text-in-file almost in full,
>    removing (org-mode) call. Why not just doing something like
>    (org-test-with-temp-text-in-file ... (fundamental-mode) ...)?
>
> 2. Please add Reported-by: and Link: to the report in the commit message.
>
> --
> Ihor Radchenko // yantar92,
> Org mode maintainer,
> Learn more about Org mode at <https://orgmode.org/>.
> Support Org development at <https://liberapay.com/org-mode>,
> or support my work at <https://liberapay.com/yantar92>
From 52b93e0daa687b3cbaa11f805224a4021a041288 Mon Sep 17 00:00:00 2001
From: ApollonDeParnasse <[email protected]>
Date: Thu, 9 Jul 2026 13:04:44 -0500
Subject: [PATCH] lisp/ol.el: Trim search string before attempting to normalize
 it.

* lisp/ol.el (org-link-normalize-string): Trim search string before
attempting to normalize it.
* testing/lisp/test-ol.el (test-org-link/precise-link-target):
New tests for `org-link-precise-link-target'.

Reported-by: Zhengyi Fu <[email protected]>
Link: https://list.orgmode.org/[email protected]/
---
 lisp/ol.el              |   8 ++-
 testing/lisp/test-ol.el | 148 ++++++++++++++++++++++++++++++++++++----
 2 files changed, 139 insertions(+), 17 deletions(-)

diff --git a/lisp/ol.el b/lisp/ol.el
index 96edafa17..3d0e32bcc 100644
--- a/lisp/ol.el
+++ b/lisp/ol.el
@@ -989,10 +989,14 @@ subset of (statistics-cookies search-syntax pipe-chars):
 - `search-syntax' is # in #heading and enclosing () in (ref)
 - `pipe-chars' are | characters that may clash with table syntax."
   (let* ((valid-symbols (seq-intersection ignored-contents (list 'statistics-cookies 'search-syntax 'pipe-chars)))
-         (values-to-remove (append valid-symbols (list 'contiguous-spaces 'leading-and-trailing-spaces))))
+         (values-to-remove (append valid-symbols (list 'contiguous-spaces 'leading-and-trailing-spaces)))
+         ;; We trim twice: before we run our string normalizers
+         ;; and after in order to remove any spaces that were introduced
+         ;; by the normalization process
+         (trimmed-string (org-trim string)))
     (seq-reduce (lambda (str func) (funcall (map-elt org-link--string-normalizers func) str))
                 values-to-remove
-                string)))
+                trimmed-string)))
 
 (defun org-link--reveal-maybe (region _)
   "Reveal folded link in REGION when needed.
diff --git a/testing/lisp/test-ol.el b/testing/lisp/test-ol.el
index 1487f7d38..7f4f41348 100644
--- a/testing/lisp/test-ol.el
+++ b/testing/lisp/test-ol.el
@@ -713,21 +713,139 @@ See https://github.com/yantar92/org/issues/4.";
 
 (ert-deftest test-org-link/precise-link-target ()
   "Test `org-link-precise-link-target` specifications."
-  (org-test-with-temp-text "* H1<point>\n* H2\n"
-    (should
-     (equal '("*H1" "H1" 1)
-            (org-link-precise-link-target))))
-  (org-test-with-temp-text "* H1\n#+name: foo<point>\n#+begin_example\nhi\n#+end_example\n"
-    (should
-     (equal '("foo" "foo" 6)
-            (org-link-precise-link-target))))
-  (org-test-with-temp-text "\nText<point>\n* H1\n"
-    (should
-     (equal '("Text" nil 2)
-            (org-link-precise-link-target))))
-  (org-test-with-temp-text "\n<point>\n* H1\n"
-    (should
-     (equal nil (org-link-precise-link-target)))))
+  (cl-macrolet ((with-text-in-regular-buffer (text &rest body)
+                  `(org-test-with-temp-text-in-file ,text
+                     (progn
+                       (fundamental-mode)
+                       ,@body))))
+    (org-test-with-temp-text "* H1<point>\n* H2\n"
+      (should
+       (equal '("*H1" "H1" 1)
+              (org-link-precise-link-target))))
+    (org-test-with-temp-text "* H1\n#+name: foo<point>\n#+begin_example\nhi\n#+end_example\n"
+      (should
+       (equal '("foo" "foo" 6)
+              (org-link-precise-link-target))))
+    (org-test-with-temp-text "\nText<point>\n* H1\n"
+      (should
+       (equal '("Text" nil 2)
+              (org-link-precise-link-target))))
+    (org-test-with-temp-text "\n<point>\n* H1\n"
+      (should
+       (equal nil (org-link-precise-link-target))))
+    ;; Assert search-syntax is removed
+    ;;# + no leading spaces
+    (with-text-in-regular-buffer
+     "#not-a-heading"
+     (should (equal
+              (list "not-a-heading" nil 1)
+              (org-link-precise-link-target))))
+    (with-text-in-regular-buffer
+     "#still not a heading"
+     (should (equal
+              (list "still not a heading" nil 1)
+              (org-link-precise-link-target))))
+    ;;# +  with leading spaces
+    (with-text-in-regular-buffer
+     "            #not-a-heading"
+     (should (equal
+              (list "not-a-heading" nil 1)
+              (org-link-precise-link-target))))
+    (with-text-in-regular-buffer
+     "                     #still not a heading"
+     (should (equal
+              (list "still not a heading" nil 1)
+              (org-link-precise-link-target))))
+    ;;single set of parens + no leading spaces
+    (with-text-in-regular-buffer
+     "(let ((element (org-element-at-point)))"
+     (should (equal
+              (list "let ((element (org-element-at-point))" nil 1)
+              (org-link-precise-link-target))))
+    (with-text-in-regular-buffer
+     "(let ((element (org-element-at-point)))"
+     (progn (set-mark (point))
+            (goto-char (line-end-position)))
+     (should (equal
+              (list "let ((element (org-element-at-point))" nil 1)
+              (org-link-precise-link-target))))
+    (with-text-in-regular-buffer
+     "(cond (line (org-goto-line line)"
+     (should (equal
+              (list "cond (line (org-goto-line line" nil 1)
+              (org-link-precise-link-target))))
+    (with-text-in-regular-buffer
+     "(cond (line (org-goto-line line)"
+     (progn (set-mark (point))
+            (goto-char (line-end-position)))
+     (should (equal
+              (list "cond (line (org-goto-line line" nil 1)
+              (org-link-precise-link-target))))
+    ;;single set of paren + leading spaces
+    (with-text-in-regular-buffer
+     "                     (let ((element (org-element-at-point)))"
+     (should (equal
+              (list "let ((element (org-element-at-point))" nil 1)
+              (org-link-precise-link-target))))
+    (with-text-in-regular-buffer
+     "                (let ((element (org-element-at-point)))"
+     (progn (set-mark (point))
+            (goto-char (line-end-position)))
+     (should (equal
+              (list "let ((element (org-element-at-point))" nil 1)
+              (org-link-precise-link-target))))
+    ;; multiple parens + no leading spaces
+    (with-text-in-regular-buffer
+     "((and (listp org-log-done) (memq 'done org-log-done))"
+     (should (equal
+              (list "and (listp org-log-done) (memq 'done org-log-done" nil 1)
+              (org-link-precise-link-target))))
+    (with-text-in-regular-buffer
+     "and (listp org-log-done) (memq 'done org-log-done"
+     (progn (set-mark (point))
+            (goto-char (line-end-position)))
+     (should (equal
+              (list "and (listp org-log-done) (memq 'done org-log-done" nil 1)
+              (org-link-precise-link-target))))
+    ;; multiple parens + leading spaces
+    (with-text-in-regular-buffer
+     "	  ((eq var 'prefix) (set-default-toplevel-value var nil))"
+     (should (equal
+              (list "eq var 'prefix) (set-default-toplevel-value var nil" nil 1)
+              (org-link-precise-link-target))))
+    (with-text-in-regular-buffer
+     "	  ((eq var 'prefix) (set-default-toplevel-value var nil))"
+     (progn (set-mark (point))
+            (goto-char (line-end-position)))
+     (should (equal
+              (list "eq var 'prefix) (set-default-toplevel-value var nil" nil 1)
+              (org-link-precise-link-target))))
+    ;; nothing but parens
+    (with-text-in-regular-buffer
+     "("
+     (should (equal
+              (list "(" nil 1)
+              (org-link-precise-link-target))))
+    (with-text-in-regular-buffer
+     "("
+     (progn (set-mark (point))
+            (goto-char (line-end-position)))
+     (should (equal
+              (list "(" nil 1)
+              (org-link-precise-link-target))))
+    ;; nothing but parens + leading spaces
+    (with-text-in-regular-buffer
+     "      ((("
+     (should (equal
+              (list "(((" nil 1)
+              (org-link-precise-link-target))))
+    (with-text-in-regular-buffer
+     "         (((("
+     (progn (set-mark (point))
+            (goto-char (line-end-position)))
+     (should (equal
+              (list "((((" nil 1)
+              (org-link-precise-link-target))))))
 
 (defmacro test-ol-stored-link-with-text (text &rest body)
   "Return :link and :description from link stored in body."
-- 
2.54.0

Reply via email to