Mercurial > emacs
comparison lisp/textmodes/bibtex.el @ 81591:33952a25e52a
(bibtex-entry-format): New options `whitespace', `braces', and `string'.
(bibtex-field-braces-alist, bibtex-field-strings-alist)
(bibtex-field-braces-opt, bibtex-field-strings-opt)
(bibtex-cite-matcher-alist): New variables.
(bibtex-font-lock-keywords): Use bibtex-cite-matcher-alist.
(bibtex-flash-head): Use blink-matching-delay.
(bibtex-insert-kill, bibtex-mark-entry): Use push-mark.
(bibtex-format-entry, bibtex-reformat): Handle new options of
bibtex-entry-format.
(bibtex-field-re-init, bibtex-font-lock-cite, bibtex-dist): New
functions.
(bibtex-complete-internal): Do not display messages while
minibuffer is used. Do not leave around a completions buffer
that is out of date.
(bibtex-copy-summary-as-kill): New optional arg.
(bibtex-font-lock-url): New optional arg no-button.
(bibtex-find-crossref): Use `bibtex-cite-matcher-alist'.
(bibtex-url): Allow multiple URLs per entry.
author | Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> |
---|---|
date | Sat, 23 Jun 2007 22:00:03 +0000 |
parents | 372e6a7ea660 |
children | b98604865ea0 988f1edc9674 |
comparison
equal
deleted
inserted
replaced
81590:ffabac9ec014 | 81591:33952a25e52a |
---|---|
32 ;;; Commentary: | 32 ;;; Commentary: |
33 | 33 |
34 ;; Major mode for editing and validating BibTeX files. | 34 ;; Major mode for editing and validating BibTeX files. |
35 | 35 |
36 ;; Usage: | 36 ;; Usage: |
37 ;; See documentation for function bibtex-mode or type "\M-x describe-mode" | 37 ;; See documentation for `bibtex-mode' or type "M-x describe-mode" |
38 ;; when you are in BibTeX mode. | 38 ;; when you are in BibTeX mode. |
39 | 39 |
40 ;; Todo: | 40 ;; Todo: |
41 ;; Distribute texinfo file. | 41 ;; Distribute texinfo file. |
42 | 42 |
110 remove OPT and ALT prefixes from used fields. | 110 remove OPT and ALT prefixes from used fields. |
111 required-fields Signal an error if a required field is missing. | 111 required-fields Signal an error if a required field is missing. |
112 numerical-fields Delete delimiters around numeral fields. | 112 numerical-fields Delete delimiters around numeral fields. |
113 page-dashes Change double dashes in page field to single dash | 113 page-dashes Change double dashes in page field to single dash |
114 (for scribe compatibility). | 114 (for scribe compatibility). |
115 whitespace Delete whitespace at the beginning and end of fields. | |
115 inherit-booktitle If entry contains a crossref field and the booktitle | 116 inherit-booktitle If entry contains a crossref field and the booktitle |
116 field is empty, set the booktitle field to the content | 117 field is empty, set the booktitle field to the content |
117 of the title field of the crossreferenced entry. | 118 of the title field of the crossreferenced entry. |
118 realign Realign entries, so that field texts and perhaps equal | 119 realign Realign entries, so that field texts and perhaps equal |
119 signs (depending on the value of | 120 signs (depending on the value of |
121 last-comma Add or delete comma on end of last field in entry, | 122 last-comma Add or delete comma on end of last field in entry, |
122 according to value of `bibtex-comma-after-last-field'. | 123 according to value of `bibtex-comma-after-last-field'. |
123 delimiters Change delimiters according to variables | 124 delimiters Change delimiters according to variables |
124 `bibtex-field-delimiters' and `bibtex-entry-delimiters'. | 125 `bibtex-field-delimiters' and `bibtex-entry-delimiters'. |
125 unify-case Change case of entry and field names. | 126 unify-case Change case of entry and field names. |
127 braces Enclose parts of field entries by braces according to | |
128 `bibtex-field-braces-alist'. | |
129 strings Replace parts of field entries by string constants | |
130 according to `bibtex-field-strings-alist'. | |
126 | 131 |
127 The value t means do all of the above formatting actions. | 132 The value t means do all of the above formatting actions. |
128 The value nil means do no formatting at all." | 133 The value nil means do no formatting at all." |
129 :group 'bibtex | 134 :group 'bibtex |
130 :type '(choice (const :tag "None" nil) | 135 :type '(choice (const :tag "None" nil) |
132 (set :menu-tag "Some" | 137 (set :menu-tag "Some" |
133 (const opts-or-alts) | 138 (const opts-or-alts) |
134 (const required-fields) | 139 (const required-fields) |
135 (const numerical-fields) | 140 (const numerical-fields) |
136 (const page-dashes) | 141 (const page-dashes) |
142 (const whitespace) | |
137 (const inherit-booktitle) | 143 (const inherit-booktitle) |
138 (const realign) | 144 (const realign) |
139 (const last-comma) | 145 (const last-comma) |
140 (const delimiters) | 146 (const delimiters) |
141 (const unify-case)))) | 147 (const unify-case) |
148 (const braces) | |
149 (const strings)))) | |
150 | |
151 (defcustom bibtex-field-braces-alist nil | |
152 "Alist of field regexps that \\[bibtex-clean-entry] encloses by braces. | |
153 Each element has the form (FIELDS REGEXP), where FIELDS is a list | |
154 of BibTeX field names and REGEXP is a regexp. | |
155 Whitespace in REGEXP will be replaced by \"[ \\t\\n]+\"." | |
156 :group 'bibtex | |
157 :type '(repeat (list (repeat (string :tag "field name")) | |
158 (choice (regexp :tag "regexp") | |
159 (sexp :tag "sexp"))))) | |
160 | |
161 (defcustom bibtex-field-strings-alist nil | |
162 "Alist of regexps that \\[bibtex-clean-entry] replaces by string constants. | |
163 Each element has the form (FIELDS REGEXP TO-STR), where FIELDS is a list | |
164 of BibTeX field names. In FIELDS search for REGEXP, which are replaced | |
165 by the BibTeX string constant TO-STR. | |
166 Whitespace in REGEXP will be replaced by \"[ \\t\\n]+\"." | |
167 :group 'bibtex | |
168 :type '(repeat (list (repeat (string :tag "field name")) | |
169 (regexp :tag "From regexp") | |
170 (regexp :tag "To string constant")))) | |
142 | 171 |
143 (defcustom bibtex-clean-entry-hook nil | 172 (defcustom bibtex-clean-entry-hook nil |
144 "List of functions to call when entry has been cleaned. | 173 "List of functions to call when entry has been cleaned. |
145 Functions are called with point inside the cleaned entry, and the buffer | 174 Functions are called with point inside the cleaned entry, and the buffer |
146 narrowed to just the entry." | 175 narrowed to just the entry." |
897 (choice (string :tag "Replacement") | 926 (choice (string :tag "Replacement") |
898 (integer :tag "Sub-match") | 927 (integer :tag "Sub-match") |
899 (function :tag "Filter")))))))) | 928 (function :tag "Filter")))))))) |
900 (put 'bibtex-generate-url-list 'risky-local-variable t) | 929 (put 'bibtex-generate-url-list 'risky-local-variable t) |
901 | 930 |
931 (defcustom bibtex-cite-matcher-alist | |
932 '(("\\\\cite[ \t\n]*{\\([^}]+\\)}" . 1)) | |
933 "Alist of rules to identify cited keys in a BibTeX entry. | |
934 Each rule should be of the form (REGEXP . SUBEXP), where SUBEXP | |
935 specifies which parenthesized expression in REGEXP is a cited key. | |
936 Case is significant. | |
937 Used by `bibtex-find-crossref' and for font-locking." | |
938 :group 'bibtex | |
939 :type '(repeat (cons (regexp :tag "Regexp") | |
940 (integer :tag "Number")))) | |
941 | |
902 (defcustom bibtex-expand-strings nil | 942 (defcustom bibtex-expand-strings nil |
903 "If non-nil, expand strings when extracting the content of a BibTeX field." | 943 "If non-nil, expand strings when extracting the content of a BibTeX field." |
904 :group 'bibtex | 944 :group 'bibtex |
905 :type 'boolean) | 945 :type 'boolean) |
906 | 946 |
1068 ["Preamble" bibtex-Preamble t])) | 1108 ["Preamble" bibtex-Preamble t])) |
1069 | 1109 |
1070 | 1110 |
1071 ;; Internal Variables | 1111 ;; Internal Variables |
1072 | 1112 |
1113 (defvar bibtex-field-braces-opt nil | |
1114 "Optimized value of `bibtex-field-braces-alist'. | |
1115 Created by `bibtex-field-re-init'. | |
1116 It is a an alist with elements (FIELD . REGEXP).") | |
1117 | |
1118 (defvar bibtex-field-strings-opt nil | |
1119 "Optimized value of `bibtex-field-strings-alist'. | |
1120 Created by `bibtex-field-re-init'. | |
1121 It is a an alist with elements (FIELD RULE1 RULE2 ...), | |
1122 where each RULE is (REGEXP . TO-STR).") | |
1123 | |
1073 (defvar bibtex-pop-previous-search-point nil | 1124 (defvar bibtex-pop-previous-search-point nil |
1074 "Next point where `bibtex-pop-previous' starts looking for a similar entry.") | 1125 "Next point where `bibtex-pop-previous' starts looking for a similar entry.") |
1075 | 1126 |
1076 (defvar bibtex-pop-next-search-point nil | 1127 (defvar bibtex-pop-next-search-point nil |
1077 "Next point where `bibtex-pop-next' starts looking for a similar entry.") | 1128 "Next point where `bibtex-pop-next' starts looking for a similar entry.") |
1213 1 font-lock-comment-face) | 1264 1 font-lock-comment-face) |
1214 ;; field names | 1265 ;; field names |
1215 (,(concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=") | 1266 (,(concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=") |
1216 1 font-lock-variable-name-face) | 1267 1 font-lock-variable-name-face) |
1217 ;; url | 1268 ;; url |
1218 (bibtex-font-lock-url) (bibtex-font-lock-crossref)) | 1269 (bibtex-font-lock-url) (bibtex-font-lock-crossref) |
1270 ;; cite | |
1271 ,@(mapcar (lambda (matcher) | |
1272 `((lambda (bound) (bibtex-font-lock-cite ',matcher bound)))) | |
1273 bibtex-cite-matcher-alist)) | |
1219 "*Default expressions to highlight in BibTeX mode.") | 1274 "*Default expressions to highlight in BibTeX mode.") |
1220 | 1275 |
1221 (defvar bibtex-font-lock-url-regexp | 1276 (defvar bibtex-font-lock-url-regexp |
1222 ;; Assume that field names begin at the beginning of a line. | 1277 ;; Assume that field names begin at the beginning of a line. |
1223 (concat "^[ \t]*" | 1278 (concat "^[ \t]*" |
1224 (regexp-opt (delete-dups (mapcar 'caar bibtex-generate-url-list)) t) | 1279 (regexp-opt (delete-dups (mapcar 'caar bibtex-generate-url-list)) t) |
1225 "[ \t]*=[ \t]*") | 1280 "[ \t]*=[ \t]*") |
1226 "Regexp for `bibtex-font-lock-url'.") | 1281 "Regexp for `bibtex-font-lock-url' derived from `bibtex-generate-url-list'.") |
1227 | 1282 |
1228 (defvar bibtex-string-empty-key nil | 1283 (defvar bibtex-string-empty-key nil |
1229 "If non-nil, `bibtex-parse-string' accepts empty key.") | 1284 "If non-nil, `bibtex-parse-string' accepts empty key.") |
1230 | 1285 |
1231 (defvar bibtex-sort-entry-class-alist nil | 1286 (defvar bibtex-sort-entry-class-alist nil |
1551 (save-excursion (goto-char (match-beginning 0)) | 1606 (save-excursion (goto-char (match-beginning 0)) |
1552 (setq bounds (bibtex-parse-string empty-key)))) | 1607 (setq bounds (bibtex-parse-string empty-key)))) |
1553 bounds)))) | 1608 bounds)))) |
1554 | 1609 |
1555 (defun bibtex-reference-key-in-string (bounds) | 1610 (defun bibtex-reference-key-in-string (bounds) |
1556 "Return the key part of a BibTeX string defined via BOUNDS" | 1611 "Return the key part of a BibTeX string defined via BOUNDS." |
1557 (buffer-substring-no-properties (nth 1 (car bounds)) | 1612 (buffer-substring-no-properties (nth 1 (car bounds)) |
1558 (nth 2 (car bounds)))) | 1613 (nth 2 (car bounds)))) |
1559 | 1614 |
1560 (defun bibtex-text-in-string (bounds &optional content) | 1615 (defun bibtex-text-in-string (bounds &optional content) |
1561 "Get text in BibTeX string field defined via BOUNDS. | 1616 "Get text in BibTeX string field defined via BOUNDS. |
1624 (goto-char (match-end 0)) | 1679 (goto-char (match-end 0)) |
1625 (let ((entry-closer | 1680 (let ((entry-closer |
1626 (if (save-excursion | 1681 (if (save-excursion |
1627 (goto-char (match-end bibtex-type-in-head)) | 1682 (goto-char (match-end bibtex-type-in-head)) |
1628 (looking-at "[ \t]*(")) | 1683 (looking-at "[ \t]*(")) |
1629 ",?[ \t\n]*)" ;; entry opened with `(' | 1684 ",?[ \t\n]*)" ; entry opened with `(' |
1630 ",?[ \t\n]*}")) ;; entry opened with `{' | 1685 ",?[ \t\n]*}")) ; entry opened with `{' |
1631 bounds) | 1686 bounds) |
1632 (skip-chars-forward " \t\n") | 1687 (skip-chars-forward " \t\n") |
1633 ;; loop over all BibTeX fields | 1688 ;; loop over all BibTeX fields |
1634 (while (setq bounds (bibtex-parse-field)) | 1689 (while (setq bounds (bibtex-parse-field)) |
1635 (goto-char (bibtex-end-of-field bounds))) | 1690 (goto-char (bibtex-end-of-field bounds))) |
1734 (bibtex-beginning-of-entry) | 1789 (bibtex-beginning-of-entry) |
1735 (when (and (looking-at bibtex-any-entry-maybe-empty-head) | 1790 (when (and (looking-at bibtex-any-entry-maybe-empty-head) |
1736 (< (point) pnt)) | 1791 (< (point) pnt)) |
1737 (goto-char (match-beginning bibtex-type-in-head)) | 1792 (goto-char (match-beginning bibtex-type-in-head)) |
1738 (if (pos-visible-in-window-p (point)) | 1793 (if (pos-visible-in-window-p (point)) |
1739 (sit-for 1) | 1794 (sit-for blink-matching-delay) |
1740 (message "%s%s" prompt (buffer-substring-no-properties | 1795 (message "%s%s" prompt (buffer-substring-no-properties |
1741 (point) (match-end bibtex-key-in-head)))))))) | 1796 (point) (match-end bibtex-key-in-head)))))))) |
1742 | 1797 |
1743 (defun bibtex-make-optional-field (field) | 1798 (defun bibtex-make-optional-field (field) |
1744 "Make an optional field named FIELD in current BibTeX entry." | 1799 "Make an optional field named FIELD in current BibTeX entry." |
1799 | 1854 |
1800 (defun bibtex-insert-kill (n &optional comma) | 1855 (defun bibtex-insert-kill (n &optional comma) |
1801 "Reinsert the Nth stretch of killed BibTeX text (field or entry). | 1856 "Reinsert the Nth stretch of killed BibTeX text (field or entry). |
1802 Optional arg COMMA is as in `bibtex-enclosing-field'." | 1857 Optional arg COMMA is as in `bibtex-enclosing-field'." |
1803 (unless bibtex-last-kill-command (error "BibTeX kill ring is empty")) | 1858 (unless bibtex-last-kill-command (error "BibTeX kill ring is empty")) |
1804 (let ((fun (lambda (kryp kr) ;; adapted from `current-kill' | 1859 (let ((fun (lambda (kryp kr) ; adapted from `current-kill' |
1805 (car (set kryp (nthcdr (mod (- n (length (eval kryp))) | 1860 (car (set kryp (nthcdr (mod (- n (length (eval kryp))) |
1806 (length kr)) kr)))))) | 1861 (length kr)) kr)))))) |
1807 (if (eq bibtex-last-kill-command 'field) | 1862 (if (eq bibtex-last-kill-command 'field) |
1808 (progn | 1863 (progn |
1809 ;; insert past the current field | 1864 ;; insert past the current field |
1810 (goto-char (bibtex-end-of-field (bibtex-enclosing-field comma))) | 1865 (goto-char (bibtex-end-of-field (bibtex-enclosing-field comma))) |
1811 (set-mark (point)) | 1866 (push-mark) |
1812 (message "Mark set") | |
1813 (bibtex-make-field (funcall fun 'bibtex-field-kill-ring-yank-pointer | 1867 (bibtex-make-field (funcall fun 'bibtex-field-kill-ring-yank-pointer |
1814 bibtex-field-kill-ring) t nil t)) | 1868 bibtex-field-kill-ring) t nil t)) |
1815 ;; insert past the current entry | 1869 ;; insert past the current entry |
1816 (bibtex-skip-to-valid-entry) | 1870 (bibtex-skip-to-valid-entry) |
1817 (set-mark (point)) | 1871 (push-mark) |
1818 (message "Mark set") | |
1819 (insert (funcall fun 'bibtex-entry-kill-ring-yank-pointer | 1872 (insert (funcall fun 'bibtex-entry-kill-ring-yank-pointer |
1820 bibtex-entry-kill-ring))))) | 1873 bibtex-entry-kill-ring))))) |
1821 | 1874 |
1822 (defun bibtex-format-entry () | 1875 (defun bibtex-format-entry () |
1823 "Helper function for `bibtex-clean-entry'. | 1876 "Helper function for `bibtex-clean-entry'. |
1832 last-comma page-dashes delimiters | 1885 last-comma page-dashes delimiters |
1833 unify-case inherit-booktitle) | 1886 unify-case inherit-booktitle) |
1834 bibtex-entry-format)) | 1887 bibtex-entry-format)) |
1835 crossref-key bounds alternatives-there non-empty-alternative | 1888 crossref-key bounds alternatives-there non-empty-alternative |
1836 entry-list req-field-list field-list) | 1889 entry-list req-field-list field-list) |
1890 | |
1891 ;; Initialize `bibtex-field-braces-opt' and `bibtex-field-strings-opt' | |
1892 ;; if necessary. | |
1893 (unless bibtex-field-braces-opt | |
1894 (setq bibtex-field-braces-opt | |
1895 (bibtex-field-re-init bibtex-field-braces-alist 'braces))) | |
1896 (unless bibtex-field-strings-opt | |
1897 (setq bibtex-field-strings-opt | |
1898 (bibtex-field-re-init bibtex-field-strings-alist 'strings))) | |
1837 | 1899 |
1838 ;; identify entry type | 1900 ;; identify entry type |
1839 (goto-char (point-min)) | 1901 (goto-char (point-min)) |
1840 (or (re-search-forward bibtex-entry-type nil t) | 1902 (or (re-search-forward bibtex-entry-type nil t) |
1841 (error "Not inside a BibTeX entry")) | 1903 (error "Not inside a BibTeX entry")) |
1902 (if opt-alt (+ beg-name 3) beg-name) end-name)) | 1964 (if opt-alt (+ beg-name 3) beg-name) end-name)) |
1903 (empty-field (equal "" (bibtex-text-in-field-bounds bounds t))) | 1965 (empty-field (equal "" (bibtex-text-in-field-bounds bounds t))) |
1904 deleted) | 1966 deleted) |
1905 | 1967 |
1906 ;; We have more elegant high-level functions for several | 1968 ;; We have more elegant high-level functions for several |
1907 ;; tasks done by bibtex-format-entry. However, they contain | 1969 ;; tasks done by `bibtex-format-entry'. However, they contain |
1908 ;; quite some redundancy compared with what we need to do | 1970 ;; quite some redundancy compared with what we need to do |
1909 ;; anyway. So for speed-up we avoid using them. | 1971 ;; anyway. So for speed-up we avoid using them. |
1910 | 1972 |
1911 (if (memq 'opts-or-alts format) | 1973 (if (memq 'opts-or-alts format) |
1912 (cond ((and empty-field | 1974 (cond ((and empty-field |
1954 (bibtex-string= field-name "pages") | 2016 (bibtex-string= field-name "pages") |
1955 (progn (goto-char beg-text) | 2017 (progn (goto-char beg-text) |
1956 (looking-at | 2018 (looking-at |
1957 "\\([\"{][0-9]+\\)[ \t\n]*--?[ \t\n]*\\([0-9]+[\"}]\\)"))) | 2019 "\\([\"{][0-9]+\\)[ \t\n]*--?[ \t\n]*\\([0-9]+[\"}]\\)"))) |
1958 (replace-match "\\1-\\2")) | 2020 (replace-match "\\1-\\2")) |
2021 | |
2022 ;; remove whitespace at beginning and end of field | |
2023 (when (memq 'whitespace format) | |
2024 (goto-char beg-text) | |
2025 (if (looking-at "\\([{\"]\\)[ \t\n]+") | |
2026 (replace-match "\\1")) | |
2027 (goto-char end-text) | |
2028 (if (looking-back "[ \t\n]+\\([}\"]\\)" beg-text t) | |
2029 (replace-match "\\1"))) | |
2030 | |
2031 ;; enclose field text by braces according to | |
2032 ;; `bibtex-field-braces-alist'. | |
2033 (let (case-fold-search temp) ; Case-sensitive search | |
2034 (when (and (memq 'braces format) | |
2035 (setq temp (cdr (assoc-string field-name | |
2036 bibtex-field-braces-opt t)))) | |
2037 (goto-char beg-text) | |
2038 (while (re-search-forward temp end-text t) | |
2039 (let ((beg (match-beginning 0)) | |
2040 (bounds (bibtex-find-text-internal nil t))) | |
2041 (unless (or (nth 4 bounds) ; string constant | |
2042 ;; match already surrounded by braces | |
2043 ;; (braces are inside field delimiters) | |
2044 (and (< (point) (1- (nth 2 bounds))) | |
2045 (< (1+ (nth 1 bounds)) beg) | |
2046 (looking-at "}") | |
2047 (save-excursion (goto-char (1- beg)) | |
2048 (looking-at "{")))) | |
2049 (insert "}") | |
2050 (goto-char beg) | |
2051 (insert "{"))))) | |
2052 | |
2053 ;; replace field text by BibTeX string constants according to | |
2054 ;; `bibtex-field-strings-alist'. | |
2055 (when (and (memq 'strings format) | |
2056 (setq temp (cdr (assoc-string field-name | |
2057 bibtex-field-strings-opt t)))) | |
2058 (goto-char beg-text) | |
2059 (dolist (re temp) | |
2060 (while (re-search-forward (car re) end-text t) | |
2061 (let ((bounds (save-match-data | |
2062 (bibtex-find-text-internal nil t)))) | |
2063 (unless (nth 4 bounds) | |
2064 ;; if match not at right subfield boundary... | |
2065 (if (< (match-end 0) (1- (nth 2 bounds))) | |
2066 (insert " # " (bibtex-field-left-delimiter)) | |
2067 (delete-char 1)) | |
2068 (replace-match (cdr re)) | |
2069 (goto-char (match-beginning 0)) | |
2070 ;; if match not at left subfield boundary... | |
2071 (if (< (1+ (nth 1 bounds)) (match-beginning 0)) | |
2072 (insert (bibtex-field-right-delimiter) " # ") | |
2073 (delete-backward-char 1)))))))) | |
1959 | 2074 |
1960 ;; use book title of crossref'd entry | 2075 ;; use book title of crossref'd entry |
1961 (if (and (memq 'inherit-booktitle format) | 2076 (if (and (memq 'inherit-booktitle format) |
1962 empty-field | 2077 empty-field |
1963 (bibtex-string= field-name "booktitle") | 2078 (bibtex-string= field-name "booktitle") |
2045 | 2160 |
2046 ;; fill entry | 2161 ;; fill entry |
2047 (if (memq 'realign format) | 2162 (if (memq 'realign format) |
2048 (bibtex-fill-entry)))))) | 2163 (bibtex-fill-entry)))))) |
2049 | 2164 |
2165 (defun bibtex-field-re-init (regexp-alist type) | |
2166 "Calculate optimized value for bibtex-regexp-TYPE-opt. | |
2167 This value is based on bibtex-regexp-TYPE-alist. TYPE is 'braces or 'strings. | |
2168 Return optimized value to be used by `bibtex-format-entry'." | |
2169 (setq regexp-alist | |
2170 (mapcar (lambda (e) | |
2171 (list (car e) | |
2172 (replace-regexp-in-string "[ \t\n]+" "[ \t\n]+" (nth 1 e)) | |
2173 (nth 2 e))) ; nil for 'braces'. | |
2174 regexp-alist)) | |
2175 (let (opt-list) | |
2176 ;; Loop over field names | |
2177 (dolist (field (delete-dups (apply 'append (mapcar 'car regexp-alist)))) | |
2178 (let (rules) | |
2179 ;; Collect all matches we have for this field name | |
2180 (dolist (e regexp-alist) | |
2181 (if (assoc-string field (car e) t) | |
2182 (push (cons (nth 1 e) (nth 2 e)) rules))) | |
2183 (if (eq type 'braces) | |
2184 ;; concatenate all regexps to a single regexp | |
2185 (setq rules (concat "\\(?:" (mapconcat 'car rules "\\|") "\\)"))) | |
2186 ;; create list of replacement rules. | |
2187 (push (cons field rules) opt-list))) | |
2188 opt-list)) | |
2189 | |
2050 | 2190 |
2051 (defun bibtex-autokey-abbrev (string len) | 2191 (defun bibtex-autokey-abbrev (string len) |
2052 "Return an abbreviation of STRING with at least LEN characters. | 2192 "Return an abbreviation of STRING with at least LEN characters. |
2053 If LEN is positive the abbreviation is terminated only after a consonant | 2193 If LEN is positive the abbreviation is terminated only after a consonant |
2054 or at the word end. If LEN is negative the abbreviation is strictly | 2194 or at the word end. If LEN is negative the abbreviation is strictly |
2097 additional-names) | 2237 additional-names) |
2098 (unless (or (not (numberp bibtex-autokey-names)) | 2238 (unless (or (not (numberp bibtex-autokey-names)) |
2099 (<= (length name-list) | 2239 (<= (length name-list) |
2100 (+ bibtex-autokey-names | 2240 (+ bibtex-autokey-names |
2101 bibtex-autokey-names-stretch))) | 2241 bibtex-autokey-names-stretch))) |
2102 ;; Take bibtex-autokey-names elements from beginning of name-list | 2242 ;; Take `bibtex-autokey-names' elements from beginning of name-list |
2103 (setq name-list (nreverse (nthcdr (- (length name-list) | 2243 (setq name-list (nreverse (nthcdr (- (length name-list) |
2104 bibtex-autokey-names) | 2244 bibtex-autokey-names) |
2105 (nreverse name-list))) | 2245 (nreverse name-list))) |
2106 additional-names bibtex-autokey-additional-names)) | 2246 additional-names bibtex-autokey-additional-names)) |
2107 (concat (mapconcat 'identity name-list | 2247 (concat (mapconcat 'identity name-list |
2159 bibtex-autokey-titlewords-stretch))) | 2299 bibtex-autokey-titlewords-stretch))) |
2160 (string-match "\\b\\w+" titlestring)) | 2300 (string-match "\\b\\w+" titlestring)) |
2161 (setq word (match-string 0 titlestring) | 2301 (setq word (match-string 0 titlestring) |
2162 titlestring (substring titlestring (match-end 0))) | 2302 titlestring (substring titlestring (match-end 0))) |
2163 ;; Ignore words matched by one of the elements of | 2303 ;; Ignore words matched by one of the elements of |
2164 ;; bibtex-autokey-titleword-ignore | 2304 ;; `bibtex-autokey-titleword-ignore' |
2165 (unless (let ((lst bibtex-autokey-titleword-ignore)) | 2305 (unless (let ((lst bibtex-autokey-titleword-ignore)) |
2166 (while (and lst | 2306 (while (and lst |
2167 (not (string-match (concat "\\`\\(?:" (car lst) | 2307 (not (string-match (concat "\\`\\(?:" (car lst) |
2168 "\\)\\'") word))) | 2308 "\\)\\'") word))) |
2169 (setq lst (cdr lst))) | 2309 (setq lst (cdr lst))) |
2171 (setq counter (1+ counter)) | 2311 (setq counter (1+ counter)) |
2172 (if (or (not (numberp bibtex-autokey-titlewords)) | 2312 (if (or (not (numberp bibtex-autokey-titlewords)) |
2173 (<= counter bibtex-autokey-titlewords)) | 2313 (<= counter bibtex-autokey-titlewords)) |
2174 (push word titlewords) | 2314 (push word titlewords) |
2175 (push word titlewords-extra)))) | 2315 (push word titlewords-extra)))) |
2176 ;; Obey bibtex-autokey-titlewords-stretch: | 2316 ;; Obey `bibtex-autokey-titlewords-stretch': |
2177 ;; If by now we have processed all words in titlestring, we include | 2317 ;; If by now we have processed all words in titlestring, we include |
2178 ;; titlewords-extra in titlewords. Otherwise, we ignore titlewords-extra. | 2318 ;; titlewords-extra in titlewords. Otherwise, we ignore titlewords-extra. |
2179 (unless (string-match "\\b\\w+" titlestring) | 2319 (unless (string-match "\\b\\w+" titlestring) |
2180 (setq titlewords (append titlewords-extra titlewords))) | 2320 (setq titlewords (append titlewords-extra titlewords))) |
2181 (mapconcat 'bibtex-autokey-demangle-title (nreverse titlewords) | 2321 (mapconcat 'bibtex-autokey-demangle-title (nreverse titlewords) |
2182 bibtex-autokey-titleword-separator)))) | 2322 bibtex-autokey-titleword-separator)))) |
2183 | 2323 |
2341 (let ((key (bibtex-key-in-head))) | 2481 (let ((key (bibtex-key-in-head))) |
2342 (unless (assoc key ref-keys) | 2482 (unless (assoc key ref-keys) |
2343 (push (cons key t) ref-keys))))))) | 2483 (push (cons key t) ref-keys))))))) |
2344 | 2484 |
2345 (let (;; ignore @String entries because they are handled | 2485 (let (;; ignore @String entries because they are handled |
2346 ;; separately by bibtex-parse-strings | 2486 ;; separately by `bibtex-parse-strings' |
2347 (bibtex-sort-ignore-string-entries t) | 2487 (bibtex-sort-ignore-string-entries t) |
2348 bounds) | 2488 bounds) |
2349 (bibtex-map-entries | 2489 (bibtex-map-entries |
2350 (lambda (key beg end) | 2490 (lambda (key beg end) |
2351 (if (and abortable | 2491 (if (and abortable |
2397 (goto-char (bibtex-end-of-text-in-string bounds))) | 2537 (goto-char (bibtex-end-of-text-in-string bounds))) |
2398 ;; successful operation --> return `bibtex-strings' | 2538 ;; successful operation --> return `bibtex-strings' |
2399 (setq bibtex-strings strings)))))) | 2539 (setq bibtex-strings strings)))))) |
2400 | 2540 |
2401 (defun bibtex-strings () | 2541 (defun bibtex-strings () |
2402 "Return `bibtex-strings'. Initialize this variable if necessary." | 2542 "Return `bibtex-strings'. Initialize this variable if necessary." |
2403 (if (listp bibtex-strings) bibtex-strings | 2543 (if (listp bibtex-strings) bibtex-strings |
2404 (bibtex-parse-strings (bibtex-string-files-init)))) | 2544 (bibtex-parse-strings (bibtex-string-files-init)))) |
2405 | 2545 |
2406 (defun bibtex-string-files-init () | 2546 (defun bibtex-string-files-init () |
2407 "Return initialization for `bibtex-strings'. | 2547 "Return initialization for `bibtex-strings'. |
2454 (if (and (eq major-mode 'bibtex-mode) | 2594 (if (and (eq major-mode 'bibtex-mode) |
2455 (not (eq (buffer-modified-tick) | 2595 (not (eq (buffer-modified-tick) |
2456 bibtex-buffer-last-parsed-tick))) | 2596 bibtex-buffer-last-parsed-tick))) |
2457 (save-restriction | 2597 (save-restriction |
2458 (widen) | 2598 (widen) |
2459 ;; Output no progress messages in bibtex-parse-keys | 2599 ;; Output no progress messages in `bibtex-parse-keys' |
2460 ;; because when in y-or-n-p that can hide the question. | 2600 ;; because when in `y-or-n-p' that can hide the question. |
2461 (if (and (listp (bibtex-parse-keys t)) | 2601 (if (and (listp (bibtex-parse-keys t)) |
2462 ;; update bibtex-strings | 2602 ;; update `bibtex-strings' |
2463 (listp (bibtex-parse-strings strings-init t))) | 2603 (listp (bibtex-parse-strings strings-init t))) |
2464 | 2604 |
2465 ;; remember that parsing was successful | 2605 ;; remember that parsing was successful |
2466 (setq bibtex-buffer-last-parsed-tick (buffer-modified-tick))))) | 2606 (setq bibtex-buffer-last-parsed-tick (buffer-modified-tick))))) |
2467 (setq buffers (cdr buffers)))))) | 2607 (setq buffers (cdr buffers)))))) |
2517 (defun bibtex-complete-internal (completions) | 2657 (defun bibtex-complete-internal (completions) |
2518 "Complete word fragment before point to longest prefix of COMPLETIONS. | 2658 "Complete word fragment before point to longest prefix of COMPLETIONS. |
2519 COMPLETIONS is an alist of strings. If point is not after the part | 2659 COMPLETIONS is an alist of strings. If point is not after the part |
2520 of a word, all strings are listed. Return completion." | 2660 of a word, all strings are listed. Return completion." |
2521 ;; Return value is used by cleanup functions. | 2661 ;; Return value is used by cleanup functions. |
2662 ;; Code inspired by `lisp-complete-symbol'. | |
2522 (let* ((case-fold-search t) | 2663 (let* ((case-fold-search t) |
2523 (beg (save-excursion | 2664 (beg (save-excursion |
2524 (re-search-backward "[ \t{\"]") | 2665 (re-search-backward "[ \t{\"]") |
2525 (forward-char) | 2666 (forward-char) |
2526 (point))) | 2667 (point))) |
2527 (end (point)) | 2668 (end (point)) |
2528 (part-of-word (buffer-substring-no-properties beg end)) | 2669 (pattern (buffer-substring-no-properties beg end)) |
2529 (completion (try-completion part-of-word completions))) | 2670 (completion (try-completion pattern completions))) |
2530 (cond ((not completion) | 2671 (cond ((not completion) |
2531 (error "Can't find completion for `%s'" part-of-word)) | 2672 (error "Can't find completion for `%s'" pattern)) |
2532 ((eq completion t) | 2673 ((eq completion t) |
2533 part-of-word) | 2674 pattern) |
2534 ((not (string= part-of-word completion)) | 2675 ((not (string= pattern completion)) |
2535 (delete-region beg end) | 2676 (delete-region beg end) |
2536 (insert completion) | 2677 (insert completion) |
2678 ;; Don't leave around a completions buffer that's out of date. | |
2679 (let ((win (get-buffer-window "*Completions*" 0))) | |
2680 (if win (with-selected-window win (bury-buffer)))) | |
2537 completion) | 2681 completion) |
2538 (t | 2682 (t |
2539 (message "Making completion list...") | 2683 (let ((minibuf-is-in-use |
2540 (with-output-to-temp-buffer "*Completions*" | 2684 (eq (minibuffer-window) (selected-window)))) |
2541 (display-completion-list (all-completions part-of-word completions) | 2685 (unless minibuf-is-in-use (message "Making completion list...")) |
2542 part-of-word)) | 2686 (with-output-to-temp-buffer "*Completions*" |
2543 (message "Making completion list...done") | 2687 (display-completion-list |
2688 (sort (all-completions pattern completions) 'string<) pattern)) | |
2689 (unless minibuf-is-in-use | |
2690 (message "Making completion list...done"))) | |
2544 nil)))) | 2691 nil)))) |
2545 | 2692 |
2546 (defun bibtex-complete-string-cleanup (str compl) | 2693 (defun bibtex-complete-string-cleanup (str compl) |
2547 "Cleanup after inserting string STR. | 2694 "Cleanup after inserting string STR. |
2548 Remove enclosing field delimiters for STR. Display message with | 2695 Remove enclosing field delimiters for STR. Display message with |
2560 (save-excursion | 2707 (save-excursion |
2561 (if (and (stringp key) | 2708 (if (and (stringp key) |
2562 (bibtex-find-entry key t)) | 2709 (bibtex-find-entry key t)) |
2563 (message "Ref: %s" (funcall bibtex-summary-function))))) | 2710 (message "Ref: %s" (funcall bibtex-summary-function))))) |
2564 | 2711 |
2565 (defun bibtex-copy-summary-as-kill () | 2712 (defun bibtex-copy-summary-as-kill (&optional arg) |
2566 "Push summery of current BibTeX entry to kill ring. | 2713 "Push summery of current BibTeX entry to kill ring. |
2567 Use `bibtex-summary-function' to generate summary." | 2714 Use `bibtex-summary-function' to generate summary. |
2568 (interactive) | 2715 If prefix ARG is non-nil push BibTeX entry's URL to kill ring |
2569 (save-excursion | 2716 that is generated by calling `bibtex-url'." |
2570 (bibtex-beginning-of-entry) | 2717 (interactive "P") |
2571 (if (looking-at bibtex-entry-maybe-empty-head) | 2718 (if arg (let ((url (bibtex-url nil t))) |
2572 (kill-new (message "%s" (funcall bibtex-summary-function))) | 2719 (if url (kill-new (message "%s" url)) |
2573 (error "No entry found")))) | 2720 (message "No URL known"))) |
2721 (save-excursion | |
2722 (bibtex-beginning-of-entry) | |
2723 (if (looking-at bibtex-entry-maybe-empty-head) | |
2724 (kill-new (message "%s" (funcall bibtex-summary-function))) | |
2725 (error "No entry found"))))) | |
2574 | 2726 |
2575 (defun bibtex-summary () | 2727 (defun bibtex-summary () |
2576 "Return summary of current BibTeX entry. | 2728 "Return summary of current BibTeX entry. |
2577 Used as default value of `bibtex-summary-function'." | 2729 Used as default value of `bibtex-summary-function'." |
2578 ;; It would be neat to customize this function. How? | 2730 ;; It would be neat to make this function customizable. How? |
2579 (if (looking-at bibtex-entry-maybe-empty-head) | 2731 (if (looking-at bibtex-entry-maybe-empty-head) |
2580 (let* ((bibtex-autokey-name-case-convert-function 'identity) | 2732 (let* ((bibtex-autokey-name-case-convert-function 'identity) |
2581 (bibtex-autokey-name-length 'infty) | 2733 (bibtex-autokey-name-length 'infty) |
2582 (bibtex-autokey-names 1) | 2734 (bibtex-autokey-names 1) |
2583 (bibtex-autokey-names-stretch 0) | 2735 (bibtex-autokey-names-stretch 0) |
2662 (let ((field-reg (concat "^[ \t]*" bibtex-field-name "[ \t]*="))) | 2814 (let ((field-reg (concat "^[ \t]*" bibtex-field-name "[ \t]*="))) |
2663 (beginning-of-line) | 2815 (beginning-of-line) |
2664 (unless (looking-at field-reg) | 2816 (unless (looking-at field-reg) |
2665 (re-search-backward field-reg nil t)))) | 2817 (re-search-backward field-reg nil t)))) |
2666 | 2818 |
2667 (defun bibtex-font-lock-url (bound) | 2819 (defun bibtex-font-lock-url (bound &optional no-button) |
2668 "Font-lock for URLs. BOUND limits the search." | 2820 "Font-lock for URLs. BOUND limits the search. |
2821 If NO-BUTTON is non-nil do not generate buttons." | |
2669 (let ((case-fold-search t) | 2822 (let ((case-fold-search t) |
2670 (pnt (point)) | 2823 (pnt (point)) |
2671 field bounds start end found) | 2824 name bounds start end found) |
2672 (bibtex-beginning-of-field) | 2825 (bibtex-beginning-of-field) |
2673 (while (and (not found) | 2826 (while (and (not found) |
2674 (<= (point) bound) | 2827 (<= (point) bound) |
2675 (prog1 (re-search-forward bibtex-font-lock-url-regexp bound t) | 2828 (prog1 (re-search-forward bibtex-font-lock-url-regexp bound t) |
2676 (setq field (match-string-no-properties 1))) | 2829 (setq name (match-string-no-properties 1))) |
2677 (setq bounds (bibtex-parse-field-text)) | 2830 (setq bounds (bibtex-parse-field-text)) |
2678 (progn | 2831 (progn |
2679 (setq start (car bounds) end (nth 1 bounds)) | 2832 (setq start (car bounds) end (nth 1 bounds)) |
2680 ;; Always ignore field delimiters | 2833 ;; Always ignore field delimiters |
2681 (if (memq (char-before end) '(?\} ?\")) | 2834 (if (memq (char-before end) '(?\} ?\")) |
2682 (setq end (1- end))) | 2835 (setq end (1- end))) |
2683 (if (memq (char-after start) '(?\{ ?\")) | 2836 (if (memq (char-after start) '(?\{ ?\")) |
2684 (setq start (1+ start))) | 2837 (setq start (1+ start))) |
2685 (>= bound start))) | 2838 (if (< start pnt) (setq start (min pnt end))) |
2686 (let ((lst bibtex-generate-url-list) url) | 2839 (<= start bound))) |
2687 (goto-char start) | 2840 (if (<= pnt start) |
2688 (while (and (not found) | 2841 (let ((lst bibtex-generate-url-list) url) |
2689 (setq url (car (pop lst)))) | 2842 (while (and (not found) (setq url (car (pop lst)))) |
2690 (setq found (and (bibtex-string= field (car url)) | 2843 (goto-char start) |
2691 (re-search-forward (cdr url) end t) | 2844 (setq found (and (bibtex-string= name (car url)) |
2692 (>= (match-beginning 0) pnt))))) | 2845 (re-search-forward (cdr url) end t)))))) |
2693 (goto-char end)) | 2846 (unless found (goto-char end))) |
2694 (if found (bibtex-button (match-beginning 0) (match-end 0) | 2847 (if (and found (not no-button)) |
2695 'bibtex-url (match-beginning 0))) | 2848 (bibtex-button (match-beginning 0) (match-end 0) |
2849 'bibtex-url (match-beginning 0))) | |
2696 found)) | 2850 found)) |
2697 | 2851 |
2698 (defun bibtex-font-lock-crossref (bound) | 2852 (defun bibtex-font-lock-crossref (bound) |
2699 "Font-lock for crossref fields. BOUND limits the search." | 2853 "Font-lock for crossref fields. BOUND limits the search." |
2700 (let ((case-fold-search t) | 2854 (let ((case-fold-search t) |
2710 found (>= start pnt))) | 2864 found (>= start pnt))) |
2711 (if found (bibtex-button start end 'bibtex-find-crossref | 2865 (if found (bibtex-button start end 'bibtex-find-crossref |
2712 (buffer-substring-no-properties start end) | 2866 (buffer-substring-no-properties start end) |
2713 start t)) | 2867 start t)) |
2714 found)) | 2868 found)) |
2869 | |
2870 (defun bibtex-font-lock-cite (matcher bound) | |
2871 "Font-lock for cited keys. | |
2872 MATCHER identifies the cited key, see `bibtex-cite-matcher-alist'. | |
2873 BOUND limits the search." | |
2874 (let (case-fold-search) | |
2875 (if (re-search-forward (car matcher) bound t) | |
2876 (let ((start (match-beginning (cdr matcher))) | |
2877 (end (match-end (cdr matcher)))) | |
2878 (bibtex-button start end 'bibtex-find-crossref | |
2879 (buffer-substring-no-properties start end) | |
2880 start t t) | |
2881 t)))) | |
2715 | 2882 |
2716 (defun bibtex-button-action (button) | 2883 (defun bibtex-button-action (button) |
2717 "Call BUTTON's BibTeX function." | 2884 "Call BUTTON's BibTeX function." |
2718 (apply (button-get button 'bibtex-function) | 2885 (apply (button-get button 'bibtex-function) |
2719 (button-get button 'bibtex-args))) | 2886 (button-get button 'bibtex-args))) |
2829 (bibtex-beginning-of-entry))))) | 2996 (bibtex-beginning-of-entry))))) |
2830 (setq imenu-generic-expression | 2997 (setq imenu-generic-expression |
2831 (list (list nil bibtex-entry-head bibtex-key-in-head)) | 2998 (list (list nil bibtex-entry-head bibtex-key-in-head)) |
2832 imenu-case-fold-search t) | 2999 imenu-case-fold-search t) |
2833 (make-local-variable 'choose-completion-string-functions) | 3000 (make-local-variable 'choose-completion-string-functions) |
2834 ;; XEmacs needs easy-menu-add, Emacs does not care | 3001 ;; XEmacs needs `easy-menu-add', Emacs does not care |
2835 (easy-menu-add bibtex-edit-menu) | 3002 (easy-menu-add bibtex-edit-menu) |
2836 (easy-menu-add bibtex-entry-menu) | 3003 (easy-menu-add bibtex-entry-menu) |
2837 (run-mode-hooks 'bibtex-mode-hook)) | 3004 (run-mode-hooks 'bibtex-mode-hook)) |
2838 | 3005 |
2839 (defun bibtex-field-list (entry-type) | 3006 (defun bibtex-field-list (entry-type) |
3123 ;; @String or @Preamble | 3290 ;; @String or @Preamble |
3124 ((setq bounds (or (bibtex-parse-string t) (bibtex-parse-preamble))) | 3291 ((setq bounds (or (bibtex-parse-string t) (bibtex-parse-preamble))) |
3125 (goto-char (bibtex-end-of-string bounds))) | 3292 (goto-char (bibtex-end-of-string bounds))) |
3126 ((looking-at bibtex-any-valid-entry-type) | 3293 ((looking-at bibtex-any-valid-entry-type) |
3127 ;; Parsing of entry failed | 3294 ;; Parsing of entry failed |
3128 (error "Syntactically incorrect BibTeX entry starts here.")) | 3295 (error "Syntactically incorrect BibTeX entry starts here")) |
3129 (t (if (interactive-p) (message "Not on a known BibTeX entry.")) | 3296 (t (if (interactive-p) (message "Not on a known BibTeX entry.")) |
3130 (goto-char pnt))) | 3297 (goto-char pnt))) |
3131 (point))) | 3298 (point))) |
3132 | 3299 |
3133 (defun bibtex-goto-line (arg) | 3300 (defun bibtex-goto-line (arg) |
3161 (goto-char pnt))))) | 3328 (goto-char pnt))))) |
3162 | 3329 |
3163 (defun bibtex-mark-entry () | 3330 (defun bibtex-mark-entry () |
3164 "Put mark at beginning, point at end of current BibTeX entry." | 3331 "Put mark at beginning, point at end of current BibTeX entry." |
3165 (interactive) | 3332 (interactive) |
3166 (set-mark (bibtex-beginning-of-entry)) | 3333 (push-mark (bibtex-beginning-of-entry)) |
3167 (bibtex-end-of-entry)) | 3334 (bibtex-end-of-entry)) |
3168 | 3335 |
3169 (defun bibtex-count-entries (&optional count-string-entries) | 3336 (defun bibtex-count-entries (&optional count-string-entries) |
3170 "Count number of entries in current buffer or region. | 3337 "Count number of entries in current buffer or region. |
3171 With prefix argument COUNT-STRING-ENTRIES count all entries, | 3338 With prefix argument COUNT-STRING-ENTRIES count all entries, |
3225 (if bounds (bibtex-text-in-field-bounds bounds t)) | 3392 (if bounds (bibtex-text-in-field-bounds bounds t)) |
3226 entry-name)) | 3393 entry-name)) |
3227 (list key nil entry-name)))))) | 3394 (list key nil entry-name)))))) |
3228 | 3395 |
3229 (defun bibtex-init-sort-entry-class-alist () | 3396 (defun bibtex-init-sort-entry-class-alist () |
3397 "Initialize `bibtex-sort-entry-class-alist' (buffer-local)." | |
3230 (unless (local-variable-p 'bibtex-sort-entry-class-alist) | 3398 (unless (local-variable-p 'bibtex-sort-entry-class-alist) |
3231 (set (make-local-variable 'bibtex-sort-entry-class-alist) | 3399 (set (make-local-variable 'bibtex-sort-entry-class-alist) |
3232 (let ((i -1) alist) | 3400 (let ((i -1) alist) |
3233 (dolist (class bibtex-sort-entry-class alist) | 3401 (dolist (class bibtex-sort-entry-class alist) |
3234 (setq i (1+ i)) | 3402 (setq i (1+ i)) |
3281 'bibtex-end-of-entry ; ENDREC function | 3449 'bibtex-end-of-entry ; ENDREC function |
3282 'bibtex-entry-index ; STARTKEY function | 3450 'bibtex-entry-index ; STARTKEY function |
3283 nil ; ENDKEY function | 3451 nil ; ENDKEY function |
3284 'bibtex-lessp)) ; PREDICATE | 3452 'bibtex-lessp)) ; PREDICATE |
3285 | 3453 |
3286 (defun bibtex-find-crossref (crossref-key &optional pnt split) | 3454 (defun bibtex-find-crossref (crossref-key &optional pnt split noerror) |
3287 "Move point to the beginning of BibTeX entry CROSSREF-KEY. | 3455 "Move point to the beginning of BibTeX entry CROSSREF-KEY. |
3288 If `bibtex-files' is non-nil, search all these files. | 3456 If `bibtex-files' is non-nil, search all these files. |
3289 Otherwise the search is limited to the current buffer. | 3457 Otherwise the search is limited to the current buffer. |
3290 Return position of entry if CROSSREF-KEY is found or nil otherwise. | 3458 Return position of entry if CROSSREF-KEY is found or nil otherwise. |
3291 If CROSSREF-KEY is in the same buffer like current entry but before it | 3459 If CROSSREF-KEY is in the same buffer like current entry but before it |
3292 an error is signaled. Optional arg PNT is the position of the referencing | 3460 an error is signaled. If NOERRER is non-nil this error is suppressed. |
3293 entry. It defaults to position of point. If optional arg SPLIT is non-nil, | 3461 Optional arg PNT is the position of the referencing entry. It defaults |
3294 split window so that both the referencing and the crossrefed entry are | 3462 to position of point. If optional arg SPLIT is non-nil, split window |
3295 displayed. | 3463 so that both the referencing and the crossrefed entry are displayed. |
3296 If called interactively, CROSSREF-KEY defaults to crossref key of current | 3464 |
3297 entry and SPLIT is t." | 3465 If called interactively, CROSSREF-KEY defaults to either the crossref key |
3466 of current entry or a key matched by `bibtex-cite-matcher-alist', | |
3467 whatever is nearer to the position of point. SPLIT is t. NOERROR is nil | |
3468 for a crossref key, t otherwise." | |
3298 (interactive | 3469 (interactive |
3299 (let ((crossref-key | 3470 (save-excursion |
3300 (save-excursion | 3471 (let* ((pnt (point)) |
3301 (bibtex-beginning-of-entry) | 3472 (_ (bibtex-beginning-of-entry)) |
3302 (let ((bounds (bibtex-search-forward-field "crossref" t))) | 3473 (end (cdr (bibtex-valid-entry t))) |
3303 (if bounds | 3474 (_ (unless end (error "Not inside valid entry"))) |
3304 (bibtex-text-in-field-bounds bounds t)))))) | 3475 (beg (match-end 0)) ; set by `bibtex-valid-entry' |
3305 (list (bibtex-read-key "Find crossref key: " crossref-key t) | 3476 (bounds (bibtex-search-forward-field "crossref" end)) |
3306 (point) t))) | 3477 case-fold-search best temp crossref-key) |
3478 (if bounds | |
3479 (setq crossref-key (bibtex-text-in-field-bounds bounds t) | |
3480 best (cons (bibtex-dist pnt (bibtex-end-of-field bounds) | |
3481 (bibtex-start-of-field bounds)) | |
3482 crossref-key))) | |
3483 (dolist (matcher bibtex-cite-matcher-alist) | |
3484 (goto-char beg) | |
3485 (while (re-search-forward (car matcher) end t) | |
3486 (setq temp (bibtex-dist pnt (match-end (cdr matcher)) | |
3487 (match-beginning (cdr matcher)))) | |
3488 ;; Accept the key closest to the position of point. | |
3489 (if (or (not best) (< temp (car best))) | |
3490 (setq best (cons temp (match-string-no-properties | |
3491 (cdr matcher))))))) | |
3492 (goto-char pnt) | |
3493 (setq temp (bibtex-read-key "Find crossref key: " (cdr best) t)) | |
3494 (list temp (point) t (not (and crossref-key | |
3495 (string= temp crossref-key))))))) | |
3496 | |
3307 (let (buffer pos eqb) | 3497 (let (buffer pos eqb) |
3308 (save-excursion | 3498 (save-excursion |
3309 (setq pos (bibtex-find-entry crossref-key t) | 3499 (setq pos (bibtex-find-entry crossref-key t) |
3310 buffer (current-buffer))) | 3500 buffer (current-buffer))) |
3311 (setq eqb (eq buffer (current-buffer))) | 3501 (setq eqb (eq buffer (current-buffer))) |
3312 (cond ((not pos) | 3502 (cond ((not pos) |
3313 (if split (message "Crossref key `%s' not found" crossref-key))) | 3503 (if split (message "Crossref key `%s' not found" crossref-key))) |
3314 (split ; called (quasi) interactively | 3504 (split ; called (quasi) interactively |
3315 (unless pnt (setq pnt (point))) | 3505 (unless pnt (setq pnt (point))) |
3316 (goto-char pnt) | 3506 (goto-char pnt) |
3317 (if eqb (select-window (split-window)) | 3507 (if (and eqb (= pos (save-excursion (bibtex-beginning-of-entry)))) |
3318 (pop-to-buffer buffer)) | 3508 (message "Key `%s' is current entry" crossref-key) |
3319 (goto-char pos) | 3509 (if eqb (select-window (split-window)) |
3320 (bibtex-reposition-window) | 3510 (pop-to-buffer buffer)) |
3321 (beginning-of-line) | 3511 (goto-char pos) |
3322 (if (and eqb (> pnt pos)) | 3512 (bibtex-reposition-window) |
3323 (error "The referencing entry must precede the crossrefed entry!"))) | 3513 (beginning-of-line) |
3514 (if (and eqb (> pnt pos) (not noerror)) | |
3515 (error "The referencing entry must precede the crossrefed entry!")))) | |
3324 ;; `bibtex-find-crossref' is called noninteractively during | 3516 ;; `bibtex-find-crossref' is called noninteractively during |
3325 ;; clean-up of an entry. Then it is not possible to check | 3517 ;; clean-up of an entry. Then it is not possible to check |
3326 ;; whether the current entry and the crossrefed entry have | 3518 ;; whether the current entry and the crossrefed entry have |
3327 ;; the correct sorting order. | 3519 ;; the correct sorting order. |
3328 (eqb (goto-char pos)) | 3520 (eqb (goto-char pos)) |
3329 (t (set-buffer buffer) (goto-char pos))) | 3521 (t (set-buffer buffer) (goto-char pos))) |
3330 pos)) | 3522 pos)) |
3523 | |
3524 (defun bibtex-dist (pos beg end) | |
3525 "Return distance between POS and region delimited by BEG and END." | |
3526 (cond ((and (<= beg pos) (<= pos end)) 0) | |
3527 ((< pos beg) (- beg pos)) | |
3528 (t (- pos end)))) | |
3331 | 3529 |
3332 (defun bibtex-find-entry (key &optional global start display) | 3530 (defun bibtex-find-entry (key &optional global start display) |
3333 "Move point to the beginning of BibTeX entry named KEY. | 3531 "Move point to the beginning of BibTeX entry named KEY. |
3334 Return position of entry if KEY is found or nil if not found. | 3532 Return position of entry if KEY is found or nil if not found. |
3335 With prefix arg GLOBAL non-nil, search KEY in `bibtex-files'. | 3533 With prefix arg GLOBAL non-nil, search KEY in `bibtex-files'. |
3392 (not bibtex-maintain-sorted-entries))) | 3590 (not bibtex-maintain-sorted-entries))) |
3393 (bibtex-move-outside-of-entry)) | 3591 (bibtex-move-outside-of-entry)) |
3394 ;; if key-exist is non-nil due to the previous cond clause | 3592 ;; if key-exist is non-nil due to the previous cond clause |
3395 ;; then point will be at beginning of entry named key. | 3593 ;; then point will be at beginning of entry named key. |
3396 (key-exist) | 3594 (key-exist) |
3397 (t ; bibtex-maintain-sorted-entries is non-nil | 3595 (t ; `bibtex-maintain-sorted-entries' is non-nil |
3398 (let* ((case-fold-search t) | 3596 (let* ((case-fold-search t) |
3399 (left (save-excursion (bibtex-beginning-of-first-entry))) | 3597 (left (save-excursion (bibtex-beginning-of-first-entry))) |
3400 (bounds (save-excursion (goto-char (point-max)) | 3598 (bounds (save-excursion (goto-char (point-max)) |
3401 (bibtex-skip-to-valid-entry t))) | 3599 (bibtex-skip-to-valid-entry t))) |
3402 (right (if bounds (cdr bounds) (point-min))) | 3600 (right (if bounds (cdr bounds) (point-min))) |
3574 (unless (eq major-mode 'compilation-mode) (compilation-mode)) | 3772 (unless (eq major-mode 'compilation-mode) (compilation-mode)) |
3575 (toggle-read-only -1) | 3773 (toggle-read-only -1) |
3576 (delete-region (point-min) (point-max)) | 3774 (delete-region (point-min) (point-max)) |
3577 (insert "BibTeX mode command `bibtex-validate'\n" | 3775 (insert "BibTeX mode command `bibtex-validate'\n" |
3578 (if syntax-error | 3776 (if syntax-error |
3579 "Maybe undetected errors due to syntax errors. Correct and validate again.\n" | 3777 "Maybe undetected errors due to syntax errors. Correct and validate again.\n" |
3580 "\n")) | 3778 "\n")) |
3581 (dolist (err error-list) | 3779 (dolist (err error-list) |
3582 (insert (format "%s:%d: %s\n" file (car err) (cdr err)))) | 3780 (insert (format "%s:%d: %s\n" file (car err) (cdr err)))) |
3583 (set-buffer-modified-p nil) | 3781 (set-buffer-modified-p nil) |
3584 (toggle-read-only 1) | 3782 (toggle-read-only 1) |
3735 start-text (or (match-beginning bibtex-key-in-head) | 3933 start-text (or (match-beginning bibtex-key-in-head) |
3736 (match-end 0)) | 3934 (match-end 0)) |
3737 end-text (or (match-end bibtex-key-in-head) | 3935 end-text (or (match-end bibtex-key-in-head) |
3738 (match-end 0)) | 3936 (match-end 0)) |
3739 end end-text | 3937 end end-text |
3740 no-sub t) ;; subfields do not make sense | 3938 no-sub t) ; subfields do not make sense |
3741 (setq failure t))) | 3939 (setq failure t))) |
3742 (t (setq failure t))) | 3940 (t (setq failure t))) |
3743 (when (and subfield (not failure)) | 3941 (when (and subfield (not failure)) |
3744 (setq failure no-sub) | 3942 (setq failure no-sub) |
3745 (unless failure | 3943 (unless failure |
3924 begin on separate lines prior to calling `bibtex-clean-entry' or if | 4122 begin on separate lines prior to calling `bibtex-clean-entry' or if |
3925 'realign is contained in `bibtex-entry-format'.) | 4123 'realign is contained in `bibtex-entry-format'.) |
3926 Don't call `bibtex-clean-entry' on @Preamble entries. | 4124 Don't call `bibtex-clean-entry' on @Preamble entries. |
3927 At end of the cleaning process, the functions in | 4125 At end of the cleaning process, the functions in |
3928 `bibtex-clean-entry-hook' are called with region narrowed to entry." | 4126 `bibtex-clean-entry-hook' are called with region narrowed to entry." |
3929 ;; Opt. arg called-by-reformat is t if bibtex-clean-entry | 4127 ;; Opt. arg CALLED-BY-REFORMAT is t if `bibtex-clean-entry' |
3930 ;; is called by bibtex-reformat | 4128 ;; is called by `bibtex-reformat' |
3931 (interactive "P") | 4129 (interactive "P") |
3932 (let ((case-fold-search t) | 4130 (let ((case-fold-search t) |
3933 (start (bibtex-beginning-of-entry)) | 4131 (start (bibtex-beginning-of-entry)) |
3934 (_ (or (looking-at bibtex-any-entry-maybe-empty-head) | 4132 (_ (or (looking-at bibtex-any-entry-maybe-empty-head) |
3935 (error "Not inside a BibTeX entry"))) | 4133 (error "Not inside a BibTeX entry"))) |
3944 ;; (bibtex-format-string) | 4142 ;; (bibtex-format-string) |
3945 (t (bibtex-format-entry))) | 4143 (t (bibtex-format-entry))) |
3946 ;; set key | 4144 ;; set key |
3947 (when (or new-key (not key)) | 4145 (when (or new-key (not key)) |
3948 (setq key (bibtex-generate-autokey)) | 4146 (setq key (bibtex-generate-autokey)) |
3949 ;; Sometimes bibtex-generate-autokey returns an empty string | 4147 ;; Sometimes `bibtex-generate-autokey' returns an empty string |
3950 (if (or bibtex-autokey-edit-before-use (string= "" key)) | 4148 (if (or bibtex-autokey-edit-before-use (string= "" key)) |
3951 (setq key (if (eq entry-type 'string) | 4149 (setq key (if (eq entry-type 'string) |
3952 (bibtex-read-string-key key) | 4150 (bibtex-read-string-key key) |
3953 (bibtex-read-key "Key to use: " key)))) | 4151 (bibtex-read-key "Key to use: " key)))) |
3954 (save-excursion | 4152 (save-excursion |
4025 If optional arg MOVE is non-nil move point to end of field." | 4223 If optional arg MOVE is non-nil move point to end of field." |
4026 (let ((end-field (copy-marker (bibtex-end-of-field bounds)))) | 4224 (let ((end-field (copy-marker (bibtex-end-of-field bounds)))) |
4027 (if (not justify) | 4225 (if (not justify) |
4028 (goto-char (bibtex-start-of-text-in-field bounds)) | 4226 (goto-char (bibtex-start-of-text-in-field bounds)) |
4029 (goto-char (bibtex-start-of-field bounds)) | 4227 (goto-char (bibtex-start-of-field bounds)) |
4030 (forward-char) ;; leading comma | 4228 (forward-char) ; leading comma |
4031 (bibtex-delete-whitespace) | 4229 (bibtex-delete-whitespace) |
4032 (open-line 1) | 4230 (open-line 1) |
4033 (forward-char) | 4231 (forward-char) |
4034 (indent-to-column (+ bibtex-entry-offset | 4232 (indent-to-column (+ bibtex-entry-offset |
4035 bibtex-field-indentation)) | 4233 bibtex-field-indentation)) |
4043 (forward-char) | 4241 (forward-char) |
4044 (bibtex-delete-whitespace) | 4242 (bibtex-delete-whitespace) |
4045 (if bibtex-align-at-equal-sign | 4243 (if bibtex-align-at-equal-sign |
4046 (insert " ") | 4244 (insert " ") |
4047 (indent-to-column bibtex-text-indentation))) | 4245 (indent-to-column bibtex-text-indentation))) |
4048 ;; Paragraphs within fields are not preserved. Bother? | 4246 ;; Paragraphs within fields are not preserved. Bother? |
4049 (fill-region-as-paragraph (line-beginning-position) end-field | 4247 (fill-region-as-paragraph (line-beginning-position) end-field |
4050 default-justification nil (point)) | 4248 default-justification nil (point)) |
4051 (if move (goto-char end-field)))) | 4249 (if move (goto-char end-field)))) |
4052 | 4250 |
4053 (defun bibtex-fill-field (&optional justify) | 4251 (defun bibtex-fill-field (&optional justify) |
4128 ("Remove empty optional and alternative fields? " . 'opts-or-alts) | 4326 ("Remove empty optional and alternative fields? " . 'opts-or-alts) |
4129 ("Remove delimiters around pure numerical fields? " . 'numerical-fields) | 4327 ("Remove delimiters around pure numerical fields? " . 'numerical-fields) |
4130 (,(concat (if bibtex-comma-after-last-field "Insert" "Remove") | 4328 (,(concat (if bibtex-comma-after-last-field "Insert" "Remove") |
4131 " comma at end of entry? ") . 'last-comma) | 4329 " comma at end of entry? ") . 'last-comma) |
4132 ("Replace double page dashes by single ones? " . 'page-dashes) | 4330 ("Replace double page dashes by single ones? " . 'page-dashes) |
4331 ("Delete whitespace at the beginning and end of fields? " . 'whitespace) | |
4133 ("Inherit booktitle? " . 'inherit-booktitle) | 4332 ("Inherit booktitle? " . 'inherit-booktitle) |
4134 ("Force delimiters? " . 'delimiters) | 4333 ("Force delimiters? " . 'delimiters) |
4135 ("Unify case of entry types and field names? " . 'unify-case)))))) | 4334 ("Unify case of entry types and field names? " . 'unify-case) |
4335 ("Enclose parts of field entries by braces? " . 'braces) | |
4336 ("Replace parts of field entries by string constants? " . 'strings)))))) | |
4136 ;; Do not include required-fields because `bibtex-reformat' | 4337 ;; Do not include required-fields because `bibtex-reformat' |
4137 ;; cannot handle the error messages of `bibtex-format-entry'. | 4338 ;; cannot handle the error messages of `bibtex-format-entry'. |
4138 ;; Use `bibtex-validate' to check for required fields. | 4339 ;; Use `bibtex-validate' to check for required fields. |
4139 ((eq t bibtex-entry-format) | 4340 ((eq t bibtex-entry-format) |
4140 '(realign opts-or-alts numerical-fields delimiters | 4341 '(realign opts-or-alts numerical-fields delimiters |
4141 last-comma page-dashes unify-case inherit-booktitle)) | 4342 last-comma page-dashes unify-case inherit-booktitle |
4343 whitespace braces strings)) | |
4142 (t | 4344 (t |
4143 (remove 'required-fields (push 'realign bibtex-entry-format))))) | 4345 (remove 'required-fields (push 'realign bibtex-entry-format))))) |
4144 (reformat-reference-keys | 4346 (reformat-reference-keys |
4145 (if read-options | 4347 (if read-options |
4146 (if use-previous-options | 4348 (if use-previous-options |
4176 entries from minibuffer." | 4378 entries from minibuffer." |
4177 (interactive "*P") | 4379 (interactive "*P") |
4178 (message "Starting to validate buffer...") | 4380 (message "Starting to validate buffer...") |
4179 (sit-for 1 nil t) | 4381 (sit-for 1 nil t) |
4180 (bibtex-realign) | 4382 (bibtex-realign) |
4181 (deactivate-mark) ; So bibtex-validate works on the whole buffer. | 4383 (deactivate-mark) ; So `bibtex-validate' works on the whole buffer. |
4182 (if (not (let (bibtex-maintain-sorted-entries) | 4384 (if (not (let (bibtex-maintain-sorted-entries) |
4183 (bibtex-validate))) | 4385 (bibtex-validate))) |
4184 (message "Correct errors and call `bibtex-convert-alien' again") | 4386 (message "Correct errors and call `bibtex-convert-alien' again") |
4185 (message "Starting to reformat entries...") | 4387 (message "Starting to reformat entries...") |
4186 (sit-for 2 nil t) | 4388 (sit-for 2 nil t) |
4187 (bibtex-reformat read-options) | 4389 (bibtex-reformat read-options) |
4188 (goto-char (point-max)) | 4390 (goto-char (point-max)) |
4189 (message "Buffer is now parsable. Please save it."))) | 4391 (message "Buffer is now parsable. Please save it."))) |
4190 | 4392 |
4191 (defun bibtex-complete () | 4393 (defun bibtex-complete () |
4192 "Complete word fragment before point according to context. | 4394 "Complete word fragment before point according to context. |
4193 If point is inside key or crossref field perform key completion based on | 4395 If point is inside key or crossref field perform key completion based on |
4194 `bibtex-reference-keys'. Inside a month field perform key completion | 4396 `bibtex-reference-keys'. Inside a month field perform key completion |
4247 ((eq compl 'crossref-key) | 4449 ((eq compl 'crossref-key) |
4248 ;; crossref key completion | 4450 ;; crossref key completion |
4249 ;; | 4451 ;; |
4250 ;; If we quit the *Completions* buffer without requesting | 4452 ;; If we quit the *Completions* buffer without requesting |
4251 ;; a completion, `choose-completion-string-functions' is still | 4453 ;; a completion, `choose-completion-string-functions' is still |
4252 ;; non-nil. Therefore, `choose-completion-string-functions' is | 4454 ;; non-nil. Therefore, `choose-completion-string-functions' is |
4253 ;; always set (either to non-nil or nil) when a new completion | 4455 ;; always set (either to non-nil or nil) when a new completion |
4254 ;; is requested. | 4456 ;; is requested. |
4255 (let (completion-ignore-case) | 4457 (let (completion-ignore-case) |
4256 (setq choose-completion-string-functions | 4458 (setq choose-completion-string-functions |
4257 (lambda (choice buffer mini-p base-size) | 4459 (lambda (choice buffer mini-p base-size) |
4274 (setq choose-completion-string-functions | 4476 (setq choose-completion-string-functions |
4275 `(lambda (choice buffer mini-p base-size) | 4477 `(lambda (choice buffer mini-p base-size) |
4276 (setq choose-completion-string-functions nil) | 4478 (setq choose-completion-string-functions nil) |
4277 (choose-completion-string choice buffer base-size) | 4479 (choose-completion-string choice buffer base-size) |
4278 (bibtex-complete-string-cleanup choice ',compl) | 4480 (bibtex-complete-string-cleanup choice ',compl) |
4279 t)) ; needed by choose-completion-string-functions | 4481 t)) ; needed by `choose-completion-string-functions' |
4280 (bibtex-complete-string-cleanup (bibtex-complete-internal compl) | 4482 (bibtex-complete-string-cleanup (bibtex-complete-internal compl) |
4281 compl))) | 4483 compl))) |
4282 | 4484 |
4283 (t (setq choose-completion-string-functions nil) | 4485 (t (setq choose-completion-string-functions nil) |
4284 (error "Point outside key or BibTeX field"))))) | 4486 (error "Point outside key or BibTeX field"))))) |
4389 | 4591 |
4390 (defun bibtex-url (&optional pos no-browse) | 4592 (defun bibtex-url (&optional pos no-browse) |
4391 "Browse a URL for the BibTeX entry at point. | 4593 "Browse a URL for the BibTeX entry at point. |
4392 Optional POS is the location of the BibTeX entry. | 4594 Optional POS is the location of the BibTeX entry. |
4393 The URL is generated using the schemes defined in `bibtex-generate-url-list' | 4595 The URL is generated using the schemes defined in `bibtex-generate-url-list' |
4394 \(see there\). Then the URL is passed to `browse-url' unless NO-BROWSE is nil. | 4596 \(see there\). If multiple schemes match for this entry, or the same scheme |
4597 matches more than once, use the one for which the first step's match is the | |
4598 closest to POS. The URL is passed to `browse-url' unless NO-BROWSE is t. | |
4395 Return the URL or nil if none can be generated." | 4599 Return the URL or nil if none can be generated." |
4396 (interactive) | 4600 (interactive) |
4601 (unless pos (setq pos (point))) | |
4397 (save-excursion | 4602 (save-excursion |
4398 (if pos (goto-char pos)) | 4603 (goto-char pos) |
4399 (bibtex-beginning-of-entry) | 4604 (bibtex-beginning-of-entry) |
4400 ;; Always remove field delimiters | 4605 (let ((end (save-excursion (bibtex-end-of-entry))) |
4401 (let ((fields-alist (bibtex-parse-entry t)) | 4606 (fields-alist (save-excursion (bibtex-parse-entry t))) |
4402 ;; Always ignore case, | 4607 ;; Always ignore case, |
4403 (case-fold-search t) | 4608 (case-fold-search t) |
4404 (lst bibtex-generate-url-list) | 4609 text url scheme obj fmt fl-match step) |
4405 field url scheme obj fmt) | 4610 ;; The return value of `bibtex-parse-entry' (i.e., FIELDS-ALIST) |
4406 (while (setq scheme (pop lst)) | 4611 ;; is always used to generate the URL. However, if the BibTeX |
4407 (when (and (setq field (cdr (assoc-string (caar scheme) | 4612 ;; entry contains more than one URL, we have multiple matches |
4408 fields-alist t))) | 4613 ;; for the first step defining the generation of the URL. |
4409 (string-match (cdar scheme) field)) | 4614 ;; Therefore, we try to initiate the generation of the URL |
4410 (setq lst nil | 4615 ;; based on the match of `bibtex-font-lock-url' that is the |
4411 scheme (cdr scheme) | 4616 ;; closest to POS. If that fails (no match found) we try to |
4412 url (if (null scheme) (match-string 0 field) | 4617 ;; initiate the generation of the URL based on the properly |
4413 (if (stringp (car scheme)) | 4618 ;; concatenated CONTENT of the field as returned by |
4414 (setq fmt (pop scheme))) | 4619 ;; `bibtex-text-in-field-bounds'. The latter approach can |
4415 (dolist (step scheme) | 4620 ;; differ from the former because `bibtex-font-lock-url' uses |
4416 (setq field (cdr (assoc-string (car step) fields-alist t))) | 4621 ;; the buffer itself. |
4417 (if (string-match (nth 1 step) field) | 4622 (while (bibtex-font-lock-url end t) |
4418 (push (cond ((functionp (nth 2 step)) | 4623 (push (list (bibtex-dist pos (match-beginning 0) (match-end 0)) |
4419 (funcall (nth 2 step) field)) | 4624 (match-beginning 0) |
4420 ((numberp (nth 2 step)) | 4625 (buffer-substring-no-properties |
4421 (match-string (nth 2 step) field)) | 4626 (match-beginning 0) (match-end 0))) |
4422 (t | 4627 fl-match) |
4423 (replace-match (nth 2 step) t nil field))) | 4628 ;; `bibtex-font-lock-url' moves point to end of match. |
4424 obj) | 4629 (forward-char)) |
4425 ;; If the scheme is set up correctly, | 4630 (when fl-match |
4426 ;; we should never reach this point | 4631 (setq fl-match (car (sort fl-match (lambda (x y) (< (car x) (car y)))))) |
4427 (error "Match failed: %s" field))) | 4632 (goto-char (nth 1 fl-match)) |
4428 (if fmt (apply 'format fmt (nreverse obj)) | 4633 (bibtex-beginning-of-field) (re-search-backward ",") |
4429 (apply 'concat (nreverse obj))))) | 4634 (let* ((bounds (bibtex-parse-field)) |
4430 (if (interactive-p) (message "%s" url)) | 4635 (name (bibtex-name-in-field bounds)) |
4431 (unless no-browse (browse-url url)))) | 4636 (content (bibtex-text-in-field-bounds bounds t)) |
4637 (lst bibtex-generate-url-list)) | |
4638 ;; This match can fail when CONTENT differs from text in buffer. | |
4639 (when (string-match (regexp-quote (nth 2 fl-match)) content) | |
4640 ;; TEXT is the part of CONTENT that starts with the match | |
4641 ;; of `bibtex-font-lock-url' we are looking for. | |
4642 (setq text (substring content (match-beginning 0))) | |
4643 (while (and (not url) (setq scheme (pop lst))) | |
4644 ;; Verify the match of `bibtex-font-lock-url' by | |
4645 ;; comparing with TEXT. | |
4646 (when (and (bibtex-string= (caar scheme) name) | |
4647 (string-match (cdar scheme) text)) | |
4648 (setq url t scheme (cdr scheme))))))) | |
4649 | |
4650 ;; If the match of `bibtex-font-lock-url' was not approved | |
4651 ;; parse FIELDS-ALIST, i.e., the output of `bibtex-parse-entry'. | |
4652 (unless url | |
4653 (let ((lst bibtex-generate-url-list)) | |
4654 (while (and (not url) (setq scheme (pop lst))) | |
4655 (when (and (setq text (cdr (assoc-string (caar scheme) | |
4656 fields-alist t))) | |
4657 (string-match (cdar scheme) text)) | |
4658 (setq url t scheme (cdr scheme)))))) | |
4659 | |
4660 (when url | |
4661 (setq url (if (null scheme) (match-string 0 text) | |
4662 (if (stringp (car scheme)) | |
4663 (setq fmt (pop scheme))) | |
4664 (dotimes (i (length scheme)) | |
4665 (setq step (nth i scheme)) | |
4666 ;; The first step shall use TEXT as obtained earlier. | |
4667 (unless (= i 0) | |
4668 (setq text (cdr (assoc-string (car step) fields-alist t)))) | |
4669 (if (string-match (nth 1 step) text) | |
4670 (push (cond ((functionp (nth 2 step)) | |
4671 (funcall (nth 2 step) text)) | |
4672 ((numberp (nth 2 step)) | |
4673 (match-string (nth 2 step) text)) | |
4674 (t | |
4675 (replace-match (nth 2 step) t nil text))) | |
4676 obj) | |
4677 ;; If SCHEME is set up correctly, | |
4678 ;; we should never reach this point | |
4679 (error "Match failed: %s" text))) | |
4680 (if fmt (apply 'format fmt (nreverse obj)) | |
4681 (apply 'concat (nreverse obj))))) | |
4682 (if (interactive-p) (message "%s" url)) | |
4683 (unless no-browse (browse-url url))) | |
4432 (if (and (not url) (interactive-p)) (message "No URL known.")) | 4684 (if (and (not url) (interactive-p)) (message "No URL known.")) |
4433 url))) | 4685 url))) |
4434 | 4686 |
4435 | 4687 |
4436 ;; Make BibTeX a Feature | 4688 ;; Make BibTeX a Feature |