Skip to content

Commit 057df6c

Browse files
committed
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/
1 parent df0e96b commit 057df6c

File tree

2 files changed

+119
-109
lines changed

2 files changed

+119
-109
lines changed

lisp/org-element.el

Lines changed: 108 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -7880,115 +7880,116 @@ the beginning of any other object, return that object.
78807880
Optional argument ELEMENT, when non-nil, is the closest element
78817881
containing point, as returned by `org-element-at-point'.
78827882
Providing it allows for quicker computation."
7883-
(catch 'objects-forbidden
7884-
(org-with-wide-buffer
7885-
(let* ((pos (point))
7886-
(element (or element (org-element-at-point)))
7887-
(type (org-element-type element))
7888-
(post (org-element-property :post-affiliated element)))
7889-
;; If point is inside an element containing objects or
7890-
;; a secondary string, narrow buffer to the container and
7891-
;; proceed with parsing. Otherwise, return ELEMENT.
7892-
(cond
7893-
;; At a parsed affiliated keyword, check if we're inside main
7894-
;; or dual value.
7895-
((and post (< pos post))
7896-
(beginning-of-line)
7897-
(let ((case-fold-search t)) (looking-at org-element--affiliated-re))
7898-
(cond
7899-
((not (member-ignore-case (match-string 1)
7883+
(save-match-data
7884+
(catch 'objects-forbidden
7885+
(org-with-wide-buffer
7886+
(let* ((pos (point))
7887+
(element (or element (org-element-at-point)))
7888+
(type (org-element-type element))
7889+
(post (org-element-property :post-affiliated element)))
7890+
;; If point is inside an element containing objects or
7891+
;; a secondary string, narrow buffer to the container and
7892+
;; proceed with parsing. Otherwise, return ELEMENT.
7893+
(cond
7894+
;; At a parsed affiliated keyword, check if we're inside main
7895+
;; or dual value.
7896+
((and post (< pos post))
7897+
(beginning-of-line)
7898+
(let ((case-fold-search t)) (looking-at org-element--affiliated-re))
7899+
(cond
7900+
((not (member-ignore-case (match-string 1)
79007901
org-element-parsed-keywords))
7901-
(throw 'objects-forbidden element))
7902-
((< (match-end 0) pos)
7903-
(narrow-to-region (match-end 0) (line-end-position)))
7904-
((and (match-beginning 2)
7905-
(>= pos (match-beginning 2))
7906-
(< pos (match-end 2)))
7907-
(narrow-to-region (match-beginning 2) (match-end 2)))
7902+
(throw 'objects-forbidden element))
7903+
((< (match-end 0) pos)
7904+
(narrow-to-region (match-end 0) (line-end-position)))
7905+
((and (match-beginning 2)
7906+
(>= pos (match-beginning 2))
7907+
(< pos (match-end 2)))
7908+
(narrow-to-region (match-beginning 2) (match-end 2)))
7909+
(t (throw 'objects-forbidden element)))
7910+
;; Also change type to retrieve correct restrictions.
7911+
(setq type 'keyword))
7912+
;; At an item, objects can only be located within tag, if any.
7913+
((eq type 'item)
7914+
(let ((tag (org-element-property :tag element)))
7915+
(if (or (not tag) (/= (line-beginning-position) post))
7916+
(throw 'objects-forbidden element)
7917+
(beginning-of-line)
7918+
(search-forward tag (line-end-position))
7919+
(goto-char (match-beginning 0))
7920+
(if (and (>= pos (point)) (< pos (match-end 0)))
7921+
(narrow-to-region (point) (match-end 0))
7922+
(throw 'objects-forbidden element)))))
7923+
;; At an headline or inlinetask, objects are in title.
7924+
((memq type '(headline inlinetask))
7925+
(let ((case-fold-search nil))
7926+
(goto-char (org-element-property :begin element))
7927+
(looking-at org-complex-heading-regexp)
7928+
(let ((end (match-end 4)))
7929+
(if (not end) (throw 'objects-forbidden element)
7930+
(goto-char (match-beginning 4))
7931+
(when (looking-at org-element-comment-string)
7932+
(goto-char (match-end 0)))
7933+
(if (>= (point) end) (throw 'objects-forbidden element)
7934+
(narrow-to-region (point) end))))))
7935+
;; At a paragraph, a table-row or a verse block, objects are
7936+
;; located within their contents.
7937+
((memq type '(paragraph table-row verse-block))
7938+
(let ((cbeg (org-element-property :contents-begin element))
7939+
(cend (org-element-property :contents-end element)))
7940+
;; CBEG is nil for table rules.
7941+
(if (and cbeg cend (>= pos cbeg)
7942+
(or (< pos cend) (and (= pos cend) (eobp))))
7943+
(narrow-to-region cbeg cend)
7944+
(throw 'objects-forbidden element))))
79087945
(t (throw 'objects-forbidden element)))
7909-
;; Also change type to retrieve correct restrictions.
7910-
(setq type 'keyword))
7911-
;; At an item, objects can only be located within tag, if any.
7912-
((eq type 'item)
7913-
(let ((tag (org-element-property :tag element)))
7914-
(if (or (not tag) (/= (line-beginning-position) post))
7915-
(throw 'objects-forbidden element)
7916-
(beginning-of-line)
7917-
(search-forward tag (line-end-position))
7918-
(goto-char (match-beginning 0))
7919-
(if (and (>= pos (point)) (< pos (match-end 0)))
7920-
(narrow-to-region (point) (match-end 0))
7921-
(throw 'objects-forbidden element)))))
7922-
;; At an headline or inlinetask, objects are in title.
7923-
((memq type '(headline inlinetask))
7924-
(let ((case-fold-search nil))
7925-
(goto-char (org-element-property :begin element))
7926-
(looking-at org-complex-heading-regexp)
7927-
(let ((end (match-end 4)))
7928-
(if (not end) (throw 'objects-forbidden element)
7929-
(goto-char (match-beginning 4))
7930-
(when (looking-at org-element-comment-string)
7931-
(goto-char (match-end 0)))
7932-
(if (>= (point) end) (throw 'objects-forbidden element)
7933-
(narrow-to-region (point) end))))))
7934-
;; At a paragraph, a table-row or a verse block, objects are
7935-
;; located within their contents.
7936-
((memq type '(paragraph table-row verse-block))
7937-
(let ((cbeg (org-element-property :contents-begin element))
7938-
(cend (org-element-property :contents-end element)))
7939-
;; CBEG is nil for table rules.
7940-
(if (and cbeg cend (>= pos cbeg)
7941-
(or (< pos cend) (and (= pos cend) (eobp))))
7942-
(narrow-to-region cbeg cend)
7943-
(throw 'objects-forbidden element))))
7944-
(t (throw 'objects-forbidden element)))
7945-
(goto-char (point-min))
7946-
(let ((restriction (org-element-restriction type))
7947-
(parent element)
7948-
last)
7949-
(catch 'exit
7950-
(while t
7951-
(let ((next (org-element--object-lex restriction)))
7952-
(when next (org-element-put-property next :parent parent))
7953-
;; Process NEXT, if any, in order to know if we need to
7954-
;; skip it, return it or move into it.
7955-
(if (or (not next) (> (org-element-property :begin next) pos))
7956-
(throw 'exit (or last parent))
7957-
(let ((end (org-element-property :end next))
7958-
(cbeg (org-element-property :contents-begin next))
7959-
(cend (org-element-property :contents-end next)))
7960-
(cond
7961-
;; Skip objects ending before point. Also skip
7962-
;; objects ending at point unless it is also the
7963-
;; end of buffer, since we want to return the
7964-
;; innermost object.
7965-
((and (<= end pos) (/= (point-max) end))
7966-
(goto-char end)
7967-
;; For convenience, when object ends at POS,
7968-
;; without any space, store it in LAST, as we
7969-
;; will return it if no object starts here.
7970-
(when (and (= end pos)
7971-
(not (memq (char-before) '(?\s ?\t))))
7972-
(setq last next)))
7973-
;; If POS is within a container object, move into
7974-
;; that object.
7975-
((and cbeg cend
7976-
(>= pos cbeg)
7977-
(or (< pos cend)
7978-
;; At contents' end, if there is no
7979-
;; space before point, also move into
7980-
;; object, for consistency with
7981-
;; convenience feature above.
7982-
(and (= pos cend)
7983-
(or (= (point-max) pos)
7984-
(not (memq (char-before pos)
7985-
'(?\s ?\t)))))))
7986-
(goto-char cbeg)
7987-
(narrow-to-region (point) cend)
7988-
(setq parent next)
7989-
(setq restriction (org-element-restriction next)))
7990-
;; Otherwise, return NEXT.
7991-
(t (throw 'exit next)))))))))))))
7946+
(goto-char (point-min))
7947+
(let ((restriction (org-element-restriction type))
7948+
(parent element)
7949+
last)
7950+
(catch 'exit
7951+
(while t
7952+
(let ((next (org-element--object-lex restriction)))
7953+
(when next (org-element-put-property next :parent parent))
7954+
;; Process NEXT, if any, in order to know if we need to
7955+
;; skip it, return it or move into it.
7956+
(if (or (not next) (> (org-element-property :begin next) pos))
7957+
(throw 'exit (or last parent))
7958+
(let ((end (org-element-property :end next))
7959+
(cbeg (org-element-property :contents-begin next))
7960+
(cend (org-element-property :contents-end next)))
7961+
(cond
7962+
;; Skip objects ending before point. Also skip
7963+
;; objects ending at point unless it is also the
7964+
;; end of buffer, since we want to return the
7965+
;; innermost object.
7966+
((and (<= end pos) (/= (point-max) end))
7967+
(goto-char end)
7968+
;; For convenience, when object ends at POS,
7969+
;; without any space, store it in LAST, as we
7970+
;; will return it if no object starts here.
7971+
(when (and (= end pos)
7972+
(not (memq (char-before) '(?\s ?\t))))
7973+
(setq last next)))
7974+
;; If POS is within a container object, move into
7975+
;; that object.
7976+
((and cbeg cend
7977+
(>= pos cbeg)
7978+
(or (< pos cend)
7979+
;; At contents' end, if there is no
7980+
;; space before point, also move into
7981+
;; object, for consistency with
7982+
;; convenience feature above.
7983+
(and (= pos cend)
7984+
(or (= (point-max) pos)
7985+
(not (memq (char-before pos)
7986+
'(?\s ?\t)))))))
7987+
(goto-char cbeg)
7988+
(narrow-to-region (point) cend)
7989+
(setq parent next)
7990+
(setq restriction (org-element-restriction next)))
7991+
;; Otherwise, return NEXT.
7992+
(t (throw 'exit next))))))))))))))
79927993

79937994
(defun org-element-lineage (datum &optional types with-self)
79947995
"List all ancestors of a given element or object.

lisp/org.el

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8200,7 +8200,9 @@ a link at point. If they don't find anything interesting at point,
82008200
they must return nil.")
82018201

82028202
(defun org-open-at-point (&optional arg)
8203-
"Open link, timestamp, footnote or tags at point.
8203+
"Open thing at point.
8204+
The thing can be a link, citation, timestamp, footnote, src-block or
8205+
tags.
82048206

82058207
When point is on a link, follow it. Normally, files will be
82068208
opened by an appropriate application. If the optional prefix
@@ -8215,6 +8217,10 @@ When point is a footnote definition, move to the first reference
82158217
found. If it is on a reference, move to the associated
82168218
definition.
82178219

8220+
When point is on a src-block of inline src-block, open its result.
8221+
8222+
When point is on a citation, follow it.
8223+
82188224
When point is on a headline, display a list of every link in the
82198225
entry, so it is possible to pick one, or all, of them. If point
82208226
is on a tag, call `org-tags-view' instead.
@@ -8333,7 +8339,10 @@ there is one, return it."
83338339
(org-back-to-heading t)
83348340
(setq end (save-excursion (outline-next-heading) (point)))
83358341
(while (re-search-forward org-link-any-re end t)
8336-
(push (match-string 0) links))
8342+
;; Only consider valid links or links openable via
8343+
;; `org-open-at-point'.
8344+
(when (memq (org-element-type (org-element-context)) '(link comment comment-block node-property keyword))
8345+
(push (match-string 0) links)))
83378346
(setq links (org-uniquify (reverse links))))
83388347
(cond
83398348
((null links)

0 commit comments

Comments
 (0)