From c3f7862c6855ca628eef0067b65158bf845eca32 Mon Sep 17 00:00:00 2001 From: Don Armstrong Date: Tue, 24 Apr 2007 07:06:17 +0000 Subject: [PATCH] remove bibtex.el --- emacs_el/bibtex.el | 4073 -------------------------------------------- emacs_el/fixme.el | 3 +- 2 files changed, 2 insertions(+), 4074 deletions(-) delete mode 100644 emacs_el/bibtex.el diff --git a/emacs_el/bibtex.el b/emacs_el/bibtex.el deleted file mode 100644 index fd50e01..0000000 --- a/emacs_el/bibtex.el +++ /dev/null @@ -1,4073 +0,0 @@ -;;; bibtex.el --- BibTeX mode for GNU Emacs - -;; Copyright (C) 1992, 1994, 1995, 1996, 1997, 1998, 1999 Free Software Foundation, Inc. - -;; Author: Stefan Schoef -;; Bengt Martensson -;; Mark Shapiro -;; Mike Newton -;; Aaron Larson -;; Maintainer: none -;; Keywords: BibTeX, LaTeX, TeX - -;; This file is part of GNU Emacs. - -;; GNU Emacs is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU Emacs is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;; Commentary: - -;; Major mode for editing and validating BibTeX files. - -;; Usage: -;; See documentation for function bibtex-mode (or type "\M-x describe-mode" -;; when you are in BibTeX mode). - -;; Todo: -;; Distribute texinfo file. - -;;; Code: - -(eval-when-compile - (require 'compile)) - - -;; Bug Reporting - -(defconst - bibtex-maintainer-address "Dirk Herrmann ") -;; current maintainer - -(defconst - bibtex-maintainer-salutation "Hallo Dirk,") -;; current maintainer - -(defconst - bibtex-version "(emacs 20.4)") -;; current version of the bibtex.el file - - -;; User Options: - -(defgroup bibtex nil - "BibTeX mode." - :group 'tex - :prefix "bibtex-") - -(defgroup bibtex-autokey nil - "Generates automatically a key from the author/editor and the title field" - :group 'bibtex - :prefix "bibtex-autokey-") - -(defcustom bibtex-mode-hook nil - "List of functions to call on entry to BibTeX mode." - :group 'bibtex - :type 'hook) - -(defcustom bibtex-field-delimiters 'braces - "*Controls type of field delimiters used. -Set this to `braces' or `double-quotes' according to your personal -preferences. This variable is buffer-local." - :group 'bibtex - :type '(choice (const braces) - (const double-quotes))) -(make-variable-buffer-local 'bibtex-field-delimiters) - -(defcustom bibtex-entry-delimiters 'braces - "*Controls type of entry delimiters used. -Set this to `braces' or `parentheses' according to your personal -preferences. This variable is buffer-local." - :group 'bibtex - :type '(choice (const braces) - (const parentheses))) -(make-variable-buffer-local 'bibtex-entry-delimiters) - -(defcustom bibtex-include-OPTcrossref '("InProceedings" "InCollection") - "*All entries listed here will have an OPTcrossref field." - :group 'bibtex - :type '(repeat string)) - -(defcustom bibtex-include-OPTkey t - "*If non-nil, all entries will have an OPTkey field. -If this is a string, it will be used as the initial field text. -If this is a function, it will be called to generate the initial field text." - :group 'bibtex - :type '(choice (const :tag "None" nil) - (string :tag "Initial text") - (function :tag "Initialize Function" :value fun) - (other :tag "Default" t))) - -(defcustom bibtex-user-optional-fields - '(("annote" "Personal annotation (ignored)")) - "*List of optional fields the user wants to have always present. -Entries should be of the same form as the OPTIONAL and -CROSSREF-OPTIONAL lists in `bibtex-entry-field-alist' (see documentation -of this variable for details)." - :group 'bibtex - :type '(repeat - (group (string :tag "Field") - (string :tag "Comment") - (option (group :inline t - :extra-offset -4 - (choice :tag "Init" :value "" - string - function)))))) - -(defcustom bibtex-entry-format '(opts-or-alts numerical-fields) - "*Controls type of formatting performed by `bibtex-clean-entry'. -It may be t, nil, or a list of symbols out of the following: -opts-or-alts Delete empty optional and alternative fields and - remove OPT and ALT prefixes from used fields. -numerical-fields Delete delimiters around numeral fields. -page-dashes Change double dashes in page field to single dash - (for scribe compatibility). -inherit-booktitle If entry contains a crossref field and booktitle - field is empty, it is set to the contents of the - title field of the crossreferenced entry. - Caution: this will work only if buffer is - correctly sorted. -realign Realign entries, so that field texts and perhaps equal - signs (depending on the value of - `bibtex-align-at-equal-sign') begin in the same column. -last-comma Add or delete comma on end of last field in entry, - according to value of `bibtex-comma-after-last-field'. -delimiters Change delimiters according to variables - `bibtex-field-delimiters' and `bibtex-entry-delimiters'. -unify-case Change case of entry and field names. - -The value t means do all of the above formatting actions. -The value nil means do no formatting at all." - :group 'bibtex - :type '(choice (const :tag "None" nil) - (const :tag "All" t) - (set :menu-tag "Some" - (const opts-or-alts) - (const numerical-fields) - (const page-dashes) - (const inherit-booktitle) - (const realign) - (const last-comma) - (const delimiters) - (const unify-case)))) - -(defcustom bibtex-clean-entry-hook nil - "*List of functions to call when entry has been cleaned. -Functions are called with point inside the cleaned entry, and the buffer -narrowed to just the entry." - :group 'bibtex - :type 'hook) - -(defcustom bibtex-sort-ignore-string-entries t - "*If non-nil, BibTeX @String entries are not sort-significant. -That means they are ignored when determining ordering of the buffer -(e.g., sorting, locating alphabetical position for new entries, etc.). -This variable is buffer-local." - :group 'bibtex - :type 'boolean) -(make-variable-buffer-local 'bibtex-sort-ignore-string-entries) - -(defcustom bibtex-maintain-sorted-entries nil - "*If non-nil, BibTeX mode maintains all BibTeX entries in sorted order. -Setting this variable to nil will strip off some comfort (e.g., TAB -completion for reference keys in minibuffer, automatic detection of -duplicates) from BibTeX mode. See also `bibtex-sort-ignore-string-entries'. -This variable is buffer-local." - :group 'bibtex - :type 'boolean) -(make-variable-buffer-local 'bibtex-maintain-sorted-entries) - -(defcustom bibtex-field-kill-ring-max 20 - "*Max length of `bibtex-field-kill-ring' before discarding oldest elements." - :group 'bibtex - :type 'integer) - -(defcustom bibtex-entry-kill-ring-max 20 - "*Max length of `bibtex-entry-kill-ring' before discarding oldest elements." - :group 'bibtex - :type 'integer) - -(defcustom bibtex-parse-keys-timeout 60 - "*Specifies interval for parsing buffers. -All BibTeX buffers in Emacs are parsed if Emacs has been idle -`bibtex-parse-keys-timeout' seconds. Only buffers which were modified -after last parsing and which are maintained in sorted order are parsed." - :group 'bibtex - :type 'integer) - -(defvar bibtex-entry-field-alist - '( - ("Article" . (((("author" "Author1 [and Author2 ...] [and others]") - ("title" "Title of the article (BibTeX converts it to lowercase)") - ("journal" "Name of the journal (use string, remove braces)") - ("year" "Year of publication")) - (("volume" "Volume of the journal") - ("number" "Number of the journal (only allowed if entry contains volume)") - ("pages" "Pages in the journal") - ("month" "Month of the publication as a string (remove braces)") - ("note" "Remarks to be put at the end of the \\bibitem") - ("abstract" "Abstract of the publication"))) - ((("author" "Author1 [and Author2 ...] [and others]") - ("title" "Title of the article (BibTeX converts it to lowercase)")) - (("pages" "Pages in the journal") - ("journal" "Name of the journal (use string, remove braces)") - ("year" "Year of publication") - ("volume" "Volume of the journal") - ("number" "Number of the journal") - ("month" "Month of the publication as a string (remove braces)") - ("note" "Remarks to be put at the end of the \\bibitem") - ("abstract" "Abstract of the publication"))))) - ("Book" . (((("author" "Author1 [and Author2 ...] [and others]" "" t) - ("editor" "Editor1 [and Editor2 ...] [and others]" "" t) - ("title" "Title of the book") - ("publisher" "Publishing company") - ("year" "Year of publication")) - (("volume" "Volume of the book in the series") - ("number" "Number of the book in a small series (overwritten by volume)") - ("series" "Series in which the book appeared") - ("address" "Address of the publisher") - ("edition" "Edition of the book as a capitalized English word") - ("month" "Month of the publication as a string (remove braces)") - ("note" "Remarks to be put at the end of the \\bibitem"))) - ((("author" "Author1 [and Author2 ...] [and others]" "" t) - ("editor" "Editor1 [and Editor2 ...] [and others]" "" t) - ("title" "Title of the book")) - (("publisher" "Publishing company") - ("year" "Year of publication") - ("volume" "Volume of the book in the series") - ("number" "Number of the book in a small series (overwritten by volume)") - ("series" "Series in which the book appeared") - ("address" "Address of the publisher") - ("edition" "Edition of the book as a capitalized English word") - ("month" "Month of the publication as a string (remove braces)") - ("note" "Remarks to be put at the end of the \\bibitem"))))) - ("Booklet" . (((("title" "Title of the booklet (BibTeX converts it to lowercase)")) - (("author" "Author1 [and Author2 ...] [and others]") - ("howpublished" "The way in which the booklet was published") - ("address" "Address of the publisher") - ("month" "Month of the publication as a string (remove braces)") - ("year" "Year of publication") - ("note" "Remarks to be put at the end of the \\bibitem"))))) - ("InBook" . (((("author" "Author1 [and Author2 ...] [and others]" "" t) - ("editor" "Editor1 [and Editor2 ...] [and others]" "" t) - ("title" "Title of the book") - ("chapter" "Chapter in the book") - ("publisher" "Publishing company") - ("year" "Year of publication")) - (("volume" "Volume of the book in the series") - ("number" "Number of the book in a small series (overwritten by volume)") - ("series" "Series in which the book appeared") - ("type" "Word to use instead of \"chapter\"") - ("address" "Address of the publisher") - ("edition" "Edition of the book as a capitalized English word") - ("month" "Month of the publication as a string (remove braces)") - ("pages" "Pages in the book") - ("note" "Remarks to be put at the end of the \\bibitem"))) - ((("author" "Author1 [and Author2 ...] [and others]" "" t) - ("editor" "Editor1 [and Editor2 ...] [and others]" "" t) - ("title" "Title of the book") - ("chapter" "Chapter in the book")) - (("pages" "Pages in the book") - ("publisher" "Publishing company") - ("year" "Year of publication") - ("volume" "Volume of the book in the series") - ("number" "Number of the book in a small series (overwritten by volume)") - ("series" "Series in which the book appeared") - ("type" "Word to use instead of \"chapter\"") - ("address" "Address of the publisher") - ("edition" "Edition of the book as a capitalized English word") - ("month" "Month of the publication as a string (remove braces)") - ("note" "Remarks to be put at the end of the \\bibitem"))))) - ("InCollection" . (((("author" "Author1 [and Author2 ...] [and others]") - ("title" "Title of the article in book (BibTeX converts it to lowercase)") - ("booktitle" "Name of the book") - ("publisher" "Publishing company") - ("year" "Year of publication")) - (("editor" "Editor1 [and Editor2 ...] [and others]") - ("volume" "Volume of the book in the series") - ("number" "Number of the book in a small series (overwritten by volume)") - ("series" "Series in which the book appeared") - ("type" "Word to use instead of \"chapter\"") - ("chapter" "Chapter in the book") - ("pages" "Pages in the book") - ("address" "Address of the publisher") - ("edition" "Edition of the book as a capitalized English word") - ("month" "Month of the publication as a string (remove braces)") - ("note" "Remarks to be put at the end of the \\bibitem"))) - ((("author" "Author1 [and Author2 ...] [and others]") - ("title" "Title of the article in book (BibTeX converts it to lowercase)") - ("booktitle" "Name of the book")) - (("pages" "Pages in the book") - ("publisher" "Publishing company") - ("year" "Year of publication") - ("editor" "Editor1 [and Editor2 ...] [and others]") - ("volume" "Volume of the book in the series") - ("number" "Number of the book in a small series (overwritten by volume)") - ("series" "Series in which the book appeared") - ("type" "Word to use instead of \"chapter\"") - ("chapter" "Chapter in the book") - ("address" "Address of the publisher") - ("edition" "Edition of the book as a capitalized English word") - ("month" "Month of the publication as a string (remove braces)") - ("note" "Remarks to be put at the end of the \\bibitem"))))) - ("InProceedings" . (((("author" "Author1 [and Author2 ...] [and others]") - ("title" "Title of the article in proceedings (BibTeX converts it to lowercase)") - ("booktitle" "Name of the conference proceedings") - ("year" "Year of publication")) - (("editor" "Editor1 [and Editor2 ...] [and others]") - ("volume" "Volume of the conference proceedings in the series") - ("number" "Number of the conference proceedings in a small series (overwritten by volume)") - ("series" "Series in which the conference proceedings appeared") - ("pages" "Pages in the conference proceedings") - ("address" "Location of the Proceedings") - ("month" "Month of the publication as a string (remove braces)") - ("organization" "Sponsoring organization of the conference") - ("publisher" "Publishing company, its location") - ("note" "Remarks to be put at the end of the \\bibitem"))) - ((("author" "Author1 [and Author2 ...] [and others]") - ("title" "Title of the article in proceedings (BibTeX converts it to lowercase)")) - (("booktitle" "Name of the conference proceedings") - ("pages" "Pages in the conference proceedings") - ("year" "Year of publication") - ("editor" "Editor1 [and Editor2 ...] [and others]") - ("volume" "Volume of the conference proceedings in the series") - ("number" "Number of the conference proceedings in a small series (overwritten by volume)") - ("series" "Series in which the conference proceedings appeared") - ("address" "Location of the Proceedings") - ("month" "Month of the publication as a string (remove braces)") - ("organization" "Sponsoring organization of the conference") - ("publisher" "Publishing company, its location") - ("note" "Remarks to be put at the end of the \\bibitem"))))) - ("Manual" . (((("title" "Title of the manual")) - (("author" "Author1 [and Author2 ...] [and others]") - ("organization" "Publishing organization of the manual") - ("address" "Address of the organization") - ("edition" "Edition of the manual as a capitalized English word") - ("month" "Month of the publication as a string (remove braces)") - ("year" "Year of publication") - ("note" "Remarks to be put at the end of the \\bibitem"))))) - ("MastersThesis" . (((("author" "Author1 [and Author2 ...] [and others]") - ("title" "Title of the master\'s thesis (BibTeX converts it to lowercase)") - ("school" "School where the master\'s thesis was written") - ("year" "Year of publication")) - (("type" "Type of the master\'s thesis (if other than \"Master\'s thesis\")") - ("address" "Address of the school (if not part of field \"school\") or country") - ("month" "Month of the publication as a string (remove braces)") - ("note" "Remarks to be put at the end of the \\bibitem"))))) - ("Misc" . ((() - (("author" "Author1 [and Author2 ...] [and others]") - ("title" "Title of the work (BibTeX converts it to lowercase)") - ("howpublished" "The way in which the work was published") - ("month" "Month of the publication as a string (remove braces)") - ("year" "Year of publication") - ("note" "Remarks to be put at the end of the \\bibitem"))))) - ("PhdThesis" . (((("author" "Author1 [and Author2 ...] [and others]") - ("title" "Title of the PhD. thesis") - ("school" "School where the PhD. thesis was written") - ("year" "Year of publication")) - (("type" "Type of the PhD. thesis") - ("address" "Address of the school (if not part of field \"school\") or country") - ("month" "Month of the publication as a string (remove braces)") - ("note" "Remarks to be put at the end of the \\bibitem"))))) - ("Proceedings" . (((("title" "Title of the conference proceedings") - ("year" "Year of publication")) - (("booktitle" "Title of the proceedings for cross references") - ("editor" "Editor1 [and Editor2 ...] [and others]") - ("volume" "Volume of the conference proceedings in the series") - ("number" "Number of the conference proceedings in a small series (overwritten by volume)") - ("series" "Series in which the conference proceedings appeared") - ("address" "Location of the Proceedings") - ("month" "Month of the publication as a string (remove braces)") - ("organization" "Sponsoring organization of the conference") - ("publisher" "Publishing company, its location") - ("note" "Remarks to be put at the end of the \\bibitem"))))) - ("TechReport" . (((("author" "Author1 [and Author2 ...] [and others]") - ("title" "Title of the technical report (BibTeX converts it to lowercase)") - ("institution" "Sponsoring institution of the report") - ("year" "Year of publication")) - (("type" "Type of the report (if other than \"technical report\")") - ("number" "Number of the technical report") - ("address" "Address of the institution (if not part of field \"institution\") or country") - ("month" "Month of the publication as a string (remove braces)") - ("note" "Remarks to be put at the end of the \\bibitem"))))) - ("Unpublished" . (((("author" "Author1 [and Author2 ...] [and others]") - ("title" "Title of the unpublished work (BibTeX converts it to lowercase)") - ("note" "Remarks to be put at the end of the \\bibitem")) - (("month" "Month of the publication as a string (remove braces)") - ("year" "Year of publication"))))) - ) - - "Defines entry types and their associated fields. -List of -(ENTRY-NAME (REQUIRED OPTIONAL) (CROSSREF-REQUIRED CROSSREF-OPTIONAL)) -triples. -If the third element is nil, the first pair is always used. -If not, the second pair is used in the case of presence of a crossref -field and the third in the case of absence. -REQUIRED, OPTIONAL, CROSSREF-REQUIRED and CROSSREF-OPTIONAL are lists. -Each element of these lists is a list of the form -(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG). -COMMENT-STRING, INIT, and ALTERNATIVE-FLAG are optional. -FIELD-NAME is the name of the field, COMMENT-STRING the comment to -appear in the echo area, INIT is either the initial content of the -field or a function, which is called to determine the initial content -of the field, and ALTERNATIVE-FLAG (either nil or t) marks if the -field is an alternative. ALTERNATIVE-FLAG may be t only in the -REQUIRED or CROSSREF-REQUIRED lists.") - -(defvar bibtex-comment-start "@Comment ") - -(defcustom bibtex-add-entry-hook nil - "List of functions to call when entry has been inserted." - :group 'bibtex - :type 'hook) - -(defcustom bibtex-predefined-month-strings - '( - ("jan") ("feb") ("mar") ("apr") ("may") ("jun") - ("jul") ("aug") ("sep") ("oct") ("nov") ("dec") - ) - "Alist of month string definitions. -Should contain all strings used for months in the BibTeX style files. -Each element is a list with just one element: the string." - :group 'bibtex - :type '(repeat - (list string))) - -(defcustom bibtex-predefined-strings - (append - bibtex-predefined-month-strings - '( - ("acmcs") ("acta") ("cacm") ("ibmjrd") ("ibmsj") ("ieeese") - ("ieeetc") ("ieeetcad") ("ipl") ("jacm") ("jcss") ("scp") - ("sicomp") ("tcs") ("tocs") ("tods") ("tog") ("toms") ("toois") - ("toplas") - )) - "Alist of string definitions. -Should contain the strings defined in the BibTeX style files. Each -element is a list with just one element: the string." - :group 'bibtex - :type '(repeat - (list string))) - -(defcustom bibtex-string-files nil - "*List of BibTeX files containing string definitions. -Those files must be specified using pathnames relative to the -directories specified in `bibtex-string-file-path'. This variable is only -evaluated when BibTeX mode is entered (i.e., when loading the BibTeX -file)." - :group 'bibtex - :type '(repeat file)) - -(defvar bibtex-string-file-path (getenv "BIBINPUTS") - "*Colon separated list of paths to search for `bibtex-string-files'.") - -(defcustom bibtex-help-message t - "*If not nil print help messages in the echo area on entering a new field." - :group 'bibtex - :type 'boolean) - -(defcustom bibtex-autokey-prefix-string "" - "*String to use as a prefix for all generated keys. -See the documentation of function `bibtex-generate-autokey' for more detail." - :group 'bibtex-autokey - :type 'string) - -(defcustom bibtex-autokey-names 1 - "*Number of names to use for the automatically generated reference key. -If this is variable is nil, all names are used. -Possibly more names are used according to `bibtex-autokey-names-stretch'. -See the documentation of function `bibtex-generate-autokey' for more detail." - :group 'bibtex-autokey - :type '(choice (const :tag "All" infty) - integer)) - -(defcustom bibtex-autokey-names-stretch 0 - "*Number of names that can additionally be used. -These names are used only, if all names are used then. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type 'integer) - -(defcustom bibtex-autokey-additional-names "" - "*String to prepend to the generated key if not all names could be used. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type 'string) - -(defvar bibtex-autokey-transcriptions - '( - ;; language specific characters - ("\\\\aa" "a") - ("\\\\AA" "A") - ("\\\"a\\|\\\\\\\"a\\|\\\\ae" "ae") - ("\\\"A\\|\\\\\\\"A\\|\\\\AE" "Ae") - ("\\\\i" "i") - ("\\\\j" "j") - ("\\\\l" "l") - ("\\\\L" "L") - ("\\\"o\\|\\\\\\\"o\\|\\\\o\\|\\\\oe" "oe") - ("\\\"O\\|\\\\\\\"O\\|\\\\O\\|\\\\OE" "Oe") - ("\\\"s\\|\\\\\\\"s" "ss") - ("\\\"u\\|\\\\\\\"u" "ue") - ("\\\"U\\|\\\\\\\"U" "Ue") - ;; accents - ("\\\\`\\|\\\\'\\|\\\\\\^\\|\\\\~\\|\\\\=\\|\\\\\\.\\|\\\\u\\|\\\\v\\|\\\\H\\|\\\\t\\|\\\\c\\|\\\\d\\|\\\\b" "") - ;; braces - ("{" "") ("}" "")) - "Alist of (old-regexp new-string) pairs. -Used by the default values of `bibtex-autokey-name-change-strings' and -`bibtex-autokey-titleword-change-strings'. Defaults to translating some -language specific characters to their ASCII transcriptions, and -removing any character accents.") - -(defcustom bibtex-autokey-name-change-strings - bibtex-autokey-transcriptions - "Alist of (OLD-REGEXP NEW-STRING) pairs. -Any part of name matching a OLD-REGEXP is replaced by NEW-STRING. -Case is significant in OLD-REGEXP. All regexps are tried in the -order in which they appear in the list, so be sure to avoid inifinite -loops here. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type '(repeat - (list (regexp :tag "Old") - (string :tag "New")))) - -(defcustom bibtex-autokey-name-case-convert 'downcase - "*Function called for each name to perform case conversion. -See the documentation of function `bibtex-generate-autokey' for more detail." - :group 'bibtex-autokey - :type '(choice (const :tag "Preserve case" identity) - (const :tag "Downcase" downcase) - (const :tag "Capitalize" capitalize) - (const :tag "Upcase" upcase) - (function :tag "Conversion function"))) - -(defcustom bibtex-autokey-name-length 'infty - "*Number of characters from name to incorporate into key. -If this is set to anything but a number, all characters are used. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type '(choice (const :tag "All" infty) - integer)) - -(defcustom bibtex-autokey-name-separator "" - "*String that comes between any two names in the key. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type 'string) - -(defcustom bibtex-autokey-year-length 2 - "*Number of rightmost digits from the year field to incorporate into key. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type 'integer) - -(defcustom bibtex-autokey-year-use-crossref-entry t - "*If non-nil use year field from crossreferenced entry if necessary. -If this variable is non-nil and the current entry has no year, but a -valid crossref entry, the year field from the crossreferenced entry is -used. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type 'boolean) - -(defcustom bibtex-autokey-titlewords 5 - "*Number of title words to use for the automatically generated reference key. -If this is set to anything but a number, all title words are used. -Possibly more words from the title are used according to -`bibtex-autokey-titlewords-stretch'. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type '(choice (const :tag "All" infty) - integer)) - -(defcustom bibtex-autokey-title-terminators - '("\\." "!" "\\?" ":" ";" "--") - "*Regexp list defining the termination of the main part of the title. -Case of the regexps is ignored. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type '(repeat regexp)) - -(defcustom bibtex-autokey-titlewords-stretch 2 - "*Number of words that can additionally be used from the title. -These words are used only, if a sentence from the title can be ended then. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type 'integer) - -(defcustom bibtex-autokey-titleword-ignore - '("A" "An" "On" "The" "Eine?" "Der" "Die" "Das" - "[^A-Z].*" ".*[^a-zA-Z0-9].*") - "*Determines words from the title that are not to be used in the key. -Each item of the list is a regexp. If a word of the title matchs a -regexp from that list, it is not included in the title part of the key. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type '(repeat regexp)) - -(defcustom bibtex-autokey-titleword-case-convert 'downcase - "*Function called for each titleword to perform case conversion. -See the documentation of function `bibtex-generate-autokey' for more detail." - :group 'bibtex-autokey - :type '(choice (const :tag "Preserve case" identity) - (const :tag "Downcase" downcase) - (const :tag "Capitalize" capitalize) - (const :tag "Upcase" upcase) - (function :tag "Conversion function"))) - -(defcustom bibtex-autokey-titleword-abbrevs nil - "*Determines exceptions to the usual abbreviation mechanism. -An alist of (OLD-REGEXP NEW-STRING) pairs. Case is ignored -in matching against OLD-REGEXP, and the first matching pair is used. -See the documentation of function `bibtex-generate-autokey' for details.") - -(defcustom bibtex-autokey-titleword-change-strings - bibtex-autokey-transcriptions - "Alist of (OLD-REGEXP NEW-STRING) pairs. -Any part of title word matching a OLD-REGEXP is replaced by NEW-STRING. -Case is significant in OLD-REGEXP. All regexps are tried in the -order in which they appear in the list, so be sure to avoid inifinite -loops here. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type '(repeat - (list (regexp :tag "Old") - (string :tag "New")))) - -(defcustom bibtex-autokey-titleword-length 5 - "*Number of characters from title words to incorporate into key. -If this is set to anything but a number, all characters are used. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type '(choice (const :tag "All" infty) - integer)) - -(defcustom bibtex-autokey-titleword-separator "_" - "*String to be put between the title words. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type 'string) - -(defcustom bibtex-autokey-name-year-separator "" - "*String to be put between name part and year part of key. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type 'string) - -(defcustom bibtex-autokey-year-title-separator ":_" - "*String to be put between name part and year part of key. -See the documentation of function `bibtex-generate-autokey' for details." - :group 'bibtex-autokey - :type 'string) - -(defcustom bibtex-autokey-edit-before-use t - "*If non-nil, user is allowed to edit the generated key before it is used." - :group 'bibtex-autokey - :type 'boolean) - -(defcustom bibtex-autokey-before-presentation-function nil - "Function to call before the generated key is presented. -If non-nil this should be a single function, which is called before -the generated key is presented (in entry or, if -`bibtex-autokey-edit-before-use' is t, in minibuffer). This function -must take one argument (the automatically generated key), and must -return with a string (the key to use)." - :group 'bibtex-autokey - :type '(choice (const nil) function)) - -(defcustom bibtex-entry-offset 0 - "*Offset for BibTeX entries. -Added to the value of all other variables which determine colums." - :group 'bibtex - :type 'integer) - -(defcustom bibtex-field-indentation 2 - "*Starting column for the name part in BibTeX fields." - :group 'bibtex - :type 'integer) - -(defcustom bibtex-text-indentation - (+ - bibtex-field-indentation - (length "organization = ")) - "*Starting column for the text part in BibTeX fields. -Should be equal to the space needed for the longest name part." - :group 'bibtex - :type 'integer) - -(defcustom bibtex-contline-indentation - (+ bibtex-text-indentation 1) - "*Starting column for continuation lines of BibTeX fields." - :group 'bibtex - :type 'integer) - -(defcustom bibtex-align-at-equal-sign nil - "*If non-nil, align fields at equal sign instead of field text. -If non-nil, the column for the equal sign is -the value of `bibtex-text-indentation', minus 2." - :group 'bibtex - :type 'boolean) - -(defcustom bibtex-comma-after-last-field nil - "*If non-nil, a comma is put at end of last field in the entry template." - :group 'bibtex - :type 'boolean) - -;; bibtex-font-lock-keywords is a user option as well, but since the -;; patterns used to define this variable are defined in a later -;; section of this file, it is defined later. - -;; Special support taking care of variants -(if (boundp 'mark-active) - (defun bibtex-mark-active () - ;; In Emacs mark-active indicates if mark is active. - mark-active) - (defun bibtex-mark-active () - ;; In XEmacs (mark) returns nil when not active. - (if zmacs-regions (mark) (mark t)))) - -(if (fboundp 'run-with-idle-timer) - ;; timer.el is distributed with Emacs - (fset 'bibtex-run-with-idle-timer 'run-with-idle-timer) - ;; timer.el is not distributed with XEmacs - ;; Notice that this does not (yet) pass the arguments, but they - ;; are not used (yet) in bibtex.el. Fix if needed. - (defun bibtex-run-with-idle-timer (secs repeat function &rest args) - (start-itimer "bibtex" function secs (if repeat secs nil) t))) - - -;; 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)))) - -(add-to-list - 'hs-special-modes-alist - '(bibtex-mode "@\\S(*\\s(" "\\s)" nil bibtex-hs-forward-sexp nil)) - - -;; Syntax Table, Keybindings and BibTeX Entry List -(defvar bibtex-mode-syntax-table - (let ((st (make-syntax-table))) - (modify-syntax-entry ?\" "\"" st) - (modify-syntax-entry ?$ "$$ " st) - (modify-syntax-entry ?% "< " st) - (modify-syntax-entry ?' "w " st) - (modify-syntax-entry ?@ "w " st) - (modify-syntax-entry ?\\ "\\" st) - (modify-syntax-entry ?\f "> " st) - (modify-syntax-entry ?\n "> " st) - (modify-syntax-entry ?~ " " st) - st)) - -(defvar bibtex-mode-map - (let ((km (make-sparse-keymap))) - ;; The Key `C-c&' is reserved for reftex.el - (define-key km "\t" 'bibtex-find-text) - (define-key km "\n" 'bibtex-next-field) - (define-key km "\M-\t" 'bibtex-complete-string) - (define-key km [(meta tab)] 'bibtex-complete-key) - (define-key km "\C-c\"" 'bibtex-remove-delimiters) - (define-key km "\C-c{" 'bibtex-remove-delimiters) - (define-key km "\C-c}" 'bibtex-remove-delimiters) - (define-key km "\C-c\C-c" 'bibtex-clean-entry) - (define-key km "\C-c\C-q" 'bibtex-fill-entry) - (define-key km "\C-c?" 'bibtex-print-help-message) - (define-key km "\C-c\C-p" 'bibtex-pop-previous) - (define-key km "\C-c\C-n" 'bibtex-pop-next) - (define-key km "\C-c\C-k" 'bibtex-kill-field) - (define-key km "\C-c\M-k" 'bibtex-copy-field-as-kill) - (define-key km "\C-c\C-w" 'bibtex-kill-entry) - (define-key km "\C-c\M-w" 'bibtex-copy-entry-as-kill) - (define-key km "\C-c\C-y" 'bibtex-yank) - (define-key km "\C-c\M-y" 'bibtex-yank-pop) - (define-key km "\C-c\C-d" 'bibtex-empty-field) - (define-key km "\C-c\C-f" 'bibtex-make-field) - (define-key km "\C-c$" 'bibtex-ispell-abstract) - (define-key km "\M-\C-a" 'bibtex-beginning-of-entry) - (define-key km "\M-\C-e" 'bibtex-end-of-entry) - (define-key km "\C-\M-l" 'bibtex-reposition-window) - (define-key km "\C-\M-h" 'bibtex-mark-entry) - (define-key km "\C-c\C-b" 'bibtex-entry) - (define-key km "\C-c\C-rn" 'bibtex-narrow-to-entry) - (define-key km "\C-c\C-rw" 'widen) - (define-key km "\C-c\C-o" 'bibtex-remove-OPT-or-ALT) - (define-key km "\C-c\C-e\C-i" 'bibtex-InProceedings) - (define-key km "\C-c\C-ei" 'bibtex-InCollection) - (define-key km "\C-c\C-eI" 'bibtex-InBook) - (define-key km "\C-c\C-e\C-a" 'bibtex-Article) - (define-key km "\C-c\C-e\C-b" 'bibtex-InBook) - (define-key km "\C-c\C-eb" 'bibtex-Book) - (define-key km "\C-c\C-eB" 'bibtex-Booklet) - (define-key km "\C-c\C-e\C-c" 'bibtex-InCollection) - (define-key km "\C-c\C-e\C-m" 'bibtex-Manual) - (define-key km "\C-c\C-em" 'bibtex-MastersThesis) - (define-key km "\C-c\C-eM" 'bibtex-Misc) - (define-key km "\C-c\C-e\C-p" 'bibtex-InProceedings) - (define-key km "\C-c\C-ep" 'bibtex-Proceedings) - (define-key km "\C-c\C-eP" 'bibtex-PhdThesis) - (define-key km "\C-c\C-e\M-p" 'bibtex-Preamble) - (define-key km "\C-c\C-e\C-s" 'bibtex-String) - (define-key km "\C-c\C-e\C-t" 'bibtex-TechReport) - (define-key km "\C-c\C-e\C-u" 'bibtex-Unpublished) - km)) - -(easy-menu-define - bibtex-edit-menu bibtex-mode-map "BibTeX-Edit Menu in BibTeX mode" - '("BibTeX-Edit" - ("Moving inside an Entry" - ["End of Field" bibtex-find-text t] - ["Next Field" bibtex-next-field t] - ["Beginning of Entry" bibtex-beginning-of-entry t] - ["End of Entry" bibtex-end-of-entry t]) - ("Operating on Current Entry" - ["Fill Entry" bibtex-fill-entry t] - ["Clean Entry" bibtex-clean-entry t] - "--" - ["Kill Entry" bibtex-kill-entry t] - ["Copy Entry to Kill Ring" bibtex-copy-entry-as-kill t] - ["Paste Most Recently Killed Entry" bibtex-yank t] - ["Paste Previously Killed Entry" bibtex-yank-pop t] - "--" - ["Ispell Entry" bibtex-ispell-entry t] - ["Ispell Entry Abstract" bibtex-ispell-abstract t] - ["Narrow to Entry" bibtex-narrow-to-entry t] - "--" - ["View Cite Locations (RefTeX)" reftex-view-crossref-from-bibtex - (fboundp 'reftex-view-crossref-from-bibtex)]) - ("Operating on Current Field" - ["Remove Delimiters" bibtex-remove-delimiters t] - ["Remove OPT or ALT Prefix" bibtex-remove-OPT-or-ALT t] - ["Clear Field" bibtex-empty-field t] - "--" - ["Kill Field" bibtex-kill-field t] - ["Copy Field to Kill Ring" bibtex-copy-field-as-kill t] - ["Paste Most Recently Killed Field" bibtex-yank t] - ["Paste Previously Killed Field" bibtex-yank-pop t] - "--" - ["Make New Field" bibtex-make-field t] - "--" - ["Snatch from Similar Following Field" bibtex-pop-next t] - ["Snatch from Similar Preceding Field" bibtex-pop-previous t] - "--" - ["String Complete" bibtex-complete-string t] - ["Key Complete" bibtex-complete-key t] - "--" - ["Help about Current Field" bibtex-print-help-message t]) - ("Operating on Buffer or Region" - ["Validate Entries" bibtex-validate t] - ["Sort Entries" bibtex-sort-buffer t] - ["Reformat Entries" bibtex-reformat t] - ["Count Entries" bibtex-count-entries t]) - ("Miscellaneous" - ["Convert Alien Buffer" bibtex-convert-alien t] - ["Submit Bug Report" bibtex-submit-bug-report t]))) - -(easy-menu-define - bibtex-entry-menu bibtex-mode-map "Entry-Types Menu in BibTeX mode" - (list "Entry-Types" - ["Article in Journal" bibtex-Article t] - ["Article in Conference Proceedings" bibtex-InProceedings t] - ["Article in a Collection" bibtex-InCollection t] - ["Chapter or Pages in a Book" bibtex-InBook t] - ["Conference Proceedings" bibtex-Proceedings t] - ["Book" bibtex-Book t] - ["Booklet (Bound, but no Publisher/Institution)" bibtex-Booklet t] - ["PhD. Thesis" bibtex-PhdThesis t] - ["Master's Thesis" bibtex-MastersThesis t] - ["Technical Report" bibtex-TechReport t] - ["Technical Manual" bibtex-Manual t] - ["Unpublished" bibtex-Unpublished t] - ["Miscellaneous" bibtex-Misc t] - ["String" bibtex-String t] - ["Preamble" bibtex-Preamble t])) - - -;; Internal Variables - -(defvar bibtex-pop-previous-search-point nil) -;; Next point where bibtex-pop-previous starts looking for a similar -;; entry. - -(defvar bibtex-pop-next-search-point nil) -;; Next point where bibtex-pop-next starts looking for a similar entry. - -(defvar bibtex-field-kill-ring nil) -;; Ring of least recently killed fields. At most -;; bibtex-field-kill-ring-max items are kept here. - -(defvar bibtex-field-kill-ring-yank-pointer nil) -;; The tail of bibtex-field-kill-ring whose car is the last item yanked. - -(defvar bibtex-entry-kill-ring nil) -;; Ring of least recently killed entries. At most -;; bibtex-entry-kill-ring-max items are kept here. - -(defvar bibtex-entry-kill-ring-yank-pointer nil) -;; The tail of bibtex-entry-kill-ring whose car is the last item yanked. - -(defvar bibtex-last-kill-command nil) -;; Holds the type of the last kill command (either 'field or 'entry) - -(defvar bibtex-strings nil) -;; Candidates for bibtex-complete-string. Initialized from -;; bibtex-predefined-strings and bibtex-string-files. -(make-variable-buffer-local 'bibtex-strings) - -(defvar bibtex-reference-keys nil) -;; Candidates for TAB completion when entering a reference key using -;; the minibuffer. Also used for bibtex-complete-key. Initialized in -;; bibtex-mode and updated for each new entry. -(make-variable-buffer-local 'bibtex-reference-keys) - -(defvar bibtex-buffer-last-parsed-tick nil) -;; Remembers the value returned by buffer-modified-tick when buffer -;; was parsed for keys the last time. -(make-variable-buffer-local 'bibtex-buffer-last-parsed-tick) - -(defvar bibtex-parse-idle-timer nil) -;; Stores if timer is already installed - -(defvar bibtex-progress-lastperc nil) -;; Holds the last reported percentage for the progress message - -(defvar bibtex-progress-lastmes nil) -;; Holds the last reported progress message - -(defvar bibtex-progress-interval nil) -;; Holds the chosen interval - -(defvar bibtex-key-history nil) -;; Used to store the history list for reading keys - -(defvar bibtex-entry-type-history nil) -;; Used to store the history list for reading entry types - -(defvar bibtex-field-history nil) -;; Used to store the history list for reading field names - -(defvar bibtex-reformat-previous-options nil) -;; Used to store the last reformat options given - -(defvar bibtex-reformat-previous-reference-keys nil) -;; Used to store the last reformat reference keys option given - - -;; Functions to Parse the BibTeX Entries - -(defconst bibtex-field-name "[^\"#%'(),={} \t\n0-9][^\"#%'(),={} \t\n]*") -;; Regexp defining the name part of a BibTeX field. - -(defconst bibtex-entry-type (concat "@" bibtex-field-name)) -;; Regexp defining the type part of a BibTeX entry. - -(defconst bibtex-reference-key "[][a-zA-Z0-9.:;?!`'/*@+=|()<>&_^$-]+") -;; Regexp defining the reference key part of a BibTeX entry - -(defun bibtex-parse-nested-braces (nesting-level) - "*Starting on an opening brace, find the corresponding closing brace. -When the function is called, NESTING-LEVEL has to be set to `0'." - (cond ((looking-at "{") - (search-forward-regexp "{[^{}]*") - (bibtex-parse-nested-braces (+ nesting-level 1))) - ((looking-at "}") - (forward-char 1) - (if (= nesting-level 1) - (point) - (search-forward-regexp "[^{}]*") - (bibtex-parse-nested-braces (- nesting-level 1)))) - (t nil))) - -(defun bibtex-parse-field-string-braced () - "*Parse a field string enclosed by braces. -The field string has to be syntactically correct, which means that the number -of opening and closing braces has to match. If this is the case, a pair -containing the start and end position of the field string is returned, nil -otherwise." - (save-match-data - (let ((starting-point (point)) - (end-point nil)) - (if (looking-at "{") - (setq end-point (bibtex-parse-nested-braces 0))) - (goto-char starting-point) - (if end-point - (cons starting-point end-point) - nil)))) - -(defun bibtex-parse-quoted-string () - "*Starting on an opening quote, find the corresponding closing quote." - (let ((rx (concat "\"" - "\\(" - "[^\"\\]" ;; anything but quote or backslash - "\\|" - "\\(" - "\\\\\\(.\\|\n\\)" ;; any backslash quoted character - "\\)" - "\\)*" - "\""))) - (if (looking-at rx) - (search-forward-regexp rx nil t) - nil))) - -(defun bibtex-parse-field-string-quoted () - "*Parse a field string enclosed by quotes. -If a syntactically correct string is found, a pair containing the start and -end position of the field string is returned, nil otherwise." - (save-match-data - (let ((starting-point (point)) - (end-point nil)) - (if (looking-at "\"") - (setq end-point (bibtex-parse-quoted-string))) - (goto-char starting-point) - (if end-point - (cons starting-point end-point) - nil)))) - -(defun bibtex-parse-field-string () - "*Parse a field string enclosed by braces or quotes. -If a syntactically correct string is found, a pair containing the start and -end position of the field string is returned, nil otherwise." - (save-match-data - (let ((starting-point (point)) - (boundaries (or (bibtex-parse-field-string-braced) - (bibtex-parse-field-string-quoted)))) - (goto-char starting-point) - boundaries))) - -(defun bibtex-search-forward-field-string (bound) - "*Search forward to find a field string enclosed by braces or quotes. -If a syntactically correct string is found, a pair containing the start and -end position of the field string is returned, nil otherwise. The search is -delimited by BOUND." - (save-match-data - (let ((starting-point (point)) - (boundaries nil)) - (while (and (not boundaries) (< (point) bound)) - (if (search-forward-regexp "[{\"]" bound 'move) - (progn - (goto-char (match-beginning 0)) - (let ((temp-boundaries (or (bibtex-parse-field-string-braced) - (bibtex-parse-field-string-quoted)))) - (if (and temp-boundaries (<= (cdr temp-boundaries) bound)) - (setq boundaries temp-boundaries) - (forward-char 1)))))) - (goto-char starting-point) - boundaries))) - -(defun bibtex-parse-association (parse-lhs parse-rhs) - "*Parse a string of the format . -The functions PARSE-LHS and PARSE-RHS are used to parse the corresponding -substrings. These functions are expected to return nil if parsing is not -successfull. If both functions return non-nil, a pair containing the returned -values of the functions PARSE-LHS and PARSE-RHSis returned." - (save-match-data - (let ((starting-point (point)) - (left (funcall parse-lhs)) - (right nil)) - (if (and left (looking-at "[ \t\n]*=[ \t\n]*")) - (progn - (goto-char (match-end 0)) - (setq right (funcall parse-rhs)))) - (goto-char starting-point) - (if (and left right) - (cons left right) - nil)))) - -(defvar bibtex-field-name-for-parsing nil) -;; Temporary variable storing the name string to be parsed by the callback -;; function bibtex-parse-field-name. -(make-variable-buffer-local 'bibtex-field-name-for-parsing) - -(defun bibtex-parse-field-name () - "*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." - (if (looking-at ",[ \t\n]*") - (let ((start (point))) - (goto-char (match-end 0)) - (if (looking-at bibtex-field-name-for-parsing) - (let ((boundaries (list start (match-beginning 0) (match-end 0)))) - (goto-char (match-end 0)) - boundaries))))) - -(defconst bibtex-field-const "[][a-zA-Z0-9.:;?!`'/*@+=|<>&_^$-]+") -;; Regexp defining a bibtex field constant - -(defun bibtex-parse-field-text () - "*Parse the text part of a BibTeX field. -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." - (let ((starting-point (point)) - (end-point nil) - (failure nil)) - (while (and (not end-point) (not failure)) - (if (looking-at bibtex-field-const) - (goto-char (match-end 0)) - (let ((boundaries (bibtex-parse-field-string))) - (if boundaries - (goto-char (cdr boundaries)) - (setq failure t)))) - (if (not (looking-at "[ \t\n]*#[ \t\n]*")) - (setq end-point (point)) - (goto-char (match-end 0)))) - (if (and (not failure) end-point) - (cons starting-point end-point) - nil))) - -(defun bibtex-parse-field (name) - "*Parse a BibTeX field of regexp NAME. -If a syntactically correct field is found, a pair containing the boundaries of -the name and text parts of the field is returned." - (setq bibtex-field-name-for-parsing name) - (bibtex-parse-association 'bibtex-parse-field-name - 'bibtex-parse-field-text)) - -(defun bibtex-search-forward-field (name bound) - "*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 -BOUND." - (save-match-data - (setq bibtex-field-name-for-parsing name) - (let ((starting-point (point)) - (boundaries nil)) - (while (and (not boundaries) - (< (point) bound) - (search-forward "," bound t)) - (goto-char (match-beginning 0)) - (let ((temp-boundaries - (bibtex-parse-association 'bibtex-parse-field-name - 'bibtex-parse-field-text))) - (if (and temp-boundaries (<= (cdr (cdr temp-boundaries)) bound)) - (setq boundaries temp-boundaries) - (forward-char 1)))) - (goto-char starting-point) - boundaries))) - -(defun bibtex-search-backward-field (name 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 -BOUND." - (save-match-data - (setq bibtex-field-name-for-parsing name) - (let ((starting-point (point)) - (boundaries nil)) - (while (and (not boundaries) - (>= (point) bound) - (search-backward "," bound t)) - (let ((temp-boundaries - (bibtex-parse-association 'bibtex-parse-field-name - 'bibtex-parse-field-text))) - (if temp-boundaries - (setq boundaries temp-boundaries)))) - (goto-char starting-point) - boundaries))) - -(defun bibtex-start-of-field (bounds) - (car (car bounds))) -(defun bibtex-end-of-field (bounds) - (cdr (cdr bounds))) -(defun bibtex-start-of-name-in-field (bounds) - (car (cdr (car bounds)))) -(defun bibtex-end-of-name-in-field (bounds) - (car (cdr (cdr (car bounds))))) -(defun bibtex-start-of-text-in-field (bounds) - (car (cdr bounds))) -(defun bibtex-end-of-text-in-field (bounds) - (cdr (cdr bounds))) - -(defun bibtex-parse-string-prefix () - "*Parse the prefix part of a bibtex string, including the reference key. -If the string prefix is found, return a triple consisting of the position of -the very first character of the match, the actual starting position of the -reference key and the end position of the match." - (let* ((case-fold-search t)) - (if (looking-at "^[ \t]*@string[ \t\n]*[({][ \t\n]*") - (let ((start (point))) - (goto-char (match-end 0)) - (if (looking-at bibtex-reference-key) - (let ((boundaries (list start (match-beginning 0) (match-end 0)))) - (goto-char (match-end 0)) - boundaries)))))) - -(defun bibtex-parse-string-postfix () - "*Parse the postfix part of a bibtex string, 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." - (let* ((case-fold-search t) - (text-boundaries (bibtex-parse-field-text))) - (if text-boundaries - (progn - (goto-char (cdr text-boundaries)) - (if (looking-at "[ \t\n]*[})]") - (let ((boundaries (list (car text-boundaries) - (cdr text-boundaries) - (match-end 0)))) - (goto-char (match-end 0)) - boundaries)))))) - -(defun bibtex-parse-string () - "*Parse 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 entry is returned." - (bibtex-parse-association 'bibtex-parse-string-prefix - 'bibtex-parse-string-postfix)) - -(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." - (save-match-data - (let* ((case-fold-search t) - (starting-point (point)) - (boundaries nil)) - (while (and (not boundaries) - (search-forward-regexp - "^[ \t]*@string[ \t\n]*[({][ \t\n]*" nil t)) - (goto-char (match-beginning 0)) - (let ((temp-boundaries (bibtex-parse-string))) - (if temp-boundaries - (setq boundaries temp-boundaries) - (forward-char 1)))) - (goto-char starting-point) - boundaries))) - -(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." - (save-match-data - (let* ((case-fold-search t) - (starting-point (point)) - (boundaries nil)) - (while (and (not boundaries) - (search-backward-regexp - "^[ \t]*@string[ \t\n]*[({][ \t\n]*" nil t)) - (goto-char (match-beginning 0)) - (let ((temp-boundaries (bibtex-parse-string))) - (if temp-boundaries - (setq boundaries temp-boundaries)))) - (goto-char starting-point) - boundaries))) - -(defun bibtex-end-of-string (bounds) - (car (cdr (cdr (cdr bounds))))) -(defun bibtex-start-of-reference-key-in-string (bounds) - (car (cdr (car bounds)))) -(defun bibtex-end-of-reference-key-in-string (bounds) - (car (cdr (cdr (car bounds))))) -(defun bibtex-start-of-text-in-string (bounds) - (car (cdr bounds))) -(defun bibtex-end-of-text-in-string (bounds) - (car (cdr (cdr bounds)))) - -(defconst bibtex-entry-head - (concat "^[ \t]*\\(" - bibtex-entry-type - "\\)[ \t]*[({][ \t\n]*\\(" - bibtex-reference-key - "\\)")) -;; Regexp defining format of the header line of a BibTeX entry. - -(defconst bibtex-entry-maybe-empty-head - (concat bibtex-entry-head "?")) -;; Regexp defining format of the header line of a maybe empty -;; BibTeX entry (possibly without reference key). - -(defconst bibtex-type-in-head 1) -;; The regexp subexpression number of the type part in -;; bibtex-entry-head. - -(defconst bibtex-key-in-head 2) -;; The regexp subexpression number of the key part in -;; bibtex-entry-head. - -(defconst bibtex-entry-postfix "[ \t\n]*,?[ \t\n]*[})]") -;; Regexp defining the postfix of a bibtex entry - -(defconst bibtex-key-in-entry bibtex-key-in-head) -;; The regexp subexpression number of the key part in a bibtex entry. - -(defvar bibtex-font-lock-keywords - (list - ;; entry type and reference key - (list bibtex-entry-maybe-empty-head - (list bibtex-type-in-head 'font-lock-function-name-face) - (list bibtex-key-in-head 'font-lock-constant-face nil t)) - ;; comments - (list - (concat "^\\([ \t]*" bibtex-comment-start ".*\\)$") - 1 'font-lock-comment-face) - ;; optional field names (treated as comments) - (list - (concat "^[ \t]*\\(OPT" bibtex-field-name "\\)[ \t]*=") - 1 'font-lock-comment-face) - ;; field names - (list (concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=") - 1 'font-lock-variable-name-face) - "*Default expressions to highlight in BibTeX mode.")) -;; now all needed patterns are defined - - - -;; Helper Functions - -(defun bibtex-delete-whitespace () - ;; Delete all whitespace starting at point - (if (looking-at "[ \t\n]+") - (delete-region (point) (match-end 0)))) - -(defun bibtex-current-line () - ;; this computes line number of point regardless whether the buffer - ;; is narrowed - (+ (count-lines 1 (point)) - (if (equal (current-column) 0) 1 0))) - -(defun bibtex-member-of-regexp (string list) - ;; Return non-nil if STRING is exactly matched by an element of - ;; LIST. The value is actually the tail of LIST whose - ;; car matches STRING. - (let* (case-fold-search) - (while - (and list (not (string-match (concat "^" (car list) "$") string))) - (setq list (cdr list))) - list)) - -(defun bibtex-assoc-of-regexp (string alist) - ;; Return non-nil if STRING is exactly matched by the car of an - ;; element of LIST (case ignored). The value is actually the element - ;; of LIST whose car matches STRING. - (let* ((case-fold-search t)) - (while - (and alist - (not (string-match (concat "^" (car (car alist)) "$") string))) - (setq alist (cdr alist))) - (car alist))) - -(defun bibtex-skip-to-valid-entry (&optional backward) - ;; If not at beginning of valid BibTeX entry, move to beginning of - ;; the next valid one. With 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. - (let* ((case-fold-search t) - (valid-bibtex-entry - (concat - "@[ \t]*\\(" - (mapconcat - (lambda (type) - (concat "\\(" (car type) "\\)")) - bibtex-entry-field-alist - "\\|") - "\\)")) - found) - (while (and (not found) - (not (if backward - (bobp) - (eobp)))) - (let ((pnt (point))) - (cond - ((looking-at valid-bibtex-entry) - (if (and - (bibtex-search-entry nil nil t) - (equal (match-beginning 0) pnt)) - (setq found t))) - ((and (not bibtex-sort-ignore-string-entries) - (bibtex-parse-string)) - (setq found t))) - (if found - (goto-char pnt) - (if backward - (progn - (goto-char (1- pnt)) - (if (re-search-backward "^[ \t]*\\(@\\)" nil 'move) - (goto-char (match-beginning 1)))) - (goto-char (1+ pnt)) - (if (re-search-forward "^[ \t]*@" nil 'move) - (forward-char -1)))))))) - -(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 one argument, the key - ;; of the entry, and with point 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) - (while (re-search-forward bibtex-entry-maybe-empty-head nil t) - (let ((pnt (point)) - (entry-type - (downcase (buffer-substring-no-properties - (1+ (match-beginning bibtex-type-in-head)) - (match-end bibtex-type-in-head)))) - (reference-key - (if (match-beginning bibtex-key-in-head) - (buffer-substring-no-properties - (match-beginning bibtex-key-in-head) - (match-end bibtex-key-in-head)) - ""))) - (if (or - (and - (not bibtex-sort-ignore-string-entries) - (string-equal "string" (downcase entry-type))) - (assoc-ignore-case entry-type bibtex-entry-field-alist)) - (funcall fun reference-key)) - (goto-char pnt) - (bibtex-end-of-entry))))) - -(defun bibtex-progress-message (&optional flag interval) - ;; echos a message about progress of current buffer - ;; if flag is a string, the message is initialized (in this case a - ;; value for INTERVAL may be given as well (if not this is set to 5)) - ;; if flag is done, the message is deinitialized - ;; if flag is absent, a message is echoed if point was incremented - ;; at least INTERVAL percent since last message was echoed - (let* ((size (- (point-max) (point-min))) - (perc (if (= size 0) - 100 - (/ (* 100 (- (point) (point-min))) size)))) - (if (or (and (not flag) - (>= perc - (+ bibtex-progress-interval bibtex-progress-lastperc))) - (stringp flag)) - (progn - (if (stringp flag) - (progn - (setq bibtex-progress-lastmes flag) - (if interval - (setq bibtex-progress-interval interval) - (setq bibtex-progress-interval 5)))) - (setq bibtex-progress-lastperc perc) - (message (concat bibtex-progress-lastmes " (%d%%)") perc)) - (if (equal flag 'done) - (progn - (message (concat bibtex-progress-lastmes " (done)")) - (setq bibtex-progress-lastmes nil)))))) - - -(defun bibtex-field-left-delimiter () - ;; returns a string dependent on bibtex-field-delimiters - (if (equal bibtex-field-delimiters 'braces) - "{" - "\"")) - -(defun bibtex-field-right-delimiter () - ;; returns a string dependent on bibtex-field-delimiters - (if (equal bibtex-field-delimiters 'braces) - "}" - "\"")) - -(defun bibtex-entry-left-delimiter () - ;; returns a string dependent on bibtex-field-delimiters - (if (equal bibtex-entry-delimiters 'braces) - "{" - "(")) - -(defun bibtex-entry-right-delimiter () - ;; returns a string dependent on bibtex-field-delimiters - (if (equal bibtex-entry-delimiters 'braces) - "}" - ")")) - -(defun bibtex-search-entry - (empty-head &optional bound noerror backward) - ;; A helper function necessary since the failure stack size limit for - ;; regexps was reduced in emacs 19.32. - ;; It searches for a BibTeX entry (maybe without a 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. After - ;; call to this function MATCH-BEGINNING and MATCH-END functions are - ;; defined, but only for the head part of the entry (especially - ;; (match-end 0) just gives the end of the head part). - (let ((pnt (point)) - (prefix (if empty-head - bibtex-entry-maybe-empty-head - bibtex-entry-head))) - (if backward - (let (found) - (while (and (not found) - (re-search-backward prefix bound noerror)) - (setq found (bibtex-search-entry empty-head pnt t))) - (if found - (goto-char (match-beginning 0)) - (if (equal noerror nil) - ;; yell - (error "Search of BibTeX entry failed")) - (if (equal noerror t) - ;; don't move - (goto-char pnt)) - nil)) - (let ((limit (if bound bound (point-max))) - md - found) - (while (and (not found) - (re-search-forward prefix bound noerror)) - (setq md (match-data)) - ;; save match-data of prefix regexp - (let ((entry-closer - (if (save-excursion - (goto-char (match-end bibtex-type-in-head)) - (looking-at "[ \t]*(")) - ;; entry opened with parenthesis - ")" - "}"))) - (let ((infix-start (point)) - (finished nil)) - (while (not finished) - (if (and (looking-at "[ \t\n]*") - (<= (match-end 0) limit)) - (goto-char (match-end 0))) - (let ((bounds (bibtex-parse-field bibtex-field-name))) - (if (and bounds (<= (bibtex-end-of-field bounds) limit)) - (progn - (goto-char (bibtex-end-of-field bounds)) - (setq infix-start (point))) - (goto-char infix-start) - (setq finished t))))) - ;; This matches the infix* part. The AND construction assures - ;; that BOUND is respected. - (if (and (looking-at bibtex-entry-postfix) - (string-equal - (buffer-substring-no-properties - (1- (match-end 0)) (match-end 0)) - entry-closer) - (<= (match-end 0) limit)) - (progn - (re-search-forward bibtex-entry-postfix) - (setq found t))))) - (if found - (progn - (set-match-data md) - ;; to set match-beginning/end again - (point)) - (if (equal noerror nil) - ;; yell - (error "Search of BibTeX entry failed")) - (if (equal noerror t) - ;; don't move - (goto-char pnt)) - nil))))) - -(defun bibtex-flash-head () - ;; Flash at BibTeX entry head before point, if exists. - (let* ((case-fold-search t) - flash) - (cond ((re-search-backward bibtex-entry-head nil t) - (goto-char (match-beginning bibtex-type-in-head)) - (setq flash (match-end bibtex-key-in-entry))) - (t - (end-of-line) - (skip-chars-backward " \t") - (setq flash (point)) - (beginning-of-line) - (skip-chars-forward " \t"))) - (if (pos-visible-in-window-p (point)) - (sit-for 1) - (message "From: %s" - (buffer-substring (point) flash))))) - -(defun bibtex-make-optional-field (e-t) - "Makes an optional field named E-T in current BibTeX entry." - (if (consp e-t) - (bibtex-make-field (cons (concat "OPT" (car e-t)) (cdr e-t))) - (bibtex-make-field (concat "OPT" e-t)))) - -(defun bibtex-move-outside-of-entry () - ;; Make sure we are outside of a BibTeX entry. - (let ((orig-point (point))) - (bibtex-end-of-entry) - (if (< (point) orig-point) - ;; We moved backward, so we weren't inside an entry to begin with. - ;; Leave point at the beginning of a line, and preferably - ;; at the beginning of a paragraph. - (progn - (goto-char orig-point) - (beginning-of-line 1) - (if (not (= ?\n (char-before (1- (point))))) - (progn - (re-search-forward "^[ \t]*[@\n]" nil 'move) - (backward-char 1))))) - (skip-chars-forward " \t\n"))) - -(defun bibtex-beginning-of-first-entry () - ;; 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)) - (point)) - -(defun bibtex-beginning-of-last-entry () - ;; Go to the beginning of the last BibTeX entry in buffer. - (goto-char (point-max)) - (if (re-search-backward "^[ \t]*@" nil 'move) - (beginning-of-line)) - (point)) - -(defun bibtex-inside-field () - ;; Try to avoid point being at end of a BibTeX field. - (end-of-line) - (skip-chars-backward " \t") - (cond ((= (preceding-char) ?,) - (forward-char -2))) - (cond ((or - (= (preceding-char) ?}) - (= (preceding-char) ?\")) - (forward-char -1)))) - -(defun bibtex-enclosing-field (&optional noerr) - ;; Search for BibTeX field enclosing point. Point moves to end of - ;; field. Use match-beginning and match-end to parse the field. If - ;; NOERR is non-nil, no error is signalled. In this case, t is - ;; returned on success, nil otherwise. - (let* ((case-fold-search t) - (old-point (point)) - (boe (bibtex-beginning-of-entry))) - (goto-char old-point) - (let ((bounds (bibtex-search-backward-field bibtex-field-name boe))) - (if (and bounds - (<= (bibtex-start-of-field bounds) old-point) - (>= (bibtex-end-of-field bounds) old-point)) - bounds - (if noerr - nil - (error "Can't find enclosing BibTeX field")))))) - -(defun bibtex-enclosing-entry-maybe-empty-head () - ;; Search for BibTeX entry enclosing point. Point moves to - ;; end of entry. Beginning (but not end) of entry is given - ;; by (match-beginning 0). - (let* ((case-fold-search t) - (old-point (point))) - (if (not - (re-search-backward - bibtex-entry-maybe-empty-head nil t)) - (progn - (error "Can't find enclosing BibTeX entry") - (goto-char old-point))) - (goto-char (match-beginning bibtex-type-in-head)) - (if (not - (bibtex-search-entry t nil t)) - (progn - (error "Can't find enclosing BibTeX entry") - (goto-char old-point))))) - -(defun bibtex-insert-current-kill (n) - (if (not bibtex-last-kill-command) - (error "BibTeX kill ring is empty") - (let* ((kr (if (equal bibtex-last-kill-command 'field) - 'bibtex-field-kill-ring - 'bibtex-entry-kill-ring)) - (kryp (if (equal bibtex-last-kill-command 'field) - 'bibtex-field-kill-ring-yank-pointer - 'bibtex-entry-kill-ring-yank-pointer)) - (ARGth-kill-element - (nthcdr - (mod (- n (length (eval kryp))) (length (eval kr))) - (eval kr))) - (current (car (set kryp ARGth-kill-element)))) - (cond - ((equal bibtex-last-kill-command 'field) - (let (bibtex-help-message) - (bibtex-find-text nil t) - (if (looking-at "[}\"]") - (forward-char))) - (set-mark (point)) - (message "Mark set") - (bibtex-make-field (list (elt current 1) nil (elt current 2)) t)) - ((equal bibtex-last-kill-command 'entry) - (if (not (eobp)) - (bibtex-beginning-of-entry)) - (set-mark (point)) - (message "Mark set") - (insert (elt current 1))) - (t - (error - "Unknown tag field: %s. Please submit a bug report" - bibtex-last-kill-command)))))) - -(defun bibtex-format-field-delimiters (start stop) - "*Replaces delimiters for field strings between START and STOP. -If the current delimiters equal the new delimiters, the buffer is not -changed." - (goto-char start) - (let ((boundaries (bibtex-search-forward-field-string stop))) - (while boundaries - (goto-char (car boundaries)) - (if (not (looking-at (bibtex-field-left-delimiter))) - (progn - (delete-char 1) - (insert (bibtex-field-left-delimiter)))) - (goto-char (- (cdr boundaries) 1)) - (if (not (looking-at (bibtex-field-right-delimiter))) - (progn - (delete-char 1) - (insert (bibtex-field-right-delimiter)))) - (setq boundaries (bibtex-search-forward-field-string stop))))) - -(defun bibtex-format-entry () - ;; Helper function for bibtex-clean-entry. Formats current entry - ;; according to variable bibtex-entry-format. - (let* ((case-fold-search t) - (beg (point)) - (start (bibtex-beginning-of-entry)) - crossref-there - alternatives-there - non-empty-alternative) - (let ((end (copy-marker (bibtex-end-of-entry)))) - (if (equal start (marker-position end)) - (error "Not on a known BibTeX entry") - (goto-char start) - (let ((bounds (bibtex-search-forward-field bibtex-field-name end))) - (while bounds - ;; determine if entry has crossref field and if at least - ;; one alternative is non-empty - (let ((begin-name (bibtex-start-of-name-in-field bounds)) - (end-name (bibtex-end-of-name-in-field bounds)) - (begin-text (bibtex-start-of-text-in-field bounds)) - (end-text (bibtex-end-of-text-in-field bounds))) - (goto-char begin-name) - (if (looking-at "ALT") - (progn - (setq alternatives-there t) - (goto-char begin-text) - (if (not (looking-at "\\(\"\"\\)\\|\\({}\\)")) - (setq non-empty-alternative t)))) - (if (string-match - "\\(OPT\\)?crossref" - (buffer-substring-no-properties begin-name end-name)) - (progn - (setq - crossref-there - (buffer-substring-no-properties - (1+ begin-text) (1- end-text))) - (if (equal crossref-there "") - (setq crossref-there nil))))) - (goto-char (bibtex-end-of-field bounds)) - (setq bounds (bibtex-search-forward-field bibtex-field-name end)))) - (if (and alternatives-there - (not non-empty-alternative)) - (progn - (goto-char beg) - (error "All alternatives are empty"))) - (goto-char start) - (re-search-forward bibtex-entry-type end) - (let* ((begin-type (1+ (match-beginning 0))) - (end-type (match-end 0)) - (entry-type - (downcase - (buffer-substring-no-properties begin-type end-type))) - (entry-list - (assoc-ignore-case entry-type bibtex-entry-field-alist)) - (req (elt (elt entry-list 1) 0)) - (creq (elt (elt entry-list 2) 0)) - (format (if (equal bibtex-entry-format t) - '(realign opts-or-alts numerical-fields - last-comma page-dashes delimiters - unify-case inherit-booktitle) - bibtex-entry-format)) - field-done) - (if (memq 'unify-case format) - (progn - (delete-region begin-type end-type) - (insert (car entry-list)))) - (if (memq 'delimiters format) - (progn - (goto-char end-type) - (skip-chars-forward " \t\n") - (delete-char 1) - (insert (bibtex-entry-left-delimiter)))) - (goto-char start) - (let ((bounds (bibtex-search-forward-field bibtex-field-name end))) - (while bounds - (let* ((begin-field (copy-marker (bibtex-start-of-field bounds))) - (end-field (copy-marker (bibtex-end-of-field bounds))) - (begin-name (copy-marker (bibtex-start-of-name-in-field bounds))) - (end-name (copy-marker (bibtex-end-of-name-in-field bounds))) - (begin-text (copy-marker (bibtex-start-of-text-in-field bounds))) - (end-text (copy-marker (bibtex-end-of-text-in-field bounds))) - (field-name - (buffer-substring-no-properties - (if (string-match - "^\\(OPT\\)\\|\\(ALT\\)$" - (buffer-substring-no-properties - begin-name (+ begin-name 3))) - (+ begin-name 3) - begin-name) - end-name))) - (cond - ((and - (memq 'opts-or-alts format) - (progn (goto-char begin-name) - (looking-at "OPT\\|ALT"))) - (goto-char begin-text) - (if (looking-at "\\(\"\"\\)\\|\\({}\\)") - ;; empty: delete whole field if really optional - ;; (missing crossref handled) or complain - (if (and - (progn - (goto-char begin-name) - (looking-at "OPT")) - (not crossref-there) - (assoc-ignore-case field-name req)) - ;; field is not really optional - (progn - (goto-char begin-name) - (bibtex-remove-OPT-or-ALT) - (error - "Mandatory field ``%s'' is empty" field-name)) - ;; field is optional - (delete-region begin-field end-field)) - ;; otherwise: not empty, delete "OPT" - (goto-char begin-name) - (bibtex-remove-OPT-or-ALT))) - ((and - (memq 'numerical-fields format) - (progn - (goto-char begin-text) - (looking-at "\\(\"[0-9]+\"\\)\\|\\({[0-9]+}\\)"))) - (goto-char end-text) - (delete-char -1) - (goto-char begin-text) - (delete-char 1)) - (t - (if (memq 'delimiters format) - (bibtex-format-field-delimiters begin-text end-text)) - (if (and - (memq 'page-dashes format) - (string-match "^\\(OPT\\)?pages$" (downcase field-name)) - (progn - (goto-char begin-text) - (looking-at - "\\([\"{][0-9]+\\)[ \t\n]*--?[ \t\n]*\\([0-9]+[\"}]\\)"))) - (replace-match "\\1-\\2")) - (if (and - (memq 'inherit-booktitle format) - (equal (downcase field-name) "booktitle") - (progn - (goto-char begin-text) - (looking-at "\\(\"\"\\)\\|\\({}\\)")) - crossref-there - (not (bibtex-find-entry-location crossref-there t))) - ;; booktitle field empty and crossref entry found - ;; --> insert title field of crossreferenced entry if there - (let ((stop (bibtex-end-of-entry))) - (bibtex-beginning-of-entry) - (let ((bounds (bibtex-search-forward-field "title" stop))) - (if bounds - (progn - (goto-char begin-text) - (forward-char) - (insert - (buffer-substring-no-properties - (1+ (bibtex-start-of-text-in-field bounds)) - (1- (bibtex-end-of-text-in-field bounds))))))))) - (if (progn - (goto-char begin-text) - (looking-at "\\(\"\"\\)\\|\\({}\\)")) - ;; if empty field, complain - (progn - (forward-char) - (if (or (and - crossref-there - (assoc-ignore-case - field-name creq)) - (and - (not crossref-there) - (assoc-ignore-case - field-name req))) - (error - "Mandatory field ``%s'' is empty" field-name)))) - (if (memq 'unify-case format) - (let* ((fl - (car (cdr (assoc-ignore-case - entry-type - bibtex-entry-field-alist)))) - (field-list - (append - (elt fl 0) - (elt fl 1) - bibtex-user-optional-fields)) - (new-field-name - (car - (assoc-ignore-case field-name field-list)))) - (goto-char begin-name) - (if new-field-name - (progn - (delete-region begin-name end-name) - (insert new-field-name)) - (downcase-region begin-name end-name)))) - (setq field-done t))) - (if (not field-done) - (goto-char begin-field) - (setq field-done nil) - (goto-char end-field))) - (setq bounds (bibtex-search-forward-field bibtex-field-name end)))) - (if (looking-at (bibtex-field-right-delimiter)) - (forward-char)) - (if (memq 'last-comma format) - (cond ((and - bibtex-comma-after-last-field - (not (looking-at ","))) - (insert ",")) - ((and - (not bibtex-comma-after-last-field) - (looking-at ",")) - (delete-char 1)))) - (if (looking-at ",") - (forward-char)) - (if (memq 'delimiters format) - (progn - (skip-chars-forward " \t\n") - (delete-char 1) - (insert (bibtex-entry-right-delimiter)))) - (if (memq 'realign format) - (bibtex-fill-entry))))))) - -(defun bibtex-autokey-change (string change-list) - ;; Returns a string where some regexps are changed according to - ;; change-list. Every item of change-list is an (old-regexp - ;; new-string) pair. - (let* (case-fold-search - (return-string string) - (index 0) - (len (length change-list)) - change-item) - (while (< index len) - (setq change-item (elt change-list index)) - (while (string-match (car change-item) return-string) - (setq - return-string - (concat (substring return-string 0 (match-beginning 0)) - (elt change-item 1) - (substring return-string (match-end 0))))) - (setq index (1+ index))) - return-string)) - -(defun bibtex-autokey-abbrev (string len) - ;; Returns an abbreviation of string with at least len - ;; characters. String is aborted only after a consonant or at the - ;; word end. If len is not a number, string is returned unchanged. - (cond ((or - (not (numberp len)) - (<= (length string) len)) - string) - ((equal len 0) - "") - (t - (let* ((case-fold-search t) - (abort-char - (string-match "[^aeiou]" string (1- len)))) - (if abort-char - (substring string 0 (1+ abort-char)) - string))))) - -(defun bibtex-autokey-get-namefield (min max) - ;; returns the contents of the name field of the current entry - ;; does some modifications based on `bibtex-autokey-name-change-strings' - ;; and removes newlines unconditionally - (goto-char min) - (let* ((case-fold-search t) - (author-or-editor "\\(author\\)\\|\\(editor\\)") - (bounds (bibtex-search-forward-field author-or-editor max))) - (if bounds - (bibtex-autokey-change - (buffer-substring-no-properties - (1+ (bibtex-start-of-text-in-field bounds)) - (1- (bibtex-end-of-text-in-field bounds))) - (append bibtex-autokey-name-change-strings '(("\n" " ")))) - ""))) - -(defun bibtex-autokey-get-names (namefield) - ;; gathers all names in namefield into a list - (let* ((case-fold-search t) - names) - (while (not (equal namefield "")) - (let (name) - (if (string-match "[ \t\n]and[ \t\n]" namefield) - (setq name (substring namefield 0 (match-beginning 0)) - namefield (substring namefield (match-end 0))) - (setq name namefield - namefield "")) - (setq names (append names (list name))))) - names)) - -(defun bibtex-autokey-demangle-name (fullname) - ;; gets the `last' part from a well-formed name - (let* (case-fold-search - (lastname - (if (string-match "," fullname) - ;; name is of the form "von Last, First" or - ;; "von Last, Jr, First" - ;; --> take only the part before the comma - (let ((von-last - (substring fullname 0 (match-beginning 0)))) - (if (string-match "^[a-z]" von-last) - ;; von-last has a "von" part --> take the "last" part - (if (string-match "[ \t][A-Z]" von-last) - (substring von-last (1+ (match-beginning 0))) - (error - "Name %s is incorrectly formed" fullname)) - ;; von-last has no "von" part --> take all - von-last)) - ;; name is of the form "First von Last" - (if (string-match "[ \t]" fullname) - ;; more than one token - (if (string-match "[ \t][a-z]" fullname) - ;; there is a "von" part - ;; --> take everything after that - (if (string-match - "[ \t][A-Z]" fullname (match-end 0)) - (substring fullname (1+ (match-beginning 0))) - (error - "Name %s is incorrectly formed" fullname)) - ;; there is no "von" part --> take only the last token - (if (string-match " [^ ]*$" fullname) - (substring fullname (1+ (match-beginning 0))) - (error "Name %s is incorrectly formed" fullname))) - ;; only one token --> take it - fullname))) - (usename - (if (string-match "[ \t]+" lastname) - ;; lastname consists of two or more tokens - ;; --> take only the first one - (substring lastname 0 (match-beginning 0)) - lastname))) - (funcall bibtex-autokey-name-case-convert usename))) - -(defun bibtex-autokey-get-namelist (namefield) - ;; gets namefield, performs abbreviations on the last parts, and - ;; return results as a list - (mapcar - (lambda (fullname) - (setq - fullname (substring fullname (string-match "[^ \t]" fullname))) - (bibtex-autokey-abbrev - (bibtex-autokey-demangle-name fullname) - bibtex-autokey-name-length)) - (bibtex-autokey-get-names namefield))) - -(defun bibtex-autokey-get-yearfield-digits (max) - ;; get digit substring from year field. - (let ((bounds (bibtex-search-forward-field "year" max))) - (if bounds - (let ((year (buffer-substring-no-properties - (bibtex-start-of-text-in-field bounds) - (bibtex-end-of-text-in-field bounds)))) - (string-match "[^0-9]*\\([0-9]+\\)" year) - (substring year (match-beginning 1) (match-end 1))) - ""))) - -(defun bibtex-autokey-get-yearfield (min max) - ;; get year field from current or maybe crossreferenced entry - (goto-char min) - (let* ((case-fold-search t) - (year (bibtex-autokey-get-yearfield-digits max))) - (if (and (string= year "") bibtex-autokey-year-use-crossref-entry) - (let* ((bounds - (bibtex-search-forward-field "\\(OPT\\)?crossref" max)) - (crossref-field - (if bounds - (buffer-substring-no-properties - (1+ (bibtex-start-of-text-in-field bounds)) - (1- (bibtex-end-of-text-in-field bounds)))))) - (if (not (bibtex-find-entry-location crossref-field t)) - (let ((stop (bibtex-end-of-entry))) - (bibtex-beginning-of-entry) - (bibtex-autokey-get-yearfield-digits stop)) - "")) - year))) - -(defun bibtex-autokey-get-titlestring (min max) - ;; get title field contents up to a terminator - (goto-char min) - (let* ((case-fold-search t) - (bounds (bibtex-search-forward-field "title" max)) - (titlefield - (if bounds - (bibtex-autokey-change - (buffer-substring-no-properties - (1+ (bibtex-start-of-text-in-field bounds)) - (1- (bibtex-end-of-text-in-field bounds))) - bibtex-autokey-titleword-change-strings) - "")) - (title-terminators bibtex-autokey-title-terminators)) - (while (not (null title-terminators)) - (if (string-match (car title-terminators) titlefield) - (setq titlefield (substring titlefield 0 (match-beginning 0)))) - (setq title-terminators (cdr title-terminators))) - titlefield)) - -(defun bibtex-autokey-get-titles (titlestring) - ;; gathers words from titlestring into a list. Ignores - ;; specific words and uses only a specific amount of words. - (let* (case-fold-search - titlewords - titlewords-extra - (counter 0)) - (while (and - (not (equal titlestring "")) - (or - (not (numberp bibtex-autokey-titlewords)) - (< counter - (+ bibtex-autokey-titlewords - bibtex-autokey-titlewords-stretch)))) - (if (string-match "\\b\\w+" titlestring) - (let* ((end-match (match-end 0)) - (titleword - (substring titlestring (match-beginning 0) end-match))) - (if (bibtex-member-of-regexp - titleword - bibtex-autokey-titleword-ignore) - (setq counter (1- counter)) - (setq - titleword - (funcall bibtex-autokey-titleword-case-convert titleword)) - (if (or (not (numberp bibtex-autokey-titlewords)) - (< counter bibtex-autokey-titlewords)) - (setq titlewords (append titlewords (list titleword))) - (setq titlewords-extra - (append titlewords-extra (list titleword))))) - (setq - titlestring (substring titlestring end-match))) - (setq titlestring "")) - (setq counter (1+ counter))) - (if (string-match "\\b\\w+" titlestring) - titlewords - (append titlewords titlewords-extra)))) - -(defun bibtex-autokey-get-titlelist (titlestring) - ;; returns all words in titlestring as a list - ;; does some abbreviation on the found words - (mapcar - (lambda (titleword) - (let ((abbrev - (bibtex-assoc-of-regexp - titleword bibtex-autokey-titleword-abbrevs))) - (if abbrev - (elt abbrev 1) - (bibtex-autokey-abbrev - titleword - bibtex-autokey-titleword-length)))) - (bibtex-autokey-get-titles titlestring))) - -(defun bibtex-generate-autokey () - "Generates automatically a key from the author/editor and the title field. -This will only work for entries where each field begins on a separate line. -The generation algorithm works as follows: - 1. Use the value of `bibtex-autokey-prefix-string' as a prefix. - 2. If there is a non-empty author (preferred) or editor field, - use it as the name part of the key. - 3. Change any substring found in - `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 - `bibtex-autokey-names' + `bibtex-autokey-names-stretch' - names, all names are used. - 5. From every last name, take at least - `bibtex-autokey-name-length' characters (abort only after a - consonant or at a word end). - 6. Convert all last names according to the conversion function - `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 - 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 is - absent, but the entry has a valid crossref field and the - variable `bibtex-autokey-year-use-crossref-entry' is non-nil, - use the year field of the crossreferenced entry instead. - 9. For the title part of the key change the contents of the - title field of the entry according to - `bibtex-autokey-titleword-change-strings' to the - corresponding new one (see documentation of this variable for - further detail). -10. Abbreviate the result to the string up to (but not including) - the first occurrence of a regexp matched by the items of - `bibtex-autokey-title-terminators' and delete those words which - 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 - maximal `bibtex-autokey-titlewords' + - `bibtex-autokey-titlewords-stretch' words, all - words from the abbreviated title are used. -11. Convert all used titlewords according to the conversion function - `bibtex-autokey-titleword-case-convert'. -12. For every used title word that appears in - `bibtex-autokey-titleword-abbrevs' use the corresponding - abbreviation (see documentation of this variable for further - detail). -13. From every title word not generated by an abbreviation, take - at least `bibtex-autokey-titleword-length' characters (abort - only after a consonant or at a word end). -14. Build the title part of the key by concatenating all - abbreviated title words with the string - `bibtex-autokey-titleword-separator' between any two. -15. At least, to get the key, concatenate - `bibtex-autokey-prefix-string', the name part, the year part - 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 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 - function is then called with the generated key as the - 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, - where it can be edited. The key given by the user is then - used." - (let* ((pnt (point)) - (min (bibtex-beginning-of-entry)) - (max (bibtex-end-of-entry)) - (namefield (bibtex-autokey-get-namefield min max)) - (name-etal "") - (namelist - (let ((nl (bibtex-autokey-get-namelist namefield))) - (if (or (not (numberp bibtex-autokey-names)) - (<= (length nl) - (+ bibtex-autokey-names - bibtex-autokey-names-stretch))) - nl - (setq name-etal bibtex-autokey-additional-names) - (let (nnl) - (while (< (length nnl) bibtex-autokey-names) - (setq nnl (append nnl (list (car nl))) - nl (cdr nl))) - nnl)))) - (namepart - (concat - (mapconcat (lambda (name) name) - namelist - bibtex-autokey-name-separator) - name-etal)) - (yearfield (bibtex-autokey-get-yearfield min max)) - (yearpart - (if (equal yearfield "") - "" - (substring - yearfield - (- (length yearfield) bibtex-autokey-year-length)))) - (titlestring (bibtex-autokey-get-titlestring min max)) - (titlelist (bibtex-autokey-get-titlelist titlestring)) - (titlepart - (mapconcat - (lambda (name) name) - titlelist - bibtex-autokey-titleword-separator)) - (autokey - (concat - bibtex-autokey-prefix-string - namepart - (if (not - (or - (equal namepart "") - (equal yearpart ""))) - bibtex-autokey-name-year-separator) - yearpart - (if (not - (or - (and - (equal namepart "") - (equal yearpart "")) - (equal titlepart ""))) - bibtex-autokey-year-title-separator) - titlepart))) - (if bibtex-autokey-before-presentation-function - (setq - autokey - (funcall bibtex-autokey-before-presentation-function autokey))) - (goto-char pnt) - autokey)) - -(defun bibtex-parse-keys (add verbose &optional abortable) - ;; Sets bibtex-reference-keys to the keys used in the whole (possibly - ;; restricted) buffer (either as entry keys or as crossref entries). - ;; If ADD is non-nil adds the new keys to bibtex-reference-keys instead of - ;; simply resetting it. If VERBOSE is non-nil gives messages about - ;; progress. If ABORTABLE is non-nil abort on user input. - (if bibtex-maintain-sorted-entries - (let* ((case-fold-search t) - (reference-keys (if add bibtex-reference-keys))) - (save-excursion - (goto-char (point-min)) - (if verbose - (bibtex-progress-message - (concat (buffer-name) ": parsing reference keys"))) - (if (catch 'userkey - (bibtex-skip-to-valid-entry) - (while (not (eobp)) - (if (and - abortable - (input-pending-p)) - (throw 'userkey t)) - (if verbose - (bibtex-progress-message)) - (let (reference-key - xrefd-reference-key) - (cond - ((looking-at bibtex-entry-head) - (setq - reference-key - (buffer-substring-no-properties - (match-beginning bibtex-key-in-head) - (match-end bibtex-key-in-head))) - (let ((p (point)) - (m (bibtex-end-of-entry))) - (goto-char p) - (let ((bounds (bibtex-search-forward-field "crossref" m))) - (if bounds - (setq - xrefd-reference-key - (buffer-substring-no-properties - (1+ (bibtex-start-of-text-in-field bounds)) - (1- (bibtex-end-of-text-in-field bounds)))))))) - ((bibtex-parse-string) - (let ((bounds (bibtex-parse-string))) - (setq - reference-key - (buffer-substring-no-properties - (bibtex-start-of-reference-key-in-string bounds) - (bibtex-end-of-reference-key-in-string bounds)))))) - (forward-char) - (bibtex-skip-to-valid-entry) - (if (not (assoc reference-key reference-keys)) - (setq reference-keys - (cons (list reference-key) reference-keys))) - (if (and xrefd-reference-key - (not (assoc xrefd-reference-key reference-keys))) - (setq reference-keys - (cons (list xrefd-reference-key) reference-keys)))))) - ;; user has aborted by typing a key --> return nil - nil - ;; successful operation --> return t - (setq - bibtex-buffer-last-parsed-tick (buffer-modified-tick) - bibtex-reference-keys reference-keys) - (if verbose - (bibtex-progress-message 'done)) - t))))) - -(defun bibtex-parse-buffers-stealthily () - ;; 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. - (let ((buffers (buffer-list))) - (save-excursion - (while (and buffers (not (input-pending-p))) - (set-buffer (car buffers)) - (save-restriction - (widen) - (if (and - (eq major-mode 'bibtex-mode) - bibtex-maintain-sorted-entries - (not - (eq (buffer-modified-tick) - bibtex-buffer-last-parsed-tick))) - (if (bibtex-parse-keys nil t t) - ;; successful operation --> remove buffer from list - (setq buffers (cdr buffers))) - ;; buffer is no BibTeX buffer or needs no parsing - (setq buffers (cdr buffers)))))))) - -(defun bibtex-complete (string-list &optional complete-strings) - ;; Complete word fragment before point to longest prefix of one - ;; string defined in STRING-LIST. If point is not after the part of - ;; a word, all strings are listed. If COMPLETE-STRINGS is non-nil, - ;; add the strings defined in this buffer before cursor to - ;; STRING-LIST and remove surrounding delimiters if complete string - ;; could be expanded. - (let* ((case-fold-search t) - (end (point)) - (beg (save-excursion - (re-search-backward "[ \t{\"]") - (forward-char) - (point))) - (part-of-word (buffer-substring-no-properties beg end)) - (completions (copy-sequence string-list)) - (completion (save-excursion - (if complete-strings - (while (bibtex-search-backward-string) - (let ((bounds (bibtex-search-backward-string))) - (setq completions - (cons - (list - (buffer-substring-no-properties - (bibtex-start-of-reference-key-in-string bounds) - (bibtex-end-of-reference-key-in-string bounds))) - completions))))) - (setq completions - (sort completions - (lambda(x y) - (string-lessp - (car x) - (car y))))) - (try-completion part-of-word completions)))) - (cond ((eq completion t) - (if complete-strings - ;; remove double-quotes or braces if field is no concatenation - (save-excursion - (bibtex-inside-field) - (let* ((bounds (bibtex-enclosing-field))) - (goto-char (bibtex-start-of-text-in-field bounds)) - (let ((boundaries (bibtex-parse-field-string))) - (if (and boundaries (equal (cdr boundaries) (bibtex-end-of-text-in-field bounds))) - (bibtex-remove-delimiters))))))) - ((not completion) - (error "Can't find completion for \"%s\"" part-of-word)) - ((not (string= part-of-word completion)) - (delete-region beg end) - (insert completion) - (if (and (assoc completion completions) - complete-strings) - ;; remove double-quotes or braces if field is no concatenation - (save-excursion - (bibtex-inside-field) - (let* ((bounds (bibtex-enclosing-field))) - (goto-char (bibtex-start-of-text-in-field bounds)) - (let ((boundaries (bibtex-parse-field-string))) - (if (and boundaries (equal (cdr boundaries) (bibtex-end-of-text-in-field bounds))) - (bibtex-remove-delimiters))))))) - (t - (message "Making completion list...") - (let ((list (all-completions part-of-word completions))) - (with-output-to-temp-buffer "*Completions*" - (display-completion-list list))) - (message "Making completion list...done"))))) - -(defun bibtex-do-auto-fill () - (let ((fill-prefix - (make-string - (+ bibtex-entry-offset bibtex-contline-indentation) ? ))) - (do-auto-fill))) - -(defun bibtex-pop (arg direction) - ;; generic function to be used by bibtex-pop-previous and bibtex-pop-next - (let (bibtex-help-message) - (bibtex-find-text nil)) - (save-excursion - ;; parse current field - (bibtex-inside-field) - (let* ((case-fold-search t) - (bounds (bibtex-enclosing-field)) - (start-old-text (bibtex-start-of-text-in-field bounds)) - (stop-old-text (bibtex-end-of-text-in-field bounds)) - (start-name (bibtex-start-of-name-in-field bounds)) - (stop-name (bibtex-end-of-name-in-field bounds)) - (new-text)) - (goto-char start-name) - ;; construct regexp for field with same name as this one, - ;; ignoring possible OPT's or ALT's - (let* ((field-name - (buffer-substring-no-properties - (if (looking-at "\\(OPT\\)\\|\\(ALT\\)") - (match-end 0) - (point)) - stop-name))) - ;; if executed several times in a row, start each search where - ;; the last one was finished - (cond ((eq last-command 'bibtex-pop) t) - (t - (bibtex-enclosing-entry-maybe-empty-head) - (setq - bibtex-pop-previous-search-point (match-beginning 0) - bibtex-pop-next-search-point (point)))) - (if (eq direction 'previous) - (goto-char bibtex-pop-previous-search-point) - (goto-char bibtex-pop-next-search-point)) - ;; Now search for arg'th previous/next similar field - (let ((bounds nil) - (failure nil)) - (while (and (not failure) (> arg 0)) - (cond ((eq direction 'previous) - (setq bounds (bibtex-search-backward-field field-name (point-min))) - (if bounds - (goto-char (bibtex-start-of-field bounds)) - (setq failure t))) - ((eq direction 'next) - (setq bounds (bibtex-search-forward-field field-name (point-max))) - (if bounds - (goto-char (bibtex-end-of-field bounds)) - (setq failure t)))) - (setq arg (- arg 1))) - (if failure - (error (if (eq direction 'previous) - "No previous matching BibTeX field." - "No next matching BibTeX field.")) - ;; Found a matching field. Remember boundaries. - (setq bibtex-pop-previous-search-point (bibtex-start-of-field bounds)) - (setq bibtex-pop-next-search-point (bibtex-end-of-field bounds)) - (setq new-text - (buffer-substring-no-properties - (bibtex-start-of-text-in-field bounds) - (bibtex-end-of-text-in-field bounds))) - (bibtex-flash-head) - ;; Go back to where we started, delete old text, and pop new. - (goto-char stop-old-text) - (delete-region start-old-text stop-old-text) - (insert new-text)))))) - (let (bibtex-help-message) - (bibtex-find-text nil)) - (setq this-command 'bibtex-pop)) - - -;; Interactive Functions: - -;;;###autoload -(defun bibtex-mode () - "Major mode for editing BibTeX files. - -To submit a problem report, enter \\[bibtex-submit-bug-report] from a -BibTeX mode buffer. This automatically sets up a mail buffer with -version information already added. You just need to add a description -of the problem, including a reproducible test case and send the -message. - - -General information on working with BibTeX mode: - -You should use commands 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 -in all desired fields in the entry, you should clean the new entry -with command \\[bibtex-clean-entry]. - -Some features of BibTeX mode are available only by setting variable -bibtex-maintain-sorted-entries to t. However, then BibTeX mode will -work with buffer containing only valid (syntactical correct) entries -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]. - -For third party BibTeX buffers, please call the function -`bibtex-convert-alien' to fully take advantage of all features of -BibTeX mode. - - -Special information: - -A command such as \\[bibtex-Book] will outline the fields for a BibTeX book entry. - -The optional fields start with the string OPT, and are thus ignored by BibTeX. -Alternatives from which only one is required start with the string ALT. -The OPT or ALT string may be removed from a field with \\[bibtex-remove-OPT-or-ALT]. -\\[bibtex-make-field] inserts a new field after the current one. -\\[bibtex-kill-field] kills the current field entirely. -\\[bibtex-yank] will yank the last recently killed field after the -current field. -\\[bibtex-remove-delimiters] removes the double-quotes or braces around the text of the current field. - \\[bibtex-empty-field] replaces the text of the current field with the default \"\" or {}. - -The command \\[bibtex-clean-entry] cleans the current entry, i.e. it removes OPT/ALT -from all non-empty optional or alternative fields, checks that no required -fields are empty, and does some formatting dependent on the value of -bibtex-entry-format. -Note: some functions in BibTeX mode depend on entries being in a special -format (all fields beginning on separate lines), so it is usually a bad -idea to remove `realign' from bibtex-entry-format. - -Use \\[bibtex-find-text] to position the cursor at the end of the current field. -Use \\[bibtex-next-field] to move to end of the next field. - -The following may be of interest as well: - - Functions: - bibtex-entry - bibtex-kill-entry - bibtex-yank-pop - bibtex-pop-previous - bibtex-pop-next - bibtex-complete-string - bibtex-complete-key - bibtex-print-help-message - bibtex-generate-autokey - bibtex-beginning-of-entry - bibtex-end-of-entry - bibtex-reposition-window - bibtex-mark-entry - bibtex-ispell-abstract - bibtex-ispell-entry - bibtex-narrow-to-entry - bibtex-sort-buffer - bibtex-validate - bibtex-count - bibtex-fill-entry - bibtex-reformat - bibtex-convert-alien - - Variables: - bibtex-field-delimiters - bibtex-include-OPTcrossref - bibtex-include-OPTkey - bibtex-user-optional-fields - bibtex-entry-format - bibtex-sort-ignore-string-entries - bibtex-maintain-sorted-entries - bibtex-entry-field-alist - bibtex-predefined-strings - bibtex-string-files - ---------------------------------------------------------- -Entry to BibTeX mode calls the value of `bibtex-mode-hook' if that value is -non-nil. - -\\{bibtex-mode-map}" - (interactive) - (kill-all-local-variables) - (use-local-map bibtex-mode-map) - (setq major-mode 'bibtex-mode) - (setq mode-name "BibTeX") - (set-syntax-table bibtex-mode-syntax-table) - (setq bibtex-strings bibtex-predefined-strings) - (mapcar - (lambda (filename) - ;; collect pathnames - (let* ((path (if bibtex-string-file-path - bibtex-string-file-path - ".")) - (dirs (split-string path ":+")) - (filename (if (string-match "\.bib$" filename) - filename - (concat filename ".bib"))) - fullfilename - (item 0) - (size (length dirs))) - ;; test filenames - (while (and - (< item size) - (not (file-readable-p - (setq fullfilename - (concat (elt dirs item) "/" filename))))) - (setq item (1+ item))) - (if (< item size) - ;; file was found - (let* ((case-fold-search t) - (compl nil)) - (with-temp-buffer - (insert-file-contents fullfilename) - (goto-char (point-min)) - (let ((bounds (bibtex-search-forward-string))) - (while bounds - (setq compl - (cons (list (buffer-substring-no-properties - (bibtex-start-of-reference-key-in-string bounds) - (bibtex-end-of-reference-key-in-string bounds))) - compl)) - (goto-char (bibtex-end-of-string bounds)) - (setq bounds (bibtex-search-forward-string))))) - (setq bibtex-strings (append bibtex-strings (nreverse compl)))) - (error - "File %s not in paths defined by bibtex-string-file-path variable" - filename)))) - bibtex-string-files) - (if bibtex-maintain-sorted-entries - (bibtex-run-with-idle-timer - 1 nil - (lambda () - (bibtex-parse-keys nil t t)))) - ;; to get buffer parsed once if everything else (including things - ;; installed in bibtex-mode-hook) has done its work - (if (not bibtex-parse-idle-timer) - (setq bibtex-parse-idle-timer - (bibtex-run-with-idle-timer - bibtex-parse-keys-timeout t - 'bibtex-parse-buffers-stealthily))) - ;; Install stealthy parse function if not already installed - (make-local-variable 'paragraph-start) - (setq paragraph-start "[ \f\n\t]*$") - (make-local-variable 'comment-start) - (setq comment-start bibtex-comment-start) - (make-local-variable 'comment-start-skip) - (setq comment-start-skip bibtex-comment-start) - (make-local-variable 'comment-column) - (setq comment-column 0) - (make-local-variable 'defun-prompt-regexp) - (setq defun-prompt-regexp "^@[a-zA-Z0-9]+") - (make-local-variable 'outline-regexp) - (setq outline-regexp "@") - (make-local-variable 'normal-auto-fill-function) - (setq normal-auto-fill-function 'bibtex-do-auto-fill) - (make-local-variable 'font-lock-defaults) - (setq font-lock-defaults - '(bibtex-font-lock-keywords - nil t ((?$ . "\"") - ;; Mathematical expressions should be fontified as strings - (?\" . ".") - ;; Quotes are field delimiters and quote-delimited - ;; entries should be fontified in the same way as - ;; brace-delimited ones - ))) - (make-local-variable 'font-lock-mark-block-function) - (setq font-lock-mark-block-function - (lambda () - (set-mark (bibtex-end-of-entry)) - (bibtex-beginning-of-entry))) - (setq imenu-generic-expression - (list (list nil bibtex-entry-head bibtex-key-in-head))) - (setq imenu-case-fold-search t) - ;; XEmacs needs easy-menu-add, Emacs does not care - (easy-menu-add bibtex-edit-menu) - (easy-menu-add bibtex-entry-menu) - (run-hooks 'bibtex-mode-hook)) - -(defun bibtex-submit-bug-report () - "Submit via mail a bug report on bibtex.el." - (interactive) - (if (y-or-n-p "Do you want to submit a bug report on BibTeX mode? ") - (progn - (require 'reporter) - (let ((reporter-prompt-for-summary-p t)) - (reporter-submit-bug-report - bibtex-maintainer-address - "bibtex.el" - (list - 'system-configuration - 'system-configuration-options - 'bibtex-mode-hook - 'bibtex-parse-keys-timeout - ;; possible general errors - 'bibtex-sort-ignore-string-entries - 'bibtex-maintain-sorted-entries - 'bibtex-entry-delimiters - 'bibtex-field-delimiters - 'bibtex-comma-after-last-field - 'bibtex-entry-offset - 'bibtex-field-indentation - 'bibtex-text-indentation - 'bibtex-contline-indentation - 'bibtex-align-at-equal-sign - ;; possible sorting and parsing bugs - 'bibtex-entry-format - 'bibtex-add-entry-hook - 'bibtex-clean-entry-hook - ;; possible cleaning error - 'bibtex-user-optional-fields - ;; possible format error - 'bibtex-predefined-month-strings - 'bibtex-predefined-strings - 'bibtex-string-files - 'bibtex-string-file-path - ;; possible format error - 'bibtex-font-lock-keywords - ;; possible bugs regarding fontlocking - 'bibtex-autokey-prefix-string - 'bibtex-autokey-names - 'bibtex-autokey-names-stretch - 'bibtex-autokey-additional-names - 'bibtex-autokey-transcriptions - 'bibtex-autokey-name-change-strings - 'bibtex-autokey-name-case-convert - 'bibtex-autokey-name-length - 'bibtex-autokey-name-separator - 'bibtex-autokey-year-length - 'bibtex-autokey-year-use-crossref-entry - 'bibtex-autokey-titlewords - 'bibtex-autokey-title-terminators - 'bibtex-autokey-titlewords-stretch - 'bibtex-autokey-titleword-ignore - 'bibtex-autokey-titleword-case-convert - 'bibtex-autokey-titleword-abbrevs - 'bibtex-autokey-titleword-change-strings - 'bibtex-autokey-titleword-length - 'bibtex-autokey-titleword-separator - 'bibtex-autokey-name-year-separator - 'bibtex-autokey-year-title-separator - 'bibtex-autokey-edit-before-use - 'bibtex-autokey-before-presentation-function - ;; possible bugs regarding automatic reference keys - 'bibtex-entry-field-alist - ;; possible format error - 'bibtex-help-message - 'bibtex-include-OPTcrossref - 'bibtex-include-OPTkey - 'bibtex-field-kill-ring-max - 'bibtex-entry-kill-ring-max - ;; user variables which shouldn't cause any errors - ) - nil nil - (concat bibtex-maintainer-salutation " - -I want to report a bug on Emacs BibTeX mode. - -I've read the `Bugs' section in the `Emacs' info page, so I know how -to make a clear and unambiguous report. I have started a fresh Emacs -via `"invocation-name " --no-init-file --no-site-file', thereafter (in -case I'm reporting on a version of `bibtex.el' which is not part of -the standard emacs distribution) I loaded the questionable version -of `bibtex.el' with `M-x load-file', and then, to produce the buggy -behaviour, I did the following:"))) - (message nil)))) - -(defun bibtex-entry (entry-type) - "Insert a new BibTeX entry. -After insertion it calls the functions in `bibtex-add-entry-hook'." - (interactive (let* ((completion-ignore-case t) - (e-t (completing-read - "Entry Type: " - bibtex-entry-field-alist - nil t nil 'bibtex-entry-type-history))) - (list e-t))) - (if (not bibtex-reference-keys) - (bibtex-parse-keys nil t)) - (let* (required - optional - (key - (if bibtex-maintain-sorted-entries - (completing-read - (format "%s key: " entry-type) - bibtex-reference-keys nil nil nil 'bibtex-key-history))) - (e (assoc-ignore-case entry-type bibtex-entry-field-alist)) - (r-n-o (elt e 1)) - (c-ref (elt e 2))) - (if (not e) - (error "Bibtex entry type %s not defined" entry-type)) - (if (and - (member entry-type bibtex-include-OPTcrossref) - c-ref) - (setq required (elt c-ref 0) - optional (elt c-ref 1)) - (setq required (elt r-n-o 0) - optional (elt r-n-o 1))) - (if bibtex-maintain-sorted-entries - (bibtex-find-entry-location key) - (bibtex-move-outside-of-entry)) - (indent-to-column bibtex-entry-offset) - (insert "@" entry-type (bibtex-entry-left-delimiter)) - (if key - (insert key)) - (save-excursion - (mapcar 'bibtex-make-field required) - (if (member entry-type bibtex-include-OPTcrossref) - (bibtex-make-optional-field '("crossref"))) - (if bibtex-include-OPTkey - (if (or - (stringp bibtex-include-OPTkey) - (fboundp bibtex-include-OPTkey)) - (bibtex-make-optional-field - (list "key" nil bibtex-include-OPTkey)) - (bibtex-make-optional-field '("key")))) - (mapcar 'bibtex-make-optional-field optional) - (mapcar 'bibtex-make-optional-field bibtex-user-optional-fields) - (if bibtex-comma-after-last-field - (insert ",")) - (insert "\n") - (indent-to-column bibtex-entry-offset) - (insert (bibtex-entry-right-delimiter) "\n\n")) - (bibtex-next-field t) - (run-hooks 'bibtex-add-entry-hook))) - -(defun bibtex-print-help-message () - "Prints helpful information about current field in current BibTeX entry." - (interactive) - (let* ((case-fold-search t) - (pnt (point)) - (field-name - (let* ((bounds (bibtex-enclosing-field)) - (mb (bibtex-start-of-name-in-field bounds)) - (me (bibtex-end-of-name-in-field bounds))) - (goto-char mb) - (buffer-substring-no-properties - (if (looking-at "OPT\\|ALT") - (+ 3 mb) - mb) - me))) - (entry-type - (progn - (re-search-backward - bibtex-entry-maybe-empty-head nil t) - (buffer-substring-no-properties - (1+ (match-beginning bibtex-type-in-head)) - (match-end bibtex-type-in-head)))) - (entry-list - (assoc-ignore-case entry-type - bibtex-entry-field-alist)) - (c-r-list (elt entry-list 2)) - (req-opt-list - (if (and - (member entry-type bibtex-include-OPTcrossref) - c-r-list) - c-r-list - (elt entry-list 1))) - (list-of-entries (append - (elt req-opt-list 0) - (elt req-opt-list 1) - bibtex-user-optional-fields - (if (member - entry-type - bibtex-include-OPTcrossref) - '(("crossref" - "Reference key of the crossreferenced entry"))) - (if bibtex-include-OPTkey - '(("key" - "Used for reference key creation if author and editor fields are missing")))))) - (goto-char pnt) - (let ((comment (assoc-ignore-case field-name list-of-entries))) - (if comment - (message (elt comment 1)) - (message "NO COMMENT AVAILABLE"))))) - -(defun bibtex-make-field (e-t &optional called-by-yank) - "Makes a field named E-T in current BibTeX entry. -This function is for interactive and non-interactive purposes. To call -it interactively, just give it no arguments and enter the field name -using the minibuffer." - (interactive "*P") - (if (not e-t) - (setq - e-t - (let* ((entry-type - (save-excursion - (bibtex-enclosing-entry-maybe-empty-head) - (buffer-substring-no-properties - (1+ (match-beginning bibtex-type-in-head)) - (match-end bibtex-type-in-head)))) - (fl - (car (cdr (assoc-ignore-case - entry-type bibtex-entry-field-alist)))) - (field-list - (append - (elt fl 0) (elt fl 1) bibtex-user-optional-fields - (if bibtex-include-OPTcrossref '(("crossref" nil))) - (if bibtex-include-OPTkey '(("key" nil))))) - (completion-ignore-case t)) - (completing-read - "BibTeX field name: " field-list - nil nil nil bibtex-field-history)))) - (if (not (consp e-t)) - (setq e-t (list e-t))) - (if (equal (length e-t) 1) - (setq e-t (append e-t (list "")))) - (if (equal (length e-t) 2) - (setq e-t (append e-t (list "")))) - (let ((name (if (elt e-t 3) - (concat "ALT" (car e-t)) - (car e-t)))) - (if (or (interactive-p) called-by-yank) - (let (bibtex-help-message) - (bibtex-find-text nil t) - (if (looking-at "[}\"]") - (forward-char)))) - (insert ",\n") - (indent-to-column - (+ bibtex-entry-offset bibtex-field-indentation)) - (insert name " ") - (if bibtex-align-at-equal-sign - (indent-to-column - (+ bibtex-entry-offset (- bibtex-text-indentation 2)))) - (insert "= ") - (if (not bibtex-align-at-equal-sign) - (indent-to-column - (+ bibtex-entry-offset bibtex-text-indentation))) - (insert (if called-by-yank - "" - (bibtex-field-left-delimiter)) - (let ((init (elt e-t 2))) - (cond - ((stringp init) - init) - ((fboundp init) - (funcall init)) - (t - (error "%s is neither a string nor a function" init)))) - (if called-by-yank - "" - (bibtex-field-right-delimiter))) - (if (interactive-p) - (forward-char -1)))) - -(defun bibtex-beginning-of-entry () - "Move to beginning of BibTeX entry. -If inside an entry, move to the beginning of it, otherwise move to the -beginning of the previous entry. -If called from a program, this function returns the new location of point." - (interactive) - (skip-chars-forward " \t") - (if (looking-at "@") - (forward-char)) - (re-search-backward "^[ \t]*@" nil 'move)) - -(defun bibtex-end-of-entry () - "Move to end of BibTeX entry. -If inside an entry, move to the end of it, otherwise move to the end -of the previous entry. -If called from a program, this function returns the new location of point." - (interactive) - (let* ((case-fold-search t) - (valid-entry-head - (concat "[ \t]*@[ \t]*\\(" - (mapconcat - (lambda (type) - (concat "\\(" (car type) "\\)")) - bibtex-entry-field-alist - "\\|") - "\\)")) - (org (point)) - (pnt (bibtex-beginning-of-entry)) - err) - (cond - ((bibtex-parse-string) - (let ((bounds (bibtex-parse-string))) - (goto-char (bibtex-end-of-string bounds)))) - ((looking-at "[ \t]*@[ \t]*preamble[ \t\n]*") - (goto-char (match-end 0)) - (cond - ((looking-at "(") - (if (not (re-search-forward ")[ \t]*\n\n" nil 'move)) - (setq err t))) - ((looking-at "{") - (if (not (re-search-forward "}[ \t]*\n\n" nil 'move)) - (setq err t))) - (t - (setq err t))) - (if (not err) - (progn - (goto-char (match-beginning 0)) - (forward-char)))) - ((looking-at valid-entry-head) - (bibtex-search-entry t nil t) - (if (not (equal (match-beginning 0) pnt)) - (setq err t))) - (t - (if (interactive-p) - (message "Not on a known BibTeX entry.")) - (goto-char org))) - (if err - (progn - (goto-char pnt) - (error "Syntactical incorrect entry starts here")))) - (point)) - -(defun bibtex-reposition-window (arg) - "Make the current BibTeX entry visible." - (interactive "P") - (save-excursion - (goto-char - (/ (+ (bibtex-beginning-of-entry) (bibtex-end-of-entry)) 2)) - (recenter arg))) - -(defun bibtex-mark-entry () - "Put mark at beginning, point at end of current BibTeX entry." - (interactive) - (set-mark (bibtex-beginning-of-entry)) - (bibtex-end-of-entry)) - -(defun bibtex-count-entries (&optional count-string-entries) - "Count number of entries in current buffer or region. -With prefix argument COUNT-STRING-ENTRIES it counts all entries, -otherwise it counts all except Strings. -If mark is active it counts entries in region, if not in whole buffer." - (interactive "P") - (let ((pnt (point)) - (start-point - (if (bibtex-mark-active) - (region-beginning) - (bibtex-beginning-of-first-entry))) - (end-point - (if (bibtex-mark-active) - (region-end) - (point-max))) - (number 0) - (bibtex-sort-ignore-string-entries - (not count-string-entries))) - (save-restriction - (narrow-to-region start-point end-point) - (goto-char start-point) - (bibtex-map-entries - (lambda (current) - (setq number (1+ number))))) - (message (concat (if (bibtex-mark-active) "Region" "Buffer") - " contains %d entries.") number) - (goto-char pnt))) - -(defun bibtex-ispell-entry () - "Spell whole BibTeX entry." - (interactive) - (ispell-region (bibtex-beginning-of-entry) (bibtex-end-of-entry))) - -(defun bibtex-ispell-abstract () - "Spell abstract of BibTeX entry." - (interactive) - (let* ((case-fold-search t) - (pnt (bibtex-end-of-entry))) - (bibtex-beginning-of-entry) - (let ((bounds (bibtex-search-forward-field "abstract" pnt))) - (if bounds - (ispell-region (bibtex-start-of-text-in-field bounds) (bibtex-end-of-text-in-field bounds)) - (error "No abstract in entry"))))) - -(defun bibtex-narrow-to-entry () - "Narrow buffer to current BibTeX entry." - (interactive) - (save-excursion - (narrow-to-region - (bibtex-beginning-of-entry) (bibtex-end-of-entry)))) - -(defun bibtex-sort-buffer () - "Sort BibTeX buffer alphabetically by key. -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 - (narrow-to-region - (bibtex-beginning-of-first-entry) - (save-excursion - (goto-char (point-max)) - (bibtex-end-of-entry))) - (bibtex-skip-to-valid-entry) - (sort-subr - nil - ;; NEXTREC function - 'bibtex-skip-to-valid-entry - ;; ENDREC function - 'bibtex-end-of-entry - ;; STARTKEY function - (lambda () - (let* ((case-fold-search t)) - (re-search-forward bibtex-entry-head) - (buffer-substring-no-properties - (match-beginning bibtex-key-in-head) - (match-end bibtex-key-in-head))))))) - -(defun bibtex-find-entry-location (entry-name &optional ignore-dups) - "Looking for place to put the BibTeX entry named ENTRY-NAME. -Performs a binary search (therefore, buffer is assumed to be in sorted -order, without duplicates (see \\[bibtex-validate]), if it is -not, `bibtex-find-entry-location' will fail). If entry-name is already -used as a reference key, an error is signaled. However, if optional -variable IGNORE-DUPS is non-nil, no error messages about duplicate -entries are signaled, but the error handling is assumed to be made in -the calling function. -The value is nil if a duplicate entry error occurred, -and t in all other cases." - (let* ((case-fold-search t) - (left - (progn - (bibtex-beginning-of-first-entry) - (bibtex-skip-to-valid-entry) - (bibtex-end-of-entry))) - (right - (progn - (bibtex-beginning-of-last-entry) - (bibtex-skip-to-valid-entry t) - (point))) - actual-point - actual-key - (done (>= left right)) - new - dup) - (while (not done) - (setq actual-point (/ (+ left right) 2)) - (goto-char actual-point) - (bibtex-skip-to-valid-entry t) - (setq actual-key - (progn - (re-search-forward bibtex-entry-head) - (buffer-substring-no-properties - (match-beginning bibtex-key-in-head) - (match-end bibtex-key-in-head)))) - (cond - ((string-lessp entry-name actual-key) - (setq new (bibtex-beginning-of-entry)) - (if (equal right new) - (setq done t) - (setq right new))) - ((string-lessp actual-key entry-name) - (setq new (bibtex-end-of-entry)) - (if (equal left new) - (setq done t) - (setq left new))) - ((string-equal actual-key entry-name) - (setq dup t - done t) - (if (not ignore-dups) - (progn - (bibtex-beginning-of-entry) - (error "Entry with key `%s' already exists" entry-name)))))) - (if dup - (progn - (bibtex-beginning-of-entry) - nil) - (goto-char right) - (setq actual-key - (if (looking-at bibtex-entry-head) - (buffer-substring-no-properties - (match-beginning bibtex-key-in-entry) - (match-end bibtex-key-in-entry)))) - (if (or - (not actual-key) - (string-lessp actual-key entry-name)) - ;; buffer contains no valid entries or - ;; greater than last entry --> append - (progn - (bibtex-end-of-entry) - (if (not (bobp)) - (newline (forward-line 2))) - (beginning-of-line)) - (goto-char right)) - t))) - -(defun bibtex-validate (&optional test-thoroughly) - "Validate if buffer or region is syntactically correct. -Only known entry types are checked, so you can put comments -outside of entries. -With optional argument TEST-THOROUGHLY non-nil it checks for absence of -required fields and questionable month fields as well. -If mark is active, it validates current region, if not whole buffer. -Returns t if test was successful, nil otherwise." - (interactive "P") - (let* (error-list - syntax-error - (case-fold-search t) - (valid-bibtex-entry - (concat - "@[ \t]*\\(\\(string\\)\\|" - (mapconcat - (lambda (type) - (concat "\\(" (car type) "\\)")) - bibtex-entry-field-alist - "\\|") - "\\)")) - (pnt (point)) - (start-point - (if (bibtex-mark-active) - (region-beginning) - (bibtex-beginning-of-first-entry))) - (end-point - (if (bibtex-mark-active) - (region-end) - (point-max)))) - (save-restriction - (narrow-to-region start-point end-point) - ;; looking if entries fit syntactical structure - (goto-char start-point) - (bibtex-progress-message "Checking syntactical structure") - (while (re-search-forward "^[ \t]*@" nil t) - (bibtex-progress-message) - (forward-char -1) - (let ((p (point)) - (must-match - (looking-at valid-bibtex-entry))) - (if (not must-match) - (forward-char) - (let (bibtex-sort-ignore-string-entries) - (bibtex-skip-to-valid-entry)) - (if (equal (point) p) - (forward-char) - (goto-char p) - (setq - error-list - (cons (list - (bibtex-current-line) - "Syntax error (check esp. commas, braces, and quotes)") - error-list)) - (forward-char))))) - (bibtex-progress-message 'done) - (if error-list - (setq syntax-error t) - ;; looking for correct sort order and duplicates (only if - ;; there were no syntax errors) - (if bibtex-maintain-sorted-entries - (let (previous) - (goto-char start-point) - (bibtex-progress-message "Checking correct sort order") - (bibtex-map-entries - (lambda (current) - (bibtex-progress-message) - (cond ((or (not previous) - (string< previous current)) - (setq previous current)) - ((string-equal previous current) - (setq - error-list - (cons (list (bibtex-current-line) - "Duplicate key with previous") - error-list))) - (t - (setq previous current - error-list - (cons (list (bibtex-current-line) - "Entries out of order") - error-list)))))) - (bibtex-progress-message 'done))) - (if test-thoroughly - (progn - (goto-char start-point) - (bibtex-progress-message - "Checking required fields and month fields") - (let ((bibtex-sort-ignore-string-entries t) - (questionable-month - (concat - "[{\"]\\(" - (mapconcat - (lambda (mon) - (concat "\\(" (car mon) "\\)")) - bibtex-predefined-month-strings - "\\|") - "\\)[}\"]"))) - (bibtex-map-entries - (lambda (current) - (bibtex-progress-message) - (let* ((beg (bibtex-beginning-of-entry)) - (end (bibtex-end-of-entry)) - (entry-list - (progn - (goto-char beg) - (bibtex-search-entry nil end) - (assoc-ignore-case - (buffer-substring-no-properties - (1+ (match-beginning bibtex-type-in-head)) - (match-end bibtex-type-in-head)) - bibtex-entry-field-alist))) - (req (copy-sequence (elt (elt entry-list 1) 0))) - (creq (copy-sequence (elt (elt entry-list 2) 0))) - crossref-there) - (goto-char beg) - (let ((bounds (bibtex-search-forward-field bibtex-field-name end))) - (while bounds - (let ((field-name - (buffer-substring-no-properties - (bibtex-start-of-name-in-field bounds) - (bibtex-end-of-name-in-field bounds)))) - (if (and (equal (downcase field-name) "month") - (string-match - questionable-month - (buffer-substring-no-properties - (bibtex-start-of-text-in-field bounds) - (bibtex-end-of-text-in-field bounds)))) - (setq - error-list - (cons - (list - (bibtex-current-line) - "Questionable month field (delimited string)") - error-list))) - (setq - req - (delete (assoc-ignore-case field-name req) req) - creq - (delete (assoc-ignore-case field-name creq) creq)) - (if (equal (downcase field-name) "crossref") - (setq crossref-there t))) - (goto-char (bibtex-end-of-field bounds)) - (setq bounds (bibtex-search-forward-field bibtex-field-name end)))) - (if crossref-there - (setq req creq)) - (if (or (> (length req) 1) - (and (= (length req) 1) - (not (elt (car req) 3)))) - ;; two (or more) fields missed or one field - ;; missed and this isn't flagged alternative - ;; (notice that this fails if there are more - ;; than two alternatives in a BibTeX entry, - ;; which isn't the case momentarily) - (setq - error-list - (cons - (list (save-excursion - (bibtex-beginning-of-entry) - (bibtex-current-line)) - (concat - "Required field \"" - (car (car req)) - "\" missing")) - error-list))))))) - (bibtex-progress-message 'done))))) - (goto-char pnt) - (if error-list - (let ((bufnam (buffer-name)) - (dir default-directory)) - (setq error-list - (sort error-list - (lambda (a b) - (< (car a) (car b))))) - (let ((pop-up-windows t)) - (pop-to-buffer nil t)) - (switch-to-buffer - (get-buffer-create "*BibTeX validation errors*") t) - ;; don't use switch-to-buffer-other-window, since this - ;; doesn't allow the second parameter NORECORD - (setq default-directory dir) - (toggle-read-only -1) - (compilation-mode) - (delete-region (point-min) (point-max)) - (goto-char (point-min)) - (insert - "BibTeX mode command `bibtex-validate'\n" - (if syntax-error - "Maybe undetected errors due to syntax errors. Correct and validate again." - "") - "\n") - (while error-list - (insert - bufnam ":" (number-to-string (elt (car error-list) 0)) - ": " (elt (car error-list) 1) "\n") - (setq error-list (cdr error-list))) - (compilation-parse-errors nil nil) - (setq compilation-old-error-list compilation-error-list) - ;; this is necessary to avoid reparsing of buffer if you - ;; switch to compilation buffer and enter - ;; `compile-goto-error' - (set-buffer-modified-p nil) - (toggle-read-only 1) - (goto-char (point-min)) - (other-window -1) - ;; return nil - nil) - (if (bibtex-mark-active) - (message "Region is syntactically correct") - (message "Buffer is syntactically correct")) - t))) - -(defun bibtex-next-field (arg) - "Finds end of text of next BibTeX field; with ARG, to its beginning." - (interactive "P") - (bibtex-inside-field) - (let ((start (point))) - (condition-case () - (let ((bounds (bibtex-enclosing-field))) - (goto-char (bibtex-end-of-field bounds)) - (forward-char 2)) - (error - (goto-char start) - (end-of-line) - (forward-char)))) - (bibtex-find-text arg t)) - -(defun bibtex-find-text (arg &optional as-if-interactive silent) - "Go to end of text of current field; with ARG, go to beginning." - (interactive "P") - (bibtex-inside-field) - (let ((bounds (bibtex-enclosing-field (or (interactive-p) as-if-interactive)))) - (if bounds - (progn - (if arg - (progn - (goto-char (bibtex-start-of-text-in-field bounds)) - (if (looking-at "[{\"]") - (forward-char))) - (goto-char (bibtex-end-of-text-in-field bounds)) - (if (or - (= (preceding-char) ?}) - (= (preceding-char) ?\")) - (forward-char -1))) - (if bibtex-help-message - (bibtex-print-help-message))) - (beginning-of-line) - (cond - ((bibtex-parse-string) - (let ((bounds (bibtex-parse-string))) - (goto-char - (if arg - (bibtex-start-of-text-in-string bounds) - (bibtex-end-of-text-in-string bounds))))) - ((looking-at bibtex-entry-maybe-empty-head) - (goto-char - (if arg - (match-beginning bibtex-key-in-head) - (match-end 0)))) - (t - (if (not silent) - (error "Not on BibTeX field"))))))) - -(defun bibtex-remove-OPT-or-ALT () - "Removes the string starting optional/alternative fields. -Aligns text and goes thereafter to end of text." - (interactive) - (bibtex-inside-field) - (let* ((case-fold-search t) - (bounds (bibtex-enclosing-field))) - (save-excursion - (goto-char (bibtex-start-of-name-in-field bounds)) - (if (looking-at "OPT\\|ALT") - (progn - (delete-char (length "OPT")) - ;; make field non-OPT - (search-forward "=") - (forward-char -1) - (delete-horizontal-space) - (if bibtex-align-at-equal-sign - (indent-to-column (- bibtex-text-indentation 2)) - (insert " ")) - (search-forward "=") - (delete-horizontal-space) - (if bibtex-align-at-equal-sign - (insert " ") - (indent-to-column bibtex-text-indentation))))) - (bibtex-inside-field))) - -(defun bibtex-remove-delimiters () - "Removes \"\" or {} around string." - (interactive) - (save-excursion - (bibtex-inside-field) - (let* ((case-fold-search t) - (bounds (bibtex-enclosing-field)) - (stop (copy-marker (bibtex-end-of-text-in-field bounds)))) - (goto-char (bibtex-start-of-text-in-field bounds)) - (let* ((boundaries (bibtex-search-forward-field-string stop))) - (while boundaries - (let ((text-end (copy-marker (cdr boundaries)))) - (goto-char (car boundaries)) - (delete-char 1) - (goto-char text-end) - (delete-backward-char 1) - (setq boundaries (bibtex-search-forward-field-string stop)))))))) - -(defun bibtex-kill-field (&optional copy-only) - "Kills the entire enclosing BibTeX field. -With prefix arg COPY-ONLY, copy the current field to `bibtex-field-kill-ring,' -but do not actually kill it." - (interactive "P") - (let* ((pnt (point)) - (case-fold-search t)) - (bibtex-inside-field) - (let* ((bounds (bibtex-enclosing-field)) - (the-end (bibtex-end-of-field bounds)) - (the-beginning (bibtex-start-of-field bounds))) - (goto-char the-end) - (skip-chars-forward " \t\n,") - (setq - bibtex-field-kill-ring - (cons - (list - 'field - (buffer-substring-no-properties - (bibtex-start-of-name-in-field bounds) - (bibtex-end-of-name-in-field bounds)) - (buffer-substring-no-properties - (bibtex-start-of-text-in-field bounds) - (bibtex-end-of-text-in-field bounds))) - bibtex-field-kill-ring)) - (if (> (length bibtex-field-kill-ring) bibtex-field-kill-ring-max) - (setcdr - (nthcdr (1- bibtex-field-kill-ring-max) bibtex-field-kill-ring) - nil)) - (setq bibtex-field-kill-ring-yank-pointer bibtex-field-kill-ring) - (if copy-only - (goto-char pnt) - (delete-region the-beginning the-end) - (let (bibtex-help-message) - (bibtex-find-text nil t t))))) - (setq bibtex-last-kill-command 'field)) - -(defun bibtex-copy-field-as-kill () - (interactive) - (bibtex-kill-field t)) - -(defun bibtex-kill-entry (&optional copy-only) - "Kill the entire enclosing BibTeX entry. -With prefix arg COPY-ONLY the current entry to -`bibtex-entry-kill-ring', but do not actually kill it." - (interactive "P") - (let* ((pnt (point)) - (case-fold-search t) - (beg (bibtex-beginning-of-entry)) - (end - (progn - (bibtex-end-of-entry) - (if (re-search-forward - bibtex-entry-maybe-empty-head nil 'move) - (goto-char (match-beginning 0))) - (point)))) - (setq - bibtex-entry-kill-ring - (cons - (list 'entry (buffer-substring-no-properties beg end)) - bibtex-entry-kill-ring)) - (if (> (length bibtex-entry-kill-ring) bibtex-entry-kill-ring-max) - (setcdr - (nthcdr (1- bibtex-entry-kill-ring-max) bibtex-entry-kill-ring) - nil)) - (setq bibtex-entry-kill-ring-yank-pointer bibtex-entry-kill-ring) - (if copy-only - (goto-char pnt) - (delete-region beg end))) - (setq bibtex-last-kill-command 'entry)) - -(defun bibtex-copy-entry-as-kill () - (interactive) - (bibtex-kill-entry t)) - -(defun bibtex-yank (&optional n) - "Reinsert the last BibTeX item. -More precisely, reinsert the field or entry killed or yanked most recently. -With argument N, reinsert the Nth most recently killed BibTeX item. -See also the command \\[bibtex-yank-pop]]." - (interactive "*p") - (bibtex-insert-current-kill (1- n)) - (setq this-command 'bibtex-yank)) - -(defun bibtex-yank-pop (n) - "Replace just-yanked killed BibTeX item with a different. -This command is allowed only immediately after a `bibtex-yank' or a -`bibtex-yank-pop'. -At such a time, the region contains a reinserted previously killed -BibTeX item. `bibtex-yank-pop' deletes that item and inserts in its -place a different killed BibTeX item. - -With no argument, the previous kill is inserted. -With argument N, insert the Nth previous kill. -If N is negative, this is a more recent kill. - -The sequence of kills wraps around, so that after the oldest one -comes the newest one." - (interactive "*p") - (if (not (eq last-command 'bibtex-yank)) - (error "Previous command was not a BibTeX yank")) - (setq this-command 'bibtex-yank) - (let ((inhibit-read-only t)) - (delete-region (point) (mark t)) - (bibtex-insert-current-kill n))) - -(defun bibtex-empty-field () - "Delete the text part of the current field, replace with empty text." - (interactive) - (bibtex-inside-field) - (let ((bounds (bibtex-enclosing-field))) - (goto-char (bibtex-start-of-text-in-field bounds)) - (delete-region (point) (bibtex-end-of-text-in-field bounds)) - (insert (concat (bibtex-field-left-delimiter) - (bibtex-field-right-delimiter)) ) - (bibtex-find-text t))) - -(defun bibtex-pop-previous (arg) - "Replace text of current field with the similar field in previous entry. -With arg, goes up ARG entries. Repeated, goes up so many times. May be -intermixed with \\[bibtex-pop-next] (bibtex-pop-next)." - (interactive "p") - (bibtex-pop arg 'previous)) - -(defun bibtex-pop-next (arg) - "Replace text of current field with the text of similar field in next entry. -With arg, goes down ARG entries. Repeated, goes down so many times. May be -intermixed with \\[bibtex-pop-previous] (bibtex-pop-previous)." - (interactive "p") - (bibtex-pop arg 'next)) - -(defun bibtex-clean-entry (&optional new-reference-key called-by-reformat) - "Finish editing the current BibTeX entry and clean it up. -Checks 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 only will 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 this on `string' or `preamble' entries. -At end of the cleaning process, the functions in -bibtex-clean-entry-hook are called with region narrowed to entry." - (interactive "P") - (bibtex-format-entry) - (let* ((case-fold-search t) - (eob (bibtex-end-of-entry)) - (key (progn - (bibtex-beginning-of-entry) - (if (re-search-forward - bibtex-entry-head eob t) - (buffer-substring-no-properties - (match-beginning bibtex-key-in-head) - (match-end bibtex-key-in-head)))))) - (if (or - new-reference-key - (not key)) - (progn - (let ((autokey - (if bibtex-autokey-edit-before-use - (read-from-minibuffer - "Key to use: " (bibtex-generate-autokey) nil nil - 'bibtex-key-history) - (bibtex-generate-autokey)))) - (bibtex-beginning-of-entry) - (re-search-forward bibtex-entry-maybe-empty-head) - (if (match-beginning bibtex-key-in-head) - (delete-region (match-beginning bibtex-key-in-head) - (match-end bibtex-key-in-head))) - (insert autokey) - (let* ((start (bibtex-beginning-of-entry)) - (end (progn - (bibtex-end-of-entry) - (if (re-search-forward - bibtex-entry-maybe-empty-head nil 'move) - (goto-char (match-beginning 0))) - (point))) - (entry (buffer-substring start end))) - (delete-region start end) - (let ((success - (or - called-by-reformat - (not bibtex-maintain-sorted-entries) - (bibtex-find-entry-location autokey t)))) - (insert entry) - (forward-char -1) - (bibtex-beginning-of-entry) - (re-search-forward bibtex-entry-head) - (if (not success) - (error - "New inserted entry yields duplicate key")))))))) - (if (not called-by-reformat) - (save-excursion - (save-restriction - (narrow-to-region - (bibtex-beginning-of-entry) (bibtex-end-of-entry)) - (bibtex-parse-keys t nil) - (run-hooks 'bibtex-clean-entry-hook))))) - -(defun bibtex-fill-entry () - "Fill current entry. -Realigns entry, so that every field starts on a separate line. Field -names appear in column `bibtex-field-indentation', field text starts in -column `bibtex-text-indentation' and continuation lines start here, too. -If `bibtex-align-at-equal-sign' is non-nil, align equal signs also." - (interactive "*") - (let ((pnt (copy-marker (point))) - (end (copy-marker (bibtex-end-of-entry)))) - (bibtex-beginning-of-entry) - (bibtex-delete-whitespace) - (indent-to-column bibtex-entry-offset) - (let ((bounds (bibtex-search-forward-field bibtex-field-name end))) - (while bounds - (let* ((begin-field (copy-marker (bibtex-start-of-field bounds))) - (end-field (copy-marker (bibtex-end-of-field bounds))) - (begin-name (copy-marker (bibtex-start-of-name-in-field bounds))) - (end-name (copy-marker (bibtex-end-of-name-in-field bounds)))) - (goto-char begin-field) - (forward-char) - (bibtex-delete-whitespace) - (open-line 1) - (forward-char) - (indent-to-column - (+ bibtex-entry-offset bibtex-field-indentation)) - (re-search-forward "[ \t\n]*=" end) - (replace-match "=") - (forward-char -1) - (if bibtex-align-at-equal-sign - (indent-to-column - (+ bibtex-entry-offset (- bibtex-text-indentation 2))) - (insert " ")) - (forward-char) - (bibtex-delete-whitespace) - (if bibtex-align-at-equal-sign - (insert " ") - (indent-to-column bibtex-text-indentation)) - (while (re-search-forward "[ \t\n]+" end-field 'move) - (replace-match " ")) - (bibtex-do-auto-fill) - (goto-char end-field)) - (setq bounds (bibtex-search-forward-field bibtex-field-name end)))) - (if (looking-at ",") - (forward-char)) - (bibtex-delete-whitespace) - (open-line 1) - (forward-char) - (indent-to-column bibtex-entry-offset) - (goto-char pnt))) - -(defun bibtex-reformat (&optional additional-options called-by-convert-alien) - "Reformat all BibTeX entries in buffer or region. -With prefix argument, read options for reformatting from minibuffer. -With \\[universal-argument] \\[universal-argument] prefix argument, reuse previous answers (if any) again. -If mark is active it reformats entries in region, if not in whole buffer." - (interactive "*P") - (let* ((pnt (point)) - (use-previous-options - (and (equal (prefix-numeric-value additional-options) 16) - (or bibtex-reformat-previous-options - bibtex-reformat-previous-reference-keys))) - (bibtex-entry-format - (if additional-options - (if use-previous-options - bibtex-reformat-previous-options - (setq - bibtex-reformat-previous-options - (delq - nil - (list - (if (or - called-by-convert-alien - (y-or-n-p - "Realign entries (recommended for files not created by BibTeX mode)? ")) - 'realign) - (if (y-or-n-p - "Remove empty optional and alternative fields? ") - 'opts-or-alts) - (if (y-or-n-p - "Remove delimiters around pure numerical fields? ") - 'numerical-fields) - (if (y-or-n-p (concat - (if bibtex-comma-after-last-field - "Insert" - "Remove") - " comma at end of entry? ")) - 'last-comma) - (if (y-or-n-p - "Replace double page dashes by single ones? ") - 'page-dashes) - (if (y-or-n-p - "Force delimiters? ") - 'delimiters) - (if (y-or-n-p - "Unify case of entry types and field names? ") - 'unify-case))))) - '(realign))) - (reformat-reference-keys - (if additional-options - (if use-previous-options - bibtex-reformat-previous-reference-keys - (setq - bibtex-reformat-previous-reference-keys - (y-or-n-p "Generate new reference keys automatically? "))))) - bibtex-autokey-edit-before-use - (bibtex-sort-ignore-string-entries t) - (start-point - (if (bibtex-mark-active) - (region-beginning) - (progn - (bibtex-beginning-of-first-entry) - (bibtex-skip-to-valid-entry) - (point)))) - (end-point - (if (bibtex-mark-active) - (region-end) - (point-max))) - (valid-bibtex-entry - (concat - "[ \t\n]+\\(@[ \t]*\\(" - (mapconcat - (lambda (type) - (concat "\\(" (car type) "\\)")) - bibtex-entry-field-alist - "\\|") - "\\)\\)"))) - (save-restriction - (narrow-to-region start-point end-point) - (if (memq 'realign bibtex-entry-format) - (progn - (goto-char (point-min)) - (while (re-search-forward valid-bibtex-entry nil t) - (replace-match "\n\\1")))) - (goto-char start-point) - (bibtex-progress-message "Formatting" 1) - (bibtex-map-entries - (lambda (current) - (bibtex-progress-message) - (bibtex-clean-entry reformat-reference-keys reformat-reference-keys) - (if (memq 'realign bibtex-entry-format) - (progn - (bibtex-end-of-entry) - (bibtex-delete-whitespace) - (open-line 2))))) - (bibtex-progress-message 'done)) - (if (and - reformat-reference-keys - bibtex-maintain-sorted-entries - (not called-by-convert-alien)) - (progn - (bibtex-sort-buffer) - (setq bibtex-reference-keys nil) - (bibtex-parse-keys nil t t))) - (goto-char pnt))) - -(defun bibtex-convert-alien (&optional do-additional-reformatting) - "Converts an alien BibTeX buffer to be fully usable by BibTeX mode. -If a file doesn't confirm with some standards used by BibTeX mode, -some of the high-level features of BibTeX mode won't be available. -This function tries to convert current buffer to confirm with these standards. -With prefix argument DO-ADDITIONAL-REFORMATTING -non-nil, read options for reformatting entries from minibuffer." - (interactive "*P") - (message "Starting to validate buffer...") - (sit-for 1 nil t) - (goto-char (point-min)) - (while (re-search-forward "[ \t\n]+@" nil t) - (replace-match "\n@")) - (message - "If errors occur, correct them and call `bibtex-convert-alien' again") - (sit-for 5 nil t) - (if (let ((bibtex-mark-active) - bibtex-maintain-sorted-entries) - (bibtex-validate)) - (progn - (message "Starting to reformat entries...") - (sit-for 2 nil t) - (bibtex-reformat do-additional-reformatting t) - (if bibtex-maintain-sorted-entries - (progn - (message "Starting to sort buffer...") - (bibtex-sort-buffer))) - (goto-char (point-max)) - (message "Buffer is now parsable. Please save it.")))) - -(defun bibtex-complete-string () - "Complete word fragment before point to longest prefix of a defined string. -If point is not after the part of a word, all strings are listed. -Remove surrounding delimiters if complete string could be expanded." - (interactive "*") - (bibtex-complete bibtex-strings t)) - -(defun bibtex-complete-key () - "Complete word fragment before point to longest prefix of a defined key. -If point is not after the part of a word, all keys are listed. This -function is most useful in completing crossref entries." - (interactive "*") - (if (not bibtex-reference-keys) - (bibtex-parse-keys nil t)) - (bibtex-complete bibtex-reference-keys)) - -(defun bibtex-Article () - "Insert a new BibTeX @Article entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "Article")) - -(defun bibtex-Book () - "Insert a new BibTeX @Book entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "Book")) - -(defun bibtex-Booklet () - "Insert a new BibTeX @Booklet entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "Booklet")) - -(defun bibtex-InBook () - "Insert a new BibTeX @InBook entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "InBook")) - -(defun bibtex-InCollection () - "Insert a new BibTeX @InCollection entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "InCollection")) - -(defun bibtex-InProceedings () - "Insert a new BibTeX @InProceedings entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "InProceedings")) - -(defun bibtex-Manual () - "Insert a new BibTeX @Manual entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "Manual")) - -(defun bibtex-MastersThesis () - "Insert a new BibTeX @MastersThesis entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "MastersThesis")) - -(defun bibtex-Misc () - "Insert a new BibTeX @Misc entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "Misc")) - -(defun bibtex-PhdThesis () - "Insert a new BibTeX @PhdThesis entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "PhdThesis")) - -(defun bibtex-Proceedings () - "Insert a new BibTeX @Proceedings entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "Proceedings")) - -(defun bibtex-TechReport () - "Insert a new BibTeX @TechReport entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "TechReport")) - -(defun bibtex-Unpublished () - "Insert a new BibTeX @Unpublished entry; see also `bibtex-entry'." - (interactive) - (bibtex-entry "Unpublished")) - -(defun bibtex-String () - "Insert a new BibTeX @String entry." - (interactive) - (if (not bibtex-reference-keys) - (bibtex-parse-keys nil t)) - (let ((key - (if (and - bibtex-maintain-sorted-entries - (not bibtex-sort-ignore-string-entries)) - (completing-read - "String key: " bibtex-reference-keys nil nil nil 'bibtex-key-history)))) - (if (and - bibtex-maintain-sorted-entries - (not bibtex-sort-ignore-string-entries)) - (bibtex-find-entry-location key) - (bibtex-move-outside-of-entry)) - (indent-to-column bibtex-entry-offset) - (insert - (concat - "@String" - (bibtex-entry-left-delimiter) - (if (and - bibtex-maintain-sorted-entries - (not bibtex-sort-ignore-string-entries)) - key) - " = " - (bibtex-field-left-delimiter) - (bibtex-field-right-delimiter) - (bibtex-entry-right-delimiter) - "\n")) - (forward-line -1) - (forward-char - (if (and - bibtex-maintain-sorted-entries - (not bibtex-sort-ignore-string-entries)) - (+ (length "@String{") (length key) (length " = {")) - (length "@String{"))))) - -(defun bibtex-Preamble () - "Insert a new BibTeX @Preamble entry." - (interactive) - (bibtex-move-outside-of-entry) - (indent-to-column bibtex-entry-offset) - (insert - "@Preamble" - (bibtex-entry-left-delimiter) - (bibtex-entry-right-delimiter) - "\n") - (forward-line -1) - (forward-char 10)) - - -;; Make BibTeX a Feature - -(provide 'bibtex) - -;;; bibtex.el ends here diff --git a/emacs_el/fixme.el b/emacs_el/fixme.el index 2cacb79..be652c6 100644 --- a/emacs_el/fixme.el +++ b/emacs_el/fixme.el @@ -1,6 +1,6 @@ ;;; fixme.el --- AUC-TeX style file for FiXme -;; Copyright (C) 2000, 2002, 2004 Didier Verna. +;; Copyright (C) 2000, 2002, 2004, 2006 Didier Verna. ;; Author: Didier Verna ;; Maintainer: Didier Verna @@ -39,6 +39,7 @@ '("FXInline") '("FXMargin") + '("FXMarginClue") '("FXFootnote") '("FXUser") '("fixmeindexname") -- 2.39.2