1;;; refbib.el --- convert refer-style references to ones usable by Latex bib
2
3;; Copyright (C) 1989, 2001, 2002, 2003, 2004, 2005,
4;;   2006, 2007 Free Software Foundation, Inc.
5
6;; Author: Henry Kautz <kautz@research.att.com>
7;; Maintainer: FSF
8;; Keywords: bib, tex
9
10;; This file is part of GNU Emacs.
11
12;; GNU Emacs is free software; you can redistribute it and/or modify
13;; it under the terms of the GNU General Public License as published by
14;; the Free Software Foundation; either version 2, or (at your option)
15;; any later version.
16
17;; GNU Emacs is distributed in the hope that it will be useful,
18;; but WITHOUT ANY WARRANTY; without even the implied warranty of
19;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20;; GNU General Public License for more details.
21
22;; You should have received a copy of the GNU General Public License
23;; along with GNU Emacs; see the file COPYING.  If not, write to the
24;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
25;; Boston, MA 02110-1301, USA.
26
27;;; Commentary:
28
29;; Use: from a buffer containing the refer-style bibliography,
30;;   M-x r2b-convert-buffer
31;; Program will prompt for an output buffer name, and will log
32;; warnings during the conversion process in the buffer *Log*.
33
34;;; Change Log:
35
36;; HISTORY
37;; 9/88, created H.Kautz
38;; modified 1/19/89, allow books with editor but no author;
39;;                   added %O ordering field;
40;;                   appended invalid multiple fields, instead of
41;;                     discarding;
42;;                   added rule, a tech report whose %R number
43;;                     contains "ISBN" is really a book
44;;                   added rule, anything with an editor is a book
45;;                     or a proceedings
46;;                   added 'manual type, for items with institution
47;;                     but no author or editor
48;;                   fixed bug so trailing blanks are trimmed
49;;                   added 'proceedings type
50;;                   used "organization" field for proceedings
51;; modified 2/16/89, updated help messages
52;; modified 2/23/89, include capitalize stop words in r2b stop words,
53;;                   fixed problems with contractions (e.g. it's),
54;;                   caught multiple stop words in a row
55;; modified 3/1/89,  fixed capitalize-title for first words all caps
56;; modified 3/15/89, allow use of " to delimit fields
57;; modified 4/18/89, properly "quote" special characters on output
58
59;;; Code:
60
61;**********************************************************
62; User Parameters
63
64(defgroup refbib nil
65  "Convert refer-style references to ones usable by Latex bib."
66  :prefix "r2b-"
67  :group 'wp)
68
69(defcustom r2b-trace-on nil
70  "*Non-nil means trace conversion."
71  :type 'boolean
72  :group 'refbib)
73
74(defcustom r2b-journal-abbrevs
75  '(
76    )
77  "Abbreviation list for journal names.
78If the car of an element matches a journal name exactly, it is replaced by
79the cadr when output.  Braces must be included if replacement is a
80{string}, but not if replacement is a bibtex abbreviation.  The cadr
81may be eliminated if is exactly the same as the car.
82  Because titles are capitalized before matching, the abbreviation
83for the journal name should be listed as beginning with a capital
84letter, even if it really doesn't.
85  For example, a value of '((\"Aij\" \"{Artificial Intelligence}\")
86\(\"Ijcai81\" \"ijcai7\")) would expand Aij to the text string
87\"Artificial Intelligence\", but would replace Ijcai81 with the
88BibTeX macro \"ijcai7\"."
89  :type '(repeat (list string string))
90  :group 'refbib)
91
92(defcustom r2b-booktitle-abbrevs
93  '(
94    )
95  "Abbreviation list for book and proceedings names.
96If the car of an element matches a title or booktitle exactly, it is
97replaced by the cadr when output.  Braces must be included if
98replacement is a {string}, but not if replacement is a bibtex
99abbreviation.  The cadr may be eliminated if is exactly the same as
100the car.
101  Because titles are capitalized before matching, the abbreviated title
102should be listed as beginning with a capital letter, even if it doesn't.
103  For example, a value of '((\"Aij\" \"{Artificial Intelligence}\")
104\(\"Ijcai81\" \"ijcai7\")) would expand Aij to the text string
105\"Artificial Intelligence\", but would replace Ijcai81 with the
106BibTeX macro \"ijcai7\"."
107  :type '(repeat (list string string))
108  :group 'refbib)
109
110(defcustom r2b-proceedings-list
111  '()
112  "Assoc list of books or journals which are really conference proceedings,
113but whose name and whose abbrev expansion (as defined in `r2b-journal-abbrevs'
114and `r2b-booktitle-abbrevs') does not contain the words \"conference\" or
115\"proceedings\".  (Those cases are handled automatically.)
116The entry must match the given data exactly.
117  Because titles are capitalized before matching, the items in this list
118should begin with a capital letter.
119  For example, suppose the title \"Ijcai81\" is used for the proceedings of
120a conference, and its expansion is the BibTeX macro \"ijcai7\".  Then
121`r2b-proceedings-list' should be '((\"Ijcai81\") ...).  If instead its
122expansion were \"Proceedings of the Seventh International Conference
123on Artificial Intelligence\", then you would NOT need to include Ijcai81
124in `r2b-proceedings-list' (although it wouldn't cause an error)."
125  :type '(repeat (list string string))
126  :group 'refbib)
127
128(defvar r2b-additional-stop-words
129  "Some\\|What"
130  "Words not to be used to build the citation key.
131This is in addition to the `r2b-capitalize-title-stop-words'.")
132
133(defcustom r2b-delimit-with-quote t
134  "*If true, then use \" to delimit fields, otherwise use braces."
135  :type 'boolean
136  :group 'refbib)
137
138;**********************************************************
139; Utility Functions
140
141(defvar r2b-capitalize-title-stop-words
142   (concat
143      "the\\|and\\|of\\|is\\|a\\|an\\|of\\|for\\|in\\|to\\|in\\|on\\|at\\|"
144      "by\\|with\\|that\\|its")
145   "Words not to be capitalized in a title (unless the first word).")
146
147(defvar r2b-capitalize-title-stop-regexp
148   (concat "\\(" r2b-capitalize-title-stop-words "\\)\\(\\b\\|'\\)"))
149
150(defun r2b-capitalize-title-region (begin end)
151   "Like `capitalize-region', but don't capitalize stop words, except the first."
152   (interactive "r")
153   (let ((case-fold-search nil) (orig-syntax-table (syntax-table)))
154      (unwind-protect
155	 (save-restriction
156	    (set-syntax-table text-mode-syntax-table)
157	    (narrow-to-region begin end)
158	    (goto-char (point-min))
159	    (if (looking-at "[A-Z][a-z]*[A-Z]")
160	       (forward-word 1)
161	       (capitalize-word 1))
162	    (while (re-search-forward "\\<" nil t)
163	       (if (looking-at "[A-Z][a-z]*[A-Z]")
164		  (forward-word 1)
165		  (if (let ((case-fold-search t))
166			 (looking-at r2b-capitalize-title-stop-regexp))
167		     (downcase-word 1)
168		     (capitalize-word 1)))
169	       ))
170	 (set-syntax-table orig-syntax-table))))
171
172
173(defun r2b-capitalize-title (s)
174   "Like `capitalize', but don't capitalize stop words, except the first."
175   (save-excursion
176      (set-buffer (get-buffer-create "$$$Scratch$$$"))
177      (erase-buffer)
178      (insert s)
179      (r2b-capitalize-title-region (point-min) (point-max))
180      (buffer-string)))
181
182;*********************************************************
183(defun r2b-reset ()
184   "Unbind defvars, for debugging."
185   (interactive)
186   (makunbound 'r2b-journal-abbrevs)
187   (makunbound 'r2b-booktitle-abbrevs)
188   (makunbound 'r2b-proceedings-list)
189   (makunbound 'r2b-capitalize-title-stop-words)
190   (makunbound 'r2b-capitalize-title-stop-regexp)
191   (makunbound 'r2b-additional-stop-words)
192   (makunbound 'r2b-stop-regexp))
193
194(defvar r2b-stop-regexp
195   (concat "\\`\\(\\("
196      r2b-additional-stop-words "\\|" r2b-capitalize-title-stop-words
197      "\\)\\('\\w*\\)?\\W+\\)*\\([A-Z0-9]+\\)"))
198
199
200(defun r2b-trace (&rest args)
201   (if r2b-trace-on
202      (progn
203	 (apply (function message) args)
204	 (sit-for 0))))
205
206(defun r2b-match (exp)
207   "Returns string matched in current buffer."
208   (buffer-substring (match-beginning exp) (match-end exp)))
209
210(defcustom r2b-out-buf-name "*Out*"
211  "*Name of buffer for output from refer-to-bibtex."
212  :type 'string
213  :group 'refbib)
214
215(defcustom r2b-log-name "*Log*"
216  "*Name of buffer for logs errors from refer-to-bibtex."
217  :type 'string
218  :group 'refbib)
219
220(defvar r2b-in-buf nil)
221(defvar r2b-out-buf nil)
222(defvar r2b-log nil)
223
224(defvar r2b-error-found nil)
225
226(eval-when-compile
227  (defvar r2b-variables) (defvar r2bv-address)    (defvar r2bv-annote)
228  (defvar r2bv-author)   (defvar r2bv-booktitle)  (defvar r2bv-date)
229  (defvar r2bv-decade)   (defvar r2bv-editor)     (defvar r2bv-entry-kind)
230  (defvar r2bv-institution) (defvar r2bv-journal) (defvar r2bv-keywords)
231  (defvar r2bv-kn)       (defvar r2bv-month)      (defvar r2bv-note)
232  (defvar r2bv-number)   (defvar r2bv-ordering)   (defvar r2bv-organization)
233  (defvar r2bv-pages)    (defvar r2bv-primary-author) (defvar r2bv-publisher)
234  (defvar r2bv-school)   (defvar r2bv-title)      (defvar r2bv-title-first-word)
235  (defvar r2bv-tr)       (defvar r2bv-type)       (defvar r2bv-volume)
236  (defvar r2bv-where)    (defvar r2bv-year))
237
238(setq r2b-variables '(
239                      r2b-error-found
240                      r2bv-author
241                      r2bv-primary-author
242                      r2bv-date
243                      r2bv-year
244                      r2bv-decade
245                      r2bv-month
246                      r2bv-title
247                      r2bv-title-first-word
248                      r2bv-editor
249                      r2bv-annote
250                      r2bv-tr
251                      r2bv-address
252                      r2bv-institution
253                      r2bv-keywords
254                      r2bv-booktitle
255                      r2bv-journal
256                      r2bv-volume
257                      r2bv-number
258                      r2bv-pages
259                      r2bv-booktitle
260                      r2bv-kn
261                      r2bv-publisher
262                      r2bv-organization
263                      r2bv-school
264                      r2bv-type
265                      r2bv-where
266                      r2bv-note
267                      r2bv-ordering
268                      ))
269
270(defun r2b-clear-variables ()
271   "Set all global vars used by r2b to nil."
272   (let ((vars r2b-variables))
273      (while vars
274	 (set (car vars) nil)
275	 (setq vars (cdr vars)))))
276
277(defun r2b-warning (&rest args)
278   (setq r2b-error-found t)
279   (princ (apply (function format) args) r2b-log)
280   (princ "\n" r2b-log)
281   (princ "\n" r2b-out-buf)
282   (princ "% " r2b-out-buf)
283   (princ (apply (function format) args) r2b-out-buf))
284
285(defun r2b-get-field (var field &optional unique required capitalize)
286   "Set VAR to string value of FIELD, if any.  If none, VAR is set to
287nil.  If multiple fields appear, then separate values with the
288'\\nand\\t\\t', unless UNIQUE is non-nil, in which case log a warning
289and just concatenate the values.  Trim off leading blanks and tabs on
290first line, and trailing blanks and tabs of every line.  Log a warning
291and set VAR to the empty string if REQUIRED is true.  Capitalize as a
292title if CAPITALIZE is true.  Returns value of VAR."
293   (let (item val (not-past-end t))
294      (r2b-trace "snarfing %s" field)
295      (goto-char (point-min))
296      (while (and not-past-end
297		(re-search-forward
298		   (concat "^" field "\\b[ \t]*\\(.*[^ \t\n]\\)[ \t]*") nil t))
299	 (setq item (r2b-match 1))
300	 (while (and (setq not-past-end (zerop (forward-line 1)))
301		   (not (looking-at "[ \t]*$\\|%")))
302	       (looking-at "\\(.*[^ \t\n]\\)[ \t]*$")
303	       (setq item (concat item "\n" (r2b-match 1)))
304	    )
305	 (if (null val)
306	    (setq val item)
307	    (if unique
308	       (progn
309		  (r2b-warning "*Invalid multiple field %s %s" field item)
310		  (setq val (concat val "\n" item))
311		  )
312	       (setq val (concat val "\n\t\tand " item))
313	       )
314	    )
315	 )
316      (if (and val capitalize)
317	 (setq val (r2b-capitalize-title val)))
318      (set var val)
319      (if (and (null val) required)
320	 (r2b-require var))
321      ))
322
323(defun r2b-set-match (var n regexp string )
324   "Set VAR to the Nth subpattern in REGEXP matched by STRING, or nil if none."
325   (set var
326      (if (and (stringp string) (string-match regexp string))
327	 (substring string (match-beginning n) (match-end n))
328	 nil)
329      )
330   )
331
332(defvar r2b-month-abbrevs
333   '(("jan") ("feb") ("mar") ("apr") ("may") ("jun") ("jul") ("aug")
334       ("sep") ("oct") ("nov") ("dec")))
335
336(defun r2b-convert-month ()
337   "Try to convert `r2bv-month' to a standard 3 letter name."
338   (if r2bv-month
339      (let ((months r2b-month-abbrevs))
340	 (if (string-match "[^0-9]" r2bv-month)
341	    (progn
342	       (while (and months (not (string-match (car (car months))
343					  r2bv-month)))
344		  (setq months (cdr months)))
345	       (if months
346		  (setq r2bv-month (car (car months)))))
347	    (progn
348	       (setq months (car (read-from-string r2bv-month)))
349	       (if (and (numberp months)
350		      (> months 0)
351		      (< months 13))
352		  (setq r2bv-month (car (nth months r2b-month-abbrevs)))
353		  (progn
354		     (r2b-warning "* Ridiculous month")
355		     (setq r2bv-month nil))
356		  ))
357	    ))
358      )
359   )
360
361(defun r2b-snarf-input ()
362   "Parse buffer into global variables."
363   (let ((case-fold-search t))
364      (r2b-trace "snarfing...")
365      (sit-for 0)
366      (set-buffer r2b-in-buf)
367      (goto-char (point-min))
368      (princ "    " r2b-log)
369      (princ (buffer-substring (point) (progn (end-of-line) (point))) r2b-log)
370      (terpri r2b-log)
371
372      (r2b-get-field 'r2bv-author "%A")
373      (r2b-get-field 'r2bv-editor "%E")
374      (cond
375	 (r2bv-author
376	    (r2b-set-match 'r2bv-primary-author 1
377	       "\\b\\(\\w+\\)[ \t]*\\($\\|,\\)" r2bv-author)
378	    )
379	 (r2bv-editor
380	    (r2b-set-match 'r2bv-primary-author 1
381	       "\\b\\(\\w+\\)[ \t]*\\($\\|,\\)" r2bv-editor)
382	    )
383	 (t
384	    (setq r2bv-primary-author "")
385	    )
386	 )
387
388      (r2b-get-field 'r2bv-date "%D" t t)
389      (r2b-set-match 'r2bv-year 0 "[12][0-9][0-9][0-9]" r2bv-date)
390      (and (null r2bv-year)
391	 (r2b-set-match 'r2bv-year 1 "[^0-9]\\([0-9][0-9]\\)$" r2bv-date)
392	 (setq r2bv-year (concat "19" r2bv-year)))
393      (r2b-set-match 'r2bv-decade 1 "..\\(..\\)" r2bv-year)
394      (r2b-set-match 'r2bv-month 0
395	 "[0-9]+/\\|[a-zA-Z]+" r2bv-date)
396      (if (and (stringp r2bv-month) (string-match "\\(.*\\)/$" r2bv-month))
397	 (setq r2bv-month (substring r2bv-month 0 (match-end 1))))
398      (r2b-convert-month)
399
400      (r2b-get-field 'r2bv-title "%T" t t t)
401      (r2b-set-match 'r2bv-title-first-word 4
402	 r2b-stop-regexp
403	 r2bv-title)
404
405      (r2b-get-field 'r2bv-annote "%X" t )
406      (r2b-get-field 'r2bv-tr "%R" t)
407      (r2b-get-field 'r2bv-address "%C" t)
408      (r2b-get-field 'r2bv-institution "%I" t)
409      (r2b-get-field 'r2bv-keywords "%K")
410      (r2b-get-field 'r2bv-booktitle "%B" t nil t)
411      (r2b-get-field 'r2bv-journal "%J" t nil t)
412      (r2b-get-field 'r2bv-volume "%V" t)
413      (r2b-get-field 'r2bv-number "%N" t)
414      (r2b-get-field 'r2bv-pages "%P" t)
415      (r2b-get-field 'r2bv-where "%W" t)
416      (r2b-get-field 'r2bv-ordering "%O" t)
417      )
418   )
419
420
421(defun r2b-put-field (field data &optional abbrevs)
422  "Print bibtex FIELD = {DATA} if DATA not null; precede
423with a comma and newline; if ABBREVS list is given, then
424try to replace the {DATA} with an abbreviation."
425  (if data
426    (let (match nodelim multi-line index)
427      (cond
428	((and abbrevs (setq match (assoc data abbrevs)))
429	  (if (null (cdr match))
430	    (setq data (car match))
431	    (setq data (car (cdr match))))
432	  (setq nodelim t))
433	((and (not (equal data ""))
434		(not (string-match "[^0-9]" data)))
435	  (setq nodelim t))
436	(t
437	  (setq index 0)
438	  (while (string-match "[\\~^]" data index)
439	    (setq data (concat (substring data 0 (match-beginning 0))
440			 "\\verb+"
441			 (substring data (match-beginning 0) (match-end 0))
442			 "+"
443			 (substring data (match-end 0))))
444	    (setq index (+ (match-end 0) 7)))
445	  (setq index 0)
446	  (while (string-match "[$&%#_{}]" data index)
447	    (setq data (concat (substring data 0 (match-beginning 0))
448			 "\\"
449			 (substring data (match-beginning 0))))
450	    (setq index (+ (match-end 0) 1)))
451	  (setq index 0)
452	  (if r2b-delimit-with-quote
453	    (while (string-match "\"" data index)
454	      (setq data (concat (substring data 0 (match-beginning 0))
455			   "{\"}"
456			   (substring data (match-end 0))))
457	      (setq index (+ (match-end 0) 2))))
458	    ))
459      (princ ", \n  ")
460      (princ field)
461      (princ " =\t")
462      (if (not nodelim)
463	(if r2b-delimit-with-quote
464	  (princ "\"")
465	  (princ "{")))
466      (string-match ".*" data)
467      (if (> (match-end 0) 59)
468	(princ "\n"))
469      (princ data)
470      (if (not nodelim)
471	(if r2b-delimit-with-quote
472	  (princ "\"")
473	  (princ "}")))
474      )
475    ))
476
477
478(defun r2b-require (vars)
479   "If any of VARS is null, set to empty string and log error."
480   (cond
481      ((null vars))
482      ((listp vars) (r2b-require (car vars)) (r2b-require (cdr vars)))
483      (t
484	 (if (null (symbol-value vars))
485	    (progn
486	       (r2b-warning "*Missing value for field %s" vars)
487	       (set vars "")
488	       )))
489      )
490   )
491
492
493(defmacro r2b-moveq (new old)
494   "Set NEW to OLD and set OLD to nil."
495   (list 'progn (list 'setq new old) (list 'setq old 'nil)))
496
497(defun r2b-isa-proceedings (name)
498   "Return t if NAME is the name of proceedings."
499   (and
500      name
501      (or
502	 (string-match "proceedings\\|conference" name)
503	 (assoc name r2b-proceedings-list)
504	 (let ((match (assoc name r2b-booktitle-abbrevs)))
505	    (and match
506	       (string-match "proceedings\\|conference" (car (cdr match)))))
507      )))
508
509(defun r2b-isa-university (name)
510   "Return t if NAME is a university or similar organization,
511but not a publisher."
512   (and
513      name
514      (string-match "university" name)
515      (not (string-match "press" name))
516
517   ))
518
519(defun r2b-barf-output ()
520   "Generate bibtex based on global variables."
521   (let ((standard-output r2b-out-buf) (case-fold-search t) match)
522
523      (r2b-trace "...barfing")
524      (sit-for 0)
525      (set-buffer r2b-out-buf)
526
527      (setq r2bv-kn (concat r2bv-primary-author r2bv-decade
528			r2bv-title-first-word))
529
530      (setq r2bv-entry-kind
531	 (cond
532	    ((r2b-isa-proceedings r2bv-journal)
533	       (r2b-moveq r2bv-booktitle r2bv-journal)
534	       (if (r2b-isa-university r2bv-institution)
535		  (r2b-moveq r2bv-organization r2bv-institution)
536		  (r2b-moveq r2bv-publisher r2bv-institution))
537	       (r2b-moveq r2bv-note r2bv-tr)
538	       (r2b-require 'r2bv-author)
539	       'inproceedings)
540	    ((r2b-isa-proceedings r2bv-booktitle)
541	       (if (r2b-isa-university r2bv-institution)
542		  (r2b-moveq r2bv-organization r2bv-institution)
543		  (r2b-moveq r2bv-publisher r2bv-institution))
544	       (r2b-moveq r2bv-note r2bv-tr)
545	       (r2b-require 'r2bv-author)
546	       'inproceedings)
547	    ((and r2bv-tr (string-match "phd" r2bv-tr))
548	       (r2b-moveq r2bv-school r2bv-institution)
549	       (r2b-require 'r2bv-school )
550	       (r2b-require 'r2bv-author)
551	       'phdthesis)
552	    ((and r2bv-tr (string-match "master" r2bv-tr))
553	       (r2b-moveq r2bv-school r2bv-institution)
554	       (r2b-require 'r2bv-school )
555	       (r2b-require 'r2bv-author)
556	       'mastersthesis)
557	    ((and r2bv-tr (string-match "draft\\|unpublish" r2bv-tr))
558	       (r2b-moveq r2bv-note r2bv-institution)
559	       (r2b-require 'r2bv-author)
560	       'unpublished)
561	    (r2bv-journal
562	       (r2b-require 'r2bv-author)
563	       'article)
564	    (r2bv-booktitle
565	       (r2b-moveq r2bv-publisher r2bv-institution)
566	       (r2b-moveq r2bv-note r2bv-tr)
567	       (r2b-require 'r2bv-publisher)
568	       (r2b-require 'r2bv-author)
569	       'incollection)
570	    ((and r2bv-author
571		(null r2bv-editor)
572		(string-match "\\`personal communication\\'" r2bv-title))
573	       'misc)
574	    ((r2b-isa-proceedings r2bv-title)
575	       (if (r2b-isa-university r2bv-institution)
576		  (r2b-moveq r2bv-organization r2bv-institution)
577		  (r2b-moveq r2bv-publisher r2bv-institution))
578	       (r2b-moveq r2bv-note r2bv-tr)
579	       'proceedings)
580	    ((or r2bv-editor
581		(and r2bv-author
582		   (or
583		      (null r2bv-tr)
584		      (string-match "\\bisbn\\b" r2bv-tr))))
585	       (r2b-moveq r2bv-publisher r2bv-institution)
586	       (r2b-moveq r2bv-note r2bv-tr)
587	       (r2b-require 'r2bv-publisher)
588	       (if (null r2bv-editor)
589		  (r2b-require 'r2bv-author))
590	       'book)
591	    (r2bv-tr
592	       (r2b-require 'r2bv-institution)
593	       (if (string-match
594		      "\\`\\(\\(.\\|\n\\)+\\)[ \t\n]+\\([^ \t\n]\\)+\\'"
595		      r2bv-tr)
596		  (progn
597		     (setq r2bv-type (substring r2bv-tr 0 (match-end 1)))
598		     (setq r2bv-number (substring r2bv-tr
599					  (match-beginning 3)))
600		     (setq r2bv-tr nil))
601		  (r2b-moveq r2bv-number r2bv-tr))
602	       (r2b-require 'r2bv-author)
603	       'techreport)
604	    (r2bv-institution
605	       (r2b-moveq r2bv-organization r2bv-institution)
606	       'manual)
607	    (t
608	       'misc)
609	    ))
610
611      (r2b-require '( r2bv-year))
612
613      (if r2b-error-found
614	 (princ "\n% Warning -- Errors During Conversion Next Entry\n"))
615
616      (princ "\n@")
617      (princ r2bv-entry-kind)
618      (princ "( ")
619      (princ r2bv-kn)
620
621      (r2b-put-field "author" r2bv-author )
622      (r2b-put-field "title" r2bv-title r2b-booktitle-abbrevs)
623      (r2b-put-field "year" r2bv-year )
624
625      (r2b-put-field "month" r2bv-month r2b-month-abbrevs)
626      (r2b-put-field "journal" r2bv-journal r2b-journal-abbrevs)
627      (r2b-put-field "volume" r2bv-volume)
628      (r2b-put-field "type" r2bv-type)
629      (r2b-put-field "number" r2bv-number)
630      (r2b-put-field "booktitle" r2bv-booktitle r2b-booktitle-abbrevs)
631      (r2b-put-field "editor" r2bv-editor)
632      (r2b-put-field "publisher" r2bv-publisher)
633      (r2b-put-field "institution" r2bv-institution)
634      (r2b-put-field "organization" r2bv-organization)
635      (r2b-put-field "school" r2bv-school)
636      (r2b-put-field "pages" r2bv-pages)
637      (r2b-put-field "address" r2bv-address)
638      (r2b-put-field "note" r2bv-note)
639      (r2b-put-field "keywords" r2bv-keywords)
640      (r2b-put-field "where" r2bv-where)
641      (r2b-put-field "ordering" r2bv-ordering)
642      (r2b-put-field "annote" r2bv-annote)
643
644      (princ " )\n")
645      )
646   )
647
648
649(defun r2b-convert-record (output)
650   "Transform current bib entry and append to buffer OUTPUT.
651Do `\\[r2b-help]' for more info."
652   (interactive
653      (list (read-string "Output to buffer: " r2b-out-buf-name)))
654   (let (rec-end rec-begin not-done)
655      (setq r2b-out-buf-name output)
656      (setq r2b-out-buf (get-buffer-create output))
657      (setq r2b-in-buf (current-buffer))
658      (set-buffer r2b-out-buf)
659      (goto-char (point-max))
660      (setq r2b-log (get-buffer-create r2b-log-name))
661      (set-buffer r2b-log)
662      (goto-char (point-max))
663      (set-buffer r2b-in-buf)
664      (setq not-done (re-search-forward "[^ \t\n]" nil t))
665      (if not-done
666	 (progn
667	    (re-search-backward "^[ \t]*$" nil 2)
668	    (re-search-forward "^%")
669	    (beginning-of-line nil)
670	    (setq rec-begin (point))
671	    (re-search-forward "^[ \t]*$" nil 2)
672	    (setq rec-end (point))
673	    (narrow-to-region rec-begin rec-end)
674	    (r2b-clear-variables)
675	    (r2b-snarf-input)
676	    (r2b-barf-output)
677	    (set-buffer r2b-in-buf)
678	    (widen)
679	    (goto-char rec-end)
680	    t)
681	 nil
682	 )
683      ))
684
685
686(defun r2b-convert-buffer (output)
687   "Transform current buffer and append to buffer OUTPUT.
688Do `\\[r2b-help]' for more info."
689   (interactive
690      (list (read-string "Output to buffer: " r2b-out-buf-name)))
691   (save-excursion
692      (setq r2b-log (get-buffer-create r2b-log-name))
693      (set-buffer r2b-log)
694      (erase-buffer))
695   (widen)
696   (goto-char (point-min))
697   (message "Working, please be patient...")
698   (sit-for 0)
699   (while (r2b-convert-record output) t)
700   (message "Done, results in %s, errors in %s"
701      r2b-out-buf-name r2b-log-name)
702   )
703
704(defvar r2b-help-message
705"                   Refer to Bibtex Bibliography Conversion
706
707A refer-style database is of the form:
708
709%A Joe Blow
710%T Great Thoughts I've Thought
711%D 1977
712etc.
713
714This utility converts these kind of databases to bibtex form, for
715users of TeX and LaTex.  Instructions:
7161.  Visit the file containing the refer-style database.
7172.  The command
718	M-x r2b-convert-buffer
719    converts the entire buffer, appending its output by default in a
720    buffer named *Out*, and logging progress and errors in a buffer
721    named *Log*.  The original file is never modified.
722	Note that results are appended to *Out*, so if that buffer
723	buffer already exists and contains material you don't want to
724 	save, you should kill it first.
7253.  Switch to the buffer *Out* and save it as a named file.
7264.  To convert a single refer-style entry, simply position the cursor
727    at the entry and enter
728	M-x r2b-convert-record
729    Again output is appended to *Out* and errors are logged in *Log*.
730
731This utility is very robust and pretty smart about determining the
732type of the entry.  It includes facilities for expanding refer macros
733to text, or substituting bibtex macros.  Do M-x describe-variable on
734     r2b-journal-abbrevs
735     r2b-booktitle-abbrevs
736     r2b-proceedings-list
737for information on these features.
738
739Please send bug reports and suggestions to
740	Henry Kautz
741        kautz@research.att.com
742	allegra!kautz")
743
744
745(defun r2b-help ()
746   "Print help describing the `refbib' package."
747   (interactive)
748   (with-output-to-temp-buffer "*Help*"
749      (princ r2b-help-message)
750      (save-excursion
751	(set-buffer standard-output)
752	(help-mode))))
753
754(provide 'refbib)
755(provide 'refer-to-bibtex)
756
757;;; arch-tag: 664afee2-6e76-4408-ba56-981d8a179586
758;;; refbib.el ends here
759