aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/textmodes
diff options
context:
space:
mode:
authorKaroly Lorentey2004-11-06 17:52:02 +0000
committerKaroly Lorentey2004-11-06 17:52:02 +0000
commit65ea79492334e2ef7b5b4e0d23b6f68ba2f4d0bb (patch)
tree853cf391ca1abda4f4ccd6fe8e7bb43f7c86ee08 /lisp/textmodes
parente0bc17abe6979d607e8de4684dddb96e53c60065 (diff)
parent392cf16dd0ee9358f8af0cd0d8048b822456bbeb (diff)
downloademacs-65ea79492334e2ef7b5b4e0d23b6f68ba2f4d0bb.tar.gz
emacs-65ea79492334e2ef7b5b4e0d23b6f68ba2f4d0bb.zip
Merged in changes from CVS trunk.
Patches applied: * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-653 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-654 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-655 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-656 Update from CVS: lisp/man.el (Man-xref-normal-file): Fix help-echo. * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-657 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-658 Merge from gnus--rel--5.10 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-659 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-660 Merge from gnus--rel--5.10 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-661 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-662 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-663 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-664 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-665 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-666 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-667 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-668 Merge from gnus--rel--5.10 * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-669 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-670 Update from CVS * miles@gnu.org--gnu-2004/emacs--cvs-trunk--0--patch-671 Update from CVS * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-64 Update from CVS * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-65 Update from CVS * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-66 Update from CVS * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-67 Update from CVS * miles@gnu.org--gnu-2004/gnus--rel--5.10--patch-68 Update from CVS git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-264
Diffstat (limited to 'lisp/textmodes')
-rw-r--r--lisp/textmodes/bibtex.el1187
-rw-r--r--lisp/textmodes/flyspell.el4
-rw-r--r--lisp/textmodes/ispell.el5
-rw-r--r--lisp/textmodes/table.el3
-rw-r--r--lisp/textmodes/texinfo.el4
5 files changed, 722 insertions, 481 deletions
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el
index ddc1d4ecb62..dd989fbea81 100644
--- a/lisp/textmodes/bibtex.el
+++ b/lisp/textmodes/bibtex.el
@@ -42,6 +42,8 @@
42 42
43;;; Code: 43;;; Code:
44 44
45(require 'button)
46
45 47
46;; User Options: 48;; User Options:
47 49
@@ -496,7 +498,7 @@ Each element is a pair of strings (ABBREVIATION . EXPANSION)."
496 498
497(defcustom bibtex-string-files nil 499(defcustom bibtex-string-files nil
498 "*List of BibTeX files containing string definitions. 500 "*List of BibTeX files containing string definitions.
499Those files must be specified using pathnames relative to the 501List elements can be absolute file names or file names relative to the
500directories specified in `bibtex-string-file-path'." 502directories specified in `bibtex-string-file-path'."
501 :group 'bibtex 503 :group 'bibtex
502 :type '(repeat file)) 504 :type '(repeat file))
@@ -504,6 +506,18 @@ directories specified in `bibtex-string-file-path'."
504(defvar bibtex-string-file-path (getenv "BIBINPUTS") 506(defvar bibtex-string-file-path (getenv "BIBINPUTS")
505 "*Colon separated list of paths to search for `bibtex-string-files'.") 507 "*Colon separated list of paths to search for `bibtex-string-files'.")
506 508
509(defcustom bibtex-files nil
510 "*List of BibTeX files checked for duplicate keys.
511List elements can be absolute file names or file names relative to the
512directories specified in `bibtex-file-path'. If an element is a directory,
513check all BibTeX files in this directory. If an element is the symbol
514`bibtex-file-path', check all BibTeX files in `bibtex-file-path'."
515 :group 'bibtex
516 :type '(repeat file))
517
518(defvar bibtex-file-path (getenv "BIBINPUTS")
519 "*Colon separated list of paths to search for `bibtex-files'.")
520
507(defcustom bibtex-help-message t 521(defcustom bibtex-help-message t
508 "*If non-nil print help messages in the echo area on entering a new field." 522 "*If non-nil print help messages in the echo area on entering a new field."
509 :group 'bibtex 523 :group 'bibtex
@@ -557,7 +571,7 @@ See `bibtex-generate-autokey' for details."
557 ;; braces, quotes, concatenation. 571 ;; braces, quotes, concatenation.
558 ("[`'\"{}#]" . "") 572 ("[`'\"{}#]" . "")
559 ;; spaces 573 ;; spaces
560 ("[ \t\n]+" . " ")) 574 ("\\\\?[ \t\n]+\\|~" . " "))
561 "Alist of (OLD-REGEXP . NEW-STRING) pairs. 575 "Alist of (OLD-REGEXP . NEW-STRING) pairs.
562Used by the default values of `bibtex-autokey-name-change-strings' and 576Used by the default values of `bibtex-autokey-name-change-strings' and
563`bibtex-autokey-titleword-change-strings'. Defaults to translating some 577`bibtex-autokey-titleword-change-strings'. Defaults to translating some
@@ -756,12 +770,22 @@ If non-nil, the column for the equal sign is the value of
756 770
757(defcustom bibtex-autoadd-commas t 771(defcustom bibtex-autoadd-commas t
758 "If non-nil automatically add missing commas at end of BibTeX fields." 772 "If non-nil automatically add missing commas at end of BibTeX fields."
773 :group 'bibtex
759 :type 'boolean) 774 :type 'boolean)
760 775
761(defcustom bibtex-autofill-types '("Proceedings") 776(defcustom bibtex-autofill-types '("Proceedings")
762 "Automatically fill fields if possible for those BibTeX entry types." 777 "Automatically fill fields if possible for those BibTeX entry types."
778 :group 'bibtex
763 :type '(repeat string)) 779 :type '(repeat string))
764 780
781(defcustom bibtex-summary-function 'bibtex-summary
782 "Function to call for generating a one-line summary of a BibTeX entry.
783It takes one argument, the key of the entry.
784Used by `bibtex-complete-key-cleanup' and `bibtex-copy-summary-as-kill'."
785 :group 'bibtex
786 :type '(choice (const :tag "Default" bibtex-summary)
787 (function :tag "Personalized function")))
788
765(defcustom bibtex-generate-url-list 789(defcustom bibtex-generate-url-list
766 '((("url" . ".*:.*")) 790 '((("url" . ".*:.*"))
767 ;; Example of a complex setup. 791 ;; Example of a complex setup.
@@ -778,7 +802,7 @@ These schemes are used by `bibtex-url'.
778Each scheme is of the form ((FIELD . REGEXP) STEP...). 802Each scheme is of the form ((FIELD . REGEXP) STEP...).
779 803
780FIELD is a field name as returned by `bibtex-parse-entry'. 804FIELD is a field name as returned by `bibtex-parse-entry'.
781REGEXP is matched against the text of FIELD. If the match succeed, then 805REGEXP is matched against the text of FIELD. If the match succeeds, then
782this scheme will be used. If no STEPS are specified the matched text is used 806this scheme will be used. If no STEPS are specified the matched text is used
783as the URL, otherwise the URL is built by concatenating the STEPS. 807as the URL, otherwise the URL is built by concatenating the STEPS.
784 808
@@ -838,6 +862,7 @@ Case is always ignored. Always remove the field delimiters."
838 (define-key km "\C-c\C-c" 'bibtex-clean-entry) 862 (define-key km "\C-c\C-c" 'bibtex-clean-entry)
839 (define-key km "\C-c\C-q" 'bibtex-fill-entry) 863 (define-key km "\C-c\C-q" 'bibtex-fill-entry)
840 (define-key km "\C-c\C-s" 'bibtex-find-entry) 864 (define-key km "\C-c\C-s" 'bibtex-find-entry)
865 (define-key km "\C-c\C-t" 'bibtex-copy-summary-as-kill)
841 (define-key km "\C-c?" 'bibtex-print-help-message) 866 (define-key km "\C-c?" 'bibtex-print-help-message)
842 (define-key km "\C-c\C-p" 'bibtex-pop-previous) 867 (define-key km "\C-c\C-p" 'bibtex-pop-previous)
843 (define-key km "\C-c\C-n" 'bibtex-pop-next) 868 (define-key km "\C-c\C-n" 'bibtex-pop-next)
@@ -892,7 +917,9 @@ Case is always ignored. Always remove the field delimiters."
892 ("Moving in BibTeX Buffer" 917 ("Moving in BibTeX Buffer"
893 ["Find Entry" bibtex-find-entry t] 918 ["Find Entry" bibtex-find-entry t]
894 ["Find Crossref Entry" bibtex-find-crossref t]) 919 ["Find Crossref Entry" bibtex-find-crossref t])
895 "--" 920 ("Moving between BibTeX Buffers"
921 ["Find Entry Globally" bibtex-find-entry-globally t])
922 "--"
896 ("Operating on Current Field" 923 ("Operating on Current Field"
897 ["Fill Field" fill-paragraph t] 924 ["Fill Field" fill-paragraph t]
898 ["Remove Delimiters" bibtex-remove-delimiters t] 925 ["Remove Delimiters" bibtex-remove-delimiters t]
@@ -922,6 +949,8 @@ Case is always ignored. Always remove the field delimiters."
922 ["Paste Most Recently Killed Entry" bibtex-yank t] 949 ["Paste Most Recently Killed Entry" bibtex-yank t]
923 ["Paste Previously Killed Entry" bibtex-yank-pop t] 950 ["Paste Previously Killed Entry" bibtex-yank-pop t]
924 "--" 951 "--"
952 ["Copy Summary to Kill Ring" bibtex-copy-summary-as-kill t]
953 "--"
925 ["Ispell Entry" bibtex-ispell-entry t] 954 ["Ispell Entry" bibtex-ispell-entry t]
926 ["Ispell Entry Abstract" bibtex-ispell-abstract t] 955 ["Ispell Entry Abstract" bibtex-ispell-abstract t]
927 ["Narrow to Entry" bibtex-narrow-to-entry t] 956 ["Narrow to Entry" bibtex-narrow-to-entry t]
@@ -934,7 +963,9 @@ Case is always ignored. Always remove the field delimiters."
934 ["Reformat Entries" bibtex-reformat t] 963 ["Reformat Entries" bibtex-reformat t]
935 ["Count Entries" bibtex-count-entries t] 964 ["Count Entries" bibtex-count-entries t]
936 "--" 965 "--"
937 ["Convert Alien Buffer" bibtex-convert-alien t]))) 966 ["Convert Alien Buffer" bibtex-convert-alien t])
967 ("Operating on Multiple Buffers"
968 ["Validate Entries" bibtex-validate-globally t])))
938 969
939(easy-menu-define 970(easy-menu-define
940 bibtex-entry-menu bibtex-mode-map "Entry-Types Menu in BibTeX mode" 971 bibtex-entry-menu bibtex-mode-map "Entry-Types Menu in BibTeX mode"
@@ -955,13 +986,6 @@ Case is always ignored. Always remove the field delimiters."
955 ["String" bibtex-String t] 986 ["String" bibtex-String t]
956 ["Preamble" bibtex-Preamble t])) 987 ["Preamble" bibtex-Preamble t]))
957 988
958(defvar bibtex-url-map
959 (let ((km (make-sparse-keymap)))
960 (define-key km [(mouse-2)] 'bibtex-url)
961 km)
962 "Local keymap for clickable URLs.")
963(fset 'bibtex-url-map bibtex-url-map)
964
965 989
966;; Internal Variables 990;; Internal Variables
967 991
@@ -996,8 +1020,9 @@ Initialized from `bibtex-predefined-strings' and `bibtex-string-files'.")
996(make-variable-buffer-local 'bibtex-strings) 1020(make-variable-buffer-local 'bibtex-strings)
997 1021
998(defvar bibtex-reference-keys 1022(defvar bibtex-reference-keys
999 (lazy-completion-table bibtex-reference-keys bibtex-parse-keys nil nil t) 1023 (lazy-completion-table bibtex-reference-keys bibtex-parse-keys nil t)
1000 "Completion table for BibTeX reference keys.") 1024 "Completion table for BibTeX reference keys.
1025The CDRs of the elements are t for header keys and nil for crossref keys.")
1001(make-variable-buffer-local 'bibtex-reference-keys) 1026(make-variable-buffer-local 'bibtex-reference-keys)
1002 1027
1003(defvar bibtex-buffer-last-parsed-tick nil 1028(defvar bibtex-buffer-last-parsed-tick nil
@@ -1103,13 +1128,13 @@ Initialized from `bibtex-predefined-strings' and `bibtex-string-files'.")
1103 (,(concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=") 1128 (,(concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=")
1104 1 font-lock-variable-name-face) 1129 1 font-lock-variable-name-face)
1105 ;; url 1130 ;; url
1106 (bibtex-font-lock-url 0 '(face nil mouse-face highlight 1131 bibtex-font-lock-url bibtex-font-lock-crossref)
1107 keymap bibtex-url-map)))
1108 "*Default expressions to highlight in BibTeX mode.") 1132 "*Default expressions to highlight in BibTeX mode.")
1109 1133
1110(defvar bibtex-font-lock-url-regexp 1134(defvar bibtex-font-lock-url-regexp
1111 (concat "\\<" (regexp-opt (mapcar 'caar bibtex-generate-url-list) t) 1135 ;; Assume that field names begin at the beginning of a line.
1112 "\\>[ \t]*=[ \t]*") 1136 (concat "^[ \t]*" (regexp-opt (mapcar 'caar bibtex-generate-url-list) t)
1137 "[ \t]*=[ \t]*")
1113 "Regexp for `bibtex-font-lock-url'.") 1138 "Regexp for `bibtex-font-lock-url'.")
1114 1139
1115(defvar bibtex-field-name-for-parsing nil 1140(defvar bibtex-field-name-for-parsing nil
@@ -1128,32 +1153,12 @@ Auto-generated from `bibtex-sort-entry-class'.
1128Used when `bibtex-maintain-sorted-entries' is `entry-class'.") 1153Used when `bibtex-maintain-sorted-entries' is `entry-class'.")
1129 1154
1130 1155
1131;; Special support taking care of variants
1132(defvar zmacs-regions)
1133(defalias 'bibtex-mark-active
1134 (if (boundp 'mark-active)
1135 ;; In Emacs mark-active indicates if mark is active.
1136 (lambda () mark-active)
1137 ;; In XEmacs (mark) returns nil when not active.
1138 (lambda () (if zmacs-regions (mark) (mark t)))))
1139
1140(defalias 'bibtex-run-with-idle-timer
1141 (if (fboundp 'run-with-idle-timer)
1142 ;; timer.el is distributed with Emacs
1143 'run-with-idle-timer
1144 ;; timer.el is not distributed with XEmacs
1145 ;; Notice that this does not (yet) pass the arguments, but they
1146 ;; are not used (yet) in bibtex.el. Fix if needed.
1147 (lambda (secs repeat function &rest args)
1148 (start-itimer "bibtex" function secs (if repeat secs nil) t))))
1149
1150
1151;; Support for hideshow minor mode 1156;; Support for hideshow minor mode
1152(defun bibtex-hs-forward-sexp (arg) 1157(defun bibtex-hs-forward-sexp (arg)
1153 "Replacement for `forward-sexp' to be used by `hs-minor-mode'. 1158 "Replacement for `forward-sexp' to be used by `hs-minor-mode'.
1154ARG is ignored." 1159ARG is ignored."
1155 (if (looking-at "@\\S(*\\s(") 1160 (if (looking-at "@\\S(*\\s(")
1156 (goto-char (1- (match-end 0)))) 1161 (goto-char (1- (match-end 0))))
1157 (forward-sexp 1)) 1162 (forward-sexp 1))
1158 1163
1159(add-to-list 1164(add-to-list
@@ -1471,12 +1476,10 @@ delimiters if present."
1471 (buffer-substring-no-properties (1+ (match-beginning bibtex-type-in-head)) 1476 (buffer-substring-no-properties (1+ (match-beginning bibtex-type-in-head))
1472 (match-end bibtex-type-in-head))) 1477 (match-end bibtex-type-in-head)))
1473 1478
1474(defun bibtex-key-in-head (&optional empty) 1479(defsubst bibtex-key-in-head (&optional empty)
1475 "Extract BibTeX key in head. Return optional arg EMPTY if key is empty." 1480 "Extract BibTeX key in head. Return optional arg EMPTY if key is empty."
1476 (if (match-beginning bibtex-key-in-head) 1481 (or (match-string-no-properties bibtex-key-in-head)
1477 (buffer-substring-no-properties (match-beginning bibtex-key-in-head) 1482 empty))
1478 (match-end bibtex-key-in-head))
1479 empty))
1480 1483
1481;; Helper Functions 1484;; Helper Functions
1482 1485
@@ -1492,7 +1495,7 @@ delimiters if present."
1492(defun bibtex-current-line () 1495(defun bibtex-current-line ()
1493 "Compute line number of point regardless whether the buffer is narrowed." 1496 "Compute line number of point regardless whether the buffer is narrowed."
1494 (+ (count-lines 1 (point)) 1497 (+ (count-lines 1 (point))
1495 (if (equal (current-column) 0) 1 0))) 1498 (if (bolp) 1 0)))
1496 1499
1497(defun bibtex-skip-to-valid-entry (&optional backward) 1500(defun bibtex-skip-to-valid-entry (&optional backward)
1498 "Move point to beginning of the next valid BibTeX entry. 1501 "Move point to beginning of the next valid BibTeX entry.
@@ -1525,24 +1528,25 @@ entry is found, nil otherwise."
1525 found)) 1528 found))
1526 1529
1527(defun bibtex-map-entries (fun) 1530(defun bibtex-map-entries (fun)
1528 "Call FUN for each BibTeX entry starting with the current. 1531 "Call FUN for each BibTeX entry in buffer (possibly narrowed).
1529Do this to the end of the file. FUN is called with three arguments, the key of 1532FUN is called with three arguments, the key of the entry and the buffer
1530the entry and the buffer positions (marker) of beginning and end of entry. 1533positions (marker) of beginning and end of entry. Point is inside the entry.
1531Point is inside the entry. If `bibtex-sort-ignore-string-entries' is non-nil, 1534If `bibtex-sort-ignore-string-entries' is non-nil, FUN will not be called for
1532FUN will not be called for @String entries." 1535@String entries."
1533 (let ((case-fold-search t)) 1536 (let ((case-fold-search t))
1534 (bibtex-beginning-of-entry) 1537 (save-excursion
1535 (while (re-search-forward bibtex-entry-head nil t) 1538 (goto-char (point-min))
1536 (let ((entry-type (bibtex-type-in-head)) 1539 (while (re-search-forward bibtex-entry-head nil t)
1537 (key (bibtex-key-in-head "")) 1540 (let ((entry-type (bibtex-type-in-head))
1538 (beg (copy-marker (match-beginning 0))) 1541 (key (bibtex-key-in-head ""))
1539 (end (copy-marker (save-excursion (bibtex-end-of-entry))))) 1542 (beg (copy-marker (match-beginning 0)))
1540 (save-excursion 1543 (end (copy-marker (save-excursion (bibtex-end-of-entry)))))
1541 (if (or (and (not bibtex-sort-ignore-string-entries) 1544 (save-excursion
1542 (bibtex-string= entry-type "string")) 1545 (if (or (and (not bibtex-sort-ignore-string-entries)
1543 (assoc-string entry-type bibtex-entry-field-alist t)) 1546 (bibtex-string= entry-type "string"))
1544 (funcall fun key beg end))) 1547 (assoc-string entry-type bibtex-entry-field-alist t))
1545 (goto-char end))))) 1548 (funcall fun key beg end)))
1549 (goto-char end))))))
1546 1550
1547(defun bibtex-progress-message (&optional flag interval) 1551(defun bibtex-progress-message (&optional flag interval)
1548 "Echo a message about progress of current buffer. 1552 "Echo a message about progress of current buffer.
@@ -1581,13 +1585,13 @@ If FLAG is nil, a message is echoed if point was incremented at least
1581 "\"")) 1585 "\""))
1582 1586
1583(defun bibtex-entry-left-delimiter () 1587(defun bibtex-entry-left-delimiter ()
1584 "Return a string dependent on `bibtex-field-delimiters'." 1588 "Return a string dependent on `bibtex-entry-delimiters'."
1585 (if (equal bibtex-entry-delimiters 'braces) 1589 (if (equal bibtex-entry-delimiters 'braces)
1586 "{" 1590 "{"
1587 "(")) 1591 "("))
1588 1592
1589(defun bibtex-entry-right-delimiter () 1593(defun bibtex-entry-right-delimiter ()
1590 "Return a string dependent on `bibtex-field-delimiters'." 1594 "Return a string dependent on `bibtex-entry-delimiters'."
1591 (if (equal bibtex-entry-delimiters 'braces) 1595 (if (equal bibtex-entry-delimiters 'braces)
1592 "}" 1596 "}"
1593 ")")) 1597 ")"))
@@ -1641,7 +1645,7 @@ are defined, but only for the head part of the entry
1641 (setq infix-start (bibtex-end-of-field bounds)) 1645 (setq infix-start (bibtex-end-of-field bounds))
1642 (setq finished t)) 1646 (setq finished t))
1643 (goto-char infix-start)) 1647 (goto-char infix-start))
1644 ;; This matches the infix* part. The AND construction assures 1648 ;; This matches the infix* part. The AND construction assures
1645 ;; that BOUND is respected. 1649 ;; that BOUND is respected.
1646 (when (and (looking-at bibtex-entry-postfix) 1650 (when (and (looking-at bibtex-entry-postfix)
1647 (eq (char-before (match-end 0)) entry-closer) 1651 (eq (char-before (match-end 0)) entry-closer)
@@ -1826,8 +1830,8 @@ Formats current entry according to variable `bibtex-entry-format'."
1826 (cdr field))) 1830 (cdr field)))
1827 (cdr field)) 1831 (cdr field))
1828 req-field-list (if crossref-key 1832 req-field-list (if crossref-key
1829 (nth 0 (nth 2 entry-list)) ; crossref part 1833 (nth 0 (nth 2 entry-list)) ; crossref part
1830 (nth 0 (nth 1 entry-list)))) ; required part 1834 (nth 0 (nth 1 entry-list)))) ; required part
1831 1835
1832 (dolist (rfield req-field-list) 1836 (dolist (rfield req-field-list)
1833 (when (nth 3 rfield) ; we should have an alternative 1837 (when (nth 3 rfield) ; we should have an alternative
@@ -1864,9 +1868,9 @@ Formats current entry according to variable `bibtex-entry-format'."
1864 deleted) 1868 deleted)
1865 1869
1866 ;; We have more elegant high-level functions for several 1870 ;; We have more elegant high-level functions for several
1867 ;; tasks done by bibtex-format-entry. However, they contain 1871 ;; tasks done by bibtex-format-entry. However, they contain
1868 ;; quite some redundancy compared with what we need to do 1872 ;; quite some redundancy compared with what we need to do
1869 ;; anyway. So for speed-up we avoid using them. 1873 ;; anyway. So for speed-up we avoid using them.
1870 1874
1871 (if (memq 'opts-or-alts format) 1875 (if (memq 'opts-or-alts format)
1872 (cond ((and empty-field 1876 (cond ((and empty-field
@@ -1875,8 +1879,8 @@ Formats current entry according to variable `bibtex-entry-format'."
1875 field-name req-field-list t))) 1879 field-name req-field-list t)))
1876 (or (not field) ; OPT field 1880 (or (not field) ; OPT field
1877 (nth 3 field))))) ; ALT field 1881 (nth 3 field))))) ; ALT field
1878 ;; Either it is an empty ALT field. Then we have checked 1882 ;; Either it is an empty ALT field. Then we have checked
1879 ;; already that we have one non-empty alternative. Or it 1883 ;; already that we have one non-empty alternative. Or it
1880 ;; is an empty OPT field that we do not miss anyway. 1884 ;; is an empty OPT field that we do not miss anyway.
1881 ;; So we can safely delete this field. 1885 ;; So we can safely delete this field.
1882 (delete-region beg-field end-field) 1886 (delete-region beg-field end-field)
@@ -2041,19 +2045,33 @@ applied to the content of FIELD. It is an alist with pairs
2041 (dolist (pattern change-list content) 2045 (dolist (pattern change-list content)
2042 (setq content (replace-regexp-in-string (car pattern) 2046 (setq content (replace-regexp-in-string (car pattern)
2043 (cdr pattern) 2047 (cdr pattern)
2044 content))))) 2048 content t)))))
2045 2049
2046(defun bibtex-autokey-get-names () 2050(defun bibtex-autokey-get-names ()
2047 "Get contents of the name field of the current entry. 2051 "Get contents of the name field of the current entry.
2048Do some modifications based on `bibtex-autokey-name-change-strings' 2052Do some modifications based on `bibtex-autokey-name-change-strings'.
2049and return results as a list." 2053Return the names as a concatenated string obeying `bibtex-autokey-names'
2050 (let ((case-fold-search t) 2054and `bibtex-autokey-names-stretch'."
2051 (names (bibtex-autokey-get-field "author\\|editor" 2055 (let ((names (bibtex-autokey-get-field "author\\|editor"
2052 bibtex-autokey-name-change-strings))) 2056 bibtex-autokey-name-change-strings)))
2053 ;; Some entries do not have a name field. 2057 ;; Some entries do not have a name field.
2054 (unless (string= "" names) 2058 (unless (string= "" names)
2055 (mapcar 'bibtex-autokey-demangle-name 2059 (let* ((case-fold-search t)
2056 (split-string names "[ \t\n]+and[ \t\n]+"))))) 2060 (name-list (mapcar 'bibtex-autokey-demangle-name
2061 (split-string names "[ \t\n]+and[ \t\n]+")))
2062 additional-names)
2063 (unless (or (not (numberp bibtex-autokey-names))
2064 (<= (length name-list)
2065 (+ bibtex-autokey-names
2066 bibtex-autokey-names-stretch)))
2067 ;; Take bibtex-autokey-names elements from beginning of name-list
2068 (setq name-list (nreverse (nthcdr (- (length name-list)
2069 bibtex-autokey-names)
2070 (nreverse name-list)))
2071 additional-names bibtex-autokey-additional-names))
2072 (concat (mapconcat 'identity name-list
2073 bibtex-autokey-name-separator)
2074 additional-names)))))
2057 2075
2058(defun bibtex-autokey-demangle-name (fullname) 2076(defun bibtex-autokey-demangle-name (fullname)
2059 "Get the last part from a well-formed FULLNAME and perform abbreviations." 2077 "Get the last part from a well-formed FULLNAME and perform abbreviations."
@@ -2082,8 +2100,15 @@ and return results as a list."
2082 (funcall bibtex-autokey-name-case-convert name) 2100 (funcall bibtex-autokey-name-case-convert name)
2083 bibtex-autokey-name-length))) 2101 bibtex-autokey-name-length)))
2084 2102
2103(defun bibtex-autokey-get-year ()
2104 "Return year field contents as a string obeying `bibtex-autokey-year-length'."
2105 (let ((yearfield (bibtex-autokey-get-field "year")))
2106 (substring yearfield (max 0 (- (length yearfield)
2107 bibtex-autokey-year-length)))))
2108
2085(defun bibtex-autokey-get-title () 2109(defun bibtex-autokey-get-title ()
2086 "Get title field contents up to a terminator." 2110 "Get title field contents up to a terminator.
2111Return the result as a string"
2087 (let ((case-fold-search t) 2112 (let ((case-fold-search t)
2088 (titlestring 2113 (titlestring
2089 (bibtex-autokey-get-field "title" 2114 (bibtex-autokey-get-field "title"
@@ -2092,35 +2117,37 @@ and return results as a list."
2092 (dolist (terminator bibtex-autokey-title-terminators) 2117 (dolist (terminator bibtex-autokey-title-terminators)
2093 (if (string-match terminator titlestring) 2118 (if (string-match terminator titlestring)
2094 (setq titlestring (substring titlestring 0 (match-beginning 0))))) 2119 (setq titlestring (substring titlestring 0 (match-beginning 0)))))
2095 ;; gather words from titlestring into a list. Ignore 2120 ;; gather words from titlestring into a list. Ignore
2096 ;; specific words and use only a specific amount of words. 2121 ;; specific words and use only a specific amount of words.
2097 (let ((counter 0) 2122 (let ((counter 0)
2098 titlewords titlewords-extra titleword end-match) 2123 titlewords titlewords-extra word)
2099 (while (and (or (not (numberp bibtex-autokey-titlewords)) 2124 (while (and (or (not (numberp bibtex-autokey-titlewords))
2100 (< counter (+ bibtex-autokey-titlewords 2125 (< counter (+ bibtex-autokey-titlewords
2101 bibtex-autokey-titlewords-stretch))) 2126 bibtex-autokey-titlewords-stretch)))
2102 (string-match "\\b\\w+" titlestring)) 2127 (string-match "\\b\\w+" titlestring))
2103 (setq end-match (match-end 0) 2128 (setq word (match-string 0 titlestring)
2104 titleword (substring titlestring 2129 titlestring (substring titlestring (match-end 0)))
2105 (match-beginning 0) end-match)) 2130 ;; Ignore words matched by one of the elements of
2131 ;; bibtex-autokey-titleword-ignore
2106 (unless (let ((lst bibtex-autokey-titleword-ignore)) 2132 (unless (let ((lst bibtex-autokey-titleword-ignore))
2107 (while (and lst 2133 (while (and lst
2108 (not (string-match (concat "\\`\\(?:" (car lst) 2134 (not (string-match (concat "\\`\\(?:" (car lst)
2109 "\\)\\'") titleword))) 2135 "\\)\\'") word)))
2110 (setq lst (cdr lst))) 2136 (setq lst (cdr lst)))
2111 lst) 2137 lst)
2112 (setq titleword 2138 (setq word (funcall bibtex-autokey-titleword-case-convert word)
2113 (funcall bibtex-autokey-titleword-case-convert titleword)) 2139 counter (1+ counter))
2114 (if (or (not (numberp bibtex-autokey-titlewords)) 2140 (if (or (not (numberp bibtex-autokey-titlewords))
2115 (< counter bibtex-autokey-titlewords)) 2141 (< counter bibtex-autokey-titlewords))
2116 (setq titlewords (append titlewords (list titleword))) 2142 (push word titlewords)
2117 (setq titlewords-extra 2143 (push word titlewords-extra))))
2118 (append titlewords-extra (list titleword)))) 2144 ;; Obey bibtex-autokey-titlewords-stretch:
2119 (setq counter (1+ counter))) 2145 ;; If by now we have processed all words in titlestring, we include
2120 (setq titlestring (substring titlestring end-match))) 2146 ;; titlewords-extra in titlewords. Otherwise, we ignore titlewords-extra.
2121 (unless (string-match "\\b\\w+" titlestring) 2147 (unless (string-match "\\b\\w+" titlestring)
2122 (setq titlewords (append titlewords titlewords-extra))) 2148 (setq titlewords (append titlewords-extra titlewords)))
2123 (mapcar 'bibtex-autokey-demangle-title titlewords)))) 2149 (mapconcat 'bibtex-autokey-demangle-title (nreverse titlewords)
2150 bibtex-autokey-titleword-separator))))
2124 2151
2125(defun bibtex-autokey-demangle-title (titleword) 2152(defun bibtex-autokey-demangle-title (titleword)
2126 "Do some abbreviations on TITLEWORD. 2153 "Do some abbreviations on TITLEWORD.
@@ -2211,65 +2238,36 @@ The generation algorithm works as follows:
2211 the key is then presented in the minibuffer to the user, 2238 the key is then presented in the minibuffer to the user,
2212 where it can be edited. The key given by the user is then 2239 where it can be edited. The key given by the user is then
2213 used." 2240 used."
2214 (let* ((name-etal "") 2241 (let* ((names (bibtex-autokey-get-names))
2215 (namelist 2242 (year (bibtex-autokey-get-year))
2216 (let ((nl (bibtex-autokey-get-names)) 2243 (title (bibtex-autokey-get-title))
2217 nnl)
2218 (if (or (not (numberp bibtex-autokey-names))
2219 (<= (length nl)
2220 (+ bibtex-autokey-names
2221 bibtex-autokey-names-stretch)))
2222 nl
2223 (setq name-etal bibtex-autokey-additional-names)
2224 (while (< (length nnl) bibtex-autokey-names)
2225 (setq nnl (append nnl (list (car nl)))
2226 nl (cdr nl)))
2227 nnl)))
2228 (namepart (concat (mapconcat 'identity
2229 namelist
2230 bibtex-autokey-name-separator)
2231 name-etal))
2232 (yearfield (bibtex-autokey-get-field "year"))
2233 (yearpart (if (equal yearfield "")
2234 ""
2235 (substring yearfield
2236 (- (length yearfield)
2237 bibtex-autokey-year-length))))
2238 (titlepart (mapconcat 'identity
2239 (bibtex-autokey-get-title)
2240 bibtex-autokey-titleword-separator))
2241 (autokey (concat bibtex-autokey-prefix-string 2244 (autokey (concat bibtex-autokey-prefix-string
2242 namepart 2245 names
2243 (unless (or (equal namepart "") 2246 (unless (or (equal names "")
2244 (equal yearpart "")) 2247 (equal year ""))
2245 bibtex-autokey-name-year-separator) 2248 bibtex-autokey-name-year-separator)
2246 yearpart 2249 year
2247 (unless (or (and (equal namepart "") 2250 (unless (or (and (equal names "")
2248 (equal yearpart "")) 2251 (equal year ""))
2249 (equal titlepart "")) 2252 (equal title ""))
2250 bibtex-autokey-year-title-separator) 2253 bibtex-autokey-year-title-separator)
2251 titlepart))) 2254 title)))
2252 (if bibtex-autokey-before-presentation-function 2255 (if bibtex-autokey-before-presentation-function
2253 (funcall bibtex-autokey-before-presentation-function autokey) 2256 (funcall bibtex-autokey-before-presentation-function autokey)
2254 autokey))) 2257 autokey)))
2255 2258
2256 2259
2257(defun bibtex-parse-keys (&optional add abortable verbose) 2260(defun bibtex-read-key (prompt &optional key)
2261 "Read BibTeX key from minibuffer using PROMPT and default KEY."
2262 (completing-read prompt bibtex-reference-keys
2263 nil nil key 'bibtex-key-history))
2264
2265(defun bibtex-parse-keys (&optional abortable verbose)
2258 "Set `bibtex-reference-keys' to the keys used in the whole buffer. 2266 "Set `bibtex-reference-keys' to the keys used in the whole buffer.
2259The buffer might possibly be restricted. 2267Find both entry keys and crossref entries. If ABORTABLE is non-nil abort on
2260Find both entry keys and crossref entries. 2268user input. If VERBOSE is non-nil gives messages about progress. Return alist
2261If ADD is non-nil add the new keys to `bibtex-reference-keys' instead of 2269of keys if parsing was completed, `aborted' otherwise."
2262simply resetting it. If ADD is an alist of keys, also add ADD to 2270 (let (ref-keys crossref-keys)
2263`bibtex-reference-keys'. If ABORTABLE is non-nil abort on user
2264input. If VERBOSE is non-nil gives messages about progress.
2265Return alist of keys if parsing was completed, `aborted' otherwise."
2266 (let ((reference-keys (if (and add
2267 (listp bibtex-reference-keys))
2268 bibtex-reference-keys)))
2269 (if (listp add)
2270 (dolist (key add)
2271 (unless (assoc (car key) reference-keys)
2272 (push key reference-keys))))
2273 (save-excursion 2271 (save-excursion
2274 (save-match-data 2272 (save-match-data
2275 (if verbose 2273 (if verbose
@@ -2286,22 +2284,24 @@ Return alist of keys if parsing was completed, `aborted' otherwise."
2286 (if (and abortable (input-pending-p)) 2284 (if (and abortable (input-pending-p))
2287 ;; user has aborted by typing a key --> return `aborted' 2285 ;; user has aborted by typing a key --> return `aborted'
2288 (throw 'userkey 'aborted)) 2286 (throw 'userkey 'aborted))
2289 (let ((key (cond ((match-end 3) 2287 (cond ((match-end 3)
2290 ;; This is a crossref. 2288 ;; This is a crossref.
2291 (buffer-substring-no-properties 2289 (let ((key (buffer-substring-no-properties
2292 (1+ (match-beginning 3)) (1- (match-end 3)))) 2290 (1+ (match-beginning 3)) (1- (match-end 3)))))
2293 ((assoc-string (bibtex-type-in-head) 2291 (unless (assoc key crossref-keys)
2294 bibtex-entry-field-alist t) 2292 (push (list key) crossref-keys))))
2295 ;; This is an entry. 2293 ;; only keys of known entries
2296 (match-string-no-properties bibtex-key-in-head))))) 2294 ((assoc-string (bibtex-type-in-head)
2297 (if (and (stringp key) 2295 bibtex-entry-field-alist t)
2298 (not (assoc key reference-keys))) 2296 ;; This is an entry.
2299 (push (list key) reference-keys))))) 2297 (let ((key (bibtex-key-in-head)))
2298 (unless (assoc key ref-keys)
2299 (push (cons key t) ref-keys)))))))
2300 2300
2301 (let (;; ignore @String entries because they are handled 2301 (let (;; ignore @String entries because they are handled
2302 ;; separately by bibtex-parse-strings 2302 ;; separately by bibtex-parse-strings
2303 (bibtex-sort-ignore-string-entries t) 2303 (bibtex-sort-ignore-string-entries t)
2304 crossref-key bounds) 2304 bounds)
2305 (bibtex-map-entries 2305 (bibtex-map-entries
2306 (lambda (key beg end) 2306 (lambda (key beg end)
2307 (if (and abortable 2307 (if (and abortable
@@ -2309,17 +2309,19 @@ Return alist of keys if parsing was completed, `aborted' otherwise."
2309 ;; user has aborted by typing a key --> return `aborted' 2309 ;; user has aborted by typing a key --> return `aborted'
2310 (throw 'userkey 'aborted)) 2310 (throw 'userkey 'aborted))
2311 (if verbose (bibtex-progress-message)) 2311 (if verbose (bibtex-progress-message))
2312 (unless (assoc key reference-keys) 2312 (unless (assoc key ref-keys)
2313 (push (list key) reference-keys)) 2313 (push (cons key t) ref-keys))
2314 (if (and (setq bounds (bibtex-search-forward-field "crossref" end)) 2314 (if (and (setq bounds (bibtex-search-forward-field "crossref" end))
2315 (setq crossref-key (bibtex-text-in-field-bounds bounds t)) 2315 (setq key (bibtex-text-in-field-bounds bounds t))
2316 (not (assoc crossref-key reference-keys))) 2316 (not (assoc key crossref-keys)))
2317 (push (list crossref-key) reference-keys)))))) 2317 (push (list key) crossref-keys))))))
2318 2318
2319 (dolist (key crossref-keys)
2320 (unless (assoc (car key) ref-keys) (push key ref-keys)))
2319 (if verbose 2321 (if verbose
2320 (bibtex-progress-message 'done)) 2322 (bibtex-progress-message 'done))
2321 ;; successful operation --> return `bibtex-reference-keys' 2323 ;; successful operation --> return `bibtex-reference-keys'
2322 (setq bibtex-reference-keys reference-keys)))))) 2324 (setq bibtex-reference-keys ref-keys))))))
2323 2325
2324(defun bibtex-parse-strings (&optional add abortable) 2326(defun bibtex-parse-strings (&optional add abortable)
2325 "Set `bibtex-strings' to the string definitions in the whole buffer. 2327 "Set `bibtex-strings' to the string definitions in the whole buffer.
@@ -2355,39 +2357,44 @@ Return alist of strings if parsing was completed, `aborted' otherwise."
2355 2357
2356(defun bibtex-string-files-init () 2358(defun bibtex-string-files-init ()
2357 "Return initialization for `bibtex-strings'. 2359 "Return initialization for `bibtex-strings'.
2358Use `bibtex-predefined-strings' and bib files `bibtex-string-files'." 2360Use `bibtex-predefined-strings' and BibTeX files `bibtex-string-files'."
2359 (save-match-data 2361 (save-match-data
2360 ;; collect pathnames 2362 (let ((dirlist (split-string (or bibtex-string-file-path default-directory)
2361 (let ((dirlist (split-string (or bibtex-string-file-path ".")
2362 ":+")) 2363 ":+"))
2363 (case-fold-search) 2364 (case-fold-search)
2364 compl) 2365 string-files fullfilename compl bounds found)
2366 ;; collect absolute file names of valid string files
2365 (dolist (filename bibtex-string-files) 2367 (dolist (filename bibtex-string-files)
2366 (unless (string-match "\\.bib\\'" filename) 2368 (unless (string-match "\\.bib\\'" filename)
2367 (setq filename (concat filename ".bib"))) 2369 (setq filename (concat filename ".bib")))
2368 ;; test filenames 2370 ;; test filenames
2369 (let (fullfilename bounds found) 2371 (if (file-name-absolute-p filename)
2372 (if (file-readable-p filename)
2373 (push filename string-files)
2374 (error "BibTeX strings file %s not found" filename))
2370 (dolist (dir dirlist) 2375 (dolist (dir dirlist)
2371 (when (file-readable-p 2376 (when (file-readable-p
2372 (setq fullfilename (expand-file-name filename dir))) 2377 (setq fullfilename (expand-file-name filename dir)))
2373 ;; file was found 2378 (push fullfilename string-files)
2374 (with-temp-buffer
2375 (insert-file-contents fullfilename)
2376 (goto-char (point-min))
2377 (while (setq bounds (bibtex-search-forward-string))
2378 (push (cons (bibtex-reference-key-in-string bounds)
2379 (bibtex-text-in-string bounds t))
2380 compl)
2381 (goto-char (bibtex-end-of-string bounds))))
2382 (setq found t))) 2379 (setq found t)))
2383 (unless found 2380 (unless found
2384 (error "File %s not in paths defined via bibtex-string-file-path" 2381 (error "File %s not in paths defined via bibtex-string-file-path"
2385 filename)))) 2382 filename))))
2383 ;; parse string files
2384 (dolist (filename string-files)
2385 (with-temp-buffer
2386 (insert-file-contents filename)
2387 (goto-char (point-min))
2388 (while (setq bounds (bibtex-search-forward-string))
2389 (push (cons (bibtex-reference-key-in-string bounds)
2390 (bibtex-text-in-string bounds t))
2391 compl)
2392 (goto-char (bibtex-end-of-string bounds)))))
2386 (append bibtex-predefined-strings (nreverse compl))))) 2393 (append bibtex-predefined-strings (nreverse compl)))))
2387 2394
2388(defun bibtex-parse-buffers-stealthily () 2395(defun bibtex-parse-buffers-stealthily ()
2389 "Parse buffer in the background during idle time. 2396 "Parse buffer in the background during idle time.
2390Called by `bibtex-run-with-idle-timer'. Whenever Emacs has been idle 2397Called by `run-with-idle-timer'. Whenever Emacs has been idle
2391for `bibtex-parse-keys-timeout' seconds, all BibTeX buffers (starting 2398for `bibtex-parse-keys-timeout' seconds, all BibTeX buffers (starting
2392with the current) are parsed." 2399with the current) are parsed."
2393 (save-excursion 2400 (save-excursion
@@ -2402,7 +2409,7 @@ with the current) are parsed."
2402 (widen) 2409 (widen)
2403 ;; Output no progress messages in bibtex-parse-keys 2410 ;; Output no progress messages in bibtex-parse-keys
2404 ;; because when in y-or-n-p that can hide the question. 2411 ;; because when in y-or-n-p that can hide the question.
2405 (if (and (listp (bibtex-parse-keys nil t)) 2412 (if (and (listp (bibtex-parse-keys t))
2406 ;; update bibtex-strings 2413 ;; update bibtex-strings
2407 (listp (bibtex-parse-strings strings-init t))) 2414 (listp (bibtex-parse-strings strings-init t)))
2408 2415
@@ -2410,6 +2417,51 @@ with the current) are parsed."
2410 (setq bibtex-buffer-last-parsed-tick (buffer-modified-tick))))) 2417 (setq bibtex-buffer-last-parsed-tick (buffer-modified-tick)))))
2411 (setq buffers (cdr buffers)))))) 2418 (setq buffers (cdr buffers))))))
2412 2419
2420(defun bibtex-files-expand (&optional current)
2421 "Return an expanded list of BibTeX buffers based on `bibtex-files'.
2422Initialize in these buffers `bibtex-reference-keys' if not yet set.
2423List includes current buffer if CURRENT is non-nil."
2424 (let ((file-path (split-string (or bibtex-file-path default-directory) ":+"))
2425 file-list dir-list buffer-list)
2426 (dolist (file bibtex-files)
2427 (cond ((eq file 'bibtex-file-path)
2428 (setq dir-list (append dir-list file-path)))
2429 ((file-accessible-directory-p file)
2430 (push file dir-list))
2431 ((progn (unless (string-match "\\.bib\\'" file)
2432 (setq file (concat file ".bib")))
2433 (file-name-absolute-p file))
2434 (push file file-list))
2435 (t
2436 (let (fullfilename found)
2437 (dolist (dir file-path)
2438 (when (file-readable-p
2439 (setq fullfilename (expand-file-name file dir)))
2440 (push fullfilename file-list)
2441 (setq found t)))
2442 (unless found
2443 (error "File %s not in paths defined via bibtex-file-path"
2444 file))))))
2445 (dolist (file file-list)
2446 (unless (file-readable-p file)
2447 (error "BibTeX file %s not found" file)))
2448 ;; expand dir-list
2449 (dolist (dir dir-list)
2450 (setq file-list
2451 (append file-list (directory-files dir t "\\.bib\\'" t))))
2452 (delete-dups file-list)
2453 (dolist (file file-list)
2454 (when (file-readable-p file)
2455 (push (find-file-noselect file) buffer-list)
2456 (with-current-buffer (car buffer-list)
2457 (unless (listp bibtex-reference-keys)
2458 (bibtex-parse-keys)))))
2459 (cond ((and current (not (memq (current-buffer) buffer-list)))
2460 (push (current-buffer) buffer-list))
2461 ((and (not current) (memq (current-buffer) buffer-list))
2462 (setq buffer-list (delq (current-buffer) buffer-list))))
2463 buffer-list))
2464
2413(defun bibtex-complete-internal (completions) 2465(defun bibtex-complete-internal (completions)
2414 "Complete word fragment before point to longest prefix of COMPLETIONS. 2466 "Complete word fragment before point to longest prefix of COMPLETIONS.
2415COMPLETIONS should be a list of strings. If point is not after the part 2467COMPLETIONS should be a list of strings. If point is not after the part
@@ -2459,58 +2511,59 @@ expansion of STR using expansion list STRINGS-ALIST."
2459 (bibtex-remove-delimiters)))))))) 2511 (bibtex-remove-delimiters))))))))
2460 2512
2461(defun bibtex-complete-key-cleanup (key) 2513(defun bibtex-complete-key-cleanup (key)
2462 "Display message on entry KEY after completion of a crossref key." 2514 "Display summary message on entry KEY after completion of a crossref key.
2515Use `bibtex-summary-function' to generate summary."
2463 (save-excursion 2516 (save-excursion
2464 ;; Don't do anything if we completed the key of an entry. 2517 ;; Don't do anything if we completed the key of an entry.
2465 (let ((pnt (bibtex-beginning-of-entry))) 2518 (let ((pnt (bibtex-beginning-of-entry)))
2466 (if (and (stringp key) 2519 (if (and (stringp key)
2467 (bibtex-find-entry key) 2520 (bibtex-find-entry key)
2468 (/= pnt (point))) 2521 (/= pnt (point)))
2469 (let* ((bibtex-autokey-name-case-convert 'identity) 2522 (message "Ref: %s" (funcall bibtex-summary-function key))))))
2470 (bibtex-autokey-name-length 'infty) 2523
2471 (nl (bibtex-autokey-get-names)) 2524(defun bibtex-copy-summary-as-kill (key)
2472 (name (concat (nth 0 nl) (if (nth 1 nl) " etal"))) 2525 "Push summery of BibTeX entry KEY to kill ring.
2473 (year (bibtex-autokey-get-field "year")) 2526Use `bibtex-summary-function' to generate summary."
2474 (bibtex-autokey-titlewords 5) 2527 (interactive
2475 (bibtex-autokey-titlewords-stretch 2) 2528 (list (bibtex-read-key
2476 (bibtex-autokey-titleword-case-convert 'identity) 2529 "Key: " (save-excursion
2477 (bibtex-autokey-titleword-length 5) 2530 (bibtex-beginning-of-entry)
2478 (title (mapconcat 'identity 2531 (when (re-search-forward bibtex-entry-head nil t)
2479 (bibtex-autokey-get-title) " ")) 2532 (bibtex-key-in-head))))))
2480 (journal (bibtex-autokey-get-field 2533 (kill-new (message "%s" (funcall bibtex-summary-function key))))
2481 "journal" bibtex-autokey-transcriptions)) 2534
2482 (volume (bibtex-autokey-get-field "volume")) 2535(defun bibtex-summary (key)
2483 (pages (bibtex-autokey-get-field "pages" '(("-.*\\'" . ""))))) 2536 "Return summary of BibTeX entry KEY.
2484 (message "Ref:%s" 2537Used as default value of `bibtex-summary-function'."
2485 (mapconcat (lambda (arg) 2538 ;; It would be neat to customize this function. How?
2486 (if (not (string= "" (cdr arg))) 2539 (save-excursion
2487 (concat (car arg) (cdr arg)))) 2540 (if (bibtex-find-entry key)
2488 `((" " . ,name) (" " . ,year) 2541 (let* ((bibtex-autokey-name-case-convert 'identity)
2489 (": " . ,title) (", " . ,journal) 2542 (bibtex-autokey-name-length 'infty)
2490 (" " . ,volume) (":" . ,pages)) 2543 (bibtex-autokey-names 1)
2491 ""))))))) 2544 (bibtex-autokey-names-stretch 0)
2492 2545 (bibtex-autokey-name-separator " ")
2493(defun bibtex-choose-completion-string (choice buffer mini-p base-size) 2546 (bibtex-autokey-additional-names " etal")
2494 ;; Code borrowed from choose-completion-string: 2547 (names (bibtex-autokey-get-names))
2495 ;; We must duplicate the code from choose-completion-string 2548 (bibtex-autokey-year-length 4)
2496 ;; because it runs the hook choose-completion-string-functions 2549 (year (bibtex-autokey-get-year))
2497 ;; before it inserts the completion. But we want to do something 2550 (bibtex-autokey-titlewords 5)
2498 ;; after the completion has been inserted. 2551 (bibtex-autokey-titlewords-stretch 2)
2499 ;; 2552 (bibtex-autokey-titleword-case-convert 'identity)
2500 ;; Insert the completion into the buffer where it was requested. 2553 (bibtex-autokey-titleword-length 5)
2501 (set-buffer buffer) 2554 (bibtex-autokey-titleword-separator " ")
2502 (if base-size 2555 (title (bibtex-autokey-get-title))
2503 (delete-region (+ base-size (point-min)) 2556 (journal (bibtex-autokey-get-field
2504 (point)) 2557 "journal" bibtex-autokey-transcriptions))
2505 ;; Delete the longest partial match for CHOICE 2558 (volume (bibtex-autokey-get-field "volume"))
2506 ;; that can be found before point. 2559 (pages (bibtex-autokey-get-field "pages" '(("-.*\\'" . "")))))
2507 (choose-completion-delete-max-match choice)) 2560 (mapconcat (lambda (arg)
2508 (insert choice) 2561 (if (not (string= "" (cdr arg)))
2509 (remove-text-properties (- (point) (length choice)) (point) 2562 (concat (car arg) (cdr arg))))
2510 '(mouse-face nil)) 2563 `((" " . ,names) (" " . ,year) (": " . ,title)
2511 ;; Update point in the window that BUFFER is showing in. 2564 (", " . ,journal) (" " . ,volume) (":" . ,pages))
2512 (let ((window (get-buffer-window buffer t))) 2565 ""))
2513 (set-window-point window (point)))) 2566 (error "Key `%s' not found." key))))
2514 2567
2515(defun bibtex-pop (arg direction) 2568(defun bibtex-pop (arg direction)
2516 "Fill current field from the ARG'th same field's text in DIRECTION. 2569 "Fill current field from the ARG'th same field's text in DIRECTION.
@@ -2550,7 +2603,7 @@ Generic function used by `bibtex-pop-previous' and `bibtex-pop-next'."
2550 (if failure 2603 (if failure
2551 (error "No %s matching BibTeX field" 2604 (error "No %s matching BibTeX field"
2552 (if (eq direction 'previous) "previous" "next")) 2605 (if (eq direction 'previous) "previous" "next"))
2553 ;; Found a matching field. Remember boundaries. 2606 ;; Found a matching field. Remember boundaries.
2554 (setq bibtex-pop-previous-search-point (bibtex-start-of-field bounds) 2607 (setq bibtex-pop-previous-search-point (bibtex-start-of-field bounds)
2555 bibtex-pop-next-search-point (bibtex-end-of-field bounds) 2608 bibtex-pop-next-search-point (bibtex-end-of-field bounds)
2556 new-text (bibtex-text-in-field-bounds bounds)) 2609 new-text (bibtex-text-in-field-bounds bounds))
@@ -2563,10 +2616,82 @@ Generic function used by `bibtex-pop-previous' and `bibtex-pop-next'."
2563 (bibtex-find-text nil)) 2616 (bibtex-find-text nil))
2564 (setq this-command 'bibtex-pop)) 2617 (setq this-command 'bibtex-pop))
2565 2618
2566(defsubst bibtex-read-key (prompt &optional key) 2619(defun bibtex-beginning-of-field ()
2567 "Read BibTeX key from minibuffer using PROMPT and default KEY." 2620 "Move point backward to beginning of field.
2568 (completing-read prompt bibtex-reference-keys 2621This function uses a simple, fast algorithm assuming that the field
2569 nil nil key 'bibtex-key-history)) 2622begins at the beginning of a line. We use this function for font-locking."
2623 (let ((field-reg (concat "^[ \t]*" bibtex-field-name "[ \t]*=")))
2624 (beginning-of-line)
2625 (unless (looking-at field-reg)
2626 (re-search-backward field-reg nil t))))
2627
2628(defun bibtex-font-lock-url (bound)
2629 "Font-lock for URLs."
2630 (let ((case-fold-search t)
2631 (pnt (point))
2632 field bounds start end found)
2633 (bibtex-beginning-of-field)
2634 (while (and (not found)
2635 (prog1 (re-search-forward bibtex-font-lock-url-regexp bound t)
2636 (setq field (match-string-no-properties 1)))
2637 (setq bounds (bibtex-parse-field-text))
2638 (progn
2639 (setq start (car bounds) end (cdr bounds))
2640 ;; Always ignore field delimiters
2641 (if (memq (char-before end) '(?\} ?\"))
2642 (setq end (1- end)))
2643 (if (memq (char-after start) '(?\{ ?\"))
2644 (setq start (1+ start)))
2645 (>= bound start)))
2646 (let ((lst bibtex-generate-url-list) url)
2647 (goto-char start)
2648 (while (and (not found)
2649 (setq url (caar lst)))
2650 (setq found (and (bibtex-string= field (car url))
2651 (re-search-forward (cdr url) end t)
2652 (>= (match-beginning 0) pnt))
2653 lst (cdr lst))))
2654 (goto-char end))
2655 (if found (bibtex-button (match-beginning 0) (match-end 0)
2656 'bibtex-url (match-beginning 0)))
2657 found))
2658
2659(defun bibtex-font-lock-crossref (bound)
2660 "Font-lock for crossref fields."
2661 (let ((case-fold-search t)
2662 (pnt (point))
2663 (crossref-reg (concat "^[ \t]*crossref[ \t]*=[ \t\n]*"
2664 "\\(\"[^\"]*\"\\|{[^}]*}\\)[ \t\n]*[,})]"))
2665 start end found)
2666 (bibtex-beginning-of-field)
2667 (while (and (not found)
2668 (re-search-forward crossref-reg bound t))
2669 (setq start (1+ (match-beginning 1))
2670 end (1- (match-end 1))
2671 found (>= start pnt)))
2672 (if found (bibtex-button start end 'bibtex-find-crossref
2673 (buffer-substring-no-properties start end)
2674 start t))
2675 found))
2676
2677(defun bibtex-button-action (button)
2678 "Call BUTTON's BibTeX function."
2679 (apply (button-get button 'bibtex-function)
2680 (button-get button 'bibtex-args)))
2681
2682(define-button-type 'bibtex-url
2683 'action 'bibtex-button-action
2684 'bibtex-function 'bibtex-url
2685 'help-echo (purecopy "mouse-2, RET: follow URL"))
2686
2687(define-button-type 'bibtex-find-crossref
2688 'action 'bibtex-button-action
2689 'bibtex-function 'bibtex-find-crossref
2690 'help-echo (purecopy "mouse-2, RET: follow crossref"))
2691
2692(defun bibtex-button (beg end type &rest args)
2693 (make-text-button beg end 'type type 'bibtex-args args))
2694
2570 2695
2571;; Interactive Functions: 2696;; Interactive Functions:
2572 2697
@@ -2668,7 +2793,7 @@ non-nil.
2668 (make-local-variable 'bibtex-buffer-last-parsed-tick) 2793 (make-local-variable 'bibtex-buffer-last-parsed-tick)
2669 ;; Install stealthy parse function if not already installed 2794 ;; Install stealthy parse function if not already installed
2670 (unless bibtex-parse-idle-timer 2795 (unless bibtex-parse-idle-timer
2671 (setq bibtex-parse-idle-timer (bibtex-run-with-idle-timer 2796 (setq bibtex-parse-idle-timer (run-with-idle-timer
2672 bibtex-parse-keys-timeout t 2797 bibtex-parse-keys-timeout t
2673 'bibtex-parse-buffers-stealthily))) 2798 'bibtex-parse-buffers-stealthily)))
2674 (set (make-local-variable 'paragraph-start) "[ \f\n\t]*$") 2799 (set (make-local-variable 'paragraph-start) "[ \f\n\t]*$")
@@ -2680,8 +2805,8 @@ non-nil.
2680 (set (make-local-variable 'outline-regexp) "[ \t]*@") 2805 (set (make-local-variable 'outline-regexp) "[ \t]*@")
2681 (set (make-local-variable 'fill-paragraph-function) 'bibtex-fill-field) 2806 (set (make-local-variable 'fill-paragraph-function) 'bibtex-fill-field)
2682 (set (make-local-variable 'fill-prefix) (make-string (+ bibtex-entry-offset 2807 (set (make-local-variable 'fill-prefix) (make-string (+ bibtex-entry-offset
2683 bibtex-contline-indentation) 2808 bibtex-contline-indentation)
2684 ? )) 2809 ? ))
2685 (set (make-local-variable 'font-lock-defaults) 2810 (set (make-local-variable 'font-lock-defaults)
2686 '(bibtex-font-lock-keywords 2811 '(bibtex-font-lock-keywords
2687 nil t ((?$ . "\"") 2812 nil t ((?$ . "\"")
@@ -2693,7 +2818,7 @@ non-nil.
2693 ) 2818 )
2694 nil 2819 nil
2695 (font-lock-syntactic-keywords . bibtex-font-lock-syntactic-keywords) 2820 (font-lock-syntactic-keywords . bibtex-font-lock-syntactic-keywords)
2696 (font-lock-extra-managed-props . (mouse-face keymap)) 2821 (font-lock-extra-managed-props . (category))
2697 (font-lock-mark-block-function 2822 (font-lock-mark-block-function
2698 . (lambda () 2823 . (lambda ()
2699 (set-mark (bibtex-end-of-entry)) 2824 (set-mark (bibtex-end-of-entry))
@@ -2776,8 +2901,7 @@ according to `bibtex-entry-field-alist', but are not yet present."
2776 ;; bibtex-parse-entry moves point to the end of the last field. 2901 ;; bibtex-parse-entry moves point to the end of the last field.
2777 (let* ((fields-alist (bibtex-parse-entry)) 2902 (let* ((fields-alist (bibtex-parse-entry))
2778 (field-list (bibtex-field-list 2903 (field-list (bibtex-field-list
2779 (substring (cdr (assoc "=type=" fields-alist)) 2904 (cdr (assoc "=type=" fields-alist)))))
2780 1)))) ; don't want @
2781 (dolist (field (car field-list)) 2905 (dolist (field (car field-list))
2782 (unless (assoc-string (car field) fields-alist t) 2906 (unless (assoc-string (car field) fields-alist t)
2783 (bibtex-make-field field))) 2907 (bibtex-make-field field)))
@@ -2793,8 +2917,8 @@ TEXT may be nil. Remove \"OPT\" and \"ALT\" from FIELD.
2793Move point to the end of the last field." 2917Move point to the end of the last field."
2794 (let (alist bounds) 2918 (let (alist bounds)
2795 (when (looking-at bibtex-entry-maybe-empty-head) 2919 (when (looking-at bibtex-entry-maybe-empty-head)
2796 (push (cons "=type=" (match-string bibtex-type-in-head)) alist) 2920 (push (cons "=type=" (bibtex-type-in-head)) alist)
2797 (push (cons "=key=" (match-string bibtex-key-in-head)) alist) 2921 (push (cons "=key=" (bibtex-key-in-head)) alist)
2798 (goto-char (match-end 0)) 2922 (goto-char (match-end 0))
2799 (while (setq bounds (bibtex-parse-field bibtex-field-name)) 2923 (while (setq bounds (bibtex-parse-field bibtex-field-name))
2800 (push (cons (bibtex-name-in-field bounds t) 2924 (push (cons (bibtex-name-in-field bounds t)
@@ -2809,8 +2933,8 @@ Move point to the end of the last field."
2809 (undo-boundary) ;So you can easily undo it, if it didn't work right. 2933 (undo-boundary) ;So you can easily undo it, if it didn't work right.
2810 (bibtex-beginning-of-entry) 2934 (bibtex-beginning-of-entry)
2811 (when (looking-at bibtex-entry-head) 2935 (when (looking-at bibtex-entry-head)
2812 (let ((type (match-string bibtex-type-in-head)) 2936 (let ((type (bibtex-type-in-head))
2813 (key (match-string bibtex-key-in-head)) 2937 (key (bibtex-key-in-head))
2814 (key-end (match-end bibtex-key-in-head)) 2938 (key-end (match-end bibtex-key-in-head))
2815 (case-fold-search t) 2939 (case-fold-search t)
2816 tmp other-key other bounds) 2940 tmp other-key other bounds)
@@ -2823,9 +2947,9 @@ Move point to the end of the last field."
2823 (bibtex-beginning-of-entry) 2947 (bibtex-beginning-of-entry)
2824 (when (and 2948 (when (and
2825 (looking-at bibtex-entry-head) 2949 (looking-at bibtex-entry-head)
2826 (bibtex-string= type (match-string bibtex-type-in-head)) 2950 (bibtex-string= type (bibtex-type-in-head))
2827 ;; In case we found ourselves :-( 2951 ;; In case we found ourselves :-(
2828 (not (equal key (setq tmp (match-string bibtex-key-in-head))))) 2952 (not (equal key (setq tmp (bibtex-key-in-head)))))
2829 (setq other-key tmp) 2953 (setq other-key tmp)
2830 (setq other (point)))) 2954 (setq other (point))))
2831 (save-excursion 2955 (save-excursion
@@ -2833,9 +2957,9 @@ Move point to the end of the last field."
2833 (bibtex-skip-to-valid-entry) 2957 (bibtex-skip-to-valid-entry)
2834 (when (and 2958 (when (and
2835 (looking-at bibtex-entry-head) 2959 (looking-at bibtex-entry-head)
2836 (bibtex-string= type (match-string bibtex-type-in-head)) 2960 (bibtex-string= type (bibtex-type-in-head))
2837 ;; In case we found ourselves :-( 2961 ;; In case we found ourselves :-(
2838 (not (equal key (setq tmp (match-string bibtex-key-in-head)))) 2962 (not (equal key (setq tmp (bibtex-key-in-head))))
2839 (or (not other-key) 2963 (or (not other-key)
2840 ;; Check which is the best match. 2964 ;; Check which is the best match.
2841 (< (length (try-completion "" (list key other-key))) 2965 (< (length (try-completion "" (list key other-key)))
@@ -2883,24 +3007,26 @@ Move point to the end of the last field."
2883 (message (nth 1 comment)) 3007 (message (nth 1 comment))
2884 (message "No comment available"))))) 3008 (message "No comment available")))))
2885 3009
2886(defun bibtex-make-field (field &optional called-by-yank) 3010(defun bibtex-make-field (field &optional called-by-yank interactive)
2887 "Make a field named FIELD in current BibTeX entry. 3011 "Make a field named FIELD in current BibTeX entry.
2888FIELD is either a string or a list of the form 3012FIELD is either a string or a list of the form
2889\(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in 3013\(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in
2890`bibtex-entry-field-alist'. 3014`bibtex-entry-field-alist'.
2891If CALLED-BY-YANK is non-nil, don't insert delimiters." 3015If CALLED-BY-YANK is non-nil, don't insert delimiters.
3016In that case, or when called interactively, also don't do (WHAT?)."
2892 (interactive 3017 (interactive
2893 (list (let ((completion-ignore-case t) 3018 (list (let ((completion-ignore-case t)
2894 (field-list (bibtex-field-list 3019 (field-list (bibtex-field-list
2895 (save-excursion 3020 (save-excursion
2896 (bibtex-enclosing-entry-maybe-empty-head) 3021 (bibtex-enclosing-entry-maybe-empty-head)
2897 (bibtex-type-in-head))))) 3022 (bibtex-type-in-head)))))
2898 (completing-read "BibTeX field name: " 3023 (completing-read "BibTeX field name: "
2899 (append (car field-list) (cdr field-list)) 3024 (append (car field-list) (cdr field-list))
2900 nil nil nil bibtex-field-history)))) 3025 nil nil nil bibtex-field-history))
3026 t))
2901 (unless (consp field) 3027 (unless (consp field)
2902 (setq field (list field))) 3028 (setq field (list field)))
2903 (if (or (interactive-p) called-by-yank) 3029 (if (or interactive called-by-yank)
2904 (let (bibtex-help-message) 3030 (let (bibtex-help-message)
2905 (bibtex-find-text nil t t) 3031 (bibtex-find-text nil t t)
2906 (if (looking-at "[}\"]") 3032 (if (looking-at "[}\"]")
@@ -2923,7 +3049,7 @@ If CALLED-BY-YANK is non-nil, don't insert delimiters."
2923 ((fboundp init) 3049 ((fboundp init)
2924 (insert (funcall init))))) 3050 (insert (funcall init)))))
2925 (unless called-by-yank (insert (bibtex-field-right-delimiter))) 3051 (unless called-by-yank (insert (bibtex-field-right-delimiter)))
2926 (when (interactive-p) 3052 (when interactive
2927 (forward-char -1) 3053 (forward-char -1)
2928 (bibtex-print-help-message))) 3054 (bibtex-print-help-message)))
2929 3055
@@ -3003,17 +3129,13 @@ If mark is active it counts entries in region, if not in whole buffer."
3003 (not count-string-entries))) 3129 (not count-string-entries)))
3004 (save-excursion 3130 (save-excursion
3005 (save-restriction 3131 (save-restriction
3006 (narrow-to-region (if (bibtex-mark-active) 3132 (narrow-to-region (if mark-active (region-beginning)
3007 (region-beginning)
3008 (bibtex-beginning-of-first-entry)) 3133 (bibtex-beginning-of-first-entry))
3009 (if (bibtex-mark-active) 3134 (if mark-active (region-end) (point-max)))
3010 (region-end)
3011 (point-max)))
3012 (goto-char (point-min))
3013 (bibtex-map-entries (lambda (key beg end) 3135 (bibtex-map-entries (lambda (key beg end)
3014 (setq number (1+ number)))))) 3136 (setq number (1+ number))))))
3015 (message "%s contains %d entries." 3137 (message "%s contains %d entries."
3016 (if (bibtex-mark-active) "Region" "Buffer") 3138 (if mark-active "Region" "Buffer")
3017 number))) 3139 number)))
3018 3140
3019(defun bibtex-ispell-entry () 3141(defun bibtex-ispell-entry ()
@@ -3110,12 +3232,39 @@ will be ignored."
3110 nil ; ENDKEY function 3232 nil ; ENDKEY function
3111 'bibtex-lessp))) ; PREDICATE 3233 'bibtex-lessp))) ; PREDICATE
3112 3234
3113(defun bibtex-find-crossref (crossref-key) 3235(defun bibtex-find-entry-globally (key)
3236 "Move point to the beginning of BibTeX entry named KEY in `bibtex-files'."
3237 (interactive
3238 (list (let (key-alist)
3239 (dolist (buffer (bibtex-files-expand t))
3240 (with-current-buffer buffer
3241 (setq key-alist (append bibtex-reference-keys key-alist))))
3242 (completing-read "Find key: " key-alist
3243 nil nil nil 'bibtex-key-history))))
3244 (let ((buffer-list (bibtex-files-expand t))
3245 buffer found)
3246 (while (and (not found)
3247 (setq buffer (pop buffer-list)))
3248 (with-current-buffer buffer
3249 (if (cdr (assoc-string key bibtex-reference-keys))
3250 (setq found t))))
3251 (if found
3252 (progn
3253 (let ((same-window-buffer-names
3254 (cons (buffer-name buffer) same-window-buffer-names)))
3255 (pop-to-buffer buffer))
3256 (bibtex-find-entry key))
3257 (message "Key `%s' not found" key))))
3258
3259(defun bibtex-find-crossref (crossref-key &optional pnt split)
3114 "Move point to the beginning of BibTeX entry CROSSREF-KEY. 3260 "Move point to the beginning of BibTeX entry CROSSREF-KEY.
3115Return position of entry if CROSSREF-KEY is found and nil otherwise. 3261Return position of entry if CROSSREF-KEY is found and nil otherwise.
3116If position of current entry is after CROSSREF-KEY an error is signaled. 3262If position of current entry is after CROSSREF-KEY an error is signaled.
3263Optional arg PNT is the position of the referencing entry.
3264If optional arg SPLIT is non-nil, split window so that both the referencing
3265and the crossrefed entry are displayed.
3117If called interactively, CROSSREF-KEY defaults to crossref key of current 3266If called interactively, CROSSREF-KEY defaults to crossref key of current
3118entry." 3267entry and SPLIT is t."
3119 (interactive 3268 (interactive
3120 (let ((crossref-key 3269 (let ((crossref-key
3121 (save-excursion 3270 (save-excursion
@@ -3123,11 +3272,23 @@ entry."
3123 (let ((bounds (bibtex-search-forward-field "crossref" t))) 3272 (let ((bounds (bibtex-search-forward-field "crossref" t)))
3124 (if bounds 3273 (if bounds
3125 (bibtex-text-in-field-bounds bounds t)))))) 3274 (bibtex-text-in-field-bounds bounds t))))))
3126 (list (bibtex-read-key "Find crossref key: " crossref-key)))) 3275 (list (bibtex-read-key "Find crossref key: " crossref-key) (point) t)))
3127 (let ((pos (save-excursion (bibtex-find-entry crossref-key)))) 3276 (let ((pos (save-excursion (bibtex-find-entry crossref-key))))
3128 (if (and pos (> (point) pos)) 3277 (unless pnt (setq pnt (point)))
3129 (error "This entry must not follow the crossrefed entry!")) 3278 (cond ((not pos)
3130 (goto-char pos))) 3279 (message "Crossref key `%s' not found" crossref-key))
3280 (split
3281 (goto-char pnt)
3282 (select-window (split-window))
3283 (goto-char pos)
3284 (beginning-of-line)
3285 (set-window-start (selected-window) (point))
3286 (if (> pnt pos)
3287 (error "The referencing entry must preceed the crossrefed entry!")))
3288 ((> pnt pos)
3289 (error "The referencing entry must preceed the crossrefed entry!"))
3290 (t (goto-char pos)))
3291 pos))
3131 3292
3132(defun bibtex-find-entry (key &optional start) 3293(defun bibtex-find-entry (key &optional start)
3133 "Move point to the beginning of BibTeX entry named KEY. 3294 "Move point to the beginning of BibTeX entry named KEY.
@@ -3212,23 +3373,21 @@ Return t if preparation was successful or nil if entry KEY already exists."
3212 3373
3213(defun bibtex-validate (&optional test-thoroughly) 3374(defun bibtex-validate (&optional test-thoroughly)
3214 "Validate if buffer or region is syntactically correct. 3375 "Validate if buffer or region is syntactically correct.
3215Only known entry types are checked, so you can put comments 3376Check also for duplicate keys and correct sort order provided
3216outside of entries. 3377`bibtex-maintain-sorted-entries' is non-nil.
3217With optional argument TEST-THOROUGHLY non-nil it checks for absence of 3378With optional argument TEST-THOROUGHLY non-nil check also for
3218required fields and questionable month fields as well. 3379the absence of required fields and for questionable month fields.
3219If mark is active, validate current region, if not the whole buffer. 3380If mark is active, validate current region, if not the whole buffer.
3220Returns t if test was successful, nil otherwise." 3381Only check known entry types, so you can put comments outside of entries.
3382Return t if test was successful, nil otherwise."
3221 (interactive "P") 3383 (interactive "P")
3222 (let* ((case-fold-search t) 3384 (let* ((case-fold-search t)
3223 error-list syntax-error) 3385 error-list syntax-error)
3224 (save-excursion 3386 (save-excursion
3225 (save-restriction 3387 (save-restriction
3226 (narrow-to-region (if (bibtex-mark-active) 3388 (narrow-to-region (if mark-active (region-beginning)
3227 (region-beginning)
3228 (bibtex-beginning-of-first-entry)) 3389 (bibtex-beginning-of-first-entry))
3229 (if (bibtex-mark-active) 3390 (if mark-active (region-end) (point-max)))
3230 (region-end)
3231 (point-max)))
3232 3391
3233 ;; looking if entries fit syntactical structure 3392 ;; looking if entries fit syntactical structure
3234 (goto-char (point-min)) 3393 (goto-char (point-min))
@@ -3244,41 +3403,54 @@ Returns t if test was successful, nil otherwise."
3244 (if (equal (point) pnt) 3403 (if (equal (point) pnt)
3245 (forward-char) 3404 (forward-char)
3246 (goto-char pnt) 3405 (goto-char pnt)
3247 (push (list (bibtex-current-line) 3406 (push (cons (bibtex-current-line)
3248 "Syntax error (check esp. commas, braces, and quotes)") 3407 "Syntax error (check esp. commas, braces, and quotes)")
3249 error-list) 3408 error-list)
3250 (forward-char)))))) 3409 (forward-char))))))
3251 (bibtex-progress-message 'done) 3410 (bibtex-progress-message 'done)
3252 3411
3253 (if error-list 3412 (if error-list
3413 ;; proceed only if there were no syntax errors.
3254 (setq syntax-error t) 3414 (setq syntax-error t)
3255 ;; looking for correct sort order and duplicates (only if 3415
3256 ;; there were no syntax errors) 3416 ;; looking for duplicate keys and correct sort order
3257 (if bibtex-maintain-sorted-entries 3417 (let (previous current key-list)
3258 (let (previous current) 3418 (bibtex-progress-message "Checking for duplicate keys")
3259 (goto-char (point-min)) 3419 (bibtex-map-entries
3260 (bibtex-progress-message "Checking correct sort order") 3420 (lambda (key beg end)
3261 (bibtex-map-entries 3421 (bibtex-progress-message)
3262 (lambda (key beg end) 3422 (goto-char beg)
3263 (bibtex-progress-message) 3423 (setq current (bibtex-entry-index))
3264 (goto-char beg) 3424 (cond ((not previous))
3265 (setq current (bibtex-entry-index)) 3425 ((member key key-list)
3266 (cond ((or (not previous) 3426 (push (cons (bibtex-current-line)
3267 (bibtex-lessp previous current)) 3427 (format "Duplicate key `%s'" key))
3268 (setq previous current)) 3428 error-list))
3269 ((string-equal (car previous) (car current)) 3429 ((and bibtex-maintain-sorted-entries
3270 (push (list (bibtex-current-line) 3430 (not (bibtex-lessp previous current)))
3271 "Duplicate key with previous") 3431 (push (cons (bibtex-current-line)
3272 error-list)) 3432 "Entries out of order")
3273 (t 3433 error-list)))
3274 (setq previous current) 3434 (push key key-list)
3275 (push (list (bibtex-current-line) 3435 (setq previous current)))
3276 "Entries out of order") 3436 (bibtex-progress-message 'done))
3277 error-list))))) 3437
3278 (bibtex-progress-message 'done))) 3438 ;; Check for duplicate keys in `bibtex-files'.
3439 (bibtex-parse-keys)
3440 (dolist (buffer (bibtex-files-expand))
3441 (dolist (key (with-current-buffer buffer
3442 ;; We don't want to be fooled by outdated
3443 ;; bibtex-reference-keys.
3444 (bibtex-parse-keys) bibtex-reference-keys))
3445 (when (and (cdr key)
3446 (cdr (assoc-string (car key) bibtex-reference-keys)))
3447 (bibtex-find-entry (car key))
3448 (push (cons (bibtex-current-line)
3449 (format "Duplicate key `%s' in %s" (car key)
3450 (abbreviate-file-name (buffer-file-name buffer))))
3451 error-list))))
3279 3452
3280 (when test-thoroughly 3453 (when test-thoroughly
3281 (goto-char (point-min))
3282 (bibtex-progress-message 3454 (bibtex-progress-message
3283 "Checking required fields and month fields") 3455 "Checking required fields and month fields")
3284 (let ((bibtex-sort-ignore-string-entries t)) 3456 (let ((bibtex-sort-ignore-string-entries t))
@@ -3292,73 +3464,135 @@ Returns t if test was successful, nil otherwise."
3292 bibtex-entry-field-alist t))) 3464 bibtex-entry-field-alist t)))
3293 (req (copy-sequence (elt (elt entry-list 1) 0))) 3465 (req (copy-sequence (elt (elt entry-list 1) 0)))
3294 (creq (copy-sequence (elt (elt entry-list 2) 0))) 3466 (creq (copy-sequence (elt (elt entry-list 2) 0)))
3295 crossref-there bounds) 3467 crossref-there bounds alt-there field)
3296 (goto-char beg) 3468 (goto-char beg)
3297 (while (setq bounds (bibtex-search-forward-field 3469 (while (setq bounds (bibtex-search-forward-field
3298 bibtex-field-name end)) 3470 bibtex-field-name end))
3299 (goto-char (bibtex-start-of-text-in-field bounds)) 3471 (goto-char (bibtex-start-of-text-in-field bounds))
3300 (let ((field-name (bibtex-name-in-field bounds))) 3472 (let ((field-name (bibtex-name-in-field bounds)))
3301 (if (and (bibtex-string= field-name "month") 3473 (if (and (bibtex-string= field-name "month")
3302 (not (assoc-string (bibtex-text-in-field-bounds bounds) 3474 ;; Check only abbreviated month fields.
3303 bibtex-predefined-month-strings t))) 3475 (let ((month (bibtex-text-in-field-bounds bounds)))
3304 (push (list (bibtex-current-line) 3476 (not (or (string-match "\\`[\"{].+[\"}]\\'" month)
3477 (assoc-string
3478 month
3479 bibtex-predefined-month-strings t)))))
3480 (push (cons (bibtex-current-line)
3305 "Questionable month field") 3481 "Questionable month field")
3306 error-list)) 3482 error-list))
3307 (setq req (delete (assoc-string field-name req t) req) 3483 (setq field (assoc-string field-name req t))
3484 (if (nth 3 field)
3485 (if alt-there (push (cons (bibtex-current-line)
3486 "More than one non-empty alternative")
3487 error-list)
3488 (setq alt-there t)))
3489 (setq req (delete field req)
3308 creq (delete (assoc-string field-name creq t) creq)) 3490 creq (delete (assoc-string field-name creq t) creq))
3309 (if (bibtex-string= field-name "crossref") 3491 (if (bibtex-string= field-name "crossref")
3310 (setq crossref-there t)))) 3492 (setq crossref-there t))))
3311 (if crossref-there 3493 (if crossref-there
3312 (setq req creq)) 3494 (setq req creq))
3313 (if (or (> (length req) 1) 3495 (let (alt)
3314 (and (= (length req) 1) 3496 (dolist (field req)
3315 (not (elt (car req) 3)))) 3497 (if (nth 3 field)
3316 ;; two (or more) fields missed or one field 3498 (push (car field) alt)
3317 ;; missed and this isn't flagged alternative 3499 (push (cons (save-excursion (goto-char beg)
3318 ;; (notice that this fails if there are more 3500 (bibtex-current-line))
3319 ;; than two alternatives in a BibTeX entry, 3501 (format "Required field `%s' missing"
3320 ;; which isn't the case momentarily) 3502 (car field)))
3321 (push (list (save-excursion 3503 error-list)))
3322 (bibtex-beginning-of-entry) 3504 ;; The following fails if there are more than two
3323 (bibtex-current-line)) 3505 ;; alternatives in a BibTeX entry, which isn't
3324 (concat "Required field `" (caar req) "' missing")) 3506 ;; the case momentarily.
3325 error-list)))))) 3507 (if (cdr alt)
3508 (push (cons (save-excursion (goto-char beg)
3509 (bibtex-current-line))
3510 (format "Alternative fields `%s'/`%s' missing"
3511 (car alt) (cadr alt)))
3512 error-list)))))))
3326 (bibtex-progress-message 'done))))) 3513 (bibtex-progress-message 'done)))))
3514
3327 (if error-list 3515 (if error-list
3328 (let ((bufnam (buffer-name)) 3516 (let ((file (file-name-nondirectory (buffer-file-name)))
3329 (dir default-directory)) 3517 (dir default-directory)
3330 (setq error-list 3518 (err-buf "*BibTeX validation errors*"))
3331 (sort error-list 3519 (setq error-list (sort error-list 'car-less-than-car))
3332 (lambda (a b) 3520 (with-current-buffer (get-buffer-create err-buf)
3333 (< (car a) (car b))))) 3521 (setq default-directory dir)
3334 (let ((pop-up-windows t)) 3522 (unless (eq major-mode 'compilation-mode) (compilation-mode))
3335 (pop-to-buffer nil t)) 3523 (toggle-read-only -1)
3336 (switch-to-buffer 3524 (delete-region (point-min) (point-max))
3337 (get-buffer-create "*BibTeX validation errors*") t) 3525 (insert "BibTeX mode command `bibtex-validate'\n"
3338 ;; don't use switch-to-buffer-other-window, since this 3526 (if syntax-error
3339 ;; doesn't allow the second parameter NORECORD 3527 "Maybe undetected errors due to syntax errors. Correct and validate again.\n"
3340 (setq default-directory dir) 3528 "\n"))
3341 (toggle-read-only -1) 3529 (dolist (err error-list)
3342 (compilation-mode) 3530 (insert (format "%s:%d: %s\n" file (car err) (cdr err))))
3343 (delete-region (point-min) (point-max)) 3531 (set-buffer-modified-p nil)
3344 (goto-char (point-min)) 3532 (toggle-read-only 1)
3345 (insert "BibTeX mode command `bibtex-validate'\n" 3533 (goto-line 3)) ; first error message
3346 (if syntax-error 3534 (display-buffer err-buf)
3347 "Maybe undetected errors due to syntax errors. Correct and validate again." 3535 ;; return nil
3348 "") 3536 nil)
3349 "\n") 3537 (message "%s is syntactically correct"
3350 (dolist (err error-list) 3538 (if mark-active "Region" "Buffer"))
3351 (insert bufnam ":" (number-to-string (elt err 0)) 3539 t)))
3352 ": " (elt err 1) "\n")) 3540
3353 (set-buffer-modified-p nil) 3541(defun bibtex-validate-globally (&optional strings)
3354 (toggle-read-only 1) 3542 "Check for duplicate keys in `bibtex-files'.
3543With prefix arg STRINGS, check for duplicate strings, too.
3544Return t if test was successful, nil otherwise."
3545 (interactive "P")
3546 (let ((buffer-list (bibtex-files-expand t))
3547 buffer-key-list current-buf current-keys error-list)
3548 ;; Check for duplicate keys within BibTeX buffer
3549 (dolist (buffer buffer-list)
3550 (save-excursion
3551 (set-buffer buffer)
3552 (let (entry-type key key-list)
3355 (goto-char (point-min)) 3553 (goto-char (point-min))
3356 (other-window -1) 3554 (while (re-search-forward bibtex-entry-head nil t)
3555 (setq entry-type (bibtex-type-in-head)
3556 key (bibtex-key-in-head))
3557 (if (or (and strings (bibtex-string= entry-type "string"))
3558 (assoc-string entry-type bibtex-entry-field-alist t))
3559 (if (member key key-list)
3560 (push (format "%s:%d: Duplicate key `%s'\n"
3561 (buffer-file-name)
3562 (bibtex-current-line) key)
3563 error-list)
3564 (push key key-list))))
3565 (push (cons buffer key-list) buffer-key-list))))
3566
3567 ;; Check for duplicate keys among BibTeX buffers
3568 (while (setq current-buf (pop buffer-list))
3569 (setq current-keys (cdr (assq current-buf buffer-key-list)))
3570 (with-current-buffer current-buf
3571 (dolist (buffer buffer-list)
3572 (dolist (key (cdr (assq buffer buffer-key-list)))
3573 (when (assoc-string key current-keys)
3574 (bibtex-find-entry key)
3575 (push (format "%s:%d: Duplicat key `%s' in %s\n"
3576 (buffer-file-name) (bibtex-current-line) key
3577 (abbreviate-file-name (buffer-file-name buffer)))
3578 error-list))))))
3579
3580 ;; Process error list
3581 (if error-list
3582 (let ((err-buf "*BibTeX validation errors*"))
3583 (with-current-buffer (get-buffer-create err-buf)
3584 (unless (eq major-mode 'compilation-mode) (compilation-mode))
3585 (toggle-read-only -1)
3586 (delete-region (point-min) (point-max))
3587 (insert "BibTeX mode command `bibtex-validate-globally'\n\n")
3588 (dolist (err (sort error-list 'string-lessp)) (insert err))
3589 (set-buffer-modified-p nil)
3590 (toggle-read-only 1)
3591 (goto-line 3)) ; first error message
3592 (display-buffer err-buf)
3357 ;; return nil 3593 ;; return nil
3358 nil) 3594 nil)
3359 (if (bibtex-mark-active) 3595 (message "No duplicate keys.")
3360 (message "Region is syntactically correct")
3361 (message "Buffer is syntactically correct"))
3362 t))) 3596 t)))
3363 3597
3364(defun bibtex-next-field (arg) 3598(defun bibtex-next-field (arg)
@@ -3378,10 +3612,9 @@ Returns t if test was successful, nil otherwise."
3378 3612
3379(defun bibtex-find-text (arg &optional as-if-interactive no-error) 3613(defun bibtex-find-text (arg &optional as-if-interactive no-error)
3380 "Go to end of text of current field; with ARG, go to beginning." 3614 "Go to end of text of current field; with ARG, go to beginning."
3381 (interactive "P") 3615 (interactive "P\np")
3382 (bibtex-inside-field) 3616 (bibtex-inside-field)
3383 (let ((bounds (bibtex-enclosing-field (or (interactive-p) 3617 (let ((bounds (bibtex-enclosing-field as-if-interactive)))
3384 as-if-interactive))))
3385 (if bounds 3618 (if bounds
3386 (progn (if arg 3619 (progn (if arg
3387 (progn (goto-char (bibtex-start-of-text-in-field bounds)) 3620 (progn (goto-char (bibtex-start-of-text-in-field bounds))
@@ -3404,7 +3637,7 @@ Returns t if test was successful, nil otherwise."
3404 (match-end 0)))) 3637 (match-end 0))))
3405 (t 3638 (t
3406 (unless no-error 3639 (unless no-error
3407 (error "Not on BibTeX field"))))))) 3640 (error "Not on BibTeX field")))))))
3408 3641
3409(defun bibtex-remove-OPT-or-ALT () 3642(defun bibtex-remove-OPT-or-ALT ()
3410 "Remove the string starting optional/alternative fields. 3643 "Remove the string starting optional/alternative fields.
@@ -3470,6 +3703,7 @@ but do not actually kill it."
3470 (setq bibtex-last-kill-command 'field)) 3703 (setq bibtex-last-kill-command 'field))
3471 3704
3472(defun bibtex-copy-field-as-kill () 3705(defun bibtex-copy-field-as-kill ()
3706 "Copy the field at point to the kill ring."
3473 (interactive) 3707 (interactive)
3474 (bibtex-kill-field t)) 3708 (bibtex-kill-field t))
3475 3709
@@ -3492,9 +3726,9 @@ With prefix arg COPY-ONLY the current entry to
3492 (setcdr (nthcdr (1- bibtex-entry-kill-ring-max) 3726 (setcdr (nthcdr (1- bibtex-entry-kill-ring-max)
3493 bibtex-entry-kill-ring) 3727 bibtex-entry-kill-ring)
3494 nil)) 3728 nil))
3495 (setq bibtex-entry-kill-ring-yank-pointer bibtex-entry-kill-ring) 3729 (setq bibtex-entry-kill-ring-yank-pointer bibtex-entry-kill-ring)
3496 (unless copy-only 3730 (unless copy-only
3497 (delete-region beg end)))) 3731 (delete-region beg end))))
3498 (setq bibtex-last-kill-command 'entry)) 3732 (setq bibtex-last-kill-command 'entry))
3499 3733
3500(defun bibtex-copy-entry-as-kill () 3734(defun bibtex-copy-entry-as-kill ()
@@ -3584,7 +3818,7 @@ At end of the cleaning process, the functions in
3584 ;; (bibtex-format-preamble) 3818 ;; (bibtex-format-preamble)
3585 (error "No clean up of @Preamble entries")) 3819 (error "No clean up of @Preamble entries"))
3586 ((bibtex-string= entry-type "string")) 3820 ((bibtex-string= entry-type "string"))
3587 ;; (bibtex-format-string) 3821 ;; (bibtex-format-string)
3588 (t (bibtex-format-entry))) 3822 (t (bibtex-format-entry)))
3589 ;; set key 3823 ;; set key
3590 (when (or new-key (not key)) 3824 (when (or new-key (not key))
@@ -3597,7 +3831,7 @@ At end of the cleaning process, the functions in
3597 (delete-region (match-beginning bibtex-key-in-head) 3831 (delete-region (match-beginning bibtex-key-in-head)
3598 (match-end bibtex-key-in-head))) 3832 (match-end bibtex-key-in-head)))
3599 (insert key)) 3833 (insert key))
3600 ;; sorting 3834
3601 (unless called-by-reformat 3835 (unless called-by-reformat
3602 (let* ((start (bibtex-beginning-of-entry)) 3836 (let* ((start (bibtex-beginning-of-entry))
3603 (end (progn (bibtex-end-of-entry) 3837 (end (progn (bibtex-end-of-entry)
@@ -3606,9 +3840,12 @@ At end of the cleaning process, the functions in
3606 (goto-char (match-beginning 0))) 3840 (goto-char (match-beginning 0)))
3607 (point))) 3841 (point)))
3608 (entry (buffer-substring start end)) 3842 (entry (buffer-substring start end))
3609 (index (progn (goto-char start) 3843 ;; include the crossref key in index
3610 (bibtex-entry-index))) 3844 (index (let ((bibtex-maintain-sorted-entries 'crossref))
3845 (goto-char start)
3846 (bibtex-entry-index)))
3611 error) 3847 error)
3848 ;; sorting
3612 (if (and bibtex-maintain-sorted-entries 3849 (if (and bibtex-maintain-sorted-entries
3613 (not (and bibtex-sort-ignore-string-entries 3850 (not (and bibtex-sort-ignore-string-entries
3614 (bibtex-string= entry-type "string")))) 3851 (bibtex-string= entry-type "string"))))
@@ -3623,17 +3860,37 @@ At end of the cleaning process, the functions in
3623 (setq error (or (/= (point) start) 3860 (setq error (or (/= (point) start)
3624 (bibtex-find-entry key end)))) 3861 (bibtex-find-entry key end))))
3625 (if error 3862 (if error
3626 (error "New inserted entry yields duplicate key")))) 3863 (error "New inserted entry yields duplicate key"))
3627 ;; final clean up 3864 (dolist (buffer (bibtex-files-expand))
3628 (unless called-by-reformat 3865 (with-current-buffer buffer
3629 (save-excursion 3866 (if (cdr (assoc-string key bibtex-reference-keys))
3630 (save-restriction 3867 (error "Duplicate key in %s" (buffer-file-name)))))
3631 (bibtex-narrow-to-entry) 3868
3632 ;; Only update the list of keys if it has been built already. 3869 ;; Only update the list of keys if it has been built already.
3633 (cond ((bibtex-string= entry-type "string") 3870 (cond ((bibtex-string= entry-type "string")
3634 (if (listp bibtex-strings) (bibtex-parse-strings t))) 3871 (if (and (listp bibtex-strings)
3635 ((listp bibtex-reference-keys) (bibtex-parse-keys t))) 3872 (not (assoc key bibtex-strings)))
3636 (run-hooks 'bibtex-clean-entry-hook)))))) 3873 (push (list key) bibtex-strings)))
3874 ;; We have a normal entry.
3875 ((listp bibtex-reference-keys)
3876 (cond ((not (assoc key bibtex-reference-keys))
3877 (push (cons key t) bibtex-reference-keys))
3878 ((not (cdr (assoc key bibtex-reference-keys)))
3879 ;; Turn a crossref key into a header key
3880 (setq bibtex-reference-keys
3881 (cons (cons key t)
3882 (delete (list key) bibtex-reference-keys)))))
3883 ;; Handle crossref key.
3884 (if (and (nth 1 index)
3885 (not (assoc (nth 1 index) bibtex-reference-keys)))
3886 (push (list (nth 1 index)) bibtex-reference-keys)))))
3887
3888 ;; final clean up
3889 (if bibtex-clean-entry-hook
3890 (save-excursion
3891 (save-restriction
3892 (bibtex-narrow-to-entry)
3893 (run-hooks 'bibtex-clean-entry-hook)))))))
3637 3894
3638(defun bibtex-fill-field-bounds (bounds justify &optional move) 3895(defun bibtex-fill-field-bounds (bounds justify &optional move)
3639 "Fill BibTeX field delimited by BOUNDS. 3896 "Fill BibTeX field delimited by BOUNDS.
@@ -3705,13 +3962,24 @@ If `bibtex-align-at-equal-sign' is non-nil, align equal signs, too."
3705 "Realign BibTeX entries such that they are separated by one blank line." 3962 "Realign BibTeX entries such that they are separated by one blank line."
3706 (goto-char (point-min)) 3963 (goto-char (point-min))
3707 (let ((case-fold-search t)) 3964 (let ((case-fold-search t))
3965 ;; No blank lines prior to the first valid entry if there no
3966 ;; non-white characters in front of it.
3708 (when (looking-at bibtex-valid-entry-whitespace-re) 3967 (when (looking-at bibtex-valid-entry-whitespace-re)
3709 (replace-match "\\1")) 3968 (replace-match "\\1"))
3969 ;; Valid entries are separated by one blank line.
3710 (while (re-search-forward bibtex-valid-entry-whitespace-re nil t) 3970 (while (re-search-forward bibtex-valid-entry-whitespace-re nil t)
3711 (replace-match "\n\n\\1")))) 3971 (replace-match "\n\n\\1"))
3972 ;; One blank line past the last valid entry if it is followed by
3973 ;; non-white characters, no blank line otherwise.
3974 (beginning-of-line)
3975 (when (re-search-forward bibtex-valid-entry-re nil t)
3976 (bibtex-end-of-entry)
3977 (bibtex-delete-whitespace)
3978 (open-line (if (eobp) 1 2)))))
3712 3979
3713(defun bibtex-reformat (&optional read-options) 3980(defun bibtex-reformat (&optional read-options)
3714 "Reformat all BibTeX entries in buffer or region. 3981 "Reformat all BibTeX entries in buffer or region.
3982Without prefix argument, reformatting is based on `bibtex-entry-format'.
3715With prefix argument, read options for reformatting from minibuffer. 3983With prefix argument, read options for reformatting from minibuffer.
3716With \\[universal-argument] \\[universal-argument] prefix argument, reuse previous answers (if any) again. 3984With \\[universal-argument] \\[universal-argument] prefix argument, reuse previous answers (if any) again.
3717If mark is active reformat entries in region, if not in whole buffer." 3985If mark is active reformat entries in region, if not in whole buffer."
@@ -3722,55 +3990,54 @@ If mark is active reformat entries in region, if not in whole buffer."
3722 (or bibtex-reformat-previous-options 3990 (or bibtex-reformat-previous-options
3723 bibtex-reformat-previous-reference-keys))) 3991 bibtex-reformat-previous-reference-keys)))
3724 (bibtex-entry-format 3992 (bibtex-entry-format
3725 (if read-options 3993 (cond (read-options
3726 (if use-previous-options 3994 (if use-previous-options
3727 bibtex-reformat-previous-options 3995 bibtex-reformat-previous-options
3728 (setq bibtex-reformat-previous-options 3996 (setq bibtex-reformat-previous-options
3729 (mapcar (lambda (option) 3997 (mapcar (lambda (option)
3730 (if (y-or-n-p (car option)) (cdr option))) 3998 (if (y-or-n-p (car option)) (cdr option)))
3731 `(("Realign entries (recommended)? " . 'realign) 3999 `(("Realign entries (recommended)? " . 'realign)
3732 ("Remove empty optional and alternative fields? " . 'opts-or-alts) 4000 ("Remove empty optional and alternative fields? " . 'opts-or-alts)
3733 ("Remove delimiters around pure numerical fields? " . 'numerical-fields) 4001 ("Remove delimiters around pure numerical fields? " . 'numerical-fields)
3734 (,(concat (if bibtex-comma-after-last-field "Insert" "Remove") 4002 (,(concat (if bibtex-comma-after-last-field "Insert" "Remove")
3735 " comma at end of entry? ") . 'last-comma) 4003 " comma at end of entry? ") . 'last-comma)
3736 ("Replace double page dashes by single ones? " . 'page-dashes) 4004 ("Replace double page dashes by single ones? " . 'page-dashes)
3737 ("Force delimiters? " . 'delimiters) 4005 ("Inherit booktitle? " . 'inherit-booktitle)
3738 ("Unify case of entry types and field names? " . 'unify-case))))) 4006 ("Force delimiters? " . 'delimiters)
3739 '(realign))) 4007 ("Unify case of entry types and field names? " . 'unify-case))))))
4008 ;; Do not include required-fields because `bibtex-reformat'
4009 ;; cannot handle the error messages of `bibtex-format-entry'.
4010 ;; Use `bibtex-validate' to check for required fields.
4011 ((eq t bibtex-entry-format)
4012 '(realign opts-or-alts numerical-fields delimiters
4013 last-comma page-dashes unify-case inherit-booktitle))
4014 (t
4015 (remove 'required-fields (push 'realign bibtex-entry-format)))))
3740 (reformat-reference-keys 4016 (reformat-reference-keys
3741 (if read-options 4017 (if read-options
3742 (if use-previous-options 4018 (if use-previous-options
3743 bibtex-reformat-previous-reference-keys 4019 bibtex-reformat-previous-reference-keys
3744 (setq bibtex-reformat-previous-reference-keys 4020 (setq bibtex-reformat-previous-reference-keys
3745 (y-or-n-p "Generate new reference keys automatically? "))))) 4021 (y-or-n-p "Generate new reference keys automatically? ")))))
3746 (start-point (if (bibtex-mark-active)
3747 (region-beginning)
3748 (point-min)))
3749 (end-point (if (bibtex-mark-active)
3750 (region-end)
3751 (point-max)))
3752 (bibtex-sort-ignore-string-entries t) 4022 (bibtex-sort-ignore-string-entries t)
3753 bibtex-autokey-edit-before-use) 4023 bibtex-autokey-edit-before-use)
3754 4024
3755 (save-restriction 4025 (save-restriction
3756 (narrow-to-region start-point end-point) 4026 (narrow-to-region (if mark-active (region-beginning) (point-min))
4027 (if mark-active (region-end) (point-max)))
3757 (if (memq 'realign bibtex-entry-format) 4028 (if (memq 'realign bibtex-entry-format)
3758 (bibtex-realign)) 4029 (bibtex-realign))
3759 (goto-char start-point)
3760 (bibtex-progress-message "Formatting" 1) 4030 (bibtex-progress-message "Formatting" 1)
3761 (bibtex-map-entries (lambda (key beg end) 4031 (bibtex-map-entries (lambda (key beg end)
3762 (bibtex-progress-message) 4032 (bibtex-progress-message)
3763 (bibtex-clean-entry reformat-reference-keys t))) 4033 (bibtex-clean-entry reformat-reference-keys t)))
3764 (when (memq 'realign bibtex-entry-format)
3765 (bibtex-delete-whitespace)
3766 (open-line (if (eobp) 1 2)))
3767 (bibtex-progress-message 'done)) 4034 (bibtex-progress-message 'done))
3768 (when (and reformat-reference-keys 4035 (when reformat-reference-keys
3769 bibtex-maintain-sorted-entries)
3770 (bibtex-progress-message "Sorting" 1)
3771 (bibtex-sort-buffer)
3772 (kill-local-variable 'bibtex-reference-keys) 4036 (kill-local-variable 'bibtex-reference-keys)
3773 (bibtex-progress-message 'done)) 4037 (when bibtex-maintain-sorted-entries
4038 (bibtex-progress-message "Sorting" 1)
4039 (bibtex-sort-buffer)
4040 (bibtex-progress-message 'done)))
3774 (goto-char pnt))) 4041 (goto-char pnt)))
3775 4042
3776(defun bibtex-convert-alien (&optional read-options) 4043(defun bibtex-convert-alien (&optional read-options)
@@ -3837,21 +4104,23 @@ signaled if point is outside key or BibTeX field."
3837 ;; key completion 4104 ;; key completion
3838 (setq choose-completion-string-functions 4105 (setq choose-completion-string-functions
3839 (lambda (choice buffer mini-p base-size) 4106 (lambda (choice buffer mini-p base-size)
3840 (bibtex-choose-completion-string choice buffer mini-p base-size) 4107 (let ((choose-completion-string-functions nil))
4108 (choose-completion-string choice buffer base-size))
3841 (bibtex-complete-key-cleanup choice) 4109 (bibtex-complete-key-cleanup choice)
3842 ;; return t (required by choose-completion-string-functions) 4110 ;; return t (required by choose-completion-string-functions)
3843 t)) 4111 t))
3844 (bibtex-complete-key-cleanup (bibtex-complete-internal 4112 (bibtex-complete-key-cleanup (bibtex-complete-internal
3845 bibtex-reference-keys))) 4113 bibtex-reference-keys)))
3846 4114
3847 (compl 4115 (compl
3848 ;; string completion 4116 ;; string completion
3849 (setq choose-completion-string-functions 4117 (setq choose-completion-string-functions
3850 `(lambda (choice buffer mini-p base-size) 4118 `(lambda (choice buffer mini-p base-size)
3851 (bibtex-choose-completion-string choice buffer mini-p base-size) 4119 (let ((choose-completion-string-functions nil))
3852 (bibtex-complete-string-cleanup choice ',compl) 4120 (choose-completion-string choice buffer base-size))
3853 ;; return t (required by choose-completion-string-functions) 4121 (bibtex-complete-string-cleanup choice ',compl)
3854 t)) 4122 ;; return t (required by choose-completion-string-functions)
4123 t))
3855 (bibtex-complete-string-cleanup (bibtex-complete-internal compl) 4124 (bibtex-complete-string-cleanup (bibtex-complete-internal compl)
3856 compl)) 4125 compl))
3857 4126
@@ -3960,80 +4229,56 @@ signaled if point is outside key or BibTeX field."
3960 "\n") 4229 "\n")
3961 (goto-char endpos))) 4230 (goto-char endpos)))
3962 4231
3963(defun bibtex-url (&optional event) 4232(defun bibtex-url (&optional pos)
3964 "Browse a URL for the BibTeX entry at position PNT. 4233 "Browse a URL for the BibTeX entry at point.
4234Optional POS is the location of the BibTeX entry.
3965The URL is generated using the schemes defined in `bibtex-generate-url-list' 4235The URL is generated using the schemes defined in `bibtex-generate-url-list'
3966\(see there\). Then the URL is passed to `browse-url'." 4236\(see there\). Then the URL is passed to `browse-url'."
3967 (interactive (list last-input-event)) 4237 (interactive)
3968 (save-excursion 4238 (save-excursion
3969 (if event (posn-set-point (event-end event))) 4239 (if pos (goto-char pos))
3970 (bibtex-beginning-of-entry) 4240 (bibtex-beginning-of-entry)
3971 (let ((fields-alist (bibtex-parse-entry)) 4241 (let ((fields-alist (bibtex-parse-entry))
4242 ;; Always ignore case,
3972 (case-fold-search t) 4243 (case-fold-search t)
3973 (lst bibtex-generate-url-list) 4244 (lst bibtex-generate-url-list)
4245 (delim-regexp "\\`[{\"]\\(.*\\)[}\"]\\'")
3974 field url scheme) 4246 field url scheme)
3975 (while (setq scheme (car lst)) 4247 (while (setq scheme (pop lst))
3976 (when (and (setq field (cdr (assoc-string (caar scheme) 4248 (when (and (setq field (cdr (assoc-string (caar scheme)
3977 fields-alist t))) 4249 fields-alist t)))
3978 (progn 4250 ;; Always remove field delimiters
3979 (if (string-match "\\`[{\"]\\(.*\\)[}\"]\\'" field) 4251 (progn (if (string-match delim-regexp field)
3980 (setq field (match-string 1 field))) 4252 (setq field (match-string 1 field)))
3981 (string-match (cdar scheme) field))) 4253 (string-match (cdar scheme) field)))
3982 (setq lst nil) 4254 (setq lst nil)
3983 (if (null (cdr scheme)) 4255 (if (null (cdr scheme))
3984 (setq url (match-string 0 field))) 4256 (setq url (match-string 0 field)))
3985 (dolist (step (cdr scheme)) 4257 (dolist (step (cdr scheme))
3986 (cond ((stringp step) 4258 (cond ((stringp step)
3987 (setq url (concat url step))) 4259 (setq url (concat url step)))
3988 ((setq field (assoc-string (car step) fields-alist t)) 4260 ((setq field (cdr (assoc-string (car step) fields-alist t)))
3989 ;; always remove field delimiters 4261 ;; Always remove field delimiters
3990 (let* ((text (if (string-match "\\`[{\"]\\(.*\\)[}\"]\\'" 4262 (if (string-match delim-regexp field)
3991 (cdr field)) 4263 (setq field (match-string 1 field)))
3992 (match-string 1 (cdr field)) 4264 (if (string-match (nth 1 step) field)
3993 (cdr field))) 4265 (setq field (cond
3994 (str (if (string-match (nth 1 step) text) 4266 ((functionp (nth 2 step))
3995 (cond 4267 (funcall (nth 2 step) field))
3996 ((functionp (nth 2 step)) 4268 ((numberp (nth 2 step))
3997 (funcall (nth 2 step) text)) 4269 (match-string (nth 2 step) field))
3998 ((numberp (nth 2 step)) 4270 (t
3999 (match-string (nth 2 step) text)) 4271 (replace-match (nth 2 step) nil nil field))))
4000 (t 4272 ;; If the scheme is set up correctly,
4001 (replace-match (nth 2 step) nil nil text))) 4273 ;; we should never reach this point
4002 ;; If the scheme is set up correctly, 4274 (error "Match failed: %s" field))
4003 ;; we should never reach this point 4275 (setq url (concat url field)))
4004 (error "Match failed: %s" text)))) 4276 ;; If the scheme is set up correctly,
4005 (setq url (concat url str)))) 4277 ;; we should never reach this point
4006 ;; If the scheme is set up correctly, 4278 (t (error "Step failed: %s" step))))
4007 ;; we should never reach this point 4279 (message "%s" url)
4008 (t (error "Step failed: %s" step)))) 4280 (browse-url url)))
4009 (message "%s" url) 4281 (unless url (message "No URL known.")))))
4010 (browse-url url))
4011 (setq lst (cdr lst)))
4012 (unless url (message "No URL known.")))))
4013
4014(defun bibtex-font-lock-url (bound)
4015 "Font-lock for URLs."
4016 (let ((case-fold-search t)
4017 (bounds (bibtex-enclosing-field t))
4018 (pnt (point))
4019 found field)
4020 ;; We use start-of-field as syntax-begin
4021 (goto-char (if bounds (bibtex-start-of-field bounds) pnt))
4022 (while (and (not found)
4023 (prog1 (re-search-forward bibtex-font-lock-url-regexp bound t)
4024 (setq field (match-string-no-properties 1)))
4025 (setq bounds (bibtex-parse-field-text))
4026 (>= bound (car bounds))
4027 (>= (car bounds) pnt))
4028 (let ((lst bibtex-generate-url-list) url)
4029 (goto-char (car bounds))
4030 (while (and (not found)
4031 (setq url (caar lst)))
4032 (when (bibtex-string= field (car url))
4033 (setq found (re-search-forward (cdr url) (cdr bounds) t)))
4034 (setq lst (cdr lst))))
4035 (goto-char (cdr bounds)))
4036 found))
4037 4282
4038 4283
4039;; Make BibTeX a Feature 4284;; Make BibTeX a Feature
diff --git a/lisp/textmodes/flyspell.el b/lisp/textmodes/flyspell.el
index 93a7ebd52e4..556369077d8 100644
--- a/lisp/textmodes/flyspell.el
+++ b/lisp/textmodes/flyspell.el
@@ -956,9 +956,7 @@ Mostly we check word delimiters."
956;*---------------------------------------------------------------------*/ 956;*---------------------------------------------------------------------*/
957(defun flyspell-word (&optional following) 957(defun flyspell-word (&optional following)
958 "Spell check a word." 958 "Spell check a word."
959 (interactive (list current-prefix-arg)) 959 (interactive (list ispell-following-word))
960 (if (interactive-p)
961 (setq following ispell-following-word))
962 (save-excursion 960 (save-excursion
963 ;; use the correct dictionary 961 ;; use the correct dictionary
964 (flyspell-accept-buffer-local-defs) 962 (flyspell-accept-buffer-local-defs)
diff --git a/lisp/textmodes/ispell.el b/lisp/textmodes/ispell.el
index f0547d6d596..d221d39180f 100644
--- a/lisp/textmodes/ispell.el
+++ b/lisp/textmodes/ispell.el
@@ -1410,12 +1410,9 @@ nil word is correct or spelling is accepted.
1410\(\"word\" arg\) word is hand entered. 1410\(\"word\" arg\) word is hand entered.
1411quit spell session exited." 1411quit spell session exited."
1412 1412
1413 (interactive (list nil nil current-prefix-arg)) 1413 (interactive (list ispell-following-word ispell-quietly current-prefix-arg))
1414 (if continue 1414 (if continue
1415 (ispell-continue) 1415 (ispell-continue)
1416 (if (interactive-p)
1417 (setq following ispell-following-word
1418 quietly ispell-quietly))
1419 (ispell-accept-buffer-local-defs) ; use the correct dictionary 1416 (ispell-accept-buffer-local-defs) ; use the correct dictionary
1420 (let ((cursor-location (point)) ; retain cursor location 1417 (let ((cursor-location (point)) ; retain cursor location
1421 (word (ispell-get-word following)) 1418 (word (ispell-get-word following))
diff --git a/lisp/textmodes/table.el b/lisp/textmodes/table.el
index 7b13d498b2e..f064dd4dee0 100644
--- a/lisp/textmodes/table.el
+++ b/lisp/textmodes/table.el
@@ -645,7 +645,8 @@ See `table-insert' for examples about how to use."
645 :group 'editing 645 :group 'editing
646 :group 'wp 646 :group 'wp
647 :group 'paragraphs 647 :group 'paragraphs
648 :group 'fill) 648 :group 'fill
649 :version "21.4")
649 650
650(defgroup table-hooks nil 651(defgroup table-hooks nil
651 "Hooks for table manipulation utilities" 652 "Hooks for table manipulation utilities"
diff --git a/lisp/textmodes/texinfo.el b/lisp/textmodes/texinfo.el
index 8e5b94114a3..54c9d6ad7db 100644
--- a/lisp/textmodes/texinfo.el
+++ b/lisp/textmodes/texinfo.el
@@ -1,7 +1,7 @@
1;;; texinfo.el --- major mode for editing Texinfo files 1;;; texinfo.el --- major mode for editing Texinfo files
2 2
3;; Copyright (C) 1985,88,89,90,91,92,93,96,97,2000,01,03,04 3;; Copyright (C) 1985, 1988, 1989, 1990, 1991, 1992, 1993, 1996, 1997,
4;; Free Software Foundation, Inc. 4;; 2000, 2001, 2003, 2004 Free Software Foundation, Inc.
5 5
6;; Author: Robert J. Chassell 6;; Author: Robert J. Chassell
7;; Date: [See date below for texinfo-version] 7;; Date: [See date below for texinfo-version]