mirror of
https://git.savannah.gnu.org/git/emacs.git
synced 2024-11-23 07:19:15 +00:00
(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.
This commit is contained in:
parent
0608b1a02e
commit
d528bff745
2
etc/NEWS
2
etc/NEWS
@ -617,6 +617,8 @@ version 4.7 or newer, compiles to Info pages with embedded images.
|
||||
'sql-sqlite'.
|
||||
|
||||
** BibTeX mode:
|
||||
*** The new command bibtex-url browses a URL for the BibTeX entry at
|
||||
point (bound to C-c C-l and mouse-2 on clickable fields).
|
||||
*** The new command bibtex-entry-update (bound to C-c C-u) updates
|
||||
an existing BibTeX entry.
|
||||
*** New `bibtex-entry-format' option `required-fields', enabled by default.
|
||||
|
@ -1,3 +1,53 @@
|
||||
2004-09-10 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* textmodes/bibtex.el (bibtex-mark-active)
|
||||
(bibtex-run-with-idle-timer): Move the `if' inside the defun.
|
||||
|
||||
2004-09-10 Roland Winkler <Roland.Winkler@physik.uni-erlangen.de>
|
||||
|
||||
* textmodes/bibtex.el (bibtex-autokey-titleword-ignore): Regexp is
|
||||
used in a case insensitive environment.
|
||||
(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 optional 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 arg.
|
||||
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.
|
||||
|
||||
2004-09-09 Stefan Monnier <monnier@iro.umontreal.ca>
|
||||
|
||||
* progmodes/grep.el (grep-mode): Remove unnecessary autoload.
|
||||
|
@ -640,7 +640,7 @@ See `bibtex-generate-autokey' for details."
|
||||
|
||||
(defcustom bibtex-autokey-titleword-ignore
|
||||
'("A" "An" "On" "The" "Eine?" "Der" "Die" "Das"
|
||||
"[^A-Z].*" ".*[^a-zA-Z0-9].*")
|
||||
"[^A-Z].*" ".*[^A-Z0-9].*")
|
||||
"*Determines words from the title that are not to be used in the key.
|
||||
Each item of the list is a regexp. If a word of the title matchs a
|
||||
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
|
||||
"Automatically fill fields if possible for those BibTeX entry types."
|
||||
:type '(repeat string))
|
||||
|
||||
(defcustom bibtex-complete-key-cleanup nil
|
||||
"*Function called by `bibtex-complete' after insertion of a key fragment."
|
||||
:group 'bibtex-autokey
|
||||
:type '(choice (const :tag "None" nil)
|
||||
(function :tag "Cleanup function")))
|
||||
(defcustom bibtex-generate-url-list
|
||||
'((("url" . t) ("url" t)))
|
||||
"List of schemes for generating the URL of a BibTeX entry.
|
||||
These schemes are used by `bibtex-url'.
|
||||
|
||||
Each scheme is of the form ((FIELD . REGEXP) STEPS).
|
||||
|
||||
FIELD is a field name as returned by `bibtex-parse-entry'.
|
||||
REGEXP is matched against the text of FIELD.
|
||||
If the match succeeds, the list STEPS is used to generate the URL.
|
||||
If REGEXP is t, always generate the URL if FIELD is present.
|
||||
|
||||
If an element of STEPS is a list (FIELD MATCH FILTER),
|
||||
the text of FIELD is matched against MATCH.
|
||||
If MATCH is t, the text of FIELD is accepted as is.
|
||||
If MATCH is a cons cell (REGEXP . REPLACE), the text is matched against REGEXP.
|
||||
If REPLACE is a string, the text is replaced with REPLACE. If REPLACE is a
|
||||
number, it specifies which parenthesized expression in the match is taken.
|
||||
The optional element FILTER is a function for piping the match through it.
|
||||
The text strings are then concatenated to generate the URL.
|
||||
|
||||
If an element of STEPS is a string, it is simply added to the URL.
|
||||
|
||||
Case is always ignored. Always remove the field delimiters."
|
||||
:group 'bibtex
|
||||
:type '(repeat
|
||||
(list :tag "Scheme"
|
||||
(cons :tag "Matcher" :extra-offset 4
|
||||
(string :tag "BibTeX field")
|
||||
(choice (regexp :tag "Regexp")
|
||||
(const :tag "Accept as is" t)))
|
||||
(repeat :tag "Steps to generate URL" :inline t
|
||||
(choice
|
||||
(string :tag "Literal text")
|
||||
(list (string :tag "BibTeX field")
|
||||
(choice (const :tag "Accept as is" t)
|
||||
(cons (string :tag "Field")
|
||||
(choice (regexp :tag "Regexp")
|
||||
(integer :tag "Matched parenthesis"))))
|
||||
(option (function :tag "Filter" :value ignore))))))))
|
||||
|
||||
;; bibtex-font-lock-keywords is a user option as well, but since the
|
||||
;; 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
|
||||
(define-key km "\C-c}" 'bibtex-remove-delimiters)
|
||||
(define-key km "\C-c\C-c" 'bibtex-clean-entry)
|
||||
(define-key km "\C-c\C-q" 'bibtex-fill-entry)
|
||||
(define-key km "\C-c\C-s" 'bibtex-find-entry)
|
||||
(define-key km "\C-c?" 'bibtex-print-help-message)
|
||||
(define-key km "\C-c\C-p" 'bibtex-pop-previous)
|
||||
(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
|
||||
(define-key km "\C-c\C-b" 'bibtex-entry)
|
||||
(define-key km "\C-c\C-rn" 'bibtex-narrow-to-entry)
|
||||
(define-key km "\C-c\C-rw" 'widen)
|
||||
(define-key km "\C-c\C-l" 'bibtex-url)
|
||||
(define-key km "\C-c\C-o" 'bibtex-remove-OPT-or-ALT)
|
||||
(define-key km "\C-c\C-e\C-i" 'bibtex-InProceedings)
|
||||
(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
|
||||
("Moving in BibTeX Buffer"
|
||||
["Find Entry" bibtex-find-entry t]
|
||||
["Find Crossref Entry" bibtex-find-crossref t])
|
||||
("Operating on Current Entry"
|
||||
["Fill Entry" bibtex-fill-entry t]
|
||||
["Clean Entry" bibtex-clean-entry t]
|
||||
"--"
|
||||
["Kill Entry" bibtex-kill-entry t]
|
||||
["Copy Entry to Kill Ring" bibtex-copy-entry-as-kill t]
|
||||
["Paste Most Recently Killed Entry" bibtex-yank t]
|
||||
["Paste Previously Killed Entry" bibtex-yank-pop t]
|
||||
"--"
|
||||
["Ispell Entry" bibtex-ispell-entry t]
|
||||
["Ispell Entry Abstract" bibtex-ispell-abstract t]
|
||||
["Narrow to Entry" bibtex-narrow-to-entry t]
|
||||
"--"
|
||||
["View Cite Locations (RefTeX)" reftex-view-crossref-from-bibtex
|
||||
(fboundp 'reftex-view-crossref-from-bibtex)])
|
||||
("Operating on Current Field"
|
||||
["Fill Field" fill-paragraph t]
|
||||
["Remove Delimiters" bibtex-remove-delimiters t]
|
||||
@ -888,12 +911,28 @@ If non-nil, the column for the equal sign is the value of
|
||||
["String or Key Complete" bibtex-complete t]
|
||||
"--"
|
||||
["Help about Current Field" bibtex-print-help-message t])
|
||||
("Operating on Current Entry"
|
||||
["Fill Entry" bibtex-fill-entry t]
|
||||
["Clean Entry" bibtex-clean-entry t]
|
||||
["Update Entry" bibtex-entry-update t]
|
||||
"--"
|
||||
["Kill Entry" bibtex-kill-entry t]
|
||||
["Copy Entry to Kill Ring" bibtex-copy-entry-as-kill t]
|
||||
["Paste Most Recently Killed Entry" bibtex-yank t]
|
||||
["Paste Previously Killed Entry" bibtex-yank-pop t]
|
||||
"--"
|
||||
["Ispell Entry" bibtex-ispell-entry t]
|
||||
["Ispell Entry Abstract" bibtex-ispell-abstract t]
|
||||
["Narrow to Entry" bibtex-narrow-to-entry t]
|
||||
"--"
|
||||
["View Cite Locations (RefTeX)" reftex-view-crossref-from-bibtex
|
||||
(fboundp 'reftex-view-crossref-from-bibtex)])
|
||||
("Operating on Buffer or Region"
|
||||
["Validate Entries" bibtex-validate t]
|
||||
["Sort Entries" bibtex-sort-buffer t]
|
||||
["Reformat Entries" bibtex-reformat t]
|
||||
["Count Entries" bibtex-count-entries t])
|
||||
("Miscellaneous"
|
||||
["Count Entries" bibtex-count-entries t]
|
||||
"--"
|
||||
["Convert Alien Buffer" bibtex-convert-alien t])))
|
||||
|
||||
(easy-menu-define
|
||||
@ -915,6 +954,13 @@ If non-nil, the column for the equal sign is the value of
|
||||
["String" bibtex-String t]
|
||||
["Preamble" bibtex-Preamble t]))
|
||||
|
||||
(defvar bibtex-url-map
|
||||
(let ((km (make-sparse-keymap)))
|
||||
(define-key km [(mouse-2)] 'bibtex-url)
|
||||
km)
|
||||
"Local keymap for clickable URLs.")
|
||||
(fset 'bibtex-url-map bibtex-url-map)
|
||||
|
||||
|
||||
;; Internal Variables
|
||||
|
||||
@ -1040,38 +1086,32 @@ was parsed for keys the last time.")
|
||||
(defconst bibtex-empty-field-re "\"\"\\|{}"
|
||||
"Regexp matching an empty field.")
|
||||
|
||||
(defconst bibtex-quoted-string-re
|
||||
(concat "\""
|
||||
"\\("
|
||||
"[^\"\\]" ; anything but quote or backslash
|
||||
"\\|"
|
||||
"\\("
|
||||
"\\\\\\(.\\|\n\\)" ; any backslash quoted character
|
||||
"\\)"
|
||||
"\\)*"
|
||||
"\"")
|
||||
"Regexp matching a field string enclosed by quotes.")
|
||||
|
||||
(defconst bibtex-font-lock-syntactic-keywords
|
||||
`((,(concat "^[ \t]*\\(" (substring bibtex-comment-start 0 1) "\\)"
|
||||
(substring bibtex-comment-start 1) "\\>")
|
||||
1 '(11))))
|
||||
|
||||
(defvar bibtex-font-lock-keywords
|
||||
(list
|
||||
;; entry type and reference key
|
||||
(list bibtex-entry-maybe-empty-head
|
||||
(list bibtex-type-in-head 'font-lock-function-name-face)
|
||||
(list bibtex-key-in-head 'font-lock-constant-face nil t))
|
||||
`((,bibtex-entry-maybe-empty-head
|
||||
(,bibtex-type-in-head font-lock-function-name-face)
|
||||
(,bibtex-key-in-head font-lock-constant-face nil t))
|
||||
;; optional field names (treated as comments)
|
||||
(list
|
||||
(concat "^[ \t]*\\(OPT" bibtex-field-name "\\)[ \t]*=")
|
||||
1 'font-lock-comment-face)
|
||||
(,(concat "^[ \t]*\\(OPT" bibtex-field-name "\\)[ \t]*=")
|
||||
1 font-lock-comment-face)
|
||||
;; field names
|
||||
(list (concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=")
|
||||
1 'font-lock-variable-name-face))
|
||||
(,(concat "^[ \t]*\\(" bibtex-field-name "\\)[ \t]*=")
|
||||
1 font-lock-variable-name-face)
|
||||
;; url
|
||||
(bibtex-font-lock-url 0 '(face nil mouse-face highlight
|
||||
keymap bibtex-url-map)))
|
||||
"*Default expressions to highlight in BibTeX mode.")
|
||||
|
||||
(defvar bibtex-font-lock-url-regexp
|
||||
(concat "\\<" (regexp-opt (mapcar 'caar bibtex-generate-url-list) t)
|
||||
"\\>[ \t]*=[ \t]*")
|
||||
"Regexp for `bibtex-font-lock-url'.")
|
||||
|
||||
(defvar bibtex-field-name-for-parsing nil
|
||||
"Temporary variable storing the name string to be parsed by the callback
|
||||
function `bibtex-parse-field-name'.")
|
||||
@ -1089,22 +1129,22 @@ function `bibtex-parse-field-name'.")
|
||||
|
||||
;; Special support taking care of variants
|
||||
(defvar zmacs-regions)
|
||||
(defalias 'bibtex-mark-active
|
||||
(if (boundp 'mark-active)
|
||||
(defun bibtex-mark-active ()
|
||||
;; In Emacs mark-active indicates if mark is active.
|
||||
mark-active)
|
||||
(defun bibtex-mark-active ()
|
||||
(lambda () mark-active)
|
||||
;; In XEmacs (mark) returns nil when not active.
|
||||
(if zmacs-regions (mark) (mark t))))
|
||||
(lambda () (if zmacs-regions (mark) (mark t)))))
|
||||
|
||||
(defalias 'bibtex-run-with-idle-timer
|
||||
(if (fboundp 'run-with-idle-timer)
|
||||
;; timer.el is distributed with Emacs
|
||||
(fset 'bibtex-run-with-idle-timer 'run-with-idle-timer)
|
||||
'run-with-idle-timer
|
||||
;; timer.el is not distributed with XEmacs
|
||||
;; Notice that this does not (yet) pass the arguments, but they
|
||||
;; are not used (yet) in bibtex.el. Fix if needed.
|
||||
(defun bibtex-run-with-idle-timer (secs repeat function &rest args)
|
||||
(start-itimer "bibtex" function secs (if repeat secs nil) t)))
|
||||
(lambda (secs repeat function &rest args)
|
||||
(start-itimer "bibtex" function secs (if repeat secs nil) t))))
|
||||
|
||||
|
||||
;; Support for hideshow minor mode
|
||||
@ -1215,9 +1255,9 @@ returned, nil otherwise. Move point to end of field text."
|
||||
((setq boundaries (bibtex-parse-field-string))
|
||||
(goto-char (cdr boundaries)))
|
||||
((setq failure t)))
|
||||
(if (not (looking-at "[ \t\n]*#[ \t\n]*"))
|
||||
(setq end-point (point))
|
||||
(goto-char (match-end 0))))
|
||||
(if (looking-at "[ \t\n]*#[ \t\n]*")
|
||||
(goto-char (match-end 0))
|
||||
(setq end-point (point))))
|
||||
(if (and (not failure)
|
||||
end-point)
|
||||
(cons starting-point end-point))))
|
||||
@ -1294,10 +1334,15 @@ current entry. Do not move point."
|
||||
(defsubst bibtex-end-of-text-in-field (bounds)
|
||||
(cddr bounds))
|
||||
|
||||
(defun bibtex-name-in-field (bounds)
|
||||
"Get content of name in BibTeX field defined via BOUNDS."
|
||||
(buffer-substring-no-properties (nth 1 (car bounds))
|
||||
(nth 2 (car bounds))))
|
||||
(defun bibtex-name-in-field (bounds &optional remove-opt-alt)
|
||||
"Get content of name in BibTeX field defined via BOUNDS.
|
||||
If optional arg REMOVE-OPT-ALT is non-nil remove \"OPT\" and \"ALT\"."
|
||||
(let ((name (buffer-substring-no-properties (nth 1 (car bounds))
|
||||
(nth 2 (car bounds)))))
|
||||
(if (and remove-opt-alt
|
||||
(string-match "\\`\\(OPT\\|ALT\\)" name))
|
||||
(substring name 3)
|
||||
name)))
|
||||
|
||||
(defun bibtex-text-in-field-bounds (bounds &optional remove-delim)
|
||||
"Get content of text in BibTeX field defined via BOUNDS.
|
||||
@ -1438,6 +1483,10 @@ delimiters if present."
|
||||
|
||||
;; Helper Functions
|
||||
|
||||
(defsubst bibtex-string= (str1 str2)
|
||||
"Return t if two strings are equal, ignoring case."
|
||||
(eq t (compare-strings str1 0 nil str2 0 nil t)))
|
||||
|
||||
(defun bibtex-delete-whitespace ()
|
||||
"Delete all whitespace starting at point."
|
||||
(if (looking-at "[ \t\n]+")
|
||||
@ -1448,15 +1497,6 @@ delimiters if present."
|
||||
(+ (count-lines 1 (point))
|
||||
(if (equal (current-column) 0) 1 0)))
|
||||
|
||||
(defun bibtex-member-of-regexp (string list)
|
||||
"Return non-nil if STRING is exactly matched by an element of LIST.
|
||||
The value is actually the tail of LIST whose car matches STRING."
|
||||
(let (case-fold-search)
|
||||
(while (and list
|
||||
(not (string-match (concat "\\`\\(?:" (car list) "\\)\\'") string)))
|
||||
(setq list (cdr list)))
|
||||
list))
|
||||
|
||||
(defun bibtex-skip-to-valid-entry (&optional backward)
|
||||
"Unless at beginning of a valid BibTeX entry, move point to beginning of the
|
||||
next valid one. With optional argument BACKWARD non-nil, move backward to
|
||||
@ -1501,7 +1541,7 @@ FUN will not be called for @String entries."
|
||||
(end (copy-marker (save-excursion (bibtex-end-of-entry)))))
|
||||
(save-excursion
|
||||
(if (or (and (not bibtex-sort-ignore-string-entries)
|
||||
(string-equal "string" (downcase entry-type)))
|
||||
(bibtex-string= entry-type "string"))
|
||||
(assoc-string entry-type bibtex-entry-field-alist t))
|
||||
(funcall fun key beg end)))
|
||||
(goto-char end)))))
|
||||
@ -1575,7 +1615,7 @@ are defined, but only for the head part of the entry
|
||||
(if found
|
||||
(progn (goto-char (match-beginning 0))
|
||||
found)
|
||||
(cond ((equal noerror nil)
|
||||
(cond ((not noerror)
|
||||
;; yell
|
||||
(error "Backward search of BibTeX entry failed"))
|
||||
((equal noerror t)
|
||||
@ -1684,10 +1724,10 @@ are defined, but only for the head part of the entry
|
||||
(forward-char -1)))
|
||||
|
||||
(defun bibtex-enclosing-field (&optional noerr)
|
||||
"Search for BibTeX field enclosing point. Point moves to end of field.
|
||||
"Search for BibTeX field enclosing point.
|
||||
Use `match-beginning' and `match-end' to parse the field. If NOERR is non-nil,
|
||||
no error is signalled. In this case, bounds are returned on success,
|
||||
nil otherwise."
|
||||
nil otherwise. Does not move point."
|
||||
(let ((bounds (bibtex-search-backward-field bibtex-field-name t)))
|
||||
(if (and bounds
|
||||
(<= (bibtex-start-of-field bounds) (point))
|
||||
@ -1732,8 +1772,7 @@ Beginning (but not end) of entry is given by (`match-beginning' 0)."
|
||||
(message "Mark set")
|
||||
(bibtex-make-field (list (elt current 1) nil (elt current 2)) t))
|
||||
((equal bibtex-last-kill-command 'entry)
|
||||
(if (not (eobp))
|
||||
(bibtex-beginning-of-entry))
|
||||
(unless (eobp) (bibtex-beginning-of-entry))
|
||||
(set-mark (point))
|
||||
(message "Mark set")
|
||||
(insert (elt current 1)))
|
||||
@ -1741,15 +1780,6 @@ Beginning (but not end) of entry is given by (`match-beginning' 0)."
|
||||
(error "Unknown tag field: %s. Please submit a bug report"
|
||||
bibtex-last-kill-command))))))
|
||||
|
||||
(defun bibtex-assoc-regexp (regexp alist)
|
||||
"Return non-nil if REGEXP matches the car of an element of ALIST.
|
||||
The value is actually the element of ALIST matched by REGEXP.
|
||||
Case is ignored if `case-fold-search' is non-nil in the current buffer."
|
||||
(while (and alist
|
||||
(not (string-match regexp (caar alist))))
|
||||
(setq alist (cdr alist)))
|
||||
(car alist))
|
||||
|
||||
(defun bibtex-format-entry ()
|
||||
"Helper function for `bibtex-clean-entry'.
|
||||
Formats current entry according to variable `bibtex-entry-format'."
|
||||
@ -1764,7 +1794,7 @@ Formats current entry according to variable `bibtex-entry-format'."
|
||||
unify-case inherit-booktitle)
|
||||
bibtex-entry-format))
|
||||
crossref-key bounds alternatives-there non-empty-alternative
|
||||
entry-list req-field-list field-done field-list)
|
||||
entry-list req-field-list field-list)
|
||||
|
||||
;; identify entry type
|
||||
(goto-char (point-min))
|
||||
@ -1792,9 +1822,7 @@ Formats current entry according to variable `bibtex-entry-format'."
|
||||
;; one alternative is non-empty
|
||||
(goto-char (point-min))
|
||||
(let* ((fields-alist (bibtex-parse-entry))
|
||||
(case-fold-search t)
|
||||
(field (bibtex-assoc-regexp "\\`\\(OPT\\)?crossref\\'"
|
||||
fields-alist)))
|
||||
(field (assoc-string "crossref" fields-alist t)))
|
||||
(setq crossref-key (and field
|
||||
(not (string-match bibtex-empty-field-re
|
||||
(cdr field)))
|
||||
@ -1806,9 +1834,7 @@ Formats current entry according to variable `bibtex-entry-format'."
|
||||
(dolist (rfield req-field-list)
|
||||
(when (nth 3 rfield) ; we should have an alternative
|
||||
(setq alternatives-there t
|
||||
field (bibtex-assoc-regexp
|
||||
(concat "\\`\\(ALT\\)?" (car rfield) "\\'")
|
||||
fields-alist))
|
||||
field (assoc-string (car rfield) fields-alist t))
|
||||
(if (and field
|
||||
(not (string-match bibtex-empty-field-re
|
||||
(cdr field))))
|
||||
@ -1887,7 +1913,7 @@ Formats current entry according to variable `bibtex-entry-format'."
|
||||
|
||||
;; update page dashes
|
||||
(if (and (memq 'page-dashes format)
|
||||
(string-match "\\`\\(OPT\\)?pages\\'" field-name)
|
||||
(bibtex-string= field-name "pages")
|
||||
(progn (goto-char beg-text)
|
||||
(looking-at
|
||||
"\\([\"{][0-9]+\\)[ \t\n]*--?[ \t\n]*\\([0-9]+[\"}]\\)")))
|
||||
@ -1896,7 +1922,7 @@ Formats current entry according to variable `bibtex-entry-format'."
|
||||
;; use book title of crossref'd entry
|
||||
(if (and (memq 'inherit-booktitle format)
|
||||
empty-field
|
||||
(equal (downcase field-name) "booktitle")
|
||||
(bibtex-string= field-name "booktitle")
|
||||
crossref-key)
|
||||
(let ((title (save-restriction
|
||||
(widen)
|
||||
@ -1909,7 +1935,7 @@ Formats current entry according to variable `bibtex-entry-format'."
|
||||
|
||||
;; Use booktitle to set a missing title.
|
||||
(if (and empty-field
|
||||
(equal (downcase field-name) "title"))
|
||||
(bibtex-string= field-name "title"))
|
||||
(let ((booktitle (bibtex-text-in-field "booktitle")))
|
||||
(when booktitle
|
||||
(setq empty-field nil)
|
||||
@ -2023,12 +2049,13 @@ applied to the content of FIELD. It is an alist with pairs
|
||||
"Get contents of the name field of the current entry.
|
||||
Do some modifications based on `bibtex-autokey-name-change-strings'
|
||||
and return results as a list."
|
||||
(let ((case-fold-search t))
|
||||
(let ((case-fold-search t)
|
||||
(names (bibtex-autokey-get-field "author\\|editor"
|
||||
bibtex-autokey-name-change-strings)))
|
||||
;; Some entries do not have a name field.
|
||||
(unless (string= "" names)
|
||||
(mapcar 'bibtex-autokey-demangle-name
|
||||
(split-string (bibtex-autokey-get-field
|
||||
"author\\|editor"
|
||||
bibtex-autokey-name-change-strings)
|
||||
"[ \t\n]+and[ \t\n]+"))))
|
||||
(split-string names "[ \t\n]+and[ \t\n]+")))))
|
||||
|
||||
(defun bibtex-autokey-demangle-name (fullname)
|
||||
"Get the last part from a well-formed name and perform abbreviations."
|
||||
@ -2059,18 +2086,18 @@ and return results as a list."
|
||||
|
||||
(defun bibtex-autokey-get-title ()
|
||||
"Get title field contents up to a terminator."
|
||||
(let ((titlestring
|
||||
(let ((case-fold-search t)
|
||||
(titlestring
|
||||
(bibtex-autokey-get-field "title"
|
||||
bibtex-autokey-titleword-change-strings)))
|
||||
;; ignore everything past a terminator
|
||||
(let ((case-fold-search t))
|
||||
(dolist (terminator bibtex-autokey-title-terminators)
|
||||
(if (string-match terminator titlestring)
|
||||
(setq titlestring (substring titlestring 0 (match-beginning 0))))))
|
||||
(setq titlestring (substring titlestring 0 (match-beginning 0)))))
|
||||
;; gather words from titlestring into a list. Ignore
|
||||
;; specific words and use only a specific amount of words.
|
||||
(let ((counter 0)
|
||||
case-fold-search titlewords titlewords-extra titleword end-match)
|
||||
titlewords titlewords-extra titleword end-match)
|
||||
(while (and (or (not (numberp bibtex-autokey-titlewords))
|
||||
(< counter (+ bibtex-autokey-titlewords
|
||||
bibtex-autokey-titlewords-stretch)))
|
||||
@ -2078,8 +2105,12 @@ and return results as a list."
|
||||
(setq end-match (match-end 0)
|
||||
titleword (substring titlestring
|
||||
(match-beginning 0) end-match))
|
||||
(unless (bibtex-member-of-regexp titleword
|
||||
bibtex-autokey-titleword-ignore)
|
||||
(unless (let ((lst bibtex-autokey-titleword-ignore))
|
||||
(while (and lst
|
||||
(not (string-match (concat "\\`\\(?:" (car lst)
|
||||
"\\)\\'") titleword)))
|
||||
(setq lst (cdr lst)))
|
||||
lst)
|
||||
(setq titleword
|
||||
(funcall bibtex-autokey-titleword-case-convert titleword))
|
||||
(if (or (not (numberp bibtex-autokey-titlewords))
|
||||
@ -2097,7 +2128,7 @@ and return results as a list."
|
||||
"Do some abbreviations on TITLEWORD.
|
||||
The rules are defined in `bibtex-autokey-titleword-abbrevs'
|
||||
and `bibtex-autokey-titleword-length'."
|
||||
(let ((case-folde-search t)
|
||||
(let ((case-fold-search t)
|
||||
(alist bibtex-autokey-titleword-abbrevs))
|
||||
(while (and alist
|
||||
(not (string-match (concat "\\`\\(?:" (caar alist) "\\)\\'")
|
||||
@ -2308,7 +2339,7 @@ Return alist of strings if parsing was completed, `aborted' otherwise."
|
||||
bounds key)
|
||||
(if (listp add)
|
||||
(dolist (string add)
|
||||
(unless (assoc (car string) strings)
|
||||
(unless (assoc-string (car string) strings t)
|
||||
(push string strings))))
|
||||
(catch 'userkey
|
||||
(while (setq bounds (bibtex-search-forward-string))
|
||||
@ -2317,7 +2348,7 @@ Return alist of strings if parsing was completed, `aborted' otherwise."
|
||||
;; user has aborted by typing a key --> return `aborted'
|
||||
(throw 'userkey 'aborted))
|
||||
(setq key (bibtex-reference-key-in-string bounds))
|
||||
(if (not (assoc key strings))
|
||||
(unless (assoc-string key strings t)
|
||||
(push (cons key (bibtex-text-in-string bounds t))
|
||||
strings))
|
||||
(goto-char (bibtex-end-of-text-in-string bounds)))
|
||||
@ -2409,11 +2440,12 @@ of a word, all strings are listed. Return completion."
|
||||
;; return value is handled by choose-completion-string-functions
|
||||
nil))))
|
||||
|
||||
(defun bibtex-complete-string-cleanup (str)
|
||||
(defun bibtex-complete-string-cleanup (str strings-alist)
|
||||
"Cleanup after inserting string STR.
|
||||
Remove enclosing field delimiters for string STR. Display message with
|
||||
expansion of STR."
|
||||
(let ((pair (assoc str bibtex-strings)))
|
||||
expansion of STR using expansion list STRINGS-ALIST."
|
||||
(let ((pair (if (stringp str)
|
||||
(assoc-string str strings-alist t))))
|
||||
(when pair
|
||||
(if (cdr pair)
|
||||
(message "Abbreviation for `%s'" (cdr pair)))
|
||||
@ -2427,6 +2459,38 @@ expansion of STR."
|
||||
(bibtex-end-of-text-in-field bounds)))
|
||||
(bibtex-remove-delimiters))))))))
|
||||
|
||||
(defun bibtex-complete-key-cleanup (key)
|
||||
"Display message on entry KEY after completion of a crossref key."
|
||||
(save-excursion
|
||||
;; Don't do anything if we completed the key of an entry.
|
||||
(let ((pnt (bibtex-beginning-of-entry)))
|
||||
(if (and (stringp key)
|
||||
(bibtex-find-entry key)
|
||||
(/= pnt (point)))
|
||||
(let* ((bibtex-autokey-name-case-convert 'identity)
|
||||
(bibtex-autokey-name-length 'infty)
|
||||
(nl (bibtex-autokey-get-names))
|
||||
(name (concat (nth 0 nl) (if (nth 1 nl) " etal")))
|
||||
(year (bibtex-autokey-get-field "year"))
|
||||
(bibtex-autokey-titlewords 5)
|
||||
(bibtex-autokey-titlewords-stretch 2)
|
||||
(bibtex-autokey-titleword-case-convert 'identity)
|
||||
(bibtex-autokey-titleword-length 5)
|
||||
(title (mapconcat 'identity
|
||||
(bibtex-autokey-get-title) " "))
|
||||
(journal (bibtex-autokey-get-field
|
||||
"journal" bibtex-autokey-transcriptions))
|
||||
(volume (bibtex-autokey-get-field "volume"))
|
||||
(pages (bibtex-autokey-get-field "pages" '(("-.*\\'" . "")))))
|
||||
(message "Ref:%s"
|
||||
(mapconcat (lambda (arg)
|
||||
(if (not (string= "" (cdr arg)))
|
||||
(concat (car arg) (cdr arg))))
|
||||
`((" " . ,name) (" " . ,year)
|
||||
(": " . ,title) (", " . ,journal)
|
||||
(" " . ,volume) (":" . ,pages))
|
||||
"")))))))
|
||||
|
||||
(defun bibtex-choose-completion-string (choice buffer mini-p base-size)
|
||||
;; Code borrowed from choose-completion-string:
|
||||
;; We must duplicate the code from choose-completion-string
|
||||
@ -2460,17 +2524,7 @@ expansion of STR."
|
||||
(bounds (bibtex-enclosing-field))
|
||||
(start-old-text (bibtex-start-of-text-in-field bounds))
|
||||
(stop-old-text (bibtex-end-of-text-in-field bounds))
|
||||
(start-name (bibtex-start-of-name-in-field bounds))
|
||||
(stop-name (bibtex-end-of-name-in-field bounds))
|
||||
;; construct regexp for field with same name as this one,
|
||||
;; ignoring possible OPT's or ALT's
|
||||
(field-name (progn
|
||||
(goto-char start-name)
|
||||
(buffer-substring-no-properties
|
||||
(if (looking-at "\\(OPT\\)\\|\\(ALT\\)")
|
||||
(match-end 0)
|
||||
(point))
|
||||
stop-name))))
|
||||
(field-name (bibtex-name-in-field bounds t)))
|
||||
;; if executed several times in a row, start each search where
|
||||
;; the last one was finished
|
||||
(unless (eq last-command 'bibtex-pop)
|
||||
@ -2639,6 +2693,7 @@ non-nil.
|
||||
)
|
||||
nil
|
||||
(font-lock-syntactic-keywords . bibtex-font-lock-syntactic-keywords)
|
||||
(font-lock-extra-managed-props . (mouse-face keymap))
|
||||
(font-lock-mark-block-function
|
||||
. (lambda ()
|
||||
(set-mark (bibtex-end-of-entry))
|
||||
@ -2722,29 +2777,27 @@ according to `bibtex-entry-field-alist', but are not yet present."
|
||||
(let* ((fields-alist (bibtex-parse-entry))
|
||||
(field-list (bibtex-field-list
|
||||
(substring (cdr (assoc "=type=" fields-alist))
|
||||
1))) ; don't want @
|
||||
(case-fold-search t))
|
||||
1)))) ; don't want @
|
||||
(dolist (field (car field-list))
|
||||
(unless (bibtex-assoc-regexp (concat "\\`\\(ALT\\)?" (car field) "\\'")
|
||||
fields-alist)
|
||||
(unless (assoc-string (car field) fields-alist t)
|
||||
(bibtex-make-field field)))
|
||||
(dolist (field (cdr field-list))
|
||||
(unless (bibtex-assoc-regexp (concat "\\`\\(OPT\\)?" (car field) "\\'")
|
||||
fields-alist)
|
||||
(unless (assoc-string (car field) fields-alist t)
|
||||
(bibtex-make-optional-field field))))))
|
||||
|
||||
(defun bibtex-parse-entry ()
|
||||
"Parse entry at point, return an alist.
|
||||
The alist elements have the form (FIELD . TEXT), where FIELD can also be
|
||||
the special strings \"=type=\" and \"=key=\". For the FIELD \"=key=\"
|
||||
TEXT may be nil. Move point to the end of the last field."
|
||||
TEXT may be nil. Remove \"OPT\" and \"ALT\" from FIELD.
|
||||
Move point to the end of the last field."
|
||||
(let (alist bounds)
|
||||
(when (looking-at bibtex-entry-maybe-empty-head)
|
||||
(push (cons "=type=" (match-string bibtex-type-in-head)) alist)
|
||||
(push (cons "=key=" (match-string bibtex-key-in-head)) alist)
|
||||
(goto-char (match-end 0))
|
||||
(while (setq bounds (bibtex-parse-field bibtex-field-name))
|
||||
(push (cons (bibtex-name-in-field bounds)
|
||||
(push (cons (bibtex-name-in-field bounds t)
|
||||
(bibtex-text-in-field-bounds bounds))
|
||||
alist)
|
||||
(goto-char (bibtex-end-of-field bounds))))
|
||||
@ -2770,7 +2823,7 @@ TEXT may be nil. Move point to the end of the last field."
|
||||
(bibtex-beginning-of-entry)
|
||||
(when (and
|
||||
(looking-at bibtex-entry-head)
|
||||
(equal type (match-string bibtex-type-in-head))
|
||||
(bibtex-string= type (match-string bibtex-type-in-head))
|
||||
;; In case we found ourselves :-(
|
||||
(not (equal key (setq tmp (match-string bibtex-key-in-head)))))
|
||||
(setq other-key tmp)
|
||||
@ -2780,7 +2833,7 @@ TEXT may be nil. Move point to the end of the last field."
|
||||
(bibtex-skip-to-valid-entry)
|
||||
(when (and
|
||||
(looking-at bibtex-entry-head)
|
||||
(equal type (match-string bibtex-type-in-head))
|
||||
(bibtex-string= type (match-string bibtex-type-in-head))
|
||||
;; In case we found ourselves :-(
|
||||
(not (equal key (setq tmp (match-string bibtex-key-in-head))))
|
||||
(or (not other-key)
|
||||
@ -2794,11 +2847,8 @@ TEXT may be nil. Move point to the end of the last field."
|
||||
(setq other (save-excursion (goto-char other) (bibtex-parse-entry)))
|
||||
(setq key-end (point)) ;In case parse-entry changed the buffer.
|
||||
(while (setq bounds (bibtex-parse-field bibtex-field-name))
|
||||
(goto-char (bibtex-start-of-name-in-field bounds))
|
||||
(let* ((name (buffer-substring
|
||||
(if (looking-at "ALT\\|OPT") (match-end 0) (point))
|
||||
(bibtex-end-of-name-in-field bounds)))
|
||||
(text (assoc-string name other t)))
|
||||
(let ((text (assoc-string (bibtex-name-in-field bounds t)
|
||||
other t)))
|
||||
(goto-char (bibtex-start-of-text-in-field bounds))
|
||||
(if (not (and (looking-at bibtex-empty-field-re) text))
|
||||
(goto-char (bibtex-end-of-field bounds))
|
||||
@ -2821,13 +2871,7 @@ TEXT may be nil. Move point to the end of the last field."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(let* ((case-fold-search t)
|
||||
(bounds (bibtex-enclosing-field))
|
||||
(mb (bibtex-start-of-name-in-field bounds))
|
||||
(field-name (buffer-substring-no-properties
|
||||
(if (progn (goto-char mb)
|
||||
(looking-at "OPT\\|ALT"))
|
||||
(match-end 0) mb)
|
||||
(bibtex-end-of-name-in-field bounds)))
|
||||
(field-name (bibtex-name-in-field (bibtex-enclosing-field) t))
|
||||
(field-list (bibtex-field-list (progn (re-search-backward
|
||||
bibtex-entry-maybe-empty-head nil t)
|
||||
(bibtex-type-in-head))))
|
||||
@ -2868,16 +2912,16 @@ FIELD is either a string or a list of the form
|
||||
(indent-to-column (+ bibtex-entry-offset
|
||||
(- bibtex-text-indentation 2))))
|
||||
(insert "= ")
|
||||
(if (not bibtex-align-at-equal-sign)
|
||||
(unless bibtex-align-at-equal-sign
|
||||
(indent-to-column (+ bibtex-entry-offset
|
||||
bibtex-text-indentation)))
|
||||
(if (not called-by-yank) (insert (bibtex-field-left-delimiter)))
|
||||
(unless called-by-yank (insert (bibtex-field-left-delimiter)))
|
||||
(let ((init (nth 2 field)))
|
||||
(cond ((stringp init)
|
||||
(insert init))
|
||||
((fboundp init)
|
||||
(insert (funcall init)))))
|
||||
(if (not called-by-yank) (insert (bibtex-field-right-delimiter)))
|
||||
(unless called-by-yank (insert (bibtex-field-right-delimiter)))
|
||||
(when (interactive-p)
|
||||
(forward-char -1)
|
||||
(bibtex-print-help-message)))
|
||||
@ -3084,13 +3128,17 @@ entry."
|
||||
(error "This entry must not follow the crossrefed entry!"))
|
||||
(goto-char pos)))
|
||||
|
||||
(defun bibtex-find-entry (key)
|
||||
(defun bibtex-find-entry (key &optional start)
|
||||
"Move point to the beginning of BibTeX entry named KEY.
|
||||
Return position of entry if KEY is found or nil if not found."
|
||||
(interactive (list (bibtex-read-key "Find key: ")))
|
||||
Return position of entry if KEY is found or nil if not found.
|
||||
Optional arg START is buffer position where the search starts.
|
||||
If it is nil, start search at beginning of buffer.
|
||||
With prefix arg, the value of START is position of point."
|
||||
(interactive (list (bibtex-read-key "Find key: ")
|
||||
(if current-prefix-arg (point))))
|
||||
(let* (case-fold-search
|
||||
(pnt (save-excursion
|
||||
(goto-char (point-min))
|
||||
(goto-char (or start (point-min)))
|
||||
(if (re-search-forward (concat "^[ \t]*\\("
|
||||
bibtex-entry-type
|
||||
"\\)[ \t]*[({][ \t\n]*\\("
|
||||
@ -3157,8 +3205,7 @@ Return t if preparation was successful or nil if entry KEY already exists."
|
||||
;; buffer contains no valid entries or
|
||||
;; greater than last entry --> append
|
||||
(bibtex-end-of-entry)
|
||||
(if (not (bobp))
|
||||
(newline (forward-line 2)))
|
||||
(unless (bobp) (newline (forward-line 2)))
|
||||
(beginning-of-line)))))
|
||||
(unless key-exist t)))
|
||||
|
||||
@ -3233,9 +3280,7 @@ Returns t if test was successful, nil otherwise."
|
||||
(goto-char (point-min))
|
||||
(bibtex-progress-message
|
||||
"Checking required fields and month fields")
|
||||
(let ((bibtex-sort-ignore-string-entries t)
|
||||
(questionable-month
|
||||
(regexp-opt (mapcar 'car bibtex-predefined-month-strings))))
|
||||
(let ((bibtex-sort-ignore-string-entries t))
|
||||
(bibtex-map-entries
|
||||
(lambda (key beg end)
|
||||
(bibtex-progress-message)
|
||||
@ -3251,17 +3296,16 @@ Returns t if test was successful, nil otherwise."
|
||||
(while (setq bounds (bibtex-search-forward-field
|
||||
bibtex-field-name end))
|
||||
(goto-char (bibtex-start-of-text-in-field bounds))
|
||||
(let ((field-name (downcase (bibtex-name-in-field bounds)))
|
||||
case-fold-search)
|
||||
(if (and (equal field-name "month")
|
||||
(not (string-match questionable-month
|
||||
(bibtex-text-in-field-bounds bounds))))
|
||||
(let ((field-name (bibtex-name-in-field bounds)))
|
||||
(if (and (bibtex-string= field-name "month")
|
||||
(not (assoc-string (bibtex-text-in-field-bounds bounds)
|
||||
bibtex-predefined-month-strings t)))
|
||||
(push (list (bibtex-current-line)
|
||||
"Questionable month field")
|
||||
error-list))
|
||||
(setq req (delete (assoc-string field-name req t) req)
|
||||
creq (delete (assoc-string field-name creq t) creq))
|
||||
(if (equal field-name "crossref")
|
||||
(if (bibtex-string= field-name "crossref")
|
||||
(setq crossref-there t))))
|
||||
(if crossref-there
|
||||
(setq req creq))
|
||||
@ -3305,10 +3349,6 @@ Returns t if test was successful, nil otherwise."
|
||||
(dolist (err error-list)
|
||||
(insert bufnam ":" (number-to-string (elt err 0))
|
||||
": " (elt err 1) "\n"))
|
||||
(compilation-parse-errors nil nil)
|
||||
(setq compilation-old-error-list compilation-error-list)
|
||||
;; this is necessary to avoid reparsing of buffer if you
|
||||
;; switch to compilation buffer and enter `compile-goto-error'
|
||||
(set-buffer-modified-p nil)
|
||||
(toggle-read-only 1)
|
||||
(goto-char (point-min))
|
||||
@ -3395,11 +3435,13 @@ Align text and go thereafter to end of text."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(bibtex-inside-field)
|
||||
(let ((bounds (bibtex-enclosing-field)))
|
||||
(goto-char (bibtex-start-of-text-in-field bounds))
|
||||
(delete-char 1)
|
||||
(goto-char (1- (bibtex-end-of-text-in-field bounds)))
|
||||
(delete-backward-char 1))))
|
||||
(let* ((bounds (bibtex-enclosing-field))
|
||||
(end (bibtex-end-of-text-in-field bounds))
|
||||
(start (bibtex-start-of-text-in-field bounds)))
|
||||
(if (memq (char-before end) '(?\} ?\"))
|
||||
(delete-region (1- end) end))
|
||||
(if (memq (char-after start) '(?\{ ?\"))
|
||||
(delete-region start (1+ start))))))
|
||||
|
||||
(defun bibtex-kill-field (&optional copy-only)
|
||||
"Kill the entire enclosing BibTeX field.
|
||||
@ -3455,6 +3497,7 @@ With prefix arg COPY-ONLY the current entry to
|
||||
(setq bibtex-last-kill-command 'entry))
|
||||
|
||||
(defun bibtex-copy-entry-as-kill ()
|
||||
"Copy the entire enclosing BibTeX entry to `bibtex-entry-kill-ring'."
|
||||
(interactive)
|
||||
(bibtex-kill-entry t))
|
||||
|
||||
@ -3482,7 +3525,7 @@ If N is negative, this is a more recent kill.
|
||||
The sequence of kills wraps around, so that after the oldest one
|
||||
comes the newest one."
|
||||
(interactive "*p")
|
||||
(if (not (eq last-command 'bibtex-yank))
|
||||
(unless (eq last-command 'bibtex-yank)
|
||||
(error "Previous command was not a BibTeX yank"))
|
||||
(setq this-command 'bibtex-yank)
|
||||
(let ((inhibit-read-only t))
|
||||
@ -3533,19 +3576,20 @@ At end of the cleaning process, the functions in
|
||||
(bibtex-beginning-of-entry)
|
||||
(save-excursion
|
||||
(when (re-search-forward bibtex-entry-maybe-empty-head nil t)
|
||||
(setq entry-type (downcase (bibtex-type-in-head)))
|
||||
(setq entry-type (bibtex-type-in-head))
|
||||
(setq key (bibtex-key-in-head))))
|
||||
;; formatting
|
||||
(cond ((equal entry-type "preamble")
|
||||
(cond ((bibtex-string= entry-type "preamble")
|
||||
;; (bibtex-format-preamble)
|
||||
(error "No clean up of @Preamble entries"))
|
||||
((equal entry-type "string"))
|
||||
((bibtex-string= entry-type "string"))
|
||||
;; (bibtex-format-string)
|
||||
(t (bibtex-format-entry)))
|
||||
;; set key
|
||||
(when (or new-key (not key))
|
||||
(setq key (bibtex-generate-autokey))
|
||||
(if bibtex-autokey-edit-before-use
|
||||
;; Sometimes bibtex-generate-autokey returns an empty string
|
||||
(if (or bibtex-autokey-edit-before-use (string= "" key))
|
||||
(setq key (bibtex-read-key "Key to use: " key)))
|
||||
(re-search-forward bibtex-entry-maybe-empty-head)
|
||||
(if (match-beginning bibtex-key-in-head)
|
||||
@ -3563,19 +3607,21 @@ At end of the cleaning process, the functions in
|
||||
(entry (buffer-substring start end))
|
||||
(index (progn (goto-char start)
|
||||
(bibtex-entry-index)))
|
||||
no-error)
|
||||
error)
|
||||
(if (and bibtex-maintain-sorted-entries
|
||||
(not (and bibtex-sort-ignore-string-entries
|
||||
(equal entry-type "string"))))
|
||||
(bibtex-string= entry-type "string"))))
|
||||
(progn
|
||||
(delete-region start end)
|
||||
(setq no-error (bibtex-prepare-new-entry index))
|
||||
(setq error (not (bibtex-prepare-new-entry index)))
|
||||
(insert entry)
|
||||
(forward-char -1)
|
||||
(bibtex-beginning-of-entry) ; moves backward
|
||||
(re-search-forward bibtex-entry-head))
|
||||
(setq no-error (bibtex-find-entry (car index))))
|
||||
(unless no-error
|
||||
(bibtex-find-entry key)
|
||||
(setq error (or (/= (point) start)
|
||||
(bibtex-find-entry key end))))
|
||||
(if error
|
||||
(error "New inserted entry yields duplicate key"))))
|
||||
;; final clean up
|
||||
(unless called-by-reformat
|
||||
@ -3583,7 +3629,7 @@ At end of the cleaning process, the functions in
|
||||
(save-restriction
|
||||
(bibtex-narrow-to-entry)
|
||||
;; Only update the list of keys if it has been built already.
|
||||
(cond ((equal entry-type "string")
|
||||
(cond ((bibtex-string= entry-type "string")
|
||||
(if (listp bibtex-strings) (bibtex-parse-strings t)))
|
||||
((listp bibtex-reference-keys) (bibtex-parse-keys t)))
|
||||
(run-hooks 'bibtex-clean-entry-hook))))))
|
||||
@ -3752,28 +3798,29 @@ entries from minibuffer."
|
||||
(defun bibtex-complete ()
|
||||
"Complete word fragment before point according to context.
|
||||
If point is inside key or crossref field perform key completion based on
|
||||
`bibtex-reference-keys'. Inside any other field perform string
|
||||
completion based on `bibtex-strings'. An error is signaled if point
|
||||
is outside key or BibTeX field."
|
||||
`bibtex-reference-keys'. Inside a month field perform key completion
|
||||
based on `bibtex-predefined-month-strings'. Inside any other field
|
||||
perform string completion based on `bibtex-strings'. An error is
|
||||
signaled if point is outside key or BibTeX field."
|
||||
(interactive)
|
||||
(let* ((pnt (point))
|
||||
(let ((pnt (point))
|
||||
(case-fold-search t)
|
||||
bounds compl)
|
||||
bounds name compl)
|
||||
(save-excursion
|
||||
(if (and (setq bounds (bibtex-enclosing-field t))
|
||||
(>= pnt (bibtex-start-of-text-in-field bounds))
|
||||
(<= pnt (bibtex-end-of-text-in-field bounds)))
|
||||
(progn
|
||||
(goto-char (bibtex-start-of-name-in-field bounds))
|
||||
(setq compl (if (string= "crossref"
|
||||
(downcase
|
||||
(buffer-substring-no-properties
|
||||
(if (looking-at "\\(OPT\\)\\|\\(ALT\\)")
|
||||
(match-end 0)
|
||||
(point))
|
||||
(bibtex-end-of-name-in-field bounds))))
|
||||
'key
|
||||
'str)))
|
||||
(setq name (bibtex-name-in-field bounds t)
|
||||
compl (cond ((bibtex-string= name "crossref")
|
||||
'key)
|
||||
((bibtex-string= name "month")
|
||||
bibtex-predefined-month-strings)
|
||||
(t (if (listp bibtex-strings)
|
||||
bibtex-strings
|
||||
;; so that bibtex-complete-string-cleanup
|
||||
;; can do its job
|
||||
(bibtex-parse-strings
|
||||
(bibtex-string-files-init))))))
|
||||
(bibtex-beginning-of-entry)
|
||||
(if (and (re-search-forward bibtex-entry-maybe-empty-head nil t)
|
||||
;; point is inside a key
|
||||
@ -3790,23 +3837,22 @@ is outside key or BibTeX field."
|
||||
(setq choose-completion-string-functions
|
||||
(lambda (choice buffer mini-p base-size)
|
||||
(bibtex-choose-completion-string choice buffer mini-p base-size)
|
||||
(if bibtex-complete-key-cleanup
|
||||
(funcall bibtex-complete-key-cleanup choice))
|
||||
(bibtex-complete-key-cleanup choice)
|
||||
;; return t (required by choose-completion-string-functions)
|
||||
t))
|
||||
(let ((choice (bibtex-complete-internal bibtex-reference-keys)))
|
||||
(if bibtex-complete-key-cleanup
|
||||
(funcall bibtex-complete-key-cleanup choice))))
|
||||
(bibtex-complete-key-cleanup (bibtex-complete-internal
|
||||
bibtex-reference-keys)))
|
||||
|
||||
((equal compl 'str)
|
||||
(compl
|
||||
;; string completion
|
||||
(setq choose-completion-string-functions
|
||||
(lambda (choice buffer mini-p base-size)
|
||||
`(lambda (choice buffer mini-p base-size)
|
||||
(bibtex-choose-completion-string choice buffer mini-p base-size)
|
||||
(bibtex-complete-string-cleanup choice)
|
||||
(bibtex-complete-string-cleanup choice ',compl)
|
||||
;; return t (required by choose-completion-string-functions)
|
||||
t))
|
||||
(bibtex-complete-string-cleanup (bibtex-complete-internal bibtex-strings)))
|
||||
(bibtex-complete-string-cleanup (bibtex-complete-internal compl)
|
||||
compl))
|
||||
|
||||
(t (error "Point outside key or BibTeX field")))))
|
||||
|
||||
@ -3880,7 +3926,7 @@ is outside key or BibTeX field."
|
||||
(interactive (list (completing-read "String key: " bibtex-strings
|
||||
nil nil nil 'bibtex-key-history)))
|
||||
(let ((bibtex-maintain-sorted-entries
|
||||
(if (not bibtex-sort-ignore-string-entries)
|
||||
(unless bibtex-sort-ignore-string-entries
|
||||
bibtex-maintain-sorted-entries))
|
||||
endpos)
|
||||
(unless (bibtex-prepare-new-entry (list key nil "String"))
|
||||
@ -3913,6 +3959,86 @@ is outside key or BibTeX field."
|
||||
"\n")
|
||||
(goto-char endpos)))
|
||||
|
||||
(defun bibtex-url (&optional event)
|
||||
"Browse a URL for the BibTeX entry at position PNT.
|
||||
The URL is generated using the schemes defined in `bibtex-generate-url-list'
|
||||
\(see there\). Then the URL is passed to `browse-url'."
|
||||
(interactive (list last-input-event))
|
||||
(save-excursion
|
||||
(if event (posn-set-point (event-end event)))
|
||||
(bibtex-beginning-of-entry)
|
||||
(let ((fields-alist (bibtex-parse-entry))
|
||||
(case-fold-search t)
|
||||
(lst bibtex-generate-url-list)
|
||||
field url scheme)
|
||||
(while (setq scheme (car lst))
|
||||
(when (and (setq field (assoc-string (caar scheme) fields-alist t))
|
||||
(or (eq t (cdar scheme))
|
||||
(string-match (cdar scheme) (cdr field))))
|
||||
(setq lst nil)
|
||||
(dolist (step (cdr scheme))
|
||||
(cond ((stringp step)
|
||||
(setq url (concat url step)))
|
||||
((setq field (assoc-string (car step) fields-alist t))
|
||||
;; always remove field delimiters
|
||||
(let* ((text (if (string-match "\\`[{\"]\\(.*\\)[}\"]\\'"
|
||||
(cdr field))
|
||||
(match-string 1 (cdr field))
|
||||
(cdr field)))
|
||||
(str (cond ((eq t (nth 1 step))
|
||||
text)
|
||||
((and (consp (nth 1 step))
|
||||
(string-match (car (nth 1 step))
|
||||
text))
|
||||
(if (numberp (cdr (nth 1 step)))
|
||||
(match-string (cdr (nth 1 step))
|
||||
text)
|
||||
(replace-match (cdr (nth 1 step))
|
||||
nil nil text)))
|
||||
;; If the scheme is set up correctly,
|
||||
;; we should never reach this point
|
||||
(t (error "Match failed: %s" text)))))
|
||||
(setq url (concat url (if (fboundp (nth 2 step))
|
||||
(funcall (nth 2 step) str)
|
||||
str)))))
|
||||
;; If the scheme is set up correctly,
|
||||
;; we should never reach this point
|
||||
(t (error "Step failed: %s" step))))
|
||||
(message "%s" url)
|
||||
(browse-url url))
|
||||
(setq lst (cdr lst)))
|
||||
(unless url (message "No URL known.")))))
|
||||
|
||||
(defun bibtex-font-lock-url (bound)
|
||||
"Font-lock for URLs."
|
||||
(let ((case-fold-search t)
|
||||
(bounds (bibtex-enclosing-field t))
|
||||
(pnt (point))
|
||||
found url)
|
||||
;; We use start-of-field as syntax-begin
|
||||
(goto-char (if bounds (bibtex-start-of-field bounds) pnt))
|
||||
(while (and (not found)
|
||||
(search-forward-regexp bibtex-font-lock-url-regexp bound t)
|
||||
(save-match-data (setq bounds (bibtex-parse-field-text)))
|
||||
(>= bound (car bounds)))
|
||||
(let ((field (match-string-no-properties 1))
|
||||
(lst bibtex-generate-url-list))
|
||||
(while (and (not found)
|
||||
(setq url (caar lst)))
|
||||
(when (bibtex-string= field (car url))
|
||||
(if (eq t (cdr url))
|
||||
(progn
|
||||
(goto-char (min bound (cdr bounds)))
|
||||
(set-match-data (list (car bounds) (point)))
|
||||
(setq found t))
|
||||
(goto-char (car bounds))
|
||||
(setq found (search-forward-regexp (cdr url)
|
||||
(min bound (cdr bounds)) t)))
|
||||
(if (< (match-beginning 0) pnt)
|
||||
(setq found nil)))
|
||||
(setq lst (cdr lst)))))
|
||||
found))
|
||||
|
||||
|
||||
;; Make BibTeX a Feature
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user