forked from mirrors/org-mode
org-open-at-point: Do not list links under headline that cannot be opened
* lisp/org-element.el (org-element-context): Do not alter match-data. * lisp/org.el (org-open-at-point): Update docstring listing that `org-open-at-point' opens src-blocks and citations. (org-offer-links-in-entry): Do not display links within invalid contexts. Reported in https://list.orgmode.org/PAXPR06MB77609E8C8E769CD7D769FA4BC6199@PAXPR06MB7760.eurprd06.prod.outlook.com/
This commit is contained in:
parent
df0e96ba42
commit
057df6cce2
|
@ -7880,115 +7880,116 @@ 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."
|
||||
(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-property :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))
|
||||
(beginning-of-line)
|
||||
(let ((case-fold-search t)) (looking-at org-element--affiliated-re))
|
||||
(cond
|
||||
((not (member-ignore-case (match-string 1)
|
||||
(save-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-property :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))
|
||||
(beginning-of-line)
|
||||
(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)))
|
||||
(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)
|
||||
(beginning-of-line)
|
||||
(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-property :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-property :contents-begin element))
|
||||
(cend (org-element-property :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)))
|
||||
;; 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)
|
||||
(beginning-of-line)
|
||||
(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-property :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-property :contents-begin element))
|
||||
(cend (org-element-property :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-property :begin next) pos))
|
||||
(throw 'exit (or last parent))
|
||||
(let ((end (org-element-property :end next))
|
||||
(cbeg (org-element-property :contents-begin next))
|
||||
(cend (org-element-property :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)))))))))))))
|
||||
(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-property :begin next) pos))
|
||||
(throw 'exit (or last parent))
|
||||
(let ((end (org-element-property :end next))
|
||||
(cbeg (org-element-property :contents-begin next))
|
||||
(cend (org-element-property :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))))))))))))))
|
||||
|
||||
(defun org-element-lineage (datum &optional types with-self)
|
||||
"List all ancestors of a given element or object.
|
||||
|
|
13
lisp/org.el
13
lisp/org.el
|
@ -8200,7 +8200,9 @@ a link at point. If they don't find anything interesting at point,
|
|||
they must return nil.")
|
||||
|
||||
(defun org-open-at-point (&optional arg)
|
||||
"Open link, timestamp, footnote or tags at point.
|
||||
"Open thing at point.
|
||||
The thing can be a link, citation, timestamp, footnote, src-block or
|
||||
tags.
|
||||
|
||||
When point is on a link, follow it. Normally, files will be
|
||||
opened by an appropriate application. If the optional prefix
|
||||
|
@ -8215,6 +8217,10 @@ When point is a footnote definition, move to the first reference
|
|||
found. If it is on a reference, move to the associated
|
||||
definition.
|
||||
|
||||
When point is on a src-block of inline src-block, open its result.
|
||||
|
||||
When point is on a citation, follow it.
|
||||
|
||||
When point is on a headline, display a list of every link in the
|
||||
entry, so it is possible to pick one, or all, of them. If point
|
||||
is on a tag, call `org-tags-view' instead.
|
||||
|
@ -8333,7 +8339,10 @@ there is one, return it."
|
|||
(org-back-to-heading t)
|
||||
(setq end (save-excursion (outline-next-heading) (point)))
|
||||
(while (re-search-forward org-link-any-re end t)
|
||||
(push (match-string 0) links))
|
||||
;; Only consider valid links or links openable via
|
||||
;; `org-open-at-point'.
|
||||
(when (memq (org-element-type (org-element-context)) '(link comment comment-block node-property keyword))
|
||||
(push (match-string 0) links)))
|
||||
(setq links (org-uniquify (reverse links))))
|
||||
(cond
|
||||
((null links)
|
||||
|
|
Loading…
Reference in a new issue