GNU bug report logs - #79984
30.1.90; post-command-hook doesn't run after an emacsclient connection

Previous Next

Package: emacs;

Reported by: Spencer Baugh <sbaugh <at> janestreet.com>

Date: Wed, 10 Dec 2025 18:37:01 UTC

Severity: normal

Found in version 30.1.90

To reply to this bug, email your comments to 79984 AT debbugs.gnu.org.

Toggle the display of automated, internal messages from the tracker.

View this report as an mbox folder, status mbox, maintainer mbox


Report forwarded to bug-gnu-emacs <at> gnu.org:
bug#79984; Package emacs. (Wed, 10 Dec 2025 18:37:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Spencer Baugh <sbaugh <at> janestreet.com>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Wed, 10 Dec 2025 18:37:02 GMT) Full text and rfc822 format available.

Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):

From: Spencer Baugh <sbaugh <at> janestreet.com>
To: bug-gnu-emacs <at> gnu.org
Subject: 30.1.90; post-command-hook doesn't run after an emacsclient connection
Date: Wed, 10 Dec 2025 13:36:35 -0500
post-command-hook doesn't run after "emacsclient --eval (something)".
This can lead to slightly incorrect behavior depending on what's in
post-command-hook.

For example, I have a post-command-hook which updates default-directory
based on the location of point.  Since it doesn't run after an
emacsclient connection, default-directory doesn't get updated.  So the
next command run after such an emacsclient connection will have an
incorrect default-directory.

It might be fine to just run post-command-hook after an emacsclient
connection?  (Or perhaps there is some other hook which I should be
using to update default-directory after a command moves point)


In GNU Emacs 30.1.90 (build 90, x86_64-pc-linux-gnu, X toolkit, cairo
 version 1.15.12, Xaw scroll bars) of 2025-12-04 built on
 igm-qws-u22796a
Repository revision: 88878f209ee0f1699952b1ba5fb829c502f5959f
Repository branch: HEAD
Windowing system distributor 'The X.Org Foundation', version 11.0.12011000
System Description: Rocky Linux 8.10 (Green Obsidian)

Configured using:
 'configure --with-x-toolkit=lucid --without-gpm --without-gconf
 --without-selinux --without-imagemagick --with-modules --with-gif=no
 --with-cairo --with-rsvg --without-compress-install --with-tree-sitter
 --with-native-compilation=aot
 PKG_CONFIG_PATH=/usr/local/home/garnish/libtree-sitter/0.22.6-1/lib/pkgconfig/'

Configured features:
CAIRO DBUS FREETYPE GLIB GMP GNUTLS GSETTINGS HARFBUZZ JPEG LIBSYSTEMD
LIBXML2 MODULES NATIVE_COMP NOTIFY INOTIFY PDUMPER PNG RSVG SECCOMP
SOUND SQLITE3 THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER X11 XDBE XIM
XINPUT2 XPM LUCID ZLIB




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79984; Package emacs. (Thu, 11 Dec 2025 07:31:06 GMT) Full text and rfc822 format available.

Message #8 received at 79984 <at> debbugs.gnu.org (full text, mbox):

From: Eli Zaretskii <eliz <at> gnu.org>
To: Spencer Baugh <sbaugh <at> janestreet.com>,
 Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 79984 <at> debbugs.gnu.org
Subject: Re: bug#79984: 30.1.90;
 post-command-hook doesn't run after an emacsclient connection
Date: Thu, 11 Dec 2025 09:30:16 +0200
> Date: Wed, 10 Dec 2025 13:36:35 -0500
> From:  Spencer Baugh via "Bug reports for GNU Emacs,
>  the Swiss army knife of text editors" <bug-gnu-emacs <at> gnu.org>
> 
> 
> post-command-hook doesn't run after "emacsclient --eval (something)".
> This can lead to slightly incorrect behavior depending on what's in
> post-command-hook.
> 
> For example, I have a post-command-hook which updates default-directory
> based on the location of point.  Since it doesn't run after an
> emacsclient connection, default-directory doesn't get updated.  So the
> next command run after such an emacsclient connection will have an
> incorrect default-directory.
> 
> It might be fine to just run post-command-hook after an emacsclient
> connection?  (Or perhaps there is some other hook which I should be
> using to update default-directory after a command moves point)

Connection from emacsclient is not a command, it is not handled by the
main command loop, so the post-command-hook is not called as part of
the normal Emacs operation.  It would be wrong to call
post-command-hook in that case.  (The fact that we call
post-command-hook when visiting files is an extra-special feature,
introduced to fix an obscure bug (see bug#6910), and IMNSHO that was
the wrong way of fixing that bug.  But that ship sailed long ago, and
I guess we are stuck with this problem for good.)

server.el has its own hooks:

  server-visit-hook
  server-switch-hook
  server-after-make-frame-hook
  server-done-hook

We could add a hook for processing -eval, if that is desired.  Or we
could add a general server-execute-hook that will be called whenever
the server performs any directive of the client.  We could also add a
hook to be run when a new client connection is accepted.

But I don't think we should make more calls to post-command-hook for
server actions triggered by emacsclient.  It is wrong to design a
feature that depends on post-command-hook when the "command" to be
hooked is something triggered by emacsclient.

Adding Stefan in case he has an opinion.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79984; Package emacs. (Thu, 11 Dec 2025 12:47:02 GMT) Full text and rfc822 format available.

Message #11 received at 79984 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: 79984 <at> debbugs.gnu.org
Subject: Re: bug#79984: 30.1.90; post-command-hook doesn't run after an
 emacsclient connection
Date: Thu, 11 Dec 2025 07:45:51 -0500
> post-command-hook doesn't run after "emacsclient --eval (something)".
> This can lead to slightly incorrect behavior depending on what's in
> post-command-hook.
>
> For example, I have a post-command-hook which updates default-directory
> based on the location of point.  Since it doesn't run after an
> emacsclient connection, default-directory doesn't get updated.  So the
> next command run after such an emacsclient connection will have an
> incorrect default-directory.
>
> It might be fine to just run post-command-hook after an emacsclient
> connection?  (Or perhaps there is some other hook which I should be
> using to update default-directory after a command moves point)

I agree with Eli.  I didn't remember the find-file case of manually
running `post-command-hook`, but I do remember adding such a thing to
the query-replace loop and have similarly learned since that it was
a bad idea.

Have you considered using another hook?  E.g. `pre-command-hook`?

[ I assume you're aware that "update default-directory
  based on the location of point" is fundamentally problematic since there
  can be several (window-)points at the same time.  ]

Of course, if you want to think of "general solutions" to the kind of
problem you're hitting, maybe you can think of it as a variant of the
multiple-major-mode problem (some of the solutions to this problem that
have been proposed over the years include setting variables
"text-locally" via overlays or text-properties).


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79984; Package emacs. (Fri, 12 Dec 2025 18:08:02 GMT) Full text and rfc822 format available.

Message #14 received at 79984 <at> debbugs.gnu.org (full text, mbox):

From: Spencer Baugh <sbaugh <at> janestreet.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 79984 <at> debbugs.gnu.org
Subject: Re: bug#79984: 30.1.90; post-command-hook doesn't run after an
 emacsclient connection
Date: Fri, 12 Dec 2025 13:07:28 -0500
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

>> post-command-hook doesn't run after "emacsclient --eval (something)".
>> This can lead to slightly incorrect behavior depending on what's in
>> post-command-hook.
>>
>> For example, I have a post-command-hook which updates default-directory
>> based on the location of point.  Since it doesn't run after an
>> emacsclient connection, default-directory doesn't get updated.  So the
>> next command run after such an emacsclient connection will have an
>> incorrect default-directory.
>>
>> It might be fine to just run post-command-hook after an emacsclient
>> connection?  (Or perhaps there is some other hook which I should be
>> using to update default-directory after a command moves point)
>
> I agree with Eli.  I didn't remember the find-file case of manually
> running `post-command-hook`, but I do remember adding such a thing to
> the query-replace loop and have similarly learned since that it was
> a bad idea.

Reasonable.

> Have you considered using another hook?  E.g. `pre-command-hook`?

I did consider pre-command-hook, but using pre-command-hook to update
default-directory means that the default-directory is at the old value
after each command.  That in turn means that project-mode-line (and
similar things) will show the "old" project, even though any subsequent
command will operate in some different new project, which is confusing.

> [ I assume you're aware that "update default-directory
>   based on the location of point" is fundamentally problematic since there
>   can be several (window-)points at the same time.  ]

Yes.  I guess doing this truly correctly would require a window-local
default-directory.  But this hasn't caused any issues so far, since
basically almost any command that interacts with the default-directory
of a buffer, requires actually selecting that buffer first.

The specific use-case is that I have a package which provides a
special-mode buffer containing a list of project.el projects.  And based
on what project is under point, I want to update default-directory to
the root of that project, so e.g. find-file opens files in that project
and vc-dir-root opens vc-dir in that project.

> Of course, if you want to think of "general solutions" to the kind of
> problem you're hitting, maybe you can think of it as a variant of the
> multiple-major-mode problem (some of the solutions to this problem that
> have been proposed over the years include setting variables
> "text-locally" via overlays or text-properties).

Setting default-directory via text property sounds a little crazy, but
maybe that is actually sane?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79984; Package emacs. (Fri, 12 Dec 2025 19:17:01 GMT) Full text and rfc822 format available.

Message #17 received at 79984 <at> debbugs.gnu.org (full text, mbox):

From: Stefan Monnier <monnier <at> iro.umontreal.ca>
To: Spencer Baugh <sbaugh <at> janestreet.com>
Cc: 79984 <at> debbugs.gnu.org
Subject: Re: bug#79984: 30.1.90; post-command-hook doesn't run after an
 emacsclient connection
Date: Fri, 12 Dec 2025 14:16:27 -0500
>> [ I assume you're aware that "update default-directory
>>   based on the location of point" is fundamentally problematic since there
>>   can be several (window-)points at the same time.  ]
> Yes.  I guess doing this truly correctly would require a window-local
> default-directory.  But this hasn't caused any issues so far, since
> basically almost any command that interacts with the default-directory
> of a buffer, requires actually selecting that buffer first.

That's just an "accident" of the default set of commands.  If someone
develops more commands like `scroll-other-window`, they might very well
bump into the same problem.

> The specific use-case is that I have a package which provides a
> special-mode buffer containing a list of project.el projects.  And based
> on what project is under point,

So you want a value of `default-directory` that depends on the text under point?

> Setting default-directory via text property sounds a little crazy,

I tend to agree, yet, it seems to be close to what you want.

BTW, please don't try to implement such a crazy feature: I could
hypothetically be convinced to discuss supporting variables whose
value depends on the text-properties at point, but I don't want
to think about supporting `let` bindings for such variables.
Even just supporting `setq` sounds painfully horrible.

My recommendation is to use both `pre-` and `post-command-hook` and
potentially use a few more hooks to cover a few other situations you may
bump into.  In any case what you're implementing is a hack.  A less
hackish solution would involve changing a lot more code to call some
function to compute dynamically the `default-directory` to use.  So in
either case you don't cover 100% of the cases.


        Stefan





Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79984; Package emacs. (Fri, 12 Dec 2025 22:44:02 GMT) Full text and rfc822 format available.

Message #20 received at 79984 <at> debbugs.gnu.org (full text, mbox):

From: Spencer Baugh <sbaugh <at> janestreet.com>
To: Stefan Monnier <monnier <at> iro.umontreal.ca>
Cc: 79984 <at> debbugs.gnu.org
Subject: Re: bug#79984: 30.1.90; post-command-hook doesn't run after an
 emacsclient connection
Date: Fri, 12 Dec 2025 17:43:49 -0500
Stefan Monnier <monnier <at> iro.umontreal.ca> writes:

>>> [ I assume you're aware that "update default-directory
>>>   based on the location of point" is fundamentally problematic since there
>>>   can be several (window-)points at the same time.  ]
>> Yes.  I guess doing this truly correctly would require a window-local
>> default-directory.  But this hasn't caused any issues so far, since
>> basically almost any command that interacts with the default-directory
>> of a buffer, requires actually selecting that buffer first.
>
> That's just an "accident" of the default set of commands.  If someone
> develops more commands like `scroll-other-window`, they might very well
> bump into the same problem.

That is true.

>> The specific use-case is that I have a package which provides a
>> special-mode buffer containing a list of project.el projects.  And based
>> on what project is under point,
>
> So you want a value of `default-directory` that depends on the text under point?

Eh, sure.

Really the thing I want is just an easy UI for switching between and
operating on projects, where I can e.g. do M-& in one project, hit C-n a
few times, then do M-& in another project.  Except not limited to just
M-&, but which works for any command.  And also you can use any command
to navigate the list of projects, like isearch, not just C-n.  This is
just kinda hard...

>> Setting default-directory via text property sounds a little crazy,
>
> I tend to agree, yet, it seems to be close to what you want.
>
> BTW, please don't try to implement such a crazy feature: I could
> hypothetically be convinced to discuss supporting variables whose
> value depends on the text-properties at point, but I don't want
> to think about supporting `let` bindings for such variables.
> Even just supporting `setq` sounds painfully horrible.

Don't worry, it is too crazy for me to do it :)

> My recommendation is to use both `pre-` and `post-command-hook` and
> potentially use a few more hooks to cover a few other situations you may
> bump into.

Yeah, I guess I'll do that.

> In any case what you're implementing is a hack.  A less hackish
> solution would involve changing a lot more code to call some function
> to compute dynamically the `default-directory` to use.  So in either
> case you don't cover 100% of the cases.

Alas, this is so.




This bug report was last modified 4 days ago.

Previous Next


GNU bug tracking system
Copyright (C) 1999 Darren O. Benham, 1997,2003 nCipher Corporation Ltd, 1994-97 Ian Jackson.