5

First, some context:

I am in the process of debugging a strange interaction between smartparens and Org Speed Keys:

After editing an .org file for a while, specific speed keys for navigating the outline start to be treated as though they are modifying the buffer. For instance, if I press n on a heading after saving the file, the portion of the mode line that indicates whether the file has been modified or not changes from -- (unmodified) to ** (modified). No characters are inserted into the buffer though.

I tried to figure out what might be causing this problem by doing C-h k n right after opening the .org file and then again after the problematic behavior started. Turns out that initially, n is bound to org-self-insert-command, and gets rebound to sp--self-insert-command later on.

The problem is that I have no idea when the command bound to n changes. I also tried C-h l (view-lossage) a few times after the behavior changed but I couldn't detect any patterns that would give me a hint as to what might be triggering the change in behavior.

Question:

I think in order to solve this problem I need to pinpoint the exact command that is causing n to be rebound to sp--self-insert-command (if only to be able to automatically reset the binding).

So my question is: How can I detect when the command bound to n changes?

itsjeyd
  • 14,586
  • 3
  • 58
  • 87
  • Which modes do you have smartparens hooked to? – Malabarba Oct 08 '14 at 19:36
  • No idea whether this is pertinent to what you observe, but know that highlighting (using text properties) also changes the buffer state to "modified". So even if no text is changed in the buffer, if some highlighting changes (and it is not overlay highlighting) then the status will change from `--` to `**`. – Drew Oct 08 '14 at 19:58
  • Look in the smart-parens code, to see where it binds keys to `sp--self-insert-command`. After you find out just what's going on, consider filing a bug/enhancement report for smart-parens or org. – Drew Oct 08 '14 at 19:59
  • @Malabarba It's not hooked to specific modes, I am using `smartparens-global-mode`. – itsjeyd Oct 08 '14 at 20:10
  • 1
    @Drew Thanks for the suggestions. The `smartparens` source has only one function that binds keys to `sp--self-insert-command`. For now, I've advised this function to `message` me with info about `last-command` when it is called. Hopefully that will shed some more light on the matter :) – itsjeyd Oct 08 '14 at 21:00
  • [How can I find out in which keymap a key is bound?](http://emacs.stackexchange.com/questions/653/how-can-i-find-out-in-which-keymap-a-key-is-bound/654#654) may help. – Gilles 'SO- stop being evil' Oct 08 '14 at 21:48
  • Just an idea: can't you "`defadvice`" `define-key` to check its second parameter, and call the debugger if it's the one you are interested in? – angus Oct 09 '14 at 19:27
  • @angus That sounds like a good idea - do you want to post it as an additional answer? Even if I don't end up solving the problem using this method, your suggestion seems like a valid answer to the generic question of detecting when a key is rebound to another command. – itsjeyd Oct 10 '14 at 13:00

2 Answers2

5

Use defadvice to intercept define-key and check for your desired key sequence.

(defadvice define-key (before define-key-check-n (keymap key def))
  (when (equal key "n")
    (message "`n' redefined")))

(You can change (message ...) to (debug) or something else that'll give you more information about where you are.)

Make the advice effective with

(ad-activate 'define-key)

To discard the advice, first disable it

(ad-disable-advice 'define-key 'before 'define-key-check-n)

and then "reconfigure" the function again

(ad-activate 'define-key)
angus
  • 593
  • 4
  • 7
2

You could do something like this:

(add-hook 'post-command-hook
          (lambda ()
            (when (not (eq (key-binding (kbd "n") t)
                           'org-self-insert-command))
              (message "Command %s rebound the key!" this-command)))
          nil t)

This will add the lambda function buffer-locally to be run after every command, so you can just kill the buffer to get rid of the behavior. If after a command (kbd "n") is not org-self-insert-command anymore, it will tell you which command did that.

Jorgen Schäfer
  • 3,899
  • 2
  • 17
  • 19