* lisp/org.el (org-next-block): Ring the bell right before throwing a
user error for when no block is found, if called interactively.
* testing/lisp/test-org.el (test-org/next-block): Test that the bell
rings if and only if called interactively.
* etc/ORG-NEWS (~org-next-block~ rings the bell if no block is found):
Announce the change and give an example use-case.
---
 etc/ORG-NEWS             | 10 ++++++++++
 lisp/org.el              |  8 ++++++--
 testing/lisp/test-org.el | 14 ++++++++++++++
 3 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 5b5908629..e1ced84e5 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -676,6 +676,16 @@ will be defined as empty and not produce any metadata if 
their
 corresponding ~org-latex-with-author~, ~org-latex-with-title~, or
 ~org-latex-with-creator~ option is set to ~nil~.
 
+*** ~org-next-block~ rings the bell if no block is found
+
+It is now possible to call the ~org-next-block~ function interactively
+from a keyboard macro that runs until the bell rings.  For example, if
+the user customizes ~org-edit-src-content-indentation~, they can run a
+keyboard macro that updates all source blocks in a file, without Emacs
+looping forever.  The change affects ~org-next-block~ and its callers,
+including functions ~org-previous-block~, ~org-babel-next-src-block~,
+and ~org-babel-previous-src-block~.
+
 * Version 9.7
 
 ** Important announcements and breaking changes
diff --git a/lisp/org.el b/lisp/org.el
index 21622523b..9d48cdd66 100644
--- a/lisp/org.el
+++ b/lisp/org.el
@@ -20170,7 +20170,9 @@ (defun org-next-block (arg &optional backward 
block-regexp)
 returns.
 
 Return point at beginning of the opening line of found block.
-Throw an error if no block is found."
+
+Throw an error if no block is found.  When called interactively,
+ring the bell before throwing."
   (interactive "p")
   (let ((re (or block-regexp "^[ \t]*#\\+BEGIN"))
        (case-fold-search t)
@@ -20190,13 +20192,15 @@ (defun org-next-block (arg &optional backward 
block-regexp)
                                   example-block export-block quote-block
                                   special-block src-block verse-block))
                   (<= (match-beginning 0)
-                     (org-element-post-affiliated element)))
+                      (org-element-post-affiliated element)))
          (setq last-element element)
          (cl-decf count))))
     (if (= count 0)
        (prog1 (goto-char (org-element-post-affiliated last-element))
          (save-match-data (org-fold-show-context)))
       (goto-char origin)
+      (when (called-interactively-p 'any)
+        (ding))
       (user-error "No %s code blocks" (if backward "previous" "further")))))
 
 (defun org-previous-block (arg &optional block-regexp)
diff --git a/testing/lisp/test-org.el b/testing/lisp/test-org.el
index 36dea35b7..cf3e0b40b 100644
--- a/testing/lisp/test-org.el
+++ b/testing/lisp/test-org.el
@@ -5652,6 +5652,20 @@ (ert-deftest test-org/next-block ()
   (should-error
    (org-test-with-temp-text "Paragraph"
      (org-next-block 1)))
+  ;; Ring the bell when no block is found.
+  (should-error
+   (org-test-with-temp-text "Paragraph"
+     (define-error 'ding "Ring my bell!")
+     (cl-letf (((symbol-function 'ding)
+                (lambda () (signal 'ding nil))))
+       (funcall-interactively #'org-next-block 1)))
+   :type 'ding)
+  ;; Ring the bell only when called interactively.
+  (should-error
+   (org-test-with-temp-text "Paragraph"
+     (let ((ring-bell-function (lambda () (signal 'ding nil))))
+       (org-next-block 1)))
+   :type 'user-error)
   ;; With an argument, skip many blocks at once.
   (should
    (org-test-with-temp-text
-- 
2.50.1


Reply via email to