Forráskód Böngészése

`org-forward/backward-paragraph' do not error at buffer boundaries

* lisp/org.el (org-forward-paragraph):
(org-backward-paragraph): Do not error at buffer boundaries.

Reported-by: Omar Antolín Camarena <omar.antolin@gmail.com>
<http://lists.gnu.org/archive/html/emacs-orgmode/2017-07/msg00478.html>
Nicolas Goaziou 7 éve
szülő
commit
808089ee04
2 módosított fájl, 125 hozzáadás és 123 törlés
  1. 117 117
      lisp/org.el
  2. 8 6
      testing/lisp/test-org.el

+ 117 - 117
lisp/org.el

@@ -24432,74 +24432,74 @@ item, etc.  It also provides some special moves for convenience:
   - On a table or a property drawer, jump after it.
   - On a verse or source block, stop after blank lines."
   (interactive)
-  (when (eobp) (user-error "Cannot move further down"))
-  (let* ((deactivate-mark nil)
-	 (element (org-element-at-point))
-         (type (org-element-type element))
-         (post-affiliated (org-element-property :post-affiliated element))
-         (contents-begin (org-element-property :contents-begin element))
-         (contents-end (org-element-property :contents-end element))
-         (end (let ((end (org-element-property :end element)) (parent element))
-                (while (and (setq parent (org-element-property :parent parent))
-                            (= (org-element-property :contents-end parent) end))
-                  (setq end (org-element-property :end parent)))
-                end)))
-    (cond ((not element)
-           (skip-chars-forward " \r\t\n")
-           (or (eobp) (beginning-of-line)))
-          ;; On affiliated keywords, move to element's beginning.
-          ((< (point) post-affiliated)
-           (goto-char post-affiliated))
-          ;; At a table row, move to the end of the table.  Similarly,
-          ;; at a node property, move to the end of the property
-          ;; drawer.
-          ((memq type '(node-property table-row))
-           (goto-char (org-element-property
-                       :end (org-element-property :parent element))))
-          ((memq type '(property-drawer table)) (goto-char end))
-          ;; Consider blank lines as separators in verse and source
-          ;; blocks to ease editing.
-          ((memq type '(src-block verse-block))
-           (when (eq type 'src-block)
-             (setq contents-end
-                   (save-excursion (goto-char end)
-                                   (skip-chars-backward " \r\t\n")
-                                   (line-beginning-position))))
-           (beginning-of-line)
-           (when (looking-at "[ \t]*$") (skip-chars-forward " \r\t\n"))
-           (if (not (re-search-forward "^[ \t]*$" contents-end t))
-               (goto-char end)
-             (skip-chars-forward " \r\t\n")
-             (if (= (point) contents-end) (goto-char end)
-               (beginning-of-line))))
-          ;; With no contents, just skip element.
-          ((not contents-begin) (goto-char end))
-          ;; If contents are invisible, skip the element altogether.
-          ((org-invisible-p (line-end-position))
-           (cl-case type
-             (headline
-              (org-with-limited-levels (outline-next-visible-heading 1)))
-             ;; At a plain list, make sure we move to the next item
-             ;; instead of skipping the whole list.
-             (plain-list (forward-char)
-                         (org-forward-paragraph))
-             (otherwise (goto-char end))))
-          ((>= (point) contents-end) (goto-char end))
-          ((>= (point) contents-begin)
-           ;; This can only happen on paragraphs and plain lists.
-           (cl-case type
-             (paragraph (goto-char end))
-             ;; At a plain list, try to move to second element in
-             ;; first item, if possible.
-             (plain-list (end-of-line)
-                         (org-forward-paragraph))))
-          ;; When contents start on the middle of a line (e.g. in
-          ;; items and footnote definitions), try to reach first
-          ;; element starting after current line.
-          ((> (line-end-position) contents-begin)
-           (end-of-line)
-           (org-forward-paragraph))
-          (t (goto-char contents-begin)))))
+  (unless (eobp)
+    (let* ((deactivate-mark nil)
+	   (element (org-element-at-point))
+	   (type (org-element-type element))
+	   (post-affiliated (org-element-property :post-affiliated element))
+	   (contents-begin (org-element-property :contents-begin element))
+	   (contents-end (org-element-property :contents-end element))
+	   (end (let ((end (org-element-property :end element)) (parent element))
+		  (while (and (setq parent (org-element-property :parent parent))
+			      (= (org-element-property :contents-end parent) end))
+		    (setq end (org-element-property :end parent)))
+		  end)))
+      (cond ((not element)
+	     (skip-chars-forward " \r\t\n")
+	     (or (eobp) (beginning-of-line)))
+	    ;; On affiliated keywords, move to element's beginning.
+	    ((< (point) post-affiliated)
+	     (goto-char post-affiliated))
+	    ;; At a table row, move to the end of the table.  Similarly,
+	    ;; at a node property, move to the end of the property
+	    ;; drawer.
+	    ((memq type '(node-property table-row))
+	     (goto-char (org-element-property
+			 :end (org-element-property :parent element))))
+	    ((memq type '(property-drawer table)) (goto-char end))
+	    ;; Consider blank lines as separators in verse and source
+	    ;; blocks to ease editing.
+	    ((memq type '(src-block verse-block))
+	     (when (eq type 'src-block)
+	       (setq contents-end
+		     (save-excursion (goto-char end)
+				     (skip-chars-backward " \r\t\n")
+				     (line-beginning-position))))
+	     (beginning-of-line)
+	     (when (looking-at "[ \t]*$") (skip-chars-forward " \r\t\n"))
+	     (if (not (re-search-forward "^[ \t]*$" contents-end t))
+		 (goto-char end)
+	       (skip-chars-forward " \r\t\n")
+	       (if (= (point) contents-end) (goto-char end)
+		 (beginning-of-line))))
+	    ;; With no contents, just skip element.
+	    ((not contents-begin) (goto-char end))
+	    ;; If contents are invisible, skip the element altogether.
+	    ((org-invisible-p (line-end-position))
+	     (cl-case type
+	       (headline
+		(org-with-limited-levels (outline-next-visible-heading 1)))
+	       ;; At a plain list, make sure we move to the next item
+	       ;; instead of skipping the whole list.
+	       (plain-list (forward-char)
+			   (org-forward-paragraph))
+	       (otherwise (goto-char end))))
+	    ((>= (point) contents-end) (goto-char end))
+	    ((>= (point) contents-begin)
+	     ;; This can only happen on paragraphs and plain lists.
+	     (cl-case type
+	       (paragraph (goto-char end))
+	       ;; At a plain list, try to move to second element in
+	       ;; first item, if possible.
+	       (plain-list (end-of-line)
+			   (org-forward-paragraph))))
+	    ;; When contents start on the middle of a line (e.g. in
+	    ;; items and footnote definitions), try to reach first
+	    ;; element starting after current line.
+	    ((> (line-end-position) contents-begin)
+	     (end-of-line)
+	     (org-forward-paragraph))
+	    (t (goto-char contents-begin))))))
 
 (defun org-backward-paragraph ()
   "Move backward to start of previous paragraph or equivalent.
@@ -24514,55 +24514,55 @@ convenience:
   - On a table or a property drawer, move to its beginning.
   - On a verse or source block, stop before blank lines."
   (interactive)
-  (when (bobp) (user-error "Cannot move further up"))
-  (let* ((deactivate-mark nil)
-	 (element (org-element-at-point))
-         (type (org-element-type element))
-         (contents-begin (org-element-property :contents-begin element))
-         (contents-end (org-element-property :contents-end element))
-         (post-affiliated (org-element-property :post-affiliated element))
-         (begin (org-element-property :begin element)))
-    (cond
-     ((not element) (goto-char (point-min)))
-     ((= (point) begin)
-      (backward-char)
-      (org-backward-paragraph))
-     ((<= (point) post-affiliated) (goto-char begin))
-     ((memq type '(node-property table-row))
-      (goto-char (org-element-property
-                  :post-affiliated (org-element-property :parent element))))
-     ((memq type '(property-drawer table)) (goto-char begin))
-     ((memq type '(src-block verse-block))
-      (when (eq type 'src-block)
-        (setq contents-begin
-              (save-excursion (goto-char begin) (forward-line) (point))))
-      (if (= (point) contents-begin) (goto-char post-affiliated)
-        ;; Inside a verse block, see blank lines as paragraph
-        ;; separators.
-        (let ((origin (point)))
-          (skip-chars-backward " \r\t\n" contents-begin)
-          (when (re-search-backward "^[ \t]*$" contents-begin 'move)
-            (skip-chars-forward " \r\t\n" origin)
-            (if (= (point) origin) (goto-char contents-begin)
-              (beginning-of-line))))))
-     ((not contents-begin) (goto-char (or post-affiliated begin)))
-     ((eq type 'paragraph)
-      (goto-char contents-begin)
-      ;; When at first paragraph in an item or a footnote definition,
-      ;; move directly to beginning of line.
-      (let ((parent-contents
-             (org-element-property
-              :contents-begin (org-element-property :parent element))))
-        (when (and parent-contents (= parent-contents contents-begin))
-          (beginning-of-line))))
-     ;; At the end of a greater element, move to the beginning of the
-     ;; last element within.
-     ((>= (point) contents-end)
-      (goto-char (1- contents-end))
-      (org-backward-paragraph))
-     (t (goto-char (or post-affiliated begin))))
-    ;; Ensure we never leave point invisible.
-    (when (org-invisible-p (point)) (beginning-of-visual-line))))
+  (unless (bobp)
+    (let* ((deactivate-mark nil)
+	   (element (org-element-at-point))
+	   (type (org-element-type element))
+	   (contents-begin (org-element-property :contents-begin element))
+	   (contents-end (org-element-property :contents-end element))
+	   (post-affiliated (org-element-property :post-affiliated element))
+	   (begin (org-element-property :begin element)))
+      (cond
+       ((not element) (goto-char (point-min)))
+       ((= (point) begin)
+	(backward-char)
+	(org-backward-paragraph))
+       ((<= (point) post-affiliated) (goto-char begin))
+       ((memq type '(node-property table-row))
+	(goto-char (org-element-property
+		    :post-affiliated (org-element-property :parent element))))
+       ((memq type '(property-drawer table)) (goto-char begin))
+       ((memq type '(src-block verse-block))
+	(when (eq type 'src-block)
+	  (setq contents-begin
+		(save-excursion (goto-char begin) (forward-line) (point))))
+	(if (= (point) contents-begin) (goto-char post-affiliated)
+	  ;; Inside a verse block, see blank lines as paragraph
+	  ;; separators.
+	  (let ((origin (point)))
+	    (skip-chars-backward " \r\t\n" contents-begin)
+	    (when (re-search-backward "^[ \t]*$" contents-begin 'move)
+	      (skip-chars-forward " \r\t\n" origin)
+	      (if (= (point) origin) (goto-char contents-begin)
+		(beginning-of-line))))))
+       ((not contents-begin) (goto-char (or post-affiliated begin)))
+       ((eq type 'paragraph)
+	(goto-char contents-begin)
+	;; When at first paragraph in an item or a footnote definition,
+	;; move directly to beginning of line.
+	(let ((parent-contents
+	       (org-element-property
+		:contents-begin (org-element-property :parent element))))
+	  (when (and parent-contents (= parent-contents contents-begin))
+	    (beginning-of-line))))
+       ;; At the end of a greater element, move to the beginning of the
+       ;; last element within.
+       ((>= (point) contents-end)
+	(goto-char (1- contents-end))
+	(org-backward-paragraph))
+       (t (goto-char (or post-affiliated begin))))
+      ;; Ensure we never leave point invisible.
+      (when (org-invisible-p (point)) (beginning-of-visual-line)))))
 
 (defun org-forward-element ()
   "Move forward by one element.

+ 8 - 6
testing/lisp/test-org.el

@@ -3259,11 +3259,12 @@ SCHEDULED: <2017-05-06 Sat>
 
 (ert-deftest test-org/forward-paragraph ()
   "Test `org-forward-paragraph' specifications."
-  ;; At end of buffer, return an error.
-  (should-error
+  ;; At end of buffer, do not return an error.
+  (should
    (org-test-with-temp-text "Paragraph"
      (goto-char (point-max))
-     (org-forward-paragraph)))
+     (org-forward-paragraph)
+     t))
   ;; Standard test.
   (should
    (org-test-with-temp-text "P1\n\nP2\n\nP3"
@@ -3328,10 +3329,11 @@ SCHEDULED: <2017-05-06 Sat>
 
 (ert-deftest test-org/backward-paragraph ()
   "Test `org-backward-paragraph' specifications."
-  ;; Error at beginning of buffer.
-  (should-error
+  ;; Do not error at beginning of buffer.
+  (should
    (org-test-with-temp-text "Paragraph"
-     (org-backward-paragraph)))
+     (org-backward-paragraph)
+     t))
   ;; Regular test.
   (should
    (org-test-with-temp-text "P1\n\nP2\n\nP3"