Fix `org-next-block'

* lisp/org.el (org-next-block): Use Element API.

* testing/lisp/test-org.el (test-org/next-block):
(test-org/previous-block): New tests.
This commit is contained in:
Nicolas Goaziou 2015-05-01 12:08:57 +02:00
parent bce77d0db3
commit 0b7721322a
2 changed files with 120 additions and 11 deletions

View File

@ -24344,19 +24344,42 @@ respect customization of `org-odd-levels-only'."
(defun org-next-block (arg &optional backward block-regexp)
"Jump to the next block.
With a prefix argument ARG, jump forward ARG many source blocks.
With a prefix argument ARG, jump forward ARG many blocks.
When BACKWARD is non-nil, jump to the previous block.
When BLOCK-REGEXP is non-nil, use this regexp to find blocks."
When BLOCK-REGEXP is non-nil, use this regexp to find blocks.
Match data is set according to this regexp when the function
returns.
Return point at beginning of the opening line of found block.
Throw an error if no block is found."
(interactive "p")
(let ((re (or block-regexp org-block-regexp))
(re-search-fn (or (and backward 're-search-backward)
're-search-forward)))
(if (looking-at re) (forward-char 1))
(condition-case nil
(funcall re-search-fn re nil nil arg)
(error (user-error "No %s code blocks"
(if backward "previous" "further" ))))
(goto-char (match-beginning 0)) (org-show-context)))
(let ((re (or block-regexp "^[ \t]*#\\+BEGIN"))
(case-fold-search t)
(search-fn (if backward #'re-search-backward #'re-search-forward))
(count (or arg 1))
(origin (point))
last-element)
(if backward (beginning-of-line) (end-of-line))
(while (and (> count 0) (funcall search-fn re nil t))
(let ((element (save-excursion
(goto-char (match-beginning 0))
(save-match-data (org-element-at-point)))))
(when (and (memq (org-element-type element)
'(center-block comment-block dynamic-block
example-block export-block quote-block
special-block src-block verse-block))
(<= (match-beginning 0)
(org-element-property :post-affiliated element)))
(setq last-element element)
(decf count))))
(if (= count 0)
(prog1 (goto-char (org-element-property :post-affiliated last-element))
(org-show-context))
(goto-char origin)
(user-error "No %s code blocks" (if backward "previous" "further")))))
(defun org-previous-block (arg &optional block-regexp)
"Jump to the previous block.

View File

@ -2309,6 +2309,92 @@ Text.
(mapcar (lambda (ov) (cons (overlay-start ov) (overlay-end ov)))
(overlays-in (point-min) (point-max)))))))
(ert-deftest test-org/next-block ()
"Test `org-next-block' specifications."
;; Regular test.
(should
(org-test-with-temp-text "Paragraph\n#+BEGIN_CENTER\ncontents\n#+END_CENTER"
(org-next-block 1)
(looking-at "#\\+BEGIN_CENTER")))
;; Ignore case.
(should
(org-test-with-temp-text "Paragraph\n#+begin_center\ncontents\n#+end_center"
(let ((case-fold-search nil))
(org-next-block 1)
(looking-at "#\\+begin_center"))))
;; Ignore current line.
(should
(org-test-with-temp-text
"#+BEGIN_QUOTE\n#+END_QUOTE\n#+BEGIN_CENTER\n#+END_CENTER"
(org-next-block 1)
(looking-at "#\\+BEGIN_CENTER")))
;; Throw an error when no block is found.
(should-error
(org-test-with-temp-text "Paragraph"
(org-next-block 1)))
;; With an argument, skip many blocks at once.
(should
(org-test-with-temp-text
"Start\n#+BEGIN_CENTER\nA\n#+END_CENTER\n#+BEGIN_QUOTE\nB\n#+END_QUOTE"
(org-next-block 2)
(looking-at "#\\+BEGIN_QUOTE")))
;; With optional argument BLOCK-REGEXP, filter matched blocks.
(should
(org-test-with-temp-text
"Start\n#+BEGIN_CENTER\nA\n#+END_CENTER\n#+BEGIN_QUOTE\nB\n#+END_QUOTE"
(org-next-block 1 nil "^[ \t]*#\\+BEGIN_QUOTE")
(looking-at "#\\+BEGIN_QUOTE")))
;; Optional argument is also case-insensitive.
(should
(org-test-with-temp-text
"Start\n#+BEGIN_CENTER\nA\n#+END_CENTER\n#+begin_quote\nB\n#+end_quote"
(let ((case-fold-search nil))
(org-next-block 1 nil "^[ \t]*#\\+BEGIN_QUOTE")
(looking-at "#\\+begin_quote")))))
(ert-deftest test-org/previous-block ()
"Test `org-previous-block' specifications."
;; Regular test.
(should
(org-test-with-temp-text "#+BEGIN_CENTER\ncontents\n#+END_CENTER\n<point>"
(org-previous-block 1)
(looking-at "#\\+BEGIN_CENTER")))
;; Ignore case.
(should
(org-test-with-temp-text "#+begin_center\ncontents\n#+end_center\n<point>"
(let ((case-fold-search nil))
(org-previous-block 1)
(looking-at "#\\+begin_center"))))
;; Ignore current line.
(should
(org-test-with-temp-text
"#+BEGIN_QUOTE\n#+END_QUOTE\n#+BEGIN_CENTER<point>\n#+END_CENTER"
(org-previous-block 1)
(looking-at "#\\+BEGIN_QUOTE")))
;; Throw an error when no block is found.
(should-error
(org-test-with-temp-text "Paragraph<point>"
(org-previous-block 1)))
;; With an argument, skip many blocks at once.
(should
(org-test-with-temp-text
"#+BEGIN_CENTER\nA\n#+END_CENTER\n#+BEGIN_QUOTE\nB\n#+END_QUOTE\n<point>"
(org-previous-block 2)
(looking-at "#\\+BEGIN_CENTER")))
;; With optional argument BLOCK-REGEXP, filter matched blocks.
(should
(org-test-with-temp-text
"#+BEGIN_CENTER\nA\n#+END_CENTER\n#+BEGIN_QUOTE\nB\n#+END_QUOTE\n<point>"
(org-previous-block 1 "^[ \t]*#\\+BEGIN_QUOTE")
(looking-at "#\\+BEGIN_QUOTE")))
;; Optional argument is also case-insensitive.
(should
(org-test-with-temp-text
"#+BEGIN_CENTER\nA\n#+END_CENTER\n#+begin_quote\nB\n#+end_quote\n<point>"
(let ((case-fold-search nil))
(org-next-block 1 "^[ \t]*#\\+BEGIN_QUOTE")
(looking-at "#\\+begin_quote")))))
;;; Outline structure