home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / languages / elisp / packages / MouseAndMenuEmacs / BibTeX-mode.el < prev    next >
Encoding:
Text File  |  1990-05-31  |  25.6 KB  |  731 lines

  1. ;;; BibTeX mode for GNU Emacs
  2.  
  3. ;;; Russell Ritchie 3-oct-88
  4. ;;;  * bibtex-mode now tries to call 'BibTeX-mode-hook instead of
  5. ;;;    'bibtex-mode-hook (which is tried if 'BibTeX-mode-hook is unbound/nil).
  6. ;;;    Added "BibTeX-mode-menus.el" file for Scottish HCI Centre Menu code,
  7. ;;;    duplicates X Windows functionality in the HCI menu environment.
  8.  
  9. ;;; Marc Shapiro 23-sep-88
  10. ;;;  * bibtex-clean-entry moves past end of entry.
  11. ;;;  * bibtex-clean-entry signals mandatory fields left empty.
  12.  
  13. ;;; Marc Shapiro 18-jul-88
  14. ;;;  * Fixed bug in bibtex-flash-entry
  15. ;;;  * Moved all the entry type keystrokes to "C-c C-e something" (instead of
  16. ;;;    "C-c something" previously) to make room for more.  C-c C-e is
  17. ;;;    supposed to stand for "entry" [idea taken from mail-mode].  Moved
  18. ;;;    bibtex-pop-previous to C-c C-p and bibtex-pop-next to C-c C-n.
  19. ;;;  * removed binding for "\e[25~"
  20. ;;;  * replaced bibtex-clean-optionals by bibtex-clean-entry, bound to
  21. ;;;    C-c C-c
  22.  
  23. ;;; Marc Shapiro 13-jul-88 [based on ideas by Sacha Krakowiak of IMAG]
  24. ;;;  * bibtex-pop-previous replaces current field with value of
  25. ;;;    similar field in previous entry.  May be called n times in a row
  26. ;;;    (or with arg n) to pop similar field of n'th previous entry.
  27. ;;;    There is also a bibtex-pop-next to get similar field of next
  28. ;;;    entry.
  29. ;;;  * C-c C-k now kills all empty optional fields of current entry, and
  30. ;;;    removes "OPT" for those optional fields which have text. 
  31.  
  32. ;;; Marc Shapiro 14-dec-87
  33. ;;;   Cosmetic fixes.  Fixed small bug in bibtex-move-outside-of-entry.
  34. ;;; Skip Montanaro <steinmetz!sprite!montanaro> 7-dec-87, Shapiro 10-dec-87
  35. ;;;   before inserting an entry, make sure we are outside of a bib entry
  36. ;;; Marc Shapiro 3-nov-87
  37. ;;;   addition for France: DEAthesis
  38. ;;; Marc Shapiro 19-oct-1987
  39. ;;;   add X window menu option; bug fixes. TAB, LFD, C-c " and C-c C-o now
  40. ;;;   behave consistently; deletion never occurs blindly.
  41. ;;; Marc Shapiro <shapiro@inria.inria.fr> 15-oct-1986
  42. ;;;    align long lines nicely; C-c C-o checks for the "OPT" string;
  43. ;;;    TAB goes to the end of the string; use lower case; use
  44. ;;;    run-hooks
  45.  
  46. ;;; Bengt Martensson <ubrinf!mond!bengt> 87-06-28
  47. ;;;   Original version
  48.  
  49. ;;; NOTE by Marc Shapiro, 14-dec-87:
  50. ;;; (bibtex-x-environment) binds an X menu for bibtex mode to x-button-c-right.
  51. ;;; Trouble is, in Emacs 18.44 you can't have a mode-specific mouse binding,
  52. ;;; so it will remain active in all windows.  Yuck!
  53.  
  54. (defvar bibtex-mode-syntax-table nil "")
  55. (defvar bibtex-mode-abbrev-table nil "")
  56. (define-abbrev-table 'bibtex-mode-abbrev-table ())
  57. (defvar bibtex-mode-map (make-sparse-keymap) "")
  58. (defvar bibtex-pop-previous-search-point nil
  59.   "Next point where bibtex-pop-previous should start looking for a similar
  60. entry.")
  61. (defvar bibtex-pop-next-search-point nil
  62.   "Next point where bibtex-pop-next should start looking for a similar
  63. entry.")
  64.  
  65. ;;; A bibtex file is a sequence of entries, either string definitions
  66. ;;; or reference entries.  A reference entry has a type part, a
  67. ;;; key part, and a comma-separated sequence of fields.  A string
  68. ;;; entry has a single field.  A field has a left and right part,
  69. ;;; separated by a '='.  The left part is the name, the right part is
  70. ;;; the text.  Here come the definitions allowing to create and/or parse
  71. ;;; entries and fields:
  72.  
  73. ;;; fields
  74. (defun bibtex-cfield (name text)
  75.   "Create a regexp for a bibtex field of name NAME and text TEXT"
  76.   (concat ",[ \t\n]*\\("
  77.       name
  78.       "\\)[ \t\n]*=[ \t\n]*\\("
  79.       text
  80.       "\\)"))
  81. (defconst bibtex-name-in-cfield 1
  82.   "The regexp subexpression number of the name part in bibtex-cfield.")
  83. (defconst bibtex-text-in-cfield 2
  84.   "The regexp subexpression number of the text part in bibtex-cfield.")
  85.  
  86. (defconst bibtex-field-name "[A-Za-z][---A-Za-z0-9:_+]*"
  87.   "Regexp defining the name part of a bibtex field.")
  88. (defconst bibtex-field-text
  89.   "\"[^\"]*[^\\\\]\"\\|\"\"\\|[0-9A-Za-z][---A-Za-z0-9:_+]*"
  90.   "Regexp defining the text part of a bibtex field: either a string, or an empty string, or a constant.")
  91. (defconst bibtex-field
  92.   (bibtex-cfield bibtex-field-name bibtex-field-text)
  93.   "Regexp defining the format of a bibtex field")
  94.  
  95. (defconst bibtex-name-in-field bibtex-name-in-cfield
  96.   "The regexp subexpression number of the name part in bibtex-field")
  97. (defconst bibtex-text-in-field bibtex-text-in-cfield
  98.   "The regexp subexpression number of the text part in bibtex-field")
  99.  
  100. ;;; references
  101. (defconst bibtex-reference-type
  102.   "@[A-Za-z]+"
  103.   "Regexp defining the type part of a bibtex reference entry")
  104. (defconst bibtex-reference-head
  105.   (concat "^[ \t]*\\("
  106.       bibtex-reference-type
  107.       "\\)[ \t]*[({]\\("
  108.       bibtex-field-name
  109.       "\\)")
  110.   "Regexp defining format of the header line of a bibtex reference entry")
  111. (defconst bibtex-type-in-head 1
  112.   "The regexp subexpression number of the type part in bibtex-reference-head")
  113. (defconst bibtex-key-in-head 2
  114.   "The regexp subexpression number of the key part in
  115. bibtex-reference-head")
  116.  
  117. (defconst bibtex-reference
  118.   (concat bibtex-reference-head
  119.       "\\([ \t\n]*" bibtex-field "\\)*"
  120.       "[ \t\n]*[})]")
  121.   "Regexp defining the format of a bibtex reference entry")
  122. (defconst bibtex-type-in-reference bibtex-type-in-head
  123.   "The regexp subexpression number of the type part in bibtex-reference")
  124. (defconst bibtex-key-in-reference bibtex-key-in-head
  125.   "The regexp subexpression number of the key part in
  126. bibtex-reference")
  127.  
  128. ;;; strings
  129. (defconst bibtex-string
  130.   (concat "^[ \t]*@[sS][tT][rR][iI][nN][gG][ \t\n]*[({][ \t\n]*\\("
  131.       bibtex-field-name
  132.       "\\)[ \t\n]*=[ \t\n]*\\("
  133.       bibtex-field-text
  134.       "\\)[ \t\n]*[})]")
  135.   "Regexp defining the format of a bibtex string entry")
  136. (defconst bibtex-name-in-string 1
  137.   "The regexp subexpression of the name part in bibtex-string")
  138. (defconst bibtex-text-in-string 2
  139.   "The regexp subexpression of the text part in bibtex-string")
  140.  
  141. ;;; bibtex mode:
  142.  
  143. (defun bibtex-mode () 
  144.   "Major mode for editing bibtex files.
  145.  
  146. \\{bibtex-mode-map}
  147.  
  148. A command such as \\[bibtex-Book] will outline the fields for a BibTeX book entry.
  149.  
  150. The optional fields start with the string OPT, and thus ignored by BibTeX.
  151. The OPT string may be removed from a field with \\[bibtex-remove-OPT].
  152. \\[bibtex-remove-double-quotes] removes the double-quotes around the text of
  153. the current field.
  154.  
  155. The command \\[bibtex-clean-entry] cleans the current entry, i.e. (i) removes
  156. double-quotes from entirely numerical fields, (ii) removes OPT from all
  157. non-empty optional fields, (iii) removes all empty optional fields, and (iv)
  158. checks that no non-optional fields are empty.
  159.  
  160. Use \\[bibtex-find-it] to position the dot at the end of the current field.
  161. Use \\[bibtex-next-field] to move to end of the next field.
  162.  
  163. \\[bibtex-x-environment] binds a mode-specific X menu to control+right
  164. mouse button.
  165.  
  166. Fields:
  167.     address
  168.            Publisher's address
  169.     annote
  170.            Long annotation used for annotated bibliographies (begins sentence)
  171.     author
  172.            Name(s) of author(s), in BibTeX name format
  173.     booktitle
  174.            Book title when the thing being referenced isn't the whole book.
  175.            For book entries, the title field should be used instead.
  176.     chapter
  177.            Chapter number
  178.     edition
  179.            Edition of a book (e.g., \"second\")
  180.     editor
  181.            Name(s) of editor(s), in BibTeX name format.
  182.            If there is also an author field, then the editor field should be
  183.            for the book or collection that the work appears in
  184.     howpublished
  185.             How something strange has been published (begins sentence)
  186.     institution
  187.            Sponsoring institution
  188.     journal
  189.            Journal name (macros are provided for many)
  190.     key
  191.            Alphabetizing and labeling key (needed when no author or editor)
  192.     month
  193.            Month (macros are provided)
  194.     note
  195.            To help the reader find a reference (begins sentence)
  196.     number
  197.            Number of a journal or technical report
  198.     organization
  199.            Organization (sponsoring a conference)
  200.     pages
  201.            Page number or numbers (use `--' to separate a range)
  202.     publisher
  203.            Publisher name
  204.     school
  205.            School name (for theses)
  206.     series
  207.            The name of a series or set of books.
  208.            An individual book will will also have it's own title
  209.     title
  210.            The title of the thing being referenced
  211.     type
  212.            Type of a technical report (e.g., \"Research Note\") to be used
  213.            instead of the default \"Technical Report\"
  214.     volume
  215.            Volume of a journal or multivolume work
  216.     year
  217.            Year---should contain only numerals
  218. ---------------------------------------------------------
  219. Entry to this mode calls the value of BibTeX-mode-hook or bibtex-mode-hook
  220. (first non-nil only) if that value is non-nil."
  221.   (interactive)
  222.   (kill-all-local-variables)
  223.   (if bibtex-mode-syntax-table
  224. (set-syntax-table bibtex-mode-syntax-table)
  225. (setq bibtex-mode-syntax-table (make-syntax-table))
  226. (set-syntax-table bibtex-mode-syntax-table)
  227. (modify-syntax-entry ?\" ".")
  228. (modify-syntax-entry ?$ "$$  ")
  229. (modify-syntax-entry ?% "<   ")
  230. (modify-syntax-entry ?'  "w   ")
  231. (modify-syntax-entry ?@  "w   ")
  232. (modify-syntax-entry ?\\ "\\")
  233. (modify-syntax-entry ?\f ">   ")
  234. (modify-syntax-entry ?\n ">   ")
  235. (modify-syntax-entry ?~ " "))
  236.   (use-local-map bibtex-mode-map)
  237.   (setq major-mode 'bibtex-mode)
  238.  
  239.  
  240.   (setq mode-name "BibTeX")
  241.   (set-syntax-table bibtex-mode-syntax-table)
  242.   (setq local-abbrev-table bibtex-mode-abbrev-table)
  243.   (make-local-variable 'paragraph-start)
  244.   (setq paragraph-start "^[ \f\n\t]*$")
  245.  
  246.   (define-key bibtex-mode-map "\t" 'bibtex-find-it)
  247.   (define-key bibtex-mode-map "\n" 'bibtex-next-field)
  248.   (define-key bibtex-mode-map "\C-c""" 'bibtex-remove-double-quotes)
  249.   (define-key bibtex-mode-map "\C-c\C-c" 'bibtex-clean-entry)
  250.   (define-key bibtex-mode-map "\C-c?" 'describe-mode)
  251.   (define-key bibtex-mode-map "\C-c\C-p" 'bibtex-pop-previous)
  252.   (define-key bibtex-mode-map "\C-c\C-n" 'bibtex-pop-next)
  253.  
  254.   (define-key bibtex-mode-map "\C-c\C-e\C-a" 'bibtex-Article)
  255.   (define-key bibtex-mode-map "\C-c\C-e\C-b" 'bibtex-Book)
  256.   (define-key bibtex-mode-map "\C-c\C-e\C-d" 'bibtex-DEAthesis)
  257.   (define-key bibtex-mode-map "\C-c\C-e\C-c" 'bibtex-InProceedings)
  258.   (define-key bibtex-mode-map "\C-c\C-e\C-i" 'bibtex-InBook)
  259.   (define-key bibtex-mode-map "\C-c\C-ei" 'bibtex-InCollection)
  260.   (define-key bibtex-mode-map "\C-c\C-eI" 'bibtex-InProceedings)
  261.   (define-key bibtex-mode-map "\C-c\C-e\C-m" 'bibtex-Manual)
  262.   (define-key bibtex-mode-map "\C-c\C-em" 'bibtex-MastersThesis)
  263.   (define-key bibtex-mode-map "\C-c\C-eM" 'bibtex-Misc)
  264.   (define-key bibtex-mode-map "\C-c\C-o" 'bibtex-remove-OPT)
  265.   (define-key bibtex-mode-map "\C-c\C-e\C-p" 'bibtex-PhdThesis)
  266.   (define-key bibtex-mode-map "\C-c\C-ep" 'bibtex-Proceedings)
  267.   (define-key bibtex-mode-map "\C-c\C-e\C-t" 'bibtex-TechReport)
  268.   (define-key bibtex-mode-map "\C-c\C-e\C-s" 'bibtex-string)
  269.   (define-key bibtex-mode-map "\C-c\C-e\C-u" 'bibtex-Unpublished)
  270.  
  271.   (auto-fill-mode 1)            ; nice alignements
  272.   (setq left-margin 17)
  273.  
  274.   (run-hooks (if (and (boundp 'BibTeX-mode-hook) BibTeX-mode-hook)
  275.          'BibTeX-mode-hook
  276.            'bibtex-mode-hook)))
  277.  
  278. (fset 'BibTeX-mode 'bibtex-mode)        ; Synonym...
  279.  
  280. (defun bibtex-move-outside-of-entry ()
  281.   "Make sure we are outside of a bib entry"
  282.   (cond ((or
  283.       (= (point) (point-max))
  284.       (= (point) (point-min))
  285.       (looking-at "[ \n]*@")
  286.       )
  287.      t)
  288.     (t
  289.      (backward-paragraph)
  290.      (forward-paragraph)))
  291.   (re-search-forward "[ \t\n]*" (point-max) t))
  292.  
  293. (defun bibtex-entry (entry-type required optional)
  294.   (bibtex-move-outside-of-entry)
  295.   (insert (concat "@" entry-type "{,\n\n}\n\n"))
  296.   (previous-line 3)
  297.   (insert (mapconcat 'bibtex-make-entry required ",\n"))
  298.   (if required
  299.       (if optional
  300.       (insert ",\n")))
  301.   (insert (mapconcat 'bibtex-make-OPT-entry optional ",\n"))
  302.   (up-list -1)
  303.   (forward-char 1))
  304.  
  305. (defun bibtex-make-entry (str)
  306.   (interactive "s")
  307.   (concat "  " str " = \t"""""))
  308.  
  309. (defun bibtex-make-OPT-entry (str)
  310.   (interactive "s")
  311.   (concat "  OPT" str " = \t"""""))
  312.  
  313. (defun bibtex-Article ()
  314.   (interactive)
  315.   (bibtex-entry "Article" (list "author" "title" "journal" "year")
  316.         (list "volume" "number" "pages" "month" "note")))
  317.  
  318. (defun bibtex-Book ()
  319.   (interactive)
  320.   (bibtex-entry "Book" (list "author" "title" "publisher" "year")
  321.         (list "editor" "volume" "series" "address"
  322.               "edition" "month" "note")))
  323.  
  324. (defun bibtex-Booklet ()
  325.   (interactive)
  326.   (bibtex-entry "Booklet" (list "title")
  327.         (list "author" "howpublished" "address" "month" "year" "note")))
  328.  
  329. ;; France: Dipl\^{o}me d'Etudes Approfondies (similar to Master's)
  330. (defun bibtex-DEAthesis ()
  331.   (interactive)
  332.   (bibtex-entry "DEAthesis" (list "author" "title" "school" "year")
  333.         (list "address" "month" "note")))
  334.  
  335. (defun bibtex-InBook ()
  336.   (interactive)
  337.   (bibtex-entry "InBook" (list "author" "title" "chapter" "publisher" "year")
  338.         (list "editor" "pages" "volume" "series" "address"
  339.               "edition" "month" "note")))
  340.  
  341. (defun bibtex-InCollection ()
  342.   (interactive)
  343.   (bibtex-entry "InCollection" (list "author" "title" "booktitle"
  344.                      "publisher" "year")
  345.         (list "editor" "chapter" "pages" "address" "month" "note")))
  346.  
  347. (defun bibtex-InProceedings ()
  348.   (interactive)
  349.   (bibtex-entry "InProceedings" (list "author" "title" "booktitle" "year")
  350.         (list "editor" "pages" "organization" "publisher"
  351.               "address" "month" "note")))
  352.  
  353. (defun bibtex-Manual ()
  354.   (interactive)
  355.   (bibtex-entry "Manual" (list "title")
  356.         (list "author" "organization" "address" "edition" "year"
  357.               "month" "note")))
  358.  
  359. (defun bibtex-MastersThesis ()
  360.   (interactive)
  361.   (bibtex-entry "MastersThesis" (list "author" "title" "school" "year")
  362.         (list "address" "month" "note")))
  363.  
  364. (defun bibtex-Misc ()
  365.   (interactive)
  366.   (bibtex-entry "Misc" '()
  367.         (list "author" "title" "howpublished" "year" "month" "note")))
  368.  
  369. (defun bibtex-PhdThesis ()
  370.   (interactive)
  371.   (bibtex-entry "PhdThesis" (list "author" "title" "school" "year")
  372.         (list "address" "month" "note")))
  373.  
  374. (defun bibtex-Proceedings ()
  375.   (interactive)
  376.   (bibtex-entry "Proceedings" (list "title" "year")
  377.         (list "editor" "publisher" "organization"
  378.               "address" "month" "note")))
  379.  
  380. (defun bibtex-TechReport ()
  381.   (interactive)
  382.   (bibtex-entry "TechReport" (list "author" "title" "institution" "year")
  383.         (list "type" "number" "address" "month" "note")))
  384.  
  385.  
  386. (defun bibtex-Unpublished ()
  387.   (interactive)
  388.   (bibtex-entry "Unpublished" (list "author" "title" "note")
  389.         (list "year" "month")))
  390.  
  391. (defun bibtex-string ()
  392.   (interactive)
  393.   (bibtex-move-outside-of-entry)
  394.   (insert "@string{ = """"}\n")
  395.   (previous-line 1)
  396.   (forward-char 8))
  397.  
  398.  
  399. (defun bibtex-next-field ()
  400.   "Finds end of text of next field."
  401.   (interactive)
  402.   (condition-case ()
  403.       (progn
  404.     (bibtex-inside-field)
  405.     (re-search-forward ",[ \t\n]*" (point-max) 1)
  406.     (bibtex-enclosing-field)
  407.     (bibtex-inside-field))
  408.     (error nil)))
  409.  
  410. (defun bibtex-find-it ()
  411.   (interactive)
  412.   "Go to end of text of current field."
  413.   (condition-case ()
  414.       (progn
  415.     (bibtex-inside-field)
  416.     (bibtex-enclosing-field)
  417.     (goto-char (match-end bibtex-text-in-field))
  418.     (bibtex-inside-field))
  419.     (error nil)))
  420.  
  421. (defun bibtex-remove-OPT ()
  422.   "Removes the 'OPT' starting optional arguments and goes to end of text"
  423.   (interactive)
  424.   (bibtex-inside-field)
  425.   (bibtex-enclosing-field)
  426.   (save-excursion
  427.     (goto-char (match-beginning bibtex-name-in-field))
  428.     (if (looking-at "OPT")
  429.     (delete-char (length "OPT"))))
  430.   (bibtex-inside-field))
  431.  
  432. (defun bibtex-inside-field ()
  433.   "Try to avoid point being at end of a bibtex field."
  434.   (skip-chars-backward " \t")
  435.   (cond ((= (preceding-char) ?,)
  436.      (forward-char -1)))
  437.   (cond ((= (preceding-char) ?\")
  438.      (forward-char -1))))
  439.  
  440. (defun bibtex-remove-double-quotes ()
  441.   "Removes \"\" around string."
  442.   (interactive)
  443.   (save-excursion
  444.     (bibtex-enclosing-field)
  445.     (let ((start (match-beginning bibtex-text-in-field))
  446.       (stop (match-end  bibtex-text-in-field)))
  447.       (goto-char stop)
  448.       (forward-char -1)
  449.       (if (looking-at "\"")
  450.       (delete-char 1))
  451.       (goto-char start)
  452.       (if (looking-at "\"")
  453.       (delete-char 1)))))
  454.  
  455. ;;; X window menus for bibtex mode
  456.  
  457. (defun bibtex-x-help (arg)
  458.   "Mouse commands for BibTeX mode"
  459.   
  460.   (let ((selection
  461.      (x-popup-menu
  462.       arg
  463.       '("BibTeX commands"
  464.         ("BibTeX entry types"
  465.          (" article in conference Proceedings " . bibtex-InProceedings)
  466.          ("        Article in journal         " . bibtex-Article)
  467.          ("               Book                " . bibtex-Book)
  468.          ("             Booklet               " . bibtex-Booklet)
  469.          ("         Master's Thesis           " . bibtex-MastersThesis)
  470.          ("            DEA Thesis             " . bibtex-DEAthesis)
  471.          ("            Phd. Thesis            " . bibtex-PhdThesis)
  472.          ("         Technical Report          " . bibtex-TechReport)
  473.          ("         technical Manual          " . bibtex-Manual)
  474.          ("      conference Proceedings       " . bibtex-Proceedings)
  475.          ("        a chapter in a Book        " . bibtex-InBook)
  476.          ("    an article in a Collection     " . bibtex-InCollection)
  477.          ("           miscellaneous           " . bibtex-Misc)
  478.          ("            unpublished            " . bibtex-Unpublished)
  479.          ("              string               " . bibtex-string)
  480.          )
  481.         ("Moving around and editing"
  482.          ("            next field             " . bibtex-next-field)
  483.          ("          to end of field          " . bibtex-find-it)
  484.          ("snatch from similar preceding field" . bibtex-pop-previous)
  485.          ("snatch from similar following field" . bibtex-pop-next)
  486.          ("            remove OPT             " . bibtex-remove-OPT)
  487.          ("           remove quotes           "
  488.           . bibtex-remove-double-quotes)
  489.          ("          clean up entry           " . bibtex-clean-entry)
  490.          )
  491.         ("help"
  492.          ("       describe BibTeX mode        " . describe-mode)
  493.          )))))
  494.     (and selection (call-interactively selection))))
  495.  
  496. (defun bibtex-x-environment ()
  497.   "Set up X menus for BibTeX mode.  Call it as bibtex-mode-hook, or interactively"
  498.   (interactive)
  499.   (require 'x-mouse)
  500.   (define-key mouse-map x-button-c-right 'bibtex-x-help)
  501.   )
  502.  
  503.  
  504. (defun bibtex-pop-previous (arg)
  505.   "Replace text of current field with the text of similar field in previous entry.
  506. With arg, go up ARG entries.  Repeated, goes up so many times.  May be
  507. intermixed with \\[bibtex-pop-next] (bibtex-pop-next)."
  508.   (interactive "p")
  509.   (bibtex-inside-field)
  510.   (save-excursion
  511.     ; parse current field
  512.     (bibtex-enclosing-field)
  513.     (let ((start-old-text (match-beginning bibtex-text-in-field))
  514.       (stop-old-text  (match-end bibtex-text-in-field))
  515.       (start-name (match-beginning bibtex-name-in-field))
  516.       (stop-name (match-end bibtex-name-in-field))
  517.       (new-text))
  518.       (goto-char start-name)
  519.       ; construct regexp for previous field with same name as this one
  520.       (let ((matching-entry
  521.          (bibtex-cfield
  522.           (buffer-substring (if (looking-at "OPT")
  523.                     (+ (point) (length "OPT"))
  524.                   (point))
  525.                 stop-name)
  526.           bibtex-field-text)))
  527.     
  528.     ; if executed several times in a row, start each search where the
  529.     ; last one finished
  530.     (cond ((or (eq last-command 'bibtex-pop-previous)
  531.            (eq last-command 'bibtex-pop-next))
  532.            t
  533.            )
  534.           (t
  535.            (bibtex-enclosing-reference)
  536.            (setq bibtex-pop-previous-search-point (match-beginning 0))
  537.            (setq bibtex-pop-next-search-point (match-end 0))))
  538.     (goto-char bibtex-pop-previous-search-point)
  539.     
  540.     ; Now search for arg'th previous similar field
  541.     (cond
  542.      ((re-search-backward matching-entry (point-min) t arg)
  543.       (setq new-text
  544.         (buffer-substring (match-beginning bibtex-text-in-cfield)
  545.                   (match-end bibtex-text-in-cfield)))
  546.       ; Found a matching field. Remember boundaries.
  547.       (setq bibtex-pop-next-search-point (match-end 0))
  548.       (setq bibtex-pop-previous-search-point (match-beginning 0))
  549.       (bibtex-flash-head)
  550.       ; Go back to where we started, delete old text, and pop new.
  551.       (goto-char stop-old-text)
  552.       (delete-region start-old-text stop-old-text)
  553.       (insert new-text))
  554.      (t                ; search failed
  555.       (error "No previous matching BibTeX field."))))))
  556.   (setq this-command 'bibtex-pop-previous))
  557.  
  558. (defun bibtex-pop-next (arg)
  559.   "Replace text of current field with the text of similar field in next entry.
  560. With arg, go up ARG entries.  Repeated, goes up so many times.  May be
  561. intermixed with \\[bibtex-pop-previous] (bibtex-pop-previous)."
  562.   (interactive "p")
  563.   (bibtex-inside-field)
  564.   (save-excursion
  565.     ; parse current field
  566.     (bibtex-enclosing-field)
  567.     (let ((start-old-text (match-beginning bibtex-text-in-field))
  568.       (stop-old-text  (match-end bibtex-text-in-field))
  569.       (start-name (match-beginning bibtex-name-in-field))
  570.       (stop-name (match-end bibtex-name-in-field))
  571.       (new-text))
  572.       (goto-char start-name)
  573.       ; construct regexp for next field with same name as this one,
  574.       ; ignoring possible OPT's
  575.       (let ((matching-entry
  576.          (bibtex-cfield
  577.           (buffer-substring (if (looking-at "OPT")
  578.                     (+ (point) (length "OPT"))
  579.                   (point))
  580.                 stop-name)
  581.           bibtex-field-text)))
  582.     
  583.     ; if executed several times in a row, start each search where the
  584.     ; last one finished
  585.     (cond ((or (eq last-command 'bibtex-pop-next)
  586.            (eq last-command 'bibtex-pop-previous))
  587.            t
  588.            )
  589.           (t
  590.            (bibtex-enclosing-reference)
  591.            (setq bibtex-pop-previous-search-point (match-beginning 0))
  592.            (setq bibtex-pop-next-search-point (match-end 0))))
  593.     (goto-char bibtex-pop-next-search-point)
  594.     
  595.     ; Now search for arg'th next similar field
  596.     (cond
  597.      ((re-search-forward matching-entry (point-max) t arg)
  598.       (setq new-text
  599.         (buffer-substring (match-beginning bibtex-text-in-cfield)
  600.                   (match-end bibtex-text-in-cfield)))
  601.       ; Found a matching field. Remember boundaries.
  602.       (setq bibtex-pop-next-search-point (match-end 0))
  603.       (setq bibtex-pop-previous-search-point (match-beginning 0))
  604.       (bibtex-flash-head)
  605.       ; Go back to where we started, delete old text, and pop new.
  606.       (goto-char stop-old-text)
  607.       (delete-region start-old-text stop-old-text)
  608.       (insert new-text))
  609.      (t                ; search failed
  610.       (error "No next matching BibTeX field."))))))
  611.   (setq this-command 'bibtex-pop-next))
  612.  
  613. (defun bibtex-flash-head ()
  614.   "Flash at BibTeX reference head before point, if exists.  (Moves point)."
  615.   (let ((flash))
  616.     (cond ((re-search-backward bibtex-reference-head (point-min) t)
  617.        (goto-char (match-beginning bibtex-type-in-head))
  618.        (setq flash (match-end bibtex-key-in-reference)))
  619.       (t
  620.        (end-of-line)
  621.        (skip-chars-backward " \t")
  622.        (setq flash (point))
  623.        (beginning-of-line)
  624.        (skip-chars-forward " \t")))
  625.     (if (pos-visible-in-window-p (point))
  626.     (sit-for 1)
  627.       (message "From: %s"
  628.            (buffer-substring (point) flash)))))
  629.  
  630.  
  631.  
  632. (defun bibtex-enclosing-field ()
  633.   "Search for BibTeX field enclosing point.
  634. Point moves to end of field; also, use match-beginning and match-end
  635. to parse the field."
  636.   (condition-case errname
  637.       (bibtex-enclosing-regexp bibtex-field)
  638.     (search-failed
  639.      (error "Can't find enclosing BibTeX field."))))
  640.  
  641. (defun bibtex-enclosing-reference ()
  642.   "Search for BibTeX reference enclosing point.
  643. Point moves to end of reference; also, use match-beginning and match-end
  644. to parse the reference."
  645.   (condition-case errname
  646.       (bibtex-enclosing-regexp bibtex-reference)
  647.     (search-failed
  648.      (error "Can't find enclosing BibTeX reference."))))
  649.  
  650. (defun bibtex-enclosing-regexp (regexp)
  651.   "Search for REGEXP enclosing point.
  652. Point moves to end of REGEXP.  See also match-beginning and match-end.
  653. If an enclosing REGEXP is not found, signals search-failed; point is left in
  654. an undefined location.
  655.  
  656. [Doesn't something like this exist already?]"
  657.   
  658.   (interactive "sRegexp: ")
  659.   ; compute reasonable limits for the loop
  660.   (let* ((initial (point))
  661.      (right (if (re-search-forward regexp (point-max) t)
  662.             (match-end 0)
  663.           (point-max)))
  664.      (left
  665.       (progn
  666.         (goto-char initial)
  667.         (if (re-search-backward regexp (point-min) t)
  668.         (match-beginning 0)
  669.           (point-min)))))
  670.     ; within the prescribed limits, loop until a match is found
  671.     (goto-char left)
  672.     (re-search-forward regexp right nil 1)
  673.     (if (> (match-beginning 0) initial)
  674.     (signal 'search-failed (list regexp)))      
  675.     (while (<= (match-end 0) initial)
  676.       (re-search-forward regexp right nil 1)
  677.       (if (> (match-beginning 0) initial)
  678.       (signal 'search-failed (list regexp))))
  679.     ))
  680.  
  681. (defun bibtex-clean-entry ()
  682.   "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."
  683.   (interactive)
  684.   (bibtex-enclosing-reference)
  685.   (goto-char (match-beginning 0))
  686.   (let ((start (point)))
  687.     (save-restriction
  688.       (narrow-to-region start (match-end 0))
  689.       (while (re-search-forward bibtex-field (point-max) t 1)
  690.     (let ((begin-field (match-beginning 0))
  691.           (end-field (match-end 0))
  692.           (begin-name (match-beginning bibtex-name-in-field))
  693.           (end-name (match-end  bibtex-name-in-field))
  694.           (begin-text (match-beginning bibtex-text-in-field))
  695.           (end-text (match-end bibtex-text-in-field))
  696.           )
  697.       (goto-char begin-name)
  698.       (cond ((looking-at "OPT")
  699.          (goto-char begin-text)
  700.          (if (looking-at "\"\"") ; empty: delete whole field
  701.              (delete-region begin-field end-field)
  702.            ; otherwise: not empty, delete "OPT"
  703.            (goto-char begin-name)
  704.            (delete-char (length "OPT"))
  705.            (goto-char begin-field) ; and loop to go through next test
  706.            ))
  707.         (t
  708.          (goto-char begin-text)
  709.          (cond ((looking-at "\"[0-9]+\"") ; if numerical,
  710.             (goto-char end-text)
  711.             (delete-char -1) ; delete enclosing double-quotes
  712.             (goto-char begin-text)
  713.             (delete-char 1)
  714.             (goto-char end-field) ; go to end for next search
  715.             (forward-char -2) ; to compensate for the 2 quotes deleted
  716.             )
  717.                ((looking-at "\"\"") ; if empty quotes, complain
  718.             (forward-char 1)
  719.             (error "Mandatory field ``%s'' is empty"
  720.                    (buffer-substring begin-name end-name)))
  721.                (t
  722.             (goto-char end-field))))))))
  723.     (goto-char start)
  724.     (skip-chars-forward "@a-zA-Z")
  725.     (bibtex-enclosing-reference)
  726.     (goto-char (match-end 0))
  727.     (skip-whitespace nil)))
  728.  
  729.  
  730.  
  731.