;;; bibtex.el --- BibTeX mode for GNU Emacs
-;; Copyright (C) 1992,94,95,96,97,98,1999,2003,2004
+;; Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2003, 2004
;; Free Software Foundation, Inc.
;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de>
:type 'hook)
(defcustom bibtex-field-delimiters 'braces
- "*Type of field delimiters. Allowed values are `braces' or `double-quotes'."
+ "*Type of field delimiters. Allowed values are `braces' or `double-quotes'."
:group 'bibtex
:type '(choice (const braces)
(const double-quotes)))
(defcustom bibtex-entry-delimiters 'braces
- "*Type of entry delimiters. Allowed values are `braces' or `parentheses'."
+ "*Type of entry delimiters. Allowed values are `braces' or `parentheses'."
:group 'bibtex
:type '(choice (const braces)
(const parentheses)))
Allowed non-nil values are:
plain All entries are sorted alphabetically.
crossref All entries are sorted alphabetically unless an entry has a
- crossref field. These crossrefed entries are placed in
+ crossref field. These crossrefed entries are placed in
alphabetical order immediately preceding the main entry.
entry-class The entries are divided into classes according to their
- entry name, see `bibtex-sort-entry-class'. Within each class
+ entry name, see `bibtex-sort-entry-class'. Within each class
the entries are sorted alphabetically.
See also `bibtex-sort-ignore-string-entries'."
:group 'bibtex
("Book" "Proceedings"))
"*List of classes of BibTeX entry names, used for sorting entries.
If value of `bibtex-maintain-sorted-entries' is `entry-class'
-entries are ordered according to the classes they belong to. Each
-class contains a list of entry names. An entry `catch-all' applies
+entries are ordered according to the classes they belong to. Each
+class contains a list of entry names. An entry `catch-all' applies
to all entries not explicitely mentioned.")
(defcustom bibtex-sort-ignore-string-entries t
:type '(repeat string))
(defcustom bibtex-generate-url-list
- '((("url" . t) ("url" t)))
+ '((("url" . ".*:.*"))
+ ;; Example of a complex setup.
+ (("journal" . "\\<\\(PR[ABCDEL]?\\|RMP\\)\\>")
+ "http://publish.aps.org/abstract/"
+ ("journal" ".*" downcase)
+ "/v"
+ ("volume" ".*" 0)
+ "/p"
+ ("pages" "\\`\\([0-9]+\\)" 1)))
"List of schemes for generating the URL of a BibTeX entry.
These schemes are used by `bibtex-url'.
-Each scheme is of the form ((FIELD . REGEXP) STEPS).
+Each scheme is of the form ((FIELD . REGEXP) STEP...).
FIELD is a field name as returned by `bibtex-parse-entry'.
-REGEXP is matched against the text of FIELD.
-If the match succeeds, the list STEPS is used to generate the URL.
-If REGEXP is t, always generate the URL if FIELD is present.
-
-If an element of STEPS is a list (FIELD MATCH FILTER),
-the text of FIELD is matched against MATCH.
-If MATCH is t, the text of FIELD is accepted as is.
-If MATCH is a cons cell (REGEXP . REPLACE), the text is matched against REGEXP.
-If REPLACE is a string, the text is replaced with REPLACE. If REPLACE is a
-number, it specifies which parenthesized expression in the match is taken.
-The optional element FILTER is a function for piping the match through it.
-The text strings are then concatenated to generate the URL.
-
-If an element of STEPS is a string, it is simply added to the URL.
-
-Case is always ignored. Always remove the field delimiters."
+REGEXP is matched against the text of FIELD. If the match succeed, then
+this scheme will be used. If no STEPS are specified the matched text is used
+as the URL, otherwise the URL is built by concatenating the STEPS.
+
+A STEP can be a string or a list (FIELD REGEXP REPLACE) in which case
+the text of FIELD is matched against REGEXP, and is replaced with REPLACE.
+REPLACE can be a string, or a number (which selects the corresponding submatch)
+or a function called with the field's text as argument and with the
+`match-data' properly set.
+
+Case is always ignored. Always remove the field delimiters."
:group 'bibtex
:type '(repeat
- (list :tag "Scheme"
+ (list :tag "Scheme"
(cons :tag "Matcher" :extra-offset 4
(string :tag "BibTeX field")
- (choice (regexp :tag "Regexp")
- (const :tag "Accept as is" t)))
+ (regexp :tag "Regexp"))
(repeat :tag "Steps to generate URL" :inline t
(choice
(string :tag "Literal text")
(list (string :tag "BibTeX field")
- (choice (const :tag "Accept as is" t)
- (cons (string :tag "Field")
- (choice (regexp :tag "Regexp")
- (integer :tag "Matched parenthesis"))))
- (option (function :tag "Filter" :value ignore))))))))
+ (regexp :tag "Regexp")
+ (choice (string :tag "Replacement")
+ (integer :tag "Sub-match")
+ (function :tag "Filter"))))))))
;; bibtex-font-lock-keywords is a user option as well, but since the
;; patterns used to define this variable are defined in a later
(make-variable-buffer-local 'bibtex-reference-keys)
(defvar bibtex-buffer-last-parsed-tick nil
- "Last value returned by `buffer-modified-tick' when buffer
-was parsed for keys the last time.")
+ "Value of `buffer-modified-tick' last time buffer was parsed for keys.")
(defvar bibtex-parse-idle-timer nil
"Stores if timer is already installed.")
(,(concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=")
1 font-lock-variable-name-face)
;; url
- (bibtex-font-lock-url 0 '(face nil mouse-face highlight
+ (bibtex-font-lock-url 0 '(face nil mouse-face highlight
keymap bibtex-url-map)))
"*Default expressions to highlight in BibTeX mode.")
"Regexp for `bibtex-font-lock-url'.")
(defvar bibtex-field-name-for-parsing nil
- "Temporary variable storing the name string to be parsed by the callback
-function `bibtex-parse-field-name'.")
+ "Regexp of field name to be parsed by function `bibtex-parse-field-name'.
+Passed by dynamic scoping.")
(defvar bibtex-sort-entry-class-alist
(let ((i -1) alist)
(dolist (entry class)
;; all entry names should be downcase (for ease of comparison)
(push (cons (if (stringp entry) (downcase entry) entry) i) alist))))
- "Alist for the classes of the entry types if the value of
-`bibtex-maintain-sorted-entries' is `entry-class'.")
+ "Alist mapping entry types to their sorting index.
+Auto-generated from `bibtex-sort-entry-class'.
+Used when `bibtex-maintain-sorted-entries' is `entry-class'.")
\f
;; Special support taking care of variants
\f
;; Support for hideshow minor mode
(defun bibtex-hs-forward-sexp (arg)
- "Replacement for `forward-sexp' to be used by `hs-minor-mode'."
- (if (< arg 0)
- (backward-sexp 1)
- (if (looking-at "@\\S(*\\s(")
- (progn
- (goto-char (match-end 0))
- (forward-char -1)
- (forward-sexp 1))
- (forward-sexp 1))))
+ "Replacement for `forward-sexp' to be used by `hs-minor-mode'.
+ARG is ignored."
+ (if (looking-at "@\\S(*\\s(")
+ (goto-char (1- (match-end 0))))
+ (forward-sexp 1))
(add-to-list
'hs-special-modes-alist
"Parse the field name stored in `bibtex-field-name-for-parsing'.
If the field name is found, return a triple consisting of the position of the
very first character of the match, the actual starting position of the name
-part and end position of the match. Move point to end of field name.
+part and end position of the match. Move point to end of field name.
If `bibtex-autoadd-commas' is non-nil add missing comma at end of preceeding
BibTeX field as necessary."
(cond ((looking-at ",[ \t\n]*")
The text part is either a string, or an empty string, or a constant followed
by one or more <# (string|constant)> pairs. If a syntactically correct text
is found, a pair containing the start and end position of the text is
-returned, nil otherwise. Move point to end of field text."
+returned, nil otherwise. Move point to end of field text."
(let ((starting-point (point))
end-point failure boundaries)
(while (not (or end-point failure))
"Search forward to find a field of name NAME.
If a syntactically correct field is found, a pair containing the boundaries of
the name and text parts of the field is returned. The search is limited by
-optional arg BOUND. If BOUND is t the search is limited by the end of the current
-entry. Do not move point."
+optional arg BOUND. If BOUND is t the search is limited by the end of the
+current entry. Do not move point."
(save-match-data
(save-excursion
(unless (integer-or-marker-p bound)
"Search backward to find a field of name NAME.
If a syntactically correct field is found, a pair containing the boundaries of
the name and text parts of the field is returned. The search is limited by
-optional arg BOUND. If BOUND is t the search is limited by the beginning of the
-current entry. Do not move point."
+optional arg BOUND. If BOUND is t the search is limited by the beginning of the
+current entry. Do not move point."
(save-match-data
(save-excursion
(unless (integer-or-marker-p bound)
content)))
(defun bibtex-text-in-field (field &optional follow-crossref)
- "Get content of field FIELD of current BibTeX entry. Return nil if not found.
+ "Get content of field FIELD of current BibTeX entry. Return nil if not found.
If optional arg FOLLOW-CROSSREF is non-nil, follow crossref."
(save-excursion
(save-restriction
"Parse the postfix part of a BibTeX string entry, including the text.
If the string postfix is found, return a triple consisting of the position of
the actual starting and ending position of the text and the very last
-character of the string entry. Move point past BibTeX string entry."
+character of the string entry. Move point past BibTeX string entry."
(let* ((case-fold-search t)
(bounds (bibtex-parse-field-text)))
(when bounds
(defun bibtex-search-forward-string ()
"Search forward to find a BibTeX string entry.
If a syntactically correct entry is found, a pair containing the boundaries of
-the reference key and text parts of the string is returned. Do not move point."
+the reference key and text parts of the string is returned. Do not move point."
(save-excursion
(save-match-data
(let ((case-fold-search t)
(defun bibtex-search-backward-string ()
"Search backward to find a BibTeX string entry.
If a syntactically correct entry is found, a pair containing the boundaries of
-the reference key and text parts of the field is returned. Do not move point."
+the reference key and text parts of the field is returned. Do not move point."
(save-excursion
(save-match-data
(let ((case-fold-search t)
(match-end bibtex-type-in-head)))
(defun bibtex-key-in-head (&optional empty)
- "Extract BibTeX key in head. Return optional arg EMPTY if key is empty."
+ "Extract BibTeX key in head. Return optional arg EMPTY if key is empty."
(if (match-beginning bibtex-key-in-head)
(buffer-substring-no-properties (match-beginning bibtex-key-in-head)
(match-end bibtex-key-in-head))
;; Helper Functions
(defsubst bibtex-string= (str1 str2)
- "Return t if two strings are equal, ignoring case."
+ "Return t if STR1 and STR2 are equal, ignoring case."
(eq t (compare-strings str1 0 nil str2 0 nil t)))
(defun bibtex-delete-whitespace ()
(if (equal (current-column) 0) 1 0)))
(defun bibtex-skip-to-valid-entry (&optional backward)
- "Unless at beginning of a valid BibTeX entry, move point to beginning of the
-next valid one. With optional argument BACKWARD non-nil, move backward to
-beginning of previous valid one. A valid entry is a syntactical correct one
+ "Move point to beginning of the next valid BibTeX entry.
+Do not move if we are already at beginning of a valid BibTeX entry.
+With optional argument BACKWARD non-nil, move backward to
+beginning of previous valid one. A valid entry is a syntactical correct one
with type contained in `bibtex-entry-field-alist' or, if
`bibtex-sort-ignore-string-entries' is nil, a syntactical correct string
-entry. Return buffer position of beginning and ending of entry if a valid
+entry. Return buffer position of beginning and ending of entry if a valid
entry is found, nil otherwise."
(interactive "P")
(let ((case-fold-search t)
(defun bibtex-map-entries (fun)
"Call FUN for each BibTeX entry starting with the current.
-Do this to the end of the file. FUN is called with three arguments, the key of
+Do this to the end of the file. FUN is called with three arguments, the key of
the entry and the buffer positions (marker) of beginning and end of entry.
-Point is inside the entry. If `bibtex-sort-ignore-string-entries' is non-nil,
+Point is inside the entry. If `bibtex-sort-ignore-string-entries' is non-nil,
FUN will not be called for @String entries."
(let ((case-fold-search t))
(bibtex-beginning-of-entry)
(defun bibtex-search-entry (empty-head &optional bound noerror backward)
"Search for a BibTeX entry (maybe without reference key if EMPTY-HEAD is t).
-BOUND and NOERROR are exactly as in `re-search-forward'. If BACKWARD
-is non-nil, search is done in reverse direction. Point is moved past the
+BOUND and NOERROR are exactly as in `re-search-forward'. If BACKWARD
+is non-nil, search is done in reverse direction. Point is moved past the
closing delimiter (at the beginning of entry if BACKWARD is non-nil).
Return a cons pair with buffer positions of beginning and end of entry.
After call to this function MATCH-BEGINNING and MATCH-END functions
(skip-chars-forward " \t\n")))
(defun bibtex-beginning-of-first-entry ()
- "Go to the beginning of the first BibTeX entry in buffer. Return point."
+ "Go to the beginning of the first BibTeX entry in buffer. Return point."
(goto-char (point-min))
(if (re-search-forward "^[ \t]*@" nil 'move)
(beginning-of-line))
(defun bibtex-enclosing-field (&optional noerr)
"Search for BibTeX field enclosing point.
-Use `match-beginning' and `match-end' to parse the field. If NOERR is non-nil,
-no error is signalled. In this case, bounds are returned on success,
-nil otherwise. Does not move point."
+Use `match-beginning' and `match-end' to parse the field. If NOERR is non-nil,
+no error is signalled. In this case, bounds are returned on success,
+nil otherwise. Does not move point."
(let ((bounds (bibtex-search-backward-field bibtex-field-name t)))
(if (and bounds
(<= (bibtex-start-of-field bounds) (point))
(error "Can't find enclosing BibTeX field")))))
(defun bibtex-enclosing-entry-maybe-empty-head ()
- "Search for BibTeX entry enclosing point. Move point to end of entry.
+ "Search for BibTeX entry enclosing point. Move point to end of entry.
Beginning (but not end) of entry is given by (`match-beginning' 0)."
(let ((case-fold-search t)
(old-point (point)))
(defun bibtex-autokey-abbrev (string len)
"Return an abbreviation of STRING with at least LEN characters.
If LEN is positive the abbreviation is terminated only after a consonant
-or at the word end. If LEN is negative the abbreviation is strictly
-enforced using abs (LEN) characters. If LEN is not a number, STRING
+or at the word end. If LEN is negative the abbreviation is strictly
+enforced using abs (LEN) characters. If LEN is not a number, STRING
is returned unchanged."
(cond ((or (not (numberp len))
(<= (length string) (abs len)))
string)))))
(defun bibtex-autokey-get-field (field &optional change-list)
- "Get content of BibTeX field FIELD. Return empty string if not found.
+ "Get content of BibTeX field FIELD. Return empty string if not found.
Optional arg CHANGE-LIST is a list of substitution patterns that is
-applied to the content of FIELD. It is an alist with pairs
+applied to the content of FIELD. It is an alist with pairs
\(OLD-REGEXP . NEW-STRING\)."
(let ((content (bibtex-text-in-field field bibtex-autokey-use-crossref))
case-fold-search)
(split-string names "[ \t\n]+and[ \t\n]+")))))
(defun bibtex-autokey-demangle-name (fullname)
- "Get the last part from a well-formed name and perform abbreviations."
+ "Get the last part from a well-formed FULLNAME and perform abbreviations."
(let* (case-fold-search
(name (cond ((string-match "\\([A-Z][^, ]*\\)[^,]*," fullname)
;; Name is of the form "von Last, First" or
`bibtex-autokey-name-change-strings' to the corresponding new
one (see documentation of this variable for further detail).
4. For every of at least first `bibtex-autokey-names' names in
- the name field, determine the last name. If there are maximal
+ the name field, determine the last name. If there are maximal
`bibtex-autokey-names' + `bibtex-autokey-names-stretch'
names, all names are used.
5. From every last name, take at least `bibtex-autokey-name-length'
`bibtex-autokey-name-case-convert'.
7. Build the name part of the key by concatenating all
abbreviated last names with the string
- `bibtex-autokey-name-separator' between any two. If there are
+ `bibtex-autokey-name-separator' between any two. If there are
more names than are used in the name part, prepend the string
contained in `bibtex-autokey-additional-names'.
8. Build the year part of the key by truncating the contents of
the year field to the rightmost `bibtex-autokey-year-length'
- digits (useful values are 2 and 4). If the year field (or any
+ digits (useful values are 2 and 4). If the year field (or any
other field required to generate the key) is absent, but the entry
has a valid crossref field and the variable
`bibtex-autokey-use-crossref' is non-nil, use the field of the
appear in `bibtex-autokey-titleword-ignore'.
Build the title part of the key by using at least the first
`bibtex-autokey-titlewords' words from this
- abbreviated title. If the abbreviated title ends after
+ abbreviated title. If the abbreviated title ends after
maximal `bibtex-autokey-titlewords' +
`bibtex-autokey-titlewords-stretch' words, all
words from the abbreviated title are used.
and the title part with `bibtex-autokey-name-year-separator'
between the name part and the year part if both are non-empty
and `bibtex-autokey-year-title-separator' between the year
- part and the title part if both are non-empty. If the year
+ part and the title part if both are non-empty. If the year
part is empty, but not the other two parts,
`bibtex-autokey-year-title-separator' is used as well.
16. If the value of `bibtex-autokey-before-presentation-function'
- is non-nil, it must be a function taking one argument. This
+ is non-nil, it must be a function taking one argument. This
function is then called with the generated key as the
- argument. The return value of this function (a string) is
+ argument. The return value of this function (a string) is
used as the key.
17. If the value of `bibtex-autokey-edit-before-use' is non-nil,
the key is then presented in the minibuffer to the user,
The buffer might possibly be restricted.
Find both entry keys and crossref entries.
If ADD is non-nil add the new keys to `bibtex-reference-keys' instead of
-simply resetting it. If ADD is an alist of keys, also add ADD to
-`bibtex-reference-keys'. If ABORTABLE is non-nil abort on user
-input. If VERBOSE is non-nil gives messages about progress.
+simply resetting it. If ADD is an alist of keys, also add ADD to
+`bibtex-reference-keys'. If ABORTABLE is non-nil abort on user
+input. If VERBOSE is non-nil gives messages about progress.
Return alist of keys if parsing was completed, `aborted' otherwise."
(let ((reference-keys (if (and add
(listp bibtex-reference-keys))
"Set `bibtex-strings' to the string definitions in the whole buffer.
The buffer might possibly be restricted.
If ADD is non-nil add the new strings to `bibtex-strings' instead of
-simply resetting it. If ADD is an alist of strings, also add ADD to
-`bibtex-strings'. If ABORTABLE is non-nil abort on user input.
+simply resetting it. If ADD is an alist of strings, also add ADD to
+`bibtex-strings'. If ABORTABLE is non-nil abort on user input.
Return alist of strings if parsing was completed, `aborted' otherwise."
(save-excursion
(save-match-data
(append bibtex-predefined-strings (nreverse compl)))))
(defun bibtex-parse-buffers-stealthily ()
- "Called by `bibtex-run-with-idle-timer'. Whenever emacs has been idle
+ "Parse buffer in the background during idle time.
+Called by `bibtex-run-with-idle-timer'. Whenever Emacs has been idle
for `bibtex-parse-keys-timeout' seconds, all BibTeX buffers (starting
with the current) are parsed."
(save-excursion
(setq buffers (cdr buffers))))))
(defun bibtex-complete-internal (completions)
- "Complete word fragment before point to longest prefix of one
-string defined in list COMPLETIONS. If point is not after the part
-of a word, all strings are listed. Return completion."
+ "Complete word fragment before point to longest prefix of COMPLETIONS.
+COMPLETIONS should be a list of strings. If point is not after the part
+of a word, all strings are listed. Return completion."
(let* ((case-fold-search t)
(beg (save-excursion
(re-search-backward "[ \t{\"]")
(set-window-point window (point))))
(defun bibtex-pop (arg direction)
- "Generic function used by `bibtex-pop-previous' and `bibtex-pop-next'."
+ "Fill current field from the ARG'th same field's text in DIRECTION.
+Generic function used by `bibtex-pop-previous' and `bibtex-pop-next'."
(let (bibtex-help-message)
(bibtex-find-text nil))
(save-excursion
General information on working with BibTeX mode:
You should use commands such as \\[bibtex-Book] to get a template for a
-specific entry. You should then fill in all desired fields using
-\\[bibtex-next-field] to jump from field to field. After having filled
+specific entry. You should then fill in all desired fields using
+\\[bibtex-next-field] to jump from field to field. After having filled
in all desired fields in the entry, you should clean the new entry
with the command \\[bibtex-clean-entry].
Some features of BibTeX mode are available only by setting the variable
-`bibtex-maintain-sorted-entries' to non-nil. However, then BibTeX mode will
+`bibtex-maintain-sorted-entries' to non-nil. However, then BibTeX mode will
work only with buffers containing valid (syntactical correct) entries
-and with entries being sorted. This is usually the case, if you have
+and with entries being sorted. This is usually the case, if you have
created a buffer completely with BibTeX mode and finished every new
entry with \\[bibtex-clean-entry].
(cons required optional)))
(defun bibtex-entry (entry-type)
- "Insert a new BibTeX entry.
+ "Insert a new BibTeX entry of type ENTRY-TYPE.
After insertion it calls the functions in `bibtex-add-entry-hook'."
(interactive (let* ((completion-ignore-case t)
(e-t (completing-read
(insert "@" entry-type (bibtex-entry-left-delimiter))
(if key (insert key))
(save-excursion
- (mapcar 'bibtex-make-field (car field-list))
- (mapcar 'bibtex-make-optional-field (cdr field-list))
+ (mapc 'bibtex-make-field (car field-list))
+ (mapc 'bibtex-make-optional-field (cdr field-list))
(if bibtex-comma-after-last-field
(insert ","))
(insert "\n")
"Make a field named FIELD in current BibTeX entry.
FIELD is either a string or a list of the form
\(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in
-`bibtex-entry-field-alist'."
+`bibtex-entry-field-alist'.
+If CALLED-BY-YANK is non-nil, don't insert delimiters."
(interactive
(list (let ((completion-ignore-case t)
(field-list (bibtex-field-list
(defun bibtex-beginning-of-entry ()
"Move to beginning of BibTeX entry (beginning of line).
If inside an entry, move to the beginning of it, otherwise move to the
-beginning of the previous entry. If point is ahead of all BibTeX entries
-move point to the beginning of buffer. Return the new location of point."
+beginning of the previous entry. If point is ahead of all BibTeX entries
+move point to the beginning of buffer. Return the new location of point."
(interactive)
(skip-chars-forward " \t")
(if (looking-at "@")
(defun bibtex-end-of-entry ()
"Move to end of BibTeX entry (past the closing brace).
If inside an entry, move to the end of it, otherwise move to the end
-of the previous entry. Do not move if ahead of first entry.
+of the previous entry. Do not move if ahead of first entry.
Return the new location of point."
(interactive)
(let ((case-fold-search t)
(bibtex-end-of-entry))))
(defun bibtex-entry-index ()
- "Return the index of the BibTeX entry at point. Move point.
+ "Return the index of the BibTeX entry at point. Move point.
The index is a list (KEY CROSSREF-KEY ENTRY-NAME) that is used for sorting
-the entries of the BibTeX buffer. Return nil if no entry found."
+the entries of the BibTeX buffer. Return nil if no entry found."
(let ((case-fold-search t))
(if (re-search-forward bibtex-entry-maybe-empty-head nil t)
(let ((key (bibtex-key-in-head))
(defun bibtex-sort-buffer ()
"Sort BibTeX buffer alphabetically by key.
The predicate for sorting is defined via `bibtex-maintain-sorted-entries'.
-If its value is nil use plain sorting. Text outside of BibTeX entries is not
-affected. If `bibtex-sort-ignore-string-entries' is non-nil, @String entries
+If its value is nil use plain sorting. Text outside of BibTeX entries is not
+affected. If `bibtex-sort-ignore-string-entries' is non-nil, @String entries
will be ignored."
(interactive)
(save-restriction
INDEX is a list (KEY CROSSREF-KEY ENTRY-NAME).
Move point where the entry KEY should be placed.
If `bibtex-maintain-sorted-entries' is non-nil, perform a binary
-search to look for place for KEY. This will fail if buffer is not in
+search to look for place for KEY. This will fail if buffer is not in
sorted order, see \\[bibtex-validate].)
Return t if preparation was successful or nil if entry KEY already exists."
(let ((key (nth 0 index))
Check that no required fields are empty and formats entry dependent
on the value of `bibtex-entry-format'.
If the reference key of the entry is empty or a prefix argument is given,
-calculate a new reference key. (Note: this will only work if fields in entry
+calculate a new reference key. (Note: this will only work if fields in entry
begin on separate lines prior to calling `bibtex-clean-entry' or if
'realign is contained in `bibtex-entry-format'.)
Don't call `bibtex-clean-entry' on @Preamble entries.
(defun bibtex-url (&optional event)
"Browse a URL for the BibTeX entry at position PNT.
The URL is generated using the schemes defined in `bibtex-generate-url-list'
-\(see there\). Then the URL is passed to `browse-url'."
+\(see there\). Then the URL is passed to `browse-url'."
(interactive (list last-input-event))
(save-excursion
(if event (posn-set-point (event-end event)))
(lst bibtex-generate-url-list)
field url scheme)
(while (setq scheme (car lst))
- (when (and (setq field (assoc-string (caar scheme) fields-alist t))
- (or (eq t (cdar scheme))
- (string-match (cdar scheme) (cdr field))))
- (setq lst nil)
+ (when (and (setq field (cdr (assoc-string (caar scheme)
+ fields-alist t)))
+ (progn
+ (if (string-match "\\`[{\"]\\(.*\\)[}\"]\\'" field)
+ (setq field (match-string 1 field)))
+ (string-match (cdar scheme) field)))
+ (setq lst nil)
+ (if (null (cdr scheme))
+ (setq url (match-string 0 field)))
(dolist (step (cdr scheme))
- (cond ((stringp step)
- (setq url (concat url step)))
- ((setq field (assoc-string (car step) fields-alist t))
- ;; always remove field delimiters
- (let* ((text (if (string-match "\\`[{\"]\\(.*\\)[}\"]\\'"
- (cdr field))
- (match-string 1 (cdr field))
- (cdr field)))
- (str (cond ((eq t (nth 1 step))
- text)
- ((and (consp (nth 1 step))
- (string-match (car (nth 1 step))
- text))
- (if (numberp (cdr (nth 1 step)))
- (match-string (cdr (nth 1 step))
- text)
- (replace-match (cdr (nth 1 step))
- nil nil text)))
- ;; If the scheme is set up correctly,
- ;; we should never reach this point
- (t (error "Match failed: %s" text)))))
- (setq url (concat url (if (fboundp (nth 2 step))
- (funcall (nth 2 step) str)
- str)))))
- ;; If the scheme is set up correctly,
- ;; we should never reach this point
- (t (error "Step failed: %s" step))))
- (message "%s" url)
+ (cond ((stringp step)
+ (setq url (concat url step)))
+ ((setq field (assoc-string (car step) fields-alist t))
+ ;; always remove field delimiters
+ (let* ((text (if (string-match "\\`[{\"]\\(.*\\)[}\"]\\'"
+ (cdr field))
+ (match-string 1 (cdr field))
+ (cdr field)))
+ (str (if (string-match (nth 1 step) text)
+ (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) nil nil text)))
+ ;; If the scheme is set up correctly,
+ ;; we should never reach this point
+ (error "Match failed: %s" text))))
+ (setq url (concat url str))))
+ ;; If the scheme is set up correctly,
+ ;; we should never reach this point
+ (t (error "Step failed: %s" step))))
+ (message "%s" url)
(browse-url url))
(setq lst (cdr lst)))
(unless url (message "No URL known.")))))
(let ((case-fold-search t)
(bounds (bibtex-enclosing-field t))
(pnt (point))
- found url)
+ found field)
;; We use start-of-field as syntax-begin
(goto-char (if bounds (bibtex-start-of-field bounds) pnt))
(while (and (not found)
- (search-forward-regexp bibtex-font-lock-url-regexp bound t)
- (save-match-data (setq bounds (bibtex-parse-field-text)))
- (>= bound (car bounds)))
- (let ((field (match-string-no-properties 1))
- (lst bibtex-generate-url-list))
- (while (and (not found)
- (setq url (caar lst)))
- (when (bibtex-string= field (car url))
- (if (eq t (cdr url))
- (progn
- (goto-char (min bound (cdr bounds)))
- (set-match-data (list (car bounds) (point)))
- (setq found t))
- (goto-char (car bounds))
- (setq found (search-forward-regexp (cdr url)
- (min bound (cdr bounds)) t)))
- (if (< (match-beginning 0) pnt)
- (setq found nil)))
- (setq lst (cdr lst)))))
+ (prog1 (re-search-forward bibtex-font-lock-url-regexp bound t)
+ (setq field (match-string-no-properties 1)))
+ (setq bounds (bibtex-parse-field-text))
+ (>= bound (car bounds))
+ (>= (car bounds) pnt))
+ (let ((lst bibtex-generate-url-list) url)
+ (goto-char (car bounds))
+ (while (and (not found)
+ (setq url (caar lst)))
+ (when (bibtex-string= field (car url))
+ (setq found (re-search-forward (cdr url) (cdr bounds) t)))
+ (setq lst (cdr lst))))
+ (goto-char (cdr bounds)))
found))
\f