5

Suppose that I use minor mode MIN with a whole bunch of major modes. In one of those major modes, call it MAJ1, MIN's binding for a specific key K is undesirable; I would therefore like to suppress that definition and get Emacs to fall back to either the major mode's definition, if any, or the default in global-map. However, I don't want to change how MIN handles that key when it's used with any other major mode, and I want to preserve MIN's other effects in MAJ1. What's the best way to accomplish that?

The specific combination I'm concerned with is Typo minor mode + Markdown major mode (these are both installed as ELPA packages) and the printable character ` (ASCII backtick), which is syntactically significant in Markdown. typo-mode defines ` to insert (left single quote) and then replace that with a backtick if pressed again. 99% of the time when I type ` in a markdown file I want the ASCII backtick, so I want to get rid of the typo-mode binding, but only when the major mode is markdown-mode.

Typo mode is activated from text-mode-hook:

(add-hook 'text-mode-hook
          #'(lambda ()
              (auto-fill-mode 1)
              (typo-mode 1)))

The obvious place to put a markdown-specific override is markdown-mode-hook, so I tried

(add-hook 'markdown-mode-hook
          #'(lambda ()
              (local-set-key (kbd "`") 'self-insert-command)))

but that seems to have no effect at all; I'm guessing that the typo-mode keymap only gets applied after markdown-mode-hook finishes.

Complicating matters, markdown-mode has optional electric behavior for `, so ideally what I would be doing is punching a markdown-specific hole in the typo-mode keymap to allow the markdown-mode-map binding to take effect for this key, but if there's no good way to do that, I could live with a solution that just gets it bound to self-insert-command.

1
  • 1
    Minor mode keymaps have precedence over the local keymap, which is why binding the same key in the local keymap has no practical effect in this instance.
    – phils
    Commented Aug 31, 2018 at 15:24

2 Answers 2

5

I don't think there's an easy way out for this one. You might do something like:

(add-hook 'typo-mode-hook
          (lambda ()
            (when (and typo-mode (derived-mode-p 'markdown-mode))
              (let ((map (make-sparse-keymap)))
                (set-keymap-parent map typo-mode-map)
                (define-key map (kbd "`") 'self-insert-command)
                (push `(typo-mode . ,map)
                      minor-mode-overriding-map-alist)))))
1
  • While it's annoying that the solution is kind of complicated, this worked perfectly for my use case. Thanks Stefan!
    – mnewt
    Commented Jul 30, 2020 at 21:34
0

While this is not a general-purpose solution, future readers might like to know that typo-mode has a hook typo-disable-electricity-functions that can be used to solve the specific case of not wanting typo's behavior for some keys in some major modes. Here's what I have been using for a while now:

(defun zw-typo-inappropriate-electricity-for-markdown ()
  "Hook for typo-disable-electricity-functions: Typographical
punctuation is desirable in Markdown mode, but should be disabled
if we are inside code (either inline or block), and the typo-mode
binding for ` should be disabled altogether."
  (and (derived-mode-p 'markdown-mode)
       (or (eq last-command-event ?`)
           (markdown-inline-code-at-point-p)
           (markdown-code-block-at-point-p))))

(add-hook 'typo-disable-electricity-functions
          'zw-typo-inappropriate-electricity-for-markdown)

(The predicates markdown-inline-code-at-point-p and markdown-code-block-at-point-p are defined by current versions of markdown-mode.)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.