使用 Emacs 的 BibTeX 模式进行 Biblatex 自定义条目

使用 Emacs 的 BibTeX 模式进行 Biblatex 自定义条目

从 24.1 版开始,Emacs 的 BibTeX 模式支持 biblatex 条目。这确实很好用。但是,我大量使用了 biblatex 的可扩展性,使用了自定义条目类型和相应的条目字段,这使得 BibTeX 模式在处理这些条目时不知所措。

在尝试理清这个问题时,我检查bibtex.el并找到了两个可定制的列表,这似乎是可行的方法:bibtex-biblatex-field-alistbibtex-biblatex-entry-alist

因此我对其进行了定制:

(use-package bibtex
  :custom
  (bibtex-dialect (quote biblatex));; biblatex as default bib format

  :config
  ;; Support for custom biblatex entries and fields in BibTeX mode
  (setq my/primary-bibtex-biblatex-field-alist
        '(("shortarchive")))
  (setq bibtex-biblatex-field-alist
        (append bibtex-biblatex-field-alist my/primary-bibtex-biblatex-field-alist))

  (setq my/primary-bibtex-biblatex-entry-alist
        '(("Archive" "Archive"
           (("title"))
           nil
           (("location") ("shortarchive")))))
  (setq bibtex-biblatex-entry-alist
        (append bibtex-biblatex-entry-alist my/primary-bibtex-biblatex-entry-alist)))

支持具有以下结构的 entrytype:

@archive{ID,
  title = {},
  OPTlocation = {},
  OPTshortarchive = {},
}

检查bibtex-biblatex-field-alistbibtex-biblatex-entry-alist表明它们按预期配置,并且确实bibtex-clean-entryC-c C-c预期工作(在定制之前,我收到了Not inside a BibTeX entry错误)。

但是,新的条目类型没有显示在“条目类型”菜单中。此外,与标准条目类型一样,该命令bibtex-Archive不可用M-x。我如何才能同时实现这两点,以便能够为版本插入自定义条目类型的空模板,就像我可以使用通常的条目类型一样?

答案1

就我在网上和 Emacs 内部文档中搜索过的情况而言,我找不到最新的 BibTeX 模式手册(如果有人知道在哪里可以找到它,请告诉我)。bibtex.el当然,里面有文档字符串,它们已经发挥了很大的作用。但是旧版手册由一位善良的灵魂在网上发布。

在那里,我们发现以下关于的评论bibtex-entry-field-alist

如果您想更改这个变量,最好的办法可能是从文件“bibtex.el”获取 BibTeX 模式的源代码,将此变量的定义复制到您的“.emacs”文件中,将其更改为 setq 语句(参见 Emacs Lisp 手册中的“设置变量”部分),然后修改变量的内容。

这肯定是处理这个问题的正确/规范方法。它确实有效。您还可以自定义bibtex-biblatex-field-alistbibtex-biblatex-entry-alist达到相同的效果。

唯一的“问题”是,bibtex-biblatex-entry-alist代码量大约有 250 行,bibtex-biblatex-field-alist另外还有近 90 行。再加上我想添加的代码。在我看来,这相当多。

我最初在问题中提出的方法存在什么问题,即菜单和命令是在加载时构建的bibtex.el,因此使用在那里定义的列表的原始值,而我的appends 来得太晚了,菜单/命令已经构建好了。

重新定义完整列表的另一种方法是在将列表附加到列表后重建菜单/命令。不幸的是,bibtex.el没有将此例程包装到我们可以调用的任何类型的函数中,因此我们必须提供相应的代码。

(use-package bibtex
  :custom
  (bibtex-dialect (quote biblatex));; biblatex as default bib format

  :config
  ;; Support for custom biblatex entries and fields in BibTeX mode
  (setq bibtex-biblatex-field-alist
        (append bibtex-biblatex-field-alist
                '(("shortarchive"))))

  (setq bibtex-biblatex-entry-alist
        (append bibtex-biblatex-entry-alist
                '(("Archive" "Archive"
                   (("title"))
                   nil
                   (("location") ("shortarchive"))))))

  ;; Taken from bibtex.el, the routine that builds the menus etc.
  ;; This must be (re)executed after `bibtex-biblatex-entry-alist` and
  ;; `bibtex-biblatex-field-alist` have been redefined. Alternative is to
  ;; redefine the *full* lists with `setq` in the `:init` section
  (let ((select-map (make-sparse-keymap)))
  ;; Submenu for selecting the dialect
  (dolist (dialect (reverse bibtex-dialect-list))
    (define-key select-map (vector dialect)
      `(menu-item ,(symbol-name dialect)
                  (lambda () (interactive) (bibtex-set-dialect ',dialect t))
                  :button (:radio . (eq bibtex-dialect ',dialect)))))
  ;; We define a menu for each dialect.
  ;; Then we select the menu we want via the :visible keyword
  (dolist (dialect bibtex-dialect-list)
    (let ((entry-alist (bibtex-entry-alist dialect))
          (menu-map (make-sparse-keymap)))
      (define-key menu-map [select]
        `(menu-item "BibTeX dialect" ,select-map))
      (define-key menu-map [nil-2] '(menu-item "--"))
      (define-key menu-map [bibtex-preamble]
        '(menu-item "Preamble" bibtex-Preamble))
      (define-key menu-map [bibtex-String]
        '(menu-item "String" bibtex-String))
      (define-key menu-map [nil-1] '(menu-item "--"))
      (dolist (elt (reverse entry-alist))
        ;; Entry commands
        (let* ((entry (car elt))
               (fname (intern (format "bibtex-%s" entry))))
          (unless (fboundp fname)
            (eval (list 'defun fname nil
                        (format "Insert a template for a @%s entry; see also `bibtex-entry'."
                                entry)
                        '(interactive "*")
                        `(bibtex-entry ,entry))))
          ;; Menu entries
          (define-key menu-map (vector fname)
            `(menu-item ,(or (nth 1 elt) (car elt)) ,fname))))
      (define-key bibtex-mode-map
        (vector 'menu-bar dialect)
        `(menu-item "Entry-Types" ,menu-map
                    :visible (eq bibtex-dialect ',dialect))))))
  ;; End of taken from bibtex.el
  )

这句话比较简短,但我不确定它是否更明智。不过,它确实有效。

更新:记录一下。我最终选择自定义完整列表。尽管代码开销很大,但感觉更明智。

相关内容