diff options
| author | Roland Winkler | 2005-12-29 15:25:28 +0000 |
|---|---|---|
| committer | Roland Winkler | 2005-12-29 15:25:28 +0000 |
| commit | ffc1e1db038d748fd94c8d0f1f17d9193d114c7e (patch) | |
| tree | 96fddbc45a93928ffd029bf4b883b583f7ffab92 | |
| parent | 88ec8c53c63b091d8b7ccc8fef3b5948f4c0a53e (diff) | |
| download | emacs-ffc1e1db038d748fd94c8d0f1f17d9193d114c7e.tar.gz emacs-ffc1e1db038d748fd94c8d0f1f17d9193d114c7e.zip | |
(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.
| -rw-r--r-- | lisp/ChangeLog | 48 | ||||
| -rw-r--r-- | lisp/textmodes/bibtex.el | 1049 |
2 files changed, 544 insertions, 553 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 288e4d7ed44..9190aa3c988 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,51 @@ | |||
| 1 | 2005-12-29 Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> | ||
| 2 | |||
| 3 | * textmodes/bibtex.el (bibtex-entry-type-whitespace) | ||
| 4 | (bibtex-entry-type-str, bibtex-empty-field-re) | ||
| 5 | (bibtex-search-backward-string, bibtex-preamble-prefix) | ||
| 6 | (bibtex-search-entry, bibtex-enclosing-entry-maybe-empty-head): | ||
| 7 | Removed. | ||
| 8 | (bibtex-any-valid-entry-type): New variable. | ||
| 9 | (bibtex-parse-field-name): Simplify. | ||
| 10 | (bibtex-parse-string, bibtex-search-forward-string): New arg | ||
| 11 | empty-key. | ||
| 12 | (bibtex-preamble-prefix): Include left delimiter. | ||
| 13 | (bibtex-search-forward-field, bibtex-search-backward-field): Allow | ||
| 14 | unbounded search past entry boundaries (required by bibtex-pop). | ||
| 15 | (bibtex-text-in-field-bounds): Use push. | ||
| 16 | (bibtex-text-in-field): Do not use bibtex-narrow-to-entry. | ||
| 17 | (bibtex-parse-preamble, bibtex-valid-entry) | ||
| 18 | (bibtex-beginning-first-field): New functions. | ||
| 19 | (bibtex-skip-to-valid-entry): Use bibtex-valid-entry. Fix regexp. | ||
| 20 | (bibtex-map-entries): Fix docstring. | ||
| 21 | (bibtex-flash-head): New arg prompt. Simplify. | ||
| 22 | (bibtex-enclosing-field): Include code of bibtex-inside-field. | ||
| 23 | (bibtex-insert-kill): Simplify. Always insert text past the | ||
| 24 | current field or entry. | ||
| 25 | (bibtex-format-entry): Use bibtex-parse-field. | ||
| 26 | (bibtex-pop): Use bibtex-beginning-of-entry and | ||
| 27 | bibtex-end-of-entry to initiate the search. Insert empty field if | ||
| 28 | we found ourselves. | ||
| 29 | (bibtex-print-help-message): New args field and comma. Handle | ||
| 30 | entry keys. | ||
| 31 | (bibtex-make-field): Use bibtex-beginning-of-entry. | ||
| 32 | (bibtex-end-of-entry): Use bibtex-valid-entry. Recognize any | ||
| 33 | invalid entry. | ||
| 34 | (bibtex-validate): Use bibtex-valid-entry and bibtex-parse-string. | ||
| 35 | Handle preambles. Simplify code for thorough test. | ||
| 36 | (bibtex-next-field, bibtex-find-text, bibtex-find-text-internal): | ||
| 37 | New arg comma. Handle entry heads. | ||
| 38 | (bibtex-remove-OPT-or-ALT, bibtex-remove-delimiters) | ||
| 39 | (bibtex-kill-field, bibtex-copy-field-as-kil, bibtex-empty-field): | ||
| 40 | New arg comma. | ||
| 41 | (bibtex-kill-entry): Use bibtex-any-entry-maybe-empty-head. | ||
| 42 | (bibtex-fill-field): Simplify. | ||
| 43 | (bibtex-fill-entry): Use bibtex-beginning-first-field and | ||
| 44 | bibtex-parse-field. | ||
| 45 | (bibtex-convert-alien): Do not wait before calling | ||
| 46 | bibtex-validate. | ||
| 47 | (bibtex-complete): Use bibtex-parse-preamble. | ||
| 48 | |||
| 1 | 2005-12-29 Nick Roberts <nickrob@snap.net.nz> | 49 | 2005-12-29 Nick Roberts <nickrob@snap.net.nz> |
| 2 | 50 | ||
| 3 | * progmodes/gdb-ui.el (gdb-tooltip-print, gdb-tooltip-print-1): | 51 | * progmodes/gdb-ui.el (gdb-tooltip-print, gdb-tooltip-print-1): |
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el index 161b5fbc126..a98fc2ddee1 100644 --- a/lisp/textmodes/bibtex.el +++ b/lisp/textmodes/bibtex.el | |||
| @@ -853,7 +853,7 @@ The following is a complex example, see http://link.aps.org/linkfaq.html. | |||
| 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 | ||
| @@ -1091,7 +1091,7 @@ The CDRs of the elements are t for header keys and nil for crossref keys.") | |||
| 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:].:;?!`'/*@+|()<>&_^$-]+" |
| @@ -1105,16 +1105,6 @@ The CDRs of the elements are t for header keys and nil for crossref keys.") | |||
| 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 | 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 | |||
| 1118 | (defvar bibtex-entry-head | 1108 | (defvar bibtex-entry-head |
| 1119 | (concat "^[ \t]*\\(" | 1109 | (concat "^[ \t]*\\(" |
| 1120 | bibtex-entry-type | 1110 | bibtex-entry-type |
| @@ -1132,15 +1122,18 @@ The CDRs of the elements are t for header keys and nil for crossref keys.") | |||
| 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 | 1136 | ||
| 1141 | (defconst bibtex-empty-field-re "\\`\\(\"\"\\|{}\\)\\'" | ||
| 1142 | "Regexp matching the text part (as a string) of an empty field.") | ||
| 1143 | |||
| 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 | ||
| @@ -1148,8 +1141,9 @@ The CDRs of the elements are t for header keys and nil for crossref keys.") | |||
| 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) "\\)" |
| @@ -1229,12 +1223,9 @@ 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 |
| @@ -1334,60 +1325,71 @@ the boundaries of the name and text parts of the field. Do not move point." | |||
| 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. |
| @@ -1407,25 +1409,22 @@ 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 | ||
| @@ -1434,19 +1433,15 @@ If `bibtex-expand-strings' is non-nil, also expand BibTeX strings." | |||
| 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. |
| @@ -1487,42 +1482,28 @@ character of the string entry. Move point past BibTeX string entry." | |||
| 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 |
| 1492 | 'bibtex-parse-string-postfix))) | ||
| 1497 | 1493 | ||
| 1498 | (defun bibtex-search-forward-string () | 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" |
| @@ -1554,14 +1535,15 @@ If `bibtex-expand-strings' is non-nil, also expand BibTeX strings." | |||
| 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 | ||
| @@ -1579,6 +1561,35 @@ move past the opening delimiter. If no preamble is found return nil." | |||
| 1579 | (+ (count-lines 1 (point)) | 1561 | (+ (count-lines 1 (point)) |
| 1580 | (if (bolp) 1 0))) | 1562 | (if (bolp) 1 0))) |
| 1581 | 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)))))) | ||
| 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. |
| @@ -1590,32 +1601,27 @@ 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 |
| @@ -1673,75 +1679,19 @@ If FLAG is nil, a message is echoed if point was incremented at least | |||
| 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." |
| @@ -1772,66 +1722,55 @@ are ignored. Return point" | |||
| 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'. |
| @@ -1900,9 +1839,8 @@ Formats current entry according to variable `bibtex-entry-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))) |
| @@ -2040,10 +1978,6 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 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 | 1980 | ||
| 2043 | ;; update point | ||
| 2044 | (if (looking-at (bibtex-field-right-delimiter)) | ||
| 2045 | (forward-char)) | ||
| 2046 | |||
| 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 |
| @@ -2565,6 +2499,7 @@ of a word, all strings are listed. Return completion." | |||
| 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))))) |
| @@ -2624,50 +2559,52 @@ Used as default value of `bibtex-summary-function'." | |||
| 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 () |
| @@ -2861,7 +2798,7 @@ 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)) |
| @@ -2918,10 +2855,11 @@ according to `bibtex-field-list', but are not yet present." | |||
| 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))) |
| @@ -2964,6 +2902,7 @@ entry (for example, the year parts of the keys)." | |||
| 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) |
| @@ -3016,28 +2955,28 @@ entry (for example, the year parts of the keys)." | |||
| 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. |
| @@ -3052,7 +2991,8 @@ MOVE and INTERACTIVE are t when called interactively." | |||
| 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)) |
| @@ -3081,8 +3021,9 @@ MOVE and INTERACTIVE are t when called interactively." | |||
| 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). |
| @@ -3103,28 +3044,19 @@ 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." |
| @@ -3188,7 +3120,7 @@ If mark is active count entries in region, if not in whole buffer." | |||
| 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)) |
| @@ -3216,7 +3148,7 @@ of the head of the entry found. Return nil if no entry found." | |||
| 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)) |
| @@ -3283,7 +3215,7 @@ entry and SPLIT is t." | |||
| 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) |
| @@ -3429,40 +3361,38 @@ Return t if test was successful, nil otherwise." | |||
| 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))) | ||
| 3434 | 3365 | ||
| 3435 | ;; looking if entries fit syntactical structure | 3366 | ;; Check syntactical structure of entries |
| 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) |
| @@ -3498,18 +3428,13 @@ Return t if test was successful, nil otherwise." | |||
| 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. |
| @@ -3521,18 +3446,19 @@ Return t if test was successful, nil otherwise." | |||
| 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) |
| @@ -3573,11 +3499,10 @@ Return t if test was successful, nil otherwise." | |||
| 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'. |
| @@ -3631,37 +3556,41 @@ Return t if test was successful, nil otherwise." | |||
| 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)) |
| @@ -3670,72 +3599,88 @@ When called interactively, the value of HELP is `bibtex-help-message'." | |||
| 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 | ||
| 3676 | (match-beginning bibtex-key-in-head) | ||
| 3677 | (match-end 0)))) | ||
| 3678 | (t | ||
| 3679 | (goto-char pnt) | ||
| 3680 | (unless noerror (error "Not on BibTeX field")))))) | ||
| 3681 | 3604 | ||
| 3682 | (defun bibtex-find-text-internal (&optional noerror subfield) | 3605 | (defun bibtex-find-text-internal (&optional noerror subfield comma) |
| 3683 | "Find text part of current BibTeX field, @String or @Preamble. | 3606 | "Find text part of current BibTeX field or entry head. |
| 3684 | Return list (NAME START END) with field name, start and end of text | 3607 | Return list (NAME START-TEXT END-TEXT END) with field or entry name, |
| 3685 | or nil if not found. | 3608 | start and end of text and end of field or entry head, 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") |
| @@ -3751,14 +3696,14 @@ Align text and go thereafter to end of text." | |||
| 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) '(?\} ?\")) |
| @@ -3766,15 +3711,15 @@ Align text and go thereafter to end of text." | |||
| 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) |
| @@ -3791,10 +3736,12 @@ but do not actually kill it." | |||
| 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. |
| @@ -3806,7 +3753,7 @@ but do not actually kill it." | |||
| 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) |
| @@ -3831,13 +3778,13 @@ 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 | ||
| @@ -3853,13 +3800,14 @@ comes the newest one." | |||
| 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) |
| @@ -3960,7 +3908,7 @@ At end of the cleaning process, the functions in | |||
| 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) |
| @@ -3988,28 +3936,27 @@ At end of the cleaning process, the functions in | |||
| 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)) |
| @@ -4017,14 +3964,13 @@ If optional arg MOVE is non-nil move point to end of 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. |
| @@ -4035,14 +3981,16 @@ 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) |
| @@ -4115,8 +4063,7 @@ If mark is active reformat entries in region, if not in whole buffer." | |||
| 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) |
| @@ -4143,12 +4090,10 @@ entries from minibuffer." | |||
| 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) |
| @@ -4166,10 +4111,9 @@ 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) |
| @@ -4182,7 +4126,7 @@ An error is signaled if point is outside key or BibTeX field." | |||
| 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)))) |
| @@ -4192,11 +4136,10 @@ An error is signaled if point is outside key or BibTeX field." | |||
| 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) |