Function: bibtex-url

bibtex-url is an interactive and byte-compiled function defined in bibtex.el.gz.

Signature

(bibtex-url &optional POS NO-BROWSE)

Documentation

Browse a URL for the BibTeX entry at point.

Optional POS is the location of the BibTeX entry. The URL is generated using the schemes defined in bibtex-generate-url-list
(see there). If multiple schemes match for this entry, or the same scheme
matches more than once, use the one for which the first step's match is the closest to POS. The URL is passed to browse-url unless NO-BROWSE is t. Return the URL or nil if none can be generated.

Probably introduced at or before Emacs version 22.1.

Key Bindings

Source Code

;; Defined in /usr/src/emacs/lisp/textmodes/bibtex.el.gz
(defun bibtex-url (&optional pos no-browse)
  "Browse a URL for the BibTeX entry at point.
Optional POS is the location of the BibTeX entry.
The URL is generated using the schemes defined in `bibtex-generate-url-list'
\(see there).  If multiple schemes match for this entry, or the same scheme
matches more than once, use the one for which the first step's match is the
closest to POS.  The URL is passed to `browse-url' unless NO-BROWSE is t.
Return the URL or nil if none can be generated."
  (interactive)
  (unless pos (setq pos (point)))
  (save-excursion
    (goto-char pos)
    (bibtex-beginning-of-entry)
    (let ((end (save-excursion (bibtex-end-of-entry)))
          (fields-alist (save-excursion (bibtex-parse-entry t)))
          ;; Always ignore case,
          (case-fold-search t)
          text url scheme obj fmt fl-match)
      ;; The return value of `bibtex-parse-entry' (i.e., FIELDS-ALIST)
      ;; is always used to generate the URL.  However, if the BibTeX
      ;; entry contains more than one URL, we have multiple matches
      ;; for the first step defining the generation of the URL.
      ;; Therefore, we try to initiate the generation of the URL
      ;; based on the match of `bibtex-font-lock-url' that is the
      ;; closest to POS.  If that fails (no match found) we try to
      ;; initiate the generation of the URL based on the properly
      ;; concatenated CONTENT of the field as returned by
      ;; `bibtex-text-in-field-bounds'.  The latter approach can
      ;; differ from the former because `bibtex-font-lock-url' uses
      ;; the buffer itself.
      (while (bibtex-font-lock-url end t)
        (push (list (bibtex-dist pos (match-beginning 0) (match-end 0))
                    (match-beginning 0)
                    (buffer-substring-no-properties
                     (match-beginning 0) (match-end 0)))
              fl-match)
        ;; `bibtex-font-lock-url' moves point to end of match.
        (forward-char))
      (when fl-match
        (setq fl-match (car (sort fl-match (lambda (x y) (< (car x) (car y))))))
        (goto-char (nth 1 fl-match))
        (bibtex-beginning-of-field) (re-search-backward ",")
        (let* ((bounds (bibtex-parse-field))
               (name (bibtex-name-in-field bounds))
               (content (bibtex-text-in-field-bounds bounds t))
               (lst bibtex-generate-url-list))
          ;; This match can fail when CONTENT differs from text in buffer.
          (when (string-match (regexp-quote (nth 2 fl-match)) content)
            ;; TEXT is the part of CONTENT that starts with the match
            ;; of `bibtex-font-lock-url' we are looking for.
            (setq text (substring content (match-beginning 0)))
            (while (and (not url) (setq scheme (pop lst)))
              ;; Verify the match of `bibtex-font-lock-url' by
              ;; comparing with TEXT.
              (when (and (string-equal-ignore-case (caar scheme) name)
                         (string-match (cdar scheme) text))
                (setq url t scheme (cdr scheme)))))))

      ;; If the match of `bibtex-font-lock-url' was not approved
      ;; parse FIELDS-ALIST, i.e., the output of `bibtex-parse-entry'.
      (unless url
        (let ((lst bibtex-generate-url-list))
          (while (and (not url) (setq scheme (pop lst)))
            (when (and (setq text (cdr (assoc-string (caar scheme)
                                                      fields-alist t)))
                       (string-match (cdar scheme) text))
              (setq url t scheme (cdr scheme))))))

      (when url
        (setq url (if (null scheme) (match-string 0 text)
                    (if (stringp (car scheme))
                        (setq fmt (pop scheme)))
                    (dolist (step scheme)
                      ;; In the first STEP, if the field contains multiple
                      ;; matches, we want the match the closest to point.
                      ;; (if (eq step (car scheme))
                      (setq text (cdr (assoc-string (car step) fields-alist t)))
                      (if (string-match (nth 1 step) text)
                          (push (cond ((functionp (nth 2 step))
                                       (funcall (nth 2 step) text))
                                      ((numberp (nth 2 step))
                                       (match-string (nth 2 step) text))
                                      (t
                                       (replace-match (nth 2 step) t nil text)))
                                obj)
                        ;; If SCHEME is set up correctly,
                        ;; we should never reach this point
                        (error "Match failed: %s" text)))
                    (if fmt (apply #'format fmt (nreverse obj))
                      (apply #'concat (nreverse obj)))))
        (if (called-interactively-p 'interactive) (message "%s" url))
        (unless no-browse (browse-url url)))
      (if (and (not url) (called-interactively-p 'interactive))
	  (message "No URL known."))
      url)))