Function: org-element-context
org-element-context is an autoloaded and byte-compiled function
defined in org-element.el.gz.
Signature
(org-element-context &optional ELEMENT)
Documentation
Return smallest element or object around point.
Return value is a list like (TYPE PROPS) where TYPE is the type of the element or object and PROPS a plist of properties associated to it.
Possible types are defined in org-element-all-elements and
org-element-all-objects. Properties depend on element or
object type, but always include :begin, :end, :parent and
:post-blank.
As a special case, if point is right after an object and not at the beginning of any other object, return that object.
Optional argument ELEMENT, when non-nil, is the closest element
containing point, as returned by org-element-at-point.
Providing it allows for quicker computation.
This function may modify match data.
Source Code
;; Defined in /usr/src/emacs/lisp/org/org-element.el.gz
;;;###autoload
(defun org-element-context (&optional element)
"Return smallest element or object around point.
Return value is a list like (TYPE PROPS) where TYPE is the type
of the element or object and PROPS a plist of properties
associated to it.
Possible types are defined in `org-element-all-elements' and
`org-element-all-objects'. Properties depend on element or
object type, but always include `:begin', `:end', `:parent' and
`:post-blank'.
As a special case, if point is right after an object and not at
the beginning of any other object, return that object.
Optional argument ELEMENT, when non-nil, is the closest element
containing point, as returned by `org-element-at-point'.
Providing it allows for quicker computation.
This function may modify match data."
(catch 'objects-forbidden
(org-with-wide-buffer
(let* ((pos (point))
(element (or element (org-element-at-point)))
(type (org-element-type element))
(post (org-element-post-affiliated element)))
;; If point is inside an element containing objects or
;; a secondary string, narrow buffer to the container and
;; proceed with parsing. Otherwise, return ELEMENT.
(cond
;; At a parsed affiliated keyword, check if we're inside main
;; or dual value.
((and post (< pos post))
(forward-line 0)
(let ((case-fold-search t)) (looking-at org-element--affiliated-re))
(cond
((not (member-ignore-case (match-string 1)
org-element-parsed-keywords))
(throw 'objects-forbidden element))
((<= (match-end 0) pos)
(narrow-to-region (match-end 0) (line-end-position)))
((and (match-beginning 2)
(>= pos (match-beginning 2))
(< pos (match-end 2)))
(narrow-to-region (match-beginning 2) (match-end 2)))
(t (throw 'objects-forbidden element)))
;; Also change type to retrieve correct restrictions.
(setq type 'keyword))
;; At an item, objects can only be located within tag, if any.
((eq type 'item)
(let ((tag (org-element-property :tag element)))
(if (or (not tag) (/= (line-beginning-position) post))
(throw 'objects-forbidden element)
(forward-line 0)
(search-forward tag (line-end-position))
(goto-char (match-beginning 0))
(if (and (>= pos (point)) (< pos (match-end 0)))
(narrow-to-region (point) (match-end 0))
(throw 'objects-forbidden element)))))
;; At an headline or inlinetask, objects are in title.
((memq type '(headline inlinetask))
(let ((case-fold-search nil))
(goto-char (org-element-begin element))
(looking-at org-complex-heading-regexp)
(let ((end (match-end 4)))
(if (not end) (throw 'objects-forbidden element)
(goto-char (match-beginning 4))
(when (looking-at org-element-comment-string)
(goto-char (match-end 0)))
(if (>= (point) end) (throw 'objects-forbidden element)
(narrow-to-region (point) end))))))
;; At a paragraph, a table-row or a verse block, objects are
;; located within their contents.
((memq type '(paragraph table-row verse-block))
(let ((cbeg (org-element-contents-begin element))
(cend (org-element-contents-end element)))
;; CBEG is nil for table rules.
(if (and cbeg cend (>= pos cbeg)
(or (< pos cend) (and (= pos cend) (eobp))))
(narrow-to-region cbeg cend)
(throw 'objects-forbidden element))))
(t (throw 'objects-forbidden element)))
(goto-char (point-min))
(let ((restriction (org-element-restriction type))
(parent element)
last)
(catch 'exit
(while t
(let ((next (org-element--object-lex restriction)))
(when next (org-element-put-property next :parent parent))
;; Process NEXT, if any, in order to know if we need to
;; skip it, return it or move into it.
(if (or (not next) (> (org-element-begin next) pos))
(throw 'exit (or last parent))
(let ((end (org-element-end next))
(cbeg (org-element-contents-begin next))
(cend (org-element-contents-end next)))
(cond
;; Skip objects ending before point. Also skip
;; objects ending at point unless it is also the
;; end of buffer, since we want to return the
;; innermost object.
((and (<= end pos) (/= (point-max) end))
(goto-char end)
;; For convenience, when object ends at POS,
;; without any space, store it in LAST, as we
;; will return it if no object starts here.
(when (and (= end pos)
(not (memq (char-before) '(?\s ?\t))))
(setq last next)))
;; If POS is within a container object, move into
;; that object.
((and cbeg cend
(>= pos cbeg)
(or (< pos cend)
;; At contents' end, if there is no
;; space before point, also move into
;; object, for consistency with
;; convenience feature above.
(and (= pos cend)
(or (= (point-max) pos)
(not (memq (char-before pos)
'(?\s ?\t)))))))
(goto-char cbeg)
(narrow-to-region (point) cend)
(setq parent next)
(setq restriction (org-element-restriction next)))
;; Otherwise, return NEXT.
(t (throw 'exit next)))))))))))))