1
0
mirror of https://git.savannah.gnu.org/git/emacs/org-mode.git synced 2024-11-29 07:58:21 +00:00

org-element: Fix `org-element-at-point' in some corner cases

* lisp/org-element.el (org-element-item-parser,
  org-element-plain-list-parser): Make sure that the element ends at
  the beginning of a line if possible.
(org-element-at-point): Return expected element when point is at an
element's end or at its contents' end.
* testing/lisp/test-org-element.el: Add test.
* testing/lisp/test-org.el: Add test.
This commit is contained in:
Nicolas Goaziou 2012-08-08 09:54:56 +02:00
parent 9dae6f04b1
commit 0a04169769
3 changed files with 49 additions and 30 deletions

View File

@ -981,10 +981,12 @@ Assume point is at the beginning of the item."
64)) 64))
((string-match "[0-9]+" c) ((string-match "[0-9]+" c)
(string-to-number (match-string 0 c)))))) (string-to-number (match-string 0 c))))))
(end (org-list-get-item-end begin struct)) (end (save-excursion (goto-char (org-list-get-item-end begin struct))
(unless (bolp) (forward-line))
(point)))
(contents-begin (progn (looking-at org-list-full-item-re) (contents-begin (progn (looking-at org-list-full-item-re)
(goto-char (match-end 0)) (goto-char (match-end 0))
(org-skip-whitespace) (skip-chars-forward " \r\t\n" limit)
;; If first line isn't empty, ;; If first line isn't empty,
;; contents really start at the text ;; contents really start at the text
;; after item's meta-data. ;; after item's meta-data.
@ -1039,10 +1041,10 @@ CONTENTS is the contents of the element."
(concat (concat
bullet bullet
(and counter (format "[@%d] " counter)) (and counter (format "[@%d] " counter))
(cond (case checkbox
((eq checkbox 'on) "[X] ") (on "[X] ")
((eq checkbox 'off) "[ ] ") (off "[ ] ")
((eq checkbox 'trans) "[-] ")) (trans "[-] "))
(and tag (format "%s :: " tag)) (and tag (format "%s :: " tag))
(let ((contents (replace-regexp-in-string (let ((contents (replace-regexp-in-string
"\\(^\\)[ \t]*\\S-" ind contents nil nil 1))) "\\(^\\)[ \t]*\\S-" ind contents nil nil 1)))
@ -1072,14 +1074,11 @@ Assume point is at the beginning of the list."
(keywords (org-element--collect-affiliated-keywords)) (keywords (org-element--collect-affiliated-keywords))
(begin (car keywords)) (begin (car keywords))
(contents-end (contents-end
(goto-char (org-list-get-list-end (point) struct prevs))) (progn (goto-char (org-list-get-list-end (point) struct prevs))
(end (save-excursion (org-skip-whitespace) (unless (bolp) (forward-line))
(if (eobp) (point) (point-at-bol))))) (point)))
;; Blank lines below list belong to the top-level list only. (end (progn (skip-chars-forward " \r\t\n" limit)
(unless (= (org-list-get-top-point struct) contents-begin) (if (eobp) (point) (point-at-bol)))))
(setq end (min (org-list-get-bottom-point struct)
(progn (skip-chars-forward " \r\t\n" limit)
(if (eobp) (point) (point-at-bol))))))
;; Return value. ;; Return value.
(list 'plain-list (list 'plain-list
(nconc (nconc
@ -4076,31 +4075,35 @@ first element of current section."
(org-element-put-property element :parent parent) (org-element-put-property element :parent parent)
(when keep-trail (push element trail)) (when keep-trail (push element trail))
(cond (cond
;; 1. Skip any element ending before point or at point ;; 1. Skip any element ending before point. Also skip
;; because the following element has started. On the ;; element ending at point when we're sure that another
;; other hand, if the element ends at point and that ;; element has started.
;; point is also the end of the buffer, do not skip it. ((let ((elem-end (org-element-property :end element)))
((let ((end (org-element-property :end element))) (when (or (< elem-end origin)
(when (or (< end origin) (and (= elem-end origin) (/= elem-end end)))
(and (= end origin) (/= (point-max) end))) (goto-char elem-end))))
(if (> (point-max) end) (goto-char end)
(throw 'exit (if keep-trail trail element))))))
;; 2. An element containing point is always the element at ;; 2. An element containing point is always the element at
;; point. ;; point.
((not (memq type org-element-greater-elements)) ((not (memq type org-element-greater-elements))
(throw 'exit (if keep-trail trail element))) (throw 'exit (if keep-trail trail element)))
;; 3. At any other greater element type, if point is ;; 3. At any other greater element type, if point is
;; within contents, move into it. Otherwise, return ;; within contents, move into it.
;; that element. As a special case, when ORIGIN is
;; contents end and is also the end of the buffer, try
;; to move inside the greater element to find the end
;; of the innermost element.
(t (t
(let ((cbeg (org-element-property :contents-begin element)) (let ((cbeg (org-element-property :contents-begin element))
(cend (org-element-property :contents-end element))) (cend (org-element-property :contents-end element)))
(if (or (not cbeg) (not cend) (> cbeg origin) (< cend origin) (if (or (not cbeg) (not cend) (> cbeg origin) (< cend origin)
(and (= cend origin) (/= (point-max) origin)) ;; Create an anchor for tables and plain lists:
(and (= cbeg origin) (memq type '(plain-list table)))) ;; when point is at the very beginning of these
;; elements, ignoring affiliated keywords,
;; target them instead of their contents.
(and (= cbeg origin) (memq type '(plain-list table)))
;; When point is at contents end, do not move
;; into elements with an explicit ending, but
;; return that element instead.
(and (= cend origin)
(memq type
'(center-block drawer dynamic-block inlinetask
quote-block special-block))))
(throw 'exit (if keep-trail trail element)) (throw 'exit (if keep-trail trail element))
(setq parent element) (setq parent element)
(case type (case type

View File

@ -2263,6 +2263,13 @@ Paragraph \\alpha."
(eq 'plain-list (eq 'plain-list
(org-test-with-temp-text "- item" (org-test-with-temp-text "- item"
(org-element-type (org-element-at-point))))) (org-element-type (org-element-at-point)))))
;; Special case: at the closing line of a greater element, be sure
;; to return it instead of the last element in its contents.
(should
(eq 'center-block
(org-test-with-temp-text "#+BEGIN_CENTER\nParagraph\n#+END_CENTER"
(progn (forward-line 2)
(org-element-type (org-element-at-point))))))
;; With an optional argument, return trail. ;; With an optional argument, return trail.
(should (should
(equal '(paragraph center-block) (equal '(paragraph center-block)

View File

@ -151,6 +151,15 @@ http://article.gmane.org/gmane.emacs.orgmode/21459/"
(goto-char (point-max)) (goto-char (point-max))
(org-fill-paragraph) (org-fill-paragraph)
(buffer-string))))) (buffer-string)))))
;; Correctly fill the last paragraph of a greater element.
(should
(equal "#+BEGIN_CENTER\n- 012345\n 789\n#+END_CENTER"
(org-test-with-temp-text "#+BEGIN_CENTER\n- 012345 789\n#+END_CENTER"
(let ((fill-column 8))
(forward-line)
(end-of-line)
(org-fill-paragraph)
(buffer-string)))))
;; Special case: Fill first paragraph when point is at an item or ;; Special case: Fill first paragraph when point is at an item or
;; a plain-list or a footnote reference. ;; a plain-list or a footnote reference.
(should (should