diff options
| author | Roland Winkler | 2012-01-28 12:06:10 -0600 |
|---|---|---|
| committer | Roland Winkler | 2012-01-28 12:06:10 -0600 |
| commit | ace88aa20f32b298e7f2e8e6115b5661504f8724 (patch) | |
| tree | 9bdc93585e14c26266180dc5c9658379f082ca12 | |
| parent | 6e9bad1452282beabc27140cd83b6b8b17ec74d6 (diff) | |
| download | emacs-ace88aa20f32b298e7f2e8e6115b5661504f8724.tar.gz emacs-ace88aa20f32b298e7f2e8e6115b5661504f8724.zip | |
lisp/textmodes/bibtex.el: allow bibtex-dialect as file-local variable (Bug#10254)
| -rw-r--r-- | lisp/ChangeLog | 15 | ||||
| -rw-r--r-- | lisp/textmodes/bibtex.el | 227 |
2 files changed, 140 insertions, 102 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index e48f16ff8ce..51c56159688 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,18 @@ | |||
| 1 | 2012-01-28 Roland Winkler <winkler@gnu.org> | ||
| 2 | |||
| 3 | * textmodes/bibtex.el (bibtex-entry-alist): New function. | ||
| 4 | (bibtex-set-dialect): Use it. Either set global values of | ||
| 5 | dialect-dependent variables or bind these variables buffer-locally | ||
| 6 | (Bug#10254). | ||
| 7 | (bibtex-mode): Call bibtex-set-dialect via | ||
| 8 | hack-local-variables-hook. | ||
| 9 | (bibtex-dialect): Update docstring. Add | ||
| 10 | safe-local-variable predicate. | ||
| 11 | (bibtex-entry-alist, bibtex-field-alist): Initialize via | ||
| 12 | bibtex-set-dialect. | ||
| 13 | (bibtex-mode-map): Define menu for each dialect. | ||
| 14 | (bibtex-entry): Fix docstring. | ||
| 15 | |||
| 1 | 2012-01-28 Chong Yidong <cyd@gnu.org> | 16 | 2012-01-28 Chong Yidong <cyd@gnu.org> |
| 2 | 17 | ||
| 3 | * eshell/esh-arg.el (eshell-quote-argument): New function. | 18 | * eshell/esh-arg.el (eshell-quote-argument): New function. |
diff --git a/lisp/textmodes/bibtex.el b/lisp/textmodes/bibtex.el index 955e148a2ab..292446ea24f 100644 --- a/lisp/textmodes/bibtex.el +++ b/lisp/textmodes/bibtex.el | |||
| @@ -826,7 +826,7 @@ Predefined dialects include BibTeX and biblatex." | |||
| 826 | 826 | ||
| 827 | (defcustom bibtex-dialect 'BibTeX | 827 | (defcustom bibtex-dialect 'BibTeX |
| 828 | "Current BibTeX dialect. For allowed values see `bibtex-dialect-list'. | 828 | "Current BibTeX dialect. For allowed values see `bibtex-dialect-list'. |
| 829 | During a session change it via `bibtex-set-dialect'." | 829 | To interactively change the dialect use the command `bibtex-set-dialect'." |
| 830 | :group 'bibtex | 830 | :group 'bibtex |
| 831 | :set '(lambda (symbol value) | 831 | :set '(lambda (symbol value) |
| 832 | (set-default symbol value) | 832 | (set-default symbol value) |
| @@ -836,6 +836,7 @@ During a session change it via `bibtex-set-dialect'." | |||
| 836 | :type '(choice (const BibTeX) | 836 | :type '(choice (const BibTeX) |
| 837 | (const biblatex) | 837 | (const biblatex) |
| 838 | (symbol :tag "Custom"))) | 838 | (symbol :tag "Custom"))) |
| 839 | (put 'bibtex-dialect 'safe-local-variable 'symbolp) | ||
| 839 | 840 | ||
| 840 | (defcustom bibtex-no-opt-remove-re "\\`option" | 841 | (defcustom bibtex-no-opt-remove-re "\\`option" |
| 841 | "If a field name matches this regexp, the prefix OPT is not removed. | 842 | "If a field name matches this regexp, the prefix OPT is not removed. |
| @@ -1442,11 +1443,13 @@ Set this variable before loading BibTeX mode." | |||
| 1442 | 1443 | ||
| 1443 | ;; Internal Variables | 1444 | ;; Internal Variables |
| 1444 | 1445 | ||
| 1445 | (defvar bibtex-entry-alist bibtex-BibTeX-entry-alist | 1446 | (defvar bibtex-entry-alist nil |
| 1446 | "Alist of currently active entry types.") | 1447 | "Alist of currently active entry types. |
| 1448 | Initialized by `bibtex-set-dialect'.") | ||
| 1447 | 1449 | ||
| 1448 | (defvar bibtex-field-alist bibtex-BibTeX-field-alist | 1450 | (defvar bibtex-field-alist nil |
| 1449 | "Alist of currently active field types.") | 1451 | "Alist of currently active field types. |
| 1452 | Initialized by `bibtex-set-dialect'.") | ||
| 1450 | 1453 | ||
| 1451 | (defvar bibtex-field-braces-opt nil | 1454 | (defvar bibtex-field-braces-opt nil |
| 1452 | "Optimized value of `bibtex-field-braces-alist'. | 1455 | "Optimized value of `bibtex-field-braces-alist'. |
| @@ -3376,104 +3379,124 @@ if that value is non-nil. | |||
| 3376 | (setq imenu-generic-expression | 3379 | (setq imenu-generic-expression |
| 3377 | (list (list nil bibtex-entry-head bibtex-key-in-head)) | 3380 | (list (list nil bibtex-entry-head bibtex-key-in-head)) |
| 3378 | imenu-case-fold-search t) | 3381 | imenu-case-fold-search t) |
| 3379 | (bibtex-set-dialect bibtex-dialect)) | 3382 | ;; Allow `bibtex-dialect' as a file-local variable. |
| 3380 | 3383 | (add-hook 'hack-local-variables-hook 'bibtex-set-dialect nil t)) | |
| 3381 | (defun bibtex-set-dialect (dialect) | 3384 | |
| 3382 | "Select BibTeX mode DIALECT. | 3385 | (defun bibtex-entry-alist (dialect) |
| 3383 | This sets the variable `bibtex-dialect' which holds the currently active | 3386 | "Return entry-alist for DIALECT." |
| 3384 | dialect. Dialects are listed in `bibtex-dialect-list'." | 3387 | (let ((var (intern (format "bibtex-%s-entry-alist" dialect))) |
| 3388 | entry-alist) | ||
| 3389 | (if (boundp var) | ||
| 3390 | (setq entry-alist (symbol-value var)) | ||
| 3391 | (error "BibTeX dialect `%s' undefined" dialect)) | ||
| 3392 | (if (not (consp (nth 1 (car entry-alist)))) | ||
| 3393 | ;; new format | ||
| 3394 | entry-alist | ||
| 3395 | ;; Convert old format of `bibtex-entry-field-alist' | ||
| 3396 | (unless (get var 'entry-list-format) | ||
| 3397 | (put var 'entry-list-format "pre-24") | ||
| 3398 | (message "Old format of `%s' (pre GNU Emacs 24). | ||
| 3399 | Please convert to the new format." | ||
| 3400 | (if (eq (indirect-variable 'bibtex-entry-field-alist) var) | ||
| 3401 | 'bibtex-entry-field-alist var)) | ||
| 3402 | (sit-for 3)) | ||
| 3403 | (let (lst) | ||
| 3404 | (dolist (entry entry-alist) | ||
| 3405 | (let ((fl (nth 1 entry)) req xref opt) | ||
| 3406 | (dolist (field (copy-tree (car fl))) | ||
| 3407 | (if (nth 3 field) (setcar (nthcdr 3 field) 0)) | ||
| 3408 | (if (or (not (nth 2 entry)) | ||
| 3409 | (assoc-string (car field) (car (nth 2 entry)) t)) | ||
| 3410 | (push field req) | ||
| 3411 | (push field xref))) | ||
| 3412 | (dolist (field (nth 1 fl)) | ||
| 3413 | (push field opt)) | ||
| 3414 | (push (list (car entry) nil (nreverse req) | ||
| 3415 | (nreverse xref) (nreverse opt)) | ||
| 3416 | lst))) | ||
| 3417 | (nreverse lst))))) | ||
| 3418 | |||
| 3419 | (defun bibtex-set-dialect (&optional dialect local) | ||
| 3420 | "Select BibTeX DIALECT for editing BibTeX files. | ||
| 3421 | This sets the user variable `bibtex-dialect' as well as the dialect-dependent | ||
| 3422 | internal variables. Allowed dialects are listed in `bibtex-dialect-list'. | ||
| 3423 | If DIALECT is nil use current value of `bibtex-dialect'. | ||
| 3424 | If LOCAL is non-nil make buffer-local bindings for these variables rather than | ||
| 3425 | setting the global values. The dialect-dependent internal variables | ||
| 3426 | are also bound buffer-locally if `bibtex-dialect' is already buffer-local | ||
| 3427 | in the current buffer (for example, as a file-local variable). | ||
| 3428 | LOCAL is t for interactive calls." | ||
| 3385 | (interactive (list (intern (completing-read "Dialect: " | 3429 | (interactive (list (intern (completing-read "Dialect: " |
| 3386 | (mapcar 'list bibtex-dialect-list) | 3430 | (mapcar 'list bibtex-dialect-list) |
| 3387 | nil t)))) | 3431 | nil t)) t)) |
| 3388 | (unless (eq dialect (get 'bibtex-dialect 'dialect)) | 3432 | (let ((setfun (if (or local (local-variable-p 'bibtex-dialect)) |
| 3389 | (put 'bibtex-dialect 'dialect dialect) | 3433 | (lambda (var val) (set (make-local-variable var) val)) |
| 3390 | (setq bibtex-dialect dialect) | 3434 | 'set))) |
| 3391 | 3435 | (if dialect (funcall setfun 'bibtex-dialect dialect)) | |
| 3392 | ;; Bind variables | 3436 | |
| 3393 | (setq bibtex-entry-alist | 3437 | ;; Set internal variables |
| 3394 | (let ((var (intern (format "bibtex-%s-entry-alist" dialect))) | 3438 | (funcall setfun 'bibtex-entry-alist (bibtex-entry-alist bibtex-dialect)) |
| 3395 | entry-alist) | 3439 | (funcall setfun 'bibtex-field-alist |
| 3396 | (if (boundp var) | 3440 | (let ((var (intern (format "bibtex-%s-field-alist" |
| 3397 | (setq entry-alist (symbol-value var)) | 3441 | bibtex-dialect)))) |
| 3398 | (error "BibTeX dialect `%s' undefined" dialect)) | 3442 | (if (boundp var) |
| 3399 | (if (not (consp (nth 1 (car entry-alist)))) | 3443 | (symbol-value var) |
| 3400 | ;; new format | 3444 | (error "Field types for BibTeX dialect `%s' undefined" |
| 3401 | entry-alist | 3445 | bibtex-dialect)))) |
| 3402 | ;; Convert old format | 3446 | (funcall setfun 'bibtex-entry-type |
| 3403 | (unless (get var 'entry-list-format) | 3447 | (concat "@[ \t]*\\(?:" |
| 3404 | (put var 'entry-list-format "pre-24") | 3448 | (regexp-opt (mapcar 'car bibtex-entry-alist)) "\\)")) |
| 3405 | (message "Old format of `%s' (pre GNU Emacs 24). | 3449 | (funcall setfun 'bibtex-entry-head |
| 3406 | Please convert to the new format." | 3450 | (concat "^[ \t]*\\(" bibtex-entry-type "\\)[ \t]*[({][ \t\n]*\\(" |
| 3407 | (if (eq (indirect-variable 'bibtex-entry-field-alist) var) | 3451 | bibtex-reference-key "\\)")) |
| 3408 | 'bibtex-entry-field-alist var)) | 3452 | (funcall setfun 'bibtex-entry-maybe-empty-head |
| 3409 | (sit-for 3)) | 3453 | (concat bibtex-entry-head "?")) |
| 3410 | (let (lst) | 3454 | (funcall setfun 'bibtex-any-valid-entry-type |
| 3411 | (dolist (entry entry-alist) | 3455 | (concat "^[ \t]*@[ \t]*\\(?:" |
| 3412 | (let ((fl (nth 1 entry)) req xref opt) | 3456 | (regexp-opt |
| 3413 | (dolist (field (copy-tree (car fl))) | 3457 | (append '("String" "Preamble") |
| 3414 | (if (nth 3 field) (setcar (nthcdr 3 field) 0)) | 3458 | (mapcar 'car bibtex-entry-alist))) "\\)")))) |
| 3415 | (if (or (not (nth 2 entry)) | 3459 | |
| 3416 | (assoc-string (car field) (car (nth 2 entry)) t)) | 3460 | ;; Entry commands and menus for BibTeX dialects |
| 3417 | (push field req) | 3461 | ;; We do not use `easy-menu-define' here because this gets confused |
| 3418 | (push field xref))) | 3462 | ;; if we want to have multiple versions of the "same" menu. |
| 3419 | (dolist (field (nth 1 fl)) | 3463 | (let ((select-map (make-sparse-keymap))) |
| 3420 | (push field opt)) | 3464 | ;; Submenu for selecting the dialect |
| 3421 | (push (list (car entry) nil (nreverse req) | 3465 | (dolist (dialect (reverse bibtex-dialect-list)) |
| 3422 | (nreverse xref) (nreverse opt)) | 3466 | (define-key select-map (vector dialect) |
| 3423 | lst))) | 3467 | `(menu-item ,(symbol-name dialect) |
| 3424 | (nreverse lst)))) | 3468 | (lambda () (interactive) (bibtex-set-dialect ',dialect t)) |
| 3425 | bibtex-field-alist | 3469 | :button (:radio . (eq bibtex-dialect ',dialect))))) |
| 3426 | (let ((var (intern (format "bibtex-%s-field-alist" dialect)))) | 3470 | ;; We define a menu for each dialect. |
| 3427 | (if (boundp var) | 3471 | ;; Then we select the menu we want via the :visible keyword |
| 3428 | (symbol-value var) | 3472 | (dolist (dialect bibtex-dialect-list) |
| 3429 | (error "Field types for BibTeX dialect `%s' undefined" dialect))) | 3473 | (let ((entry-alist (bibtex-entry-alist dialect)) |
| 3430 | bibtex-entry-type | 3474 | (menu-map (make-sparse-keymap))) |
| 3431 | (concat "@[ \t]*\\(?:" | 3475 | (define-key menu-map [select] |
| 3432 | (regexp-opt (mapcar 'car bibtex-entry-alist)) "\\)") | 3476 | `(menu-item "BibTeX dialect" ,select-map)) |
| 3433 | bibtex-entry-head (concat "^[ \t]*\\(" | 3477 | (define-key menu-map [nil-2] '(menu-item "--")) |
| 3434 | bibtex-entry-type | 3478 | (define-key menu-map [bibtex-preamble] |
| 3435 | "\\)[ \t]*[({][ \t\n]*\\(" | 3479 | '(menu-item "Preamble" bibtex-Preamble)) |
| 3436 | bibtex-reference-key | 3480 | (define-key menu-map [bibtex-String] |
| 3437 | "\\)") | 3481 | '(menu-item "String" bibtex-String)) |
| 3438 | bibtex-entry-maybe-empty-head (concat bibtex-entry-head "?") | 3482 | (define-key menu-map [nil-1] '(menu-item "--")) |
| 3439 | bibtex-any-valid-entry-type | 3483 | (dolist (elt (reverse entry-alist)) |
| 3440 | (concat "^[ \t]*@[ \t]*\\(?:" | 3484 | ;; Entry commands |
| 3441 | (regexp-opt (append '("String" "Preamble") | 3485 | (let* ((entry (car elt)) |
| 3442 | (mapcar 'car bibtex-entry-alist))) "\\)")) | 3486 | (fname (intern (format "bibtex-%s" entry)))) |
| 3443 | ;; Define entry commands | 3487 | (unless (fboundp fname) |
| 3444 | (dolist (elt bibtex-entry-alist) | 3488 | (eval (list 'defun fname nil |
| 3445 | (let* ((entry (car elt)) | 3489 | (format "Insert a template for a @%s entry; see also `bibtex-entry'." |
| 3446 | (fname (intern (concat "bibtex-" entry)))) | 3490 | entry) |
| 3447 | (unless (fboundp fname) | 3491 | '(interactive "*") |
| 3448 | (eval (list 'defun fname nil | 3492 | `(bibtex-entry ,entry)))) |
| 3449 | (format "Insert a new BibTeX @%s entry; see also `bibtex-entry'." | 3493 | ;; Menu entries |
| 3450 | entry) | 3494 | (define-key menu-map (vector fname) |
| 3451 | '(interactive "*") | 3495 | `(menu-item ,(or (nth 1 elt) (car elt)) ,fname)))) |
| 3452 | `(bibtex-entry ,entry)))))) | 3496 | (define-key bibtex-mode-map |
| 3453 | ;; Define menu | 3497 | (vector 'menu-bar dialect) |
| 3454 | ;; We use the same keymap for all BibTeX buffers. So all these buffers | 3498 | `(menu-item "Entry-Types" ,menu-map |
| 3455 | ;; have the same BibTeX dialect. To define entry types buffer-locally, | 3499 | :visible (eq bibtex-dialect ',dialect)))))) |
| 3456 | ;; it would be necessary to give each BibTeX buffer a new keymap that | ||
| 3457 | ;; becomes a child of `bibtex-mode-map'. Useful?? | ||
| 3458 | (easy-menu-define | ||
| 3459 | nil bibtex-mode-map "Entry-Types Menu in BibTeX mode" | ||
| 3460 | (apply 'list "Entry-Types" | ||
| 3461 | (append | ||
| 3462 | (mapcar (lambda (entry) | ||
| 3463 | (vector (or (nth 1 entry) (car entry)) | ||
| 3464 | (intern (format "bibtex-%s" (car entry))) t)) | ||
| 3465 | bibtex-entry-alist) | ||
| 3466 | `("---" | ||
| 3467 | ["String" bibtex-String t] | ||
| 3468 | ["Preamble" bibtex-Preamble t] | ||
| 3469 | "---" | ||
| 3470 | ,(append '("BibTeX dialect") | ||
| 3471 | (mapcar (lambda (dialect) | ||
| 3472 | (vector (symbol-name dialect) | ||
| 3473 | `(lambda () (interactive) | ||
| 3474 | (bibtex-set-dialect ',dialect)) | ||
| 3475 | t)) | ||
| 3476 | bibtex-dialect-list)))))))) | ||
| 3477 | 3500 | ||
| 3478 | (defun bibtex-field-list (entry-type) | 3501 | (defun bibtex-field-list (entry-type) |
| 3479 | "Return list of allowed fields for entry ENTRY-TYPE. | 3502 | "Return list of allowed fields for entry ENTRY-TYPE. |
| @@ -3505,7 +3528,7 @@ and `bibtex-user-optional-fields'." | |||
| 3505 | (cons required optional))) | 3528 | (cons required optional))) |
| 3506 | 3529 | ||
| 3507 | (defun bibtex-entry (entry-type) | 3530 | (defun bibtex-entry (entry-type) |
| 3508 | "Insert a new BibTeX entry of type ENTRY-TYPE. | 3531 | "Insert a template for a BibTeX entry of type ENTRY-TYPE. |
| 3509 | After insertion call the value of `bibtex-add-entry-hook' if that value | 3532 | After insertion call the value of `bibtex-add-entry-hook' if that value |
| 3510 | is non-nil." | 3533 | is non-nil." |
| 3511 | (interactive | 3534 | (interactive |