help-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

hyperbole: programmatic button creation


From: Jim Ottaway
Subject: hyperbole: programmatic button creation
Date: Thu, 20 Nov 2003 14:49:40 +0000
User-agent: Gnus/5.090024 (Oort Gnus v0.24) Emacs/21.2 (gnu/linux)

I am trying to create a new hyperbole explicit button with a link to a
bibtex entry in a bibtex file. The idea is to use the reftex search
mechanism to ``cite'' a reference as a hyperbole button.

So far I have:

(defact link-to-bibtex-entry (entry)
  "Find bibtex entry. ENTRY is a list: \(key file-name title\)"
  (interactive (list (rft-hyp-get-citation)))
  (funcall 
   (actype:action 'link-to-regexp-match)
   ;; regexp cribbed from reftex-cite.el
   (concat "@[a-zA-Z]+[ \t\n\r]*[{(][ \t\n\r]*" 
           (regexp-quote (first entry)))
   1 (second entry) nil))

The function `rft-hyp-get-citation' supplies a list: (key file-name
title). It uses a slightly modified form of
`reftex-extract-bib-entries' that adds an element with the file name of
the match (see code below).

This works well, as it stands, but it is not quite what I want. What I
would really like is to programmatically create the explicit button
using the list returned from `rft-hyp-get-citation', avoiding all the 
prompts for button type and label in `hui:ebut-create'.

I have looked at the manual and the documentation for `ebut:create',
but I can not work out how to do this from the information supplied.

Does anyone have any experience of creating explicit buttons
programmatically? 

Regards,

Jim Ottaway

Here is the code for `rft-hyp-get-citation':

(require 'cl)
(require 'reftex-cite) 

(defun rft-hyp-get-citation ()
  (let ((entry '()))
    (flet ((reftex-extract-bib-entries 
            (buffers)
            (rft-hyp-reftex-extract-bib-entries buffers)))
      ;; todo: only deals with single choices at the moment
      (setq entry (car (reftex-offer-bib-menu)))
      (list
       (rft-hyp-strip-properties
        (reftex-get-bib-field "&key" entry))
       (reftex-get-bib-field "&file" entry)
       (rft-hyp-strip-properties
        (reftex-get-bib-field "title" entry))))))

(defun rft-hyp-reftex-extract-bib-entries (buffers)
  ;; Extract bib entries which match regexps from BUFFERS.
  ;; BUFFERS is a list of buffers or file names.
  ;; Return list with entries."
  (let* (re-list first-re rest-re
                 (buffer-list (if (listp buffers) buffers (list buffers)))
                 found-list entry buffer1 buffer alist
                 key-point start-point end-point)

    ;; Read a regexp, completing on known citation keys.
    (setq re-list 
          (split-string 
           (completing-read 
            "RegExp [ && RegExp...]: "
            (if reftex-mode
                (if (fboundp 'LaTeX-bibitem-list)
                    (LaTeX-bibitem-list)
                  (cdr (assoc 'bibview-cache 
                              (symbol-value reftex-docstruct-symbol))))
              nil)
            nil nil nil 'reftex-cite-regexp-hist)
           "[ \t]*&&[ \t]*"))

    (setq first-re (car re-list)    ; We'll use the first re to find things,
          rest-re  (cdr re-list))   ; the others to narrow down.
    (if (string-match "\\`[ \t]*\\'" (or first-re ""))
        (error "Empty regular expression"))

    (save-excursion
      (save-window-excursion

        ;; Walk through all bibtex files
        (while buffer-list
          (setq buffer (car buffer-list)
                buffer-list (cdr buffer-list))
          (if (and (bufferp buffer)
                   (buffer-live-p buffer))
              (setq buffer1 buffer)
            (setq buffer1 (reftex-get-file-buffer-force
                           buffer (not reftex-keep-temporary-buffers))))
          (if (not buffer1)
              (message "No such BibTeX file %s (ignored)" buffer)
            (message "Scanning bibliography database %s" buffer1))

          (set-buffer buffer1)
          (save-excursion
            (goto-char (point-min))
            (while (re-search-forward first-re nil t)
              (catch 'search-again
                (setq key-point (point))
                (unless (re-search-backward
                         "\\(\\`\\|[\n\r]\\)[ \t]*@\\([a-zA-Z]+\\)[ 
\t\n\r]*[{(]" nil t)
                  (throw 'search-again nil))
                (setq start-point (point))
                (goto-char (match-end 0))
                (condition-case nil
                    (up-list 1)
                  (error (goto-char key-point)
                          (throw 'search-again nil)))
                (setq end-point (point))

                ;; Ignore @string, @comment and @c entries or things
                ;; outside entries
                (when (or (string= (downcase (match-string 2)) "string")
                          (string= (downcase (match-string 2)) "comment")
                          (string= (downcase (match-string 2)) "c")
                          (< (point) key-point)) ; this means match not in {}
                  (goto-char key-point)
                  (throw 'search-again nil))

                ;; Well, we have got a match
                (setq entry (concat
                             (buffer-substring start-point (point)) "\n"))

                ;; Check if other regexp match as well
                (setq re-list rest-re)
                (while re-list
                  (unless (string-match (car re-list) entry)
                    ;; nope - move on
                    (throw 'search-again nil))
                  (pop re-list))

                (setq alist (reftex-parse-bibtex-entry
                             nil start-point end-point))
                (push (cons "&entry" entry) alist)

                ;; ADDED 
                (push (cons "&file" (buffer-file-name)) alist)

                ;; check for crossref entries
                (if (assoc "crossref" alist)
                    (setq alist
                          (append
                           alist (reftex-get-crossref-alist alist))))

                ;; format the entry
                (push (cons "&formatted" (reftex-format-bib-entry alist))
                      alist)

                ;; make key the first element
                (push (reftex-get-bib-field "&key" alist) alist)

                ;; add it to the list
                (push alist found-list))))
          (reftex-kill-temporary-buffers))))
    (setq found-list (nreverse found-list))

    ;; Sorting
    (cond
     ((eq 'author reftex-sort-bibtex-matches)
      (sort found-list 'reftex-bib-sort-author))
     ((eq 'year   reftex-sort-bibtex-matches)
      (sort found-list 'reftex-bib-sort-year))
     ((eq 'reverse-year reftex-sort-bibtex-matches)
      (sort found-list 'reftex-bib-sort-year-reverse))
     (t found-list))))




reply via email to

[Prev in Thread] Current Thread [Next in Thread]