Mercurial > emacs
comparison lisp/textmodes/bibtex.el @ 57054:0b058857c704
(bibtex-mark-active, bibtex-run-with-idle-timer): Move `if' inside the defun.
(bibtex-autokey-titleword-ignore): Regexp is used in a case insensitive env.
(bibtex-mode-map): Rearrange order of menus.
(bibtex-quoted-string-re): Obsolete.
(bibtex-complete-key-cleanup): Variable replaced by new function.
(bibtex-font-lock-keywords): Use backquotes.
(bibtex-font-lock-url-regexp): New internal variable.
(bibtex-name-in-field): New opt arg remove-opt-alt to remove "OPT" and "ALT".
(bibtex-insert-current-kill, bibtex-make-field)
(bibtex-prepare-new-entry, bibtex-yank-pop, bibtex-String): Use unless.
(bibtex-parse-field-text): Simplify.
(bibtex-string=): New helper function.
(bibtex-member-of-regexp): Merge with bibtex-autokey-get-title.
(bibtex-map-entries): Use bibtex-string=.
(bibtex-search-entry): Use not.
(bibtex-enclosing-field): Fix docstring.
(bibtex-assoc-regexp): Obsolete.
(bibtex-format-entry): Use assoc-string and bibtex-string=.
(bibtex-autokey-get-names): Handle empty name field.
(bibtex-parse-strings): Use assoc-string and unless.
(bibtex-complete-string-cleanup): Expansion list is passed as an argument.
Use assoc-string.
(bibtex-pop): Simplify.
(bibtex-mode): Set font-lock-extra-managed-props.
(bibtex-entry-update): Use assoc-string.
(bibtex-parse-entry): Remove "OPT" and "ALT" from FIELD.
(bibtex-autofill-entry): Use bibtex-string=.
(bibtex-print-help-message): Simplify.
(bibtex-find-entry): New optional arg START.
(bibtex-validate): Use bibtex-string= and assoc-string.
Do not call obsolete function compilation-parse-errors.
(bibtex-remove-delimiters): Only remove delimiters if present.
(bibtex-copy-entry-as-kill): Add docstring.
(bibtex-clean-entry): Use bibtex-string=. Handle empty keys.
Detect duplicate keys if bibtex-maintain-sorted-entries is nil.
(bibtex-complete): Use bibtex-predefined-month-strings,
bibtex-string=, and new function bibtex-complete-key-cleanup.
(bibtex-generate-url-list): New variable.
(bibtex-url): New command bound to C-c C-l and mouse-2.
(bibtex-url-map): New local keymap for bibtex-url-mouse.
(bibtex-font-lock-url): New function.
author | Stefan Monnier <monnier@iro.umontreal.ca> |
---|---|
date | Fri, 10 Sep 2004 21:24:50 +0000 |
parents | 1b2cb608f18e |
children | 3d9707888790 |
comparison
equal
deleted
inserted
replaced
57053:abdfb8ccbb2b | 57054:0b058857c704 |
---|---|
638 :group 'bibtex-autokey | 638 :group 'bibtex-autokey |
639 :type 'integer) | 639 :type 'integer) |
640 | 640 |
641 (defcustom bibtex-autokey-titleword-ignore | 641 (defcustom bibtex-autokey-titleword-ignore |
642 '("A" "An" "On" "The" "Eine?" "Der" "Die" "Das" | 642 '("A" "An" "On" "The" "Eine?" "Der" "Die" "Das" |
643 "[^A-Z].*" ".*[^a-zA-Z0-9].*") | 643 "[^A-Z].*" ".*[^A-Z0-9].*") |
644 "*Determines words from the title that are not to be used in the key. | 644 "*Determines words from the title that are not to be used in the key. |
645 Each item of the list is a regexp. If a word of the title matchs a | 645 Each item of the list is a regexp. If a word of the title matchs a |
646 regexp from that list, it is not included in the title part of the key. | 646 regexp from that list, it is not included in the title part of the key. |
647 See `bibtex-generate-autokey' for details." | 647 See `bibtex-generate-autokey' for details." |
648 :group 'bibtex-autokey | 648 :group 'bibtex-autokey |
760 | 760 |
761 (defcustom bibtex-autofill-types '("Proceedings") | 761 (defcustom bibtex-autofill-types '("Proceedings") |
762 "Automatically fill fields if possible for those BibTeX entry types." | 762 "Automatically fill fields if possible for those BibTeX entry types." |
763 :type '(repeat string)) | 763 :type '(repeat string)) |
764 | 764 |
765 (defcustom bibtex-complete-key-cleanup nil | 765 (defcustom bibtex-generate-url-list |
766 "*Function called by `bibtex-complete' after insertion of a key fragment." | 766 '((("url" . t) ("url" t))) |
767 :group 'bibtex-autokey | 767 "List of schemes for generating the URL of a BibTeX entry. |
768 :type '(choice (const :tag "None" nil) | 768 These schemes are used by `bibtex-url'. |
769 (function :tag "Cleanup function"))) | 769 |
770 Each scheme is of the form ((FIELD . REGEXP) STEPS). | |
771 | |
772 FIELD is a field name as returned by `bibtex-parse-entry'. | |
773 REGEXP is matched against the text of FIELD. | |
774 If the match succeeds, the list STEPS is used to generate the URL. | |
775 If REGEXP is t, always generate the URL if FIELD is present. | |
776 | |
777 If an element of STEPS is a list (FIELD MATCH FILTER), | |
778 the text of FIELD is matched against MATCH. | |
779 If MATCH is t, the text of FIELD is accepted as is. | |
780 If MATCH is a cons cell (REGEXP . REPLACE), the text is matched against REGEXP. | |
781 If REPLACE is a string, the text is replaced with REPLACE. If REPLACE is a | |
782 number, it specifies which parenthesized expression in the match is taken. | |
783 The optional element FILTER is a function for piping the match through it. | |
784 The text strings are then concatenated to generate the URL. | |
785 | |
786 If an element of STEPS is a string, it is simply added to the URL. | |
787 | |
788 Case is always ignored. Always remove the field delimiters." | |
789 :group 'bibtex | |
790 :type '(repeat | |
791 (list :tag "Scheme" | |
792 (cons :tag "Matcher" :extra-offset 4 | |
793 (string :tag "BibTeX field") | |
794 (choice (regexp :tag "Regexp") | |
795 (const :tag "Accept as is" t))) | |
796 (repeat :tag "Steps to generate URL" :inline t | |
797 (choice | |
798 (string :tag "Literal text") | |
799 (list (string :tag "BibTeX field") | |
800 (choice (const :tag "Accept as is" t) | |
801 (cons (string :tag "Field") | |
802 (choice (regexp :tag "Regexp") | |
803 (integer :tag "Matched parenthesis")))) | |
804 (option (function :tag "Filter" :value ignore)))))))) | |
770 | 805 |
771 ;; bibtex-font-lock-keywords is a user option as well, but since the | 806 ;; bibtex-font-lock-keywords is a user option as well, but since the |
772 ;; patterns used to define this variable are defined in a later | 807 ;; patterns used to define this variable are defined in a later |
773 ;; section of this file, it is defined later. | 808 ;; section of this file, it is defined later. |
774 | 809 |
799 (define-key km "\C-c\"" 'bibtex-remove-delimiters) | 834 (define-key km "\C-c\"" 'bibtex-remove-delimiters) |
800 (define-key km "\C-c{" 'bibtex-remove-delimiters) | 835 (define-key km "\C-c{" 'bibtex-remove-delimiters) |
801 (define-key km "\C-c}" 'bibtex-remove-delimiters) | 836 (define-key km "\C-c}" 'bibtex-remove-delimiters) |
802 (define-key km "\C-c\C-c" 'bibtex-clean-entry) | 837 (define-key km "\C-c\C-c" 'bibtex-clean-entry) |
803 (define-key km "\C-c\C-q" 'bibtex-fill-entry) | 838 (define-key km "\C-c\C-q" 'bibtex-fill-entry) |
839 (define-key km "\C-c\C-s" 'bibtex-find-entry) | |
804 (define-key km "\C-c?" 'bibtex-print-help-message) | 840 (define-key km "\C-c?" 'bibtex-print-help-message) |
805 (define-key km "\C-c\C-p" 'bibtex-pop-previous) | 841 (define-key km "\C-c\C-p" 'bibtex-pop-previous) |
806 (define-key km "\C-c\C-n" 'bibtex-pop-next) | 842 (define-key km "\C-c\C-n" 'bibtex-pop-next) |
807 (define-key km "\C-c\C-k" 'bibtex-kill-field) | 843 (define-key km "\C-c\C-k" 'bibtex-kill-field) |
808 (define-key km "\C-c\M-k" 'bibtex-copy-field-as-kill) | 844 (define-key km "\C-c\M-k" 'bibtex-copy-field-as-kill) |
819 (define-key km "\C-\M-l" 'bibtex-reposition-window) | 855 (define-key km "\C-\M-l" 'bibtex-reposition-window) |
820 (define-key km "\C-\M-h" 'bibtex-mark-entry) | 856 (define-key km "\C-\M-h" 'bibtex-mark-entry) |
821 (define-key km "\C-c\C-b" 'bibtex-entry) | 857 (define-key km "\C-c\C-b" 'bibtex-entry) |
822 (define-key km "\C-c\C-rn" 'bibtex-narrow-to-entry) | 858 (define-key km "\C-c\C-rn" 'bibtex-narrow-to-entry) |
823 (define-key km "\C-c\C-rw" 'widen) | 859 (define-key km "\C-c\C-rw" 'widen) |
860 (define-key km "\C-c\C-l" 'bibtex-url) | |
824 (define-key km "\C-c\C-o" 'bibtex-remove-OPT-or-ALT) | 861 (define-key km "\C-c\C-o" 'bibtex-remove-OPT-or-ALT) |
825 (define-key km "\C-c\C-e\C-i" 'bibtex-InProceedings) | 862 (define-key km "\C-c\C-e\C-i" 'bibtex-InProceedings) |
826 (define-key km "\C-c\C-ei" 'bibtex-InCollection) | 863 (define-key km "\C-c\C-ei" 'bibtex-InCollection) |
827 (define-key km "\C-c\C-eI" 'bibtex-InBook) | 864 (define-key km "\C-c\C-eI" 'bibtex-InBook) |
828 (define-key km "\C-c\C-e\C-a" 'bibtex-Article) | 865 (define-key km "\C-c\C-e\C-a" 'bibtex-Article) |
852 ["Beginning of Entry" bibtex-beginning-of-entry t] | 889 ["Beginning of Entry" bibtex-beginning-of-entry t] |
853 ["End of Entry" bibtex-end-of-entry t]) | 890 ["End of Entry" bibtex-end-of-entry t]) |
854 ("Moving in BibTeX Buffer" | 891 ("Moving in BibTeX Buffer" |
855 ["Find Entry" bibtex-find-entry t] | 892 ["Find Entry" bibtex-find-entry t] |
856 ["Find Crossref Entry" bibtex-find-crossref t]) | 893 ["Find Crossref Entry" bibtex-find-crossref t]) |
857 ("Operating on Current Entry" | |
858 ["Fill Entry" bibtex-fill-entry t] | |
859 ["Clean Entry" bibtex-clean-entry t] | |
860 "--" | 894 "--" |
861 ["Kill Entry" bibtex-kill-entry t] | |
862 ["Copy Entry to Kill Ring" bibtex-copy-entry-as-kill t] | |
863 ["Paste Most Recently Killed Entry" bibtex-yank t] | |
864 ["Paste Previously Killed Entry" bibtex-yank-pop t] | |
865 "--" | |
866 ["Ispell Entry" bibtex-ispell-entry t] | |
867 ["Ispell Entry Abstract" bibtex-ispell-abstract t] | |
868 ["Narrow to Entry" bibtex-narrow-to-entry t] | |
869 "--" | |
870 ["View Cite Locations (RefTeX)" reftex-view-crossref-from-bibtex | |
871 (fboundp 'reftex-view-crossref-from-bibtex)]) | |
872 ("Operating on Current Field" | 895 ("Operating on Current Field" |
873 ["Fill Field" fill-paragraph t] | 896 ["Fill Field" fill-paragraph t] |
874 ["Remove Delimiters" bibtex-remove-delimiters t] | 897 ["Remove Delimiters" bibtex-remove-delimiters t] |
875 ["Remove OPT or ALT Prefix" bibtex-remove-OPT-or-ALT t] | 898 ["Remove OPT or ALT Prefix" bibtex-remove-OPT-or-ALT t] |
876 ["Clear Field" bibtex-empty-field t] | 899 ["Clear Field" bibtex-empty-field t] |
886 ["Snatch from Similar Preceding Field" bibtex-pop-previous t] | 909 ["Snatch from Similar Preceding Field" bibtex-pop-previous t] |
887 "--" | 910 "--" |
888 ["String or Key Complete" bibtex-complete t] | 911 ["String or Key Complete" bibtex-complete t] |
889 "--" | 912 "--" |
890 ["Help about Current Field" bibtex-print-help-message t]) | 913 ["Help about Current Field" bibtex-print-help-message t]) |
914 ("Operating on Current Entry" | |
915 ["Fill Entry" bibtex-fill-entry t] | |
916 ["Clean Entry" bibtex-clean-entry t] | |
917 ["Update Entry" bibtex-entry-update t] | |
918 "--" | |
919 ["Kill Entry" bibtex-kill-entry t] | |
920 ["Copy Entry to Kill Ring" bibtex-copy-entry-as-kill t] | |
921 ["Paste Most Recently Killed Entry" bibtex-yank t] | |
922 ["Paste Previously Killed Entry" bibtex-yank-pop t] | |
923 "--" | |
924 ["Ispell Entry" bibtex-ispell-entry t] | |
925 ["Ispell Entry Abstract" bibtex-ispell-abstract t] | |
926 ["Narrow to Entry" bibtex-narrow-to-entry t] | |
927 "--" | |
928 ["View Cite Locations (RefTeX)" reftex-view-crossref-from-bibtex | |
929 (fboundp 'reftex-view-crossref-from-bibtex)]) | |
891 ("Operating on Buffer or Region" | 930 ("Operating on Buffer or Region" |
892 ["Validate Entries" bibtex-validate t] | 931 ["Validate Entries" bibtex-validate t] |
893 ["Sort Entries" bibtex-sort-buffer t] | 932 ["Sort Entries" bibtex-sort-buffer t] |
894 ["Reformat Entries" bibtex-reformat t] | 933 ["Reformat Entries" bibtex-reformat t] |
895 ["Count Entries" bibtex-count-entries t]) | 934 ["Count Entries" bibtex-count-entries t] |
896 ("Miscellaneous" | 935 "--" |
897 ["Convert Alien Buffer" bibtex-convert-alien t]))) | 936 ["Convert Alien Buffer" bibtex-convert-alien t]))) |
898 | 937 |
899 (easy-menu-define | 938 (easy-menu-define |
900 bibtex-entry-menu bibtex-mode-map "Entry-Types Menu in BibTeX mode" | 939 bibtex-entry-menu bibtex-mode-map "Entry-Types Menu in BibTeX mode" |
901 (list "Entry-Types" | 940 (list "Entry-Types" |
913 ["Unpublished" bibtex-Unpublished t] | 952 ["Unpublished" bibtex-Unpublished t] |
914 ["Miscellaneous" bibtex-Misc t] | 953 ["Miscellaneous" bibtex-Misc t] |
915 ["String" bibtex-String t] | 954 ["String" bibtex-String t] |
916 ["Preamble" bibtex-Preamble t])) | 955 ["Preamble" bibtex-Preamble t])) |
917 | 956 |
957 (defvar bibtex-url-map | |
958 (let ((km (make-sparse-keymap))) | |
959 (define-key km [(mouse-2)] 'bibtex-url) | |
960 km) | |
961 "Local keymap for clickable URLs.") | |
962 (fset 'bibtex-url-map bibtex-url-map) | |
963 | |
918 | 964 |
919 ;; Internal Variables | 965 ;; Internal Variables |
920 | 966 |
921 (defvar bibtex-pop-previous-search-point nil | 967 (defvar bibtex-pop-previous-search-point nil |
922 "Next point where `bibtex-pop-previous' starts looking for a similar entry.") | 968 "Next point where `bibtex-pop-previous' starts looking for a similar entry.") |
1038 | 1084 |
1039 | 1085 |
1040 (defconst bibtex-empty-field-re "\"\"\\|{}" | 1086 (defconst bibtex-empty-field-re "\"\"\\|{}" |
1041 "Regexp matching an empty field.") | 1087 "Regexp matching an empty field.") |
1042 | 1088 |
1043 (defconst bibtex-quoted-string-re | |
1044 (concat "\"" | |
1045 "\\(" | |
1046 "[^\"\\]" ; anything but quote or backslash | |
1047 "\\|" | |
1048 "\\(" | |
1049 "\\\\\\(.\\|\n\\)" ; any backslash quoted character | |
1050 "\\)" | |
1051 "\\)*" | |
1052 "\"") | |
1053 "Regexp matching a field string enclosed by quotes.") | |
1054 | |
1055 (defconst bibtex-font-lock-syntactic-keywords | 1089 (defconst bibtex-font-lock-syntactic-keywords |
1056 `((,(concat "^[ \t]*\\(" (substring bibtex-comment-start 0 1) "\\)" | 1090 `((,(concat "^[ \t]*\\(" (substring bibtex-comment-start 0 1) "\\)" |
1057 (substring bibtex-comment-start 1) "\\>") | 1091 (substring bibtex-comment-start 1) "\\>") |
1058 1 '(11)))) | 1092 1 '(11)))) |
1059 | 1093 |
1060 (defvar bibtex-font-lock-keywords | 1094 (defvar bibtex-font-lock-keywords |
1061 (list | 1095 ;; entry type and reference key |
1062 ;; entry type and reference key | 1096 `((,bibtex-entry-maybe-empty-head |
1063 (list bibtex-entry-maybe-empty-head | 1097 (,bibtex-type-in-head font-lock-function-name-face) |
1064 (list bibtex-type-in-head 'font-lock-function-name-face) | 1098 (,bibtex-key-in-head font-lock-constant-face nil t)) |
1065 (list bibtex-key-in-head 'font-lock-constant-face nil t)) | 1099 ;; optional field names (treated as comments) |
1066 ;; optional field names (treated as comments) | 1100 (,(concat "^[ \t]*\\(OPT" bibtex-field-name "\\)[ \t]*=") |
1067 (list | 1101 1 font-lock-comment-face) |
1068 (concat "^[ \t]*\\(OPT" bibtex-field-name "\\)[ \t]*=") | 1102 ;; field names |
1069 1 'font-lock-comment-face) | 1103 (,(concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=") |
1070 ;; field names | 1104 1 font-lock-variable-name-face) |
1071 (list (concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=") | 1105 ;; url |
1072 1 'font-lock-variable-name-face)) | 1106 (bibtex-font-lock-url 0 '(face nil mouse-face highlight |
1107 keymap bibtex-url-map))) | |
1073 "*Default expressions to highlight in BibTeX mode.") | 1108 "*Default expressions to highlight in BibTeX mode.") |
1109 | |
1110 (defvar bibtex-font-lock-url-regexp | |
1111 (concat "\\<" (regexp-opt (mapcar 'caar bibtex-generate-url-list) t) | |
1112 "\\>[ \t]*=[ \t]*") | |
1113 "Regexp for `bibtex-font-lock-url'.") | |
1074 | 1114 |
1075 (defvar bibtex-field-name-for-parsing nil | 1115 (defvar bibtex-field-name-for-parsing nil |
1076 "Temporary variable storing the name string to be parsed by the callback | 1116 "Temporary variable storing the name string to be parsed by the callback |
1077 function `bibtex-parse-field-name'.") | 1117 function `bibtex-parse-field-name'.") |
1078 | 1118 |
1087 `bibtex-maintain-sorted-entries' is `entry-class'.") | 1127 `bibtex-maintain-sorted-entries' is `entry-class'.") |
1088 | 1128 |
1089 | 1129 |
1090 ;; Special support taking care of variants | 1130 ;; Special support taking care of variants |
1091 (defvar zmacs-regions) | 1131 (defvar zmacs-regions) |
1092 (if (boundp 'mark-active) | 1132 (defalias 'bibtex-mark-active |
1093 (defun bibtex-mark-active () | 1133 (if (boundp 'mark-active) |
1094 ;; In Emacs mark-active indicates if mark is active. | 1134 ;; In Emacs mark-active indicates if mark is active. |
1095 mark-active) | 1135 (lambda () mark-active) |
1096 (defun bibtex-mark-active () | |
1097 ;; In XEmacs (mark) returns nil when not active. | 1136 ;; In XEmacs (mark) returns nil when not active. |
1098 (if zmacs-regions (mark) (mark t)))) | 1137 (lambda () (if zmacs-regions (mark) (mark t))))) |
1099 | 1138 |
1100 (if (fboundp 'run-with-idle-timer) | 1139 (defalias 'bibtex-run-with-idle-timer |
1101 ;; timer.el is distributed with Emacs | 1140 (if (fboundp 'run-with-idle-timer) |
1102 (fset 'bibtex-run-with-idle-timer 'run-with-idle-timer) | 1141 ;; timer.el is distributed with Emacs |
1103 ;; timer.el is not distributed with XEmacs | 1142 'run-with-idle-timer |
1104 ;; Notice that this does not (yet) pass the arguments, but they | 1143 ;; timer.el is not distributed with XEmacs |
1105 ;; are not used (yet) in bibtex.el. Fix if needed. | 1144 ;; Notice that this does not (yet) pass the arguments, but they |
1106 (defun bibtex-run-with-idle-timer (secs repeat function &rest args) | 1145 ;; are not used (yet) in bibtex.el. Fix if needed. |
1107 (start-itimer "bibtex" function secs (if repeat secs nil) t))) | 1146 (lambda (secs repeat function &rest args) |
1147 (start-itimer "bibtex" function secs (if repeat secs nil) t)))) | |
1108 | 1148 |
1109 | 1149 |
1110 ;; Support for hideshow minor mode | 1150 ;; Support for hideshow minor mode |
1111 (defun bibtex-hs-forward-sexp (arg) | 1151 (defun bibtex-hs-forward-sexp (arg) |
1112 "Replacement for `forward-sexp' to be used by `hs-minor-mode'." | 1152 "Replacement for `forward-sexp' to be used by `hs-minor-mode'." |
1213 (cond ((looking-at bibtex-field-const) | 1253 (cond ((looking-at bibtex-field-const) |
1214 (goto-char (match-end 0))) | 1254 (goto-char (match-end 0))) |
1215 ((setq boundaries (bibtex-parse-field-string)) | 1255 ((setq boundaries (bibtex-parse-field-string)) |
1216 (goto-char (cdr boundaries))) | 1256 (goto-char (cdr boundaries))) |
1217 ((setq failure t))) | 1257 ((setq failure t))) |
1218 (if (not (looking-at "[ \t\n]*#[ \t\n]*")) | 1258 (if (looking-at "[ \t\n]*#[ \t\n]*") |
1219 (setq end-point (point)) | 1259 (goto-char (match-end 0)) |
1220 (goto-char (match-end 0)))) | 1260 (setq end-point (point)))) |
1221 (if (and (not failure) | 1261 (if (and (not failure) |
1222 end-point) | 1262 end-point) |
1223 (cons starting-point end-point)))) | 1263 (cons starting-point end-point)))) |
1224 | 1264 |
1225 (defun bibtex-parse-field (name) | 1265 (defun bibtex-parse-field (name) |
1292 (defsubst bibtex-start-of-text-in-field (bounds) | 1332 (defsubst bibtex-start-of-text-in-field (bounds) |
1293 (cadr bounds)) | 1333 (cadr bounds)) |
1294 (defsubst bibtex-end-of-text-in-field (bounds) | 1334 (defsubst bibtex-end-of-text-in-field (bounds) |
1295 (cddr bounds)) | 1335 (cddr bounds)) |
1296 | 1336 |
1297 (defun bibtex-name-in-field (bounds) | 1337 (defun bibtex-name-in-field (bounds &optional remove-opt-alt) |
1298 "Get content of name in BibTeX field defined via BOUNDS." | 1338 "Get content of name in BibTeX field defined via BOUNDS. |
1299 (buffer-substring-no-properties (nth 1 (car bounds)) | 1339 If optional arg REMOVE-OPT-ALT is non-nil remove \"OPT\" and \"ALT\"." |
1300 (nth 2 (car bounds)))) | 1340 (let ((name (buffer-substring-no-properties (nth 1 (car bounds)) |
1341 (nth 2 (car bounds))))) | |
1342 (if (and remove-opt-alt | |
1343 (string-match "\\`\\(OPT\\|ALT\\)" name)) | |
1344 (substring name 3) | |
1345 name))) | |
1301 | 1346 |
1302 (defun bibtex-text-in-field-bounds (bounds &optional remove-delim) | 1347 (defun bibtex-text-in-field-bounds (bounds &optional remove-delim) |
1303 "Get content of text in BibTeX field defined via BOUNDS. | 1348 "Get content of text in BibTeX field defined via BOUNDS. |
1304 If optional arg REMOVE-DELIM is non-nil remove enclosing field delimiters | 1349 If optional arg REMOVE-DELIM is non-nil remove enclosing field delimiters |
1305 if present." | 1350 if present." |
1436 (match-end bibtex-key-in-head)) | 1481 (match-end bibtex-key-in-head)) |
1437 empty)) | 1482 empty)) |
1438 | 1483 |
1439 ;; Helper Functions | 1484 ;; Helper Functions |
1440 | 1485 |
1486 (defsubst bibtex-string= (str1 str2) | |
1487 "Return t if two strings are equal, ignoring case." | |
1488 (eq t (compare-strings str1 0 nil str2 0 nil t))) | |
1489 | |
1441 (defun bibtex-delete-whitespace () | 1490 (defun bibtex-delete-whitespace () |
1442 "Delete all whitespace starting at point." | 1491 "Delete all whitespace starting at point." |
1443 (if (looking-at "[ \t\n]+") | 1492 (if (looking-at "[ \t\n]+") |
1444 (delete-region (point) (match-end 0)))) | 1493 (delete-region (point) (match-end 0)))) |
1445 | 1494 |
1446 (defun bibtex-current-line () | 1495 (defun bibtex-current-line () |
1447 "Compute line number of point regardless whether the buffer is narrowed." | 1496 "Compute line number of point regardless whether the buffer is narrowed." |
1448 (+ (count-lines 1 (point)) | 1497 (+ (count-lines 1 (point)) |
1449 (if (equal (current-column) 0) 1 0))) | 1498 (if (equal (current-column) 0) 1 0))) |
1450 | |
1451 (defun bibtex-member-of-regexp (string list) | |
1452 "Return non-nil if STRING is exactly matched by an element of LIST. | |
1453 The value is actually the tail of LIST whose car matches STRING." | |
1454 (let (case-fold-search) | |
1455 (while (and list | |
1456 (not (string-match (concat "\\`\\(?:" (car list) "\\)\\'") string))) | |
1457 (setq list (cdr list))) | |
1458 list)) | |
1459 | 1499 |
1460 (defun bibtex-skip-to-valid-entry (&optional backward) | 1500 (defun bibtex-skip-to-valid-entry (&optional backward) |
1461 "Unless at beginning of a valid BibTeX entry, move point to beginning of the | 1501 "Unless at beginning of a valid BibTeX entry, move point to beginning of the |
1462 next valid one. With optional argument BACKWARD non-nil, move backward to | 1502 next valid one. With optional argument BACKWARD non-nil, move backward to |
1463 beginning of previous valid one. A valid entry is a syntactical correct one | 1503 beginning of previous valid one. A valid entry is a syntactical correct one |
1499 (key (bibtex-key-in-head "")) | 1539 (key (bibtex-key-in-head "")) |
1500 (beg (copy-marker (match-beginning 0))) | 1540 (beg (copy-marker (match-beginning 0))) |
1501 (end (copy-marker (save-excursion (bibtex-end-of-entry))))) | 1541 (end (copy-marker (save-excursion (bibtex-end-of-entry))))) |
1502 (save-excursion | 1542 (save-excursion |
1503 (if (or (and (not bibtex-sort-ignore-string-entries) | 1543 (if (or (and (not bibtex-sort-ignore-string-entries) |
1504 (string-equal "string" (downcase entry-type))) | 1544 (bibtex-string= entry-type "string")) |
1505 (assoc-string entry-type bibtex-entry-field-alist t)) | 1545 (assoc-string entry-type bibtex-entry-field-alist t)) |
1506 (funcall fun key beg end))) | 1546 (funcall fun key beg end))) |
1507 (goto-char end))))) | 1547 (goto-char end))))) |
1508 | 1548 |
1509 (defun bibtex-progress-message (&optional flag interval) | 1549 (defun bibtex-progress-message (&optional flag interval) |
1573 (re-search-backward entry-head-re bound noerror)) | 1613 (re-search-backward entry-head-re bound noerror)) |
1574 (setq found (bibtex-search-entry empty-head pnt t))) | 1614 (setq found (bibtex-search-entry empty-head pnt t))) |
1575 (if found | 1615 (if found |
1576 (progn (goto-char (match-beginning 0)) | 1616 (progn (goto-char (match-beginning 0)) |
1577 found) | 1617 found) |
1578 (cond ((equal noerror nil) | 1618 (cond ((not noerror) |
1579 ;; yell | 1619 ;; yell |
1580 (error "Backward search of BibTeX entry failed")) | 1620 (error "Backward search of BibTeX entry failed")) |
1581 ((equal noerror t) | 1621 ((equal noerror t) |
1582 ;; don't move | 1622 ;; don't move |
1583 (goto-char pnt))) | 1623 (goto-char pnt))) |
1682 (if (or (= (preceding-char) ?}) | 1722 (if (or (= (preceding-char) ?}) |
1683 (= (preceding-char) ?\")) | 1723 (= (preceding-char) ?\")) |
1684 (forward-char -1))) | 1724 (forward-char -1))) |
1685 | 1725 |
1686 (defun bibtex-enclosing-field (&optional noerr) | 1726 (defun bibtex-enclosing-field (&optional noerr) |
1687 "Search for BibTeX field enclosing point. Point moves to end of field. | 1727 "Search for BibTeX field enclosing point. |
1688 Use `match-beginning' and `match-end' to parse the field. If NOERR is non-nil, | 1728 Use `match-beginning' and `match-end' to parse the field. If NOERR is non-nil, |
1689 no error is signalled. In this case, bounds are returned on success, | 1729 no error is signalled. In this case, bounds are returned on success, |
1690 nil otherwise." | 1730 nil otherwise. Does not move point." |
1691 (let ((bounds (bibtex-search-backward-field bibtex-field-name t))) | 1731 (let ((bounds (bibtex-search-backward-field bibtex-field-name t))) |
1692 (if (and bounds | 1732 (if (and bounds |
1693 (<= (bibtex-start-of-field bounds) (point)) | 1733 (<= (bibtex-start-of-field bounds) (point)) |
1694 (>= (bibtex-end-of-field bounds) (point))) | 1734 (>= (bibtex-end-of-field bounds) (point))) |
1695 bounds | 1735 bounds |
1730 (forward-char))) | 1770 (forward-char))) |
1731 (set-mark (point)) | 1771 (set-mark (point)) |
1732 (message "Mark set") | 1772 (message "Mark set") |
1733 (bibtex-make-field (list (elt current 1) nil (elt current 2)) t)) | 1773 (bibtex-make-field (list (elt current 1) nil (elt current 2)) t)) |
1734 ((equal bibtex-last-kill-command 'entry) | 1774 ((equal bibtex-last-kill-command 'entry) |
1735 (if (not (eobp)) | 1775 (unless (eobp) (bibtex-beginning-of-entry)) |
1736 (bibtex-beginning-of-entry)) | |
1737 (set-mark (point)) | 1776 (set-mark (point)) |
1738 (message "Mark set") | 1777 (message "Mark set") |
1739 (insert (elt current 1))) | 1778 (insert (elt current 1))) |
1740 (t | 1779 (t |
1741 (error "Unknown tag field: %s. Please submit a bug report" | 1780 (error "Unknown tag field: %s. Please submit a bug report" |
1742 bibtex-last-kill-command)))))) | 1781 bibtex-last-kill-command)))))) |
1743 | |
1744 (defun bibtex-assoc-regexp (regexp alist) | |
1745 "Return non-nil if REGEXP matches the car of an element of ALIST. | |
1746 The value is actually the element of ALIST matched by REGEXP. | |
1747 Case is ignored if `case-fold-search' is non-nil in the current buffer." | |
1748 (while (and alist | |
1749 (not (string-match regexp (caar alist)))) | |
1750 (setq alist (cdr alist))) | |
1751 (car alist)) | |
1752 | 1782 |
1753 (defun bibtex-format-entry () | 1783 (defun bibtex-format-entry () |
1754 "Helper function for `bibtex-clean-entry'. | 1784 "Helper function for `bibtex-clean-entry'. |
1755 Formats current entry according to variable `bibtex-entry-format'." | 1785 Formats current entry according to variable `bibtex-entry-format'." |
1756 (save-excursion | 1786 (save-excursion |
1762 numerical-fields | 1792 numerical-fields |
1763 last-comma page-dashes delimiters | 1793 last-comma page-dashes delimiters |
1764 unify-case inherit-booktitle) | 1794 unify-case inherit-booktitle) |
1765 bibtex-entry-format)) | 1795 bibtex-entry-format)) |
1766 crossref-key bounds alternatives-there non-empty-alternative | 1796 crossref-key bounds alternatives-there non-empty-alternative |
1767 entry-list req-field-list field-done field-list) | 1797 entry-list req-field-list field-list) |
1768 | 1798 |
1769 ;; identify entry type | 1799 ;; identify entry type |
1770 (goto-char (point-min)) | 1800 (goto-char (point-min)) |
1771 (re-search-forward bibtex-entry-type) | 1801 (re-search-forward bibtex-entry-type) |
1772 (let ((beg-type (1+ (match-beginning 0))) | 1802 (let ((beg-type (1+ (match-beginning 0))) |
1790 | 1820 |
1791 ;; determine if entry has crossref field and if at least | 1821 ;; determine if entry has crossref field and if at least |
1792 ;; one alternative is non-empty | 1822 ;; one alternative is non-empty |
1793 (goto-char (point-min)) | 1823 (goto-char (point-min)) |
1794 (let* ((fields-alist (bibtex-parse-entry)) | 1824 (let* ((fields-alist (bibtex-parse-entry)) |
1795 (case-fold-search t) | 1825 (field (assoc-string "crossref" fields-alist t))) |
1796 (field (bibtex-assoc-regexp "\\`\\(OPT\\)?crossref\\'" | |
1797 fields-alist))) | |
1798 (setq crossref-key (and field | 1826 (setq crossref-key (and field |
1799 (not (string-match bibtex-empty-field-re | 1827 (not (string-match bibtex-empty-field-re |
1800 (cdr field))) | 1828 (cdr field))) |
1801 (cdr field)) | 1829 (cdr field)) |
1802 req-field-list (if crossref-key | 1830 req-field-list (if crossref-key |
1804 (nth 0 (nth 1 entry-list)))) ; required part | 1832 (nth 0 (nth 1 entry-list)))) ; required part |
1805 | 1833 |
1806 (dolist (rfield req-field-list) | 1834 (dolist (rfield req-field-list) |
1807 (when (nth 3 rfield) ; we should have an alternative | 1835 (when (nth 3 rfield) ; we should have an alternative |
1808 (setq alternatives-there t | 1836 (setq alternatives-there t |
1809 field (bibtex-assoc-regexp | 1837 field (assoc-string (car rfield) fields-alist t)) |
1810 (concat "\\`\\(ALT\\)?" (car rfield) "\\'") | |
1811 fields-alist)) | |
1812 (if (and field | 1838 (if (and field |
1813 (not (string-match bibtex-empty-field-re | 1839 (not (string-match bibtex-empty-field-re |
1814 (cdr field)))) | 1840 (cdr field)))) |
1815 (cond ((not non-empty-alternative) | 1841 (cond ((not non-empty-alternative) |
1816 (setq non-empty-alternative t)) | 1842 (setq non-empty-alternative t)) |
1885 (delete-char 1) | 1911 (delete-char 1) |
1886 (insert (bibtex-field-right-delimiter)))) | 1912 (insert (bibtex-field-right-delimiter)))) |
1887 | 1913 |
1888 ;; update page dashes | 1914 ;; update page dashes |
1889 (if (and (memq 'page-dashes format) | 1915 (if (and (memq 'page-dashes format) |
1890 (string-match "\\`\\(OPT\\)?pages\\'" field-name) | 1916 (bibtex-string= field-name "pages") |
1891 (progn (goto-char beg-text) | 1917 (progn (goto-char beg-text) |
1892 (looking-at | 1918 (looking-at |
1893 "\\([\"{][0-9]+\\)[ \t\n]*--?[ \t\n]*\\([0-9]+[\"}]\\)"))) | 1919 "\\([\"{][0-9]+\\)[ \t\n]*--?[ \t\n]*\\([0-9]+[\"}]\\)"))) |
1894 (replace-match "\\1-\\2")) | 1920 (replace-match "\\1-\\2")) |
1895 | 1921 |
1896 ;; use book title of crossref'd entry | 1922 ;; use book title of crossref'd entry |
1897 (if (and (memq 'inherit-booktitle format) | 1923 (if (and (memq 'inherit-booktitle format) |
1898 empty-field | 1924 empty-field |
1899 (equal (downcase field-name) "booktitle") | 1925 (bibtex-string= field-name "booktitle") |
1900 crossref-key) | 1926 crossref-key) |
1901 (let ((title (save-restriction | 1927 (let ((title (save-restriction |
1902 (widen) | 1928 (widen) |
1903 (if (bibtex-find-entry crossref-key) | 1929 (if (bibtex-find-entry crossref-key) |
1904 (bibtex-text-in-field "title"))))) | 1930 (bibtex-text-in-field "title"))))) |
1907 (goto-char (1+ beg-text)) | 1933 (goto-char (1+ beg-text)) |
1908 (insert title)))) | 1934 (insert title)))) |
1909 | 1935 |
1910 ;; Use booktitle to set a missing title. | 1936 ;; Use booktitle to set a missing title. |
1911 (if (and empty-field | 1937 (if (and empty-field |
1912 (equal (downcase field-name) "title")) | 1938 (bibtex-string= field-name "title")) |
1913 (let ((booktitle (bibtex-text-in-field "booktitle"))) | 1939 (let ((booktitle (bibtex-text-in-field "booktitle"))) |
1914 (when booktitle | 1940 (when booktitle |
1915 (setq empty-field nil) | 1941 (setq empty-field nil) |
1916 (goto-char (1+ beg-text)) | 1942 (goto-char (1+ beg-text)) |
1917 (insert booktitle)))) | 1943 (insert booktitle)))) |
2021 | 2047 |
2022 (defun bibtex-autokey-get-names () | 2048 (defun bibtex-autokey-get-names () |
2023 "Get contents of the name field of the current entry. | 2049 "Get contents of the name field of the current entry. |
2024 Do some modifications based on `bibtex-autokey-name-change-strings' | 2050 Do some modifications based on `bibtex-autokey-name-change-strings' |
2025 and return results as a list." | 2051 and return results as a list." |
2026 (let ((case-fold-search t)) | 2052 (let ((case-fold-search t) |
2027 (mapcar 'bibtex-autokey-demangle-name | 2053 (names (bibtex-autokey-get-field "author\\|editor" |
2028 (split-string (bibtex-autokey-get-field | 2054 bibtex-autokey-name-change-strings))) |
2029 "author\\|editor" | 2055 ;; Some entries do not have a name field. |
2030 bibtex-autokey-name-change-strings) | 2056 (unless (string= "" names) |
2031 "[ \t\n]+and[ \t\n]+")))) | 2057 (mapcar 'bibtex-autokey-demangle-name |
2058 (split-string names "[ \t\n]+and[ \t\n]+"))))) | |
2032 | 2059 |
2033 (defun bibtex-autokey-demangle-name (fullname) | 2060 (defun bibtex-autokey-demangle-name (fullname) |
2034 "Get the last part from a well-formed name and perform abbreviations." | 2061 "Get the last part from a well-formed name and perform abbreviations." |
2035 (let* (case-fold-search | 2062 (let* (case-fold-search |
2036 (name (cond ((string-match "\\([A-Z][^, ]*\\)[^,]*," fullname) | 2063 (name (cond ((string-match "\\([A-Z][^, ]*\\)[^,]*," fullname) |
2057 (funcall bibtex-autokey-name-case-convert name) | 2084 (funcall bibtex-autokey-name-case-convert name) |
2058 bibtex-autokey-name-length))) | 2085 bibtex-autokey-name-length))) |
2059 | 2086 |
2060 (defun bibtex-autokey-get-title () | 2087 (defun bibtex-autokey-get-title () |
2061 "Get title field contents up to a terminator." | 2088 "Get title field contents up to a terminator." |
2062 (let ((titlestring | 2089 (let ((case-fold-search t) |
2090 (titlestring | |
2063 (bibtex-autokey-get-field "title" | 2091 (bibtex-autokey-get-field "title" |
2064 bibtex-autokey-titleword-change-strings))) | 2092 bibtex-autokey-titleword-change-strings))) |
2065 ;; ignore everything past a terminator | 2093 ;; ignore everything past a terminator |
2066 (let ((case-fold-search t)) | 2094 (dolist (terminator bibtex-autokey-title-terminators) |
2067 (dolist (terminator bibtex-autokey-title-terminators) | 2095 (if (string-match terminator titlestring) |
2068 (if (string-match terminator titlestring) | 2096 (setq titlestring (substring titlestring 0 (match-beginning 0))))) |
2069 (setq titlestring (substring titlestring 0 (match-beginning 0)))))) | |
2070 ;; gather words from titlestring into a list. Ignore | 2097 ;; gather words from titlestring into a list. Ignore |
2071 ;; specific words and use only a specific amount of words. | 2098 ;; specific words and use only a specific amount of words. |
2072 (let ((counter 0) | 2099 (let ((counter 0) |
2073 case-fold-search titlewords titlewords-extra titleword end-match) | 2100 titlewords titlewords-extra titleword end-match) |
2074 (while (and (or (not (numberp bibtex-autokey-titlewords)) | 2101 (while (and (or (not (numberp bibtex-autokey-titlewords)) |
2075 (< counter (+ bibtex-autokey-titlewords | 2102 (< counter (+ bibtex-autokey-titlewords |
2076 bibtex-autokey-titlewords-stretch))) | 2103 bibtex-autokey-titlewords-stretch))) |
2077 (string-match "\\b\\w+" titlestring)) | 2104 (string-match "\\b\\w+" titlestring)) |
2078 (setq end-match (match-end 0) | 2105 (setq end-match (match-end 0) |
2079 titleword (substring titlestring | 2106 titleword (substring titlestring |
2080 (match-beginning 0) end-match)) | 2107 (match-beginning 0) end-match)) |
2081 (unless (bibtex-member-of-regexp titleword | 2108 (unless (let ((lst bibtex-autokey-titleword-ignore)) |
2082 bibtex-autokey-titleword-ignore) | 2109 (while (and lst |
2110 (not (string-match (concat "\\`\\(?:" (car lst) | |
2111 "\\)\\'") titleword))) | |
2112 (setq lst (cdr lst))) | |
2113 lst) | |
2083 (setq titleword | 2114 (setq titleword |
2084 (funcall bibtex-autokey-titleword-case-convert titleword)) | 2115 (funcall bibtex-autokey-titleword-case-convert titleword)) |
2085 (if (or (not (numberp bibtex-autokey-titlewords)) | 2116 (if (or (not (numberp bibtex-autokey-titlewords)) |
2086 (< counter bibtex-autokey-titlewords)) | 2117 (< counter bibtex-autokey-titlewords)) |
2087 (setq titlewords (append titlewords (list titleword))) | 2118 (setq titlewords (append titlewords (list titleword))) |
2095 | 2126 |
2096 (defun bibtex-autokey-demangle-title (titleword) | 2127 (defun bibtex-autokey-demangle-title (titleword) |
2097 "Do some abbreviations on TITLEWORD. | 2128 "Do some abbreviations on TITLEWORD. |
2098 The rules are defined in `bibtex-autokey-titleword-abbrevs' | 2129 The rules are defined in `bibtex-autokey-titleword-abbrevs' |
2099 and `bibtex-autokey-titleword-length'." | 2130 and `bibtex-autokey-titleword-length'." |
2100 (let ((case-folde-search t) | 2131 (let ((case-fold-search t) |
2101 (alist bibtex-autokey-titleword-abbrevs)) | 2132 (alist bibtex-autokey-titleword-abbrevs)) |
2102 (while (and alist | 2133 (while (and alist |
2103 (not (string-match (concat "\\`\\(?:" (caar alist) "\\)\\'") | 2134 (not (string-match (concat "\\`\\(?:" (caar alist) "\\)\\'") |
2104 titleword))) | 2135 titleword))) |
2105 (setq alist (cdr alist))) | 2136 (setq alist (cdr alist))) |
2306 (listp bibtex-strings)) | 2337 (listp bibtex-strings)) |
2307 bibtex-strings)) | 2338 bibtex-strings)) |
2308 bounds key) | 2339 bounds key) |
2309 (if (listp add) | 2340 (if (listp add) |
2310 (dolist (string add) | 2341 (dolist (string add) |
2311 (unless (assoc (car string) strings) | 2342 (unless (assoc-string (car string) strings t) |
2312 (push string strings)))) | 2343 (push string strings)))) |
2313 (catch 'userkey | 2344 (catch 'userkey |
2314 (while (setq bounds (bibtex-search-forward-string)) | 2345 (while (setq bounds (bibtex-search-forward-string)) |
2315 (if (and abortable | 2346 (if (and abortable |
2316 (input-pending-p)) | 2347 (input-pending-p)) |
2317 ;; user has aborted by typing a key --> return `aborted' | 2348 ;; user has aborted by typing a key --> return `aborted' |
2318 (throw 'userkey 'aborted)) | 2349 (throw 'userkey 'aborted)) |
2319 (setq key (bibtex-reference-key-in-string bounds)) | 2350 (setq key (bibtex-reference-key-in-string bounds)) |
2320 (if (not (assoc key strings)) | 2351 (unless (assoc-string key strings t) |
2321 (push (cons key (bibtex-text-in-string bounds t)) | 2352 (push (cons key (bibtex-text-in-string bounds t)) |
2322 strings)) | 2353 strings)) |
2323 (goto-char (bibtex-end-of-text-in-string bounds))) | 2354 (goto-char (bibtex-end-of-text-in-string bounds))) |
2324 ;; successful operation --> return `bibtex-strings' | 2355 ;; successful operation --> return `bibtex-strings' |
2325 (setq bibtex-strings strings)))))) | 2356 (setq bibtex-strings strings)))))) |
2326 | 2357 |
2327 (defun bibtex-string-files-init () | 2358 (defun bibtex-string-files-init () |
2407 completions))) | 2438 completions))) |
2408 (message "Making completion list...done") | 2439 (message "Making completion list...done") |
2409 ;; return value is handled by choose-completion-string-functions | 2440 ;; return value is handled by choose-completion-string-functions |
2410 nil)))) | 2441 nil)))) |
2411 | 2442 |
2412 (defun bibtex-complete-string-cleanup (str) | 2443 (defun bibtex-complete-string-cleanup (str strings-alist) |
2413 "Cleanup after inserting string STR. | 2444 "Cleanup after inserting string STR. |
2414 Remove enclosing field delimiters for string STR. Display message with | 2445 Remove enclosing field delimiters for string STR. Display message with |
2415 expansion of STR." | 2446 expansion of STR using expansion list STRINGS-ALIST." |
2416 (let ((pair (assoc str bibtex-strings))) | 2447 (let ((pair (if (stringp str) |
2448 (assoc-string str strings-alist t)))) | |
2417 (when pair | 2449 (when pair |
2418 (if (cdr pair) | 2450 (if (cdr pair) |
2419 (message "Abbreviation for `%s'" (cdr pair))) | 2451 (message "Abbreviation for `%s'" (cdr pair))) |
2420 (save-excursion | 2452 (save-excursion |
2421 (bibtex-inside-field) | 2453 (bibtex-inside-field) |
2424 (let ((boundaries (bibtex-parse-field-string))) | 2456 (let ((boundaries (bibtex-parse-field-string))) |
2425 (if (and boundaries | 2457 (if (and boundaries |
2426 (equal (cdr boundaries) | 2458 (equal (cdr boundaries) |
2427 (bibtex-end-of-text-in-field bounds))) | 2459 (bibtex-end-of-text-in-field bounds))) |
2428 (bibtex-remove-delimiters)))))))) | 2460 (bibtex-remove-delimiters)))))))) |
2461 | |
2462 (defun bibtex-complete-key-cleanup (key) | |
2463 "Display message on entry KEY after completion of a crossref key." | |
2464 (save-excursion | |
2465 ;; Don't do anything if we completed the key of an entry. | |
2466 (let ((pnt (bibtex-beginning-of-entry))) | |
2467 (if (and (stringp key) | |
2468 (bibtex-find-entry key) | |
2469 (/= pnt (point))) | |
2470 (let* ((bibtex-autokey-name-case-convert 'identity) | |
2471 (bibtex-autokey-name-length 'infty) | |
2472 (nl (bibtex-autokey-get-names)) | |
2473 (name (concat (nth 0 nl) (if (nth 1 nl) " etal"))) | |
2474 (year (bibtex-autokey-get-field "year")) | |
2475 (bibtex-autokey-titlewords 5) | |
2476 (bibtex-autokey-titlewords-stretch 2) | |
2477 (bibtex-autokey-titleword-case-convert 'identity) | |
2478 (bibtex-autokey-titleword-length 5) | |
2479 (title (mapconcat 'identity | |
2480 (bibtex-autokey-get-title) " ")) | |
2481 (journal (bibtex-autokey-get-field | |
2482 "journal" bibtex-autokey-transcriptions)) | |
2483 (volume (bibtex-autokey-get-field "volume")) | |
2484 (pages (bibtex-autokey-get-field "pages" '(("-.*\\'" . ""))))) | |
2485 (message "Ref:%s" | |
2486 (mapconcat (lambda (arg) | |
2487 (if (not (string= "" (cdr arg))) | |
2488 (concat (car arg) (cdr arg)))) | |
2489 `((" " . ,name) (" " . ,year) | |
2490 (": " . ,title) (", " . ,journal) | |
2491 (" " . ,volume) (":" . ,pages)) | |
2492 ""))))))) | |
2429 | 2493 |
2430 (defun bibtex-choose-completion-string (choice buffer mini-p base-size) | 2494 (defun bibtex-choose-completion-string (choice buffer mini-p base-size) |
2431 ;; Code borrowed from choose-completion-string: | 2495 ;; Code borrowed from choose-completion-string: |
2432 ;; We must duplicate the code from choose-completion-string | 2496 ;; We must duplicate the code from choose-completion-string |
2433 ;; because it runs the hook choose-completion-string-functions | 2497 ;; because it runs the hook choose-completion-string-functions |
2458 (bibtex-inside-field) | 2522 (bibtex-inside-field) |
2459 (let* ((case-fold-search t) | 2523 (let* ((case-fold-search t) |
2460 (bounds (bibtex-enclosing-field)) | 2524 (bounds (bibtex-enclosing-field)) |
2461 (start-old-text (bibtex-start-of-text-in-field bounds)) | 2525 (start-old-text (bibtex-start-of-text-in-field bounds)) |
2462 (stop-old-text (bibtex-end-of-text-in-field bounds)) | 2526 (stop-old-text (bibtex-end-of-text-in-field bounds)) |
2463 (start-name (bibtex-start-of-name-in-field bounds)) | 2527 (field-name (bibtex-name-in-field bounds t))) |
2464 (stop-name (bibtex-end-of-name-in-field bounds)) | |
2465 ;; construct regexp for field with same name as this one, | |
2466 ;; ignoring possible OPT's or ALT's | |
2467 (field-name (progn | |
2468 (goto-char start-name) | |
2469 (buffer-substring-no-properties | |
2470 (if (looking-at "\\(OPT\\)\\|\\(ALT\\)") | |
2471 (match-end 0) | |
2472 (point)) | |
2473 stop-name)))) | |
2474 ;; if executed several times in a row, start each search where | 2528 ;; if executed several times in a row, start each search where |
2475 ;; the last one was finished | 2529 ;; the last one was finished |
2476 (unless (eq last-command 'bibtex-pop) | 2530 (unless (eq last-command 'bibtex-pop) |
2477 (bibtex-enclosing-entry-maybe-empty-head) | 2531 (bibtex-enclosing-entry-maybe-empty-head) |
2478 (setq bibtex-pop-previous-search-point (match-beginning 0) | 2532 (setq bibtex-pop-previous-search-point (match-beginning 0) |
2637 ;; entries should be fontified in the same way as | 2691 ;; entries should be fontified in the same way as |
2638 ;; brace-delimited ones | 2692 ;; brace-delimited ones |
2639 ) | 2693 ) |
2640 nil | 2694 nil |
2641 (font-lock-syntactic-keywords . bibtex-font-lock-syntactic-keywords) | 2695 (font-lock-syntactic-keywords . bibtex-font-lock-syntactic-keywords) |
2696 (font-lock-extra-managed-props . (mouse-face keymap)) | |
2642 (font-lock-mark-block-function | 2697 (font-lock-mark-block-function |
2643 . (lambda () | 2698 . (lambda () |
2644 (set-mark (bibtex-end-of-entry)) | 2699 (set-mark (bibtex-end-of-entry)) |
2645 (bibtex-beginning-of-entry))))) | 2700 (bibtex-beginning-of-entry))))) |
2646 (setq imenu-generic-expression | 2701 (setq imenu-generic-expression |
2647 (list (list nil bibtex-entry-head bibtex-key-in-head))) | 2702 (list (list nil bibtex-entry-head bibtex-key-in-head))) |
2648 (make-local-variable 'choose-completion-string-functions) | 2703 (make-local-variable 'choose-completion-string-functions) |
2649 (setq imenu-case-fold-search t) | 2704 (setq imenu-case-fold-search t) |
2720 ;; For inserting new fields, we use the fact that | 2775 ;; For inserting new fields, we use the fact that |
2721 ;; bibtex-parse-entry moves point to the end of the last field. | 2776 ;; bibtex-parse-entry moves point to the end of the last field. |
2722 (let* ((fields-alist (bibtex-parse-entry)) | 2777 (let* ((fields-alist (bibtex-parse-entry)) |
2723 (field-list (bibtex-field-list | 2778 (field-list (bibtex-field-list |
2724 (substring (cdr (assoc "=type=" fields-alist)) | 2779 (substring (cdr (assoc "=type=" fields-alist)) |
2725 1))) ; don't want @ | 2780 1)))) ; don't want @ |
2726 (case-fold-search t)) | |
2727 (dolist (field (car field-list)) | 2781 (dolist (field (car field-list)) |
2728 (unless (bibtex-assoc-regexp (concat "\\`\\(ALT\\)?" (car field) "\\'") | 2782 (unless (assoc-string (car field) fields-alist t) |
2729 fields-alist) | |
2730 (bibtex-make-field field))) | 2783 (bibtex-make-field field))) |
2731 (dolist (field (cdr field-list)) | 2784 (dolist (field (cdr field-list)) |
2732 (unless (bibtex-assoc-regexp (concat "\\`\\(OPT\\)?" (car field) "\\'") | 2785 (unless (assoc-string (car field) fields-alist t) |
2733 fields-alist) | |
2734 (bibtex-make-optional-field field)))))) | 2786 (bibtex-make-optional-field field)))))) |
2735 | 2787 |
2736 (defun bibtex-parse-entry () | 2788 (defun bibtex-parse-entry () |
2737 "Parse entry at point, return an alist. | 2789 "Parse entry at point, return an alist. |
2738 The alist elements have the form (FIELD . TEXT), where FIELD can also be | 2790 The alist elements have the form (FIELD . TEXT), where FIELD can also be |
2739 the special strings \"=type=\" and \"=key=\". For the FIELD \"=key=\" | 2791 the special strings \"=type=\" and \"=key=\". For the FIELD \"=key=\" |
2740 TEXT may be nil. Move point to the end of the last field." | 2792 TEXT may be nil. Remove \"OPT\" and \"ALT\" from FIELD. |
2793 Move point to the end of the last field." | |
2741 (let (alist bounds) | 2794 (let (alist bounds) |
2742 (when (looking-at bibtex-entry-maybe-empty-head) | 2795 (when (looking-at bibtex-entry-maybe-empty-head) |
2743 (push (cons "=type=" (match-string bibtex-type-in-head)) alist) | 2796 (push (cons "=type=" (match-string bibtex-type-in-head)) alist) |
2744 (push (cons "=key=" (match-string bibtex-key-in-head)) alist) | 2797 (push (cons "=key=" (match-string bibtex-key-in-head)) alist) |
2745 (goto-char (match-end 0)) | 2798 (goto-char (match-end 0)) |
2746 (while (setq bounds (bibtex-parse-field bibtex-field-name)) | 2799 (while (setq bounds (bibtex-parse-field bibtex-field-name)) |
2747 (push (cons (bibtex-name-in-field bounds) | 2800 (push (cons (bibtex-name-in-field bounds t) |
2748 (bibtex-text-in-field-bounds bounds)) | 2801 (bibtex-text-in-field-bounds bounds)) |
2749 alist) | 2802 alist) |
2750 (goto-char (bibtex-end-of-field bounds)))) | 2803 (goto-char (bibtex-end-of-field bounds)))) |
2751 alist)) | 2804 alist)) |
2752 | 2805 |
2768 (save-excursion | 2821 (save-excursion |
2769 (goto-char (1- (match-beginning 0))) | 2822 (goto-char (1- (match-beginning 0))) |
2770 (bibtex-beginning-of-entry) | 2823 (bibtex-beginning-of-entry) |
2771 (when (and | 2824 (when (and |
2772 (looking-at bibtex-entry-head) | 2825 (looking-at bibtex-entry-head) |
2773 (equal type (match-string bibtex-type-in-head)) | 2826 (bibtex-string= type (match-string bibtex-type-in-head)) |
2774 ;; In case we found ourselves :-( | 2827 ;; In case we found ourselves :-( |
2775 (not (equal key (setq tmp (match-string bibtex-key-in-head))))) | 2828 (not (equal key (setq tmp (match-string bibtex-key-in-head))))) |
2776 (setq other-key tmp) | 2829 (setq other-key tmp) |
2777 (setq other (point)))) | 2830 (setq other (point)))) |
2778 (save-excursion | 2831 (save-excursion |
2779 (bibtex-end-of-entry) | 2832 (bibtex-end-of-entry) |
2780 (bibtex-skip-to-valid-entry) | 2833 (bibtex-skip-to-valid-entry) |
2781 (when (and | 2834 (when (and |
2782 (looking-at bibtex-entry-head) | 2835 (looking-at bibtex-entry-head) |
2783 (equal type (match-string bibtex-type-in-head)) | 2836 (bibtex-string= type (match-string bibtex-type-in-head)) |
2784 ;; In case we found ourselves :-( | 2837 ;; In case we found ourselves :-( |
2785 (not (equal key (setq tmp (match-string bibtex-key-in-head)))) | 2838 (not (equal key (setq tmp (match-string bibtex-key-in-head)))) |
2786 (or (not other-key) | 2839 (or (not other-key) |
2787 ;; Check which is the best match. | 2840 ;; Check which is the best match. |
2788 (< (length (try-completion "" (list key other-key))) | 2841 (< (length (try-completion "" (list key other-key))) |
2792 ;; Then fill the new entry's fields with the chosen other entry. | 2845 ;; Then fill the new entry's fields with the chosen other entry. |
2793 (when other | 2846 (when other |
2794 (setq other (save-excursion (goto-char other) (bibtex-parse-entry))) | 2847 (setq other (save-excursion (goto-char other) (bibtex-parse-entry))) |
2795 (setq key-end (point)) ;In case parse-entry changed the buffer. | 2848 (setq key-end (point)) ;In case parse-entry changed the buffer. |
2796 (while (setq bounds (bibtex-parse-field bibtex-field-name)) | 2849 (while (setq bounds (bibtex-parse-field bibtex-field-name)) |
2797 (goto-char (bibtex-start-of-name-in-field bounds)) | 2850 (let ((text (assoc-string (bibtex-name-in-field bounds t) |
2798 (let* ((name (buffer-substring | 2851 other t))) |
2799 (if (looking-at "ALT\\|OPT") (match-end 0) (point)) | |
2800 (bibtex-end-of-name-in-field bounds))) | |
2801 (text (assoc-string name other t))) | |
2802 (goto-char (bibtex-start-of-text-in-field bounds)) | 2852 (goto-char (bibtex-start-of-text-in-field bounds)) |
2803 (if (not (and (looking-at bibtex-empty-field-re) text)) | 2853 (if (not (and (looking-at bibtex-empty-field-re) text)) |
2804 (goto-char (bibtex-end-of-field bounds)) | 2854 (goto-char (bibtex-end-of-field bounds)) |
2805 (delete-region (point) (bibtex-end-of-text-in-field bounds)) | 2855 (delete-region (point) (bibtex-end-of-text-in-field bounds)) |
2806 (insert (cdr text))))) | 2856 (insert (cdr text))))) |
2819 (defun bibtex-print-help-message () | 2869 (defun bibtex-print-help-message () |
2820 "Print helpful information about current field in current BibTeX entry." | 2870 "Print helpful information about current field in current BibTeX entry." |
2821 (interactive) | 2871 (interactive) |
2822 (save-excursion | 2872 (save-excursion |
2823 (let* ((case-fold-search t) | 2873 (let* ((case-fold-search t) |
2824 (bounds (bibtex-enclosing-field)) | 2874 (field-name (bibtex-name-in-field (bibtex-enclosing-field) t)) |
2825 (mb (bibtex-start-of-name-in-field bounds)) | |
2826 (field-name (buffer-substring-no-properties | |
2827 (if (progn (goto-char mb) | |
2828 (looking-at "OPT\\|ALT")) | |
2829 (match-end 0) mb) | |
2830 (bibtex-end-of-name-in-field bounds))) | |
2831 (field-list (bibtex-field-list (progn (re-search-backward | 2875 (field-list (bibtex-field-list (progn (re-search-backward |
2832 bibtex-entry-maybe-empty-head nil t) | 2876 bibtex-entry-maybe-empty-head nil t) |
2833 (bibtex-type-in-head)))) | 2877 (bibtex-type-in-head)))) |
2834 (comment (assoc-string field-name | 2878 (comment (assoc-string field-name |
2835 (append (car field-list) | 2879 (append (car field-list) |
2866 (insert (car field) " ") | 2910 (insert (car field) " ") |
2867 (if bibtex-align-at-equal-sign | 2911 (if bibtex-align-at-equal-sign |
2868 (indent-to-column (+ bibtex-entry-offset | 2912 (indent-to-column (+ bibtex-entry-offset |
2869 (- bibtex-text-indentation 2)))) | 2913 (- bibtex-text-indentation 2)))) |
2870 (insert "= ") | 2914 (insert "= ") |
2871 (if (not bibtex-align-at-equal-sign) | 2915 (unless bibtex-align-at-equal-sign |
2872 (indent-to-column (+ bibtex-entry-offset | 2916 (indent-to-column (+ bibtex-entry-offset |
2873 bibtex-text-indentation))) | 2917 bibtex-text-indentation))) |
2874 (if (not called-by-yank) (insert (bibtex-field-left-delimiter))) | 2918 (unless called-by-yank (insert (bibtex-field-left-delimiter))) |
2875 (let ((init (nth 2 field))) | 2919 (let ((init (nth 2 field))) |
2876 (cond ((stringp init) | 2920 (cond ((stringp init) |
2877 (insert init)) | 2921 (insert init)) |
2878 ((fboundp init) | 2922 ((fboundp init) |
2879 (insert (funcall init))))) | 2923 (insert (funcall init))))) |
2880 (if (not called-by-yank) (insert (bibtex-field-right-delimiter))) | 2924 (unless called-by-yank (insert (bibtex-field-right-delimiter))) |
2881 (when (interactive-p) | 2925 (when (interactive-p) |
2882 (forward-char -1) | 2926 (forward-char -1) |
2883 (bibtex-print-help-message))) | 2927 (bibtex-print-help-message))) |
2884 | 2928 |
2885 (defun bibtex-beginning-of-entry () | 2929 (defun bibtex-beginning-of-entry () |
3082 (let ((pos (save-excursion (bibtex-find-entry crossref-key)))) | 3126 (let ((pos (save-excursion (bibtex-find-entry crossref-key)))) |
3083 (if (and pos (> (point) pos)) | 3127 (if (and pos (> (point) pos)) |
3084 (error "This entry must not follow the crossrefed entry!")) | 3128 (error "This entry must not follow the crossrefed entry!")) |
3085 (goto-char pos))) | 3129 (goto-char pos))) |
3086 | 3130 |
3087 (defun bibtex-find-entry (key) | 3131 (defun bibtex-find-entry (key &optional start) |
3088 "Move point to the beginning of BibTeX entry named KEY. | 3132 "Move point to the beginning of BibTeX entry named KEY. |
3089 Return position of entry if KEY is found or nil if not found." | 3133 Return position of entry if KEY is found or nil if not found. |
3090 (interactive (list (bibtex-read-key "Find key: "))) | 3134 Optional arg START is buffer position where the search starts. |
3135 If it is nil, start search at beginning of buffer. | |
3136 With prefix arg, the value of START is position of point." | |
3137 (interactive (list (bibtex-read-key "Find key: ") | |
3138 (if current-prefix-arg (point)))) | |
3091 (let* (case-fold-search | 3139 (let* (case-fold-search |
3092 (pnt (save-excursion | 3140 (pnt (save-excursion |
3093 (goto-char (point-min)) | 3141 (goto-char (or start (point-min))) |
3094 (if (re-search-forward (concat "^[ \t]*\\(" | 3142 (if (re-search-forward (concat "^[ \t]*\\(" |
3095 bibtex-entry-type | 3143 bibtex-entry-type |
3096 "\\)[ \t]*[({][ \t\n]*\\(" | 3144 "\\)[ \t]*[({][ \t\n]*\\(" |
3097 (regexp-quote key) | 3145 (regexp-quote key) |
3098 "\\)[ \t\n]*[,=]") | 3146 "\\)[ \t\n]*[,=]") |
3155 (when (or (not actual-index) | 3203 (when (or (not actual-index) |
3156 (bibtex-lessp actual-index index)) | 3204 (bibtex-lessp actual-index index)) |
3157 ;; buffer contains no valid entries or | 3205 ;; buffer contains no valid entries or |
3158 ;; greater than last entry --> append | 3206 ;; greater than last entry --> append |
3159 (bibtex-end-of-entry) | 3207 (bibtex-end-of-entry) |
3160 (if (not (bobp)) | 3208 (unless (bobp) (newline (forward-line 2))) |
3161 (newline (forward-line 2))) | |
3162 (beginning-of-line))))) | 3209 (beginning-of-line))))) |
3163 (unless key-exist t))) | 3210 (unless key-exist t))) |
3164 | 3211 |
3165 (defun bibtex-validate (&optional test-thoroughly) | 3212 (defun bibtex-validate (&optional test-thoroughly) |
3166 "Validate if buffer or region is syntactically correct. | 3213 "Validate if buffer or region is syntactically correct. |
3231 | 3278 |
3232 (when test-thoroughly | 3279 (when test-thoroughly |
3233 (goto-char (point-min)) | 3280 (goto-char (point-min)) |
3234 (bibtex-progress-message | 3281 (bibtex-progress-message |
3235 "Checking required fields and month fields") | 3282 "Checking required fields and month fields") |
3236 (let ((bibtex-sort-ignore-string-entries t) | 3283 (let ((bibtex-sort-ignore-string-entries t)) |
3237 (questionable-month | |
3238 (regexp-opt (mapcar 'car bibtex-predefined-month-strings)))) | |
3239 (bibtex-map-entries | 3284 (bibtex-map-entries |
3240 (lambda (key beg end) | 3285 (lambda (key beg end) |
3241 (bibtex-progress-message) | 3286 (bibtex-progress-message) |
3242 (let* ((entry-list (progn | 3287 (let* ((entry-list (progn |
3243 (goto-char beg) | 3288 (goto-char beg) |
3249 crossref-there bounds) | 3294 crossref-there bounds) |
3250 (goto-char beg) | 3295 (goto-char beg) |
3251 (while (setq bounds (bibtex-search-forward-field | 3296 (while (setq bounds (bibtex-search-forward-field |
3252 bibtex-field-name end)) | 3297 bibtex-field-name end)) |
3253 (goto-char (bibtex-start-of-text-in-field bounds)) | 3298 (goto-char (bibtex-start-of-text-in-field bounds)) |
3254 (let ((field-name (downcase (bibtex-name-in-field bounds))) | 3299 (let ((field-name (bibtex-name-in-field bounds))) |
3255 case-fold-search) | 3300 (if (and (bibtex-string= field-name "month") |
3256 (if (and (equal field-name "month") | 3301 (not (assoc-string (bibtex-text-in-field-bounds bounds) |
3257 (not (string-match questionable-month | 3302 bibtex-predefined-month-strings t))) |
3258 (bibtex-text-in-field-bounds bounds)))) | |
3259 (push (list (bibtex-current-line) | 3303 (push (list (bibtex-current-line) |
3260 "Questionable month field") | 3304 "Questionable month field") |
3261 error-list)) | 3305 error-list)) |
3262 (setq req (delete (assoc-string field-name req t) req) | 3306 (setq req (delete (assoc-string field-name req t) req) |
3263 creq (delete (assoc-string field-name creq t) creq)) | 3307 creq (delete (assoc-string field-name creq t) creq)) |
3264 (if (equal field-name "crossref") | 3308 (if (bibtex-string= field-name "crossref") |
3265 (setq crossref-there t)))) | 3309 (setq crossref-there t)))) |
3266 (if crossref-there | 3310 (if crossref-there |
3267 (setq req creq)) | 3311 (setq req creq)) |
3268 (if (or (> (length req) 1) | 3312 (if (or (> (length req) 1) |
3269 (and (= (length req) 1) | 3313 (and (= (length req) 1) |
3303 "") | 3347 "") |
3304 "\n") | 3348 "\n") |
3305 (dolist (err error-list) | 3349 (dolist (err error-list) |
3306 (insert bufnam ":" (number-to-string (elt err 0)) | 3350 (insert bufnam ":" (number-to-string (elt err 0)) |
3307 ": " (elt err 1) "\n")) | 3351 ": " (elt err 1) "\n")) |
3308 (compilation-parse-errors nil nil) | |
3309 (setq compilation-old-error-list compilation-error-list) | |
3310 ;; this is necessary to avoid reparsing of buffer if you | |
3311 ;; switch to compilation buffer and enter `compile-goto-error' | |
3312 (set-buffer-modified-p nil) | 3352 (set-buffer-modified-p nil) |
3313 (toggle-read-only 1) | 3353 (toggle-read-only 1) |
3314 (goto-char (point-min)) | 3354 (goto-char (point-min)) |
3315 (other-window -1) | 3355 (other-window -1) |
3316 ;; return nil | 3356 ;; return nil |
3393 (defun bibtex-remove-delimiters () | 3433 (defun bibtex-remove-delimiters () |
3394 "Remove \"\" or {} around string." | 3434 "Remove \"\" or {} around string." |
3395 (interactive) | 3435 (interactive) |
3396 (save-excursion | 3436 (save-excursion |
3397 (bibtex-inside-field) | 3437 (bibtex-inside-field) |
3398 (let ((bounds (bibtex-enclosing-field))) | 3438 (let* ((bounds (bibtex-enclosing-field)) |
3399 (goto-char (bibtex-start-of-text-in-field bounds)) | 3439 (end (bibtex-end-of-text-in-field bounds)) |
3400 (delete-char 1) | 3440 (start (bibtex-start-of-text-in-field bounds))) |
3401 (goto-char (1- (bibtex-end-of-text-in-field bounds))) | 3441 (if (memq (char-before end) '(?\} ?\")) |
3402 (delete-backward-char 1)))) | 3442 (delete-region (1- end) end)) |
3443 (if (memq (char-after start) '(?\{ ?\")) | |
3444 (delete-region start (1+ start)))))) | |
3403 | 3445 |
3404 (defun bibtex-kill-field (&optional copy-only) | 3446 (defun bibtex-kill-field (&optional copy-only) |
3405 "Kill the entire enclosing BibTeX field. | 3447 "Kill the entire enclosing BibTeX field. |
3406 With prefix arg COPY-ONLY, copy the current field to `bibtex-field-kill-ring', | 3448 With prefix arg COPY-ONLY, copy the current field to `bibtex-field-kill-ring', |
3407 but do not actually kill it." | 3449 but do not actually kill it." |
3453 (unless copy-only | 3495 (unless copy-only |
3454 (delete-region beg end)))) | 3496 (delete-region beg end)))) |
3455 (setq bibtex-last-kill-command 'entry)) | 3497 (setq bibtex-last-kill-command 'entry)) |
3456 | 3498 |
3457 (defun bibtex-copy-entry-as-kill () | 3499 (defun bibtex-copy-entry-as-kill () |
3500 "Copy the entire enclosing BibTeX entry to `bibtex-entry-kill-ring'." | |
3458 (interactive) | 3501 (interactive) |
3459 (bibtex-kill-entry t)) | 3502 (bibtex-kill-entry t)) |
3460 | 3503 |
3461 (defun bibtex-yank (&optional n) | 3504 (defun bibtex-yank (&optional n) |
3462 "Reinsert the last BibTeX item. | 3505 "Reinsert the last BibTeX item. |
3480 If N is negative, this is a more recent kill. | 3523 If N is negative, this is a more recent kill. |
3481 | 3524 |
3482 The sequence of kills wraps around, so that after the oldest one | 3525 The sequence of kills wraps around, so that after the oldest one |
3483 comes the newest one." | 3526 comes the newest one." |
3484 (interactive "*p") | 3527 (interactive "*p") |
3485 (if (not (eq last-command 'bibtex-yank)) | 3528 (unless (eq last-command 'bibtex-yank) |
3486 (error "Previous command was not a BibTeX yank")) | 3529 (error "Previous command was not a BibTeX yank")) |
3487 (setq this-command 'bibtex-yank) | 3530 (setq this-command 'bibtex-yank) |
3488 (let ((inhibit-read-only t)) | 3531 (let ((inhibit-read-only t)) |
3489 (delete-region (point) (mark t)) | 3532 (delete-region (point) (mark t)) |
3490 (bibtex-insert-current-kill n))) | 3533 (bibtex-insert-current-kill n))) |
3491 | 3534 |
3531 (let ((case-fold-search t) | 3574 (let ((case-fold-search t) |
3532 entry-type key) | 3575 entry-type key) |
3533 (bibtex-beginning-of-entry) | 3576 (bibtex-beginning-of-entry) |
3534 (save-excursion | 3577 (save-excursion |
3535 (when (re-search-forward bibtex-entry-maybe-empty-head nil t) | 3578 (when (re-search-forward bibtex-entry-maybe-empty-head nil t) |
3536 (setq entry-type (downcase (bibtex-type-in-head))) | 3579 (setq entry-type (bibtex-type-in-head)) |
3537 (setq key (bibtex-key-in-head)))) | 3580 (setq key (bibtex-key-in-head)))) |
3538 ;; formatting | 3581 ;; formatting |
3539 (cond ((equal entry-type "preamble") | 3582 (cond ((bibtex-string= entry-type "preamble") |
3540 ;; (bibtex-format-preamble) | 3583 ;; (bibtex-format-preamble) |
3541 (error "No clean up of @Preamble entries")) | 3584 (error "No clean up of @Preamble entries")) |
3542 ((equal entry-type "string")) | 3585 ((bibtex-string= entry-type "string")) |
3543 ;; (bibtex-format-string) | 3586 ;; (bibtex-format-string) |
3544 (t (bibtex-format-entry))) | 3587 (t (bibtex-format-entry))) |
3545 ;; set key | 3588 ;; set key |
3546 (when (or new-key (not key)) | 3589 (when (or new-key (not key)) |
3547 (setq key (bibtex-generate-autokey)) | 3590 (setq key (bibtex-generate-autokey)) |
3548 (if bibtex-autokey-edit-before-use | 3591 ;; Sometimes bibtex-generate-autokey returns an empty string |
3592 (if (or bibtex-autokey-edit-before-use (string= "" key)) | |
3549 (setq key (bibtex-read-key "Key to use: " key))) | 3593 (setq key (bibtex-read-key "Key to use: " key))) |
3550 (re-search-forward bibtex-entry-maybe-empty-head) | 3594 (re-search-forward bibtex-entry-maybe-empty-head) |
3551 (if (match-beginning bibtex-key-in-head) | 3595 (if (match-beginning bibtex-key-in-head) |
3552 (delete-region (match-beginning bibtex-key-in-head) | 3596 (delete-region (match-beginning bibtex-key-in-head) |
3553 (match-end bibtex-key-in-head))) | 3597 (match-end bibtex-key-in-head))) |
3561 (goto-char (match-beginning 0))) | 3605 (goto-char (match-beginning 0))) |
3562 (point))) | 3606 (point))) |
3563 (entry (buffer-substring start end)) | 3607 (entry (buffer-substring start end)) |
3564 (index (progn (goto-char start) | 3608 (index (progn (goto-char start) |
3565 (bibtex-entry-index))) | 3609 (bibtex-entry-index))) |
3566 no-error) | 3610 error) |
3567 (if (and bibtex-maintain-sorted-entries | 3611 (if (and bibtex-maintain-sorted-entries |
3568 (not (and bibtex-sort-ignore-string-entries | 3612 (not (and bibtex-sort-ignore-string-entries |
3569 (equal entry-type "string")))) | 3613 (bibtex-string= entry-type "string")))) |
3570 (progn | 3614 (progn |
3571 (delete-region start end) | 3615 (delete-region start end) |
3572 (setq no-error (bibtex-prepare-new-entry index)) | 3616 (setq error (not (bibtex-prepare-new-entry index))) |
3573 (insert entry) | 3617 (insert entry) |
3574 (forward-char -1) | 3618 (forward-char -1) |
3575 (bibtex-beginning-of-entry) ; moves backward | 3619 (bibtex-beginning-of-entry) ; moves backward |
3576 (re-search-forward bibtex-entry-head)) | 3620 (re-search-forward bibtex-entry-head)) |
3577 (setq no-error (bibtex-find-entry (car index)))) | 3621 (bibtex-find-entry key) |
3578 (unless no-error | 3622 (setq error (or (/= (point) start) |
3623 (bibtex-find-entry key end)))) | |
3624 (if error | |
3579 (error "New inserted entry yields duplicate key")))) | 3625 (error "New inserted entry yields duplicate key")))) |
3580 ;; final clean up | 3626 ;; final clean up |
3581 (unless called-by-reformat | 3627 (unless called-by-reformat |
3582 (save-excursion | 3628 (save-excursion |
3583 (save-restriction | 3629 (save-restriction |
3584 (bibtex-narrow-to-entry) | 3630 (bibtex-narrow-to-entry) |
3585 ;; Only update the list of keys if it has been built already. | 3631 ;; Only update the list of keys if it has been built already. |
3586 (cond ((equal entry-type "string") | 3632 (cond ((bibtex-string= entry-type "string") |
3587 (if (listp bibtex-strings) (bibtex-parse-strings t))) | 3633 (if (listp bibtex-strings) (bibtex-parse-strings t))) |
3588 ((listp bibtex-reference-keys) (bibtex-parse-keys t))) | 3634 ((listp bibtex-reference-keys) (bibtex-parse-keys t))) |
3589 (run-hooks 'bibtex-clean-entry-hook)))))) | 3635 (run-hooks 'bibtex-clean-entry-hook)))))) |
3590 | 3636 |
3591 (defun bibtex-fill-field-bounds (bounds justify &optional move) | 3637 (defun bibtex-fill-field-bounds (bounds justify &optional move) |
3750 (message "Buffer is now parsable. Please save it."))) | 3796 (message "Buffer is now parsable. Please save it."))) |
3751 | 3797 |
3752 (defun bibtex-complete () | 3798 (defun bibtex-complete () |
3753 "Complete word fragment before point according to context. | 3799 "Complete word fragment before point according to context. |
3754 If point is inside key or crossref field perform key completion based on | 3800 If point is inside key or crossref field perform key completion based on |
3755 `bibtex-reference-keys'. Inside any other field perform string | 3801 `bibtex-reference-keys'. Inside a month field perform key completion |
3756 completion based on `bibtex-strings'. An error is signaled if point | 3802 based on `bibtex-predefined-month-strings'. Inside any other field |
3757 is outside key or BibTeX field." | 3803 perform string completion based on `bibtex-strings'. An error is |
3804 signaled if point is outside key or BibTeX field." | |
3758 (interactive) | 3805 (interactive) |
3759 (let* ((pnt (point)) | 3806 (let ((pnt (point)) |
3760 (case-fold-search t) | 3807 (case-fold-search t) |
3761 bounds compl) | 3808 bounds name compl) |
3762 (save-excursion | 3809 (save-excursion |
3763 (if (and (setq bounds (bibtex-enclosing-field t)) | 3810 (if (and (setq bounds (bibtex-enclosing-field t)) |
3764 (>= pnt (bibtex-start-of-text-in-field bounds)) | 3811 (>= pnt (bibtex-start-of-text-in-field bounds)) |
3765 (<= pnt (bibtex-end-of-text-in-field bounds))) | 3812 (<= pnt (bibtex-end-of-text-in-field bounds))) |
3766 (progn | 3813 (setq name (bibtex-name-in-field bounds t) |
3767 (goto-char (bibtex-start-of-name-in-field bounds)) | 3814 compl (cond ((bibtex-string= name "crossref") |
3768 (setq compl (if (string= "crossref" | 3815 'key) |
3769 (downcase | 3816 ((bibtex-string= name "month") |
3770 (buffer-substring-no-properties | 3817 bibtex-predefined-month-strings) |
3771 (if (looking-at "\\(OPT\\)\\|\\(ALT\\)") | 3818 (t (if (listp bibtex-strings) |
3772 (match-end 0) | 3819 bibtex-strings |
3773 (point)) | 3820 ;; so that bibtex-complete-string-cleanup |
3774 (bibtex-end-of-name-in-field bounds)))) | 3821 ;; can do its job |
3775 'key | 3822 (bibtex-parse-strings |
3776 'str))) | 3823 (bibtex-string-files-init)))))) |
3777 (bibtex-beginning-of-entry) | 3824 (bibtex-beginning-of-entry) |
3778 (if (and (re-search-forward bibtex-entry-maybe-empty-head nil t) | 3825 (if (and (re-search-forward bibtex-entry-maybe-empty-head nil t) |
3779 ;; point is inside a key | 3826 ;; point is inside a key |
3780 (or (and (match-beginning bibtex-key-in-head) | 3827 (or (and (match-beginning bibtex-key-in-head) |
3781 (>= pnt (match-beginning bibtex-key-in-head)) | 3828 (>= pnt (match-beginning bibtex-key-in-head)) |
3787 | 3834 |
3788 (cond ((equal compl 'key) | 3835 (cond ((equal compl 'key) |
3789 ;; key completion | 3836 ;; key completion |
3790 (setq choose-completion-string-functions | 3837 (setq choose-completion-string-functions |
3791 (lambda (choice buffer mini-p base-size) | 3838 (lambda (choice buffer mini-p base-size) |
3792 (bibtex-choose-completion-string choice buffer mini-p base-size) | 3839 (bibtex-choose-completion-string choice buffer mini-p base-size) |
3793 (if bibtex-complete-key-cleanup | 3840 (bibtex-complete-key-cleanup choice) |
3794 (funcall bibtex-complete-key-cleanup choice)) | |
3795 ;; return t (required by choose-completion-string-functions) | 3841 ;; return t (required by choose-completion-string-functions) |
3796 t)) | 3842 t)) |
3797 (let ((choice (bibtex-complete-internal bibtex-reference-keys))) | 3843 (bibtex-complete-key-cleanup (bibtex-complete-internal |
3798 (if bibtex-complete-key-cleanup | 3844 bibtex-reference-keys))) |
3799 (funcall bibtex-complete-key-cleanup choice)))) | 3845 |
3800 | 3846 (compl |
3801 ((equal compl 'str) | |
3802 ;; string completion | 3847 ;; string completion |
3803 (setq choose-completion-string-functions | 3848 (setq choose-completion-string-functions |
3804 (lambda (choice buffer mini-p base-size) | 3849 `(lambda (choice buffer mini-p base-size) |
3805 (bibtex-choose-completion-string choice buffer mini-p base-size) | 3850 (bibtex-choose-completion-string choice buffer mini-p base-size) |
3806 (bibtex-complete-string-cleanup choice) | 3851 (bibtex-complete-string-cleanup choice ',compl) |
3807 ;; return t (required by choose-completion-string-functions) | 3852 ;; return t (required by choose-completion-string-functions) |
3808 t)) | 3853 t)) |
3809 (bibtex-complete-string-cleanup (bibtex-complete-internal bibtex-strings))) | 3854 (bibtex-complete-string-cleanup (bibtex-complete-internal compl) |
3855 compl)) | |
3810 | 3856 |
3811 (t (error "Point outside key or BibTeX field"))))) | 3857 (t (error "Point outside key or BibTeX field"))))) |
3812 | 3858 |
3813 (defun bibtex-Article () | 3859 (defun bibtex-Article () |
3814 "Insert a new BibTeX @Article entry; see also `bibtex-entry'." | 3860 "Insert a new BibTeX @Article entry; see also `bibtex-entry'." |
3878 (defun bibtex-String (&optional key) | 3924 (defun bibtex-String (&optional key) |
3879 "Insert a new BibTeX @String entry with key KEY." | 3925 "Insert a new BibTeX @String entry with key KEY." |
3880 (interactive (list (completing-read "String key: " bibtex-strings | 3926 (interactive (list (completing-read "String key: " bibtex-strings |
3881 nil nil nil 'bibtex-key-history))) | 3927 nil nil nil 'bibtex-key-history))) |
3882 (let ((bibtex-maintain-sorted-entries | 3928 (let ((bibtex-maintain-sorted-entries |
3883 (if (not bibtex-sort-ignore-string-entries) | 3929 (unless bibtex-sort-ignore-string-entries |
3884 bibtex-maintain-sorted-entries)) | 3930 bibtex-maintain-sorted-entries)) |
3885 endpos) | 3931 endpos) |
3886 (unless (bibtex-prepare-new-entry (list key nil "String")) | 3932 (unless (bibtex-prepare-new-entry (list key nil "String")) |
3887 (error "Entry with key `%s' already exists" key)) | 3933 (error "Entry with key `%s' already exists" key)) |
3888 (if (zerop (length key)) (setq key nil)) | 3934 (if (zerop (length key)) (setq key nil)) |
3889 (indent-to-column bibtex-entry-offset) | 3935 (indent-to-column bibtex-entry-offset) |
3911 (let ((endpos (point))) | 3957 (let ((endpos (point))) |
3912 (insert (bibtex-entry-right-delimiter) | 3958 (insert (bibtex-entry-right-delimiter) |
3913 "\n") | 3959 "\n") |
3914 (goto-char endpos))) | 3960 (goto-char endpos))) |
3915 | 3961 |
3962 (defun bibtex-url (&optional event) | |
3963 "Browse a URL for the BibTeX entry at position PNT. | |
3964 The URL is generated using the schemes defined in `bibtex-generate-url-list' | |
3965 \(see there\). Then the URL is passed to `browse-url'." | |
3966 (interactive (list last-input-event)) | |
3967 (save-excursion | |
3968 (if event (posn-set-point (event-end event))) | |
3969 (bibtex-beginning-of-entry) | |
3970 (let ((fields-alist (bibtex-parse-entry)) | |
3971 (case-fold-search t) | |
3972 (lst bibtex-generate-url-list) | |
3973 field url scheme) | |
3974 (while (setq scheme (car lst)) | |
3975 (when (and (setq field (assoc-string (caar scheme) fields-alist t)) | |
3976 (or (eq t (cdar scheme)) | |
3977 (string-match (cdar scheme) (cdr field)))) | |
3978 (setq lst nil) | |
3979 (dolist (step (cdr scheme)) | |
3980 (cond ((stringp step) | |
3981 (setq url (concat url step))) | |
3982 ((setq field (assoc-string (car step) fields-alist t)) | |
3983 ;; always remove field delimiters | |
3984 (let* ((text (if (string-match "\\`[{\"]\\(.*\\)[}\"]\\'" | |
3985 (cdr field)) | |
3986 (match-string 1 (cdr field)) | |
3987 (cdr field))) | |
3988 (str (cond ((eq t (nth 1 step)) | |
3989 text) | |
3990 ((and (consp (nth 1 step)) | |
3991 (string-match (car (nth 1 step)) | |
3992 text)) | |
3993 (if (numberp (cdr (nth 1 step))) | |
3994 (match-string (cdr (nth 1 step)) | |
3995 text) | |
3996 (replace-match (cdr (nth 1 step)) | |
3997 nil nil text))) | |
3998 ;; If the scheme is set up correctly, | |
3999 ;; we should never reach this point | |
4000 (t (error "Match failed: %s" text))))) | |
4001 (setq url (concat url (if (fboundp (nth 2 step)) | |
4002 (funcall (nth 2 step) str) | |
4003 str))))) | |
4004 ;; If the scheme is set up correctly, | |
4005 ;; we should never reach this point | |
4006 (t (error "Step failed: %s" step)))) | |
4007 (message "%s" url) | |
4008 (browse-url url)) | |
4009 (setq lst (cdr lst))) | |
4010 (unless url (message "No URL known."))))) | |
4011 | |
4012 (defun bibtex-font-lock-url (bound) | |
4013 "Font-lock for URLs." | |
4014 (let ((case-fold-search t) | |
4015 (bounds (bibtex-enclosing-field t)) | |
4016 (pnt (point)) | |
4017 found url) | |
4018 ;; We use start-of-field as syntax-begin | |
4019 (goto-char (if bounds (bibtex-start-of-field bounds) pnt)) | |
4020 (while (and (not found) | |
4021 (search-forward-regexp bibtex-font-lock-url-regexp bound t) | |
4022 (save-match-data (setq bounds (bibtex-parse-field-text))) | |
4023 (>= bound (car bounds))) | |
4024 (let ((field (match-string-no-properties 1)) | |
4025 (lst bibtex-generate-url-list)) | |
4026 (while (and (not found) | |
4027 (setq url (caar lst))) | |
4028 (when (bibtex-string= field (car url)) | |
4029 (if (eq t (cdr url)) | |
4030 (progn | |
4031 (goto-char (min bound (cdr bounds))) | |
4032 (set-match-data (list (car bounds) (point))) | |
4033 (setq found t)) | |
4034 (goto-char (car bounds)) | |
4035 (setq found (search-forward-regexp (cdr url) | |
4036 (min bound (cdr bounds)) t))) | |
4037 (if (< (match-beginning 0) pnt) | |
4038 (setq found nil))) | |
4039 (setq lst (cdr lst))))) | |
4040 found)) | |
4041 | |
3916 | 4042 |
3917 ;; Make BibTeX a Feature | 4043 ;; Make BibTeX a Feature |
3918 | 4044 |
3919 (provide 'bibtex) | 4045 (provide 'bibtex) |
3920 | 4046 |