diff options
| author | Stefan Monnier | 2004-05-03 23:04:55 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2004-05-03 23:04:55 +0000 |
| commit | 8bf38a9bfef78cbfe65762db736188cfaa99dbd7 (patch) | |
| tree | 4bf2fc4b6f73e4fb294467c0ee371aff2043fa95 | |
| parent | e0db3d3f0048af8557090bc93d75bcfd43774bbc (diff) | |
| download | emacs-8bf38a9bfef78cbfe65762db736188cfaa99dbd7.tar.gz emacs-8bf38a9bfef78cbfe65762db736188cfaa99dbd7.zip | |
(bibtex-progress-message): Fix docstring.
(bibtex-entry-update): New command bound to C-c C-u.
(bibtex-text-in-string): Fix regexp.
(bibtex-assoc-of-regexp): Remove.
(bibtex-progress-message): Fix docstring.
(bibtex-inside-field): Use if.
(bibtex-assoc-regexp): New function.
(bibtex-format-entry): Make code more robust so it formats also old entries.
(bibtex-autokey-demangle-title): Merge with obsolete function
bibtex-assoc-of-regexp.
(bibtex-field-list): New function.
(bibtex-entry): Use bibtex-field-list.
(bibtex-parse-entry): Fix docstring.
(bibtex-print-help-message): Use bibtex-field-list.
(bibtex-make-field): Use bibtex-field-list.
(bibtex-entry-index): Bugfix. Return crossref key if required.
(bibtex-lessp): Fix docstring.
| -rw-r--r-- | lisp/ChangeLog | 30 | ||||
| -rw-r--r-- | lisp/textmodes/bibtex.el | 367 |
2 files changed, 220 insertions, 177 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index bc05f864677..157b5416eaa 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,7 +1,27 @@ | |||
| 1 | 2004-05-03 Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> | ||
| 2 | |||
| 3 | * textmodes/bibtex.el (bibtex-progress-message): Fix docstring. | ||
| 4 | (bibtex-entry-update): New command bound to C-c C-u. | ||
| 5 | (bibtex-text-in-string): Fix regexp. | ||
| 6 | (bibtex-assoc-of-regexp): Remove. | ||
| 7 | (bibtex-progress-message): Fix docstring. | ||
| 8 | (bibtex-inside-field): Use if. | ||
| 9 | (bibtex-assoc-regexp): New function. | ||
| 10 | (bibtex-format-entry): Make code more robust so that it formats | ||
| 11 | also old entries. | ||
| 12 | (bibtex-autokey-demangle-title): Merge with obsolete function | ||
| 13 | bibtex-assoc-of-regexp. | ||
| 14 | (bibtex-field-list): New function. | ||
| 15 | (bibtex-entry): Use bibtex-field-list. | ||
| 16 | (bibtex-parse-entry): Fix docstring. | ||
| 17 | (bibtex-print-help-message): Use bibtex-field-list. | ||
| 18 | (bibtex-make-field): Use bibtex-field-list. | ||
| 19 | (bibtex-entry-index): Bugfix. Return crossref key if required. | ||
| 20 | (bibtex-lessp): Fix docstring. | ||
| 21 | |||
| 1 | 2004-05-03 Luc Teirlinck <teirllm@auburn.edu> | 22 | 2004-05-03 Luc Teirlinck <teirllm@auburn.edu> |
| 2 | 23 | ||
| 3 | * select.el (xselect-convert-to-string): Move comment to intended | 24 | * select.el (xselect-convert-to-string): Move comment to intended line. |
| 4 | line. | ||
| 5 | 25 | ||
| 6 | 2004-05-03 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> | 26 | 2004-05-03 Jan Dj,Ad(Brv <jan.h.d@swipnet.se> |
| 7 | 27 | ||
| @@ -19,14 +39,12 @@ | |||
| 19 | 39 | ||
| 20 | 2004-05-03 Kim F. Storm <storm@cua.dk> | 40 | 2004-05-03 Kim F. Storm <storm@cua.dk> |
| 21 | 41 | ||
| 22 | * emulation/cua-base.el (cua--update-indications): | 42 | * emulation/cua-base.el (cua--update-indications): Fix last change. |
| 23 | Fix last change. | ||
| 24 | (cua-mode): Deactivate mark when cua-mode is enabled. | 43 | (cua-mode): Deactivate mark when cua-mode is enabled. |
| 25 | 44 | ||
| 26 | 2004-05-02 Luc Teirlinck <teirllm@auburn.edu> | 45 | 2004-05-02 Luc Teirlinck <teirllm@auburn.edu> |
| 27 | 46 | ||
| 28 | * select.el (xselect-convert-to-string): Bind `inhibit-read-only' | 47 | * select.el (xselect-convert-to-string): Bind `inhibit-read-only' to t. |
| 29 | to t. | ||
| 30 | 48 | ||
| 31 | 2004-05-03 Nick Roberts <nickrob@gnu.org> | 49 | 2004-05-03 Nick Roberts <nickrob@gnu.org> |
| 32 | 50 | ||
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el index 1926661bbab..5c95b138720 100644 --- a/lisp/textmodes/bibtex.el +++ b/lisp/textmodes/bibtex.el | |||
| @@ -1,6 +1,7 @@ | |||
| 1 | ;;; bibtex.el --- BibTeX mode for GNU Emacs | 1 | ;;; bibtex.el --- BibTeX mode for GNU Emacs |
| 2 | 2 | ||
| 3 | ;; Copyright (C) 1992,94,95,96,97,98,1999,2003 Free Software Foundation, Inc. | 3 | ;; Copyright (C) 1992,94,95,96,97,98,1999,2003,2004 |
| 4 | ;; Free Software Foundation, Inc. | ||
| 4 | 5 | ||
| 5 | ;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de> | 6 | ;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de> |
| 6 | ;; Bengt Martensson <bengt@mathematik.uni-Bremen.de> | 7 | ;; Bengt Martensson <bengt@mathematik.uni-Bremen.de> |
| @@ -811,6 +812,7 @@ If non-nil, the column for the equal sign is the value of | |||
| 811 | (define-key km "\C-c\M-y" 'bibtex-yank-pop) | 812 | (define-key km "\C-c\M-y" 'bibtex-yank-pop) |
| 812 | (define-key km "\C-c\C-d" 'bibtex-empty-field) | 813 | (define-key km "\C-c\C-d" 'bibtex-empty-field) |
| 813 | (define-key km "\C-c\C-f" 'bibtex-make-field) | 814 | (define-key km "\C-c\C-f" 'bibtex-make-field) |
| 815 | (define-key km "\C-c\C-u" 'bibtex-entry-update) | ||
| 814 | (define-key km "\C-c$" 'bibtex-ispell-abstract) | 816 | (define-key km "\C-c$" 'bibtex-ispell-abstract) |
| 815 | (define-key km "\M-\C-a" 'bibtex-beginning-of-entry) | 817 | (define-key km "\M-\C-a" 'bibtex-beginning-of-entry) |
| 816 | (define-key km "\M-\C-e" 'bibtex-end-of-entry) | 818 | (define-key km "\M-\C-e" 'bibtex-end-of-entry) |
| @@ -1122,44 +1124,6 @@ function `bibtex-parse-field-name'.") | |||
| 1122 | '(bibtex-mode "@\\S(*\\s(" "\\s)" nil bibtex-hs-forward-sexp nil)) | 1124 | '(bibtex-mode "@\\S(*\\s(" "\\s)" nil bibtex-hs-forward-sexp nil)) |
| 1123 | 1125 | ||
| 1124 | 1126 | ||
| 1125 | (defconst bibtex-braced-string-syntax-table | ||
| 1126 | (let ((st (make-syntax-table))) | ||
| 1127 | (modify-syntax-entry ?\{ "(}" st) | ||
| 1128 | (modify-syntax-entry ?\} "){" st) | ||
| 1129 | (modify-syntax-entry ?\[ "." st) | ||
| 1130 | (modify-syntax-entry ?\] "." st) | ||
| 1131 | (modify-syntax-entry ?\( "." st) | ||
| 1132 | (modify-syntax-entry ?\) "." st) | ||
| 1133 | (modify-syntax-entry ?\\ "." st) | ||
| 1134 | (modify-syntax-entry ?\" "." st) | ||
| 1135 | st) | ||
| 1136 | "Syntax-table to parse matched braces.") | ||
| 1137 | |||
| 1138 | (defconst bibtex-quoted-string-syntax-table | ||
| 1139 | (let ((st (make-syntax-table))) | ||
| 1140 | (modify-syntax-entry ?\\ "\\" st) | ||
| 1141 | (modify-syntax-entry ?\" "\"" st) | ||
| 1142 | st) | ||
| 1143 | "Syntax-table to parse matched quotes.") | ||
| 1144 | |||
| 1145 | (defun bibtex-parse-field-string () | ||
| 1146 | "Parse a field string enclosed by braces or quotes. | ||
| 1147 | If a syntactically correct string is found, a pair containing the start and | ||
| 1148 | end position of the field string is returned, nil otherwise." | ||
| 1149 | (let ((end-point | ||
| 1150 | (or (and (eq (following-char) ?\") | ||
| 1151 | (save-excursion | ||
| 1152 | (with-syntax-table bibtex-quoted-string-syntax-table | ||
| 1153 | (forward-sexp 1)) | ||
| 1154 | (point))) | ||
| 1155 | (and (eq (following-char) ?\{) | ||
| 1156 | (save-excursion | ||
| 1157 | (with-syntax-table bibtex-braced-string-syntax-table | ||
| 1158 | (forward-sexp 1)) | ||
| 1159 | (point)))))) | ||
| 1160 | (if end-point | ||
| 1161 | (cons (point) end-point)))) | ||
| 1162 | |||
| 1163 | (defun bibtex-parse-association (parse-lhs parse-rhs) | 1127 | (defun bibtex-parse-association (parse-lhs parse-rhs) |
| 1164 | "Parse a string of the format <left-hand-side = right-hand-side>. | 1128 | "Parse a string of the format <left-hand-side = right-hand-side>. |
| 1165 | The functions PARSE-LHS and PARSE-RHS are used to parse the corresponding | 1129 | The functions PARSE-LHS and PARSE-RHS are used to parse the corresponding |
| @@ -1199,6 +1163,44 @@ BibTeX field as necessary." | |||
| 1199 | ;; Now try again. | 1163 | ;; Now try again. |
| 1200 | (bibtex-parse-field-name)))) | 1164 | (bibtex-parse-field-name)))) |
| 1201 | 1165 | ||
| 1166 | (defconst bibtex-braced-string-syntax-table | ||
| 1167 | (let ((st (make-syntax-table))) | ||
| 1168 | (modify-syntax-entry ?\{ "(}" st) | ||
| 1169 | (modify-syntax-entry ?\} "){" st) | ||
| 1170 | (modify-syntax-entry ?\[ "." st) | ||
| 1171 | (modify-syntax-entry ?\] "." st) | ||
| 1172 | (modify-syntax-entry ?\( "." st) | ||
| 1173 | (modify-syntax-entry ?\) "." st) | ||
| 1174 | (modify-syntax-entry ?\\ "." st) | ||
| 1175 | (modify-syntax-entry ?\" "." st) | ||
| 1176 | st) | ||
| 1177 | "Syntax-table to parse matched braces.") | ||
| 1178 | |||
| 1179 | (defconst bibtex-quoted-string-syntax-table | ||
| 1180 | (let ((st (make-syntax-table))) | ||
| 1181 | (modify-syntax-entry ?\\ "\\" st) | ||
| 1182 | (modify-syntax-entry ?\" "\"" st) | ||
| 1183 | st) | ||
| 1184 | "Syntax-table to parse matched quotes.") | ||
| 1185 | |||
| 1186 | (defun bibtex-parse-field-string () | ||
| 1187 | "Parse a field string enclosed by braces or quotes. | ||
| 1188 | If a syntactically correct string is found, a pair containing the start and | ||
| 1189 | end position of the field string is returned, nil otherwise." | ||
| 1190 | (let ((end-point | ||
| 1191 | (or (and (eq (following-char) ?\") | ||
| 1192 | (save-excursion | ||
| 1193 | (with-syntax-table bibtex-quoted-string-syntax-table | ||
| 1194 | (forward-sexp 1)) | ||
| 1195 | (point))) | ||
| 1196 | (and (eq (following-char) ?\{) | ||
| 1197 | (save-excursion | ||
| 1198 | (with-syntax-table bibtex-braced-string-syntax-table | ||
| 1199 | (forward-sexp 1)) | ||
| 1200 | (point)))))) | ||
| 1201 | (if end-point | ||
| 1202 | (cons (point) end-point)))) | ||
| 1203 | |||
| 1202 | (defun bibtex-parse-field-text () | 1204 | (defun bibtex-parse-field-text () |
| 1203 | "Parse the text part of a BibTeX field. | 1205 | "Parse the text part of a BibTeX field. |
| 1204 | The text part is either a string, or an empty string, or a constant followed | 1206 | The text part is either a string, or an empty string, or a constant followed |
| @@ -1410,7 +1412,7 @@ delimiters if present." | |||
| 1410 | (let ((content (buffer-substring-no-properties (nth 0 (cdr bounds)) | 1412 | (let ((content (buffer-substring-no-properties (nth 0 (cdr bounds)) |
| 1411 | (nth 1 (cdr bounds))))) | 1413 | (nth 1 (cdr bounds))))) |
| 1412 | (if (and remove-delim | 1414 | (if (and remove-delim |
| 1413 | (string-match "\\`{\\(.*\\)}\\'" content)) | 1415 | (string-match "\\`[{\"]\\(.*\\)[}\"]\\'" content)) |
| 1414 | (substring content (match-beginning 1) (match-end 1)) | 1416 | (substring content (match-beginning 1) (match-end 1)) |
| 1415 | content))) | 1417 | content))) |
| 1416 | 1418 | ||
| @@ -1455,16 +1457,6 @@ The value is actually the tail of LIST whose car matches STRING." | |||
| 1455 | (setq list (cdr list))) | 1457 | (setq list (cdr list))) |
| 1456 | list)) | 1458 | list)) |
| 1457 | 1459 | ||
| 1458 | (defun bibtex-assoc-of-regexp (string alist) | ||
| 1459 | "Return non-nil if STRING is exactly matched by the car of an | ||
| 1460 | element of ALIST (case ignored). The value is actually the element | ||
| 1461 | of LIST whose car matches STRING." | ||
| 1462 | (let ((case-fold-search t)) | ||
| 1463 | (while (and alist | ||
| 1464 | (not (string-match (concat "\\`\\(?:" (caar alist) "\\)\\'") string))) | ||
| 1465 | (setq alist (cdr alist))) | ||
| 1466 | (car alist))) | ||
| 1467 | |||
| 1468 | (defun bibtex-skip-to-valid-entry (&optional backward) | 1460 | (defun bibtex-skip-to-valid-entry (&optional backward) |
| 1469 | "Unless at beginning of a valid BibTeX entry, move point to beginning of the | 1461 | "Unless at beginning of a valid BibTeX entry, move point to beginning of the |
| 1470 | next valid one. With optional argument BACKWARD non-nil, move backward to | 1462 | next valid one. With optional argument BACKWARD non-nil, move backward to |
| @@ -1519,8 +1511,8 @@ FUN will not be called for @String entries." | |||
| 1519 | If FLAG is a string, the message is initialized (in this case a | 1511 | If FLAG is a string, the message is initialized (in this case a |
| 1520 | value for INTERVAL may be given as well (if not this is set to 5)). | 1512 | value for INTERVAL may be given as well (if not this is set to 5)). |
| 1521 | If FLAG is done, the message is deinitialized. | 1513 | If FLAG is done, the message is deinitialized. |
| 1522 | If FLAG is absent, a message is echoed if point was incremented | 1514 | If FLAG is nil, a message is echoed if point was incremented at least |
| 1523 | at least INTERVAL percent since last message was echoed." | 1515 | `bibtex-progress-interval' percent since last message was echoed." |
| 1524 | (cond ((stringp flag) | 1516 | (cond ((stringp flag) |
| 1525 | (setq bibtex-progress-lastmes flag) | 1517 | (setq bibtex-progress-lastmes flag) |
| 1526 | (setq bibtex-progress-interval (or interval 5) | 1518 | (setq bibtex-progress-interval (or interval 5) |
| @@ -1685,11 +1677,11 @@ are defined, but only for the head part of the entry | |||
| 1685 | "Try to avoid point being at end of a BibTeX field." | 1677 | "Try to avoid point being at end of a BibTeX field." |
| 1686 | (end-of-line) | 1678 | (end-of-line) |
| 1687 | (skip-chars-backward " \t") | 1679 | (skip-chars-backward " \t") |
| 1688 | (cond ((= (preceding-char) ?,) | 1680 | (if (= (preceding-char) ?,) |
| 1689 | (forward-char -2))) | 1681 | (forward-char -2)) |
| 1690 | (cond ((or (= (preceding-char) ?}) | 1682 | (if (or (= (preceding-char) ?}) |
| 1691 | (= (preceding-char) ?\")) | 1683 | (= (preceding-char) ?\")) |
| 1692 | (forward-char -1)))) | 1684 | (forward-char -1))) |
| 1693 | 1685 | ||
| 1694 | (defun bibtex-enclosing-field (&optional noerr) | 1686 | (defun bibtex-enclosing-field (&optional noerr) |
| 1695 | "Search for BibTeX field enclosing point. Point moves to end of field. | 1687 | "Search for BibTeX field enclosing point. Point moves to end of field. |
| @@ -1749,6 +1741,15 @@ Beginning (but not end) of entry is given by (`match-beginning' 0)." | |||
| 1749 | (error "Unknown tag field: %s. Please submit a bug report" | 1741 | (error "Unknown tag field: %s. Please submit a bug report" |
| 1750 | bibtex-last-kill-command)))))) | 1742 | bibtex-last-kill-command)))))) |
| 1751 | 1743 | ||
| 1744 | (defun bibtex-assoc-regexp (regexp alist) | ||
| 1745 | "Return non-nil if REGEXP matches the car of an element of ALIST. | ||
| 1746 | The value is actually the element of ALIST matched by REGEXP. | ||
| 1747 | Case is ignored if `case-fold-search' is non-nil in the current buffer." | ||
| 1748 | (while (and alist | ||
| 1749 | (not (string-match regexp (caar alist)))) | ||
| 1750 | (setq alist (cdr alist))) | ||
| 1751 | (car alist)) | ||
| 1752 | |||
| 1752 | (defun bibtex-format-entry () | 1753 | (defun bibtex-format-entry () |
| 1753 | "Helper function for `bibtex-clean-entry'. | 1754 | "Helper function for `bibtex-clean-entry'. |
| 1754 | Formats current entry according to variable `bibtex-entry-format'." | 1755 | Formats current entry according to variable `bibtex-entry-format'." |
| @@ -1763,7 +1764,7 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1763 | unify-case inherit-booktitle) | 1764 | unify-case inherit-booktitle) |
| 1764 | bibtex-entry-format)) | 1765 | bibtex-entry-format)) |
| 1765 | crossref-key bounds alternatives-there non-empty-alternative | 1766 | crossref-key bounds alternatives-there non-empty-alternative |
| 1766 | entry-list req creq field-done field-list) | 1767 | entry-list req-field-list field-done field-list) |
| 1767 | 1768 | ||
| 1768 | ;; identify entry type | 1769 | ;; identify entry type |
| 1769 | (goto-char (point-min)) | 1770 | (goto-char (point-min)) |
| @@ -1772,9 +1773,7 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1772 | (end-type (match-end 0))) | 1773 | (end-type (match-end 0))) |
| 1773 | (setq entry-list (assoc-ignore-case (buffer-substring-no-properties | 1774 | (setq entry-list (assoc-ignore-case (buffer-substring-no-properties |
| 1774 | beg-type end-type) | 1775 | beg-type end-type) |
| 1775 | bibtex-entry-field-alist) | 1776 | bibtex-entry-field-alist)) |
| 1776 | req (nth 0 (nth 1 entry-list)) ; required part | ||
| 1777 | creq (nth 0 (nth 2 entry-list))) ; crossref part | ||
| 1778 | 1777 | ||
| 1779 | ;; unify case of entry name | 1778 | ;; unify case of entry name |
| 1780 | (when (memq 'unify-case format) | 1779 | (when (memq 'unify-case format) |
| @@ -1791,20 +1790,32 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1791 | ;; determine if entry has crossref field and if at least | 1790 | ;; determine if entry has crossref field and if at least |
| 1792 | ;; one alternative is non-empty | 1791 | ;; one alternative is non-empty |
| 1793 | (goto-char (point-min)) | 1792 | (goto-char (point-min)) |
| 1794 | (while (setq bounds (bibtex-search-forward-field | 1793 | (let* ((fields-alist (bibtex-parse-entry)) |
| 1795 | bibtex-field-name)) | 1794 | (case-fold-search t) |
| 1796 | (goto-char (bibtex-start-of-name-in-field bounds)) | 1795 | (field (bibtex-assoc-regexp "\\(OPT\\)?crossref\\>" |
| 1797 | (cond ((looking-at "ALT") | 1796 | fields-alist))) |
| 1798 | (setq alternatives-there t) | 1797 | (setq crossref-key (and field |
| 1799 | (goto-char (bibtex-start-of-text-in-field bounds)) | 1798 | (not (string-match bibtex-empty-field-re |
| 1800 | (if (not (looking-at bibtex-empty-field-re)) | 1799 | (cdr field))) |
| 1801 | (setq non-empty-alternative t))) | 1800 | (cdr field)) |
| 1802 | ((and (looking-at "\\(OPT\\)?crossref\\>") | 1801 | req-field-list (if crossref-key |
| 1803 | (progn (goto-char (bibtex-start-of-text-in-field bounds)) | 1802 | (nth 0 (nth 2 entry-list)) ; crossref part |
| 1804 | (not (looking-at bibtex-empty-field-re)))) | 1803 | (nth 0 (nth 1 entry-list)))) ; required part |
| 1805 | (setq crossref-key | 1804 | |
| 1806 | (bibtex-text-in-field-bounds bounds t)))) | 1805 | (dolist (rfield req-field-list) |
| 1807 | (goto-char (bibtex-end-of-field bounds))) | 1806 | (when (nth 3 rfield) ; we should have an alternative |
| 1807 | (setq alternatives-there t | ||
| 1808 | field (bibtex-assoc-regexp | ||
| 1809 | (concat "\\(ALT\\)?" (car rfield) "\\>") | ||
| 1810 | fields-alist)) | ||
| 1811 | (if (and field | ||
| 1812 | (not (string-match bibtex-empty-field-re | ||
| 1813 | (cdr field)))) | ||
| 1814 | (cond ((not non-empty-alternative) | ||
| 1815 | (setq non-empty-alternative t)) | ||
| 1816 | ((memq 'required-fields format) | ||
| 1817 | (error "More than one non-empty alternative."))))))) | ||
| 1818 | |||
| 1808 | (if (and alternatives-there | 1819 | (if (and alternatives-there |
| 1809 | (not non-empty-alternative) | 1820 | (not non-empty-alternative) |
| 1810 | (memq 'required-fields format)) | 1821 | (memq 'required-fields format)) |
| @@ -1832,18 +1843,23 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1832 | ;; quite some redundancy compared with what we need to do | 1843 | ;; quite some redundancy compared with what we need to do |
| 1833 | ;; anyway. So for speed-up we avoid using them. | 1844 | ;; anyway. So for speed-up we avoid using them. |
| 1834 | 1845 | ||
| 1835 | (when (and opt-alt | 1846 | (if (memq 'opts-or-alts format) |
| 1836 | (memq 'opts-or-alts format)) | 1847 | (cond ((and empty-field |
| 1837 | (if empty-field | 1848 | (or opt-alt |
| 1838 | ;; Either it is an empty ALT field. Then we have checked | 1849 | (let ((field (assoc-ignore-case |
| 1839 | ;; already that we have one non-empty alternative. | 1850 | field-name req-field-list))) |
| 1840 | ;; Or it is an empty OPT field that we do not miss anyway. | 1851 | (or (not field) ; OPT field |
| 1841 | ;; So we can safely delete this field. | 1852 | (nth 3 field))))) ; ALT field |
| 1842 | (progn (delete-region beg-field end-field) | 1853 | ;; Either it is an empty ALT field. Then we have checked |
| 1843 | (setq deleted t)) | 1854 | ;; already that we have one non-empty alternative. Or it |
| 1844 | ;; otherwise: not empty, delete "OPT" or "ALT" | 1855 | ;; is an empty OPT field that we do not miss anyway. |
| 1845 | (goto-char beg-name) | 1856 | ;; So we can safely delete this field. |
| 1846 | (delete-char 3))) | 1857 | (delete-region beg-field end-field) |
| 1858 | (setq deleted t)) | ||
| 1859 | ;; otherwise: not empty, delete "OPT" or "ALT" | ||
| 1860 | (opt-alt | ||
| 1861 | (goto-char beg-name) | ||
| 1862 | (delete-char 3)))) | ||
| 1847 | 1863 | ||
| 1848 | (unless deleted | 1864 | (unless deleted |
| 1849 | (push field-name field-list) | 1865 | (push field-name field-list) |
| @@ -1902,8 +1918,7 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1902 | ;; if empty field, complain | 1918 | ;; if empty field, complain |
| 1903 | (if (and empty-field | 1919 | (if (and empty-field |
| 1904 | (memq 'required-fields format) | 1920 | (memq 'required-fields format) |
| 1905 | (assoc-ignore-case field-name | 1921 | (assoc-ignore-case field-name req-field-list)) |
| 1906 | (if crossref-key creq req))) | ||
| 1907 | (error "Mandatory field `%s' is empty" field-name)) | 1922 | (error "Mandatory field `%s' is empty" field-name)) |
| 1908 | 1923 | ||
| 1909 | ;; unify case of field name | 1924 | ;; unify case of field name |
| @@ -1925,8 +1940,8 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1925 | 1940 | ||
| 1926 | ;; check whether all required fields are present | 1941 | ;; check whether all required fields are present |
| 1927 | (if (memq 'required-fields format) | 1942 | (if (memq 'required-fields format) |
| 1928 | (let (altlist (found 0)) | 1943 | (let ((found 0) altlist) |
| 1929 | (dolist (fname (if crossref-key creq req)) | 1944 | (dolist (fname req-field-list) |
| 1930 | (if (nth 3 fname) | 1945 | (if (nth 3 fname) |
| 1931 | (push (car fname) altlist)) | 1946 | (push (car fname) altlist)) |
| 1932 | (unless (or (member (car fname) field-list) | 1947 | (unless (or (member (car fname) field-list) |
| @@ -1940,7 +1955,7 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1940 | (error "Alternative mandatory field `%s' is missing" | 1955 | (error "Alternative mandatory field `%s' is missing" |
| 1941 | altlist)) | 1956 | altlist)) |
| 1942 | ((> found 1) | 1957 | ((> found 1) |
| 1943 | (error "Alternative fields `%s' is defined %s times" | 1958 | (error "Alternative fields `%s' are defined %s times" |
| 1944 | altlist found)))))) | 1959 | altlist found)))))) |
| 1945 | 1960 | ||
| 1946 | ;; update point | 1961 | ;; update point |
| @@ -2051,8 +2066,8 @@ and return results as a list." | |||
| 2051 | (setq titlestring (substring titlestring 0 (match-beginning 0)))))) | 2066 | (setq titlestring (substring titlestring 0 (match-beginning 0)))))) |
| 2052 | ;; gather words from titlestring into a list. Ignore | 2067 | ;; gather words from titlestring into a list. Ignore |
| 2053 | ;; specific words and use only a specific amount of words. | 2068 | ;; specific words and use only a specific amount of words. |
| 2054 | (let (case-fold-search titlewords titlewords-extra titleword end-match | 2069 | (let ((counter 0) |
| 2055 | (counter 0)) | 2070 | case-fold-search titlewords titlewords-extra titleword end-match) |
| 2056 | (while (and (or (not (numberp bibtex-autokey-titlewords)) | 2071 | (while (and (or (not (numberp bibtex-autokey-titlewords)) |
| 2057 | (< counter (+ bibtex-autokey-titlewords | 2072 | (< counter (+ bibtex-autokey-titlewords |
| 2058 | bibtex-autokey-titlewords-stretch))) | 2073 | bibtex-autokey-titlewords-stretch))) |
| @@ -2079,10 +2094,14 @@ and return results as a list." | |||
| 2079 | "Do some abbreviations on TITLEWORD. | 2094 | "Do some abbreviations on TITLEWORD. |
| 2080 | The rules are defined in `bibtex-autokey-titleword-abbrevs' | 2095 | The rules are defined in `bibtex-autokey-titleword-abbrevs' |
| 2081 | and `bibtex-autokey-titleword-length'." | 2096 | and `bibtex-autokey-titleword-length'." |
| 2082 | (let ((abbrev (bibtex-assoc-of-regexp | 2097 | (let ((case-folde-search t) |
| 2083 | titleword bibtex-autokey-titleword-abbrevs))) | 2098 | (alist bibtex-autokey-titleword-abbrevs)) |
| 2084 | (if abbrev | 2099 | (while (and alist |
| 2085 | (cdr abbrev) | 2100 | (not (string-match (concat "\\`\\(?:" (caar alist) "\\)\\'") |
| 2101 | titleword))) | ||
| 2102 | (setq alist (cdr alist))) | ||
| 2103 | (if alist | ||
| 2104 | (cdar alist) | ||
| 2086 | (bibtex-autokey-abbrev titleword | 2105 | (bibtex-autokey-abbrev titleword |
| 2087 | bibtex-autokey-titleword-length)))) | 2106 | bibtex-autokey-titleword-length)))) |
| 2088 | 2107 | ||
| @@ -2384,6 +2403,7 @@ of a word, all strings are listed. Return completion." | |||
| 2384 | (display-completion-list (all-completions part-of-word | 2403 | (display-completion-list (all-completions part-of-word |
| 2385 | completions))) | 2404 | completions))) |
| 2386 | (message "Making completion list...done") | 2405 | (message "Making completion list...done") |
| 2406 | ;; return value is handled by choose-completion-string-functions | ||
| 2387 | nil)))) | 2407 | nil)))) |
| 2388 | 2408 | ||
| 2389 | (defun bibtex-complete-string-cleanup (str) | 2409 | (defun bibtex-complete-string-cleanup (str) |
| @@ -2629,6 +2649,34 @@ non-nil. | |||
| 2629 | (easy-menu-add bibtex-entry-menu) | 2649 | (easy-menu-add bibtex-entry-menu) |
| 2630 | (run-hooks 'bibtex-mode-hook)) | 2650 | (run-hooks 'bibtex-mode-hook)) |
| 2631 | 2651 | ||
| 2652 | (defun bibtex-field-list (entry-type) | ||
| 2653 | "Return list of allowed fields for entry ENTRY-TYPE. | ||
| 2654 | More specifically, the return value is a cons pair (REQUIRED . OPTIONAL), | ||
| 2655 | where REQUIRED and OPTIONAL are lists of the required and optional field | ||
| 2656 | names for ENTRY-TYPE according to `bibtex-entry-field-alist'." | ||
| 2657 | (let ((e (assoc-ignore-case entry-type bibtex-entry-field-alist)) | ||
| 2658 | required optional) | ||
| 2659 | (unless e | ||
| 2660 | (error "Bibtex entry type %s not defined" entry-type)) | ||
| 2661 | (if (and (member-ignore-case entry-type bibtex-include-OPTcrossref) | ||
| 2662 | (nth 2 e)) | ||
| 2663 | (setq required (nth 0 (nth 2 e)) | ||
| 2664 | optional (nth 1 (nth 2 e))) | ||
| 2665 | (setq required (nth 0 (nth 1 e)) | ||
| 2666 | optional (nth 1 (nth 1 e)))) | ||
| 2667 | (if bibtex-include-OPTkey | ||
| 2668 | (push (list "key" | ||
| 2669 | "Used for reference key creation if author and editor fields are missing" | ||
| 2670 | (if (or (stringp bibtex-include-OPTkey) | ||
| 2671 | (fboundp bibtex-include-OPTkey)) | ||
| 2672 | bibtex-include-OPTkey)) | ||
| 2673 | optional)) | ||
| 2674 | (if (member-ignore-case entry-type bibtex-include-OPTcrossref) | ||
| 2675 | (push '("crossref" "Reference key of the cross-referenced entry") | ||
| 2676 | optional)) | ||
| 2677 | (setq optional (append optional bibtex-user-optional-fields)) | ||
| 2678 | (cons required optional))) | ||
| 2679 | |||
| 2632 | (defun bibtex-entry (entry-type) | 2680 | (defun bibtex-entry (entry-type) |
| 2633 | "Insert a new BibTeX entry. | 2681 | "Insert a new BibTeX entry. |
| 2634 | After insertion it calls the functions in `bibtex-add-entry-hook'." | 2682 | After insertion it calls the functions in `bibtex-add-entry-hook'." |
| @@ -2638,38 +2686,17 @@ After insertion it calls the functions in `bibtex-add-entry-hook'." | |||
| 2638 | bibtex-entry-field-alist | 2686 | bibtex-entry-field-alist |
| 2639 | nil t nil 'bibtex-entry-type-history))) | 2687 | nil t nil 'bibtex-entry-type-history))) |
| 2640 | (list e-t))) | 2688 | (list e-t))) |
| 2641 | (let* (required optional | 2689 | (let ((key (if bibtex-maintain-sorted-entries |
| 2642 | (key (if bibtex-maintain-sorted-entries | 2690 | (bibtex-read-key (format "%s key: " entry-type)))) |
| 2643 | (bibtex-read-key (format "%s key: " entry-type)))) | 2691 | (field-list (bibtex-field-list entry-type))) |
| 2644 | (e (assoc-ignore-case entry-type bibtex-entry-field-alist)) | ||
| 2645 | (r-n-o (elt e 1)) | ||
| 2646 | (c-ref (elt e 2))) | ||
| 2647 | (if (not e) | ||
| 2648 | (error "Bibtex entry type %s not defined" entry-type)) | ||
| 2649 | (if (and (member entry-type bibtex-include-OPTcrossref) | ||
| 2650 | c-ref) | ||
| 2651 | (setq required (elt c-ref 0) | ||
| 2652 | optional (elt c-ref 1)) | ||
| 2653 | (setq required (elt r-n-o 0) | ||
| 2654 | optional (elt r-n-o 1))) | ||
| 2655 | (unless (bibtex-prepare-new-entry (list key nil entry-type)) | 2692 | (unless (bibtex-prepare-new-entry (list key nil entry-type)) |
| 2656 | (error "Entry with key `%s' already exists" key)) | 2693 | (error "Entry with key `%s' already exists" key)) |
| 2657 | (indent-to-column bibtex-entry-offset) | 2694 | (indent-to-column bibtex-entry-offset) |
| 2658 | (insert "@" entry-type (bibtex-entry-left-delimiter)) | 2695 | (insert "@" entry-type (bibtex-entry-left-delimiter)) |
| 2659 | (if key | 2696 | (if key (insert key)) |
| 2660 | (insert key)) | ||
| 2661 | (save-excursion | 2697 | (save-excursion |
| 2662 | (mapcar 'bibtex-make-field required) | 2698 | (mapcar 'bibtex-make-field (car field-list)) |
| 2663 | (if (member entry-type bibtex-include-OPTcrossref) | 2699 | (mapcar 'bibtex-make-optional-field (cdr field-list)) |
| 2664 | (bibtex-make-optional-field '("crossref"))) | ||
| 2665 | (if bibtex-include-OPTkey | ||
| 2666 | (if (or (stringp bibtex-include-OPTkey) | ||
| 2667 | (fboundp bibtex-include-OPTkey)) | ||
| 2668 | (bibtex-make-optional-field | ||
| 2669 | (list "key" nil bibtex-include-OPTkey)) | ||
| 2670 | (bibtex-make-optional-field '("key")))) | ||
| 2671 | (mapcar 'bibtex-make-optional-field optional) | ||
| 2672 | (mapcar 'bibtex-make-optional-field bibtex-user-optional-fields) | ||
| 2673 | (if bibtex-comma-after-last-field | 2700 | (if bibtex-comma-after-last-field |
| 2674 | (insert ",")) | 2701 | (insert ",")) |
| 2675 | (insert "\n") | 2702 | (insert "\n") |
| @@ -2680,10 +2707,31 @@ After insertion it calls the functions in `bibtex-add-entry-hook'." | |||
| 2680 | (bibtex-autofill-entry)) | 2707 | (bibtex-autofill-entry)) |
| 2681 | (run-hooks 'bibtex-add-entry-hook))) | 2708 | (run-hooks 'bibtex-add-entry-hook))) |
| 2682 | 2709 | ||
| 2710 | (defun bibtex-entry-update () | ||
| 2711 | "Update an existing BibTeX entry. | ||
| 2712 | In the BibTeX entry at point, make new fields for those items that may occur | ||
| 2713 | according to `bibtex-entry-field-alist', but are not yet present." | ||
| 2714 | (interactive) | ||
| 2715 | (save-excursion | ||
| 2716 | (bibtex-beginning-of-entry) | ||
| 2717 | ;; For inserting new fields, we use the fact that | ||
| 2718 | ;; bibtex-parse-entry moves point to the end of the last field. | ||
| 2719 | (let* ((fields-alist (bibtex-parse-entry)) | ||
| 2720 | (field-list (bibtex-field-list | ||
| 2721 | (substring (cdr (assoc "=type=" fields-alist)) | ||
| 2722 | 1)))) ; don't want @ | ||
| 2723 | (dolist (field (car field-list)) | ||
| 2724 | (unless (assoc-ignore-case (car field) fields-alist) | ||
| 2725 | (bibtex-make-field field))) | ||
| 2726 | (dolist (field (cdr field-list)) | ||
| 2727 | (unless (assoc-ignore-case (car field) fields-alist) | ||
| 2728 | (bibtex-make-optional-field field)))))) | ||
| 2729 | |||
| 2683 | (defun bibtex-parse-entry () | 2730 | (defun bibtex-parse-entry () |
| 2684 | "Parse entry at point, return an alist. | 2731 | "Parse entry at point, return an alist. |
| 2685 | The alist elements have the form (FIELD . TEXT), where FIELD can also be | 2732 | The alist elements have the form (FIELD . TEXT), where FIELD can also be |
| 2686 | the special strings \"=type=\" and \"=key=\"." | 2733 | the special strings \"=type=\" and \"=key=\". |
| 2734 | Move point to the end of the last field." | ||
| 2687 | (let (alist bounds) | 2735 | (let (alist bounds) |
| 2688 | (when (looking-at bibtex-entry-head) | 2736 | (when (looking-at bibtex-entry-head) |
| 2689 | (push (cons "=type=" (match-string bibtex-type-in-head)) alist) | 2737 | (push (cons "=type=" (match-string bibtex-type-in-head)) alist) |
| @@ -2774,28 +2822,14 @@ the special strings \"=type=\" and \"=key=\"." | |||
| 2774 | (looking-at "OPT\\|ALT")) | 2822 | (looking-at "OPT\\|ALT")) |
| 2775 | (match-end 0) mb) | 2823 | (match-end 0) mb) |
| 2776 | (bibtex-end-of-name-in-field bounds))) | 2824 | (bibtex-end-of-name-in-field bounds))) |
| 2777 | (entry-type (progn (re-search-backward | 2825 | (field-list (bibtex-field-list (progn (re-search-backward |
| 2778 | bibtex-entry-maybe-empty-head nil t) | 2826 | bibtex-entry-maybe-empty-head nil t) |
| 2779 | (bibtex-type-in-head))) | 2827 | (bibtex-type-in-head)))) |
| 2780 | (entry-list (assoc-ignore-case entry-type | 2828 | (comment (assoc-ignore-case field-name |
| 2781 | bibtex-entry-field-alist)) | 2829 | (append (car field-list) |
| 2782 | (c-r-list (elt entry-list 2)) | 2830 | (cdr field-list))))) |
| 2783 | (req-opt-list (if (and (member entry-type | ||
| 2784 | bibtex-include-OPTcrossref) | ||
| 2785 | c-r-list) | ||
| 2786 | c-r-list | ||
| 2787 | (elt entry-list 1))) | ||
| 2788 | (list-of-entries (append (elt req-opt-list 0) | ||
| 2789 | (elt req-opt-list 1) | ||
| 2790 | bibtex-user-optional-fields | ||
| 2791 | (if (member entry-type | ||
| 2792 | bibtex-include-OPTcrossref) | ||
| 2793 | '(("crossref" "Reference key of the cross-referenced entry"))) | ||
| 2794 | (if bibtex-include-OPTkey | ||
| 2795 | '(("key" "Used for reference key creation if author and editor fields are missing"))))) | ||
| 2796 | (comment (assoc-ignore-case field-name list-of-entries))) | ||
| 2797 | (if comment | 2831 | (if comment |
| 2798 | (message (elt comment 1)) | 2832 | (message (nth 1 comment)) |
| 2799 | (message "No comment available"))))) | 2833 | (message "No comment available"))))) |
| 2800 | 2834 | ||
| 2801 | (defun bibtex-make-field (field &optional called-by-yank) | 2835 | (defun bibtex-make-field (field &optional called-by-yank) |
| @@ -2804,24 +2838,13 @@ FIELD is either a string or a list of the form | |||
| 2804 | \(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in | 2838 | \(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in |
| 2805 | `bibtex-entry-field-alist'." | 2839 | `bibtex-entry-field-alist'." |
| 2806 | (interactive | 2840 | (interactive |
| 2807 | (list (let* ((entry-type | 2841 | (list (let ((completion-ignore-case t) |
| 2808 | (save-excursion | 2842 | (field-list (bibtex-field-list |
| 2809 | (bibtex-enclosing-entry-maybe-empty-head) | 2843 | (save-excursion |
| 2810 | (bibtex-type-in-head))) | 2844 | (bibtex-enclosing-entry-maybe-empty-head) |
| 2811 | ;; "preliminary" completion list | 2845 | (bibtex-type-in-head))))) |
| 2812 | (fl (nth 1 (assoc-ignore-case | 2846 | (completing-read "BibTeX field name: " |
| 2813 | entry-type bibtex-entry-field-alist))) | 2847 | (append (car field-list) (cdr field-list)) |
| 2814 | ;; "full" completion list | ||
| 2815 | (field-list (append (nth 0 fl) | ||
| 2816 | (nth 1 fl) | ||
| 2817 | bibtex-user-optional-fields | ||
| 2818 | (if (member entry-type | ||
| 2819 | bibtex-include-OPTcrossref) | ||
| 2820 | '(("crossref"))) | ||
| 2821 | (if bibtex-include-OPTkey | ||
| 2822 | '(("key"))))) | ||
| 2823 | (completion-ignore-case t)) | ||
| 2824 | (completing-read "BibTeX field name: " field-list | ||
| 2825 | nil nil nil bibtex-field-history)))) | 2848 | nil nil nil bibtex-field-history)))) |
| 2826 | (unless (consp field) | 2849 | (unless (consp field) |
| 2827 | (setq field (list field))) | 2850 | (setq field (list field))) |
| @@ -2848,8 +2871,9 @@ FIELD is either a string or a list of the form | |||
| 2848 | ((fboundp init) | 2871 | ((fboundp init) |
| 2849 | (insert (funcall init))))) | 2872 | (insert (funcall init))))) |
| 2850 | (if (not called-by-yank) (insert (bibtex-field-right-delimiter))) | 2873 | (if (not called-by-yank) (insert (bibtex-field-right-delimiter))) |
| 2851 | (if (interactive-p) | 2874 | (when (interactive-p) |
| 2852 | (forward-char -1))) | 2875 | (forward-char -1) |
| 2876 | (bibtex-print-help-message))) | ||
| 2853 | 2877 | ||
| 2854 | (defun bibtex-beginning-of-entry () | 2878 | (defun bibtex-beginning-of-entry () |
| 2855 | "Move to beginning of BibTeX entry (beginning of line). | 2879 | "Move to beginning of BibTeX entry (beginning of line). |
| @@ -2982,13 +3006,14 @@ the entries of the BibTeX buffer. Return nil if no entry found." | |||
| 2982 | "\\(OPT\\)?crossref" t))) | 3006 | "\\(OPT\\)?crossref" t))) |
| 2983 | (list key | 3007 | (list key |
| 2984 | (if bounds (bibtex-text-in-field-bounds bounds t)) | 3008 | (if bounds (bibtex-text-in-field-bounds bounds t)) |
| 2985 | entry-name)))) | 3009 | entry-name))) |
| 2986 | (list key nil entry-name))))) | 3010 | (list key nil entry-name)))))) |
| 2987 | 3011 | ||
| 2988 | (defun bibtex-lessp (index1 index2) | 3012 | (defun bibtex-lessp (index1 index2) |
| 2989 | "Predicate for sorting BibTeX entries with indices INDEX1 and INDEX2. | 3013 | "Predicate for sorting BibTeX entries with indices INDEX1 and INDEX2. |
| 2990 | Each index is a list (KEY CROSSREF-KEY ENTRY-NAME). | 3014 | Each index is a list (KEY CROSSREF-KEY ENTRY-NAME). |
| 2991 | The predicate depends on the variable `bibtex-maintain-sorted-entries'." | 3015 | The predicate depends on the variable `bibtex-maintain-sorted-entries'. |
| 3016 | If its value is nil use plain sorting." | ||
| 2992 | (cond ((not index1) (not index2)) ; indices can be nil | 3017 | (cond ((not index1) (not index2)) ; indices can be nil |
| 2993 | ((not index2) nil) | 3018 | ((not index2) nil) |
| 2994 | ((equal bibtex-maintain-sorted-entries 'crossref) | 3019 | ((equal bibtex-maintain-sorted-entries 'crossref) |
| @@ -3886,5 +3911,5 @@ is outside key or BibTeX field." | |||
| 3886 | 3911 | ||
| 3887 | (provide 'bibtex) | 3912 | (provide 'bibtex) |
| 3888 | 3913 | ||
| 3889 | ;;; arch-tag: ee2be3af-caad-427f-b42a-d20fad630d04 | 3914 | ;; arch-tag: ee2be3af-caad-427f-b42a-d20fad630d04 |
| 3890 | ;;; bibtex.el ends here | 3915 | ;;; bibtex.el ends here |