Skip to content

Commit

Permalink
add support for remapped and aliased modes
Browse files Browse the repository at this point in the history
This patch tries to make `bind-map` aware of two ways in which major modes can
be remapped: via aliasing or via `major-mode-remap-alist`.

The motivating scenario is AUCTeX, which as of version 14.0.1 has renamed
several major modes, e.g., latex-mode has been renamed as LaTeX-mode. AUCTeX
attempts to offer backwards compatibility using a mix of remapping and aliasing.
For users of emacs < 29, `latex-mode` is redefined as an alias for `LaTeX-mode`,
whereas for users of emacs 29+, `latex-mode` is remapped to `LaTeX-mode` using
`major-mode-remap-alist`.

However, if a user had configured keymaps for `latex-mode` using `bind-map`,
they will not be available in `LaTeX-mode`. This is especially problematic for
distributions like `spacemacs` which need to support users of both old and new
AUCTeX (see syl20bnr/spacemacs#16282 for more discussion).

This patch introduces two new customizable options,
`bind-map-use-remapped-modes` and `bind-map-use-aliased-modes`. Both options
default to `t`, in which case when `bind-map` is deciding whether to activate a
given keymap, it will compare the value of `major-mode` to not only the symbol
for which the keymap was configured configured (e.g., `latex-mode`), but any
remapped or aliased modes (e.g., `'(latex-mode LaTeX-mode)`. This logic is
implemented in the new (private) function `bind-map--lookup-major-modes` to
facilitate lookup of applicable major-modes on the fly. As a result, if a user
adjusts `major-mode-remap-alist` or adjusts aliased, `bind-map`'s behavior will
change accordingly.
  • Loading branch information
dankessler committed Feb 17, 2024
1 parent 510a241 commit 87a193f
Showing 1 changed file with 46 additions and 1 deletion.
47 changes: 46 additions & 1 deletion bind-map.el
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,32 @@
:group 'bind-map
:type 'string)

(defcustom bind-map-use-remapped-modes t
"If non-nil, bind-map will be aware of remapped modes. For
example, suppose you used `bind-map' to define a keymap for
`foo-mode', but use `major-mode-remap-alist' to remap `foo-mode'
to `bar-mode'. If `bind-map-use-remapped-modes' is non-nil, then,
when `bar-mode' is activated
(either directly or by activating `foo-mode'), the keymap for
`foo-mode' will be active. If you define separate keymaps for
`foo-mode' and `bar-mode' yet leave this option non-nil, chaos
may ensue."
:group 'bind-map
:type 'boolean)

(defcustom bind-map-use-aliased-modes t
"If non-nil, bind-map will be aware of aliased modes. For example,
suppose you used `bind-map' to define a keymap for `foo-mode',
but `foo-mode' is actually an alias for `bar-mode'. If
`bind-map-use-aliased-modes' is non-nil, then, when `bar-mode' is
activated (either directly or by activating `foo-mode'), the
keymap for `foo-mode' will be active. If you define separate
keymaps for `foo-mode' and `bar-mode' yet leave this option
non-nil, chaos may ensue."
:group 'bind-map
:type 'boolean)


(defvar bind-map-evil-local-bindings '()
"Each element takes the form (OVERRIDE-MODE STATE KEY DEF) and
corresponds to a binding for an evil local state map.
Expand Down Expand Up @@ -173,11 +199,30 @@ when the major mode is an element of the cdr. See
(dolist (entry bind-map-major-modes-alist)
(if (boundp (car entry))
(setf (symbol-value (car entry))
(not (null (member major-mode (cdr entry)))))
(not
(null
(member major-mode
(mapcan
#'bind-map--lookup-major-modes (cdr entry))))))
(message "bind-map: %s is void in change major mode hook" (car entry)))))
(add-hook 'change-major-mode-after-body-hook
'bind-map-change-major-mode-after-body-hook)

(defun bind-map--lookup-major-modes (mode)
"Return a list of implicated modes depending on the values of
`bind-map-use-remapped-modes' and `bind-map-use-aliased-modes'.
If both are nil, just return `mode'. If
`bind-map-use-remapped-modes' is non-nil, also return mode to
which it has been remapped in `major-mode-remap-alist' (if
applicable). If `bind-map-use-aliased-modes' is non-nil, also
return any modes for which `mode' is an alias (if applicable)."
(let ((r-mode
(or (and bind-map-use-remapped-modes
(boundp 'major-mode-remap-alist)
(alist-get mode major-mode-remap-alist))))
(a-modes (and bind-map-use-aliased-modes (function-alias-p mode))))
(delq nil (append (list mode r-mode) a-modes))))

(defun bind-map-add-to-major-mode-list (activate-var major-mode-list)
"Add (ACTIVATE-VAR . MAJOR-MODE-LIST) to
`bind-map-major-modes-alist'. If ACTIVATE-VAR is already a key,
Expand Down

0 comments on commit 87a193f

Please sign in to comment.