diff options
Diffstat (limited to 'lisp/textmodes/bibtex.el')
| -rw-r--r-- | lisp/textmodes/bibtex.el | 566 |
1 files changed, 297 insertions, 269 deletions
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el index 82b15cf4eb5..15348205c51 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 |
| @@ -1510,7 +1502,7 @@ FUN will not be called for @String entries." | |||
| 1510 | (save-excursion | 1502 | (save-excursion |
| 1511 | (if (or (and (not bibtex-sort-ignore-string-entries) | 1503 | (if (or (and (not bibtex-sort-ignore-string-entries) |
| 1512 | (string-equal "string" (downcase entry-type))) | 1504 | (string-equal "string" (downcase entry-type))) |
| 1513 | (assoc-ignore-case entry-type bibtex-entry-field-alist)) | 1505 | (assoc-string entry-type bibtex-entry-field-alist t)) |
| 1514 | (funcall fun key beg end))) | 1506 | (funcall fun key beg end))) |
| 1515 | (goto-char end))))) | 1507 | (goto-char end))))) |
| 1516 | 1508 | ||
| @@ -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,18 +1764,17 @@ 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)) |
| 1770 | (re-search-forward bibtex-entry-type) | 1771 | (re-search-forward bibtex-entry-type) |
| 1771 | (let ((beg-type (1+ (match-beginning 0))) | 1772 | (let ((beg-type (1+ (match-beginning 0))) |
| 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-string (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 | t)) |
| 1777 | creq (nth 0 (nth 2 entry-list))) ; crossref part | ||
| 1778 | 1778 | ||
| 1779 | ;; unify case of entry name | 1779 | ;; unify case of entry name |
| 1780 | (when (memq 'unify-case format) | 1780 | (when (memq 'unify-case format) |
| @@ -1791,20 +1791,32 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1791 | ;; determine if entry has crossref field and if at least | 1791 | ;; determine if entry has crossref field and if at least |
| 1792 | ;; one alternative is non-empty | 1792 | ;; one alternative is non-empty |
| 1793 | (goto-char (point-min)) | 1793 | (goto-char (point-min)) |
| 1794 | (while (setq bounds (bibtex-search-forward-field | 1794 | (let* ((fields-alist (bibtex-parse-entry)) |
| 1795 | bibtex-field-name)) | 1795 | (case-fold-search t) |
| 1796 | (goto-char (bibtex-start-of-name-in-field bounds)) | 1796 | (field (bibtex-assoc-regexp "\\`\\(OPT\\)?crossref\\'" |
| 1797 | (cond ((looking-at "ALT") | 1797 | fields-alist))) |
| 1798 | (setq alternatives-there t) | 1798 | (setq crossref-key (and field |
| 1799 | (goto-char (bibtex-start-of-text-in-field bounds)) | 1799 | (not (string-match bibtex-empty-field-re |
| 1800 | (if (not (looking-at bibtex-empty-field-re)) | 1800 | (cdr field))) |
| 1801 | (setq non-empty-alternative t))) | 1801 | (cdr field)) |
| 1802 | ((and (looking-at "\\(OPT\\)?crossref\\>") | 1802 | req-field-list (if crossref-key |
| 1803 | (progn (goto-char (bibtex-start-of-text-in-field bounds)) | 1803 | (nth 0 (nth 2 entry-list)) ; crossref part |
| 1804 | (not (looking-at bibtex-empty-field-re)))) | 1804 | (nth 0 (nth 1 entry-list)))) ; required part |
| 1805 | (setq crossref-key | 1805 | |
| 1806 | (bibtex-text-in-field-bounds bounds t)))) | 1806 | (dolist (rfield req-field-list) |
| 1807 | (goto-char (bibtex-end-of-field bounds))) | 1807 | (when (nth 3 rfield) ; we should have an alternative |
| 1808 | (setq alternatives-there t | ||
| 1809 | field (bibtex-assoc-regexp | ||
| 1810 | (concat "\\`\\(ALT\\)?" (car rfield) "\\'") | ||
| 1811 | fields-alist)) | ||
| 1812 | (if (and field | ||
| 1813 | (not (string-match bibtex-empty-field-re | ||
| 1814 | (cdr field)))) | ||
| 1815 | (cond ((not non-empty-alternative) | ||
| 1816 | (setq non-empty-alternative t)) | ||
| 1817 | ((memq 'required-fields format) | ||
| 1818 | (error "More than one non-empty alternative."))))))) | ||
| 1819 | |||
| 1808 | (if (and alternatives-there | 1820 | (if (and alternatives-there |
| 1809 | (not non-empty-alternative) | 1821 | (not non-empty-alternative) |
| 1810 | (memq 'required-fields format)) | 1822 | (memq 'required-fields format)) |
| @@ -1832,18 +1844,23 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1832 | ;; quite some redundancy compared with what we need to do | 1844 | ;; quite some redundancy compared with what we need to do |
| 1833 | ;; anyway. So for speed-up we avoid using them. | 1845 | ;; anyway. So for speed-up we avoid using them. |
| 1834 | 1846 | ||
| 1835 | (when (and opt-alt | 1847 | (if (memq 'opts-or-alts format) |
| 1836 | (memq 'opts-or-alts format)) | 1848 | (cond ((and empty-field |
| 1837 | (if empty-field | 1849 | (or opt-alt |
| 1838 | ;; Either it is an empty ALT field. Then we have checked | 1850 | (let ((field (assoc-string |
| 1839 | ;; already that we have one non-empty alternative. | 1851 | field-name req-field-list t))) |
| 1840 | ;; Or it is an empty OPT field that we do not miss anyway. | 1852 | (or (not field) ; OPT field |
| 1841 | ;; So we can safely delete this field. | 1853 | (nth 3 field))))) ; ALT field |
| 1842 | (progn (delete-region beg-field end-field) | 1854 | ;; Either it is an empty ALT field. Then we have checked |
| 1843 | (setq deleted t)) | 1855 | ;; already that we have one non-empty alternative. Or it |
| 1844 | ;; otherwise: not empty, delete "OPT" or "ALT" | 1856 | ;; is an empty OPT field that we do not miss anyway. |
| 1845 | (goto-char beg-name) | 1857 | ;; So we can safely delete this field. |
| 1846 | (delete-char 3))) | 1858 | (delete-region beg-field end-field) |
| 1859 | (setq deleted t)) | ||
| 1860 | ;; otherwise: not empty, delete "OPT" or "ALT" | ||
| 1861 | (opt-alt | ||
| 1862 | (goto-char beg-name) | ||
| 1863 | (delete-char 3)))) | ||
| 1847 | 1864 | ||
| 1848 | (unless deleted | 1865 | (unless deleted |
| 1849 | (push field-name field-list) | 1866 | (push field-name field-list) |
| @@ -1902,16 +1919,17 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1902 | ;; if empty field, complain | 1919 | ;; if empty field, complain |
| 1903 | (if (and empty-field | 1920 | (if (and empty-field |
| 1904 | (memq 'required-fields format) | 1921 | (memq 'required-fields format) |
| 1905 | (assoc-ignore-case field-name | 1922 | (assoc-string field-name req-field-list t)) |
| 1906 | (if crossref-key creq req))) | ||
| 1907 | (error "Mandatory field `%s' is empty" field-name)) | 1923 | (error "Mandatory field `%s' is empty" field-name)) |
| 1908 | 1924 | ||
| 1909 | ;; unify case of field name | 1925 | ;; unify case of field name |
| 1910 | (if (memq 'unify-case format) | 1926 | (if (memq 'unify-case format) |
| 1911 | (let ((fname (car (assoc-ignore-case | 1927 | (let ((fname (car (assoc-string |
| 1912 | field-name (append (nth 0 (nth 1 entry-list)) | 1928 | field-name |
| 1913 | (nth 1 (nth 1 entry-list)) | 1929 | (append (nth 0 (nth 1 entry-list)) |
| 1914 | bibtex-user-optional-fields))))) | 1930 | (nth 1 (nth 1 entry-list)) |
| 1931 | bibtex-user-optional-fields) | ||
| 1932 | t)))) | ||
| 1915 | (if fname | 1933 | (if fname |
| 1916 | (progn | 1934 | (progn |
| 1917 | (delete-region beg-name end-name) | 1935 | (delete-region beg-name end-name) |
| @@ -1925,8 +1943,8 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1925 | 1943 | ||
| 1926 | ;; check whether all required fields are present | 1944 | ;; check whether all required fields are present |
| 1927 | (if (memq 'required-fields format) | 1945 | (if (memq 'required-fields format) |
| 1928 | (let (altlist (found 0)) | 1946 | (let ((found 0) altlist) |
| 1929 | (dolist (fname (if crossref-key creq req)) | 1947 | (dolist (fname req-field-list) |
| 1930 | (if (nth 3 fname) | 1948 | (if (nth 3 fname) |
| 1931 | (push (car fname) altlist)) | 1949 | (push (car fname) altlist)) |
| 1932 | (unless (or (member (car fname) field-list) | 1950 | (unless (or (member (car fname) field-list) |
| @@ -1940,7 +1958,7 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 1940 | (error "Alternative mandatory field `%s' is missing" | 1958 | (error "Alternative mandatory field `%s' is missing" |
| 1941 | altlist)) | 1959 | altlist)) |
| 1942 | ((> found 1) | 1960 | ((> found 1) |
| 1943 | (error "Alternative fields `%s' is defined %s times" | 1961 | (error "Alternative fields `%s' are defined %s times" |
| 1944 | altlist found)))))) | 1962 | altlist found)))))) |
| 1945 | 1963 | ||
| 1946 | ;; update point | 1964 | ;; update point |
| @@ -2051,8 +2069,8 @@ and return results as a list." | |||
| 2051 | (setq titlestring (substring titlestring 0 (match-beginning 0)))))) | 2069 | (setq titlestring (substring titlestring 0 (match-beginning 0)))))) |
| 2052 | ;; gather words from titlestring into a list. Ignore | 2070 | ;; gather words from titlestring into a list. Ignore |
| 2053 | ;; specific words and use only a specific amount of words. | 2071 | ;; specific words and use only a specific amount of words. |
| 2054 | (let (case-fold-search titlewords titlewords-extra titleword end-match | 2072 | (let ((counter 0) |
| 2055 | (counter 0)) | 2073 | case-fold-search titlewords titlewords-extra titleword end-match) |
| 2056 | (while (and (or (not (numberp bibtex-autokey-titlewords)) | 2074 | (while (and (or (not (numberp bibtex-autokey-titlewords)) |
| 2057 | (< counter (+ bibtex-autokey-titlewords | 2075 | (< counter (+ bibtex-autokey-titlewords |
| 2058 | bibtex-autokey-titlewords-stretch))) | 2076 | bibtex-autokey-titlewords-stretch))) |
| @@ -2079,10 +2097,14 @@ and return results as a list." | |||
| 2079 | "Do some abbreviations on TITLEWORD. | 2097 | "Do some abbreviations on TITLEWORD. |
| 2080 | The rules are defined in `bibtex-autokey-titleword-abbrevs' | 2098 | The rules are defined in `bibtex-autokey-titleword-abbrevs' |
| 2081 | and `bibtex-autokey-titleword-length'." | 2099 | and `bibtex-autokey-titleword-length'." |
| 2082 | (let ((abbrev (bibtex-assoc-of-regexp | 2100 | (let ((case-folde-search t) |
| 2083 | titleword bibtex-autokey-titleword-abbrevs))) | 2101 | (alist bibtex-autokey-titleword-abbrevs)) |
| 2084 | (if abbrev | 2102 | (while (and alist |
| 2085 | (cdr abbrev) | 2103 | (not (string-match (concat "\\`\\(?:" (caar alist) "\\)\\'") |
| 2104 | titleword))) | ||
| 2105 | (setq alist (cdr alist))) | ||
| 2106 | (if alist | ||
| 2107 | (cdar alist) | ||
| 2086 | (bibtex-autokey-abbrev titleword | 2108 | (bibtex-autokey-abbrev titleword |
| 2087 | bibtex-autokey-titleword-length)))) | 2109 | bibtex-autokey-titleword-length)))) |
| 2088 | 2110 | ||
| @@ -2239,8 +2261,8 @@ Return alist of keys if parsing was completed, `aborted' otherwise." | |||
| 2239 | ;; This is a crossref. | 2261 | ;; This is a crossref. |
| 2240 | (buffer-substring-no-properties | 2262 | (buffer-substring-no-properties |
| 2241 | (1+ (match-beginning 3)) (1- (match-end 3)))) | 2263 | (1+ (match-beginning 3)) (1- (match-end 3)))) |
| 2242 | ((assoc-ignore-case (bibtex-type-in-head) | 2264 | ((assoc-string (bibtex-type-in-head) |
| 2243 | bibtex-entry-field-alist) | 2265 | bibtex-entry-field-alist t) |
| 2244 | ;; This is an entry. | 2266 | ;; This is an entry. |
| 2245 | (match-string-no-properties bibtex-key-in-head))))) | 2267 | (match-string-no-properties bibtex-key-in-head))))) |
| 2246 | (if (and (stringp key) | 2268 | (if (and (stringp key) |
| @@ -2295,7 +2317,7 @@ Return alist of strings if parsing was completed, `aborted' otherwise." | |||
| 2295 | ;; user has aborted by typing a key --> return `aborted' | 2317 | ;; user has aborted by typing a key --> return `aborted' |
| 2296 | (throw 'userkey 'aborted)) | 2318 | (throw 'userkey 'aborted)) |
| 2297 | (setq key (bibtex-reference-key-in-string bounds)) | 2319 | (setq key (bibtex-reference-key-in-string bounds)) |
| 2298 | (if (not (assoc-ignore-case key strings)) | 2320 | (if (not (assoc key strings)) |
| 2299 | (push (cons key (bibtex-text-in-string bounds t)) | 2321 | (push (cons key (bibtex-text-in-string bounds t)) |
| 2300 | strings)) | 2322 | strings)) |
| 2301 | (goto-char (bibtex-end-of-text-in-string bounds))) | 2323 | (goto-char (bibtex-end-of-text-in-string bounds))) |
| @@ -2384,6 +2406,7 @@ of a word, all strings are listed. Return completion." | |||
| 2384 | (display-completion-list (all-completions part-of-word | 2406 | (display-completion-list (all-completions part-of-word |
| 2385 | completions))) | 2407 | completions))) |
| 2386 | (message "Making completion list...done") | 2408 | (message "Making completion list...done") |
| 2409 | ;; return value is handled by choose-completion-string-functions | ||
| 2387 | nil)))) | 2410 | nil)))) |
| 2388 | 2411 | ||
| 2389 | (defun bibtex-complete-string-cleanup (str) | 2412 | (defun bibtex-complete-string-cleanup (str) |
| @@ -2629,6 +2652,34 @@ non-nil. | |||
| 2629 | (easy-menu-add bibtex-entry-menu) | 2652 | (easy-menu-add bibtex-entry-menu) |
| 2630 | (run-hooks 'bibtex-mode-hook)) | 2653 | (run-hooks 'bibtex-mode-hook)) |
| 2631 | 2654 | ||
| 2655 | (defun bibtex-field-list (entry-type) | ||
| 2656 | "Return list of allowed fields for entry ENTRY-TYPE. | ||
| 2657 | More specifically, the return value is a cons pair (REQUIRED . OPTIONAL), | ||
| 2658 | where REQUIRED and OPTIONAL are lists of the required and optional field | ||
| 2659 | names for ENTRY-TYPE according to `bibtex-entry-field-alist'." | ||
| 2660 | (let ((e (assoc-string entry-type bibtex-entry-field-alist t)) | ||
| 2661 | required optional) | ||
| 2662 | (unless e | ||
| 2663 | (error "Bibtex entry type %s not defined" entry-type)) | ||
| 2664 | (if (and (member-ignore-case entry-type bibtex-include-OPTcrossref) | ||
| 2665 | (nth 2 e)) | ||
| 2666 | (setq required (nth 0 (nth 2 e)) | ||
| 2667 | optional (nth 1 (nth 2 e))) | ||
| 2668 | (setq required (nth 0 (nth 1 e)) | ||
| 2669 | optional (nth 1 (nth 1 e)))) | ||
| 2670 | (if bibtex-include-OPTkey | ||
| 2671 | (push (list "key" | ||
| 2672 | "Used for reference key creation if author and editor fields are missing" | ||
| 2673 | (if (or (stringp bibtex-include-OPTkey) | ||
| 2674 | (fboundp bibtex-include-OPTkey)) | ||
| 2675 | bibtex-include-OPTkey)) | ||
| 2676 | optional)) | ||
| 2677 | (if (member-ignore-case entry-type bibtex-include-OPTcrossref) | ||
| 2678 | (push '("crossref" "Reference key of the cross-referenced entry") | ||
| 2679 | optional)) | ||
| 2680 | (setq optional (append optional bibtex-user-optional-fields)) | ||
| 2681 | (cons required optional))) | ||
| 2682 | |||
| 2632 | (defun bibtex-entry (entry-type) | 2683 | (defun bibtex-entry (entry-type) |
| 2633 | "Insert a new BibTeX entry. | 2684 | "Insert a new BibTeX entry. |
| 2634 | After insertion it calls the functions in `bibtex-add-entry-hook'." | 2685 | After insertion it calls the functions in `bibtex-add-entry-hook'." |
| @@ -2638,38 +2689,17 @@ After insertion it calls the functions in `bibtex-add-entry-hook'." | |||
| 2638 | bibtex-entry-field-alist | 2689 | bibtex-entry-field-alist |
| 2639 | nil t nil 'bibtex-entry-type-history))) | 2690 | nil t nil 'bibtex-entry-type-history))) |
| 2640 | (list e-t))) | 2691 | (list e-t))) |
| 2641 | (let* (required optional | 2692 | (let ((key (if bibtex-maintain-sorted-entries |
| 2642 | (key (if bibtex-maintain-sorted-entries | 2693 | (bibtex-read-key (format "%s key: " entry-type)))) |
| 2643 | (bibtex-read-key (format "%s key: " entry-type)))) | 2694 | (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)) | 2695 | (unless (bibtex-prepare-new-entry (list key nil entry-type)) |
| 2656 | (error "Entry with key `%s' already exists" key)) | 2696 | (error "Entry with key `%s' already exists" key)) |
| 2657 | (indent-to-column bibtex-entry-offset) | 2697 | (indent-to-column bibtex-entry-offset) |
| 2658 | (insert "@" entry-type (bibtex-entry-left-delimiter)) | 2698 | (insert "@" entry-type (bibtex-entry-left-delimiter)) |
| 2659 | (if key | 2699 | (if key (insert key)) |
| 2660 | (insert key)) | ||
| 2661 | (save-excursion | 2700 | (save-excursion |
| 2662 | (mapcar 'bibtex-make-field required) | 2701 | (mapcar 'bibtex-make-field (car field-list)) |
| 2663 | (if (member entry-type bibtex-include-OPTcrossref) | 2702 | (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 | 2703 | (if bibtex-comma-after-last-field |
| 2674 | (insert ",")) | 2704 | (insert ",")) |
| 2675 | (insert "\n") | 2705 | (insert "\n") |
| @@ -2680,15 +2710,39 @@ After insertion it calls the functions in `bibtex-add-entry-hook'." | |||
| 2680 | (bibtex-autofill-entry)) | 2710 | (bibtex-autofill-entry)) |
| 2681 | (run-hooks 'bibtex-add-entry-hook))) | 2711 | (run-hooks 'bibtex-add-entry-hook))) |
| 2682 | 2712 | ||
| 2713 | (defun bibtex-entry-update () | ||
| 2714 | "Update an existing BibTeX entry. | ||
| 2715 | In the BibTeX entry at point, make new fields for those items that may occur | ||
| 2716 | according to `bibtex-entry-field-alist', but are not yet present." | ||
| 2717 | (interactive) | ||
| 2718 | (save-excursion | ||
| 2719 | (bibtex-beginning-of-entry) | ||
| 2720 | ;; For inserting new fields, we use the fact that | ||
| 2721 | ;; bibtex-parse-entry moves point to the end of the last field. | ||
| 2722 | (let* ((fields-alist (bibtex-parse-entry)) | ||
| 2723 | (field-list (bibtex-field-list | ||
| 2724 | (substring (cdr (assoc "=type=" fields-alist)) | ||
| 2725 | 1))) ; don't want @ | ||
| 2726 | (case-fold-search t)) | ||
| 2727 | (dolist (field (car field-list)) | ||
| 2728 | (unless (bibtex-assoc-regexp (concat "\\`\\(ALT\\)?" (car field) "\\'") | ||
| 2729 | fields-alist) | ||
| 2730 | (bibtex-make-field field))) | ||
| 2731 | (dolist (field (cdr field-list)) | ||
| 2732 | (unless (bibtex-assoc-regexp (concat "\\`\\(OPT\\)?" (car field) "\\'") | ||
| 2733 | fields-alist) | ||
| 2734 | (bibtex-make-optional-field field)))))) | ||
| 2735 | |||
| 2683 | (defun bibtex-parse-entry () | 2736 | (defun bibtex-parse-entry () |
| 2684 | "Parse entry at point, return an alist. | 2737 | "Parse entry at point, return an alist. |
| 2685 | The alist elements have the form (FIELD . TEXT), where FIELD can also be | 2738 | The alist elements have the form (FIELD . TEXT), where FIELD can also be |
| 2686 | the special strings \"=type=\" and \"=key=\"." | 2739 | the special strings \"=type=\" and \"=key=\". For the FIELD \"=key=\" |
| 2740 | TEXT may be nil. Move point to the end of the last field." | ||
| 2687 | (let (alist bounds) | 2741 | (let (alist bounds) |
| 2688 | (when (looking-at bibtex-entry-head) | 2742 | (when (looking-at bibtex-entry-maybe-empty-head) |
| 2689 | (push (cons "=type=" (match-string bibtex-type-in-head)) alist) | 2743 | (push (cons "=type=" (match-string bibtex-type-in-head)) alist) |
| 2690 | (push (cons "=key=" (match-string bibtex-key-in-head)) alist) | 2744 | (push (cons "=key=" (match-string bibtex-key-in-head)) alist) |
| 2691 | (goto-char (match-end bibtex-key-in-head)) | 2745 | (goto-char (match-end 0)) |
| 2692 | (while (setq bounds (bibtex-parse-field bibtex-field-name)) | 2746 | (while (setq bounds (bibtex-parse-field bibtex-field-name)) |
| 2693 | (push (cons (bibtex-name-in-field bounds) | 2747 | (push (cons (bibtex-name-in-field bounds) |
| 2694 | (bibtex-text-in-field-bounds bounds)) | 2748 | (bibtex-text-in-field-bounds bounds)) |
| @@ -2744,7 +2798,7 @@ the special strings \"=type=\" and \"=key=\"." | |||
| 2744 | (let* ((name (buffer-substring | 2798 | (let* ((name (buffer-substring |
| 2745 | (if (looking-at "ALT\\|OPT") (match-end 0) (point)) | 2799 | (if (looking-at "ALT\\|OPT") (match-end 0) (point)) |
| 2746 | (bibtex-end-of-name-in-field bounds))) | 2800 | (bibtex-end-of-name-in-field bounds))) |
| 2747 | (text (assoc-ignore-case name other))) | 2801 | (text (assoc-string name other t))) |
| 2748 | (goto-char (bibtex-start-of-text-in-field bounds)) | 2802 | (goto-char (bibtex-start-of-text-in-field bounds)) |
| 2749 | (if (not (and (looking-at bibtex-empty-field-re) text)) | 2803 | (if (not (and (looking-at bibtex-empty-field-re) text)) |
| 2750 | (goto-char (bibtex-end-of-field bounds)) | 2804 | (goto-char (bibtex-end-of-field bounds)) |
| @@ -2774,28 +2828,15 @@ the special strings \"=type=\" and \"=key=\"." | |||
| 2774 | (looking-at "OPT\\|ALT")) | 2828 | (looking-at "OPT\\|ALT")) |
| 2775 | (match-end 0) mb) | 2829 | (match-end 0) mb) |
| 2776 | (bibtex-end-of-name-in-field bounds))) | 2830 | (bibtex-end-of-name-in-field bounds))) |
| 2777 | (entry-type (progn (re-search-backward | 2831 | (field-list (bibtex-field-list (progn (re-search-backward |
| 2778 | bibtex-entry-maybe-empty-head nil t) | 2832 | bibtex-entry-maybe-empty-head nil t) |
| 2779 | (bibtex-type-in-head))) | 2833 | (bibtex-type-in-head)))) |
| 2780 | (entry-list (assoc-ignore-case entry-type | 2834 | (comment (assoc-string field-name |
| 2781 | bibtex-entry-field-alist)) | 2835 | (append (car field-list) |
| 2782 | (c-r-list (elt entry-list 2)) | 2836 | (cdr field-list)) |
| 2783 | (req-opt-list (if (and (member entry-type | 2837 | t))) |
| 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 | 2838 | (if comment |
| 2798 | (message (elt comment 1)) | 2839 | (message (nth 1 comment)) |
| 2799 | (message "No comment available"))))) | 2840 | (message "No comment available"))))) |
| 2800 | 2841 | ||
| 2801 | (defun bibtex-make-field (field &optional called-by-yank) | 2842 | (defun bibtex-make-field (field &optional called-by-yank) |
| @@ -2804,24 +2845,13 @@ FIELD is either a string or a list of the form | |||
| 2804 | \(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in | 2845 | \(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in |
| 2805 | `bibtex-entry-field-alist'." | 2846 | `bibtex-entry-field-alist'." |
| 2806 | (interactive | 2847 | (interactive |
| 2807 | (list (let* ((entry-type | 2848 | (list (let ((completion-ignore-case t) |
| 2808 | (save-excursion | 2849 | (field-list (bibtex-field-list |
| 2809 | (bibtex-enclosing-entry-maybe-empty-head) | 2850 | (save-excursion |
| 2810 | (bibtex-type-in-head))) | 2851 | (bibtex-enclosing-entry-maybe-empty-head) |
| 2811 | ;; "preliminary" completion list | 2852 | (bibtex-type-in-head))))) |
| 2812 | (fl (nth 1 (assoc-ignore-case | 2853 | (completing-read "BibTeX field name: " |
| 2813 | entry-type bibtex-entry-field-alist))) | 2854 | (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)))) | 2855 | nil nil nil bibtex-field-history)))) |
| 2826 | (unless (consp field) | 2856 | (unless (consp field) |
| 2827 | (setq field (list field))) | 2857 | (setq field (list field))) |
| @@ -2848,8 +2878,9 @@ FIELD is either a string or a list of the form | |||
| 2848 | ((fboundp init) | 2878 | ((fboundp init) |
| 2849 | (insert (funcall init))))) | 2879 | (insert (funcall init))))) |
| 2850 | (if (not called-by-yank) (insert (bibtex-field-right-delimiter))) | 2880 | (if (not called-by-yank) (insert (bibtex-field-right-delimiter))) |
| 2851 | (if (interactive-p) | 2881 | (when (interactive-p) |
| 2852 | (forward-char -1))) | 2882 | (forward-char -1) |
| 2883 | (bibtex-print-help-message))) | ||
| 2853 | 2884 | ||
| 2854 | (defun bibtex-beginning-of-entry () | 2885 | (defun bibtex-beginning-of-entry () |
| 2855 | "Move to beginning of BibTeX entry (beginning of line). | 2886 | "Move to beginning of BibTeX entry (beginning of line). |
| @@ -2982,13 +3013,14 @@ the entries of the BibTeX buffer. Return nil if no entry found." | |||
| 2982 | "\\(OPT\\)?crossref" t))) | 3013 | "\\(OPT\\)?crossref" t))) |
| 2983 | (list key | 3014 | (list key |
| 2984 | (if bounds (bibtex-text-in-field-bounds bounds t)) | 3015 | (if bounds (bibtex-text-in-field-bounds bounds t)) |
| 2985 | entry-name)))) | 3016 | entry-name))) |
| 2986 | (list key nil entry-name))))) | 3017 | (list key nil entry-name)))))) |
| 2987 | 3018 | ||
| 2988 | (defun bibtex-lessp (index1 index2) | 3019 | (defun bibtex-lessp (index1 index2) |
| 2989 | "Predicate for sorting BibTeX entries with indices INDEX1 and INDEX2. | 3020 | "Predicate for sorting BibTeX entries with indices INDEX1 and INDEX2. |
| 2990 | Each index is a list (KEY CROSSREF-KEY ENTRY-NAME). | 3021 | Each index is a list (KEY CROSSREF-KEY ENTRY-NAME). |
| 2991 | The predicate depends on the variable `bibtex-maintain-sorted-entries'." | 3022 | The predicate depends on the variable `bibtex-maintain-sorted-entries'. |
| 3023 | If its value is nil use plain sorting." | ||
| 2992 | (cond ((not index1) (not index2)) ; indices can be nil | 3024 | (cond ((not index1) (not index2)) ; indices can be nil |
| 2993 | ((not index2) nil) | 3025 | ((not index2) nil) |
| 2994 | ((equal bibtex-maintain-sorted-entries 'crossref) | 3026 | ((equal bibtex-maintain-sorted-entries 'crossref) |
| @@ -3017,12 +3049,10 @@ The predicate depends on the variable `bibtex-maintain-sorted-entries'." | |||
| 3017 | (defun bibtex-sort-buffer () | 3049 | (defun bibtex-sort-buffer () |
| 3018 | "Sort BibTeX buffer alphabetically by key. | 3050 | "Sort BibTeX buffer alphabetically by key. |
| 3019 | The predicate for sorting is defined via `bibtex-maintain-sorted-entries'. | 3051 | The predicate for sorting is defined via `bibtex-maintain-sorted-entries'. |
| 3020 | Text outside of BibTeX entries is not affected. If | 3052 | If its value is nil use plain sorting. Text outside of BibTeX entries is not |
| 3021 | `bibtex-sort-ignore-string-entries' is non-nil, @String entries will be | 3053 | affected. If `bibtex-sort-ignore-string-entries' is non-nil, @String entries |
| 3022 | ignored." | 3054 | will be ignored." |
| 3023 | (interactive) | 3055 | (interactive) |
| 3024 | (unless bibtex-maintain-sorted-entries | ||
| 3025 | (error "You must choose a sorting scheme")) | ||
| 3026 | (save-restriction | 3056 | (save-restriction |
| 3027 | (narrow-to-region (bibtex-beginning-of-first-entry) | 3057 | (narrow-to-region (bibtex-beginning-of-first-entry) |
| 3028 | (save-excursion (goto-char (point-max)) | 3058 | (save-excursion (goto-char (point-max)) |
| @@ -3212,8 +3242,8 @@ Returns t if test was successful, nil otherwise." | |||
| 3212 | (let* ((entry-list (progn | 3242 | (let* ((entry-list (progn |
| 3213 | (goto-char beg) | 3243 | (goto-char beg) |
| 3214 | (bibtex-search-entry nil end) | 3244 | (bibtex-search-entry nil end) |
| 3215 | (assoc-ignore-case (bibtex-type-in-head) | 3245 | (assoc-string (bibtex-type-in-head) |
| 3216 | bibtex-entry-field-alist))) | 3246 | bibtex-entry-field-alist t))) |
| 3217 | (req (copy-sequence (elt (elt entry-list 1) 0))) | 3247 | (req (copy-sequence (elt (elt entry-list 1) 0))) |
| 3218 | (creq (copy-sequence (elt (elt entry-list 2) 0))) | 3248 | (creq (copy-sequence (elt (elt entry-list 2) 0))) |
| 3219 | crossref-there bounds) | 3249 | crossref-there bounds) |
| @@ -3229,8 +3259,8 @@ Returns t if test was successful, nil otherwise." | |||
| 3229 | (push (list (bibtex-current-line) | 3259 | (push (list (bibtex-current-line) |
| 3230 | "Questionable month field") | 3260 | "Questionable month field") |
| 3231 | error-list)) | 3261 | error-list)) |
| 3232 | (setq req (delete (assoc-ignore-case field-name req) req) | 3262 | (setq req (delete (assoc-string field-name req t) req) |
| 3233 | creq (delete (assoc-ignore-case field-name creq) creq)) | 3263 | creq (delete (assoc-string field-name creq t) creq)) |
| 3234 | (if (equal field-name "crossref") | 3264 | (if (equal field-name "crossref") |
| 3235 | (setq crossref-there t)))) | 3265 | (setq crossref-there t)))) |
| 3236 | (if crossref-there | 3266 | (if crossref-there |
| @@ -3523,27 +3553,30 @@ At end of the cleaning process, the functions in | |||
| 3523 | (match-end bibtex-key-in-head))) | 3553 | (match-end bibtex-key-in-head))) |
| 3524 | (insert key)) | 3554 | (insert key)) |
| 3525 | ;; sorting | 3555 | ;; sorting |
| 3526 | (let* ((start (bibtex-beginning-of-entry)) | 3556 | (unless called-by-reformat |
| 3527 | (end (progn (bibtex-end-of-entry) | 3557 | (let* ((start (bibtex-beginning-of-entry)) |
| 3528 | (if (re-search-forward | 3558 | (end (progn (bibtex-end-of-entry) |
| 3529 | bibtex-entry-maybe-empty-head nil 'move) | 3559 | (if (re-search-forward |
| 3530 | (goto-char (match-beginning 0))) | 3560 | bibtex-entry-maybe-empty-head nil 'move) |
| 3531 | (point))) | 3561 | (goto-char (match-beginning 0))) |
| 3532 | (entry (buffer-substring start end)) | 3562 | (point))) |
| 3533 | (index (progn (goto-char start) | 3563 | (entry (buffer-substring start end)) |
| 3534 | (bibtex-entry-index)))) | 3564 | (index (progn (goto-char start) |
| 3535 | (delete-region start end) | 3565 | (bibtex-entry-index))) |
| 3536 | (unless (prog1 (or called-by-reformat | 3566 | no-error) |
| 3537 | (if (and bibtex-maintain-sorted-entries | 3567 | (if (and bibtex-maintain-sorted-entries |
| 3538 | (not (and bibtex-sort-ignore-string-entries | 3568 | (not (and bibtex-sort-ignore-string-entries |
| 3539 | (equal entry-type "string")))) | 3569 | (equal entry-type "string")))) |
| 3540 | (bibtex-prepare-new-entry index) | 3570 | (progn |
| 3541 | (not (bibtex-find-entry (car index))))) | 3571 | (delete-region start end) |
| 3542 | (insert entry) | 3572 | (setq no-error (bibtex-prepare-new-entry index)) |
| 3543 | (forward-char -1) | 3573 | (insert entry) |
| 3544 | (bibtex-beginning-of-entry) ; moves backward | 3574 | (forward-char -1) |
| 3545 | (re-search-forward bibtex-entry-head)) | 3575 | (bibtex-beginning-of-entry) ; moves backward |
| 3546 | (error "New inserted entry yields duplicate key"))) | 3576 | (re-search-forward bibtex-entry-head)) |
| 3577 | (setq no-error (bibtex-find-entry (car index)))) | ||
| 3578 | (unless no-error | ||
| 3579 | (error "New inserted entry yields duplicate key")))) | ||
| 3547 | ;; final clean up | 3580 | ;; final clean up |
| 3548 | (unless called-by-reformat | 3581 | (unless called-by-reformat |
| 3549 | (save-excursion | 3582 | (save-excursion |
| @@ -3621,91 +3654,89 @@ If `bibtex-align-at-equal-sign' is non-nil, align equal signs, too." | |||
| 3621 | (indent-to-column bibtex-entry-offset) | 3654 | (indent-to-column bibtex-entry-offset) |
| 3622 | (goto-char pnt))) | 3655 | (goto-char pnt))) |
| 3623 | 3656 | ||
| 3624 | (defun bibtex-reformat (&optional additional-options called-by-convert-alien) | 3657 | (defun bibtex-realign () |
| 3658 | "Realign BibTeX entries such that they are separated by one blank line." | ||
| 3659 | (goto-char (point-min)) | ||
| 3660 | (let ((case-fold-search t)) | ||
| 3661 | (when (looking-at bibtex-valid-entry-whitespace-re) | ||
| 3662 | (replace-match "\\1")) | ||
| 3663 | (while (re-search-forward bibtex-valid-entry-whitespace-re nil t) | ||
| 3664 | (replace-match "\n\n\\1")))) | ||
| 3665 | |||
| 3666 | (defun bibtex-reformat (&optional read-options) | ||
| 3625 | "Reformat all BibTeX entries in buffer or region. | 3667 | "Reformat all BibTeX entries in buffer or region. |
| 3626 | With prefix argument, read options for reformatting from minibuffer. | 3668 | With prefix argument, read options for reformatting from minibuffer. |
| 3627 | With \\[universal-argument] \\[universal-argument] prefix argument, reuse previous answers (if any) again. | 3669 | With \\[universal-argument] \\[universal-argument] prefix argument, reuse previous answers (if any) again. |
| 3628 | If mark is active it reformats entries in region, if not in whole buffer." | 3670 | If mark is active reformat entries in region, if not in whole buffer." |
| 3629 | (interactive "*P") | 3671 | (interactive "*P") |
| 3630 | (let* ((pnt (point)) | 3672 | (let* ((pnt (point)) |
| 3631 | (use-previous-options | 3673 | (use-previous-options |
| 3632 | (and (equal (prefix-numeric-value additional-options) 16) | 3674 | (and (equal (prefix-numeric-value read-options) 16) |
| 3633 | (or bibtex-reformat-previous-options | 3675 | (or bibtex-reformat-previous-options |
| 3634 | bibtex-reformat-previous-reference-keys))) | 3676 | bibtex-reformat-previous-reference-keys))) |
| 3635 | (bibtex-entry-format | 3677 | (bibtex-entry-format |
| 3636 | (if additional-options | 3678 | (if read-options |
| 3637 | (if use-previous-options | 3679 | (if use-previous-options |
| 3638 | bibtex-reformat-previous-options | 3680 | bibtex-reformat-previous-options |
| 3639 | (setq bibtex-reformat-previous-options | 3681 | (setq bibtex-reformat-previous-options |
| 3640 | (delq nil (list | 3682 | (mapcar (lambda (option) |
| 3641 | (if (or called-by-convert-alien | 3683 | (if (y-or-n-p (car option)) (cdr option))) |
| 3642 | (y-or-n-p "Realign entries (recommended)? ")) | 3684 | `(("Realign entries (recommended)? " . 'realign) |
| 3643 | 'realign) | 3685 | ("Remove empty optional and alternative fields? " . 'opts-or-alts) |
| 3644 | (if (y-or-n-p "Remove empty optional and alternative fields? ") | 3686 | ("Remove delimiters around pure numerical fields? " . 'numerical-fields) |
| 3645 | 'opts-or-alts) | 3687 | (,(concat (if bibtex-comma-after-last-field "Insert" "Remove") |
| 3646 | (if (y-or-n-p "Remove delimiters around pure numerical fields? ") | 3688 | " comma at end of entry? ") . 'last-comma) |
| 3647 | 'numerical-fields) | 3689 | ("Replace double page dashes by single ones? " . 'page-dashes) |
| 3648 | (if (y-or-n-p (concat (if bibtex-comma-after-last-field "Insert" "Remove") | 3690 | ("Force delimiters? " . 'delimiters) |
| 3649 | " comma at end of entry? ")) | 3691 | ("Unify case of entry types and field names? " . 'unify-case))))) |
| 3650 | 'last-comma) | ||
| 3651 | (if (y-or-n-p "Replace double page dashes by single ones? ") | ||
| 3652 | 'page-dashes) | ||
| 3653 | (if (y-or-n-p "Force delimiters? ") | ||
| 3654 | 'delimiters) | ||
| 3655 | (if (y-or-n-p "Unify case of entry types and field names? ") | ||
| 3656 | 'unify-case))))) | ||
| 3657 | '(realign))) | 3692 | '(realign))) |
| 3658 | (reformat-reference-keys (if additional-options | 3693 | (reformat-reference-keys |
| 3659 | (if use-previous-options | 3694 | (if read-options |
| 3660 | bibtex-reformat-previous-reference-keys | 3695 | (if use-previous-options |
| 3661 | (setq bibtex-reformat-previous-reference-keys | 3696 | bibtex-reformat-previous-reference-keys |
| 3662 | (y-or-n-p "Generate new reference keys automatically? "))))) | 3697 | (setq bibtex-reformat-previous-reference-keys |
| 3663 | bibtex-autokey-edit-before-use | 3698 | (y-or-n-p "Generate new reference keys automatically? "))))) |
| 3664 | (bibtex-sort-ignore-string-entries t) | ||
| 3665 | (start-point (if (bibtex-mark-active) | 3699 | (start-point (if (bibtex-mark-active) |
| 3666 | (region-beginning) | 3700 | (region-beginning) |
| 3667 | (bibtex-beginning-of-first-entry) | 3701 | (point-min))) |
| 3668 | (bibtex-skip-to-valid-entry) | ||
| 3669 | (point))) | ||
| 3670 | (end-point (if (bibtex-mark-active) | 3702 | (end-point (if (bibtex-mark-active) |
| 3671 | (region-end) | 3703 | (region-end) |
| 3672 | (point-max)))) | 3704 | (point-max))) |
| 3705 | (bibtex-sort-ignore-string-entries t) | ||
| 3706 | bibtex-autokey-edit-before-use) | ||
| 3707 | |||
| 3673 | (save-restriction | 3708 | (save-restriction |
| 3674 | (narrow-to-region start-point end-point) | 3709 | (narrow-to-region start-point end-point) |
| 3675 | (when (memq 'realign bibtex-entry-format) | 3710 | (if (memq 'realign bibtex-entry-format) |
| 3676 | (goto-char (point-min)) | 3711 | (bibtex-realign)) |
| 3677 | (while (re-search-forward bibtex-valid-entry-whitespace-re nil t) | ||
| 3678 | (replace-match "\n\\1"))) | ||
| 3679 | (goto-char start-point) | 3712 | (goto-char start-point) |
| 3680 | (bibtex-progress-message "Formatting" 1) | 3713 | (bibtex-progress-message "Formatting" 1) |
| 3681 | (bibtex-map-entries (lambda (key beg end) | 3714 | (bibtex-map-entries (lambda (key beg end) |
| 3682 | (bibtex-progress-message) | 3715 | (bibtex-progress-message) |
| 3683 | (bibtex-clean-entry reformat-reference-keys t) | 3716 | (bibtex-clean-entry reformat-reference-keys t))) |
| 3684 | (when (memq 'realign bibtex-entry-format) | 3717 | (when (memq 'realign bibtex-entry-format) |
| 3685 | (goto-char end) | 3718 | (bibtex-delete-whitespace) |
| 3686 | (bibtex-delete-whitespace) | 3719 | (open-line (if (eobp) 1 2))) |
| 3687 | (open-line 2)))) | ||
| 3688 | (bibtex-progress-message 'done)) | 3720 | (bibtex-progress-message 'done)) |
| 3689 | (when (and reformat-reference-keys | 3721 | (when (and reformat-reference-keys |
| 3690 | bibtex-maintain-sorted-entries | 3722 | bibtex-maintain-sorted-entries) |
| 3691 | (not called-by-convert-alien)) | 3723 | (bibtex-progress-message "Sorting" 1) |
| 3692 | (bibtex-sort-buffer) | 3724 | (bibtex-sort-buffer) |
| 3693 | (kill-local-variable 'bibtex-reference-keys)) | 3725 | (kill-local-variable 'bibtex-reference-keys) |
| 3726 | (bibtex-progress-message 'done)) | ||
| 3694 | (goto-char pnt))) | 3727 | (goto-char pnt))) |
| 3695 | 3728 | ||
| 3696 | (defun bibtex-convert-alien (&optional do-additional-reformatting) | 3729 | (defun bibtex-convert-alien (&optional read-options) |
| 3697 | "Convert an alien BibTeX buffer to be fully usable by BibTeX mode. | 3730 | "Convert an alien BibTeX buffer to be fully usable by BibTeX mode. |
| 3698 | If a file does not conform with some standards used by BibTeX mode, | 3731 | If a file does not conform with all standards used by BibTeX mode, |
| 3699 | some of the high-level features of BibTeX mode will not be available. | 3732 | some of the high-level features of BibTeX mode will not be available. |
| 3700 | This function tries to convert current buffer to conform with these standards. | 3733 | This function tries to convert current buffer to conform with these standards. |
| 3701 | With prefix argument DO-ADDITIONAL-REFORMATTING | 3734 | With prefix argument READ-OPTIONS non-nil, read options for reformatting |
| 3702 | non-nil, read options for reformatting entries from minibuffer." | 3735 | entries from minibuffer." |
| 3703 | (interactive "*P") | 3736 | (interactive "*P") |
| 3704 | (message "Starting to validate buffer...") | 3737 | (message "Starting to validate buffer...") |
| 3705 | (sit-for 1 nil t) | 3738 | (sit-for 1 nil t) |
| 3706 | (goto-char (point-min)) | 3739 | (bibtex-realign) |
| 3707 | (while (re-search-forward "[ \t\n]+@" nil t) | ||
| 3708 | (replace-match "\n@")) | ||
| 3709 | (message | 3740 | (message |
| 3710 | "If errors occur, correct them and call `bibtex-convert-alien' again") | 3741 | "If errors occur, correct them and call `bibtex-convert-alien' again") |
| 3711 | (sit-for 5 nil t) | 3742 | (sit-for 5 nil t) |
| @@ -3714,10 +3745,7 @@ non-nil, read options for reformatting entries from minibuffer." | |||
| 3714 | (bibtex-validate)) | 3745 | (bibtex-validate)) |
| 3715 | (message "Starting to reformat entries...") | 3746 | (message "Starting to reformat entries...") |
| 3716 | (sit-for 2 nil t) | 3747 | (sit-for 2 nil t) |
| 3717 | (bibtex-reformat do-additional-reformatting t) | 3748 | (bibtex-reformat read-options) |
| 3718 | (when bibtex-maintain-sorted-entries | ||
| 3719 | (message "Starting to sort buffer...") | ||
| 3720 | (bibtex-sort-buffer)) | ||
| 3721 | (goto-char (point-max)) | 3749 | (goto-char (point-max)) |
| 3722 | (message "Buffer is now parsable. Please save it."))) | 3750 | (message "Buffer is now parsable. Please save it."))) |
| 3723 | 3751 | ||
| @@ -3890,5 +3918,5 @@ is outside key or BibTeX field." | |||
| 3890 | 3918 | ||
| 3891 | (provide 'bibtex) | 3919 | (provide 'bibtex) |
| 3892 | 3920 | ||
| 3893 | ;;; arch-tag: ee2be3af-caad-427f-b42a-d20fad630d04 | 3921 | ;; arch-tag: ee2be3af-caad-427f-b42a-d20fad630d04 |
| 3894 | ;;; bibtex.el ends here | 3922 | ;;; bibtex.el ends here |