diff options
| author | Roland Winkler | 2011-06-05 00:46:43 -0500 |
|---|---|---|
| committer | Roland Winkler | 2011-06-05 00:46:43 -0500 |
| commit | 34699b85fd84223412b39dc2e455d43756903671 (patch) | |
| tree | 3bc5e7f7b5bc5fee910c5f37720871f650e3b9d5 | |
| parent | 004dedd364f5944b51b61acf90c4976f9c974ba9 (diff) | |
| download | emacs-34699b85fd84223412b39dc2e455d43756903671.tar.gz emacs-34699b85fd84223412b39dc2e455d43756903671.zip | |
lisp/textmodes/bibtex.el: new command bibtex-search-entries
| -rw-r--r-- | etc/NEWS | 2 | ||||
| -rw-r--r-- | lisp/ChangeLog | 6 | ||||
| -rw-r--r-- | lisp/textmodes/bibtex.el | 120 |
3 files changed, 128 insertions, 0 deletions
| @@ -438,6 +438,8 @@ Just set shell-dir-cookie-re to an appropriate regexp. | |||
| 438 | 438 | ||
| 439 | ** BibTeX mode | 439 | ** BibTeX mode |
| 440 | 440 | ||
| 441 | *** New command `bibtex-search-entries' bound to C-c C-a. | ||
| 442 | |||
| 441 | *** New `bibtex-entry-format' option `sort-fields', disabled by default. | 443 | *** New `bibtex-entry-format' option `sort-fields', disabled by default. |
| 442 | 444 | ||
| 443 | *** New variable `bibtex-search-entry-globally'. | 445 | *** New variable `bibtex-search-entry-globally'. |
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 8a7b9f4f822..2e0352a7bdf 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,5 +1,11 @@ | |||
| 1 | 2011-06-05 Roland Winkler <winkler@gnu.org> | 1 | 2011-06-05 Roland Winkler <winkler@gnu.org> |
| 2 | 2 | ||
| 3 | * textmodes/bibtex.el (bibtex-search-buffer): New variable. | ||
| 4 | (bibtex-search-entries): New command bound to C-c C-a. | ||
| 5 | (bibtex-display-entries): New function. | ||
| 6 | |||
| 7 | 2011-06-05 Roland Winkler <winkler@gnu.org> | ||
| 8 | |||
| 3 | * textmodes/bibtex.el (bibtex-generate-url-list): Fix docstring. | 9 | * textmodes/bibtex.el (bibtex-generate-url-list): Fix docstring. |
| 4 | (bibtex-insert-kill): After yanking insert newline if necessary. | 10 | (bibtex-insert-kill): After yanking insert newline if necessary. |
| 5 | (bibtex-initialize): Call bibtex-string-files-init only once. | 11 | (bibtex-initialize): Call bibtex-string-files-init only once. |
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el index 6d07a6e3950..12094887f38 100644 --- a/lisp/textmodes/bibtex.el +++ b/lisp/textmodes/bibtex.el | |||
| @@ -968,6 +968,11 @@ Set this variable before loading BibTeX mode." | |||
| 968 | :group 'bibtex | 968 | :group 'bibtex |
| 969 | :type 'boolean) | 969 | :type 'boolean) |
| 970 | 970 | ||
| 971 | (defcustom bibtex-search-buffer "*BibTeX Search*" | ||
| 972 | "Buffer for BibTeX search results." | ||
| 973 | :group 'bibtex | ||
| 974 | :type 'string) | ||
| 975 | |||
| 971 | ;; `bibtex-font-lock-keywords' is a user option, too. But since the | 976 | ;; `bibtex-font-lock-keywords' is a user option, too. But since the |
| 972 | ;; patterns used to define this variable are defined in a later | 977 | ;; patterns used to define this variable are defined in a later |
| 973 | ;; section of this file, it is defined later. | 978 | ;; section of this file, it is defined later. |
| @@ -1025,6 +1030,7 @@ Set this variable before loading BibTeX mode." | |||
| 1025 | (define-key km "\C-c\C-rn" 'bibtex-narrow-to-entry) | 1030 | (define-key km "\C-c\C-rn" 'bibtex-narrow-to-entry) |
| 1026 | (define-key km "\C-c\C-rw" 'widen) | 1031 | (define-key km "\C-c\C-rw" 'widen) |
| 1027 | (define-key km "\C-c\C-l" 'bibtex-url) | 1032 | (define-key km "\C-c\C-l" 'bibtex-url) |
| 1033 | (define-key km "\C-c\C-a" 'bibtex-search-entries) | ||
| 1028 | (define-key km "\C-c\C-o" 'bibtex-remove-OPT-or-ALT) | 1034 | (define-key km "\C-c\C-o" 'bibtex-remove-OPT-or-ALT) |
| 1029 | (define-key km "\C-c\C-e\C-i" 'bibtex-InProceedings) | 1035 | (define-key km "\C-c\C-e\C-i" 'bibtex-InProceedings) |
| 1030 | (define-key km "\C-c\C-ei" 'bibtex-InCollection) | 1036 | (define-key km "\C-c\C-ei" 'bibtex-InCollection) |
| @@ -1102,6 +1108,8 @@ Set this variable before loading BibTeX mode." | |||
| 1102 | ["View Cite Locations (RefTeX)" reftex-view-crossref-from-bibtex | 1108 | ["View Cite Locations (RefTeX)" reftex-view-crossref-from-bibtex |
| 1103 | (fboundp 'reftex-view-crossref-from-bibtex)]) | 1109 | (fboundp 'reftex-view-crossref-from-bibtex)]) |
| 1104 | ("Operating on Buffer or Region" | 1110 | ("Operating on Buffer or Region" |
| 1111 | ["Search Entries" bibtex-search-entries t] | ||
| 1112 | "--" | ||
| 1105 | ["Validate Entries" bibtex-validate t] | 1113 | ["Validate Entries" bibtex-validate t] |
| 1106 | ["Sort Entries" bibtex-sort-buffer t] | 1114 | ["Sort Entries" bibtex-sort-buffer t] |
| 1107 | ["Reformat Entries" bibtex-reformat t] | 1115 | ["Reformat Entries" bibtex-reformat t] |
| @@ -4789,6 +4797,118 @@ Return the URL or nil if none can be generated." | |||
| 4789 | (message "No URL known.")) | 4797 | (message "No URL known.")) |
| 4790 | url))) | 4798 | url))) |
| 4791 | 4799 | ||
| 4800 | ;; We could combine multiple seach results with set operations | ||
| 4801 | ;; AND, OR, MINUS, and NOT. Would this be useful? | ||
| 4802 | ;; How complicated are searches in real life? | ||
| 4803 | ;; We could also have other searches such as "publication year newer than...". | ||
| 4804 | (defun bibtex-search-entries (field regexp &optional global display) | ||
| 4805 | "Search BibTeX entries for FIELD matching REGEXP. | ||
| 4806 | REGEXP may be a regexp to search for. | ||
| 4807 | If REGEXP is a function, it is called for each entry with two args, | ||
| 4808 | the buffer positions of beginning and end of entry. Then an entry | ||
| 4809 | is accepted if this function returns non-nil. | ||
| 4810 | If FIELD is an empty string perform search for REGEXP in whole entry. | ||
| 4811 | With GLOBAL non-nil, search in `bibtex-files'. Otherwise the search | ||
| 4812 | is limited to the current buffer. | ||
| 4813 | If DISPLAY is non-nil, display search results in `bibtex-search-buffer'. | ||
| 4814 | When called interactively, DISPLAY is t. | ||
| 4815 | Also, GLOBAL is t if `bibtex-search-entry-globally' is non-nil. | ||
| 4816 | A prefix arg negates the value of `bibtex-search-entry-globally'. | ||
| 4817 | Return alist with elements (KEY FILE ENTRY), | ||
| 4818 | where FILE is the BibTeX file of ENTRY." | ||
| 4819 | (interactive | ||
| 4820 | (list (completing-read | ||
| 4821 | "Field: " | ||
| 4822 | (delete-dups | ||
| 4823 | (apply 'append | ||
| 4824 | bibtex-user-optional-fields | ||
| 4825 | (mapcar (lambda (x) | ||
| 4826 | (append (mapcar 'car (nth 0 (nth 1 x))) | ||
| 4827 | (mapcar 'car (nth 1 (nth 1 x))))) | ||
| 4828 | bibtex-entry-field-alist))) nil t) | ||
| 4829 | (read-string "Regexp: ") | ||
| 4830 | (if bibtex-search-entry-globally | ||
| 4831 | (not current-prefix-arg) | ||
| 4832 | current-prefix-arg) | ||
| 4833 | t)) | ||
| 4834 | (let ((funp (functionp regexp)) | ||
| 4835 | entries text file) | ||
| 4836 | ;; If REGEXP is a function, the value of FIELD is ignored anyway. | ||
| 4837 | ;; Yet to ensure the code below does not fail, we make FIELD | ||
| 4838 | ;; a non-empty string. | ||
| 4839 | (if (and funp (string= "" field)) (setq field "unrestricted")) | ||
| 4840 | (dolist (buffer (if (and global bibtex-files) | ||
| 4841 | (bibtex-initialize t) | ||
| 4842 | (list (current-buffer)))) | ||
| 4843 | (with-current-buffer buffer | ||
| 4844 | (setq file (if buffer-file-name | ||
| 4845 | (file-name-nondirectory buffer-file-name) | ||
| 4846 | (buffer-name buffer))) | ||
| 4847 | (save-excursion | ||
| 4848 | (goto-char (point-min)) | ||
| 4849 | (if (string= "" field) | ||
| 4850 | ;; Unrestricted search. | ||
| 4851 | (while (re-search-forward regexp nil t) | ||
| 4852 | (let ((beg (bibtex-beginning-of-entry)) | ||
| 4853 | (end (bibtex-end-of-entry)) | ||
| 4854 | key) | ||
| 4855 | (if (and (<= beg (match-beginning 0)) | ||
| 4856 | (<= (match-end 0) end) | ||
| 4857 | (save-excursion | ||
| 4858 | (goto-char beg) | ||
| 4859 | (and (looking-at bibtex-entry-head) | ||
| 4860 | (setq key (bibtex-key-in-head))))) | ||
| 4861 | (add-to-list 'entries | ||
| 4862 | (list key file | ||
| 4863 | (buffer-substring-no-properties | ||
| 4864 | beg end)))))) | ||
| 4865 | ;; The following is slow. But it works reliably even in more | ||
| 4866 | ;; complicated cases with BibTeX string constants and crossrefed | ||
| 4867 | ;; entries. If you prefer speed over reliability, perform an | ||
| 4868 | ;; unrestricted search. | ||
| 4869 | (bibtex-map-entries | ||
| 4870 | (lambda (key beg end) | ||
| 4871 | (if (cond (funp (funcall regexp beg end)) | ||
| 4872 | ((and (setq text (bibtex-text-in-field field t)) | ||
| 4873 | (string-match regexp text)))) | ||
| 4874 | (add-to-list 'entries | ||
| 4875 | (list key file | ||
| 4876 | (buffer-substring-no-properties | ||
| 4877 | beg end)))))))))) | ||
| 4878 | (if display | ||
| 4879 | (if entries | ||
| 4880 | (bibtex-display-entries entries) | ||
| 4881 | (message "No BibTeX entries %smatching `%s'" | ||
| 4882 | (if (string= "" field) "" | ||
| 4883 | (format "with field `%s' " field)) | ||
| 4884 | regexp))) | ||
| 4885 | entries)) | ||
| 4886 | |||
| 4887 | (defun bibtex-display-entries (entries &optional append) | ||
| 4888 | "Display BibTeX ENTRIES in `bibtex-search-buffer'. | ||
| 4889 | ENTRIES is an alist with elements (KEY FILE ENTRY), | ||
| 4890 | where FILE is the BibTeX file of ENTRY. | ||
| 4891 | If APPEND is non-nil, append ENTRIES to those already displayed." | ||
| 4892 | (pop-to-buffer (get-buffer-create bibtex-search-buffer)) | ||
| 4893 | ;; It would be nice if this buffer was editable, though editing | ||
| 4894 | ;; can be meaningful only for individual existing entries | ||
| 4895 | ;; (unlike reordering or creating new entries). | ||
| 4896 | ;; Fancy workaround: Editing commands in the virtual buffer could | ||
| 4897 | ;; jump to the real entry in the real buffer. | ||
| 4898 | (let (buffer-read-only) | ||
| 4899 | (if append (goto-char (point-max)) (erase-buffer)) | ||
| 4900 | (dolist (entry (sort entries (lambda (x y) (string< (car x) (car y))))) | ||
| 4901 | (insert "% " (nth 1 entry) "\n" (nth 2 entry) "\n\n"))) | ||
| 4902 | ;; `bibtex-sort-buffer' fails with the file names associated with | ||
| 4903 | ;; each entry. Prior to sorting we could make the file name | ||
| 4904 | ;; a BibTeX field of each entry (using `bibtex-make-field'). | ||
| 4905 | ;; Or we could make it a text property that we unfold afterwards. | ||
| 4906 | ;; (bibtex-sort-buffer) | ||
| 4907 | (bibtex-mode) | ||
| 4908 | (set-buffer-modified-p nil) | ||
| 4909 | (setq buffer-read-only t) | ||
| 4910 | (goto-char (point-min))) | ||
| 4911 | |||
| 4792 | 4912 | ||
| 4793 | ;; Make BibTeX a Feature | 4913 | ;; Make BibTeX a Feature |
| 4794 | 4914 | ||