emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Making a key undefined again


From: Jonas Bernoulli
Subject: Making a key undefined again
Date: Mon, 25 Oct 2021 16:22:46 +0200

> OK, that's fewer than I thought.  So, new random thought:
>
> kbd-keymap
> kbd-define
> kbd-set-globally
> kbd-unset-globally
> kbd-set-locally
> kbd-unset-locally
> kbd-lookup

If we do that, could we please also consider what it means to "unset"
a key.  `local-unset-key' sets a key to nil, but IMO that is not good
enough.

After I have done

  (local-set-key "a" 'a)
  (local-unset-key "a")

I would like the keymap to be in exactly the same state as before I
have done that.

`kmu-remove-key' from my `keymap-utils' package truly removes a key
binding.  Visit or clone from https://github.com/tarsius/keymap-utils.

    (defun kmu-remove-key (keymap key)
      "In KEYMAP, remove key sequence KEY.
    
    Make the event KEY truly undefined in KEYMAP by removing the
    respective element of KEYMAP (or a sub-keymap or a bound prefix
    command) as opposed to merely setting its binding to nil.
    
    There are several ways in which a key can be \"undefined\":
    
       (keymap (65 . undefined) ; A
               (66))            ; B
    
    As far as key lookup is concerned A isn't undefined at all, it is
    bound to the command `undefined' (which doesn't do anything but
    make some noise).  This can be used to override lower-precedence
    keymaps.
    
    B's binding is nil which doesn't constitute a definition but does
    take precedence over a default binding or a binding in the parent
    keymap.  On the other hand, a binding of nil does _not_ override
    lower-precedence keymaps; thus, if the local map gives a binding
    of nil, Emacs uses the binding from the global map.
    
    All other events are truly undefined in KEYMAP.
    
    Note that in a full keymap all characters without modifiers are
    always bound to something, the closest these events can get to
    being undefined is being bound to nil like B above."
      ;; Uses kbd-syntax, but that's not relevant for
      ;; this side-thread, so let's comment that out.
      ;; (when (stringp key)
      ;;   (setq key (kmu-parse-key-description key t)))
      (define-key keymap key nil)
      (setq key (cl-mapcan (lambda (k)
                             (if (and (integerp k)
                                      (/= (logand k ?\M-\0) 0))
                                 (list ?\e (- k ?\M-\0))
                               (list k)))
                           key))
      (if (= (length key) 1)
          (delete key keymap)
        (let* ((prefix (vconcat (butlast key)))
               (submap (lookup-key keymap prefix)))
          (if (not (keymapp submap))
              (error "Cannot remove %; %s is not bound to a keymap" key prefix)
            (when (symbolp submap)
              (setq submap (symbol-function submap)))
            (delete (last key) submap)
            (when (= (length submap) 1)
              (kmu-remove-key keymap prefix))))))

Maybe the code could be simplified; it has been a long time since
I wrote that, with a little help from my friends.  But I hope the
doc-string makes it clear why something like this is desirable.

It would be nice if such a function could be added to Emacs and if
`kbd-unset-{locally,globally}' behaved that way as well.

     Thanks for considering,
     Jonas



reply via email to

[Prev in Thread] Current Thread [Next in Thread]