Allow to follow internal links from the agenda

* org-agenda.el (org-agenda-open-link): Allow to open an
internal link by using the new `org-offer-links-in-entry'
function.

* org.el (org-offer-links-in-entry): Do not open the link
directly through `org-open-link-from-string', only offer to
select a link and return a cons with the link (as a string)
and the end of entry.
(org-open-at-point): Use `org-offer-links-in-entry' correctly.

Thanks to Memnon Anon for reporting this.
This commit is contained in:
Bastien Guerry 2012-12-29 09:20:35 +01:00
parent 43a242c44d
commit 8477a4b215
2 changed files with 91 additions and 70 deletions

View File

@ -7892,23 +7892,39 @@ If this information is not given, the function uses the tree at point."
(unless no-update (org-agenda-redo))))
(defun org-agenda-open-link (&optional arg)
"Follow the link in the current line, if any.
This looks for a link in the displayed line in the agenda. It also looks
at the text of the entry itself."
"Open the link(s) in the current entry, if any.
This looks for a link in the displayed line in the agenda.
It also looks at the text of the entry itself."
(interactive "P")
(let* ((marker (or (org-get-at-bol 'org-hd-marker)
(org-get-at-bol 'org-marker)))
(buffer (and marker (marker-buffer marker)))
(prefix (buffer-substring
(point-at-bol) (point-at-eol))))
(point-at-bol) (point-at-eol)))
(lkall (org-offer-links-in-entry buffer marker arg prefix))
(lk (car lkall))
(lkend (cdr lkall))
trg)
(cond
(buffer
(with-current-buffer buffer
(save-excursion
(save-restriction
(widen)
(goto-char marker)
(org-offer-links-in-entry arg prefix)))))
(setq trg (and (string-match org-bracket-link-regexp lk)
(match-string 1 lk)))
(if (or (not trg) (string-match org-any-link-re trg))
(save-excursion
(save-restriction
(widen)
(goto-char marker)
(when (search-forward lk nil lkend)
(goto-char (match-beginning 0))
(org-open-at-point))))
;; This is an internal link, widen the buffer
(switch-to-buffer-other-window buffer)
(widen)
(goto-char marker)
(when (search-forward lk nil lkend)
(goto-char (match-beginning 0))
(org-open-at-point)))))
((or (org-in-regexp (concat "\\(" org-bracket-link-regexp "\\)"))
(save-excursion
(beginning-of-line 1)

View File

@ -9648,7 +9648,13 @@ application the system uses for this file type."
org-angle-link-re "\\|"
"[ \t]:[^ \t\n]+:[ \t]*$")))
(not (get-text-property (point) 'org-linked-text)))
(or (org-offer-links-in-entry arg)
(or (let* ((lkall (org-offer-links-in-entry (current-buffer) (point) arg))
(lk (car lkall))
(lkend (cdr lkall)))
(when lk
(prog1 (search-forward lk nil lkend)
(goto-char (match-beginning 0))
(org-open-at-point))))
(progn (require 'org-attach) (org-attach-reveal 'if-exists))))
((run-hook-with-args-until-success 'org-open-at-point-functions))
((and (org-at-timestamp-p t)
@ -9844,68 +9850,67 @@ application the system uses for this file type."
(move-marker org-open-link-marker nil)
(run-hook-with-args 'org-follow-link-hook)))
(defun org-offer-links-in-entry (&optional nth zero)
"Offer links in the current entry and follow the selected link.
If there is only one link, follow it immediately as well.
If NTH is an integer, immediately pick the NTH link found.
(defun org-offer-links-in-entry (buffer marker &optional nth zero)
"Offer links in the current entry and return the selected link.
If there is only one link, return it.
If NTH is an integer, return the NTH link found.
If ZERO is a string, check also this string for a link, and if
there is one, offer it as link number zero."
(let ((re (concat "\\(" org-bracket-link-regexp "\\)\\|"
"\\(" org-angle-link-re "\\)\\|"
"\\(" org-plain-link-re "\\)"))
(cnt ?0)
(in-emacs (if (integerp nth) nil nth))
have-zero end links link c)
(when (and (stringp zero) (string-match org-bracket-link-regexp zero))
(push (match-string 0 zero) links)
(setq cnt (1- cnt) have-zero t))
there is one, return it."
(with-current-buffer buffer
(save-excursion
(org-back-to-heading t)
(setq end (save-excursion (outline-next-heading) (point)))
(while (re-search-forward re end t)
(push (match-string 0) links))
(setq links (org-uniquify (reverse links))))
(cond
((null links)
(message "No links"))
((equal (length links) 1)
(setq link (list (car links))))
((and (integerp nth) (>= (length links) (if have-zero (1+ nth) nth)))
(setq link (list (nth (if have-zero nth (1- nth)) links))))
(t ; we have to select a link
(save-excursion
(save-window-excursion
(delete-other-windows)
(with-output-to-temp-buffer "*Select Link*"
(mapc (lambda (l)
(if (not (string-match org-bracket-link-regexp l))
(princ (format "[%c] %s\n" (incf cnt)
(org-remove-angle-brackets l)))
(if (match-end 3)
(princ (format "[%c] %s (%s)\n" (incf cnt)
(match-string 3 l) (match-string 1 l)))
(princ (format "[%c] %s\n" (incf cnt)
(match-string 1 l))))))
links))
(org-fit-window-to-buffer (get-buffer-window "*Select Link*"))
(message "Select link to open, RET to open all:")
(setq c (read-char-exclusive))
(and (get-buffer "*Select Link*") (kill-buffer "*Select Link*"))))
(when (equal c ?q) (error "Abort"))
(if (equal c ?\C-m)
(setq link links)
(setq nth (- c ?0))
(if have-zero (setq nth (1+ nth)))
(unless (and (integerp nth) (>= (length links) nth))
(error "Invalid link selection"))
(setq link (list (nth (1- nth) links))))))
(if link
(let ((buf (current-buffer)))
(dolist (l link)
(org-open-link-from-string l in-emacs buf))
t)
nil)))
(save-restriction
(widen)
(goto-char marker)
(let ((re (concat "\\(" org-bracket-link-regexp "\\)\\|"
"\\(" org-angle-link-re "\\)\\|"
"\\(" org-plain-link-re "\\)"))
(cnt ?0)
(in-emacs (if (integerp nth) nil nth))
have-zero end links link c)
(when (and (stringp zero) (string-match org-bracket-link-regexp zero))
(push (match-string 0 zero) links)
(setq cnt (1- cnt) have-zero t))
(save-excursion
(org-back-to-heading t)
(setq end (save-excursion (outline-next-heading) (point)))
(while (re-search-forward re end t)
(push (match-string 0) links))
(setq links (org-uniquify (reverse links))))
(cond
((null links)
(message "No links"))
((equal (length links) 1)
(setq link (car links)))
((and (integerp nth) (>= (length links) (if have-zero (1+ nth) nth)))
(setq link (nth (if have-zero nth (1- nth)) links)))
(t ; we have to select a link
(save-excursion
(save-window-excursion
(delete-other-windows)
(with-output-to-temp-buffer "*Select Link*"
(mapc (lambda (l)
(if (not (string-match org-bracket-link-regexp l))
(princ (format "[%c] %s\n" (incf cnt)
(org-remove-angle-brackets l)))
(if (match-end 3)
(princ (format "[%c] %s (%s)\n" (incf cnt)
(match-string 3 l) (match-string 1 l)))
(princ (format "[%c] %s\n" (incf cnt)
(match-string 1 l))))))
links))
(org-fit-window-to-buffer (get-buffer-window "*Select Link*"))
(message "Select link to open, RET to open all:")
(setq c (read-char-exclusive))
(and (get-buffer "*Select Link*") (kill-buffer "*Select Link*"))))
(when (equal c ?q) (error "Abort"))
(if (equal c ?\C-m)
(setq link links)
(setq nth (- c ?0))
(if have-zero (setq nth (1+ nth)))
(unless (and (integerp nth) (>= (length links) nth))
(error "Invalid link selection"))
(setq link (nth (1- nth) links)))))
(cons link end))))))
;; Add special file links that specify the way of opening