diff options
| author | Stefan Monnier | 2004-09-10 21:24:50 +0000 |
|---|---|---|
| committer | Stefan Monnier | 2004-09-10 21:24:50 +0000 |
| commit | d528bff7457eee0a714a17b8f8f68e2cfe4d3314 (patch) | |
| tree | b9fdeea23fa3726ade40a793af3fe24406b98d91 | |
| parent | 0608b1a02e348e79206f52bde026f4e3bb9c5e93 (diff) | |
| download | emacs-d528bff7457eee0a714a17b8f8f68e2cfe4d3314.tar.gz emacs-d528bff7457eee0a714a17b8f8f68e2cfe4d3314.zip | |
(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.
| -rw-r--r-- | etc/NEWS | 2 | ||||
| -rw-r--r-- | lisp/ChangeLog | 50 | ||||
| -rw-r--r-- | lisp/textmodes/bibtex.el | 584 |
3 files changed, 407 insertions, 229 deletions
| @@ -617,6 +617,8 @@ version 4.7 or newer, compiles to Info pages with embedded images. | |||
| 617 | 'sql-sqlite'. | 617 | 'sql-sqlite'. |
| 618 | 618 | ||
| 619 | ** BibTeX mode: | 619 | ** BibTeX mode: |
| 620 | *** The new command bibtex-url browses a URL for the BibTeX entry at | ||
| 621 | point (bound to C-c C-l and mouse-2 on clickable fields). | ||
| 620 | *** The new command bibtex-entry-update (bound to C-c C-u) updates | 622 | *** The new command bibtex-entry-update (bound to C-c C-u) updates |
| 621 | an existing BibTeX entry. | 623 | an existing BibTeX entry. |
| 622 | *** New `bibtex-entry-format' option `required-fields', enabled by default. | 624 | *** New `bibtex-entry-format' option `required-fields', enabled by default. |
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 6d466b5a791..163445567b4 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,53 @@ | |||
| 1 | 2004-09-10 Stefan Monnier <monnier@iro.umontreal.ca> | ||
| 2 | |||
| 3 | * textmodes/bibtex.el (bibtex-mark-active) | ||
| 4 | (bibtex-run-with-idle-timer): Move the `if' inside the defun. | ||
| 5 | |||
| 6 | 2004-09-10 Roland Winkler <Roland.Winkler@physik.uni-erlangen.de> | ||
| 7 | |||
| 8 | * textmodes/bibtex.el (bibtex-autokey-titleword-ignore): Regexp is | ||
| 9 | used in a case insensitive environment. | ||
| 10 | (bibtex-mode-map): Rearrange order of menus. | ||
| 11 | (bibtex-quoted-string-re): Obsolete. | ||
| 12 | (bibtex-complete-key-cleanup): Variable replaced by new function. | ||
| 13 | (bibtex-font-lock-keywords): Use backquotes. | ||
| 14 | (bibtex-font-lock-url-regexp): New internal variable. | ||
| 15 | (bibtex-name-in-field): New optional arg remove-opt-alt to remove | ||
| 16 | "OPT" and "ALT". | ||
| 17 | (bibtex-insert-current-kill, bibtex-make-field) | ||
| 18 | (bibtex-prepare-new-entry, bibtex-yank-pop, bibtex-String): Use unless. | ||
| 19 | (bibtex-parse-field-text): Simplify. | ||
| 20 | (bibtex-string=): New helper function. | ||
| 21 | (bibtex-member-of-regexp): Merge with bibtex-autokey-get-title. | ||
| 22 | (bibtex-map-entries): Use bibtex-string=. | ||
| 23 | (bibtex-search-entry): Use not. | ||
| 24 | (bibtex-enclosing-field): Fix docstring. | ||
| 25 | (bibtex-assoc-regexp): Obsolete. | ||
| 26 | (bibtex-format-entry): Use assoc-string and bibtex-string=. | ||
| 27 | (bibtex-autokey-get-names): Handle empty name field. | ||
| 28 | (bibtex-parse-strings): Use assoc-string and unless. | ||
| 29 | (bibtex-complete-string-cleanup): Expansion list is passed as an arg. | ||
| 30 | Use assoc-string. | ||
| 31 | (bibtex-pop): Simplify. | ||
| 32 | (bibtex-mode): Set font-lock-extra-managed-props. | ||
| 33 | (bibtex-entry-update): Use assoc-string. | ||
| 34 | (bibtex-parse-entry): Remove "OPT" and "ALT" from FIELD. | ||
| 35 | (bibtex-autofill-entry): Use bibtex-string=. | ||
| 36 | (bibtex-print-help-message): Simplify. | ||
| 37 | (bibtex-find-entry): New optional arg START. | ||
| 38 | (bibtex-validate): Use bibtex-string= and assoc-string. | ||
| 39 | Do not call obsolete function compilation-parse-errors. | ||
| 40 | (bibtex-remove-delimiters): Only remove delimiters if present. | ||
| 41 | (bibtex-copy-entry-as-kill): Add docstring. | ||
| 42 | (bibtex-clean-entry): Use bibtex-string=. Handle empty keys. | ||
| 43 | Detect duplicate keys if bibtex-maintain-sorted-entries is nil. | ||
| 44 | (bibtex-complete): Use bibtex-predefined-month-strings, | ||
| 45 | bibtex-string=, and new function bibtex-complete-key-cleanup. | ||
| 46 | (bibtex-generate-url-list): New variable. | ||
| 47 | (bibtex-url): New command bound to C-c C-l and mouse-2. | ||
| 48 | (bibtex-url-map): New local keymap for bibtex-url-mouse. | ||
| 49 | (bibtex-font-lock-url): New function. | ||
| 50 | |||
| 1 | 2004-09-09 Stefan Monnier <monnier@iro.umontreal.ca> | 51 | 2004-09-09 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 52 | ||
| 3 | * progmodes/grep.el (grep-mode): Remove unnecessary autoload. | 53 | * progmodes/grep.el (grep-mode): Remove unnecessary autoload. |
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el index 15348205c51..d521a98b9b1 100644 --- a/lisp/textmodes/bibtex.el +++ b/lisp/textmodes/bibtex.el | |||
| @@ -640,7 +640,7 @@ See `bibtex-generate-autokey' for details." | |||
| 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. |
| @@ -762,11 +762,46 @@ If non-nil, the column for the equal sign is the value of | |||
| 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 |
| @@ -801,6 +836,7 @@ If non-nil, the column for the equal sign is the value of | |||
| 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) |
| @@ -821,6 +857,7 @@ If non-nil, the column for the equal sign is the value of | |||
| 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) |
| @@ -854,21 +891,7 @@ If non-nil, the column for the equal sign is the value of | |||
| 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] |
| @@ -888,12 +911,28 @@ If non-nil, the column for the equal sign is the value of | |||
| 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 |
| @@ -915,6 +954,13 @@ If non-nil, the column for the equal sign is the value of | |||
| 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 | ||
| @@ -1040,38 +1086,32 @@ was parsed for keys the last time.") | |||
| 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.") |
| 1074 | 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'.") | ||
| 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'.") |
| @@ -1089,22 +1129,22 @@ function `bibtex-parse-field-name'.") | |||
| 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 |
| @@ -1215,9 +1255,9 @@ returned, nil otherwise. Move point to end of field text." | |||
| 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)))) |
| @@ -1294,10 +1334,15 @@ current entry. Do not move point." | |||
| 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. |
| @@ -1438,6 +1483,10 @@ delimiters if present." | |||
| 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]+") |
| @@ -1448,15 +1497,6 @@ delimiters if present." | |||
| 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 | 1499 | ||
| 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 | |||
| 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 |
| @@ -1501,7 +1541,7 @@ FUN will not be called for @String entries." | |||
| 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))))) |
| @@ -1575,7 +1615,7 @@ are defined, but only for the head part of the entry | |||
| 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) |
| @@ -1684,10 +1724,10 @@ are defined, but only for the head part of the entry | |||
| 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)) |
| @@ -1732,8 +1772,7 @@ Beginning (but not end) of entry is given by (`match-beginning' 0)." | |||
| 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))) |
| @@ -1741,15 +1780,6 @@ Beginning (but not end) of entry is given by (`match-beginning' 0)." | |||
| 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 | 1782 | ||
| 1744 | (defun bibtex-assoc-regexp (regexp alist) | ||
| 1745 | "Return non-nil if REGEXP matches the car of an element of ALIST. | ||
| 1746 | The value is actually the element of ALIST matched by REGEXP. | ||
| 1747 | Case is ignored if `case-fold-search' is non-nil in the current buffer." | ||
| 1748 | (while (and alist | ||
| 1749 | (not (string-match regexp (caar alist)))) | ||
| 1750 | (setq alist (cdr alist))) | ||
| 1751 | (car alist)) | ||
| 1752 | |||
| 1753 | (defun bibtex-format-entry () | 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'." |
| @@ -1764,7 +1794,7 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 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)) |
| @@ -1792,9 +1822,7 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 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))) |
| @@ -1806,9 +1834,7 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 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)))) |
| @@ -1887,7 +1913,7 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 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]+[\"}]\\)"))) |
| @@ -1896,7 +1922,7 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 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) |
| @@ -1909,7 +1935,7 @@ Formats current entry according to variable `bibtex-entry-format'." | |||
| 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) |
| @@ -2023,12 +2049,13 @@ applied to the content of FIELD. It is an alist with pairs | |||
| 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." |
| @@ -2059,18 +2086,18 @@ and return results as a list." | |||
| 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))) |
| @@ -2078,8 +2105,12 @@ and return results as a list." | |||
| 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)) |
| @@ -2097,7 +2128,7 @@ and return results as a list." | |||
| 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) "\\)\\'") |
| @@ -2308,7 +2339,7 @@ Return alist of strings if parsing was completed, `aborted' otherwise." | |||
| 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)) |
| @@ -2317,9 +2348,9 @@ Return alist of strings if parsing was completed, `aborted' otherwise." | |||
| 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)))))) |
| @@ -2409,11 +2440,12 @@ of a word, all strings are listed. Return completion." | |||
| 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))) |
| @@ -2427,6 +2459,38 @@ expansion of STR." | |||
| 2427 | (bibtex-end-of-text-in-field bounds))) | 2459 | (bibtex-end-of-text-in-field bounds))) |
| 2428 | (bibtex-remove-delimiters)))))))) | 2460 | (bibtex-remove-delimiters)))))))) |
| 2429 | 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 | ""))))))) | ||
| 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 |
| @@ -2460,17 +2524,7 @@ expansion of STR." | |||
| 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) |
| @@ -2639,9 +2693,10 @@ non-nil. | |||
| 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))) |
| @@ -2722,29 +2777,27 @@ according to `bibtex-entry-field-alist', but are not yet present." | |||
| 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)))) |
| @@ -2770,7 +2823,7 @@ TEXT may be nil. Move point to the end of the last field." | |||
| 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) |
| @@ -2780,7 +2833,7 @@ TEXT may be nil. Move point to the end of the last field." | |||
| 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) |
| @@ -2794,11 +2847,8 @@ TEXT may be nil. Move point to the end of the last field." | |||
| 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)) |
| @@ -2821,13 +2871,7 @@ TEXT may be nil. Move point to the end of the last field." | |||
| 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)))) |
| @@ -2868,16 +2912,16 @@ FIELD is either a string or a list of the form | |||
| 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))) |
| @@ -3084,13 +3128,17 @@ entry." | |||
| 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]*\\(" |
| @@ -3157,8 +3205,7 @@ Return t if preparation was successful or nil if entry KEY already exists." | |||
| 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 | ||
| @@ -3233,9 +3280,7 @@ Returns t if test was successful, nil otherwise." | |||
| 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) |
| @@ -3251,17 +3296,16 @@ Returns t if test was successful, nil otherwise." | |||
| 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)) |
| @@ -3305,10 +3349,6 @@ Returns t if test was successful, nil otherwise." | |||
| 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)) |
| @@ -3395,11 +3435,13 @@ Align text and go thereafter to end of text." | |||
| 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. |
| @@ -3455,6 +3497,7 @@ With prefix arg COPY-ONLY the current entry to | |||
| 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 | ||
| @@ -3482,8 +3525,8 @@ If N is negative, this is a more recent kill. | |||
| 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)) |
| @@ -3533,19 +3576,20 @@ At end of the cleaning process, the functions in | |||
| 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) |
| @@ -3563,19 +3607,21 @@ At end of the cleaning process, the functions in | |||
| 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 |
| @@ -3583,7 +3629,7 @@ At end of the cleaning process, the functions in | |||
| 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)))))) |
| @@ -3752,28 +3798,29 @@ entries from minibuffer." | |||
| 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 |
| @@ -3789,24 +3836,23 @@ is outside key or BibTeX field." | |||
| 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)))) | ||
| 3800 | 3845 | ||
| 3801 | ((equal compl 'str) | 3846 | (compl |
| 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 | ||
| @@ -3880,8 +3926,8 @@ is outside key or BibTeX field." | |||
| 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)) |
| @@ -3913,6 +3959,86 @@ is outside key or BibTeX field." | |||
| 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 | ||