Mercurial > emacs
comparison lisp/textmodes/bibtex.el @ 67894:d742983a2136
(bibtex-entry-type-whitespace)
(bibtex-entry-type-str, bibtex-empty-field-re)
(bibtex-search-backward-string, bibtex-preamble-prefix)
(bibtex-search-entry, bibtex-enclosing-entry-maybe-empty-head):
Removed.
(bibtex-any-valid-entry-type): New variable.
(bibtex-parse-field-name): Simplify.
(bibtex-parse-string, bibtex-search-forward-string): New arg
empty-key.
(bibtex-preamble-prefix): Include left delimiter.
(bibtex-search-forward-field, bibtex-search-backward-field): Allow
unbounded search past entry boundaries (required by bibtex-pop).
(bibtex-text-in-field-bounds): Use push.
(bibtex-text-in-field): Do not use bibtex-narrow-to-entry.
(bibtex-parse-preamble, bibtex-valid-entry)
(bibtex-beginning-first-field): New functions.
(bibtex-skip-to-valid-entry): Use bibtex-valid-entry. Fix regexp.
(bibtex-map-entries): Fix docstring.
(bibtex-flash-head): New arg prompt. Simplify.
(bibtex-enclosing-field): Include code of bibtex-inside-field.
(bibtex-insert-kill): Simplify. Always insert text past the
current field or entry.
(bibtex-format-entry): Use bibtex-parse-field.
(bibtex-pop): Use bibtex-beginning-of-entry and
bibtex-end-of-entry to initiate the search. Insert empty field if
we found ourselves.
(bibtex-print-help-message): New args field and comma. Handle
entry keys.
(bibtex-make-field): Use bibtex-beginning-of-entry.
(bibtex-end-of-entry): Use bibtex-valid-entry. Recognize any
invalid entry.
(bibtex-validate): Use bibtex-valid-entry and bibtex-parse-string.
Handle preambles. Simplify code for thorough test.
(bibtex-next-field, bibtex-find-text, bibtex-find-text-internal):
New arg comma. Handle entry heads.
(bibtex-remove-OPT-or-ALT, bibtex-remove-delimiters)
(bibtex-kill-field, bibtex-copy-field-as-kil, bibtex-empty-field):
New arg comma.
(bibtex-kill-entry): Use bibtex-any-entry-maybe-empty-head.
(bibtex-fill-field): Simplify.
(bibtex-fill-entry): Use bibtex-beginning-first-field and
bibtex-parse-field.
(bibtex-convert-alien): Do not wait before calling
bibtex-validate.
(bibtex-complete): Use bibtex-parse-preamble.
author | Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> |
---|---|
date | Thu, 29 Dec 2005 15:23:52 +0000 |
parents | d195eef388b8 |
children | 823f54b91fe2 |
comparison
equal
deleted
inserted
replaced
67893:6af57e0a5d45 | 67894:d742983a2136 |
---|---|
851 (defcustom bibtex-expand-strings nil | 851 (defcustom bibtex-expand-strings nil |
852 "If non-nil, expand strings when extracting the content of a BibTeX field." | 852 "If non-nil, expand strings when extracting the content of a BibTeX field." |
853 :group 'bibtex | 853 :group 'bibtex |
854 :type 'boolean) | 854 :type 'boolean) |
855 | 855 |
856 ;; `bibtex-font-lock-keywords' is a user option as well, but since the | 856 ;; `bibtex-font-lock-keywords' is a user option, too. But since the |
857 ;; patterns used to define this variable are defined in a later | 857 ;; patterns used to define this variable are defined in a later |
858 ;; section of this file, it is defined later. | 858 ;; section of this file, it is defined later. |
859 | 859 |
860 | 860 |
861 ;; Syntax Table and Keybindings | 861 ;; Syntax Table and Keybindings |
1089 | 1089 |
1090 (defconst bibtex-field-name "[^\"#%'(),={} \t\n0-9][^\"#%'(),={} \t\n]*" | 1090 (defconst bibtex-field-name "[^\"#%'(),={} \t\n0-9][^\"#%'(),={} \t\n]*" |
1091 "Regexp matching the name of a BibTeX field.") | 1091 "Regexp matching the name of a BibTeX field.") |
1092 | 1092 |
1093 (defconst bibtex-name-part | 1093 (defconst bibtex-name-part |
1094 (concat ",[ \t\n]*\\(" bibtex-field-name "\\)[ \t\n]*=") | 1094 (concat ",[ \t\n]*\\(" bibtex-field-name "\\)") |
1095 "Regexp matching the name part of a BibTeX field.") | 1095 "Regexp matching the name part of a BibTeX field.") |
1096 | 1096 |
1097 (defconst bibtex-reference-key "[][[:alnum:].:;?!`'/*@+|()<>&_^$-]+" | 1097 (defconst bibtex-reference-key "[][[:alnum:].:;?!`'/*@+|()<>&_^$-]+" |
1098 "Regexp matching the reference key part of a BibTeX entry.") | 1098 "Regexp matching the reference key part of a BibTeX entry.") |
1099 | 1099 |
1102 | 1102 |
1103 (defvar bibtex-entry-type | 1103 (defvar bibtex-entry-type |
1104 (concat "@[ \t]*\\(?:" | 1104 (concat "@[ \t]*\\(?:" |
1105 (regexp-opt (mapcar 'car bibtex-entry-field-alist)) "\\)") | 1105 (regexp-opt (mapcar 'car bibtex-entry-field-alist)) "\\)") |
1106 "Regexp matching the name of a BibTeX entry.") | 1106 "Regexp matching the name of a BibTeX entry.") |
1107 | |
1108 (defvar bibtex-entry-type-whitespace | |
1109 (concat "[ \t]*" bibtex-entry-type) | |
1110 "Regexp matching the name of a BibTeX entry preceded by whitespace.") | |
1111 | |
1112 (defvar bibtex-entry-type-str | |
1113 (concat "@[ \t]*\\(?:" | |
1114 (regexp-opt (append '("String") | |
1115 (mapcar 'car bibtex-entry-field-alist))) "\\)") | |
1116 "Regexp matching the name of a BibTeX entry (including @String).") | |
1117 | 1107 |
1118 (defvar bibtex-entry-head | 1108 (defvar bibtex-entry-head |
1119 (concat "^[ \t]*\\(" | 1109 (concat "^[ \t]*\\(" |
1120 bibtex-entry-type | 1110 bibtex-entry-type |
1121 "\\)[ \t]*[({][ \t\n]*\\(" | 1111 "\\)[ \t]*[({][ \t\n]*\\(" |
1130 (defconst bibtex-any-entry-maybe-empty-head | 1120 (defconst bibtex-any-entry-maybe-empty-head |
1131 (concat "^[ \t]*\\(@[ \t]*" bibtex-field-name "\\)[ \t]*[({][ \t\n]*\\(" | 1121 (concat "^[ \t]*\\(@[ \t]*" bibtex-field-name "\\)[ \t]*[({][ \t\n]*\\(" |
1132 bibtex-reference-key "\\)?") | 1122 bibtex-reference-key "\\)?") |
1133 "Regexp matching the header line of any BibTeX entry (possibly without key).") | 1123 "Regexp matching the header line of any BibTeX entry (possibly without key).") |
1134 | 1124 |
1125 (defvar bibtex-any-valid-entry-type | |
1126 (concat "^[ \t]*@[ \t]*\\(?:" | |
1127 (regexp-opt (append '("String" "Preamble") | |
1128 (mapcar 'car bibtex-entry-field-alist))) "\\)") | |
1129 "Regexp matching any valid BibTeX entry (including String and Preamble).") | |
1130 | |
1135 (defconst bibtex-type-in-head 1 | 1131 (defconst bibtex-type-in-head 1 |
1136 "Regexp subexpression number of the type part in `bibtex-entry-head'.") | 1132 "Regexp subexpression number of the type part in `bibtex-entry-head'.") |
1137 | 1133 |
1138 (defconst bibtex-key-in-head 2 | 1134 (defconst bibtex-key-in-head 2 |
1139 "Regexp subexpression number of the key part in `bibtex-entry-head'.") | 1135 "Regexp subexpression number of the key part in `bibtex-entry-head'.") |
1140 | |
1141 (defconst bibtex-empty-field-re "\\`\\(\"\"\\|{}\\)\\'" | |
1142 "Regexp matching the text part (as a string) of an empty field.") | |
1143 | 1136 |
1144 (defconst bibtex-string-type "^[ \t]*\\(@[ \t]*String\\)[ \t]*[({][ \t\n]*" | 1137 (defconst bibtex-string-type "^[ \t]*\\(@[ \t]*String\\)[ \t]*[({][ \t\n]*" |
1145 "Regexp matching the name of a BibTeX String entry.") | 1138 "Regexp matching the name of a BibTeX String entry.") |
1146 | 1139 |
1147 (defconst bibtex-string-maybe-empty-head | 1140 (defconst bibtex-string-maybe-empty-head |
1148 (concat bibtex-string-type "\\(" bibtex-reference-key "\\)?") | 1141 (concat bibtex-string-type "\\(" bibtex-reference-key "\\)?") |
1149 "Regexp matching the header line of a BibTeX String entry.") | 1142 "Regexp matching the header line of a BibTeX String entry.") |
1150 | 1143 |
1151 (defconst bibtex-preamble-prefix "[ \t]*@[ \t]*Preamble[ \t]*" | 1144 (defconst bibtex-preamble-prefix |
1152 "Regexp matching the prefix part of a preamble.") | 1145 "[ \t]*\\(@[ \t]*Preamble\\)[ \t]*[({][ \t\n]*" |
1146 "Regexp matching the prefix part of a BibTeX Preamble entry.") | |
1153 | 1147 |
1154 (defconst bibtex-font-lock-syntactic-keywords | 1148 (defconst bibtex-font-lock-syntactic-keywords |
1155 `((,(concat "^[ \t]*\\(" (substring bibtex-comment-start 0 1) "\\)" | 1149 `((,(concat "^[ \t]*\\(" (substring bibtex-comment-start 0 1) "\\)" |
1156 (substring bibtex-comment-start 1) "\\>") | 1150 (substring bibtex-comment-start 1) "\\>") |
1157 1 '(11)))) | 1151 1 '(11)))) |
1227 If the field name is found, return a triple consisting of the position of the | 1221 If the field name is found, return a triple consisting of the position of the |
1228 very first character of the match, the actual starting position of the name | 1222 very first character of the match, the actual starting position of the name |
1229 part and end position of the match. Move point to end of field name. | 1223 part and end position of the match. Move point to end of field name. |
1230 If `bibtex-autoadd-commas' is non-nil add missing comma at end of preceding | 1224 If `bibtex-autoadd-commas' is non-nil add missing comma at end of preceding |
1231 BibTeX field as necessary." | 1225 BibTeX field as necessary." |
1232 (cond ((looking-at ",[ \t\n]*") | 1226 (cond ((looking-at bibtex-name-part) |
1233 (let ((start (point))) | 1227 (goto-char (match-end 0)) |
1234 (goto-char (match-end 0)) | 1228 (list (match-beginning 0) (match-beginning 1) (match-end 0))) |
1235 (when (looking-at bibtex-field-name) | |
1236 (goto-char (match-end 0)) | |
1237 (list start (match-beginning 0) (match-end 0))))) | |
1238 ;; Maybe add a missing comma. | 1229 ;; Maybe add a missing comma. |
1239 ((and bibtex-autoadd-commas | 1230 ((and bibtex-autoadd-commas |
1240 (looking-at (concat "[ \t\n]*\\(?:" bibtex-field-name | 1231 (looking-at (concat "[ \t\n]*\\(?:" bibtex-field-name |
1241 "\\)[ \t\n]*="))) | 1232 "\\)[ \t\n]*="))) |
1242 (skip-chars-backward " \t\n") | 1233 (skip-chars-backward " \t\n") |
1332 | 1323 |
1333 (defun bibtex-search-forward-field (name &optional bound) | 1324 (defun bibtex-search-forward-field (name &optional bound) |
1334 "Search forward to find a BibTeX field of name NAME. | 1325 "Search forward to find a BibTeX field of name NAME. |
1335 If a syntactically correct field is found, return a pair containing | 1326 If a syntactically correct field is found, return a pair containing |
1336 the boundaries of the name and text parts of the field. The search | 1327 the boundaries of the name and text parts of the field. The search |
1337 is limited by optional arg BOUND or if nil by the end of the current | 1328 is limited by optional arg BOUND. If BOUND is t the search is limited |
1338 entry. Do not move point." | 1329 by the end of the current entry. Do not move point." |
1339 (save-match-data | 1330 (save-match-data |
1340 (save-excursion | 1331 (save-excursion |
1341 (if bound | 1332 (if (eq bound t) |
1342 ;; If the search is bounded we need not worry we could overshoot. | 1333 (let ((regexp (concat bibtex-name-part "[ \t\n]*=\\|" |
1343 ;; This is indeed the case when `bibtex-search-forward-field' is | 1334 bibtex-any-entry-maybe-empty-head)) |
1344 ;; called many times. So we optimize this part of this function. | 1335 (case-fold-search t) bounds) |
1345 (let ((name-part (concat ",[ \t\n]*\\(" name "\\)[ \t\n]*=[ \t\n]*")) | 1336 (catch 'done |
1346 (case-fold-search t) left right) | 1337 (if (looking-at "[ \t]*@") (goto-char (match-end 0))) |
1347 (while (and (not right) | 1338 (while (and (not bounds) |
1348 (re-search-forward name-part bound t)) | 1339 (re-search-forward regexp nil t)) |
1349 (setq left (list (match-beginning 0) (match-beginning 1) | 1340 (if (match-beginning 2) |
1350 (match-end 1)) | 1341 ;; We found a new entry |
1351 ;; Don't worry that the field text could be past bound. | 1342 (throw 'done nil) |
1352 right (bibtex-parse-field-text))) | 1343 ;; We found a field |
1353 (if right (cons left right))) | 1344 (goto-char (match-beginning 0)) |
1354 (let ((regexp (concat bibtex-name-part "\\|" | 1345 (setq bounds (bibtex-parse-field)))) |
1355 bibtex-any-entry-maybe-empty-head)) | 1346 ;; Step through all fields so that we cannot overshoot. |
1356 (case-fold-search t) bounds) | 1347 (while bounds |
1357 (catch 'done | 1348 (goto-char (bibtex-start-of-name-in-field bounds)) |
1358 (if (looking-at "[ \t]*@") (goto-char (match-end 0))) | 1349 (if (looking-at name) (throw 'done bounds)) |
1359 (while (and (not bounds) | 1350 (goto-char (bibtex-end-of-field bounds)) |
1360 (re-search-forward regexp nil t)) | 1351 (setq bounds (bibtex-parse-field))))) |
1361 (if (match-beginning 2) | 1352 ;; Bounded search or bound is nil (i.e. we cannot overshoot). |
1362 ;; We found a new entry | 1353 ;; Indeed, the search is bounded when `bibtex-search-forward-field' |
1363 (throw 'done nil) | 1354 ;; is called many times. So we optimize this part of this function. |
1364 ;; We found a field | 1355 (let ((name-part (concat ",[ \t\n]*\\(" name "\\)[ \t\n]*=[ \t\n]*")) |
1365 (goto-char (match-beginning 0)) | 1356 (case-fold-search t) left right) |
1366 (setq bounds (bibtex-parse-field)))) | 1357 (while (and (not right) |
1367 ;; Step through all fields so that we cannot overshoot. | 1358 (re-search-forward name-part bound t)) |
1368 (while bounds | 1359 (setq left (list (match-beginning 0) (match-beginning 1) |
1369 (goto-char (bibtex-start-of-name-in-field bounds)) | 1360 (match-end 1)) |
1370 (if (looking-at name) (throw 'done bounds)) | 1361 ;; Don't worry that the field text could be past bound. |
1371 (goto-char (bibtex-end-of-field bounds)) | 1362 right (bibtex-parse-field-text))) |
1372 (setq bounds (bibtex-parse-field))))))))) | 1363 (if right (cons left right))))))) |
1373 | 1364 |
1374 (defun bibtex-search-backward-field (name &optional bound) | 1365 (defun bibtex-search-backward-field (name &optional bound) |
1375 "Search backward to find a BibTeX field of name NAME. | 1366 "Search backward to find a BibTeX field of name NAME. |
1376 If a syntactically correct field is found, return a pair containing | 1367 If a syntactically correct field is found, return a pair containing |
1377 the boundaries of the name and text parts of the field. The search | 1368 the boundaries of the name and text parts of the field. The search |
1378 is limited by the optional arg BOUND. If BOUND is nil the search is | 1369 is limited by the optional arg BOUND. If BOUND is t the search is |
1379 limited by the beginning of the current entry. Do not move point." | 1370 limited by the beginning of the current entry. Do not move point." |
1380 (save-match-data | 1371 (save-match-data |
1381 (save-excursion | 1372 (if (eq bound t) |
1382 (let ((name-part (concat ",[ \t\n]*\\(?:" name "\\)[ \t\n]*=")) | 1373 (setq bound (save-excursion (bibtex-beginning-of-entry)))) |
1383 (case-fold-search t) | 1374 (let ((name-part (concat ",[ \t\n]*\\(" name "\\)[ \t\n]*=[ \t\n]*")) |
1384 bounds) | 1375 (case-fold-search t) left right) |
1385 (unless bound (setq bound (save-excursion (bibtex-beginning-of-entry)))) | 1376 (save-excursion |
1386 (while (and (not bounds) | 1377 ;; the parsing functions are not designed for parsing backwards :-( |
1387 (search-backward "," bound t) | 1378 (when (search-backward "," bound t) |
1388 (looking-at name-part)) | 1379 (or (save-excursion |
1389 (setq bounds (bibtex-parse-field))) | 1380 (when (looking-at name-part) |
1390 bounds)))) | 1381 (setq left (list (match-beginning 0) (match-beginning 1) |
1382 (match-end 1))) | |
1383 (goto-char (match-end 0)) | |
1384 (setq right (bibtex-parse-field-text)))) | |
1385 (while (and (not right) | |
1386 (re-search-backward name-part bound t)) | |
1387 (setq left (list (match-beginning 0) (match-beginning 1) | |
1388 (match-end 1))) | |
1389 (save-excursion | |
1390 (goto-char (match-end 0)) | |
1391 (setq right (bibtex-parse-field-text))))) | |
1392 (if right (cons left right))))))) | |
1391 | 1393 |
1392 (defun bibtex-name-in-field (bounds &optional remove-opt-alt) | 1394 (defun bibtex-name-in-field (bounds &optional remove-opt-alt) |
1393 "Get content of name in BibTeX field defined via BOUNDS. | 1395 "Get content of name in BibTeX field defined via BOUNDS. |
1394 If optional arg REMOVE-OPT-ALT is non-nil remove \"OPT\" and \"ALT\"." | 1396 If optional arg REMOVE-OPT-ALT is non-nil remove \"OPT\" and \"ALT\"." |
1395 (let ((name (buffer-substring-no-properties | 1397 (let ((name (buffer-substring-no-properties |
1405 If optional arg CONTENT is non-nil extract content of field | 1407 If optional arg CONTENT is non-nil extract content of field |
1406 by removing field delimiters and concatenating the resulting string. | 1408 by removing field delimiters and concatenating the resulting string. |
1407 If `bibtex-expand-strings' is non-nil, also expand BibTeX strings." | 1409 If `bibtex-expand-strings' is non-nil, also expand BibTeX strings." |
1408 (if content | 1410 (if content |
1409 (save-excursion | 1411 (save-excursion |
1412 (goto-char (bibtex-start-of-text-in-field bounds)) | |
1410 (let ((epoint (bibtex-end-of-text-in-field bounds)) | 1413 (let ((epoint (bibtex-end-of-text-in-field bounds)) |
1411 content opoint temp) | 1414 content opoint) |
1412 (goto-char (bibtex-start-of-text-in-field bounds)) | |
1413 (while (< (setq opoint (point)) epoint) | 1415 (while (< (setq opoint (point)) epoint) |
1414 (cond ((looking-at bibtex-field-const) | 1416 (if (looking-at bibtex-field-const) |
1415 (let ((mtch (match-string-no-properties 0))) | 1417 (let ((mtch (match-string-no-properties 0))) |
1416 (goto-char (match-end 0)) | 1418 (push (if bibtex-expand-strings |
1417 (setq temp (if bibtex-expand-strings | 1419 (cdr (assoc-string mtch (bibtex-strings) t)) |
1418 (cdr (assoc-string mtch (bibtex-strings) t))) | 1420 mtch) content) |
1419 content (concat content (or temp mtch))))) | 1421 (goto-char (match-end 0))) |
1420 | 1422 (let ((bounds (bibtex-parse-field-string))) |
1421 ((setq temp (bibtex-parse-field-string)) | 1423 (push (buffer-substring-no-properties |
1422 (setq content (concat content (buffer-substring-no-properties | 1424 (1+ (car bounds)) (1- (cdr bounds))) content) |
1423 (1+ (car temp)) | 1425 (goto-char (cdr bounds)))) |
1424 (1- (cdr temp))))) | |
1425 (goto-char (cdr temp))) | |
1426 (t (error "Malformed text field"))) | |
1427 (re-search-forward "\\=[ \t\n]*#[ \t\n]*" nil t)) | 1426 (re-search-forward "\\=[ \t\n]*#[ \t\n]*" nil t)) |
1428 content)) | 1427 (apply 'concat (nreverse content)))) |
1429 (buffer-substring-no-properties (bibtex-start-of-text-in-field bounds) | 1428 (buffer-substring-no-properties (bibtex-start-of-text-in-field bounds) |
1430 (bibtex-end-of-text-in-field bounds)))) | 1429 (bibtex-end-of-text-in-field bounds)))) |
1431 | 1430 |
1432 (defun bibtex-text-in-field (field &optional follow-crossref) | 1431 (defun bibtex-text-in-field (field &optional follow-crossref) |
1433 "Get content of field FIELD of current BibTeX entry. | 1432 "Get content of field FIELD of current BibTeX entry. |
1434 Return nil if not found. | 1433 Return nil if not found. |
1435 If optional arg FOLLOW-CROSSREF is non-nil, follow crossref." | 1434 If optional arg FOLLOW-CROSSREF is non-nil, follow crossref." |
1436 (save-excursion | 1435 (save-excursion |
1437 (save-restriction | 1436 (let* ((end (if follow-crossref (bibtex-end-of-entry) t)) |
1438 ;; We want to jump back and forth while searching FIELD | 1437 (beg (bibtex-beginning-of-entry)) ; move point |
1439 (bibtex-narrow-to-entry) | 1438 (bounds (bibtex-search-forward-field field end))) |
1440 (goto-char (point-min)) | 1439 (cond (bounds (bibtex-text-in-field-bounds bounds t)) |
1441 (let ((bounds (bibtex-search-forward-field field (point-max))) | 1440 ((and follow-crossref |
1442 crossref-field) | 1441 (progn (goto-char beg) |
1443 (cond (bounds (bibtex-text-in-field-bounds bounds t)) | 1442 (setq bounds (bibtex-search-forward-field |
1444 ((and follow-crossref | 1443 "\\(OPT\\)?crossref" end)))) |
1445 (progn (goto-char (point-min)) | 1444 (let ((crossref-field (bibtex-text-in-field-bounds bounds t))) |
1446 (setq bounds (bibtex-search-forward-field | |
1447 "\\(OPT\\)?crossref" (point-max))))) | |
1448 (setq crossref-field (bibtex-text-in-field-bounds bounds t)) | |
1449 (widen) | |
1450 (if (bibtex-find-crossref crossref-field) | 1445 (if (bibtex-find-crossref crossref-field) |
1451 ;; Do not pass FOLLOW-CROSSREF because we want | 1446 ;; Do not pass FOLLOW-CROSSREF because we want |
1452 ;; to follow crossrefs only one level of recursion. | 1447 ;; to follow crossrefs only one level of recursion. |
1453 (bibtex-text-in-field field)))))))) | 1448 (bibtex-text-in-field field)))))))) |
1454 | 1449 |
1485 (goto-char (match-end 0)) | 1480 (goto-char (match-end 0)) |
1486 (list (car bounds) | 1481 (list (car bounds) |
1487 (nth 1 bounds) | 1482 (nth 1 bounds) |
1488 (match-end 0)))))) | 1483 (match-end 0)))))) |
1489 | 1484 |
1490 (defun bibtex-parse-string () | 1485 (defun bibtex-parse-string (&optional empty-key) |
1491 "Parse a BibTeX string entry beginning at the position of point. | 1486 "Parse a BibTeX string entry beginning at the position of point. |
1492 If a syntactically correct entry is found, return a cons pair containing | 1487 If a syntactically correct entry is found, return a cons pair containing |
1493 the boundaries of the reference key and text parts of the entry. | 1488 the boundaries of the reference key and text parts of the entry. |
1494 Do not move point." | 1489 If EMPTY-KEY is non-nil, key may be empty. Do not move point." |
1495 (bibtex-parse-association 'bibtex-parse-string-prefix | 1490 (let ((bibtex-string-empty-key empty-key)) |
1496 'bibtex-parse-string-postfix)) | 1491 (bibtex-parse-association 'bibtex-parse-string-prefix |
1497 | 1492 'bibtex-parse-string-postfix))) |
1498 (defun bibtex-search-forward-string () | 1493 |
1494 (defun bibtex-search-forward-string (&optional empty-key) | |
1499 "Search forward to find a BibTeX string entry. | 1495 "Search forward to find a BibTeX string entry. |
1500 If a syntactically correct entry is found, a pair containing the boundaries of | 1496 If a syntactically correct entry is found, a pair containing the boundaries of |
1501 the reference key and text parts of the string is returned. Do not move point." | 1497 the reference key and text parts of the string is returned. |
1498 If EMPTY-KEY is non-nil, key may be empty. Do not move point." | |
1502 (save-excursion | 1499 (save-excursion |
1503 (save-match-data | 1500 (save-match-data |
1504 (let ((case-fold-search t) | 1501 (let ((case-fold-search t) bounds) |
1505 boundaries) | 1502 (while (and (not bounds) |
1506 (while (and (not boundaries) | |
1507 (search-forward-regexp bibtex-string-type nil t)) | 1503 (search-forward-regexp bibtex-string-type nil t)) |
1508 (goto-char (match-beginning 0)) | 1504 (save-excursion (goto-char (match-beginning 0)) |
1509 (unless (setq boundaries (bibtex-parse-string)) | 1505 (setq bounds (bibtex-parse-string empty-key)))) |
1510 (forward-char 1))) | 1506 bounds)))) |
1511 boundaries)))) | |
1512 | |
1513 (defun bibtex-search-backward-string () | |
1514 "Search backward to find a BibTeX string entry. | |
1515 If a syntactically correct entry is found, a pair containing the boundaries of | |
1516 the reference key and text parts of the field is returned. Do not move point." | |
1517 (save-excursion | |
1518 (save-match-data | |
1519 (let ((case-fold-search t) | |
1520 boundaries) | |
1521 (while (and (not boundaries) | |
1522 (search-backward-regexp bibtex-string-type nil t)) | |
1523 (goto-char (match-beginning 0)) | |
1524 (setq boundaries (bibtex-parse-string))) | |
1525 boundaries)))) | |
1526 | 1507 |
1527 (defun bibtex-reference-key-in-string (bounds) | 1508 (defun bibtex-reference-key-in-string (bounds) |
1528 "Return the key part of a BibTeX string defined via BOUNDS" | 1509 "Return the key part of a BibTeX string defined via BOUNDS" |
1529 (buffer-substring-no-properties (nth 1 (car bounds)) | 1510 (buffer-substring-no-properties (nth 1 (car bounds)) |
1530 (nth 2 (car bounds)))) | 1511 (nth 2 (car bounds)))) |
1552 (defsubst bibtex-key-in-head (&optional empty) | 1533 (defsubst bibtex-key-in-head (&optional empty) |
1553 "Extract BibTeX key in head. Return optional arg EMPTY if key is empty." | 1534 "Extract BibTeX key in head. Return optional arg EMPTY if key is empty." |
1554 (or (match-string-no-properties bibtex-key-in-head) | 1535 (or (match-string-no-properties bibtex-key-in-head) |
1555 empty)) | 1536 empty)) |
1556 | 1537 |
1557 (defun bibtex-preamble-prefix (&optional delim) | 1538 (defun bibtex-parse-preamble () |
1558 "Parse the prefix part of a BibTeX Preamble. | 1539 "Parse BibTeX preamble. |
1559 Point must be at beginning of prefix part. If prefix is found move point | 1540 Point must be at beginning of preamble. Do not move point." |
1560 to its end and return position of point. If optional arg DELIM is non-nil, | |
1561 move past the opening delimiter. If no preamble is found return nil." | |
1562 (let ((case-fold-search t)) | 1541 (let ((case-fold-search t)) |
1563 (re-search-forward (concat "\\=" bibtex-preamble-prefix | 1542 (when (looking-at bibtex-preamble-prefix) |
1564 (if delim "[({][ \t\n]*")) nil t))) | 1543 (let ((start (match-beginning 0)) (pref-start (match-beginning 1)) |
1544 (bounds (save-excursion (goto-char (match-end 0)) | |
1545 (bibtex-parse-string-postfix)))) | |
1546 (if bounds (cons (list start pref-start) bounds)))))) | |
1565 | 1547 |
1566 ;; Helper Functions | 1548 ;; Helper Functions |
1567 | 1549 |
1568 (defsubst bibtex-string= (str1 str2) | 1550 (defsubst bibtex-string= (str1 str2) |
1569 "Return t if STR1 and STR2 are equal, ignoring case." | 1551 "Return t if STR1 and STR2 are equal, ignoring case." |
1576 | 1558 |
1577 (defun bibtex-current-line () | 1559 (defun bibtex-current-line () |
1578 "Compute line number of point regardless whether the buffer is narrowed." | 1560 "Compute line number of point regardless whether the buffer is narrowed." |
1579 (+ (count-lines 1 (point)) | 1561 (+ (count-lines 1 (point)) |
1580 (if (bolp) 1 0))) | 1562 (if (bolp) 1 0))) |
1563 | |
1564 (defun bibtex-valid-entry (&optional empty-key) | |
1565 "Parse a valid BibTeX entry (maybe without key if EMPTY-KEY is t). | |
1566 A valid entry is a syntactical correct one with type contained in | |
1567 `bibtex-entry-field-alist'. Ignore @String and @Preamble entries. | |
1568 Return a cons pair with buffer positions of beginning and end of entry | |
1569 if a valid entry is found, nil otherwise. Do not move point. | |
1570 After a call to this function `match-data' corresponds to the header | |
1571 of the entry, see regexp `bibtex-entry-head'." | |
1572 (let ((case-fold-search t) end) | |
1573 (if (looking-at (if empty-key bibtex-entry-maybe-empty-head | |
1574 bibtex-entry-head)) | |
1575 (save-excursion | |
1576 (save-match-data | |
1577 (goto-char (match-end 0)) | |
1578 (let ((entry-closer | |
1579 (if (save-excursion | |
1580 (goto-char (match-end bibtex-type-in-head)) | |
1581 (looking-at "[ \t]*(")) | |
1582 ",?[ \t\n]*)" ;; entry opened with `(' | |
1583 ",?[ \t\n]*}")) ;; entry opened with `{' | |
1584 bounds) | |
1585 (skip-chars-forward " \t\n") | |
1586 ;; loop over all BibTeX fields | |
1587 (while (setq bounds (bibtex-parse-field)) | |
1588 (goto-char (bibtex-end-of-field bounds))) | |
1589 ;; This matches the infix* part. | |
1590 (if (looking-at entry-closer) (setq end (match-end 0))))) | |
1591 (if end (cons (match-beginning 0) end)))))) | |
1581 | 1592 |
1582 (defun bibtex-skip-to-valid-entry (&optional backward) | 1593 (defun bibtex-skip-to-valid-entry (&optional backward) |
1583 "Move point to beginning of the next valid BibTeX entry. | 1594 "Move point to beginning of the next valid BibTeX entry. |
1584 Do not move if we are already at beginning of a valid BibTeX entry. | 1595 Do not move if we are already at beginning of a valid BibTeX entry. |
1585 With optional argument BACKWARD non-nil, move backward to | 1596 With optional argument BACKWARD non-nil, move backward to |
1588 `bibtex-sort-ignore-string-entries' is nil, a syntactical correct string | 1599 `bibtex-sort-ignore-string-entries' is nil, a syntactical correct string |
1589 entry. Return buffer position of beginning and end of entry if a valid | 1600 entry. Return buffer position of beginning and end of entry if a valid |
1590 entry is found, nil otherwise." | 1601 entry is found, nil otherwise." |
1591 (interactive "P") | 1602 (interactive "P") |
1592 (let ((case-fold-search t) | 1603 (let ((case-fold-search t) |
1593 found) | 1604 found bounds) |
1594 (beginning-of-line) | 1605 (beginning-of-line) |
1595 ;; Loop till we look at a valid entry. | 1606 ;; Loop till we look at a valid entry. |
1596 (while (not (or found (if backward (bobp) (eobp)))) | 1607 (while (not (or found (if backward (bobp) (eobp)))) |
1597 (let ((pnt (point)) | 1608 (cond ((setq found (or (bibtex-valid-entry) |
1598 bounds) | 1609 (and (not bibtex-sort-ignore-string-entries) |
1599 (cond ((or (and (looking-at bibtex-entry-type-whitespace) | 1610 (setq bounds (bibtex-parse-string)) |
1600 (setq found (bibtex-search-entry nil nil t)) | 1611 (cons (bibtex-start-of-field bounds) |
1601 (equal (match-beginning 0) pnt)) | 1612 (bibtex-end-of-string bounds)))))) |
1602 (and (not bibtex-sort-ignore-string-entries) | 1613 (backward (re-search-backward "^[ \t]*@" nil 'move)) |
1603 (setq bounds (bibtex-parse-string)) | 1614 (t (if (re-search-forward "\n\\([ \t]*@\\)" nil 'move) |
1604 (setq found (cons (bibtex-start-of-field bounds) | 1615 (goto-char (match-beginning 1)))))) |
1605 (bibtex-end-of-string bounds))))) | |
1606 (goto-char pnt)) | |
1607 (backward (re-search-backward "^[ \t]*@" nil 'move)) | |
1608 (t (re-search-forward "\\=[ \t]*@" nil t) ;; don't be stuck | |
1609 (if (re-search-forward "^[ \t]*@" nil 'move) | |
1610 (goto-char (match-beginning 0))))))) | |
1611 found)) | 1616 found)) |
1612 | 1617 |
1613 (defun bibtex-map-entries (fun) | 1618 (defun bibtex-map-entries (fun) |
1614 "Call FUN for each BibTeX entry in buffer (possibly narrowed). | 1619 "Call FUN for each BibTeX entry in buffer (possibly narrowed). |
1615 FUN is called with three arguments, the key of the entry and the buffer | 1620 FUN is called with three arguments, the key of the entry and the buffer |
1616 positions (marker) of beginning and end of entry. Point is inside the entry. | 1621 positions of beginning and end of entry. Also, point is at beginning of |
1617 If `bibtex-sort-ignore-string-entries' is non-nil, FUN is not called for | 1622 entry and `match-data' corresponds to the header of the entry, |
1618 @String entries." | 1623 see regexp `bibtex-entry-head'. If `bibtex-sort-ignore-string-entries' |
1624 is non-nil, FUN is not called for @String entries." | |
1619 (let ((case-fold-search t) | 1625 (let ((case-fold-search t) |
1620 found) | 1626 found) |
1621 (save-excursion | 1627 (save-excursion |
1622 (goto-char (point-min)) | 1628 (goto-char (point-min)) |
1623 (while (setq found (bibtex-skip-to-valid-entry)) | 1629 (while (setq found (bibtex-skip-to-valid-entry)) |
1671 "Return a string dependent on `bibtex-entry-delimiters'." | 1677 "Return a string dependent on `bibtex-entry-delimiters'." |
1672 (if (eq bibtex-entry-delimiters 'braces) | 1678 (if (eq bibtex-entry-delimiters 'braces) |
1673 "}" | 1679 "}" |
1674 ")")) | 1680 ")")) |
1675 | 1681 |
1676 (defun bibtex-search-entry (empty-head &optional bound noerror backward) | 1682 (defun bibtex-flash-head (prompt) |
1677 "Search for a BibTeX entry (maybe without reference key if EMPTY-HEAD is t). | |
1678 BOUND and NOERROR are exactly as in `re-search-forward'. If BACKWARD | |
1679 is non-nil, search in reverse direction. Move point past the closing | |
1680 delimiter (at the beginning of entry if BACKWARD is non-nil). | |
1681 Return a cons pair with buffer positions of beginning and end of entry. | |
1682 After a call to this function `match-data' corresponds to the head part | |
1683 of the entry, see regexp `bibtex-entry-head'. | |
1684 Ignore @String and @Preamble entries." | |
1685 (let ((pnt (point)) | |
1686 (entry-head-re (if empty-head | |
1687 bibtex-entry-maybe-empty-head | |
1688 bibtex-entry-head))) | |
1689 (if backward | |
1690 (let (found) | |
1691 (while (and (not found) | |
1692 (re-search-backward entry-head-re bound noerror)) | |
1693 (setq found (bibtex-search-entry empty-head pnt t))) | |
1694 (cond (found | |
1695 (goto-char (match-beginning 0)) | |
1696 found) | |
1697 ((not noerror) ;; yell | |
1698 (error "Backward search of BibTeX entry failed")) | |
1699 (t (if (eq noerror t) (goto-char pnt)) ;; don't move | |
1700 nil))) | |
1701 (let (found) | |
1702 (unless bound (setq bound (point-max))) | |
1703 (while (and (not found) | |
1704 (re-search-forward entry-head-re bound noerror)) | |
1705 (save-match-data | |
1706 (let ((entry-closer | |
1707 (if (save-excursion | |
1708 (goto-char (match-end bibtex-type-in-head)) | |
1709 (looking-at "[ \t]*(")) | |
1710 ",?[ \t\n]*)" ;; entry opened with `(' | |
1711 ",?[ \t\n]*}")) ;; entry opened with `{' | |
1712 bounds) | |
1713 (skip-chars-forward " \t\n" bound) | |
1714 ;; loop over all BibTeX fields | |
1715 (while (and (setq bounds (bibtex-parse-field)) | |
1716 (<= (bibtex-end-of-field bounds) bound)) | |
1717 (goto-char (bibtex-end-of-field bounds))) | |
1718 ;; This matches the infix* part. | |
1719 (when (and (looking-at entry-closer) | |
1720 (<= (match-end 0) bound)) | |
1721 (goto-char (match-end 0)) | |
1722 (setq found t))))) | |
1723 (cond (found | |
1724 (cons (match-beginning 0) (point))) | |
1725 ((not noerror) ;; yell | |
1726 (error "Search of BibTeX entry failed")) | |
1727 (t (if (eq noerror t) (goto-char pnt)) ;; don't move | |
1728 nil)))))) | |
1729 | |
1730 (defun bibtex-flash-head () | |
1731 "Flash at BibTeX entry head before point, if exists." | 1683 "Flash at BibTeX entry head before point, if exists." |
1732 (let ((case-fold-search t) | 1684 (let ((case-fold-search t) |
1733 (pnt (point)) | 1685 (pnt (point))) |
1734 flash) | |
1735 (save-excursion | 1686 (save-excursion |
1736 (bibtex-beginning-of-entry) | 1687 (bibtex-beginning-of-entry) |
1737 (when (and (looking-at bibtex-any-entry-maybe-empty-head) | 1688 (when (and (looking-at bibtex-any-entry-maybe-empty-head) |
1738 (< (point) pnt)) | 1689 (< (point) pnt)) |
1739 (goto-char (match-beginning bibtex-type-in-head)) | 1690 (goto-char (match-beginning bibtex-type-in-head)) |
1740 (setq flash (match-end bibtex-key-in-head)) | |
1741 (if (pos-visible-in-window-p (point)) | 1691 (if (pos-visible-in-window-p (point)) |
1742 (sit-for 1) | 1692 (sit-for 1) |
1743 (message "From: %s" | 1693 (message "%s%s" prompt (buffer-substring-no-properties |
1744 (buffer-substring (point) flash))))))) | 1694 (point) (match-end bibtex-key-in-head)))))))) |
1745 | 1695 |
1746 (defun bibtex-make-optional-field (field) | 1696 (defun bibtex-make-optional-field (field) |
1747 "Make an optional field named FIELD in current BibTeX entry." | 1697 "Make an optional field named FIELD in current BibTeX entry." |
1748 (if (consp field) | 1698 (if (consp field) |
1749 (bibtex-make-field (cons (concat "OPT" (car field)) (cdr field))) | 1699 (bibtex-make-field (cons (concat "OPT" (car field)) (cdr field))) |
1770 are ignored. Return point" | 1720 are ignored. Return point" |
1771 (goto-char (point-min)) | 1721 (goto-char (point-min)) |
1772 (bibtex-skip-to-valid-entry) | 1722 (bibtex-skip-to-valid-entry) |
1773 (point)) | 1723 (point)) |
1774 | 1724 |
1775 (defun bibtex-inside-field () | 1725 (defun bibtex-enclosing-field (&optional comma noerr) |
1776 "Try to avoid point being at end of a BibTeX field." | |
1777 (end-of-line) | |
1778 (skip-chars-backward " \t") | |
1779 (if (= (preceding-char) ?,) | |
1780 (forward-char -2)) | |
1781 (if (or (= (preceding-char) ?}) | |
1782 (= (preceding-char) ?\")) | |
1783 (forward-char -1))) | |
1784 | |
1785 (defun bibtex-enclosing-field (&optional noerr) | |
1786 "Search for BibTeX field enclosing point. | 1726 "Search for BibTeX field enclosing point. |
1727 For `bibtex-mode''s internal algorithms, a field begins at the comma | |
1728 following the preceding field. Usually, this is not what the user expects. | |
1729 Thus if COMMA is non-nil, the \"current field\" includes the terminating comma. | |
1787 Unless NOERR is non-nil, signal an error if no enclosing field is found. | 1730 Unless NOERR is non-nil, signal an error if no enclosing field is found. |
1788 On success return bounds, nil otherwise. Do not move point." | 1731 On success return bounds, nil otherwise. Do not move point." |
1789 (let ((bounds (bibtex-search-backward-field bibtex-field-name))) | 1732 (save-excursion |
1790 (if (and bounds | 1733 (when comma |
1791 (<= (bibtex-start-of-field bounds) (point)) | 1734 (end-of-line) |
1792 (>= (bibtex-end-of-field bounds) (point))) | 1735 (skip-chars-backward " \t") |
1793 bounds | 1736 (if (= (preceding-char) ?,) (forward-char -1))) |
1794 (unless noerr | 1737 |
1795 (error "Can't find enclosing BibTeX field"))))) | 1738 (let ((bounds (bibtex-search-backward-field bibtex-field-name t))) |
1796 | 1739 (cond ((and bounds |
1797 (defun bibtex-enclosing-entry-maybe-empty-head () | 1740 (<= (bibtex-start-of-field bounds) (point)) |
1798 "Search for BibTeX entry enclosing point. Move point to end of entry. | 1741 (>= (bibtex-end-of-field bounds) (point))) |
1799 Beginning (but not end) of entry is given by (`match-beginning' 0)." | 1742 bounds) |
1800 (let ((case-fold-search t) | 1743 ((not noerr) |
1801 (old-point (point))) | 1744 (error "Can't find enclosing BibTeX field")))))) |
1802 (unless (re-search-backward bibtex-entry-maybe-empty-head nil t) | 1745 |
1803 (goto-char old-point) | 1746 (defun bibtex-beginning-first-field (&optional beg) |
1804 (error "Can't find beginning of enclosing BibTeX entry")) | 1747 "Move point to beginning of first field. |
1805 (goto-char (match-beginning bibtex-type-in-head)) | 1748 Optional arg BEG is beginning of entry." |
1806 (unless (bibtex-search-entry t nil t) | 1749 (if beg (goto-char beg) (bibtex-beginning-of-entry)) |
1807 (goto-char old-point) | 1750 (looking-at bibtex-any-entry-maybe-empty-head) |
1808 (error "Can't find end of enclosing BibTeX entry")))) | 1751 (goto-char (match-end 0))) |
1809 | 1752 |
1810 (defun bibtex-insert-kill (n) | 1753 (defun bibtex-insert-kill (n &optional comma) |
1811 "Reinsert the Nth stretch of killed BibTeX text." | 1754 "Reinsert the Nth stretch of killed BibTeX text (field or entry). |
1812 (if (not bibtex-last-kill-command) | 1755 Optional arg COMMA is as in `bibtex-enclosing-field'." |
1813 (error "BibTeX kill ring is empty") | 1756 (unless bibtex-last-kill-command (error "BibTeX kill ring is empty")) |
1814 (let* ((kr (if (eq bibtex-last-kill-command 'field) | 1757 (let ((fun (lambda (kryp kr) ;; adapted from `current-kill' |
1815 'bibtex-field-kill-ring | 1758 (car (set kryp (nthcdr (mod (- n (length (eval kryp))) |
1816 'bibtex-entry-kill-ring)) | 1759 (length kr)) kr)))))) |
1817 (kryp (if (eq bibtex-last-kill-command 'field) | 1760 (if (eq bibtex-last-kill-command 'field) |
1818 'bibtex-field-kill-ring-yank-pointer | 1761 (progn |
1819 'bibtex-entry-kill-ring-yank-pointer)) | 1762 ;; insert past the current field |
1820 (current (car (set kryp (nthcdr (mod (- n (length (eval kryp))) | 1763 (goto-char (bibtex-end-of-field (bibtex-enclosing-field comma))) |
1821 (length (eval kr))) | 1764 (set-mark (point)) |
1822 (eval kr)))))) | 1765 (message "Mark set") |
1823 (if (eq bibtex-last-kill-command 'field) | 1766 (bibtex-make-field (funcall fun 'bibtex-field-kill-ring-yank-pointer |
1824 (progn | 1767 bibtex-field-kill-ring) t)) |
1825 (bibtex-find-text) | 1768 ;; insert past the current entry |
1826 (if (looking-at "[}\"]") | 1769 (bibtex-skip-to-valid-entry) |
1827 (forward-char)) | 1770 (set-mark (point)) |
1828 (set-mark (point)) | 1771 (message "Mark set") |
1829 (message "Mark set") | 1772 (insert (funcall fun 'bibtex-entry-kill-ring-yank-pointer |
1830 (bibtex-make-field current t)) | 1773 bibtex-entry-kill-ring))))) |
1831 (unless (eobp) (bibtex-beginning-of-entry)) | |
1832 (set-mark (point)) | |
1833 (message "Mark set") | |
1834 (insert current))))) | |
1835 | 1774 |
1836 (defun bibtex-format-entry () | 1775 (defun bibtex-format-entry () |
1837 "Helper function for `bibtex-clean-entry'. | 1776 "Helper function for `bibtex-clean-entry'. |
1838 Formats current entry according to variable `bibtex-entry-format'." | 1777 Formats current entry according to variable `bibtex-entry-format'." |
1839 (save-excursion | 1778 (save-excursion |
1898 (not non-empty-alternative) | 1837 (not non-empty-alternative) |
1899 (memq 'required-fields format)) | 1838 (memq 'required-fields format)) |
1900 (error "All alternatives are empty")) | 1839 (error "All alternatives are empty")) |
1901 | 1840 |
1902 ;; process all fields | 1841 ;; process all fields |
1903 (goto-char (point-min)) | 1842 (bibtex-beginning-first-field (point-min)) |
1904 (while (setq bounds (bibtex-search-forward-field | 1843 (while (setq bounds (bibtex-parse-field)) |
1905 bibtex-field-name (point-max))) | |
1906 (let* ((beg-field (copy-marker (bibtex-start-of-field bounds))) | 1844 (let* ((beg-field (copy-marker (bibtex-start-of-field bounds))) |
1907 (end-field (copy-marker (bibtex-end-of-field bounds) t)) | 1845 (end-field (copy-marker (bibtex-end-of-field bounds) t)) |
1908 (beg-name (copy-marker (bibtex-start-of-name-in-field bounds))) | 1846 (beg-name (copy-marker (bibtex-start-of-name-in-field bounds))) |
1909 (end-name (copy-marker (bibtex-end-of-name-in-field bounds))) | 1847 (end-name (copy-marker (bibtex-end-of-name-in-field bounds))) |
1910 (beg-text (copy-marker (bibtex-start-of-text-in-field bounds))) | 1848 (beg-text (copy-marker (bibtex-start-of-text-in-field bounds))) |
2037 (error "Alternative mandatory field `%s' is missing" | 1975 (error "Alternative mandatory field `%s' is missing" |
2038 altlist)) | 1976 altlist)) |
2039 ((> found 1) | 1977 ((> found 1) |
2040 (error "Alternative fields `%s' are defined %s times" | 1978 (error "Alternative fields `%s' are defined %s times" |
2041 altlist found)))))) | 1979 altlist found)))))) |
2042 | |
2043 ;; update point | |
2044 (if (looking-at (bibtex-field-right-delimiter)) | |
2045 (forward-char)) | |
2046 | 1980 |
2047 ;; update comma after last field | 1981 ;; update comma after last field |
2048 (if (memq 'last-comma format) | 1982 (if (memq 'last-comma format) |
2049 (cond ((and bibtex-comma-after-last-field | 1983 (cond ((and bibtex-comma-after-last-field |
2050 (not (looking-at ","))) | 1984 (not (looking-at ","))) |
2563 | 2497 |
2564 (defun bibtex-complete-string-cleanup (str compl) | 2498 (defun bibtex-complete-string-cleanup (str compl) |
2565 "Cleanup after inserting string STR. | 2499 "Cleanup after inserting string STR. |
2566 Remove enclosing field delimiters for STR. Display message with | 2500 Remove enclosing field delimiters for STR. Display message with |
2567 expansion of STR using expansion list COMPL." | 2501 expansion of STR using expansion list COMPL." |
2502 ;; point is at position inside field where completion was requested | |
2568 (save-excursion | 2503 (save-excursion |
2569 (let ((abbr (cdr (if (stringp str) | 2504 (let ((abbr (cdr (if (stringp str) |
2570 (assoc-string str compl t))))) | 2505 (assoc-string str compl t))))) |
2571 (if abbr (message "Abbreviation for `%s'" abbr)) | 2506 (if abbr (message "Abbreviation for `%s'" abbr)) |
2572 (bibtex-remove-delimiters)))) | 2507 (bibtex-remove-delimiters)))) |
2622 (error "Entry not found"))) | 2557 (error "Entry not found"))) |
2623 | 2558 |
2624 (defun bibtex-pop (arg direction) | 2559 (defun bibtex-pop (arg direction) |
2625 "Fill current field from the ARGth same field's text in DIRECTION. | 2560 "Fill current field from the ARGth same field's text in DIRECTION. |
2626 Generic function used by `bibtex-pop-previous' and `bibtex-pop-next'." | 2561 Generic function used by `bibtex-pop-previous' and `bibtex-pop-next'." |
2627 (bibtex-find-text) | 2562 ;; parse current field |
2628 (save-excursion | 2563 (let* ((bounds (bibtex-enclosing-field t)) |
2629 ;; parse current field | 2564 (start-old-field (bibtex-start-of-field bounds)) |
2630 (bibtex-inside-field) | 2565 (start-old-text (bibtex-start-of-text-in-field bounds)) |
2631 (let* ((case-fold-search t) | 2566 (end-old-text (bibtex-end-of-text-in-field bounds)) |
2632 (bounds (bibtex-enclosing-field)) | 2567 (field-name (bibtex-name-in-field bounds t)) |
2633 (start-old-text (bibtex-start-of-text-in-field bounds)) | 2568 failure) |
2634 (stop-old-text (bibtex-end-of-text-in-field bounds)) | 2569 (save-excursion |
2635 (field-name (bibtex-name-in-field bounds t))) | |
2636 ;; if executed several times in a row, start each search where | 2570 ;; if executed several times in a row, start each search where |
2637 ;; the last one was finished | 2571 ;; the last one was finished |
2638 (unless (eq last-command 'bibtex-pop) | 2572 (cond ((eq last-command 'bibtex-pop) |
2639 (bibtex-enclosing-entry-maybe-empty-head) | 2573 (goto-char (if (eq direction 'previous) |
2640 (setq bibtex-pop-previous-search-point (match-beginning 0) | 2574 bibtex-pop-previous-search-point |
2641 bibtex-pop-next-search-point (point))) | 2575 bibtex-pop-next-search-point))) |
2642 (if (eq direction 'previous) | 2576 ((eq direction 'previous) |
2643 (goto-char bibtex-pop-previous-search-point) | 2577 (bibtex-beginning-of-entry)) |
2644 (goto-char bibtex-pop-next-search-point)) | 2578 (t (bibtex-end-of-entry))) |
2645 ;; Now search for arg'th previous/next similar field | 2579 ;; Search for arg'th previous/next similar field |
2646 (let (bounds failure new-text) | 2580 (while (and (not failure) |
2647 (while (and (not failure) | 2581 (>= (setq arg (1- arg)) 0)) |
2648 (> arg 0)) | 2582 ;; The search of BibTeX fields is not bounded by entry boundaries |
2649 (cond ((eq direction 'previous) | 2583 (if (eq direction 'previous) |
2650 (if (setq bounds (bibtex-search-backward-field field-name)) | 2584 (if (setq bounds (bibtex-search-backward-field field-name)) |
2651 (goto-char (bibtex-start-of-field bounds)) | 2585 (goto-char (bibtex-start-of-field bounds)) |
2652 (setq failure t))) | 2586 (setq failure t)) |
2653 ((eq direction 'next) | 2587 (if (setq bounds (bibtex-search-forward-field field-name)) |
2654 (if (setq bounds (bibtex-search-forward-field field-name)) | 2588 (goto-char (bibtex-end-of-field bounds)) |
2655 (goto-char (bibtex-end-of-field bounds)) | 2589 (setq failure t)))) |
2656 (setq failure t)))) | 2590 (if failure |
2657 (setq arg (- arg 1))) | 2591 (error "No %s matching BibTeX field" |
2658 (if failure | 2592 (if (eq direction 'previous) "previous" "next")) |
2659 (error "No %s matching BibTeX field" | 2593 ;; Found a matching field. Remember boundaries. |
2660 (if (eq direction 'previous) "previous" "next")) | 2594 (let ((new-text (bibtex-text-in-field-bounds bounds)) |
2661 ;; Found a matching field. Remember boundaries. | 2595 (nbeg (copy-marker (bibtex-start-of-field bounds))) |
2662 (setq bibtex-pop-previous-search-point (bibtex-start-of-field bounds) | 2596 (nend (copy-marker (bibtex-end-of-field bounds)))) |
2663 bibtex-pop-next-search-point (bibtex-end-of-field bounds) | 2597 (bibtex-flash-head "From: ") |
2664 new-text (bibtex-text-in-field-bounds bounds)) | |
2665 (bibtex-flash-head) | |
2666 ;; Go back to where we started, delete old text, and pop new. | 2598 ;; Go back to where we started, delete old text, and pop new. |
2667 (goto-char stop-old-text) | 2599 (goto-char end-old-text) |
2668 (delete-region start-old-text stop-old-text) | 2600 (delete-region start-old-text end-old-text) |
2669 (insert new-text))))) | 2601 (if (= nbeg start-old-field) |
2670 (bibtex-find-text) | 2602 (insert (bibtex-field-left-delimiter) |
2603 (bibtex-field-right-delimiter)) | |
2604 (insert new-text)) | |
2605 (setq bibtex-pop-previous-search-point (marker-position nbeg) | |
2606 bibtex-pop-next-search-point (marker-position nend)))))) | |
2607 (bibtex-find-text nil nil nil t) | |
2671 (setq this-command 'bibtex-pop)) | 2608 (setq this-command 'bibtex-pop)) |
2672 | 2609 |
2673 (defun bibtex-beginning-of-field () | 2610 (defun bibtex-beginning-of-field () |
2674 "Move point backward to beginning of field. | 2611 "Move point backward to beginning of field. |
2675 This function uses a simple, fast algorithm assuming that the field | 2612 This function uses a simple, fast algorithm assuming that the field |
2859 `bibtex-include-OPTkey', `bibtex-include-OPTcrossref', | 2796 `bibtex-include-OPTkey', `bibtex-include-OPTcrossref', |
2860 and `bibtex-user-optional-fields'." | 2797 and `bibtex-user-optional-fields'." |
2861 (let ((e (assoc-string entry-type bibtex-entry-field-alist t)) | 2798 (let ((e (assoc-string entry-type bibtex-entry-field-alist t)) |
2862 required optional) | 2799 required optional) |
2863 (unless e | 2800 (unless e |
2864 (error "BibTeX entry type %s not defined" entry-type)) | 2801 (error "Fields for BibTeX entry type %s not defined" entry-type)) |
2865 (if (and (member-ignore-case entry-type bibtex-include-OPTcrossref) | 2802 (if (and (member-ignore-case entry-type bibtex-include-OPTcrossref) |
2866 (nth 2 e)) | 2803 (nth 2 e)) |
2867 (setq required (nth 0 (nth 2 e)) | 2804 (setq required (nth 0 (nth 2 e)) |
2868 optional (nth 1 (nth 2 e))) | 2805 optional (nth 1 (nth 2 e))) |
2869 (setq required (nth 0 (nth 1 e)) | 2806 (setq required (nth 0 (nth 1 e)) |
2916 according to `bibtex-field-list', but are not yet present." | 2853 according to `bibtex-field-list', but are not yet present." |
2917 (interactive) | 2854 (interactive) |
2918 (save-excursion | 2855 (save-excursion |
2919 (bibtex-beginning-of-entry) | 2856 (bibtex-beginning-of-entry) |
2920 ;; For inserting new fields, we use the fact that | 2857 ;; For inserting new fields, we use the fact that |
2921 ;; bibtex-parse-entry moves point to the end of the last field. | 2858 ;; `bibtex-parse-entry' moves point to the end of the last field. |
2922 (let* ((fields-alist (bibtex-parse-entry)) | 2859 (let* ((fields-alist (bibtex-parse-entry)) |
2923 (field-list (bibtex-field-list | 2860 (field-list (bibtex-field-list |
2924 (cdr (assoc "=type=" fields-alist))))) | 2861 (cdr (assoc "=type=" fields-alist))))) |
2862 (skip-chars-backward " \t\n") | |
2925 (dolist (field (car field-list)) | 2863 (dolist (field (car field-list)) |
2926 (unless (assoc-string (car field) fields-alist t) | 2864 (unless (assoc-string (car field) fields-alist t) |
2927 (bibtex-make-field field))) | 2865 (bibtex-make-field field))) |
2928 (dolist (field (cdr field-list)) | 2866 (dolist (field (cdr field-list)) |
2929 (unless (assoc-string (car field) fields-alist t) | 2867 (unless (assoc-string (car field) fields-alist t) |
2962 (when (looking-at bibtex-entry-head) | 2900 (when (looking-at bibtex-entry-head) |
2963 (let ((type (bibtex-type-in-head)) | 2901 (let ((type (bibtex-type-in-head)) |
2964 (key (bibtex-key-in-head)) | 2902 (key (bibtex-key-in-head)) |
2965 (key-end (match-end bibtex-key-in-head)) | 2903 (key-end (match-end bibtex-key-in-head)) |
2966 (case-fold-search t) | 2904 (case-fold-search t) |
2905 (bibtex-sort-ignore-string-entries t) | |
2967 tmp other-key other bounds) | 2906 tmp other-key other bounds) |
2968 ;; The fields we want to change start right after the key. | 2907 ;; The fields we want to change start right after the key. |
2969 (goto-char key-end) | 2908 (goto-char key-end) |
2970 ;; First see whether to use the previous or the next entry | 2909 ;; First see whether to use the previous or the next entry |
2971 ;; for "inspiration". | 2910 ;; for "inspiration". |
3014 (suffix (substring key (length prefix))) | 2953 (suffix (substring key (length prefix))) |
3015 (other-suffix (substring other-key (length prefix)))) | 2954 (other-suffix (substring other-key (length prefix)))) |
3016 (while (re-search-backward (regexp-quote other-suffix) key-end 'move) | 2955 (while (re-search-backward (regexp-quote other-suffix) key-end 'move) |
3017 (replace-match suffix))))))) | 2956 (replace-match suffix))))))) |
3018 | 2957 |
3019 (defun bibtex-print-help-message () | 2958 (defun bibtex-print-help-message (&optional field comma) |
3020 "Print helpful information about current field in current BibTeX entry." | 2959 "Print helpful information about current FIELD in current BibTeX entry. |
3021 (interactive) | 2960 Optional arg COMMA is as in `bibtex-enclosing-field'. It is t for |
3022 (let* ((case-fold-search t) | 2961 interactive calls." |
3023 (type (save-excursion | 2962 (interactive (list nil t)) |
3024 (bibtex-beginning-of-entry) | 2963 (unless field (setq field (car (bibtex-find-text-internal nil nil comma)))) |
3025 (looking-at bibtex-any-entry-maybe-empty-head) | 2964 (if (string-match "@" field) |
3026 (bibtex-type-in-head))) | 2965 (cond ((bibtex-string= field "@string") |
3027 comment field-list) | 2966 (message "String definition")) |
3028 (cond ((bibtex-string= type "string") | 2967 ((bibtex-string= field "@preamble") |
3029 (message "String definition")) | 2968 (message "Preamble definition")) |
3030 ((bibtex-string= type "preamble") | 2969 (t (message "Entry key"))) |
3031 (message "Preamble definition")) | 2970 (let* ((case-fold-search t) |
3032 (t | 2971 (type (save-excursion |
3033 (setq field-list (bibtex-field-list type) | 2972 (bibtex-beginning-of-entry) |
3034 comment | 2973 (looking-at bibtex-entry-maybe-empty-head) |
3035 (assoc-string (bibtex-name-in-field (bibtex-enclosing-field) t) | 2974 (bibtex-type-in-head))) |
3036 (append (car field-list) (cdr field-list)) | 2975 (field-list (bibtex-field-list type)) |
3037 t)) | 2976 (comment (assoc-string field (append (car field-list) |
3038 (if comment | 2977 (cdr field-list)) t))) |
3039 (message "%s" (nth 1 comment)) | 2978 (if comment (message "%s" (nth 1 comment)) |
3040 (message "No comment available")))))) | 2979 (message "No comment available"))))) |
3041 | 2980 |
3042 (defun bibtex-make-field (field &optional move interactive) | 2981 (defun bibtex-make-field (field &optional move interactive) |
3043 "Make a field named FIELD in current BibTeX entry. | 2982 "Make a field named FIELD in current BibTeX entry. |
3044 FIELD is either a string or a list of the form | 2983 FIELD is either a string or a list of the form |
3045 \(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in | 2984 \(FIELD-NAME COMMENT-STRING INIT ALTERNATIVE-FLAG) as in |
3050 MOVE and INTERACTIVE are t when called interactively." | 2989 MOVE and INTERACTIVE are t when called interactively." |
3051 (interactive | 2990 (interactive |
3052 (list (let ((completion-ignore-case t) | 2991 (list (let ((completion-ignore-case t) |
3053 (field-list (bibtex-field-list | 2992 (field-list (bibtex-field-list |
3054 (save-excursion | 2993 (save-excursion |
3055 (bibtex-enclosing-entry-maybe-empty-head) | 2994 (bibtex-beginning-of-entry) |
2995 (looking-at bibtex-any-entry-maybe-empty-head) | |
3056 (bibtex-type-in-head))))) | 2996 (bibtex-type-in-head))))) |
3057 (completing-read "BibTeX field name: " | 2997 (completing-read "BibTeX field name: " |
3058 (append (car field-list) (cdr field-list)) | 2998 (append (car field-list) (cdr field-list)) |
3059 nil nil nil bibtex-field-history)) | 2999 nil nil nil bibtex-field-history)) |
3060 t t)) | 3000 t t)) |
3079 (insert (cond ((stringp init) init) | 3019 (insert (cond ((stringp init) init) |
3080 ((fboundp init) (funcall init)) | 3020 ((fboundp init) (funcall init)) |
3081 (t (concat (bibtex-field-left-delimiter) | 3021 (t (concat (bibtex-field-left-delimiter) |
3082 (bibtex-field-right-delimiter)))))) | 3022 (bibtex-field-right-delimiter)))))) |
3083 (when interactive | 3023 (when interactive |
3084 (forward-char -1) | 3024 ;; (bibtex-find-text nil nil bibtex-help-message) |
3085 (bibtex-print-help-message))) | 3025 (if (memq (preceding-char) '(?} ?\")) (forward-char -1)) |
3026 (if bibtex-help-message (bibtex-print-help-message (car field))))) | |
3086 | 3027 |
3087 (defun bibtex-beginning-of-entry () | 3028 (defun bibtex-beginning-of-entry () |
3088 "Move to beginning of BibTeX entry (beginning of line). | 3029 "Move to beginning of BibTeX entry (beginning of line). |
3089 If inside an entry, move to the beginning of it, otherwise move to the | 3030 If inside an entry, move to the beginning of it, otherwise move to the |
3090 beginning of the previous entry. If point is ahead of all BibTeX entries | 3031 beginning of the previous entry. If point is ahead of all BibTeX entries |
3101 If inside an entry, move to the end of it, otherwise move to the end | 3042 If inside an entry, move to the end of it, otherwise move to the end |
3102 of the previous entry. Do not move if ahead of first entry. | 3043 of the previous entry. Do not move if ahead of first entry. |
3103 Return the new location of point." | 3044 Return the new location of point." |
3104 (interactive) | 3045 (interactive) |
3105 (let ((case-fold-search t) | 3046 (let ((case-fold-search t) |
3106 (org (point)) | 3047 (pnt (point)) |
3107 (pnt (bibtex-beginning-of-entry)) | 3048 (_ (bibtex-beginning-of-entry)) |
3108 err bounds) | 3049 (bounds (bibtex-valid-entry t))) |
3109 (cond ((looking-at bibtex-entry-type-whitespace) | 3050 (cond (bounds (goto-char (cdr bounds))) ; regular entry |
3110 (bibtex-search-entry t nil t) | 3051 ;; @String or @Preamble |
3111 (unless (equal (match-beginning 0) pnt) | 3052 ((setq bounds (or (bibtex-parse-string t) (bibtex-parse-preamble))) |
3112 (setq err t))) | |
3113 ;; @String | |
3114 ((setq bounds (bibtex-parse-string)) | |
3115 (goto-char (bibtex-end-of-string bounds))) | 3053 (goto-char (bibtex-end-of-string bounds))) |
3116 ;; @Preamble | 3054 ((looking-at bibtex-any-valid-entry-type) |
3117 ((bibtex-preamble-prefix t) | 3055 ;; Parsing of entry failed |
3118 (unless (bibtex-parse-string-postfix) ;; @String postfix OK | 3056 (error "Syntactically incorrect BibTeX entry starts here.")) |
3119 (setq err t))) | 3057 (t (if (interactive-p) (message "Not on a known BibTeX entry.")) |
3120 (t | 3058 (goto-char pnt))) |
3121 (if (interactive-p) | 3059 (point))) |
3122 (message "Not on a known BibTeX entry.")) | |
3123 (goto-char org))) | |
3124 (when err | |
3125 (goto-char pnt) | |
3126 (error "Syntactically incorrect BibTeX entry starts here"))) | |
3127 (point)) | |
3128 | 3060 |
3129 (defun bibtex-goto-line (arg) | 3061 (defun bibtex-goto-line (arg) |
3130 "Goto line ARG, counting from beginning of (narrowed) buffer." | 3062 "Goto line ARG, counting from beginning of (narrowed) buffer." |
3131 ;; code adapted from `goto-line' | 3063 ;; code adapted from `goto-line' |
3132 (goto-char (point-min)) | 3064 (goto-char (point-min)) |
3186 (defun bibtex-ispell-abstract () | 3118 (defun bibtex-ispell-abstract () |
3187 "Check abstract of BibTeX entry for spelling errors." | 3119 "Check abstract of BibTeX entry for spelling errors." |
3188 (interactive) | 3120 (interactive) |
3189 (let ((bounds (save-excursion | 3121 (let ((bounds (save-excursion |
3190 (bibtex-beginning-of-entry) | 3122 (bibtex-beginning-of-entry) |
3191 (bibtex-search-forward-field "abstract")))) | 3123 (bibtex-search-forward-field "abstract" t)))) |
3192 (if bounds | 3124 (if bounds |
3193 (ispell-region (bibtex-start-of-text-in-field bounds) | 3125 (ispell-region (bibtex-start-of-text-in-field bounds) |
3194 (bibtex-end-of-text-in-field bounds)) | 3126 (bibtex-end-of-text-in-field bounds)) |
3195 (error "No abstract in entry")))) | 3127 (error "No abstract in entry")))) |
3196 | 3128 |
3214 ;; all entry names should be downcase (for ease of comparison) | 3146 ;; all entry names should be downcase (for ease of comparison) |
3215 (entry-name (downcase (bibtex-type-in-head)))) | 3147 (entry-name (downcase (bibtex-type-in-head)))) |
3216 ;; Don't search CROSSREF-KEY if we don't need it. | 3148 ;; Don't search CROSSREF-KEY if we don't need it. |
3217 (if (eq bibtex-maintain-sorted-entries 'crossref) | 3149 (if (eq bibtex-maintain-sorted-entries 'crossref) |
3218 (let ((bounds (bibtex-search-forward-field | 3150 (let ((bounds (bibtex-search-forward-field |
3219 "\\(OPT\\)?crossref"))) | 3151 "\\(OPT\\)?crossref" t))) |
3220 (list key | 3152 (list key |
3221 (if bounds (bibtex-text-in-field-bounds bounds t)) | 3153 (if bounds (bibtex-text-in-field-bounds bounds t)) |
3222 entry-name)) | 3154 entry-name)) |
3223 (list key nil entry-name)))))) | 3155 (list key nil entry-name)))))) |
3224 | 3156 |
3281 entry and SPLIT is t." | 3213 entry and SPLIT is t." |
3282 (interactive | 3214 (interactive |
3283 (let ((crossref-key | 3215 (let ((crossref-key |
3284 (save-excursion | 3216 (save-excursion |
3285 (bibtex-beginning-of-entry) | 3217 (bibtex-beginning-of-entry) |
3286 (let ((bounds (bibtex-search-forward-field "crossref"))) | 3218 (let ((bounds (bibtex-search-forward-field "crossref" t))) |
3287 (if bounds | 3219 (if bounds |
3288 (bibtex-text-in-field-bounds bounds t)))))) | 3220 (bibtex-text-in-field-bounds bounds t)))))) |
3289 (list (bibtex-read-key "Find crossref key: " crossref-key t) | 3221 (list (bibtex-read-key "Find crossref key: " crossref-key t) |
3290 (point) t))) | 3222 (point) t))) |
3291 (let (buffer pos eqb) | 3223 (let (buffer pos eqb) |
3427 (interactive "P") | 3359 (interactive "P") |
3428 (let* ((case-fold-search t) | 3360 (let* ((case-fold-search t) |
3429 error-list syntax-error) | 3361 error-list syntax-error) |
3430 (save-excursion | 3362 (save-excursion |
3431 (save-restriction | 3363 (save-restriction |
3432 (if mark-active | 3364 (if mark-active (narrow-to-region (region-beginning) (region-end))) |
3433 (narrow-to-region (region-beginning) (region-end))) | 3365 |
3434 | 3366 ;; Check syntactical structure of entries |
3435 ;; looking if entries fit syntactical structure | |
3436 (goto-char (point-min)) | 3367 (goto-char (point-min)) |
3437 (bibtex-progress-message "Checking syntactical structure") | 3368 (bibtex-progress-message "Checking syntactical structure") |
3438 (let (bibtex-sort-ignore-string-entries) | 3369 (let (bounds end) |
3439 (while (re-search-forward "^[ \t]*@" nil t) | 3370 (while (setq end (re-search-forward "^[ \t]*@" nil t)) |
3440 (bibtex-progress-message) | 3371 (bibtex-progress-message) |
3441 (forward-char -1) | 3372 (goto-char (match-beginning 0)) |
3442 (let ((pnt (point))) | 3373 (cond ((setq bounds (bibtex-valid-entry)) |
3443 (if (not (looking-at bibtex-entry-type-str)) | 3374 (goto-char (cdr bounds))) |
3444 (forward-char) | 3375 ((setq bounds (or (bibtex-parse-string) |
3445 (bibtex-skip-to-valid-entry) | 3376 (bibtex-parse-preamble))) |
3446 (if (equal (point) pnt) | 3377 (goto-char (bibtex-end-of-string bounds))) |
3447 (forward-char) | 3378 ((looking-at bibtex-any-valid-entry-type) |
3448 (goto-char pnt) | 3379 (push (cons (bibtex-current-line) |
3449 (push (cons (bibtex-current-line) | 3380 "Syntax error (check esp. commas, braces, and quotes)") |
3450 "Syntax error (check esp. commas, braces, and quotes)") | 3381 error-list) |
3451 error-list) | 3382 (goto-char (match-end 0))) |
3452 (forward-char)))))) | 3383 (t (goto-char end))))) |
3453 (bibtex-progress-message 'done) | 3384 (bibtex-progress-message 'done) |
3454 | 3385 |
3455 (if error-list | 3386 (if error-list |
3456 ;; proceed only if there were no syntax errors. | 3387 ;; Continue only if there were no syntax errors. |
3457 (setq syntax-error t) | 3388 (setq syntax-error t) |
3458 | 3389 |
3459 ;; looking for duplicate keys and correct sort order | 3390 ;; Check for duplicate keys and correct sort order |
3460 (let (previous current key-list) | 3391 (let (previous current key-list) |
3461 (bibtex-progress-message "Checking for duplicate keys") | 3392 (bibtex-progress-message "Checking for duplicate keys") |
3462 (bibtex-map-entries | 3393 (bibtex-map-entries |
3463 (lambda (key beg end) | 3394 (lambda (key beg end) |
3464 (bibtex-progress-message) | 3395 (bibtex-progress-message) |
3465 (goto-char beg) | |
3466 (setq current (bibtex-entry-index)) | 3396 (setq current (bibtex-entry-index)) |
3467 (cond ((not previous)) | 3397 (cond ((not previous)) |
3468 ((member key key-list) | 3398 ((member key key-list) |
3469 (push (cons (bibtex-current-line) | 3399 (push (cons (bibtex-current-line) |
3470 (format "Duplicate key `%s'" key)) | 3400 (format "Duplicate key `%s'" key)) |
3496 "Checking required fields and month fields") | 3426 "Checking required fields and month fields") |
3497 (let ((bibtex-sort-ignore-string-entries t)) | 3427 (let ((bibtex-sort-ignore-string-entries t)) |
3498 (bibtex-map-entries | 3428 (bibtex-map-entries |
3499 (lambda (key beg end) | 3429 (lambda (key beg end) |
3500 (bibtex-progress-message) | 3430 (bibtex-progress-message) |
3501 (let* ((entry-list (progn | 3431 (let* ((entry-list (assoc-string (bibtex-type-in-head) |
3502 (goto-char beg) | 3432 bibtex-entry-field-alist t)) |
3503 (bibtex-search-entry nil end) | |
3504 (assoc-string (bibtex-type-in-head) | |
3505 bibtex-entry-field-alist t))) | |
3506 (req (copy-sequence (elt (elt entry-list 1) 0))) | 3433 (req (copy-sequence (elt (elt entry-list 1) 0))) |
3507 (creq (copy-sequence (elt (elt entry-list 2) 0))) | 3434 (creq (copy-sequence (elt (elt entry-list 2) 0))) |
3508 crossref-there bounds alt-there field) | 3435 crossref-there bounds alt-there field) |
3509 (goto-char beg) | 3436 (bibtex-beginning-first-field beg) |
3510 (while (setq bounds (bibtex-search-forward-field | 3437 (while (setq bounds (bibtex-parse-field)) |
3511 bibtex-field-name end)) | |
3512 (goto-char (bibtex-start-of-text-in-field bounds)) | |
3513 (let ((field-name (bibtex-name-in-field bounds))) | 3438 (let ((field-name (bibtex-name-in-field bounds))) |
3514 (if (and (bibtex-string= field-name "month") | 3439 (if (and (bibtex-string= field-name "month") |
3515 ;; Check only abbreviated month fields. | 3440 ;; Check only abbreviated month fields. |
3516 (let ((month (bibtex-text-in-field-bounds bounds))) | 3441 (let ((month (bibtex-text-in-field-bounds bounds))) |
3517 (not (or (string-match "\\`[\"{].+[\"}]\\'" month) | 3442 (not (or (string-match "\\`[\"{].+[\"}]\\'" month) |
3519 month | 3444 month |
3520 bibtex-predefined-month-strings t))))) | 3445 bibtex-predefined-month-strings t))))) |
3521 (push (cons (bibtex-current-line) | 3446 (push (cons (bibtex-current-line) |
3522 "Questionable month field") | 3447 "Questionable month field") |
3523 error-list)) | 3448 error-list)) |
3524 (setq field (assoc-string field-name req t)) | 3449 (setq field (assoc-string field-name req t) |
3450 req (delete field req) | |
3451 creq (delete (assoc-string field-name creq t) creq)) | |
3525 (if (nth 3 field) | 3452 (if (nth 3 field) |
3526 (if alt-there (push (cons (bibtex-current-line) | 3453 (if alt-there |
3527 "More than one non-empty alternative") | 3454 (push (cons (bibtex-current-line) |
3528 error-list) | 3455 "More than one non-empty alternative") |
3456 error-list) | |
3529 (setq alt-there t))) | 3457 (setq alt-there t))) |
3530 (setq req (delete field req) | |
3531 creq (delete (assoc-string field-name creq t) creq)) | |
3532 (if (bibtex-string= field-name "crossref") | 3458 (if (bibtex-string= field-name "crossref") |
3533 (setq crossref-there t)))) | 3459 (setq crossref-there t))) |
3534 (if crossref-there | 3460 (goto-char (bibtex-end-of-field bounds))) |
3535 (setq req creq)) | 3461 (if crossref-there (setq req creq)) |
3536 (let (alt) | 3462 (let (alt) |
3537 (dolist (field req) | 3463 (dolist (field req) |
3538 (if (nth 3 field) | 3464 (if (nth 3 field) |
3539 (push (car field) alt) | 3465 (push (car field) alt) |
3540 (push (cons (save-excursion (goto-char beg) | 3466 (push (cons (save-excursion (goto-char beg) |
3571 (insert (format "%s:%d: %s\n" file (car err) (cdr err)))) | 3497 (insert (format "%s:%d: %s\n" file (car err) (cdr err)))) |
3572 (set-buffer-modified-p nil) | 3498 (set-buffer-modified-p nil) |
3573 (toggle-read-only 1) | 3499 (toggle-read-only 1) |
3574 (goto-line 3)) ; first error message | 3500 (goto-line 3)) ; first error message |
3575 (display-buffer err-buf) | 3501 (display-buffer err-buf) |
3576 ;; return nil | 3502 nil) ; return `nil' (i.e., buffer is invalid) |
3577 nil) | |
3578 (message "%s is syntactically correct" | 3503 (message "%s is syntactically correct" |
3579 (if mark-active "Region" "Buffer")) | 3504 (if mark-active "Region" "Buffer")) |
3580 t))) | 3505 t))) ; return `t' (i.e., buffer is valid) |
3581 | 3506 |
3582 (defun bibtex-validate-globally (&optional strings) | 3507 (defun bibtex-validate-globally (&optional strings) |
3583 "Check for duplicate keys in `bibtex-files'. | 3508 "Check for duplicate keys in `bibtex-files'. |
3584 With optional prefix arg STRINGS, check for duplicate strings, too. | 3509 With optional prefix arg STRINGS, check for duplicate strings, too. |
3585 Return t if test was successful, nil otherwise." | 3510 Return t if test was successful, nil otherwise." |
3629 (dolist (err (sort error-list 'string-lessp)) (insert err)) | 3554 (dolist (err (sort error-list 'string-lessp)) (insert err)) |
3630 (set-buffer-modified-p nil) | 3555 (set-buffer-modified-p nil) |
3631 (toggle-read-only 1) | 3556 (toggle-read-only 1) |
3632 (goto-line 3)) ; first error message | 3557 (goto-line 3)) ; first error message |
3633 (display-buffer err-buf) | 3558 (display-buffer err-buf) |
3634 ;; return nil | 3559 nil) ; return `nil' (i.e., buffer is invalid) |
3635 nil) | |
3636 (message "No duplicate keys.") | 3560 (message "No duplicate keys.") |
3637 t))) | 3561 t))) ; return `t' (i.e., buffer is valid) |
3638 | 3562 |
3639 (defun bibtex-next-field (begin) | 3563 (defun bibtex-next-field (begin &optional comma) |
3640 "Move point to end of text of next BibTeX field. | 3564 "Move point to end of text of next BibTeX field or entry head. |
3641 With prefix BEGIN non-nil, move point to its beginning." | 3565 With prefix BEGIN non-nil, move point to its beginning. Optional arg COMMA |
3642 (interactive "P") | 3566 is as in `bibtex-enclosing-field'. It is t for interactive calls." |
3643 (bibtex-inside-field) | 3567 (interactive (list current-prefix-arg t)) |
3644 (let ((start (point))) | 3568 (let ((bounds (bibtex-find-text-internal t nil comma)) |
3645 (condition-case () | 3569 end-of-entry) |
3646 (let ((bounds (bibtex-enclosing-field))) | 3570 (if (not bounds) |
3647 (goto-char (bibtex-end-of-field bounds)) | 3571 (setq end-of-entry t) |
3648 (forward-char 2)) | 3572 (goto-char (nth 3 bounds)) |
3649 (error | 3573 (if (assoc-string (car bounds) '("@String" "@Preamble") t) |
3650 (goto-char start) | 3574 (setq end-of-entry t) |
3651 (end-of-line) | 3575 ;; BibTeX key or field |
3652 (forward-char)))) | 3576 (if (looking-at ",[ \t\n]*") (goto-char (match-end 0))) |
3653 (bibtex-find-text begin nil bibtex-help-message)) | 3577 ;; end of entry |
3654 | 3578 (if (looking-at "[)}][ \t\n]*") (setq end-of-entry t)))) |
3655 (defun bibtex-find-text (&optional begin noerror help) | 3579 (if (and end-of-entry |
3656 "Move point to end of text of current BibTeX field. | 3580 (re-search-forward bibtex-any-entry-maybe-empty-head nil t)) |
3581 (goto-char (match-beginning 0))) | |
3582 (bibtex-find-text begin nil bibtex-help-message))) | |
3583 | |
3584 (defun bibtex-find-text (&optional begin noerror help comma) | |
3585 "Move point to end of text of current BibTeX field or entry head. | |
3657 With optional prefix BEGIN non-nil, move point to its beginning. | 3586 With optional prefix BEGIN non-nil, move point to its beginning. |
3658 Unless NOERROR is non-nil, an error is signaled if point is not | 3587 Unless NOERROR is non-nil, an error is signaled if point is not |
3659 on a BibTeX field. If optional arg HELP is non-nil print help message. | 3588 on a BibTeX field. If optional arg HELP is non-nil print help message. |
3660 When called interactively, the value of HELP is `bibtex-help-message'." | 3589 When called interactively, the value of HELP is `bibtex-help-message'. |
3661 (interactive (list current-prefix-arg nil bibtex-help-message)) | 3590 Optional arg COMMA is as in `bibtex-enclosing-field'. It is t for |
3662 (let ((pnt (point)) | 3591 interactive calls." |
3663 (bounds (bibtex-find-text-internal))) | 3592 (interactive (list current-prefix-arg nil bibtex-help-message t)) |
3664 (beginning-of-line) | 3593 (let ((bounds (bibtex-find-text-internal t nil comma))) |
3665 (cond (bounds | 3594 (cond (bounds |
3666 (if begin | 3595 (if begin |
3667 (progn (goto-char (nth 1 bounds)) | 3596 (progn (goto-char (nth 1 bounds)) |
3668 (if (looking-at "[{\"]") | 3597 (if (looking-at "[{\"]") |
3669 (forward-char))) | 3598 (forward-char))) |
3670 (goto-char (nth 2 bounds)) | 3599 (goto-char (nth 2 bounds)) |
3671 (if (memq (preceding-char) '(?} ?\")) | 3600 (if (memq (preceding-char) '(?} ?\")) |
3672 (forward-char -1))) | 3601 (forward-char -1))) |
3673 (if help (bibtex-print-help-message))) | 3602 (if help (bibtex-print-help-message (car bounds)))) |
3674 ((looking-at bibtex-entry-maybe-empty-head) | 3603 ((not noerror) (error "Not on BibTeX field"))))) |
3675 (goto-char (if begin | 3604 |
3676 (match-beginning bibtex-key-in-head) | 3605 (defun bibtex-find-text-internal (&optional noerror subfield comma) |
3677 (match-end 0)))) | 3606 "Find text part of current BibTeX field or entry head. |
3678 (t | 3607 Return list (NAME START-TEXT END-TEXT END) with field or entry name, |
3679 (goto-char pnt) | 3608 start and end of text and end of field or entry head, or nil if not found. |
3680 (unless noerror (error "Not on BibTeX field")))))) | |
3681 | |
3682 (defun bibtex-find-text-internal (&optional noerror subfield) | |
3683 "Find text part of current BibTeX field, @String or @Preamble. | |
3684 Return list (NAME START END) with field name, start and end of text | |
3685 or nil if not found. | |
3686 If optional arg NOERROR is non-nil, an error message is suppressed if text | 3609 If optional arg NOERROR is non-nil, an error message is suppressed if text |
3687 is not found. If optional arg SUBFIELD is non-nil START and END correspond | 3610 is not found. If optional arg SUBFIELD is non-nil START-TEXT and END-TEXT |
3688 to the current subfield delimited by #." | 3611 correspond to the current subfield delimited by #. |
3612 Optional arg COMMA is as in `bibtex-enclosing-field'." | |
3689 (save-excursion | 3613 (save-excursion |
3690 (let ((pnt (point)) | 3614 (let ((pnt (point)) |
3691 (_ (bibtex-inside-field)) | 3615 (bounds (bibtex-enclosing-field comma t)) |
3692 (bounds (bibtex-enclosing-field t)) | |
3693 (case-fold-search t) | 3616 (case-fold-search t) |
3694 (bibtex-string-empty-key t) | 3617 name start-text end-text end failure done no-sub) |
3695 name start end) | |
3696 (bibtex-beginning-of-entry) | 3618 (bibtex-beginning-of-entry) |
3697 (cond (bounds | 3619 (cond (bounds |
3698 (setq name (bibtex-name-in-field bounds t) | 3620 (setq name (bibtex-name-in-field bounds t) |
3699 start (bibtex-start-of-text-in-field bounds) | 3621 start-text (bibtex-start-of-text-in-field bounds) |
3700 end (bibtex-end-of-text-in-field bounds))) | 3622 end-text (bibtex-end-of-text-in-field bounds) |
3623 end (bibtex-end-of-field bounds))) | |
3701 ;; @String | 3624 ;; @String |
3702 ((setq bounds (bibtex-parse-string)) | 3625 ((setq bounds (bibtex-parse-string t)) |
3703 (setq name "@String" ;; not a field name! | 3626 (if (<= pnt (bibtex-end-of-string bounds)) |
3704 start (bibtex-start-of-text-in-string bounds) | 3627 (setq name "@String" ;; not a field name! |
3705 end (bibtex-end-of-text-in-string bounds))) | 3628 start-text (bibtex-start-of-text-in-string bounds) |
3629 end-text (bibtex-end-of-text-in-string bounds) | |
3630 end (bibtex-end-of-string bounds)) | |
3631 (setq failure t))) | |
3706 ;; @Preamble | 3632 ;; @Preamble |
3707 ((and (bibtex-preamble-prefix t) | 3633 ((setq bounds (bibtex-parse-preamble)) |
3708 (setq bounds (bibtex-parse-field-text))) | 3634 (if (<= pnt (bibtex-end-of-string bounds)) |
3709 (setq name "@Preamble" ;; not a field name! | 3635 (setq name "@Preamble" ;; not a field name! |
3710 start (car bounds) | 3636 start-text (bibtex-start-of-text-in-string bounds) |
3711 end (nth 1 bounds))) | 3637 end-text (bibtex-end-of-text-in-string bounds) |
3712 (t (unless noerror (error "Not on BibTeX field")))) | 3638 end (bibtex-end-of-string bounds)) |
3713 (when (and start end subfield) | 3639 (setq failure t))) |
3714 (goto-char start) | 3640 ;; BibTeX head |
3715 (let (done) | 3641 ((looking-at bibtex-entry-maybe-empty-head) |
3642 (goto-char (match-end 0)) | |
3643 (if comma (save-match-data | |
3644 (re-search-forward "\\=[ \t\n]*," nil t))) | |
3645 (if (<= pnt (point)) | |
3646 (setq name (match-string-no-properties bibtex-type-in-head) | |
3647 start-text (or (match-beginning bibtex-key-in-head) | |
3648 (match-end 0)) | |
3649 end-text (or (match-end bibtex-key-in-head) | |
3650 (match-end 0)) | |
3651 end end-text | |
3652 no-sub t) ;; subfields do not make sense | |
3653 (setq failure t))) | |
3654 (t (setq failure t))) | |
3655 (when (and subfield (not failure)) | |
3656 (setq failure no-sub) | |
3657 (unless failure | |
3658 (goto-char start-text) | |
3716 (while (not done) | 3659 (while (not done) |
3717 (if (or (prog1 (looking-at bibtex-field-const) | 3660 (if (or (prog1 (looking-at bibtex-field-const) |
3718 (setq end (match-end 0))) | 3661 (setq end-text (match-end 0))) |
3719 (prog1 (setq bounds (bibtex-parse-field-string)) | 3662 (prog1 (setq bounds (bibtex-parse-field-string)) |
3720 (setq end (cdr bounds)))) | 3663 (setq end-text (cdr bounds)))) |
3721 (progn | 3664 (progn |
3722 (if (and (<= start pnt) (<= pnt end)) | 3665 (if (and (<= start-text pnt) (<= pnt end-text)) |
3723 (setq done t) | 3666 (setq done t) |
3724 (goto-char end)) | 3667 (goto-char end-text)) |
3725 (if (looking-at "[ \t\n]*#[ \t\n]*") | 3668 (if (looking-at "[ \t\n]*#[ \t\n]*") |
3726 (setq start (goto-char (match-end 0))))) | 3669 (setq start-text (goto-char (match-end 0))))) |
3727 (unless noerror (error "Not on text part of BibTeX field")) | 3670 (setq done t failure t))))) |
3728 (setq done t start nil end nil))))) | 3671 (cond ((not failure) |
3729 (if (and start end) | 3672 (list name start-text end-text end)) |
3730 (list name start end))))) | 3673 ((and no-sub (not noerror)) |
3731 | 3674 (error "Not on text part of BibTeX field")) |
3732 (defun bibtex-remove-OPT-or-ALT () | 3675 ((not noerror) (error "Not on BibTeX field")))))) |
3676 | |
3677 (defun bibtex-remove-OPT-or-ALT (&optional comma) | |
3733 "Remove the string starting optional/alternative fields. | 3678 "Remove the string starting optional/alternative fields. |
3734 Align text and go thereafter to end of text." | 3679 Align text and go thereafter to end of text. Optional arg COMMA |
3735 (interactive) | 3680 is as in `bibtex-enclosing-field'. It is t for interactive calls." |
3736 (bibtex-inside-field) | 3681 (interactive (list t)) |
3737 (let ((case-fold-search t) | 3682 (let ((case-fold-search t) |
3738 (bounds (bibtex-enclosing-field))) | 3683 (bounds (bibtex-enclosing-field comma))) |
3739 (save-excursion | 3684 (save-excursion |
3740 (goto-char (bibtex-start-of-name-in-field bounds)) | 3685 (goto-char (bibtex-start-of-name-in-field bounds)) |
3741 (when (looking-at "OPT\\|ALT") | 3686 (when (looking-at "OPT\\|ALT") |
3742 (delete-region (match-beginning 0) (match-end 0)) | 3687 (delete-region (match-beginning 0) (match-end 0)) |
3743 ;; make field non-OPT | 3688 ;; make field non-OPT |
3749 (insert " ")) | 3694 (insert " ")) |
3750 (search-forward "=") | 3695 (search-forward "=") |
3751 (delete-horizontal-space) | 3696 (delete-horizontal-space) |
3752 (if bibtex-align-at-equal-sign | 3697 (if bibtex-align-at-equal-sign |
3753 (insert " ") | 3698 (insert " ") |
3754 (indent-to-column bibtex-text-indentation)))) | 3699 (indent-to-column bibtex-text-indentation)))))) |
3755 (bibtex-inside-field))) | 3700 |
3756 | 3701 (defun bibtex-remove-delimiters (&optional comma) |
3757 (defun bibtex-remove-delimiters () | 3702 "Remove \"\" or {} around current BibTeX field text. |
3758 "Remove \"\" or {} around current BibTeX field text." | 3703 Optional arg COMMA is as in `bibtex-enclosing-field'. It is t for |
3759 (interactive) | 3704 interactive calls." |
3760 ;; `bibtex-find-text-internal' issues an error message if bounds is nil. | 3705 (interactive (list t)) |
3761 (let* ((bounds (bibtex-find-text-internal nil t)) | 3706 (let* ((bounds (bibtex-find-text-internal nil t comma)) |
3762 (start (nth 1 bounds)) | 3707 (start (nth 1 bounds)) |
3763 (end (nth 2 bounds))) | 3708 (end (nth 2 bounds))) |
3764 (if (memq (char-before end) '(?\} ?\")) | 3709 (if (memq (char-before end) '(?\} ?\")) |
3765 (delete-region (1- end) end)) | 3710 (delete-region (1- end) end)) |
3766 (if (memq (char-after start) '(?\{ ?\")) | 3711 (if (memq (char-after start) '(?\{ ?\")) |
3767 (delete-region start (1+ start))))) | 3712 (delete-region start (1+ start))))) |
3768 | 3713 |
3769 (defun bibtex-kill-field (&optional copy-only) | 3714 (defun bibtex-kill-field (&optional copy-only comma) |
3770 "Kill the entire enclosing BibTeX field. | 3715 "Kill the entire enclosing BibTeX field. |
3771 With prefix arg COPY-ONLY, copy the current field to `bibtex-field-kill-ring', | 3716 With prefix arg COPY-ONLY, copy the current field to `bibtex-field-kill-ring', |
3772 but do not actually kill it." | 3717 but do not actually kill it. Optional arg COMMA is as in |
3773 (interactive "P") | 3718 `bibtex-enclosing-field'. It is t for interactive calls." |
3719 (interactive (list current-prefix-arg t)) | |
3774 (save-excursion | 3720 (save-excursion |
3775 (bibtex-inside-field) | |
3776 (let* ((case-fold-search t) | 3721 (let* ((case-fold-search t) |
3777 (bounds (bibtex-enclosing-field)) | 3722 (bounds (bibtex-enclosing-field comma)) |
3778 (end (bibtex-end-of-field bounds)) | 3723 (end (bibtex-end-of-field bounds)) |
3779 (beg (bibtex-start-of-field bounds))) | 3724 (beg (bibtex-start-of-field bounds))) |
3780 (goto-char end) | 3725 (goto-char end) |
3781 (skip-chars-forward ",") | 3726 (skip-chars-forward ",") |
3782 (push (list (bibtex-name-in-field bounds) nil | 3727 (push (list (bibtex-name-in-field bounds) nil |
3789 (setq bibtex-field-kill-ring-yank-pointer bibtex-field-kill-ring) | 3734 (setq bibtex-field-kill-ring-yank-pointer bibtex-field-kill-ring) |
3790 (unless copy-only | 3735 (unless copy-only |
3791 (delete-region beg end)))) | 3736 (delete-region beg end)))) |
3792 (setq bibtex-last-kill-command 'field)) | 3737 (setq bibtex-last-kill-command 'field)) |
3793 | 3738 |
3794 (defun bibtex-copy-field-as-kill () | 3739 (defun bibtex-copy-field-as-kill (&optional comma) |
3795 "Copy the BibTeX field at point to the kill ring." | 3740 "Copy the BibTeX field at point to the kill ring. |
3796 (interactive) | 3741 Optional arg COMMA is as in `bibtex-enclosing-field'. It is t for |
3797 (bibtex-kill-field t)) | 3742 interactive calls." |
3743 (interactive (list t)) | |
3744 (bibtex-kill-field t comma)) | |
3798 | 3745 |
3799 (defun bibtex-kill-entry (&optional copy-only) | 3746 (defun bibtex-kill-entry (&optional copy-only) |
3800 "Kill the entire enclosing BibTeX entry. | 3747 "Kill the entire enclosing BibTeX entry. |
3801 With prefix arg COPY-ONLY, copy the current entry to `bibtex-entry-kill-ring', | 3748 With prefix arg COPY-ONLY, copy the current entry to `bibtex-entry-kill-ring', |
3802 but do not actually kill it." | 3749 but do not actually kill it." |
3804 (save-excursion | 3751 (save-excursion |
3805 (let* ((case-fold-search t) | 3752 (let* ((case-fold-search t) |
3806 (beg (bibtex-beginning-of-entry)) | 3753 (beg (bibtex-beginning-of-entry)) |
3807 (end (progn (bibtex-end-of-entry) | 3754 (end (progn (bibtex-end-of-entry) |
3808 (if (re-search-forward | 3755 (if (re-search-forward |
3809 bibtex-entry-maybe-empty-head nil 'move) | 3756 bibtex-any-entry-maybe-empty-head nil 'move) |
3810 (goto-char (match-beginning 0))) | 3757 (goto-char (match-beginning 0))) |
3811 (point)))) | 3758 (point)))) |
3812 (push (buffer-substring-no-properties beg end) | 3759 (push (buffer-substring-no-properties beg end) |
3813 bibtex-entry-kill-ring) | 3760 bibtex-entry-kill-ring) |
3814 (if (> (length bibtex-entry-kill-ring) bibtex-entry-kill-ring-max) | 3761 (if (> (length bibtex-entry-kill-ring) bibtex-entry-kill-ring-max) |
3829 "Reinsert the last BibTeX item. | 3776 "Reinsert the last BibTeX item. |
3830 More precisely, reinsert the field or entry killed or yanked most recently. | 3777 More precisely, reinsert the field or entry killed or yanked most recently. |
3831 With argument N, reinsert the Nth most recently killed BibTeX item. | 3778 With argument N, reinsert the Nth most recently killed BibTeX item. |
3832 See also the command \\[bibtex-yank-pop]." | 3779 See also the command \\[bibtex-yank-pop]." |
3833 (interactive "*p") | 3780 (interactive "*p") |
3834 (bibtex-insert-kill (1- n)) | 3781 (bibtex-insert-kill (1- n) t) |
3835 (setq this-command 'bibtex-yank)) | 3782 (setq this-command 'bibtex-yank)) |
3836 | 3783 |
3837 (defun bibtex-yank-pop (n) | 3784 (defun bibtex-yank-pop (n) |
3838 "Replace just-yanked killed BibTeX item with a different item. | 3785 "Replace just-yanked killed BibTeX item with a different item. |
3839 This command is allowed only immediately after a `bibtex-yank' or a | 3786 This command is allowed only immediately after a `bibtex-yank' or a |
3840 `bibtex-yank-pop'. At such a time, the region contains a reinserted | 3787 `bibtex-yank-pop'. In this case, the region contains a reinserted |
3841 previously killed BibTeX item. `bibtex-yank-pop' deletes that item | 3788 previously killed BibTeX item. `bibtex-yank-pop' deletes that item |
3842 and inserts in its place a different killed BibTeX item. | 3789 and inserts in its place a different killed BibTeX item. |
3843 | 3790 |
3844 With no argument, the previous kill is inserted. | 3791 With no argument, the previous kill is inserted. |
3845 With argument N, insert the Nth previous kill. | 3792 With argument N, insert the Nth previous kill. |
3851 (unless (eq last-command 'bibtex-yank) | 3798 (unless (eq last-command 'bibtex-yank) |
3852 (error "Previous command was not a BibTeX yank")) | 3799 (error "Previous command was not a BibTeX yank")) |
3853 (setq this-command 'bibtex-yank) | 3800 (setq this-command 'bibtex-yank) |
3854 (let ((inhibit-read-only t)) | 3801 (let ((inhibit-read-only t)) |
3855 (delete-region (point) (mark t)) | 3802 (delete-region (point) (mark t)) |
3856 (bibtex-insert-kill n))) | 3803 (bibtex-insert-kill n t))) |
3857 | 3804 |
3858 (defun bibtex-empty-field () | 3805 (defun bibtex-empty-field (&optional comma) |
3859 "Delete the text part of the current field, replace with empty text." | 3806 "Delete the text part of the current field, replace with empty text. |
3860 (interactive) | 3807 Optional arg COMMA is as in `bibtex-enclosing-field'. It is t for |
3861 (bibtex-inside-field) | 3808 interactive calls." |
3862 (let ((bounds (bibtex-enclosing-field))) | 3809 (interactive (list t)) |
3810 (let ((bounds (bibtex-enclosing-field comma))) | |
3863 (goto-char (bibtex-start-of-text-in-field bounds)) | 3811 (goto-char (bibtex-start-of-text-in-field bounds)) |
3864 (delete-region (point) (bibtex-end-of-text-in-field bounds)) | 3812 (delete-region (point) (bibtex-end-of-text-in-field bounds)) |
3865 (insert (bibtex-field-left-delimiter) | 3813 (insert (bibtex-field-left-delimiter) |
3866 (bibtex-field-right-delimiter)) | 3814 (bibtex-field-right-delimiter)) |
3867 (bibtex-find-text t nil bibtex-help-message))) | 3815 (bibtex-find-text t nil bibtex-help-message))) |
3958 ;; Only update the list of keys if it has been built already. | 3906 ;; Only update the list of keys if it has been built already. |
3959 (cond ((eq entry-type 'string) | 3907 (cond ((eq entry-type 'string) |
3960 (if (and (listp bibtex-strings) | 3908 (if (and (listp bibtex-strings) |
3961 (not (assoc key bibtex-strings))) | 3909 (not (assoc key bibtex-strings))) |
3962 (push (cons key (bibtex-text-in-string | 3910 (push (cons key (bibtex-text-in-string |
3963 (save-excursion (bibtex-parse-string)) t)) | 3911 (bibtex-parse-string) t)) |
3964 bibtex-strings))) | 3912 bibtex-strings))) |
3965 ;; We have a normal entry. | 3913 ;; We have a normal entry. |
3966 ((listp bibtex-reference-keys) | 3914 ((listp bibtex-reference-keys) |
3967 (cond ((not (assoc key bibtex-reference-keys)) | 3915 (cond ((not (assoc key bibtex-reference-keys)) |
3968 (push (cons key t) bibtex-reference-keys)) | 3916 (push (cons key t) bibtex-reference-keys)) |
3986 (defun bibtex-fill-field-bounds (bounds justify &optional move) | 3934 (defun bibtex-fill-field-bounds (bounds justify &optional move) |
3987 "Fill BibTeX field delimited by BOUNDS. | 3935 "Fill BibTeX field delimited by BOUNDS. |
3988 If JUSTIFY is non-nil justify as well. | 3936 If JUSTIFY is non-nil justify as well. |
3989 If optional arg MOVE is non-nil move point to end of field." | 3937 If optional arg MOVE is non-nil move point to end of field." |
3990 (let ((end-field (copy-marker (bibtex-end-of-field bounds)))) | 3938 (let ((end-field (copy-marker (bibtex-end-of-field bounds)))) |
3991 (goto-char (bibtex-start-of-field bounds)) | 3939 (if (not justify) |
3992 (if justify | 3940 (goto-char (bibtex-start-of-text-in-field bounds)) |
3993 (progn | 3941 (goto-char (bibtex-start-of-field bounds)) |
3994 (forward-char) | 3942 (forward-char) ;; leading comma |
3995 (bibtex-delete-whitespace) | 3943 (bibtex-delete-whitespace) |
3996 (open-line 1) | 3944 (open-line 1) |
3997 (forward-char) | 3945 (forward-char) |
3998 (indent-to-column (+ bibtex-entry-offset | 3946 (indent-to-column (+ bibtex-entry-offset |
3999 bibtex-field-indentation)) | 3947 bibtex-field-indentation)) |
4000 (re-search-forward "[ \t\n]*=" end-field) | 3948 (re-search-forward "[ \t\n]*=" end-field) |
4001 (replace-match "=") | 3949 (replace-match "=") |
4002 (forward-char -1) | 3950 (forward-char -1) |
4003 (if bibtex-align-at-equal-sign | 3951 (if bibtex-align-at-equal-sign |
4004 (indent-to-column | 3952 (indent-to-column |
4005 (+ bibtex-entry-offset (- bibtex-text-indentation 2))) | 3953 (+ bibtex-entry-offset (- bibtex-text-indentation 2))) |
4006 (insert " ")) | 3954 (insert " ")) |
4007 (forward-char) | 3955 (forward-char) |
4008 (bibtex-delete-whitespace) | 3956 (bibtex-delete-whitespace) |
4009 (if bibtex-align-at-equal-sign | 3957 (if bibtex-align-at-equal-sign |
4010 (insert " ") | 3958 (insert " ") |
4011 (indent-to-column bibtex-text-indentation))) | 3959 (indent-to-column bibtex-text-indentation))) |
4012 (re-search-forward "[ \t\n]*=[ \t\n]*" end-field)) | |
4013 ;; Paragraphs within fields are not preserved. Bother? | 3960 ;; Paragraphs within fields are not preserved. Bother? |
4014 (fill-region-as-paragraph (line-beginning-position) end-field | 3961 (fill-region-as-paragraph (line-beginning-position) end-field |
4015 default-justification nil (point)) | 3962 default-justification nil (point)) |
4016 (if move (goto-char end-field)))) | 3963 (if move (goto-char end-field)))) |
4017 | 3964 |
4018 (defun bibtex-fill-field (&optional justify) | 3965 (defun bibtex-fill-field (&optional justify) |
4019 "Like \\[fill-paragraph], but fill current BibTeX field. | 3966 "Like \\[fill-paragraph], but fill current BibTeX field. |
4020 Optional prefix arg JUSTIFY non-nil means justify as well. | 3967 If optional prefix JUSTIFY is non-nil justify as well. |
4021 In BibTeX mode this function is bound to `fill-paragraph-function'." | 3968 In BibTeX mode this function is bound to `fill-paragraph-function'." |
4022 (interactive "*P") | 3969 (interactive "*P") |
4023 (let ((pnt (copy-marker (point))) | 3970 (let ((pnt (copy-marker (point))) |
4024 (bounds (bibtex-enclosing-field))) | 3971 (bounds (bibtex-enclosing-field t))) |
4025 (when bounds | 3972 (bibtex-fill-field-bounds bounds justify) |
4026 (bibtex-fill-field-bounds bounds justify) | 3973 (goto-char pnt))) |
4027 (goto-char pnt)))) | |
4028 | 3974 |
4029 (defun bibtex-fill-entry () | 3975 (defun bibtex-fill-entry () |
4030 "Fill current BibTeX entry. | 3976 "Fill current BibTeX entry. |
4031 Realign entry, so that every field starts on a separate line. Field | 3977 Realign entry, so that every field starts on a separate line. Field |
4032 names appear in column `bibtex-field-indentation', field text starts in | 3978 names appear in column `bibtex-field-indentation', field text starts in |
4033 column `bibtex-text-indentation' and continuation lines start here, too. | 3979 column `bibtex-text-indentation' and continuation lines start here, too. |
4034 If `bibtex-align-at-equal-sign' is non-nil, align equal signs, too." | 3980 If `bibtex-align-at-equal-sign' is non-nil, align equal signs, too." |
4035 (interactive "*") | 3981 (interactive "*") |
4036 (let ((pnt (copy-marker (point))) | 3982 (let ((pnt (copy-marker (point))) |
4037 (end (copy-marker (bibtex-end-of-entry))) | 3983 (end (copy-marker (bibtex-end-of-entry))) |
3984 (beg (bibtex-beginning-of-entry)) ; move point | |
4038 bounds) | 3985 bounds) |
4039 (bibtex-beginning-of-entry) | |
4040 (bibtex-delete-whitespace) | 3986 (bibtex-delete-whitespace) |
4041 (indent-to-column bibtex-entry-offset) | 3987 (indent-to-column bibtex-entry-offset) |
4042 (while (setq bounds (bibtex-search-forward-field bibtex-field-name end)) | 3988 (bibtex-beginning-first-field beg) |
3989 (while (setq bounds (bibtex-parse-field)) | |
4043 (bibtex-fill-field-bounds bounds t t)) | 3990 (bibtex-fill-field-bounds bounds t t)) |
4044 (if (looking-at ",") | 3991 (if (looking-at ",") |
4045 (forward-char)) | 3992 (forward-char)) |
3993 (skip-chars-backward " \t\n") | |
4046 (bibtex-delete-whitespace) | 3994 (bibtex-delete-whitespace) |
4047 (open-line 1) | 3995 (open-line 1) |
4048 (forward-char) | 3996 (forward-char) |
4049 (indent-to-column bibtex-entry-offset) | 3997 (indent-to-column bibtex-entry-offset) |
4050 (goto-char pnt))) | 3998 (goto-char pnt))) |
4113 (y-or-n-p "Generate new reference keys automatically? "))))) | 4061 (y-or-n-p "Generate new reference keys automatically? "))))) |
4114 (bibtex-sort-ignore-string-entries t) | 4062 (bibtex-sort-ignore-string-entries t) |
4115 bibtex-autokey-edit-before-use) | 4063 bibtex-autokey-edit-before-use) |
4116 | 4064 |
4117 (save-restriction | 4065 (save-restriction |
4118 (narrow-to-region (if mark-active (region-beginning) (point-min)) | 4066 (if mark-active (narrow-to-region (region-beginning) (region-end))) |
4119 (if mark-active (region-end) (point-max))) | |
4120 (if (memq 'realign bibtex-entry-format) | 4067 (if (memq 'realign bibtex-entry-format) |
4121 (bibtex-realign)) | 4068 (bibtex-realign)) |
4122 (bibtex-progress-message "Formatting" 1) | 4069 (bibtex-progress-message "Formatting" 1) |
4123 (bibtex-map-entries (lambda (key beg end) | 4070 (bibtex-map-entries (lambda (key beg end) |
4124 (bibtex-progress-message) | 4071 (bibtex-progress-message) |
4141 entries from minibuffer." | 4088 entries from minibuffer." |
4142 (interactive "*P") | 4089 (interactive "*P") |
4143 (message "Starting to validate buffer...") | 4090 (message "Starting to validate buffer...") |
4144 (sit-for 1 nil t) | 4091 (sit-for 1 nil t) |
4145 (bibtex-realign) | 4092 (bibtex-realign) |
4146 (message | |
4147 "If errors occur, correct them and call `bibtex-convert-alien' again") | |
4148 (sit-for 5 nil t) | |
4149 (deactivate-mark) ; So bibtex-validate works on the whole buffer. | 4093 (deactivate-mark) ; So bibtex-validate works on the whole buffer. |
4150 (when (let (bibtex-maintain-sorted-entries) | 4094 (if (not (let (bibtex-maintain-sorted-entries) |
4151 (bibtex-validate)) | 4095 (bibtex-validate))) |
4096 (message "Correct errors and call `bibtex-convert-alien' again") | |
4152 (message "Starting to reformat entries...") | 4097 (message "Starting to reformat entries...") |
4153 (sit-for 2 nil t) | 4098 (sit-for 2 nil t) |
4154 (bibtex-reformat read-options) | 4099 (bibtex-reformat read-options) |
4155 (goto-char (point-max)) | 4100 (goto-char (point-max)) |
4156 (message "Buffer is now parsable. Please save it."))) | 4101 (message "Buffer is now parsable. Please save it."))) |
4164 based on `bibtex-strings'. | 4109 based on `bibtex-strings'. |
4165 An error is signaled if point is outside key or BibTeX field." | 4110 An error is signaled if point is outside key or BibTeX field." |
4166 (interactive) | 4111 (interactive) |
4167 (let ((pnt (point)) | 4112 (let ((pnt (point)) |
4168 (case-fold-search t) | 4113 (case-fold-search t) |
4169 (bibtex-string-empty-key t) | |
4170 bounds name compl) | 4114 bounds name compl) |
4171 (save-excursion | 4115 (save-excursion |
4172 (if (and (setq bounds (bibtex-enclosing-field t)) | 4116 (if (and (setq bounds (bibtex-enclosing-field nil t)) |
4173 (>= pnt (bibtex-start-of-text-in-field bounds)) | 4117 (>= pnt (bibtex-start-of-text-in-field bounds)) |
4174 (<= pnt (bibtex-end-of-text-in-field bounds))) | 4118 (<= pnt (bibtex-end-of-text-in-field bounds))) |
4175 (setq name (bibtex-name-in-field bounds t) | 4119 (setq name (bibtex-name-in-field bounds t) |
4176 compl (cond ((bibtex-string= name "crossref") | 4120 compl (cond ((bibtex-string= name "crossref") |
4177 ;; point is in crossref field | 4121 ;; point is in crossref field |
4180 ;; point is in month field | 4124 ;; point is in month field |
4181 bibtex-predefined-month-strings) | 4125 bibtex-predefined-month-strings) |
4182 ;; point is in other field | 4126 ;; point is in other field |
4183 (t (bibtex-strings)))) | 4127 (t (bibtex-strings)))) |
4184 (bibtex-beginning-of-entry) | 4128 (bibtex-beginning-of-entry) |
4185 (cond ((setq bounds (bibtex-parse-string)) | 4129 (cond ((setq bounds (bibtex-parse-string t)) |
4186 ;; point is inside a @String key | 4130 ;; point is inside a @String key |
4187 (cond ((and (>= pnt (nth 1 (car bounds))) | 4131 (cond ((and (>= pnt (nth 1 (car bounds))) |
4188 (<= pnt (nth 2 (car bounds)))) | 4132 (<= pnt (nth 2 (car bounds)))) |
4189 (setq compl 'string)) | 4133 (setq compl 'string)) |
4190 ;; point is inside a @String field | 4134 ;; point is inside a @String field |
4191 ((and (>= pnt (bibtex-start-of-text-in-string bounds)) | 4135 ((and (>= pnt (bibtex-start-of-text-in-string bounds)) |
4192 (<= pnt (bibtex-end-of-text-in-string bounds))) | 4136 (<= pnt (bibtex-end-of-text-in-string bounds))) |
4193 (setq compl (bibtex-strings))))) | 4137 (setq compl (bibtex-strings))))) |
4194 ;; point is inside a @Preamble field | 4138 ;; point is inside a @Preamble field |
4195 ((and (bibtex-preamble-prefix t) | 4139 ((setq bounds (bibtex-parse-preamble)) |
4196 (setq bounds (bibtex-parse-field-text)) | 4140 (if (and (>= pnt (bibtex-start-of-text-in-string bounds)) |
4197 (>= pnt (car bounds)) | 4141 (<= pnt (bibtex-end-of-text-in-string bounds))) |
4198 (<= pnt (nth 1 bounds))) | 4142 (setq compl (bibtex-strings)))) |
4199 (setq compl (bibtex-strings))) | |
4200 ((and (looking-at bibtex-entry-maybe-empty-head) | 4143 ((and (looking-at bibtex-entry-maybe-empty-head) |
4201 ;; point is inside a key | 4144 ;; point is inside a key |
4202 (or (and (match-beginning bibtex-key-in-head) | 4145 (or (and (match-beginning bibtex-key-in-head) |
4203 (>= pnt (match-beginning bibtex-key-in-head)) | 4146 (>= pnt (match-beginning bibtex-key-in-head)) |
4204 (<= pnt (match-end bibtex-key-in-head))) | 4147 (<= pnt (match-end bibtex-key-in-head))) |