> Elisp code must not set window point in normal circumstances.
That's fine, my proposed workaround doesn't involve setting it
anyway. I wasn't proposing that, just explaining what's happening
> What if you wrap your completing-read into save-excursion?
That avoids the issue, of course. But to do that you have to know
already that completing-read is the culprit of the unexpected point
movement, which I do because I've invested some time on debugging the
issue, but the regular user won't.
> If the problem is that redisplay (or whatever inside the macro) moves
> point, it is not a bug in org-with-point-at.
>
> So, not a bug.
> Canceled.
Not so sure about that. Clearly there is a bug (or a known limitation)
somewhere, as a user should be able to use completing-read in the body
of the macro without needing to care about something like this. I
investigated further and the issue is a combination of many things,
none of which I think are bugs per se. I finally removed flycheck out
of the equation, and have concrete reproduction steps which work with
emacs -Q:
1) Set this local hook in an Org buffer (which flycheck-mode did)
```
(defun my-dummy-hook ()
(message "Hook called"))
(setq-local window-configuration-change-hook '(my-dummy-hook))
```
2) Run this with point somewhere in the Org buffer
```
(setq my-marker (point-marker))
(goto-char 1)
```
3) Split the frame in two windows, leave the Org buffer in one, and
select the other
4) Run in that other window
```
(org-with-point-at my-marker
(redisplay t) ;; completing-read works too if it's not the built-in one
;; (i.e., if the minibuffer grows size)
(message "Point: %s. Original marker: %s" (point) my-marker))
```
The problem is that as the documentation of
`window-configuration-change-hook` says, "Functions specified
buffer-locally are called for each window showing the corresponding
buffer if at least one window on that frame has been added, deleted or
changed its buffer or its total or body size since the last redisplay.
Each call is performed with the window showing "the buffer temporarily
selected.
So if this hook is set locally and the window size is modified (which
usually happens with most minibuffer completion packages, in which the
minibuffer area grows and steals screen from the other buffers, to
later give it back), the Org window is selected again temporarilly,
and the buffer and window points are re-synced
I guess there is a reason for the hook to work that way, so the bug is
probably not there. Minibuffer completion changing the size of other
windows is also completely legit. Any buffer having that hook set
locally should be valid too. So there are three possible solutions
IMO, none of which is ideal:
- Every function that tries to execute arbitrary code at some
particular buffer and point should take this possibility into
account and protect against it. This would mean the issue needs to
be fixed in org-mode
- Every minibuffer completion package that modifies the size of other
windows should take this into account and restore the point if it
has changed
- Emacs core itself should take this into account and try to detect
this situation when running the hook
I guess for now I should bring the discussion to emacs-devel, since
this is not exclusive to org mode, and see what they think. I'll
update this thread once we decide something there