`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>
This commit is contained in:
parent
f203d378bd
commit
808089ee04
234
lisp/org.el
234
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 table or a property drawer, jump after it.
|
||||||
- On a verse or source block, stop after blank lines."
|
- On a verse or source block, stop after blank lines."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (eobp) (user-error "Cannot move further down"))
|
(unless (eobp)
|
||||||
(let* ((deactivate-mark nil)
|
(let* ((deactivate-mark nil)
|
||||||
(element (org-element-at-point))
|
(element (org-element-at-point))
|
||||||
(type (org-element-type element))
|
(type (org-element-type element))
|
||||||
(post-affiliated (org-element-property :post-affiliated element))
|
(post-affiliated (org-element-property :post-affiliated element))
|
||||||
(contents-begin (org-element-property :contents-begin element))
|
(contents-begin (org-element-property :contents-begin element))
|
||||||
(contents-end (org-element-property :contents-end element))
|
(contents-end (org-element-property :contents-end element))
|
||||||
(end (let ((end (org-element-property :end element)) (parent element))
|
(end (let ((end (org-element-property :end element)) (parent element))
|
||||||
(while (and (setq parent (org-element-property :parent parent))
|
(while (and (setq parent (org-element-property :parent parent))
|
||||||
(= (org-element-property :contents-end parent) end))
|
(= (org-element-property :contents-end parent) end))
|
||||||
(setq end (org-element-property :end parent)))
|
(setq end (org-element-property :end parent)))
|
||||||
end)))
|
end)))
|
||||||
(cond ((not element)
|
(cond ((not element)
|
||||||
(skip-chars-forward " \r\t\n")
|
(skip-chars-forward " \r\t\n")
|
||||||
(or (eobp) (beginning-of-line)))
|
(or (eobp) (beginning-of-line)))
|
||||||
;; On affiliated keywords, move to element's beginning.
|
;; On affiliated keywords, move to element's beginning.
|
||||||
((< (point) post-affiliated)
|
((< (point) post-affiliated)
|
||||||
(goto-char post-affiliated))
|
(goto-char post-affiliated))
|
||||||
;; At a table row, move to the end of the table. Similarly,
|
;; At a table row, move to the end of the table. Similarly,
|
||||||
;; at a node property, move to the end of the property
|
;; at a node property, move to the end of the property
|
||||||
;; drawer.
|
;; drawer.
|
||||||
((memq type '(node-property table-row))
|
((memq type '(node-property table-row))
|
||||||
(goto-char (org-element-property
|
(goto-char (org-element-property
|
||||||
:end (org-element-property :parent element))))
|
:end (org-element-property :parent element))))
|
||||||
((memq type '(property-drawer table)) (goto-char end))
|
((memq type '(property-drawer table)) (goto-char end))
|
||||||
;; Consider blank lines as separators in verse and source
|
;; Consider blank lines as separators in verse and source
|
||||||
;; blocks to ease editing.
|
;; blocks to ease editing.
|
||||||
((memq type '(src-block verse-block))
|
((memq type '(src-block verse-block))
|
||||||
(when (eq type 'src-block)
|
(when (eq type 'src-block)
|
||||||
(setq contents-end
|
(setq contents-end
|
||||||
(save-excursion (goto-char end)
|
(save-excursion (goto-char end)
|
||||||
(skip-chars-backward " \r\t\n")
|
(skip-chars-backward " \r\t\n")
|
||||||
(line-beginning-position))))
|
(line-beginning-position))))
|
||||||
(beginning-of-line)
|
(beginning-of-line)
|
||||||
(when (looking-at "[ \t]*$") (skip-chars-forward " \r\t\n"))
|
(when (looking-at "[ \t]*$") (skip-chars-forward " \r\t\n"))
|
||||||
(if (not (re-search-forward "^[ \t]*$" contents-end t))
|
(if (not (re-search-forward "^[ \t]*$" contents-end t))
|
||||||
(goto-char end)
|
(goto-char end)
|
||||||
(skip-chars-forward " \r\t\n")
|
(skip-chars-forward " \r\t\n")
|
||||||
(if (= (point) contents-end) (goto-char end)
|
(if (= (point) contents-end) (goto-char end)
|
||||||
(beginning-of-line))))
|
(beginning-of-line))))
|
||||||
;; With no contents, just skip element.
|
;; With no contents, just skip element.
|
||||||
((not contents-begin) (goto-char end))
|
((not contents-begin) (goto-char end))
|
||||||
;; If contents are invisible, skip the element altogether.
|
;; If contents are invisible, skip the element altogether.
|
||||||
((org-invisible-p (line-end-position))
|
((org-invisible-p (line-end-position))
|
||||||
(cl-case type
|
(cl-case type
|
||||||
(headline
|
(headline
|
||||||
(org-with-limited-levels (outline-next-visible-heading 1)))
|
(org-with-limited-levels (outline-next-visible-heading 1)))
|
||||||
;; At a plain list, make sure we move to the next item
|
;; At a plain list, make sure we move to the next item
|
||||||
;; instead of skipping the whole list.
|
;; instead of skipping the whole list.
|
||||||
(plain-list (forward-char)
|
(plain-list (forward-char)
|
||||||
(org-forward-paragraph))
|
(org-forward-paragraph))
|
||||||
(otherwise (goto-char end))))
|
(otherwise (goto-char end))))
|
||||||
((>= (point) contents-end) (goto-char end))
|
((>= (point) contents-end) (goto-char end))
|
||||||
((>= (point) contents-begin)
|
((>= (point) contents-begin)
|
||||||
;; This can only happen on paragraphs and plain lists.
|
;; This can only happen on paragraphs and plain lists.
|
||||||
(cl-case type
|
(cl-case type
|
||||||
(paragraph (goto-char end))
|
(paragraph (goto-char end))
|
||||||
;; At a plain list, try to move to second element in
|
;; At a plain list, try to move to second element in
|
||||||
;; first item, if possible.
|
;; first item, if possible.
|
||||||
(plain-list (end-of-line)
|
(plain-list (end-of-line)
|
||||||
(org-forward-paragraph))))
|
(org-forward-paragraph))))
|
||||||
;; When contents start on the middle of a line (e.g. in
|
;; When contents start on the middle of a line (e.g. in
|
||||||
;; items and footnote definitions), try to reach first
|
;; items and footnote definitions), try to reach first
|
||||||
;; element starting after current line.
|
;; element starting after current line.
|
||||||
((> (line-end-position) contents-begin)
|
((> (line-end-position) contents-begin)
|
||||||
(end-of-line)
|
(end-of-line)
|
||||||
(org-forward-paragraph))
|
(org-forward-paragraph))
|
||||||
(t (goto-char contents-begin)))))
|
(t (goto-char contents-begin))))))
|
||||||
|
|
||||||
(defun org-backward-paragraph ()
|
(defun org-backward-paragraph ()
|
||||||
"Move backward to start of previous paragraph or equivalent.
|
"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 table or a property drawer, move to its beginning.
|
||||||
- On a verse or source block, stop before blank lines."
|
- On a verse or source block, stop before blank lines."
|
||||||
(interactive)
|
(interactive)
|
||||||
(when (bobp) (user-error "Cannot move further up"))
|
(unless (bobp)
|
||||||
(let* ((deactivate-mark nil)
|
(let* ((deactivate-mark nil)
|
||||||
(element (org-element-at-point))
|
(element (org-element-at-point))
|
||||||
(type (org-element-type element))
|
(type (org-element-type element))
|
||||||
(contents-begin (org-element-property :contents-begin element))
|
(contents-begin (org-element-property :contents-begin element))
|
||||||
(contents-end (org-element-property :contents-end element))
|
(contents-end (org-element-property :contents-end element))
|
||||||
(post-affiliated (org-element-property :post-affiliated element))
|
(post-affiliated (org-element-property :post-affiliated element))
|
||||||
(begin (org-element-property :begin element)))
|
(begin (org-element-property :begin element)))
|
||||||
(cond
|
(cond
|
||||||
((not element) (goto-char (point-min)))
|
((not element) (goto-char (point-min)))
|
||||||
((= (point) begin)
|
((= (point) begin)
|
||||||
(backward-char)
|
(backward-char)
|
||||||
(org-backward-paragraph))
|
(org-backward-paragraph))
|
||||||
((<= (point) post-affiliated) (goto-char begin))
|
((<= (point) post-affiliated) (goto-char begin))
|
||||||
((memq type '(node-property table-row))
|
((memq type '(node-property table-row))
|
||||||
(goto-char (org-element-property
|
(goto-char (org-element-property
|
||||||
:post-affiliated (org-element-property :parent element))))
|
:post-affiliated (org-element-property :parent element))))
|
||||||
((memq type '(property-drawer table)) (goto-char begin))
|
((memq type '(property-drawer table)) (goto-char begin))
|
||||||
((memq type '(src-block verse-block))
|
((memq type '(src-block verse-block))
|
||||||
(when (eq type 'src-block)
|
(when (eq type 'src-block)
|
||||||
(setq contents-begin
|
(setq contents-begin
|
||||||
(save-excursion (goto-char begin) (forward-line) (point))))
|
(save-excursion (goto-char begin) (forward-line) (point))))
|
||||||
(if (= (point) contents-begin) (goto-char post-affiliated)
|
(if (= (point) contents-begin) (goto-char post-affiliated)
|
||||||
;; Inside a verse block, see blank lines as paragraph
|
;; Inside a verse block, see blank lines as paragraph
|
||||||
;; separators.
|
;; separators.
|
||||||
(let ((origin (point)))
|
(let ((origin (point)))
|
||||||
(skip-chars-backward " \r\t\n" contents-begin)
|
(skip-chars-backward " \r\t\n" contents-begin)
|
||||||
(when (re-search-backward "^[ \t]*$" contents-begin 'move)
|
(when (re-search-backward "^[ \t]*$" contents-begin 'move)
|
||||||
(skip-chars-forward " \r\t\n" origin)
|
(skip-chars-forward " \r\t\n" origin)
|
||||||
(if (= (point) origin) (goto-char contents-begin)
|
(if (= (point) origin) (goto-char contents-begin)
|
||||||
(beginning-of-line))))))
|
(beginning-of-line))))))
|
||||||
((not contents-begin) (goto-char (or post-affiliated begin)))
|
((not contents-begin) (goto-char (or post-affiliated begin)))
|
||||||
((eq type 'paragraph)
|
((eq type 'paragraph)
|
||||||
(goto-char contents-begin)
|
(goto-char contents-begin)
|
||||||
;; When at first paragraph in an item or a footnote definition,
|
;; When at first paragraph in an item or a footnote definition,
|
||||||
;; move directly to beginning of line.
|
;; move directly to beginning of line.
|
||||||
(let ((parent-contents
|
(let ((parent-contents
|
||||||
(org-element-property
|
(org-element-property
|
||||||
:contents-begin (org-element-property :parent element))))
|
:contents-begin (org-element-property :parent element))))
|
||||||
(when (and parent-contents (= parent-contents contents-begin))
|
(when (and parent-contents (= parent-contents contents-begin))
|
||||||
(beginning-of-line))))
|
(beginning-of-line))))
|
||||||
;; At the end of a greater element, move to the beginning of the
|
;; At the end of a greater element, move to the beginning of the
|
||||||
;; last element within.
|
;; last element within.
|
||||||
((>= (point) contents-end)
|
((>= (point) contents-end)
|
||||||
(goto-char (1- contents-end))
|
(goto-char (1- contents-end))
|
||||||
(org-backward-paragraph))
|
(org-backward-paragraph))
|
||||||
(t (goto-char (or post-affiliated begin))))
|
(t (goto-char (or post-affiliated begin))))
|
||||||
;; Ensure we never leave point invisible.
|
;; Ensure we never leave point invisible.
|
||||||
(when (org-invisible-p (point)) (beginning-of-visual-line))))
|
(when (org-invisible-p (point)) (beginning-of-visual-line)))))
|
||||||
|
|
||||||
(defun org-forward-element ()
|
(defun org-forward-element ()
|
||||||
"Move forward by one element.
|
"Move forward by one element.
|
||||||
|
|
|
@ -3259,11 +3259,12 @@ SCHEDULED: <2017-05-06 Sat>
|
||||||
|
|
||||||
(ert-deftest test-org/forward-paragraph ()
|
(ert-deftest test-org/forward-paragraph ()
|
||||||
"Test `org-forward-paragraph' specifications."
|
"Test `org-forward-paragraph' specifications."
|
||||||
;; At end of buffer, return an error.
|
;; At end of buffer, do not return an error.
|
||||||
(should-error
|
(should
|
||||||
(org-test-with-temp-text "Paragraph"
|
(org-test-with-temp-text "Paragraph"
|
||||||
(goto-char (point-max))
|
(goto-char (point-max))
|
||||||
(org-forward-paragraph)))
|
(org-forward-paragraph)
|
||||||
|
t))
|
||||||
;; Standard test.
|
;; Standard test.
|
||||||
(should
|
(should
|
||||||
(org-test-with-temp-text "P1\n\nP2\n\nP3"
|
(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 ()
|
(ert-deftest test-org/backward-paragraph ()
|
||||||
"Test `org-backward-paragraph' specifications."
|
"Test `org-backward-paragraph' specifications."
|
||||||
;; Error at beginning of buffer.
|
;; Do not error at beginning of buffer.
|
||||||
(should-error
|
(should
|
||||||
(org-test-with-temp-text "Paragraph"
|
(org-test-with-temp-text "Paragraph"
|
||||||
(org-backward-paragraph)))
|
(org-backward-paragraph)
|
||||||
|
t))
|
||||||
;; Regular test.
|
;; Regular test.
|
||||||
(should
|
(should
|
||||||
(org-test-with-temp-text "P1\n\nP2\n\nP3"
|
(org-test-with-temp-text "P1\n\nP2\n\nP3"
|
||||||
|
|
Loading…
Reference in New Issue