diff options
| author | Jim Blandy | 1991-05-09 21:50:45 +0000 |
|---|---|---|
| committer | Jim Blandy | 1991-05-09 21:50:45 +0000 |
| commit | 745bc783eb8bd84b07a7d512660947ec214e71eb (patch) | |
| tree | 89290135fc261eacb5a368d79face4cd4391db2f /lisp/textmodes | |
| parent | 7229064dbf9dfcb873824a6f2a9af0bdb112b550 (diff) | |
| download | emacs-745bc783eb8bd84b07a7d512660947ec214e71eb.tar.gz emacs-745bc783eb8bd84b07a7d512660947ec214e71eb.zip | |
Initial revision
Diffstat (limited to 'lisp/textmodes')
| -rw-r--r-- | lisp/textmodes/bibtex.el | 1020 |
1 files changed, 1020 insertions, 0 deletions
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el new file mode 100644 index 00000000000..17591f658fe --- /dev/null +++ b/lisp/textmodes/bibtex.el | |||
| @@ -0,0 +1,1020 @@ | |||
| 1 | ;;; BibTeX mode for GNU Emacs | ||
| 2 | ;; Copyright (C) 1985, 1986, 1987, 1990 Free Software Foundation, Inc. | ||
| 3 | |||
| 4 | ;; This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | ;; it under the terms of the GNU General Public License as published by | ||
| 8 | ;; the Free Software Foundation; either version 1, or (at your option) | ||
| 9 | ;; any later version. | ||
| 10 | |||
| 11 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | ;; GNU General Public License for more details. | ||
| 15 | |||
| 16 | ;; You should have received a copy of the GNU General Public License | ||
| 17 | ;; along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 19 | |||
| 20 | ;;; Mike Newton (newton@gumby.cs.caltech.edu) 91.1.20 | ||
| 21 | ;;; * bibtex.el/bibtex-mode : updated comments to indicate new use of | ||
| 22 | ;;; address, add minor explanations and fix small omissions. | ||
| 23 | ;;; * bibtex.el/bibtex-entry : fixed spelling of variable | ||
| 24 | |||
| 25 | ;;; Mike Newton (newton@gumby.cs.caltech.edu) 90.11.17 | ||
| 26 | ;;; * Handle items like | ||
| 27 | ;;; title = poft # "Fifth Tri-quaterly" # random-conf, | ||
| 28 | ;;; and title = {This title is inside curlies} | ||
| 29 | ;;; * added user settable, always present, optional fields | ||
| 30 | ;;; * fixed 'bibtex-find-it's doc string's location | ||
| 31 | ;;; * bibtex-field-text made more general (it wouldnt handle the # construct) | ||
| 32 | ;;; and it now handles a small subset of the {} cases | ||
| 33 | ;;; * put DEA thesis back in (why get rid of good code?) | ||
| 34 | ;;; * merged into release 19 version code | ||
| 35 | ;;; * if cross-ref'ing is on, put 'pages' near top of OPTs, as the other | ||
| 36 | ;;; entries are unlikely to be used. | ||
| 37 | ;;; * skip-whitespace replaced by skip-chars-forward (also done | ||
| 38 | ;;; by Marc Shairo) | ||
| 39 | |||
| 40 | ;;; Bengt Martensson, March 6 | ||
| 41 | ;;; Adapted to Bibtex 0.99 by updating the optional fields according | ||
| 42 | ;;; to the document BibTeXing, Oren Patashnik, dated January 31, 1988. | ||
| 43 | ;;; Updated documentation strings accordingly. Added (provide 'bibtex). | ||
| 44 | ;;; If bibtex-include-OPT-crossref is non-nil, every entry will have | ||
| 45 | ;;; an OPTcrossref field, analogously for bibtex-include-OPTkey and | ||
| 46 | ;;; bibtex-include-OPTannote. Added bibtex-preamble, bound to ^C^EP, | ||
| 47 | ;;; and also found in X- and sun-menus. Cleaned up the sun-menu | ||
| 48 | ;;; stuff, and made it more uniform with the X-menu stuff. Marc: I | ||
| 49 | ;;; strongly suspect that I broke your parsing... (Or, more | ||
| 50 | ;;; correctly, BibTeX 0.99 broke it.) | ||
| 51 | ;;; Added bibtex-clean-entry-zap-empty-opts, defvar'd to t. If it | ||
| 52 | ;;; is nil, bibtex-clean-entry will leave empty optional fields alone. | ||
| 53 | |||
| 54 | ;;; Marc Shapiro 1-feb-89: integrated changes by Bengt Martensson 88-05-06: | ||
| 55 | ;;; Added Sun menu support. Locally bound to right mouse button in | ||
| 56 | ;;; bibtex-mode. Emacs 18.49 allows local mouse bindings!! | ||
| 57 | ;;; Commented out DEAthesis. | ||
| 58 | |||
| 59 | ;;; Marc Shapiro 6-oct-88 | ||
| 60 | ;;; * use indent-to-column instead of inserting tabs (changes to | ||
| 61 | ;;; bibtex-entry, bibtex-make-entry, bibtex-make-OPT-entry, renamed to | ||
| 62 | ;;; bibtex-make-optional-entry) | ||
| 63 | ;;; * C-c C-k deletes the current OPT entry entirely | ||
| 64 | ;;; * C-c C-d replaces text of field with "" | ||
| 65 | ;;; * renamed bibtex-find-it to bibtex-find-text. With arg, now goes to | ||
| 66 | ;;; start of text. Fixed bugs in it. | ||
| 67 | |||
| 68 | ;;; Marc Shapiro 23-sep-88 | ||
| 69 | ;;; * bibtex-clean-entry moves past end of entry. | ||
| 70 | ;;; * bibtex-clean-entry signals mandatory fields left empty. | ||
| 71 | |||
| 72 | ;;; Marc Shapiro 18-jul-88 | ||
| 73 | ;;; * Moved all the entry type keystrokes to "C-c C-e something" (instead of | ||
| 74 | ;;; "C-c something" previously) to make room for more. C-c C-e is | ||
| 75 | ;;; supposed to stand for "entry" [idea taken from mail-mode]. Moved | ||
| 76 | ;;; bibtex-pop-previous to C-c C-p and bibtex-pop-next to C-c C-n. | ||
| 77 | ;;; * removed binding for "\e[25~" | ||
| 78 | ;;; * replaced bibtex-clean-optionals by bibtex-clean-entry, bound to | ||
| 79 | ;;; C-c C-c | ||
| 80 | |||
| 81 | ;;; Marc Shapiro 13-jul-88 [based on ideas by Sacha Krakowiak of IMAG] | ||
| 82 | ;;; * bibtex-pop-previous replaces current field with value of | ||
| 83 | ;;; similar field in previous entry. May be called n times in a row | ||
| 84 | ;;; (or with arg n) to pop similar field of n'th previous entry. | ||
| 85 | ;;; There is also a bibtex-pop-next to get similar field of next | ||
| 86 | ;;; entry. | ||
| 87 | ;;; * C-c C-k now kills all empty optional fields of current entry, and | ||
| 88 | ;;; removes "OPT" for those optional fields which have text. | ||
| 89 | |||
| 90 | ;;; Marc Shapiro 14-dec-87 | ||
| 91 | ;;; Cosmetic fixes. Fixed small bug in bibtex-move-outside-of-entry. | ||
| 92 | ;;; Skip Montanaro <steinmetz!sprite!montanaro> 7-dec-87, Shapiro 10-dec-87 | ||
| 93 | ;;; before inserting an entry, make sure we are outside of a bib entry | ||
| 94 | ;;; Marc Shapiro 3-nov-87 | ||
| 95 | ;;; addition for France: DEAthesis | ||
| 96 | ;;; Marc Shapiro 19-oct-1987 | ||
| 97 | ;;; add X window menu option; bug fixes. TAB, LFD, C-c " and C-c C-o now | ||
| 98 | ;;; behave consistently; deletion never occurs blindly. | ||
| 99 | ;;; Marc Shapiro <shapiro@inria.inria.fr> 15-oct-1986 | ||
| 100 | ;;; align long lines nicely; C-c C-o checks for the "OPT" string; | ||
| 101 | ;;; TAB goes to the end of the string; use lower case; use | ||
| 102 | ;;; run-hooks | ||
| 103 | |||
| 104 | ;;; Bengt Martensson <ubrinf!mond!bengt> 87-06-28 | ||
| 105 | ;;; (Bengt Martensson <bengt@mathematik.uni-Bremen.de> 87-06-28) | ||
| 106 | ;;; Original version | ||
| 107 | |||
| 108 | ;;; NOTE by Marc Shapiro, 14-dec-87: | ||
| 109 | ;;; (bibtex-x-environment) binds an X menu for bibtex mode to x-button-c-right. | ||
| 110 | ;;; Trouble is, in Emacs 18.44 you can't have a mode-specific mouse binding, | ||
| 111 | ;;; so it will remain active in all windows. Yuck! | ||
| 112 | |||
| 113 | (provide 'bibtex) | ||
| 114 | |||
| 115 | (defvar bibtex-mode-syntax-table nil "") | ||
| 116 | (defvar bibtex-mode-abbrev-table nil "") | ||
| 117 | (define-abbrev-table 'bibtex-mode-abbrev-table ()) | ||
| 118 | (defvar bibtex-mode-map (make-sparse-keymap) "") | ||
| 119 | (defvar bibtex-pop-previous-search-point nil | ||
| 120 | "Next point where `bibtex-pop-previous' should start looking for a similar | ||
| 121 | entry.") | ||
| 122 | (defvar bibtex-pop-next-search-point nil | ||
| 123 | "Next point where `bibtex-pop-next' should start looking for a similar | ||
| 124 | entry.") | ||
| 125 | |||
| 126 | (defvar bibtex-clean-entry-zap-empty-opts t | ||
| 127 | "*If non-nil, `bibtex-clean-entry' will delete all empty optional fields.") | ||
| 128 | (defvar bibtex-include-OPTcrossref t | ||
| 129 | "*If non-nil, all entries will have an `OPTcrossref' field.") | ||
| 130 | (defvar bibtex-include-OPTkey t | ||
| 131 | "*If non-nil, all entries will have an `OPTkey' field.") | ||
| 132 | (defvar bibtex-include-OPTannote t | ||
| 133 | "*If non-nil, all entries will have an `OPTannote' field.") | ||
| 134 | |||
| 135 | ;; note: the user should be allowed to have their own list of always | ||
| 136 | ;; available optional fields. exs: "keywords" "categories" | ||
| 137 | (defvar bibtex-mode-user-optional-fields nil ;no default value | ||
| 138 | "*List of optional fields that user always wants present in a bibtex entry. | ||
| 139 | One possibility is for ``keywords''") | ||
| 140 | |||
| 141 | |||
| 142 | ;;; A bibtex file is a sequence of entries, either string definitions | ||
| 143 | ;;; or reference entries. A reference entry has a type part, a | ||
| 144 | ;;; key part, and a comma-separated sequence of fields. A string | ||
| 145 | ;;; entry has a single field. A field has a left and right part, | ||
| 146 | ;;; separated by a '='. The left part is the name, the right part is | ||
| 147 | ;;; the text. Here come the definitions allowing to create and/or parse | ||
| 148 | ;;; entries and fields: | ||
| 149 | |||
| 150 | ;;; fields | ||
| 151 | (defun bibtex-cfield (name text) | ||
| 152 | "Create a regexp for a bibtex field of name NAME and text TEXT." | ||
| 153 | (concat ",[ \t\n]*\\(" | ||
| 154 | name | ||
| 155 | "\\)[ \t\n]*=[ \t\n]*\\(" | ||
| 156 | text | ||
| 157 | "\\)")) | ||
| 158 | (defconst bibtex-name-in-cfield 1 | ||
| 159 | "The regexp subexpression number of the name part in `bibtex-cfield'.") | ||
| 160 | (defconst bibtex-text-in-cfield 2 | ||
| 161 | "The regexp subexpression number of the text part in `bibtex-cfield'.") | ||
| 162 | |||
| 163 | (defconst bibtex-field-name "[A-Za-z][---A-Za-z0-9:_+]*" | ||
| 164 | "Regexp defining the name part of a bibtex field.") | ||
| 165 | |||
| 166 | ;; bibtex-field-text must be able to handle | ||
| 167 | ;; title = "Proc. Fifteenth Annual" # STOC, | ||
| 168 | ;; month = "10~" # jan, | ||
| 169 | ;; year = "{\noopsort{1973c}}1981", | ||
| 170 | ;; month = apr # "-" # may, | ||
| 171 | ;; key = {Volume-2}, | ||
| 172 | ;; note = "Volume~2 is listed under Knuth \cite{book-full}" | ||
| 173 | ;; i have added a few of these, but not all! -- MON | ||
| 174 | |||
| 175 | (defconst bibtex-field-const | ||
| 176 | "[0-9A-Za-z][---A-Za-z0-9:_+]*" | ||
| 177 | "Format of a bibtex field constant.") | ||
| 178 | (defconst bibtex-field-string | ||
| 179 | (concat | ||
| 180 | "\"[^\"]*[^\\\\]\"\\|\"\"") | ||
| 181 | "Match either a string or an empty string.") | ||
| 182 | (defconst bibtex-field-string-or-const | ||
| 183 | (concat bibtex-field-const "\\|" bibtex-field-string) | ||
| 184 | "Match either `bibtex-field-string' or `bibtex-field-const'.") | ||
| 185 | |||
| 186 | ;(defconst bibtex-field-text | ||
| 187 | ; "\"[^\"]*[^\\\\]\"\\|\"\"\\|[0-9A-Za-z][---A-Za-z0-9:_+]*" | ||
| 188 | ; "Regexp defining the text part of a bibtex field: either a string, or an empty string, or a constant.") | ||
| 189 | |||
| 190 | (defconst bibtex-field-text | ||
| 191 | (concat | ||
| 192 | "\\(" bibtex-field-string-or-const "\\)" | ||
| 193 | "\\([ \t\n]+#[ \t\n]+\\(" bibtex-field-string-or-const "\\)\\)*\\|" | ||
| 194 | "{[^{}]*[^\\\\]}") | ||
| 195 | "Regexp defining the text part of a bibtex field: either a string, or | ||
| 196 | an empty string, or a constant followed by one or more # / constant pairs. | ||
| 197 | Also matches simple {...} patterns.") | ||
| 198 | |||
| 199 | (defconst bibtex-field | ||
| 200 | (bibtex-cfield bibtex-field-name bibtex-field-text) | ||
| 201 | "Regexp defining the format of a bibtex field") | ||
| 202 | |||
| 203 | (defconst bibtex-name-in-field bibtex-name-in-cfield | ||
| 204 | "The regexp subexpression number of the name part in `bibtex-field'.") | ||
| 205 | (defconst bibtex-text-in-field bibtex-text-in-cfield | ||
| 206 | "The regexp subexpression number of the text part in `bibtex-field'.") | ||
| 207 | |||
| 208 | ;;; references | ||
| 209 | (defconst bibtex-reference-type | ||
| 210 | "@[A-Za-z]+" | ||
| 211 | "Regexp defining the type part of a bibtex reference entry.") | ||
| 212 | (defconst bibtex-reference-head | ||
| 213 | (concat "^[ \t]*\\(" | ||
| 214 | bibtex-reference-type | ||
| 215 | "\\)[ \t]*[({]\\(" | ||
| 216 | bibtex-field-name | ||
| 217 | "\\)") | ||
| 218 | "Regexp defining format of the header line of a bibtex reference entry.") | ||
| 219 | (defconst bibtex-type-in-head 1 | ||
| 220 | "The regexp subexpression number of the type part in `bibtex-reference-head'.") | ||
| 221 | (defconst bibtex-key-in-head 2 | ||
| 222 | "The regexp subexpression number of the key part in `bibtex-reference-head'.") | ||
| 223 | |||
| 224 | (defconst bibtex-reference | ||
| 225 | (concat bibtex-reference-head | ||
| 226 | "\\([ \t\n]*" bibtex-field "\\)*" | ||
| 227 | "[ \t\n]*[})]") | ||
| 228 | "Regexp defining the format of a bibtex reference entry.") | ||
| 229 | (defconst bibtex-type-in-reference bibtex-type-in-head | ||
| 230 | "The regexp subexpression number of the type part in `bibtex-reference'.") | ||
| 231 | (defconst bibtex-key-in-reference bibtex-key-in-head | ||
| 232 | "The regexp subexpression number of the key part in `bibtex-reference'.") | ||
| 233 | |||
| 234 | ;;; strings | ||
| 235 | (defconst bibtex-string | ||
| 236 | (concat "^[ \t]*@[sS][tT][rR][iI][nN][gG][ \t\n]*[({][ \t\n]*\\(" | ||
| 237 | bibtex-field-name | ||
| 238 | "\\)[ \t\n]*=[ \t\n]*\\(" | ||
| 239 | bibtex-field-text | ||
| 240 | "\\)[ \t\n]*[})]") | ||
| 241 | "Regexp defining the format of a bibtex string entry.") | ||
| 242 | (defconst bibtex-name-in-string 1 | ||
| 243 | "The regexp subexpression of the name part in `bibtex-string'.") | ||
| 244 | (defconst bibtex-text-in-string 2 | ||
| 245 | "The regexp subexpression of the text part in `bibtex-string'.") | ||
| 246 | |||
| 247 | (defconst bibtex-name-alignement 2 | ||
| 248 | "Alignment for the name part in BibTeX fields. | ||
| 249 | Chosen on aesthetic grounds only.") | ||
| 250 | |||
| 251 | (defconst bibtex-text-alignment (length " organization = ") | ||
| 252 | "Alignment for the text part in BibTeX fields. | ||
| 253 | Equal to the space needed for the longest name part.") | ||
| 254 | |||
| 255 | ;;; bibtex mode: | ||
| 256 | |||
| 257 | ;;;###autoload | ||
| 258 | (defun bibtex-mode () | ||
| 259 | "Major mode for editing bibtex files. | ||
| 260 | |||
| 261 | \\{bibtex-mode-map} | ||
| 262 | |||
| 263 | A command such as \\[bibtex-Book] will outline the fields for a BibTeX book entry. | ||
| 264 | |||
| 265 | The optional fields start with the string OPT, and thus ignored by BibTeX. | ||
| 266 | The OPT string may be removed from a field with \\[bibtex-remove-OPT]. | ||
| 267 | \\[bibtex-kill-optional-field] kills the current optional field entirely. | ||
| 268 | \\[bibtex-remove-double-quotes] removes the double-quotes around the text of | ||
| 269 | the current field. \\[bibtex-empty-field] replaces the text of the current | ||
| 270 | field with the default \"\". | ||
| 271 | |||
| 272 | The command \\[bibtex-clean-entry] cleans the current entry, i.e. (i) removes | ||
| 273 | double-quotes from entirely numerical fields, (ii) removes OPT from all | ||
| 274 | non-empty optional fields, (iii) removes all empty optional fields, and (iv) | ||
| 275 | checks that no non-optional fields are empty. | ||
| 276 | |||
| 277 | Use \\[bibtex-find-text] to position the dot at the end of the current field. | ||
| 278 | Use \\[bibtex-next-field] to move to end of the next field. | ||
| 279 | |||
| 280 | \\[bibtex-x-environment] binds a mode-specific X menu to control+right | ||
| 281 | mouse button. | ||
| 282 | \\[bibtex-sun-environment] binds a mode-specific Sun menu to right | ||
| 283 | mouse button. | ||
| 284 | |||
| 285 | Fields: | ||
| 286 | address | ||
| 287 | Publisher's address, or for conference, location held | ||
| 288 | annote | ||
| 289 | Long annotation used for annotated bibliographies (begins sentence) | ||
| 290 | author | ||
| 291 | Name(s) of author(s), in BibTeX name format | ||
| 292 | booktitle | ||
| 293 | Book title when the thing being referenced isn't the whole book. | ||
| 294 | For book entries, the title field should be used instead. | ||
| 295 | chapter | ||
| 296 | Chapter number (or section or whatever). | ||
| 297 | crossref | ||
| 298 | The database key of the entry being cross referenced. | ||
| 299 | edition | ||
| 300 | Edition of a book (e.g., \"second\") | ||
| 301 | editor | ||
| 302 | Name(s) of editor(s), in BibTeX name format. | ||
| 303 | If there is also an author field, then the editor field should be | ||
| 304 | for the book or collection that the work appears in | ||
| 305 | howpublished | ||
| 306 | How something strange has been published (begins sentence) | ||
| 307 | institution | ||
| 308 | Sponsoring institution | ||
| 309 | journal | ||
| 310 | Journal name (macros are provided for many) | ||
| 311 | key | ||
| 312 | Alphabetizing, labeling and cross-refing key (needed when no | ||
| 313 | author or editor) | ||
| 314 | month | ||
| 315 | Month (macros are provided) | ||
| 316 | note | ||
| 317 | To help the reader find a reference (begins sentence) | ||
| 318 | number | ||
| 319 | Number of a journal or technical report | ||
| 320 | organization | ||
| 321 | Organization (sponsoring a conference) | ||
| 322 | pages | ||
| 323 | Page number or numbers (use `--' to separate a range) | ||
| 324 | publisher | ||
| 325 | Publisher name | ||
| 326 | school | ||
| 327 | School name (for theses) | ||
| 328 | series | ||
| 329 | The name of a series or set of books. | ||
| 330 | An individual book will will also have it's own title | ||
| 331 | title | ||
| 332 | The title of the thing being referenced | ||
| 333 | type | ||
| 334 | Type of a technical report (e.g., \"Research Note\") to be used | ||
| 335 | instead of the default \"Technical Report\" | ||
| 336 | volume | ||
| 337 | Volume of a journal or multivolume work | ||
| 338 | year | ||
| 339 | Year---should contain only numerals | ||
| 340 | --------------------------------------------------------- | ||
| 341 | Entry to this mode calls the value of bibtex-mode-hook if that value is | ||
| 342 | non-nil." | ||
| 343 | (interactive) | ||
| 344 | (kill-all-local-variables) | ||
| 345 | (if bibtex-mode-syntax-table | ||
| 346 | (set-syntax-table bibtex-mode-syntax-table) | ||
| 347 | (setq bibtex-mode-syntax-table (make-syntax-table)) | ||
| 348 | (set-syntax-table bibtex-mode-syntax-table) | ||
| 349 | (modify-syntax-entry ?\" ".") | ||
| 350 | (modify-syntax-entry ?$ "$$ ") | ||
| 351 | (modify-syntax-entry ?% "< ") | ||
| 352 | (modify-syntax-entry ?' "w ") | ||
| 353 | (modify-syntax-entry ?@ "w ") | ||
| 354 | (modify-syntax-entry ?\\ "\\") | ||
| 355 | (modify-syntax-entry ?\f "> ") | ||
| 356 | (modify-syntax-entry ?\n "> ") | ||
| 357 | (modify-syntax-entry ?~ " ")) | ||
| 358 | (use-local-map bibtex-mode-map) | ||
| 359 | (setq major-mode 'bibtex-mode) | ||
| 360 | |||
| 361 | |||
| 362 | (setq mode-name "BibTeX") | ||
| 363 | (set-syntax-table bibtex-mode-syntax-table) | ||
| 364 | (setq local-abbrev-table bibtex-mode-abbrev-table) | ||
| 365 | (make-local-variable 'paragraph-start) | ||
| 366 | (setq paragraph-start "^[ \f\n\t]*$") | ||
| 367 | |||
| 368 | (define-key bibtex-mode-map "\t" 'bibtex-find-text) | ||
| 369 | (define-key bibtex-mode-map "\n" 'bibtex-next-field) | ||
| 370 | (define-key bibtex-mode-map "\C-c\"" 'bibtex-remove-double-quotes) | ||
| 371 | (define-key bibtex-mode-map "\C-c\C-c" 'bibtex-clean-entry) | ||
| 372 | (define-key bibtex-mode-map "\C-c?" 'describe-mode) | ||
| 373 | (define-key bibtex-mode-map "\C-c\C-p" 'bibtex-pop-previous) | ||
| 374 | (define-key bibtex-mode-map "\C-c\C-n" 'bibtex-pop-next) | ||
| 375 | (define-key bibtex-mode-map "\C-c\C-k" 'bibtex-kill-optional-field) | ||
| 376 | (define-key bibtex-mode-map "\C-c\C-d" 'bibtex-empty-field) | ||
| 377 | |||
| 378 | (define-key bibtex-mode-map "\C-c\C-e\C-a" 'bibtex-Article) | ||
| 379 | (define-key bibtex-mode-map "\C-c\C-e\C-b" 'bibtex-Book) | ||
| 380 | (define-key bibtex-mode-map "\C-c\C-e\C-d" 'bibtex-DEAthesis) | ||
| 381 | (define-key bibtex-mode-map "\C-c\C-e\C-c" 'bibtex-InProceedings) | ||
| 382 | (define-key bibtex-mode-map "\C-c\C-e\C-i" 'bibtex-InBook) | ||
| 383 | (define-key bibtex-mode-map "\C-c\C-ei" 'bibtex-InCollection) | ||
| 384 | (define-key bibtex-mode-map "\C-c\C-eI" 'bibtex-InProceedings) | ||
| 385 | (define-key bibtex-mode-map "\C-c\C-e\C-m" 'bibtex-Manual) | ||
| 386 | (define-key bibtex-mode-map "\C-c\C-em" 'bibtex-MastersThesis) | ||
| 387 | (define-key bibtex-mode-map "\C-c\C-eM" 'bibtex-Misc) | ||
| 388 | (define-key bibtex-mode-map "\C-c\C-o" 'bibtex-remove-OPT) | ||
| 389 | (define-key bibtex-mode-map "\C-c\C-e\C-p" 'bibtex-PhdThesis) | ||
| 390 | (define-key bibtex-mode-map "\C-c\C-ep" 'bibtex-Proceedings) | ||
| 391 | (define-key bibtex-mode-map "\C-c\C-eP" 'bibtex-preamble) | ||
| 392 | (define-key bibtex-mode-map "\C-c\C-e\C-t" 'bibtex-TechReport) | ||
| 393 | (define-key bibtex-mode-map "\C-c\C-e\C-s" 'bibtex-string) | ||
| 394 | (define-key bibtex-mode-map "\C-c\C-e\C-u" 'bibtex-Unpublished) | ||
| 395 | |||
| 396 | (auto-fill-mode 1) ; nice alignements | ||
| 397 | (setq left-margin (+ bibtex-text-alignment 1)) | ||
| 398 | |||
| 399 | (run-hooks 'bibtex-mode-hook)) | ||
| 400 | |||
| 401 | (defun bibtex-move-outside-of-entry () | ||
| 402 | "Make sure we are outside of a bib entry" | ||
| 403 | (cond ((or | ||
| 404 | (= (point) (point-max)) | ||
| 405 | (= (point) (point-min)) | ||
| 406 | (looking-at "[ \n]*@") | ||
| 407 | ) | ||
| 408 | t) | ||
| 409 | (t | ||
| 410 | (backward-paragraph) | ||
| 411 | (forward-paragraph))) | ||
| 412 | (re-search-forward "[ \t\n]*" (point-max) t)) | ||
| 413 | |||
| 414 | ;; | ||
| 415 | ;; note: this should really take lists of strings OR of lists. in the | ||
| 416 | ;; second case, one can use either list. (ie: | ||
| 417 | ;; "name" (("crossref") ("journal" "year")) ) | ||
| 418 | ;; | ||
| 419 | |||
| 420 | (defun bibtex-entry (entry-type required optional) | ||
| 421 | (bibtex-move-outside-of-entry) | ||
| 422 | (insert "@" entry-type "{") | ||
| 423 | (mapcar 'bibtex-make-field required) | ||
| 424 | (if bibtex-include-OPTcrossref | ||
| 425 | (bibtex-make-optional-field "crossref")) | ||
| 426 | (if bibtex-include-OPTkey | ||
| 427 | (bibtex-make-optional-field "key")) | ||
| 428 | (mapcar 'bibtex-make-optional-field optional) | ||
| 429 | (if bibtex-mode-user-optional-fields ;MON... | ||
| 430 | (mapcar 'bibtex-make-optional-field | ||
| 431 | bibtex-mode-user-optional-fields)) | ||
| 432 | (if bibtex-include-OPTannote | ||
| 433 | (bibtex-make-optional-field "annote")) | ||
| 434 | (insert "\n}\n\n") | ||
| 435 | (forward-char -3) | ||
| 436 | (up-list -1) | ||
| 437 | (forward-char 1)) | ||
| 438 | |||
| 439 | (defun bibtex-make-field (str) | ||
| 440 | (interactive "sBibTeX entry type: ") | ||
| 441 | (insert ",\n") | ||
| 442 | (indent-to-column bibtex-name-alignement) | ||
| 443 | (insert str " = ") | ||
| 444 | (indent-to-column bibtex-text-alignment) | ||
| 445 | (insert "\"\"") | ||
| 446 | nil) | ||
| 447 | |||
| 448 | (defun bibtex-make-optional-field (str) | ||
| 449 | (interactive "sOptional BibTeX entry type: ") | ||
| 450 | (insert ",\n") | ||
| 451 | (indent-to-column bibtex-name-alignement) | ||
| 452 | (insert "OPT" str " = ") | ||
| 453 | (indent-to-column bibtex-text-alignment) | ||
| 454 | (insert "\"\"") | ||
| 455 | nil) | ||
| 456 | |||
| 457 | ;; What to do about crossref? if present, journal and year are | ||
| 458 | ;; both optional. Due to this, i move all of them into optional. -- MON | ||
| 459 | |||
| 460 | (defun bibtex-Article () | ||
| 461 | (interactive) | ||
| 462 | (if bibtex-include-OPTcrossref | ||
| 463 | (bibtex-entry "Article" '("author" "title") | ||
| 464 | '("journal" "year" "volume" "number" "pages" | ||
| 465 | "month" "note")) | ||
| 466 | (bibtex-entry "Article" '("author" "title" "journal" "year") | ||
| 467 | '("volume" "number" "pages" "month" "note")))) | ||
| 468 | |||
| 469 | (defun bibtex-Book () | ||
| 470 | (interactive) | ||
| 471 | (bibtex-entry "Book" '("author" "title" "publisher" "year") | ||
| 472 | '("editor" "volume" "number" "series" "address" | ||
| 473 | "edition" "month" "note"))) | ||
| 474 | |||
| 475 | (defun bibtex-Booklet () | ||
| 476 | (interactive) | ||
| 477 | (bibtex-entry "Booklet" '("title") | ||
| 478 | '("author" "howpublished" "address" "month" "year" "note"))) | ||
| 479 | |||
| 480 | ;; France: Dipl\^{o}me d'Etudes Approfondies (similar to Master's) | ||
| 481 | (defun bibtex-DEAthesis () | ||
| 482 | (interactive) | ||
| 483 | (bibtex-entry "DEAthesis" '("author" "title" "school" "year") | ||
| 484 | '("address" "month" "note"))) | ||
| 485 | |||
| 486 | (defun bibtex-InBook () | ||
| 487 | (interactive) | ||
| 488 | (if bibtex-include-OPTcrossref | ||
| 489 | (bibtex-entry "InBook" '("author" "title" "chapter") | ||
| 490 | '("publisher" "year" "editor" "pages" "volume" "number" | ||
| 491 | "series" "address" "edition" "month" "type" "note")) | ||
| 492 | (bibtex-entry "InBook" '("author" "title" "chapter" "publisher" "year") | ||
| 493 | '("editor" "pages" "volume" "number" "series" "address" | ||
| 494 | "edition" "month" "type" "note")))) | ||
| 495 | |||
| 496 | ;; In next 2, for crossref case, put pages near beginning of | ||
| 497 | ;; optionals as it will be used most often -- MON | ||
| 498 | (defun bibtex-InCollection () | ||
| 499 | (interactive) | ||
| 500 | (if bibtex-include-OPTcrossref | ||
| 501 | (bibtex-entry "InCollection" '("author" "title") | ||
| 502 | '("pages" "booktitle" "publisher" "year" | ||
| 503 | "editor" "volume" "number" "series" "type" "chapter" | ||
| 504 | "address" "edition" "month" "note")) | ||
| 505 | (bibtex-entry "InCollection" '("author" "title" | ||
| 506 | "booktitle" "publisher" "year") | ||
| 507 | '("editor" "volume" "number" "series" "type" "chapter" | ||
| 508 | "pages" "address" "edition" "month" "note")))) | ||
| 509 | |||
| 510 | (defun bibtex-InProceedings () | ||
| 511 | (interactive) | ||
| 512 | (if bibtex-include-OPTcrossref | ||
| 513 | (bibtex-entry "InProceedings" '("author" "title") | ||
| 514 | '( "pages" "editor" "volume" "number" "series" | ||
| 515 | "booktitle" "year" | ||
| 516 | "organization" "publisher" "address" "month" "note")) | ||
| 517 | (bibtex-entry "InProceedings" '("author" "title" "booktitle" "year") | ||
| 518 | '("editor" "volume" "number" "series" "pages" | ||
| 519 | "organization" "publisher" "address" "month" "note")))) | ||
| 520 | |||
| 521 | (defun bibtex-Manual () | ||
| 522 | (interactive) | ||
| 523 | (bibtex-entry "Manual" '("title") | ||
| 524 | '("author" "organization" "address" "edition" "year" | ||
| 525 | "month" "note"))) | ||
| 526 | |||
| 527 | (defun bibtex-MastersThesis () | ||
| 528 | (interactive) | ||
| 529 | (bibtex-entry "MastersThesis" '("author" "title" "school" "year") | ||
| 530 | '("address" "month" "note" "type"))) | ||
| 531 | |||
| 532 | (defun bibtex-Misc () | ||
| 533 | (interactive) | ||
| 534 | (bibtex-entry "Misc" '() | ||
| 535 | '("author" "title" "howpublished" "year" "month" "note"))) | ||
| 536 | |||
| 537 | (defun bibtex-PhdThesis () | ||
| 538 | (interactive) | ||
| 539 | (bibtex-entry "PhdThesis" '("author" "title" "school" "year") | ||
| 540 | '("address" "month" "type" "note"))) | ||
| 541 | |||
| 542 | (defun bibtex-Proceedings () | ||
| 543 | (interactive) | ||
| 544 | (bibtex-entry "Proceedings" '("title" "year") | ||
| 545 | '("editor" "volume" "number" "series" "publisher" | ||
| 546 | "organization" "address" "month" "note"))) | ||
| 547 | |||
| 548 | (defun bibtex-TechReport () | ||
| 549 | (interactive) | ||
| 550 | (bibtex-entry "TechReport" '("author" "title" "institution" "year") | ||
| 551 | '("type" "number" "address" "month" "note"))) | ||
| 552 | |||
| 553 | |||
| 554 | (defun bibtex-Unpublished () | ||
| 555 | (interactive) | ||
| 556 | (bibtex-entry "Unpublished" '("author" "title" "note") | ||
| 557 | '("year" "month"))) | ||
| 558 | |||
| 559 | (defun bibtex-string () | ||
| 560 | (interactive) | ||
| 561 | (bibtex-move-outside-of-entry) | ||
| 562 | (insert "@string{ = """"}\n") | ||
| 563 | (previous-line 1) | ||
| 564 | (forward-char 8)) | ||
| 565 | |||
| 566 | (defun bibtex-preamble () | ||
| 567 | (interactive) | ||
| 568 | (bibtex-move-outside-of-entry) | ||
| 569 | (insert "@Preamble{}\n") | ||
| 570 | (previous-line 1) | ||
| 571 | (forward-char 10)) | ||
| 572 | |||
| 573 | (defun bibtex-next-field (arg) | ||
| 574 | "Finds end of text of next BibTeX field; with arg, to its beginning" | ||
| 575 | (interactive "P") | ||
| 576 | (bibtex-inside-field) | ||
| 577 | (let ((start (point))) | ||
| 578 | (condition-case () | ||
| 579 | (progn | ||
| 580 | (bibtex-enclosing-field) | ||
| 581 | (goto-char (match-end 0)) | ||
| 582 | (forward-char 2)) | ||
| 583 | (error | ||
| 584 | (goto-char start) | ||
| 585 | (end-of-line) | ||
| 586 | (forward-char 1)))) | ||
| 587 | (bibtex-find-text arg)) | ||
| 588 | |||
| 589 | (defun bibtex-find-text (arg) | ||
| 590 | "Go to end of text of current field; with arg, go to beginning." | ||
| 591 | (interactive "P") | ||
| 592 | (bibtex-inside-field) | ||
| 593 | (bibtex-enclosing-field) | ||
| 594 | (if arg | ||
| 595 | (progn | ||
| 596 | (goto-char (match-beginning bibtex-text-in-field)) | ||
| 597 | (if (looking-at "\"") | ||
| 598 | (forward-char 1))) | ||
| 599 | (goto-char (match-end bibtex-text-in-field)) | ||
| 600 | (if (= (preceding-char) ?\") | ||
| 601 | (forward-char -1)))) | ||
| 602 | |||
| 603 | (defun bibtex-remove-OPT () | ||
| 604 | "Removes the 'OPT' starting optional arguments and goes to end of text" | ||
| 605 | (interactive) | ||
| 606 | (bibtex-inside-field) | ||
| 607 | (bibtex-enclosing-field) | ||
| 608 | (save-excursion | ||
| 609 | (goto-char (match-beginning bibtex-name-in-field)) | ||
| 610 | (if (looking-at "OPT") | ||
| 611 | (delete-char (length "OPT")))) | ||
| 612 | (bibtex-inside-field)) | ||
| 613 | |||
| 614 | (defun bibtex-inside-field () | ||
| 615 | "Try to avoid point being at end of a bibtex field." | ||
| 616 | (interactive) | ||
| 617 | (end-of-line) | ||
| 618 | (skip-chars-backward " \t") ;delete these chars? -- MON | ||
| 619 | (cond ((= (preceding-char) ?,) | ||
| 620 | (forward-char -1))) | ||
| 621 | (cond ((= (preceding-char) ?\") | ||
| 622 | (forward-char -1)))) ;only go back if quote | ||
| 623 | |||
| 624 | |||
| 625 | (defun bibtex-remove-double-quotes () | ||
| 626 | "Removes """" around string." | ||
| 627 | (interactive) | ||
| 628 | (save-excursion | ||
| 629 | (bibtex-inside-field) | ||
| 630 | (bibtex-enclosing-field) | ||
| 631 | (let ((start (match-beginning bibtex-text-in-field)) | ||
| 632 | (stop (match-end bibtex-text-in-field))) | ||
| 633 | (goto-char stop) | ||
| 634 | (forward-char -1) | ||
| 635 | (if (looking-at "\"") | ||
| 636 | (delete-char 1)) | ||
| 637 | (goto-char start) | ||
| 638 | (if (looking-at "\"") | ||
| 639 | (delete-char 1))))) | ||
| 640 | |||
| 641 | (defun bibtex-kill-optional-field () | ||
| 642 | "Kill the entire enclosing optional BibTeX field" | ||
| 643 | (interactive) | ||
| 644 | (bibtex-inside-field) | ||
| 645 | (bibtex-enclosing-field) | ||
| 646 | (goto-char (match-beginning bibtex-name-in-field)) | ||
| 647 | (let ((the-end (match-end 0)) | ||
| 648 | (the-beginning (match-beginning 0))) | ||
| 649 | (if (looking-at "OPT") | ||
| 650 | (progn | ||
| 651 | (goto-char the-end) | ||
| 652 | (skip-chars-forward " \t\n,") | ||
| 653 | (kill-region the-beginning the-end)) | ||
| 654 | (error "Mandatory fields can't be killed")))) | ||
| 655 | |||
| 656 | (defun bibtex-empty-field () | ||
| 657 | "Delete the text part of the current field, replace with empty text" | ||
| 658 | (interactive) | ||
| 659 | (bibtex-inside-field) | ||
| 660 | (bibtex-enclosing-field) | ||
| 661 | (goto-char (match-beginning bibtex-text-in-field)) | ||
| 662 | (kill-region (point) (match-end bibtex-text-in-field)) | ||
| 663 | (insert "\"\"") | ||
| 664 | (bibtex-find-text t)) | ||
| 665 | |||
| 666 | |||
| 667 | (defun bibtex-pop-previous (arg) | ||
| 668 | "Replace text of current field with the text of similar field in previous entry. | ||
| 669 | With arg, go up ARG entries. Repeated, goes up so many times. May be | ||
| 670 | intermixed with \\[bibtex-pop-next] (bibtex-pop-next)." | ||
| 671 | (interactive "p") | ||
| 672 | (bibtex-inside-field) | ||
| 673 | (save-excursion | ||
| 674 | ; parse current field | ||
| 675 | (bibtex-enclosing-field) | ||
| 676 | (let ((start-old-text (match-beginning bibtex-text-in-field)) | ||
| 677 | (stop-old-text (match-end bibtex-text-in-field)) | ||
| 678 | (start-name (match-beginning bibtex-name-in-field)) | ||
| 679 | (stop-name (match-end bibtex-name-in-field)) | ||
| 680 | (new-text)) | ||
| 681 | (goto-char start-name) | ||
| 682 | ; construct regexp for previous field with same name as this one | ||
| 683 | (let ((matching-entry | ||
| 684 | (bibtex-cfield | ||
| 685 | (buffer-substring (if (looking-at "OPT") | ||
| 686 | (+ (point) (length "OPT")) | ||
| 687 | (point)) | ||
| 688 | stop-name) | ||
| 689 | bibtex-field-text))) | ||
| 690 | |||
| 691 | ; if executed several times in a row, start each search where the | ||
| 692 | ; last one finished | ||
| 693 | (cond ((or (eq last-command 'bibtex-pop-previous) | ||
| 694 | (eq last-command 'bibtex-pop-next)) | ||
| 695 | t | ||
| 696 | ) | ||
| 697 | (t | ||
| 698 | (bibtex-enclosing-reference) | ||
| 699 | (setq bibtex-pop-previous-search-point (match-beginning 0)) | ||
| 700 | (setq bibtex-pop-next-search-point (match-end 0)))) | ||
| 701 | (goto-char bibtex-pop-previous-search-point) | ||
| 702 | |||
| 703 | ; Now search for arg'th previous similar field | ||
| 704 | (cond | ||
| 705 | ((re-search-backward matching-entry (point-min) t arg) | ||
| 706 | (setq new-text | ||
| 707 | (buffer-substring (match-beginning bibtex-text-in-cfield) | ||
| 708 | (match-end bibtex-text-in-cfield))) | ||
| 709 | ; Found a matching field. Remember boundaries. | ||
| 710 | (setq bibtex-pop-next-search-point (match-end 0)) | ||
| 711 | (setq bibtex-pop-previous-search-point (match-beginning 0)) | ||
| 712 | (bibtex-flash-head) | ||
| 713 | ; Go back to where we started, delete old text, and pop new. | ||
| 714 | (goto-char stop-old-text) | ||
| 715 | (delete-region start-old-text stop-old-text) | ||
| 716 | (insert new-text)) | ||
| 717 | (t ; search failed | ||
| 718 | (error "No previous matching BibTeX field.")))))) | ||
| 719 | (setq this-command 'bibtex-pop-previous)) | ||
| 720 | |||
| 721 | (defun bibtex-pop-next (arg) | ||
| 722 | "Replace text of current field with the text of similar field in next entry. | ||
| 723 | With arg, go up ARG entries. Repeated, goes up so many times. May be | ||
| 724 | intermixed with \\[bibtex-pop-previous] (bibtex-pop-previous)." | ||
| 725 | (interactive "p") | ||
| 726 | (bibtex-inside-field) | ||
| 727 | (save-excursion | ||
| 728 | ; parse current field | ||
| 729 | (bibtex-enclosing-field) | ||
| 730 | (let ((start-old-text (match-beginning bibtex-text-in-field)) | ||
| 731 | (stop-old-text (match-end bibtex-text-in-field)) | ||
| 732 | (start-name (match-beginning bibtex-name-in-field)) | ||
| 733 | (stop-name (match-end bibtex-name-in-field)) | ||
| 734 | (new-text)) | ||
| 735 | (goto-char start-name) | ||
| 736 | ; construct regexp for next field with same name as this one, | ||
| 737 | ; ignoring possible OPT's | ||
| 738 | (let ((matching-entry | ||
| 739 | (bibtex-cfield | ||
| 740 | (buffer-substring (if (looking-at "OPT") | ||
| 741 | (+ (point) (length "OPT")) | ||
| 742 | (point)) | ||
| 743 | stop-name) | ||
| 744 | bibtex-field-text))) | ||
| 745 | |||
| 746 | ; if executed several times in a row, start each search where the | ||
| 747 | ; last one finished | ||
| 748 | (cond ((or (eq last-command 'bibtex-pop-next) | ||
| 749 | (eq last-command 'bibtex-pop-previous)) | ||
| 750 | t | ||
| 751 | ) | ||
| 752 | (t | ||
| 753 | (bibtex-enclosing-reference) | ||
| 754 | (setq bibtex-pop-previous-search-point (match-beginning 0)) | ||
| 755 | (setq bibtex-pop-next-search-point (match-end 0)))) | ||
| 756 | (goto-char bibtex-pop-next-search-point) | ||
| 757 | |||
| 758 | ; Now search for arg'th next similar field | ||
| 759 | (cond | ||
| 760 | ((re-search-forward matching-entry (point-max) t arg) | ||
| 761 | (setq new-text | ||
| 762 | (buffer-substring (match-beginning bibtex-text-in-cfield) | ||
| 763 | (match-end bibtex-text-in-cfield))) | ||
| 764 | ; Found a matching field. Remember boundaries. | ||
| 765 | (setq bibtex-pop-next-search-point (match-end 0)) | ||
| 766 | (setq bibtex-pop-previous-search-point (match-beginning 0)) | ||
| 767 | (bibtex-flash-head) | ||
| 768 | ; Go back to where we started, delete old text, and pop new. | ||
| 769 | (goto-char stop-old-text) | ||
| 770 | (delete-region start-old-text stop-old-text) | ||
| 771 | (insert new-text)) | ||
| 772 | (t ; search failed | ||
| 773 | (error "No next matching BibTeX field.")))))) | ||
| 774 | (setq this-command 'bibtex-pop-next)) | ||
| 775 | |||
| 776 | (defun bibtex-flash-head () | ||
| 777 | "Flash at BibTeX reference head before point, if exists. (Moves point)." | ||
| 778 | (let ((flash)) | ||
| 779 | (cond ((re-search-backward bibtex-reference-head (point-min) t) | ||
| 780 | (goto-char (match-beginning bibtex-type-in-head)) | ||
| 781 | (setq flash (match-end bibtex-key-in-reference))) | ||
| 782 | (t | ||
| 783 | (end-of-line) | ||
| 784 | (skip-chars-backward " \t") | ||
| 785 | (setq flash (point)) | ||
| 786 | (beginning-of-line) | ||
| 787 | (skip-chars-forward " \t"))) | ||
| 788 | (if (pos-visible-in-window-p (point)) | ||
| 789 | (sit-for 1) | ||
| 790 | (message "From: %s" | ||
| 791 | (buffer-substring (point) flash))))) | ||
| 792 | |||
| 793 | |||
| 794 | |||
| 795 | (defun bibtex-enclosing-field () | ||
| 796 | "Search for BibTeX field enclosing point. | ||
| 797 | Point moves to end of field; also, use match-beginning and match-end | ||
| 798 | to parse the field." | ||
| 799 | (condition-case errname | ||
| 800 | (bibtex-enclosing-regexp bibtex-field) | ||
| 801 | (search-failed | ||
| 802 | (error "Can't find enclosing BibTeX field.")))) | ||
| 803 | |||
| 804 | (defun bibtex-enclosing-reference () | ||
| 805 | "Search for BibTeX reference enclosing point. | ||
| 806 | Point moves to end of reference; also, use match-beginning and match-end | ||
| 807 | to parse the reference." | ||
| 808 | (condition-case errname | ||
| 809 | (bibtex-enclosing-regexp bibtex-reference) | ||
| 810 | (search-failed | ||
| 811 | (error "Can't find enclosing BibTeX reference.")))) | ||
| 812 | |||
| 813 | (defun bibtex-enclosing-regexp (regexp) | ||
| 814 | "Search for REGEXP enclosing point. | ||
| 815 | Point moves to end of REGEXP. See also match-beginning and match-end. | ||
| 816 | If an enclosing REGEXP is not found, signals search-failed; point is left in | ||
| 817 | an undefined location. | ||
| 818 | |||
| 819 | [Doesn't something like this exist already?]" | ||
| 820 | |||
| 821 | (interactive "sRegexp: ") | ||
| 822 | ; compute reasonable limits for the loop | ||
| 823 | (let* ((initial (point)) | ||
| 824 | (right (if (re-search-forward regexp (point-max) t) | ||
| 825 | (match-end 0) | ||
| 826 | (point-max))) | ||
| 827 | (left | ||
| 828 | (progn | ||
| 829 | (goto-char initial) | ||
| 830 | (if (re-search-backward regexp (point-min) t) | ||
| 831 | (match-beginning 0) | ||
| 832 | (point-min))))) | ||
| 833 | ; within the prescribed limits, loop until a match is found | ||
| 834 | (goto-char left) | ||
| 835 | (re-search-forward regexp right nil 1) | ||
| 836 | (if (> (match-beginning 0) initial) | ||
| 837 | (signal 'search-failed (list regexp))) | ||
| 838 | (while (<= (match-end 0) initial) | ||
| 839 | (re-search-forward regexp right nil 1) | ||
| 840 | (if (> (match-beginning 0) initial) | ||
| 841 | (signal 'search-failed (list regexp)))) | ||
| 842 | )) | ||
| 843 | |||
| 844 | (defun bibtex-clean-entry () | ||
| 845 | "For all optional fields of current BibTeX entry: if empty, kill the whole field; otherwise, remove the \"OPT\" string in the name; if text numerical, remove double-quotes. For all mandatory fields: if empty, signal error." | ||
| 846 | (interactive) | ||
| 847 | (bibtex-enclosing-reference) | ||
| 848 | (goto-char (match-beginning 0)) | ||
| 849 | (let ((start (point))) | ||
| 850 | (save-restriction | ||
| 851 | (narrow-to-region start (match-end 0)) | ||
| 852 | (while (re-search-forward bibtex-field (point-max) t 1) | ||
| 853 | (let ((begin-field (match-beginning 0)) | ||
| 854 | (end-field (match-end 0)) | ||
| 855 | (begin-name (match-beginning bibtex-name-in-field)) | ||
| 856 | (end-name (match-end bibtex-name-in-field)) | ||
| 857 | (begin-text (match-beginning bibtex-text-in-field)) | ||
| 858 | (end-text (match-end bibtex-text-in-field)) | ||
| 859 | ) | ||
| 860 | (goto-char begin-name) | ||
| 861 | (cond ((and | ||
| 862 | (looking-at "OPT") | ||
| 863 | bibtex-clean-entry-zap-empty-opts) | ||
| 864 | (goto-char begin-text) | ||
| 865 | (if (looking-at "\"\"") ; empty: delete whole field | ||
| 866 | (delete-region begin-field end-field) | ||
| 867 | ; otherwise: not empty, delete "OPT" | ||
| 868 | (goto-char begin-name) | ||
| 869 | (delete-char (length "OPT")) | ||
| 870 | (goto-char begin-field) ; and loop to go through next test | ||
| 871 | )) | ||
| 872 | (t | ||
| 873 | (goto-char begin-text) | ||
| 874 | (cond ((looking-at "\"[0-9]+\"") ; if numerical, | ||
| 875 | (goto-char end-text) | ||
| 876 | (delete-char -1) ; delete enclosing double-quotes | ||
| 877 | (goto-char begin-text) | ||
| 878 | (delete-char 1) | ||
| 879 | (goto-char end-field) ; go to end for next search | ||
| 880 | (forward-char -2) ; to compensate for the 2 quotes deleted | ||
| 881 | ) | ||
| 882 | ((looking-at "\"\"") ; if empty quotes, complain | ||
| 883 | (forward-char 1) | ||
| 884 | (if (not (or (equal (buffer-substring | ||
| 885 | begin-name | ||
| 886 | (+ begin-name 3)) | ||
| 887 | "OPT") | ||
| 888 | (equal (buffer-substring | ||
| 889 | begin-name | ||
| 890 | (+ begin-name 3)) | ||
| 891 | "opt"))) | ||
| 892 | (error "Mandatory field ``%s'' is empty" | ||
| 893 | (buffer-substring begin-name end-name)))) | ||
| 894 | (t | ||
| 895 | (goto-char end-field)))))))) | ||
| 896 | (goto-char start) | ||
| 897 | (skip-chars-forward "@a-zA-Z") | ||
| 898 | (bibtex-enclosing-reference) | ||
| 899 | (goto-char (match-end 0)) | ||
| 900 | (skip-chars-forward " \t\n"))) | ||
| 901 | |||
| 902 | |||
| 903 | |||
| 904 | ;;; X window menus for bibtex mode | ||
| 905 | |||
| 906 | (defun bibtex-x-help (arg) | ||
| 907 | "Mouse commands for BibTeX mode" | ||
| 908 | |||
| 909 | (let ((selection | ||
| 910 | (x-popup-menu | ||
| 911 | arg | ||
| 912 | '("BibTeX commands" | ||
| 913 | ("BibTeX entry types" | ||
| 914 | (" article in conference Proceedings " . bibtex-InProceedings) | ||
| 915 | (" Article in journal " . bibtex-Article) | ||
| 916 | (" Book " . bibtex-Book) | ||
| 917 | (" Booklet " . bibtex-Booklet) | ||
| 918 | (" Conference " . bibtex-InProceedings) | ||
| 919 | (" Master's Thesis " . bibtex-MastersThesis) | ||
| 920 | (" DEA Thesis " . bibtex-DEAthesis) | ||
| 921 | (" Phd. Thesis " . bibtex-PhdThesis) | ||
| 922 | (" Technical Report " . bibtex-TechReport) | ||
| 923 | (" technical Manual " . bibtex-Manual) | ||
| 924 | (" conference Proceedings " . bibtex-Proceedings) | ||
| 925 | (" a chapter in a Book " . bibtex-InBook) | ||
| 926 | (" an article in a Collection " . bibtex-InCollection) | ||
| 927 | (" miscellaneous " . bibtex-Misc) | ||
| 928 | (" unpublished " . bibtex-Unpublished) | ||
| 929 | (" string " . bibtex-string) | ||
| 930 | (" preamble " . bibtex-preamble) | ||
| 931 | ) | ||
| 932 | ("Moving around and editing" | ||
| 933 | (" next field " . bibtex-next-field) | ||
| 934 | (" to end of field " . bibtex-find-text) | ||
| 935 | ("snatch from similar preceding field" . bibtex-pop-previous) | ||
| 936 | ("snatch from similar following field" . bibtex-pop-next) | ||
| 937 | (" remove OPT " . bibtex-remove-OPT) | ||
| 938 | (" remove quotes " | ||
| 939 | . bibtex-remove-double-quotes) | ||
| 940 | (" clean up entry " . bibtex-clean-entry) | ||
| 941 | ) | ||
| 942 | ("help" | ||
| 943 | (" describe BibTeX mode " . describe-mode) | ||
| 944 | ))))) | ||
| 945 | (and selection (call-interactively selection)))) | ||
| 946 | |||
| 947 | (defun bibtex-x-environment () | ||
| 948 | "Set up X menus for BibTeX mode. Call it as bibtex-mode-hook, or interactively" | ||
| 949 | (interactive) | ||
| 950 | (require 'x-mouse) | ||
| 951 | (define-key mouse-map x-button-c-right 'bibtex-x-help) | ||
| 952 | ) | ||
| 953 | |||
| 954 | |||
| 955 | |||
| 956 | ;; Please don't send anything to bug-gnu-emacs about these Sunwindows functions | ||
| 957 | ;; since we aren't interested. See etc/SUN-SUPPORT for the reasons why | ||
| 958 | ;; we consider this nothing but a distraction from our work. | ||
| 959 | |||
| 960 | (if (fboundp 'defmenu) | ||
| 961 | (progn | ||
| 962 | |||
| 963 | (defmenu bibtex-sun-entry-menu | ||
| 964 | ("Article In Conf. Proc." | ||
| 965 | (lambda () (eval-in-window *menu-window* (bibtex-InProceedings)))) | ||
| 966 | ("Article In Journal" | ||
| 967 | (lambda () (eval-in-window *menu-window* (bibtex-Article)))) | ||
| 968 | ("Book" | ||
| 969 | (lambda () (eval-in-window *menu-window* (bibtex-Book)))) | ||
| 970 | ("Booklet" | ||
| 971 | (lambda () (eval-in-window *menu-window* (bibtex-Booklet)))) | ||
| 972 | ("Master's Thesis" | ||
| 973 | (lambda () (eval-in-window *menu-window* (bibtex-MastersThesis)))) | ||
| 974 | ;;("DEA Thesis" bibtex-DEAthesis) | ||
| 975 | ("PhD. Thesis" | ||
| 976 | (lambda () (eval-in-window *menu-window* (bibtex-PhdThesis)))) | ||
| 977 | ("Technical Report" | ||
| 978 | (lambda () (eval-in-window *menu-window* (bibtex-TechReport)))) | ||
| 979 | ("Technical Manual" | ||
| 980 | (lambda () (eval-in-window *menu-window* (bibtex-Manual)))) | ||
| 981 | ("Conference Proceedings" | ||
| 982 | (lambda () (eval-in-window *menu-window* (bibtex-Proceedings)))) | ||
| 983 | ("In A Book" | ||
| 984 | (lambda () (eval-in-window *menu-window* (bibtex-InBook)))) | ||
| 985 | ("In A Collection" | ||
| 986 | (lambda () (eval-in-window *menu-window* (bibtex-InCollection)))) | ||
| 987 | ("Miscellaneous" | ||
| 988 | (lambda () (eval-in-window *menu-window* (bibtex-Misc)))) | ||
| 989 | ("Unpublished" | ||
| 990 | (lambda () (eval-in-window *menu-window* (bibtex-Unpublished))))) | ||
| 991 | |||
| 992 | (defmenu bibtex-sun-menu | ||
| 993 | ("BibTeX menu") | ||
| 994 | ("add entry" . bibtex-sun-entry-menu) | ||
| 995 | ("add string" | ||
| 996 | (lambda () (eval-in-window *menu-window* (bibtex-string)))) | ||
| 997 | ;("next field" bibtex-next-position) | ||
| 998 | ;("to end of field" bibtex-find-it) | ||
| 999 | ; ("remove OPT" | ||
| 1000 | ; (lambda () (eval-in-window *menu-window* (bibtex-remove-opt)))) | ||
| 1001 | ; ("remove quotes" | ||
| 1002 | ; (lambda () (eval-in-window *menu-window* (bibtex-remove-double-quotes)))) | ||
| 1003 | ; ("remove this line" | ||
| 1004 | ; (lambda () (eval-in-window *menu-window* (kill-current-line)))) | ||
| 1005 | ("describe BibTeX mode" | ||
| 1006 | (lambda () (eval-in-window *menu-window* (describe-mode)))) | ||
| 1007 | ("Main Emacs menu" . emacs-menu)) | ||
| 1008 | |||
| 1009 | (defun bibtex-sun-menu-eval (window x y) | ||
| 1010 | "Pop-up menu of BibTeX commands." | ||
| 1011 | (sun-menu-evaluate window (1+ x) (1- y) 'bibtex-sun-menu)) | ||
| 1012 | |||
| 1013 | (defun bibtex-sun-environment () | ||
| 1014 | "Set up sun menus for BibTeX mode. Call it as bibtex-mode-hook, or interactively" | ||
| 1015 | (interactive) | ||
| 1016 | (local-set-mouse '(text right) 'bibtex-sun-menu-eval)) | ||
| 1017 | |||
| 1018 | )) ; matches (if... | ||
| 1019 | |||
| 1020 | ;;; ------------- end bibtex-mode.el ------------------------------- | ||