1 |
;;; bibtex.el --- BibTeX mode for GNU Emacs |
;;; bibtex.el --- BibTeX mode for GNU Emacs |
2 |
|
|
3 |
;; Copyright (C) 1992,94,95,96,97,98,1999,2003 Free Software Foundation, Inc. |
;; Copyright (C) 1992,94,95,96,97,98,1999,2003,2004 |
4 |
|
;; Free Software Foundation, Inc. |
5 |
|
|
6 |
;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de> |
;; Author: Stefan Schoef <schoef@offis.uni-oldenburg.de> |
7 |
;; Bengt Martensson <bengt@mathematik.uni-Bremen.de> |
;; Bengt Martensson <bengt@mathematik.uni-Bremen.de> |
812 |
(define-key km "\C-c\M-y" 'bibtex-yank-pop) |
(define-key km "\C-c\M-y" 'bibtex-yank-pop) |
813 |
(define-key km "\C-c\C-d" 'bibtex-empty-field) |
(define-key km "\C-c\C-d" 'bibtex-empty-field) |
814 |
(define-key km "\C-c\C-f" 'bibtex-make-field) |
(define-key km "\C-c\C-f" 'bibtex-make-field) |
815 |
|
(define-key km "\C-c\C-u" 'bibtex-entry-update) |
816 |
(define-key km "\C-c$" 'bibtex-ispell-abstract) |
(define-key km "\C-c$" 'bibtex-ispell-abstract) |
817 |
(define-key km "\M-\C-a" 'bibtex-beginning-of-entry) |
(define-key km "\M-\C-a" 'bibtex-beginning-of-entry) |
818 |
(define-key km "\M-\C-e" 'bibtex-end-of-entry) |
(define-key km "\M-\C-e" 'bibtex-end-of-entry) |
1124 |
'(bibtex-mode "@\\S(*\\s(" "\\s)" nil bibtex-hs-forward-sexp nil)) |
'(bibtex-mode "@\\S(*\\s(" "\\s)" nil bibtex-hs-forward-sexp nil)) |
1125 |
|
|
1126 |
|
|
|
(defconst bibtex-braced-string-syntax-table |
|
|
(let ((st (make-syntax-table))) |
|
|
(modify-syntax-entry ?\{ "(}" st) |
|
|
(modify-syntax-entry ?\} "){" st) |
|
|
(modify-syntax-entry ?\[ "." st) |
|
|
(modify-syntax-entry ?\] "." st) |
|
|
(modify-syntax-entry ?\( "." st) |
|
|
(modify-syntax-entry ?\) "." st) |
|
|
(modify-syntax-entry ?\\ "." st) |
|
|
(modify-syntax-entry ?\" "." st) |
|
|
st) |
|
|
"Syntax-table to parse matched braces.") |
|
|
|
|
|
(defconst bibtex-quoted-string-syntax-table |
|
|
(let ((st (make-syntax-table))) |
|
|
(modify-syntax-entry ?\\ "\\" st) |
|
|
(modify-syntax-entry ?\" "\"" st) |
|
|
st) |
|
|
"Syntax-table to parse matched quotes.") |
|
|
|
|
|
(defun bibtex-parse-field-string () |
|
|
"Parse a field string enclosed by braces or quotes. |
|
|
If a syntactically correct string is found, a pair containing the start and |
|
|
end position of the field string is returned, nil otherwise." |
|
|
(let ((end-point |
|
|
(or (and (eq (following-char) ?\") |
|
|
(save-excursion |
|
|
(with-syntax-table bibtex-quoted-string-syntax-table |
|
|
(forward-sexp 1)) |
|
|
(point))) |
|
|
(and (eq (following-char) ?\{) |
|
|
(save-excursion |
|
|
(with-syntax-table bibtex-braced-string-syntax-table |
|
|
(forward-sexp 1)) |
|
|
(point)))))) |
|
|
(if end-point |
|
|
(cons (point) end-point)))) |
|
|
|
|
1127 |
(defun bibtex-parse-association (parse-lhs parse-rhs) |
(defun bibtex-parse-association (parse-lhs parse-rhs) |
1128 |
"Parse a string of the format <left-hand-side = right-hand-side>. |
"Parse a string of the format <left-hand-side = right-hand-side>. |
1129 |
The functions PARSE-LHS and PARSE-RHS are used to parse the corresponding |
The functions PARSE-LHS and PARSE-RHS are used to parse the corresponding |
1163 |
;; Now try again. |
;; Now try again. |
1164 |
(bibtex-parse-field-name)))) |
(bibtex-parse-field-name)))) |
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 |
|
|
1204 |
(defun bibtex-parse-field-text () |
(defun bibtex-parse-field-text () |
1205 |
"Parse the text part of a BibTeX field. |
"Parse the text part of a BibTeX field. |
1206 |
The text part is either a string, or an empty string, or a constant followed |
The text part is either a string, or an empty string, or a constant followed |
1412 |
(let ((content (buffer-substring-no-properties (nth 0 (cdr bounds)) |
(let ((content (buffer-substring-no-properties (nth 0 (cdr bounds)) |
1413 |
(nth 1 (cdr bounds))))) |
(nth 1 (cdr bounds))))) |
1414 |
(if (and remove-delim |
(if (and remove-delim |
1415 |
(string-match "\\`{\\(.*\\)}\\'" content)) |
(string-match "\\`[{\"]\\(.*\\)[}\"]\\'" content)) |
1416 |
(substring content (match-beginning 1) (match-end 1)) |
(substring content (match-beginning 1) (match-end 1)) |
1417 |
content))) |
content))) |
1418 |
|
|
1457 |
(setq list (cdr list))) |
(setq list (cdr list))) |
1458 |
list)) |
list)) |
1459 |
|
|
|
(defun bibtex-assoc-of-regexp (string alist) |
|
|
"Return non-nil if STRING is exactly matched by the car of an |
|
|
element of ALIST (case ignored). The value is actually the element |
|
|
of LIST whose car matches STRING." |
|
|
(let ((case-fold-search t)) |
|
|
(while (and alist |
|
|
(not (string-match (concat "\\`\\(?:" (caar alist) "\\)\\'") string))) |
|
|
(setq alist (cdr alist))) |
|
|
(car alist))) |
|
|
|
|
1460 |
(defun bibtex-skip-to-valid-entry (&optional backward) |
(defun bibtex-skip-to-valid-entry (&optional backward) |
1461 |
"Unless at beginning of a valid BibTeX entry, move point to beginning of the |
"Unless at beginning of a valid BibTeX entry, move point to beginning of the |
1462 |
next valid one. With optional argument BACKWARD non-nil, move backward to |
next valid one. With optional argument BACKWARD non-nil, move backward to |
1502 |
(save-excursion |
(save-excursion |
1503 |
(if (or (and (not bibtex-sort-ignore-string-entries) |
(if (or (and (not bibtex-sort-ignore-string-entries) |
1504 |
(string-equal "string" (downcase entry-type))) |
(string-equal "string" (downcase entry-type))) |
1505 |
(assoc-ignore-case entry-type bibtex-entry-field-alist)) |
(assoc-string entry-type bibtex-entry-field-alist t)) |
1506 |
(funcall fun key beg end))) |
(funcall fun key beg end))) |
1507 |
(goto-char end))))) |
(goto-char end))))) |
1508 |
|
|
1511 |
If FLAG is a string, the message is initialized (in this case a |
If FLAG is a string, the message is initialized (in this case a |
1512 |
value for INTERVAL may be given as well (if not this is set to 5)). |
value for INTERVAL may be given as well (if not this is set to 5)). |
1513 |
If FLAG is done, the message is deinitialized. |
If FLAG is done, the message is deinitialized. |
1514 |
If FLAG is absent, a message is echoed if point was incremented |
If FLAG is nil, a message is echoed if point was incremented at least |
1515 |
at least INTERVAL percent since last message was echoed." |
`bibtex-progress-interval' percent since last message was echoed." |
1516 |
(cond ((stringp flag) |
(cond ((stringp flag) |
1517 |
(setq bibtex-progress-lastmes flag) |
(setq bibtex-progress-lastmes flag) |
1518 |
(setq bibtex-progress-interval (or interval 5) |
(setq bibtex-progress-interval (or interval 5) |
1677 |
"Try to avoid point being at end of a BibTeX field." |
"Try to avoid point being at end of a BibTeX field." |
1678 |
(end-of-line) |
(end-of-line) |
1679 |
(skip-chars-backward " \t") |
(skip-chars-backward " \t") |
1680 |
(cond ((= (preceding-char) ?,) |
(if (= (preceding-char) ?,) |
1681 |
(forward-char -2))) |
(forward-char -2)) |
1682 |
(cond ((or (= (preceding-char) ?}) |
(if (or (= (preceding-char) ?}) |
1683 |
(= (preceding-char) ?\")) |
(= (preceding-char) ?\")) |
1684 |
(forward-char -1)))) |
(forward-char -1))) |
1685 |
|
|
1686 |
(defun bibtex-enclosing-field (&optional noerr) |
(defun bibtex-enclosing-field (&optional noerr) |
1687 |
"Search for BibTeX field enclosing point. Point moves to end of field. |
"Search for BibTeX field enclosing point. Point moves to end of field. |
1741 |
(error "Unknown tag field: %s. Please submit a bug report" |
(error "Unknown tag field: %s. Please submit a bug report" |
1742 |
bibtex-last-kill-command)))))) |
bibtex-last-kill-command)))))) |
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 |
|
|
1753 |
(defun bibtex-format-entry () |
(defun bibtex-format-entry () |
1754 |
"Helper function for `bibtex-clean-entry'. |
"Helper function for `bibtex-clean-entry'. |
1755 |
Formats current entry according to variable `bibtex-entry-format'." |
Formats current entry according to variable `bibtex-entry-format'." |
1764 |
unify-case inherit-booktitle) |
unify-case inherit-booktitle) |
1765 |
bibtex-entry-format)) |
bibtex-entry-format)) |
1766 |
crossref-key bounds alternatives-there non-empty-alternative |
crossref-key bounds alternatives-there non-empty-alternative |
1767 |
entry-list req creq field-done field-list) |
entry-list req-field-list field-done field-list) |
1768 |
|
|
1769 |
;; identify entry type |
;; identify entry type |
1770 |
(goto-char (point-min)) |
(goto-char (point-min)) |
1771 |
(re-search-forward bibtex-entry-type) |
(re-search-forward bibtex-entry-type) |
1772 |
(let ((beg-type (1+ (match-beginning 0))) |
(let ((beg-type (1+ (match-beginning 0))) |
1773 |
(end-type (match-end 0))) |
(end-type (match-end 0))) |
1774 |
(setq entry-list (assoc-ignore-case (buffer-substring-no-properties |
(setq entry-list (assoc-string (buffer-substring-no-properties |
1775 |
beg-type end-type) |
beg-type end-type) |
1776 |
bibtex-entry-field-alist) |
bibtex-entry-field-alist |
1777 |
req (nth 0 (nth 1 entry-list)) ; required part |
t)) |
|
creq (nth 0 (nth 2 entry-list))) ; crossref part |
|
1778 |
|
|
1779 |
;; unify case of entry name |
;; unify case of entry name |
1780 |
(when (memq 'unify-case format) |
(when (memq 'unify-case format) |
1791 |
;; determine if entry has crossref field and if at least |
;; determine if entry has crossref field and if at least |
1792 |
;; one alternative is non-empty |
;; one alternative is non-empty |
1793 |
(goto-char (point-min)) |
(goto-char (point-min)) |
1794 |
(while (setq bounds (bibtex-search-forward-field |
(let* ((fields-alist (bibtex-parse-entry)) |
1795 |
bibtex-field-name)) |
(case-fold-search t) |
1796 |
(goto-char (bibtex-start-of-name-in-field bounds)) |
(field (bibtex-assoc-regexp "\\`\\(OPT\\)?crossref\\'" |
1797 |
(cond ((looking-at "ALT") |
fields-alist))) |
1798 |
(setq alternatives-there t) |
(setq crossref-key (and field |
1799 |
(goto-char (bibtex-start-of-text-in-field bounds)) |
(not (string-match bibtex-empty-field-re |
1800 |
(if (not (looking-at bibtex-empty-field-re)) |
(cdr field))) |
1801 |
(setq non-empty-alternative t))) |
(cdr field)) |
1802 |
((and (looking-at "\\(OPT\\)?crossref\\>") |
req-field-list (if crossref-key |
1803 |
(progn (goto-char (bibtex-start-of-text-in-field bounds)) |
(nth 0 (nth 2 entry-list)) ; crossref part |
1804 |
(not (looking-at bibtex-empty-field-re)))) |
(nth 0 (nth 1 entry-list)))) ; required part |
1805 |
(setq crossref-key |
|
1806 |
(bibtex-text-in-field-bounds bounds t)))) |
(dolist (rfield req-field-list) |
1807 |
(goto-char (bibtex-end-of-field bounds))) |
(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 |
|
|
1820 |
(if (and alternatives-there |
(if (and alternatives-there |
1821 |
(not non-empty-alternative) |
(not non-empty-alternative) |
1822 |
(memq 'required-fields format)) |
(memq 'required-fields format)) |
1844 |
;; quite some redundancy compared with what we need to do |
;; quite some redundancy compared with what we need to do |
1845 |
;; anyway. So for speed-up we avoid using them. |
;; anyway. So for speed-up we avoid using them. |
1846 |
|
|
1847 |
(when (and opt-alt |
(if (memq 'opts-or-alts format) |
1848 |
(memq 'opts-or-alts format)) |
(cond ((and empty-field |
1849 |
(if empty-field |
(or opt-alt |
1850 |
;; Either it is an empty ALT field. Then we have checked |
(let ((field (assoc-string |
1851 |
;; already that we have one non-empty alternative. |
field-name req-field-list t))) |
1852 |
;; Or it is an empty OPT field that we do not miss anyway. |
(or (not field) ; OPT field |
1853 |
;; So we can safely delete this field. |
(nth 3 field))))) ; ALT field |
1854 |
(progn (delete-region beg-field end-field) |
;; Either it is an empty ALT field. Then we have checked |
1855 |
(setq deleted t)) |
;; already that we have one non-empty alternative. Or it |
1856 |
;; otherwise: not empty, delete "OPT" or "ALT" |
;; is an empty OPT field that we do not miss anyway. |
1857 |
(goto-char beg-name) |
;; So we can safely delete this field. |
1858 |
(delete-char 3))) |
(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)))) |
1864 |
|
|
1865 |
(unless deleted |
(unless deleted |
1866 |
(push field-name field-list) |
(push field-name field-list) |
1919 |
;; if empty field, complain |
;; if empty field, complain |
1920 |
(if (and empty-field |
(if (and empty-field |
1921 |
(memq 'required-fields format) |
(memq 'required-fields format) |
1922 |
(assoc-ignore-case field-name |
(assoc-string field-name req-field-list t)) |
|
(if crossref-key creq req))) |
|
1923 |
(error "Mandatory field `%s' is empty" field-name)) |
(error "Mandatory field `%s' is empty" field-name)) |
1924 |
|
|
1925 |
;; unify case of field name |
;; unify case of field name |
1926 |
(if (memq 'unify-case format) |
(if (memq 'unify-case format) |
1927 |
(let ((fname (car (assoc-ignore-case |
(let ((fname (car (assoc-string |
1928 |
field-name (append (nth 0 (nth 1 entry-list)) |
field-name |
1929 |
(nth 1 (nth 1 entry-list)) |
(append (nth 0 (nth 1 entry-list)) |
1930 |
bibtex-user-optional-fields))))) |
(nth 1 (nth 1 entry-list)) |
1931 |
|
bibtex-user-optional-fields) |
1932 |
|
t)))) |
1933 |
(if fname |
(if fname |
1934 |
(progn |
(progn |
1935 |
(delete-region beg-name end-name) |
(delete-region beg-name end-name) |
1943 |
|
|
1944 |
;; check whether all required fields are present |
;; check whether all required fields are present |
1945 |
(if (memq 'required-fields format) |
(if (memq 'required-fields format) |
1946 |
(let (altlist (found 0)) |
(let ((found 0) altlist) |
1947 |
(dolist (fname (if crossref-key creq req)) |
(dolist (fname req-field-list) |
1948 |
(if (nth 3 fname) |
(if (nth 3 fname) |
1949 |
(push (car fname) altlist)) |
(push (car fname) altlist)) |
1950 |
(unless (or (member (car fname) field-list) |
(unless (or (member (car fname) field-list) |
1958 |
(error "Alternative mandatory field `%s' is missing" |
(error "Alternative mandatory field `%s' is missing" |
1959 |
altlist)) |
altlist)) |
1960 |
((> found 1) |
((> found 1) |
1961 |
(error "Alternative fields `%s' is defined %s times" |
(error "Alternative fields `%s' are defined %s times" |
1962 |
altlist found)))))) |
altlist found)))))) |
1963 |
|
|
1964 |
;; update point |
;; update point |
2069 |
(setq titlestring (substring titlestring 0 (match-beginning 0)))))) |
(setq titlestring (substring titlestring 0 (match-beginning 0)))))) |
2070 |
;; gather words from titlestring into a list. Ignore |
;; gather words from titlestring into a list. Ignore |
2071 |
;; specific words and use only a specific amount of words. |
;; specific words and use only a specific amount of words. |
2072 |
(let (case-fold-search titlewords titlewords-extra titleword end-match |
(let ((counter 0) |
2073 |
(counter 0)) |
case-fold-search titlewords titlewords-extra titleword end-match) |
2074 |
(while (and (or (not (numberp bibtex-autokey-titlewords)) |
(while (and (or (not (numberp bibtex-autokey-titlewords)) |
2075 |
(< counter (+ bibtex-autokey-titlewords |
(< counter (+ bibtex-autokey-titlewords |
2076 |
bibtex-autokey-titlewords-stretch))) |
bibtex-autokey-titlewords-stretch))) |
2097 |
"Do some abbreviations on TITLEWORD. |
"Do some abbreviations on TITLEWORD. |
2098 |
The rules are defined in `bibtex-autokey-titleword-abbrevs' |
The rules are defined in `bibtex-autokey-titleword-abbrevs' |
2099 |
and `bibtex-autokey-titleword-length'." |
and `bibtex-autokey-titleword-length'." |
2100 |
(let ((abbrev (bibtex-assoc-of-regexp |
(let ((case-folde-search t) |
2101 |
titleword bibtex-autokey-titleword-abbrevs))) |
(alist bibtex-autokey-titleword-abbrevs)) |
2102 |
(if abbrev |
(while (and alist |
2103 |
(cdr abbrev) |
(not (string-match (concat "\\`\\(?:" (caar alist) "\\)\\'") |
2104 |
|
titleword))) |
2105 |
|
(setq alist (cdr alist))) |
2106 |
|
(if alist |
2107 |
|
(cdar alist) |
2108 |
(bibtex-autokey-abbrev titleword |
(bibtex-autokey-abbrev titleword |
2109 |
bibtex-autokey-titleword-length)))) |
bibtex-autokey-titleword-length)))) |
2110 |
|
|
2261 |
;; This is a crossref. |
;; This is a crossref. |
2262 |
(buffer-substring-no-properties |
(buffer-substring-no-properties |
2263 |
(1+ (match-beginning 3)) (1- (match-end 3)))) |
(1+ (match-beginning 3)) (1- (match-end 3)))) |
2264 |
((assoc-ignore-case (bibtex-type-in-head) |
((assoc-string (bibtex-type-in-head) |
2265 |
bibtex-entry-field-alist) |
bibtex-entry-field-alist t) |
2266 |
;; This is an entry. |
;; This is an entry. |
2267 |
(match-string-no-properties bibtex-key-in-head))))) |
(match-string-no-properties bibtex-key-in-head))))) |
2268 |
(if (and (stringp key) |
(if (and (stringp key) |
2317 |
;; user has aborted by typing a key --> return `aborted' |
;; user has aborted by typing a key --> return `aborted' |
2318 |
(throw 'userkey 'aborted)) |
(throw 'userkey 'aborted)) |
2319 |
(setq key (bibtex-reference-key-in-string bounds)) |
(setq key (bibtex-reference-key-in-string bounds)) |
2320 |
(if (not (assoc-ignore-case key strings)) |
(if (not (assoc key strings)) |
2321 |
(push (cons key (bibtex-text-in-string bounds t)) |
(push (cons key (bibtex-text-in-string bounds t)) |
2322 |
strings)) |
strings)) |
2323 |
(goto-char (bibtex-end-of-text-in-string bounds))) |
(goto-char (bibtex-end-of-text-in-string bounds))) |
2406 |
(display-completion-list (all-completions part-of-word |
(display-completion-list (all-completions part-of-word |
2407 |
completions))) |
completions))) |
2408 |
(message "Making completion list...done") |
(message "Making completion list...done") |
2409 |
|
;; return value is handled by choose-completion-string-functions |
2410 |
nil)))) |
nil)))) |
2411 |
|
|
2412 |
(defun bibtex-complete-string-cleanup (str) |
(defun bibtex-complete-string-cleanup (str) |
2652 |
(easy-menu-add bibtex-entry-menu) |
(easy-menu-add bibtex-entry-menu) |
2653 |
(run-hooks 'bibtex-mode-hook)) |
(run-hooks 'bibtex-mode-hook)) |
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 |
|
|
2683 |
(defun bibtex-entry (entry-type) |
(defun bibtex-entry (entry-type) |
2684 |
"Insert a new BibTeX entry. |
"Insert a new BibTeX entry. |
2685 |
After insertion it calls the functions in `bibtex-add-entry-hook'." |
After insertion it calls the functions in `bibtex-add-entry-hook'." |
2689 |
bibtex-entry-field-alist |
bibtex-entry-field-alist |
2690 |
nil t nil 'bibtex-entry-type-history))) |
nil t nil 'bibtex-entry-type-history))) |
2691 |
(list e-t))) |
(list e-t))) |
2692 |
(let* (required optional |
(let ((key (if bibtex-maintain-sorted-entries |
2693 |
(key (if bibtex-maintain-sorted-entries |
(bibtex-read-key (format "%s key: " entry-type)))) |
2694 |
(bibtex-read-key (format "%s key: " entry-type)))) |
(field-list (bibtex-field-list entry-type))) |
|
(e (assoc-ignore-case entry-type bibtex-entry-field-alist)) |
|
|
(r-n-o (elt e 1)) |
|
|
(c-ref (elt e 2))) |
|
|
(if (not e) |
|
|
(error "Bibtex entry type %s not defined" entry-type)) |
|
|
(if (and (member entry-type bibtex-include-OPTcrossref) |
|
|
c-ref) |
|
|
(setq required (elt c-ref 0) |
|
|
optional (elt c-ref 1)) |
|
|
(setq required (elt r-n-o 0) |
|
|
optional (elt r-n-o 1))) |
|
2695 |
(unless (bibtex-prepare-new-entry (list key nil entry-type)) |
(unless (bibtex-prepare-new-entry (list key nil entry-type)) |
2696 |
(error "Entry with key `%s' already exists" key)) |
(error "Entry with key `%s' already exists" key)) |
2697 |
(indent-to-column bibtex-entry-offset) |
(indent-to-column bibtex-entry-offset) |
2698 |
(insert "@" entry-type (bibtex-entry-left-delimiter)) |
(insert "@" entry-type (bibtex-entry-left-delimiter)) |
2699 |
(if key |
(if key (insert key)) |
|
(insert key)) |
|
2700 |
(save-excursion |
(save-excursion |
2701 |
(mapcar 'bibtex-make-field required) |
(mapcar 'bibtex-make-field (car field-list)) |
2702 |
(if (member entry-type bibtex-include-OPTcrossref) |
(mapcar 'bibtex-make-optional-field (cdr field-list)) |
|
(bibtex-make-optional-field '("crossref"))) |
|
|
(if bibtex-include-OPTkey |
|
|
(if (or (stringp bibtex-include-OPTkey) |
|
|
(fboundp bibtex-include-OPTkey)) |
|
|
(bibtex-make-optional-field |
|
|
(list "key" nil bibtex-include-OPTkey)) |
|
|
(bibtex-make-optional-field '("key")))) |
|
|
(mapcar 'bibtex-make-optional-field optional) |
|
|
(mapcar 'bibtex-make-optional-field bibtex-user-optional-fields) |
|
2703 |
(if bibtex-comma-after-last-field |
(if bibtex-comma-after-last-field |
2704 |
(insert ",")) |
(insert ",")) |
2705 |
(insert "\n") |
(insert "\n") |
2710 |
(bibtex-autofill-entry)) |
(bibtex-autofill-entry)) |
2711 |
(run-hooks 'bibtex-add-entry-hook))) |
(run-hooks 'bibtex-add-entry-hook))) |
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 |
|
|
2736 |
(defun bibtex-parse-entry () |
(defun bibtex-parse-entry () |
2737 |
"Parse entry at point, return an alist. |
"Parse entry at point, return an alist. |
2738 |
The alist elements have the form (FIELD . TEXT), where FIELD can also be |
The alist elements have the form (FIELD . TEXT), where FIELD can also be |
2739 |
the special strings \"=type=\" and \"=key=\"." |
the special strings \"=type=\" and \"=key=\". For the FIELD \"=key=\" |
2740 |
|
TEXT may be nil. Move point to the end of the last field." |
2741 |
(let (alist bounds) |
(let (alist bounds) |
2742 |
(when (looking-at bibtex-entry-head) |
(when (looking-at bibtex-entry-maybe-empty-head) |
2743 |
(push (cons "=type=" (match-string bibtex-type-in-head)) alist) |
(push (cons "=type=" (match-string bibtex-type-in-head)) alist) |
2744 |
(push (cons "=key=" (match-string bibtex-key-in-head)) alist) |
(push (cons "=key=" (match-string bibtex-key-in-head)) alist) |
2745 |
(goto-char (match-end bibtex-key-in-head)) |
(goto-char (match-end 0)) |
2746 |
(while (setq bounds (bibtex-parse-field bibtex-field-name)) |
(while (setq bounds (bibtex-parse-field bibtex-field-name)) |
2747 |
(push (cons (bibtex-name-in-field bounds) |
(push (cons (bibtex-name-in-field bounds) |
2748 |
(bibtex-text-in-field-bounds bounds)) |
(bibtex-text-in-field-bounds bounds)) |
2798 |
(let* ((name (buffer-substring |
(let* ((name (buffer-substring |
2799 |
(if (looking-at "ALT\\|OPT") (match-end 0) (point)) |
(if (looking-at "ALT\\|OPT") (match-end 0) (point)) |
2800 |
(bibtex-end-of-name-in-field bounds))) |
(bibtex-end-of-name-in-field bounds))) |
2801 |
(text (assoc-ignore-case name other))) |
(text (assoc-string name other t))) |
2802 |
(goto-char (bibtex-start-of-text-in-field bounds)) |
(goto-char (bibtex-start-of-text-in-field bounds)) |
2803 |
(if (not (and (looking-at bibtex-empty-field-re) text)) |
(if (not (and (looking-at bibtex-empty-field-re) text)) |
2804 |
(goto-char (bibtex-end-of-field bounds)) |
(goto-char (bibtex-end-of-field bounds)) |
2828 |
(looking-at "OPT\\|ALT")) |
(looking-at "OPT\\|ALT")) |
2829 |
(match-end 0) mb) |
(match-end 0) mb) |
2830 |
(bibtex-end-of-name-in-field bounds))) |
(bibtex-end-of-name-in-field bounds))) |
2831 |
(entry-type (progn (re-search-backward |
(field-list (bibtex-field-list (progn (re-search-backward |
2832 |
bibtex-entry-maybe-empty-head nil t) |
bibtex-entry-maybe-empty-head nil t) |
2833 |
(bibtex-type-in-head))) |
(bibtex-type-in-head)))) |
2834 |
(entry-list (assoc-ignore-case entry-type |
(comment (assoc-string field-name |
2835 |
bibtex-entry-field-alist)) |
(append (car field-list) |
2836 |
(c-r-list (elt entry-list 2)) |
(cdr field-list)) |
2837 |
(req-opt-list (if (and (member entry-type |
t))) |
|
bibtex-include-OPTcrossref) |
|
|
c-r-list) |
|
|
c-r-list |
|
|
(elt entry-list 1))) |
|
|
(list-of-entries (append (elt req-opt-list 0) |
|
|
(elt req-opt-list 1) |
|
|
bibtex-user-optional-fields |
|
|
(if (member entry-type |
|
|
bibtex-include-OPTcrossref) |
|
|
'(("crossref" "Reference key of the cross-referenced entry"))) |
|
|
(if bibtex-include-OPTkey |
|
|
'(("key" "Used for reference key creation if author and editor fields are missing"))))) |
|
|
(comment (assoc-ignore-case field-name list-of-entries))) |
|
2838 |
(if comment |
(if comment |
2839 |
(message (elt comment 1)) |
(message (nth 1 comment)) |
2840 |
(message "No comment available"))))) |
(message "No comment available"))))) |
2841 |
|
|
2842 |
(defun bibtex-make-field (field &optional called-by-yank) |
(defun bibtex-make-field (field &optional called-by-yank) |
2845 |
\(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in |
\(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in |
2846 |
`bibtex-entry-field-alist'." |
`bibtex-entry-field-alist'." |
2847 |
(interactive |
(interactive |
2848 |
(list (let* ((entry-type |
(list (let ((completion-ignore-case t) |
2849 |
(save-excursion |
(field-list (bibtex-field-list |
2850 |
(bibtex-enclosing-entry-maybe-empty-head) |
(save-excursion |
2851 |
(bibtex-type-in-head))) |
(bibtex-enclosing-entry-maybe-empty-head) |
2852 |
;; "preliminary" completion list |
(bibtex-type-in-head))))) |
2853 |
(fl (nth 1 (assoc-ignore-case |
(completing-read "BibTeX field name: " |
2854 |
entry-type bibtex-entry-field-alist))) |
(append (car field-list) (cdr field-list)) |
|
;; "full" completion list |
|
|
(field-list (append (nth 0 fl) |
|
|
(nth 1 fl) |
|
|
bibtex-user-optional-fields |
|
|
(if (member entry-type |
|
|
bibtex-include-OPTcrossref) |
|
|
'(("crossref"))) |
|
|
(if bibtex-include-OPTkey |
|
|
'(("key"))))) |
|
|
(completion-ignore-case t)) |
|
|
(completing-read "BibTeX field name: " field-list |
|
2855 |
nil nil nil bibtex-field-history)))) |
nil nil nil bibtex-field-history)))) |
2856 |
(unless (consp field) |
(unless (consp field) |
2857 |
(setq field (list field))) |
(setq field (list field))) |
2878 |
((fboundp init) |
((fboundp init) |
2879 |
(insert (funcall init))))) |
(insert (funcall init))))) |
2880 |
(if (not called-by-yank) (insert (bibtex-field-right-delimiter))) |
(if (not called-by-yank) (insert (bibtex-field-right-delimiter))) |
2881 |
(if (interactive-p) |
(when (interactive-p) |
2882 |
(forward-char -1))) |
(forward-char -1) |
2883 |
|
(bibtex-print-help-message))) |
2884 |
|
|
2885 |
(defun bibtex-beginning-of-entry () |
(defun bibtex-beginning-of-entry () |
2886 |
"Move to beginning of BibTeX entry (beginning of line). |
"Move to beginning of BibTeX entry (beginning of line). |
3013 |
"\\(OPT\\)?crossref" t))) |
"\\(OPT\\)?crossref" t))) |
3014 |
(list key |
(list key |
3015 |
(if bounds (bibtex-text-in-field-bounds bounds t)) |
(if bounds (bibtex-text-in-field-bounds bounds t)) |
3016 |
entry-name)))) |
entry-name))) |
3017 |
(list key nil entry-name))))) |
(list key nil entry-name)))))) |
3018 |
|
|
3019 |
(defun bibtex-lessp (index1 index2) |
(defun bibtex-lessp (index1 index2) |
3020 |
"Predicate for sorting BibTeX entries with indices INDEX1 and INDEX2. |
"Predicate for sorting BibTeX entries with indices INDEX1 and INDEX2. |
3021 |
Each index is a list (KEY CROSSREF-KEY ENTRY-NAME). |
Each index is a list (KEY CROSSREF-KEY ENTRY-NAME). |
3022 |
The predicate depends on the variable `bibtex-maintain-sorted-entries'." |
The predicate depends on the variable `bibtex-maintain-sorted-entries'. |
3023 |
|
If its value is nil use plain sorting." |
3024 |
(cond ((not index1) (not index2)) ; indices can be nil |
(cond ((not index1) (not index2)) ; indices can be nil |
3025 |
((not index2) nil) |
((not index2) nil) |
3026 |
((equal bibtex-maintain-sorted-entries 'crossref) |
((equal bibtex-maintain-sorted-entries 'crossref) |
3049 |
(defun bibtex-sort-buffer () |
(defun bibtex-sort-buffer () |
3050 |
"Sort BibTeX buffer alphabetically by key. |
"Sort BibTeX buffer alphabetically by key. |
3051 |
The predicate for sorting is defined via `bibtex-maintain-sorted-entries'. |
The predicate for sorting is defined via `bibtex-maintain-sorted-entries'. |
3052 |
Text outside of BibTeX entries is not affected. If |
If its value is nil use plain sorting. Text outside of BibTeX entries is not |
3053 |
`bibtex-sort-ignore-string-entries' is non-nil, @String entries will be |
affected. If `bibtex-sort-ignore-string-entries' is non-nil, @String entries |
3054 |
ignored." |
will be ignored." |
3055 |
(interactive) |
(interactive) |
|
(unless bibtex-maintain-sorted-entries |
|
|
(error "You must choose a sorting scheme")) |
|
3056 |
(save-restriction |
(save-restriction |
3057 |
(narrow-to-region (bibtex-beginning-of-first-entry) |
(narrow-to-region (bibtex-beginning-of-first-entry) |
3058 |
(save-excursion (goto-char (point-max)) |
(save-excursion (goto-char (point-max)) |
3242 |
(let* ((entry-list (progn |
(let* ((entry-list (progn |
3243 |
(goto-char beg) |
(goto-char beg) |
3244 |
(bibtex-search-entry nil end) |
(bibtex-search-entry nil end) |
3245 |
(assoc-ignore-case (bibtex-type-in-head) |
(assoc-string (bibtex-type-in-head) |
3246 |
bibtex-entry-field-alist))) |
bibtex-entry-field-alist t))) |
3247 |
(req (copy-sequence (elt (elt entry-list 1) 0))) |
(req (copy-sequence (elt (elt entry-list 1) 0))) |
3248 |
(creq (copy-sequence (elt (elt entry-list 2) 0))) |
(creq (copy-sequence (elt (elt entry-list 2) 0))) |
3249 |
crossref-there bounds) |
crossref-there bounds) |
3259 |
(push (list (bibtex-current-line) |
(push (list (bibtex-current-line) |
3260 |
"Questionable month field") |
"Questionable month field") |
3261 |
error-list)) |
error-list)) |
3262 |
(setq req (delete (assoc-ignore-case field-name req) req) |
(setq req (delete (assoc-string field-name req t) req) |
3263 |
creq (delete (assoc-ignore-case field-name creq) creq)) |
creq (delete (assoc-string field-name creq t) creq)) |
3264 |
(if (equal field-name "crossref") |
(if (equal field-name "crossref") |
3265 |
(setq crossref-there t)))) |
(setq crossref-there t)))) |
3266 |
(if crossref-there |
(if crossref-there |
3553 |
(match-end bibtex-key-in-head))) |
(match-end bibtex-key-in-head))) |
3554 |
(insert key)) |
(insert key)) |
3555 |
;; sorting |
;; sorting |
3556 |
(let* ((start (bibtex-beginning-of-entry)) |
(unless called-by-reformat |
3557 |
(end (progn (bibtex-end-of-entry) |
(let* ((start (bibtex-beginning-of-entry)) |
3558 |
(if (re-search-forward |
(end (progn (bibtex-end-of-entry) |
3559 |
bibtex-entry-maybe-empty-head nil 'move) |
(if (re-search-forward |
3560 |
(goto-char (match-beginning 0))) |
bibtex-entry-maybe-empty-head nil 'move) |
3561 |
(point))) |
(goto-char (match-beginning 0))) |
3562 |
(entry (buffer-substring start end)) |
(point))) |
3563 |
(index (progn (goto-char start) |
(entry (buffer-substring start end)) |
3564 |
(bibtex-entry-index)))) |
(index (progn (goto-char start) |
3565 |
(delete-region start end) |
(bibtex-entry-index))) |
3566 |
(unless (prog1 (or called-by-reformat |
no-error) |
3567 |
(if (and bibtex-maintain-sorted-entries |
(if (and bibtex-maintain-sorted-entries |
3568 |
(not (and bibtex-sort-ignore-string-entries |
(not (and bibtex-sort-ignore-string-entries |
3569 |
(equal entry-type "string")))) |
(equal entry-type "string")))) |
3570 |
(bibtex-prepare-new-entry index) |
(progn |
3571 |
(not (bibtex-find-entry (car index))))) |
(delete-region start end) |
3572 |
(insert entry) |
(setq no-error (bibtex-prepare-new-entry index)) |
3573 |
(forward-char -1) |
(insert entry) |
3574 |
(bibtex-beginning-of-entry) ; moves backward |
(forward-char -1) |
3575 |
(re-search-forward bibtex-entry-head)) |
(bibtex-beginning-of-entry) ; moves backward |
3576 |
(error "New inserted entry yields duplicate key"))) |
(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")))) |
3580 |
;; final clean up |
;; final clean up |
3581 |
(unless called-by-reformat |
(unless called-by-reformat |
3582 |
(save-excursion |
(save-excursion |
3654 |
(indent-to-column bibtex-entry-offset) |
(indent-to-column bibtex-entry-offset) |
3655 |
(goto-char pnt))) |
(goto-char pnt))) |
3656 |
|
|
3657 |
(defun bibtex-reformat (&optional additional-options called-by-convert-alien) |
(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) |
3667 |
"Reformat all BibTeX entries in buffer or region. |
"Reformat all BibTeX entries in buffer or region. |
3668 |
With prefix argument, read options for reformatting from minibuffer. |
With prefix argument, read options for reformatting from minibuffer. |
3669 |
With \\[universal-argument] \\[universal-argument] prefix argument, reuse previous answers (if any) again. |
With \\[universal-argument] \\[universal-argument] prefix argument, reuse previous answers (if any) again. |
3670 |
If mark is active it reformats entries in region, if not in whole buffer." |
If mark is active reformat entries in region, if not in whole buffer." |
3671 |
(interactive "*P") |
(interactive "*P") |
3672 |
(let* ((pnt (point)) |
(let* ((pnt (point)) |
3673 |
(use-previous-options |
(use-previous-options |
3674 |
(and (equal (prefix-numeric-value additional-options) 16) |
(and (equal (prefix-numeric-value read-options) 16) |
3675 |
(or bibtex-reformat-previous-options |
(or bibtex-reformat-previous-options |
3676 |
bibtex-reformat-previous-reference-keys))) |
bibtex-reformat-previous-reference-keys))) |
3677 |
(bibtex-entry-format |
(bibtex-entry-format |
3678 |
(if additional-options |
(if read-options |
3679 |
(if use-previous-options |
(if use-previous-options |
3680 |
bibtex-reformat-previous-options |
bibtex-reformat-previous-options |
3681 |
(setq bibtex-reformat-previous-options |
(setq bibtex-reformat-previous-options |
3682 |
(delq nil (list |
(mapcar (lambda (option) |
3683 |
(if (or called-by-convert-alien |
(if (y-or-n-p (car option)) (cdr option))) |
3684 |
(y-or-n-p "Realign entries (recommended)? ")) |
`(("Realign entries (recommended)? " . 'realign) |
3685 |
'realign) |
("Remove empty optional and alternative fields? " . 'opts-or-alts) |
3686 |
(if (y-or-n-p "Remove empty optional and alternative fields? ") |
("Remove delimiters around pure numerical fields? " . 'numerical-fields) |
3687 |
'opts-or-alts) |
(,(concat (if bibtex-comma-after-last-field "Insert" "Remove") |
3688 |
(if (y-or-n-p "Remove delimiters around pure numerical fields? ") |
" comma at end of entry? ") . 'last-comma) |
3689 |
'numerical-fields) |
("Replace double page dashes by single ones? " . 'page-dashes) |
3690 |
(if (y-or-n-p (concat (if bibtex-comma-after-last-field "Insert" "Remove") |
("Force delimiters? " . 'delimiters) |
3691 |
" comma at end of entry? ")) |
("Unify case of entry types and field names? " . 'unify-case))))) |
|
'last-comma) |
|
|
(if (y-or-n-p "Replace double page dashes by single ones? ") |
|
|
'page-dashes) |
|
|
(if (y-or-n-p "Force delimiters? ") |
|
|
'delimiters) |
|
|
(if (y-or-n-p "Unify case of entry types and field names? ") |
|
|
'unify-case))))) |
|
3692 |
'(realign))) |
'(realign))) |
3693 |
(reformat-reference-keys (if additional-options |
(reformat-reference-keys |
3694 |
(if use-previous-options |
(if read-options |
3695 |
bibtex-reformat-previous-reference-keys |
(if use-previous-options |
3696 |
(setq bibtex-reformat-previous-reference-keys |
bibtex-reformat-previous-reference-keys |
3697 |
(y-or-n-p "Generate new reference keys automatically? "))))) |
(setq bibtex-reformat-previous-reference-keys |
3698 |
bibtex-autokey-edit-before-use |
(y-or-n-p "Generate new reference keys automatically? "))))) |
|
(bibtex-sort-ignore-string-entries t) |
|
3699 |
(start-point (if (bibtex-mark-active) |
(start-point (if (bibtex-mark-active) |
3700 |
(region-beginning) |
(region-beginning) |
3701 |
(bibtex-beginning-of-first-entry) |
(point-min))) |
|
(bibtex-skip-to-valid-entry) |
|
|
(point))) |
|
3702 |
(end-point (if (bibtex-mark-active) |
(end-point (if (bibtex-mark-active) |
3703 |
(region-end) |
(region-end) |
3704 |
(point-max)))) |
(point-max))) |
3705 |
|
(bibtex-sort-ignore-string-entries t) |
3706 |
|
bibtex-autokey-edit-before-use) |
3707 |
|
|
3708 |
(save-restriction |
(save-restriction |
3709 |
(narrow-to-region start-point end-point) |
(narrow-to-region start-point end-point) |
3710 |
(when (memq 'realign bibtex-entry-format) |
(if (memq 'realign bibtex-entry-format) |
3711 |
(goto-char (point-min)) |
(bibtex-realign)) |
|
(while (re-search-forward bibtex-valid-entry-whitespace-re nil t) |
|
|
(replace-match "\n\\1"))) |
|
3712 |
(goto-char start-point) |
(goto-char start-point) |
3713 |
(bibtex-progress-message "Formatting" 1) |
(bibtex-progress-message "Formatting" 1) |
3714 |
(bibtex-map-entries (lambda (key beg end) |
(bibtex-map-entries (lambda (key beg end) |
3715 |
(bibtex-progress-message) |
(bibtex-progress-message) |
3716 |
(bibtex-clean-entry reformat-reference-keys t) |
(bibtex-clean-entry reformat-reference-keys t))) |
3717 |
(when (memq 'realign bibtex-entry-format) |
(when (memq 'realign bibtex-entry-format) |
3718 |
(goto-char end) |
(bibtex-delete-whitespace) |
3719 |
(bibtex-delete-whitespace) |
(open-line (if (eobp) 1 2))) |
|
(open-line 2)))) |
|
3720 |
(bibtex-progress-message 'done)) |
(bibtex-progress-message 'done)) |
3721 |
(when (and reformat-reference-keys |
(when (and reformat-reference-keys |
3722 |
bibtex-maintain-sorted-entries |
bibtex-maintain-sorted-entries) |
3723 |
(not called-by-convert-alien)) |
(bibtex-progress-message "Sorting" 1) |
3724 |
(bibtex-sort-buffer) |
(bibtex-sort-buffer) |
3725 |
(kill-local-variable 'bibtex-reference-keys)) |
(kill-local-variable 'bibtex-reference-keys) |
3726 |
|
(bibtex-progress-message 'done)) |
3727 |
(goto-char pnt))) |
(goto-char pnt))) |
3728 |
|
|
3729 |
(defun bibtex-convert-alien (&optional do-additional-reformatting) |
(defun bibtex-convert-alien (&optional read-options) |
3730 |
"Convert an alien BibTeX buffer to be fully usable by BibTeX mode. |
"Convert an alien BibTeX buffer to be fully usable by BibTeX mode. |
3731 |
If a file does not conform with some standards used by BibTeX mode, |
If a file does not conform with all standards used by BibTeX mode, |
3732 |
some of the high-level features of BibTeX mode will not be available. |
some of the high-level features of BibTeX mode will not be available. |
3733 |
This function tries to convert current buffer to conform with these standards. |
This function tries to convert current buffer to conform with these standards. |
3734 |
With prefix argument DO-ADDITIONAL-REFORMATTING |
With prefix argument READ-OPTIONS non-nil, read options for reformatting |
3735 |
non-nil, read options for reformatting entries from minibuffer." |
entries from minibuffer." |
3736 |
(interactive "*P") |
(interactive "*P") |
3737 |
(message "Starting to validate buffer...") |
(message "Starting to validate buffer...") |
3738 |
(sit-for 1 nil t) |
(sit-for 1 nil t) |
3739 |
(goto-char (point-min)) |
(bibtex-realign) |
|
(while (re-search-forward "[ \t\n]+@" nil t) |
|
|
(replace-match "\n@")) |
|
3740 |
(message |
(message |
3741 |
"If errors occur, correct them and call `bibtex-convert-alien' again") |
"If errors occur, correct them and call `bibtex-convert-alien' again") |
3742 |
(sit-for 5 nil t) |
(sit-for 5 nil t) |
3745 |
(bibtex-validate)) |
(bibtex-validate)) |
3746 |
(message "Starting to reformat entries...") |
(message "Starting to reformat entries...") |
3747 |
(sit-for 2 nil t) |
(sit-for 2 nil t) |
3748 |
(bibtex-reformat do-additional-reformatting t) |
(bibtex-reformat read-options) |
|
(when bibtex-maintain-sorted-entries |
|
|
(message "Starting to sort buffer...") |
|
|
(bibtex-sort-buffer)) |
|
3749 |
(goto-char (point-max)) |
(goto-char (point-max)) |
3750 |
(message "Buffer is now parsable. Please save it."))) |
(message "Buffer is now parsable. Please save it."))) |
3751 |
|
|
3918 |
|
|
3919 |
(provide 'bibtex) |
(provide 'bibtex) |
3920 |
|
|
3921 |
;;; arch-tag: ee2be3af-caad-427f-b42a-d20fad630d04 |
;; arch-tag: ee2be3af-caad-427f-b42a-d20fad630d04 |
3922 |
;;; bibtex.el ends here |
;;; bibtex.el ends here |