1

When I add this post-command-hook:

(defun insert-into-a-buffer ()
  (with-current-buffer
      (get-buffer-create "some-buffer")
    (insert "a")))

(add-hook 'post-command-hook 'insert-into-a-buffer :local)

I cannot mark text regions. This appears to be because some of the commands I use in my post-command-hook function internally set the deactivate-mark to t, which causes the (deactivate-mark) function to be run after I run my post-command-hook function.

I have tried multiple different methods of getting at the stack trace to show me how and why the (deactivate-mark) function is called, but no method has given me a stack trace that includes its caller, so it appears that (deactivate-mark) is the top-level function that is being run. This corroborates with the answer to this question, which explains that the deactivate-mark variable can be set to t during a command in order for mark to be deactivate after the command.

Exact steps to reproduce:

  • Run emacs -Q
  • (optional) Press C-SPC to set mark. Move point around. Observe that the region between point and mark is visually highlighted.
  • Enter the above code, and evaluate it.
  • Press C-SPC to set mark. Move point around. Region between point and mark is not highlighted.

Expected behavior: Region between point and mark is visually highlighted, even after evaluating those 2 lines of elisp. Actual behavior: Region between point and mark is not highlighted.


The answer linked says that as a possible fix, (setq deactivate-mark nil) can be placed at the end of your command to prevent mark from being deactivated. However, some commands such as kill-region intentionally and quite correctly set it to t. If I set (setq deactivate-mark nil) at the end of my command, I interfere with those commands' correctly deactivating mark once they are run.

That answer also says C-h v deactivate-mark says Automatically becomes buffer-local when set regarding the deactivate-mark variable, but when I run C-h v deactivate-mark, that is not mentioned. Has this been changed? I guess I'll need to do a git bisect...

jcarpenter2
  • 227
  • 1
  • 6
  • The question is unclear. What do you mean by "I cannot mark text regions"? Be specific. Provide a recipe to repro what you see, starting from `emacs -Q` (no init file). Say what you see at each step, and what you expected to see instead. – Drew Mar 30 '18 at 23:46
  • @Drew See edits - added exact steps to reproduce the behavior. – jcarpenter2 Mar 30 '18 at 23:58
  • Thanks. But in that case it appears to be a [duplicate](https://emacs.stackexchange.com/q/19275/105) question. I retracted my vote to close because it was unclear, but now it should be closed because it is a duplicate. (I can't vote for that now, myself, but others can.) – Drew Mar 31 '18 at 01:25
  • @Drew This question isn't quite a duplicate of that one -- see edits. If I simply put `(setq deactivate-mark nil)` at the end of my function, it interferes with mark's correctly being deactivated when I manually insert text or `C-w` (kill-region). Your answer to that question mentions that `deactivate-mark` becomes buffer-local when set, but I do not see that in my `C-h v deactivate-mark` so I suppose that was changed between 2016 and today. If it were still buffer-local, I don't think I would be having a problem at all, since my post-command-hook edits a different buffer. – jcarpenter2 Mar 31 '18 at 03:54
  • 1
    "changed between 2016 and today" - I see the usual `Automatically becomes buffer-local when set.` in the doc, using the latest Emacs version from emacs-26 and master compiled in the last few days. – npostavs Mar 31 '18 at 04:59
  • @Drew While the two questions are related, they aren't quite duplicates. Wrapping around a specific command and dealing with a post-command hook is evidently different enough that the same solution doesn't always work for both. – Gilles 'SO- stop being evil' Mar 31 '18 at 09:55
  • 1
    Note that `(add-hook 'post-command-hook 'insert-into-a-buffer :local)` makes the APPEND argument non-nil, *not* the LOCAL argument. – phils Mar 31 '18 at 10:50
  • @npostavs @Drew Updated to latest version of emacs and now `deactivate-mark` is buffer-local for me too. Sorry, I was on version 24 before! It was obviously incorrect to assume that Debian Stretch would come with a recent version of emacs. Because deactivate-mark is buffer-local now, the problem no longer happens, with no changes at all to the code I posted. – jcarpenter2 Mar 31 '18 at 21:07

1 Answers1

1

What didn't work in Keep region activated upon completion of my command does seem to work here. You want to ignore the changes that the code you're running might make to deactivate-mark. So arrange for these changes to affect only a local variable that will no longer exist when your hook returns.

(defun insert-into-a-buffer ()
  (let (deactivate-mark)
    (with-current-buffer
        (get-buffer-create "some-buffer")
      (insert "a"))))
  • 1
    For the record this did work, however I also updated to the latest version of emacs where `deactivate-mark` is now a buffer-local variable, so this solution is no longer needed! – jcarpenter2 Mar 31 '18 at 21:08