jwiegley / use-package

A use-package declaration for simplifying your .emacs
https://jwiegley.github.io/use-package
GNU General Public License v3.0
4.42k stars 261 forks source link

Binding a key in a map for a different, not-yet-loaded mode? #1063

Open hdeyoung opened 1 year ago

hdeyoung commented 1 year ago

Binding a key in a map for a different mode?

I'm trying to use citar with both AUCTeX and org-mode.

(use-package org
  :ensure t
  :mode ("\\.org\\'" . org-mode))

(use-package latex
  :ensure auctex
  :mode ("\\.tex\\'" . LaTeX-mode))

(use-package citar
  :after (:any latex org)
  :demand t
  :bind (:map LaTeX-mode-map ("C-c [" . citar-insert-citation)))

Problem: This works fine if, after starting Emacs, I happen to open a .tex file before opening a .org file. However, if I happen to first open a .org file, I get a (void-variable LaTeX-mode-map) error in the *Messages* buffer and, worse than that, when I later open a .tex file, the binding is not set up. From what I can tell, the problem is that org-mode triggers the use-package citar, but the binding fails because LaTeX-mode-map does not exist until LaTeX-mode is used.

Question: What is the idiomatic way to handle this kind of situation with use-package? Should I be splitting the clauses for citar into two calls to use-package? The following does work, but I feel slightly unsettled by using two use-package citar. What is the recommended idiom?

(use-package org
  :ensure t
  :mode ("\\.org\\'" . org-mode))

(use-package latex
  :ensure auctex
  :mode ("\\.tex\\'" . LaTeX-mode))

(use-package citar
  :after (:any latex org))

(use-package citar
  :after latex
  :bind (:map LaTeX-mode-map ("C-c [" . citar-insert-citation)))

Also, if I expand this last use-package citar, I see that the bind-keys has :package citar, and I sort of expected to see :package latex... Can someone please explain this to me?

mmarshall540 commented 11 months ago

The default value for :package is the package being configured by the current use-package form.

However, you can set the :package value yourself after the :map keyword, and this will override the default behavior, setting up an eval-after-load for the package you specify instead.

    (use-package citar
      :after (:any latex org)
      :demand t
      :bind 
      ( :map LaTeX-mode-map 
        :package latex
        ("C-c [" . citar-insert-citation)))

This will cause it to wait for latex.el to load (and define the keymap) before attempting to set the binding in LaTeX-mode-map.

A minor caveat is that the :package keyword does not seem to be documented. So there's no guarantee that use-package/bind-key will continue to use it.