Subject: bug#57556: 28.1; Eshell not finding executables in PATH when tramp-integration loaded

From: Michael Albinus <[email-masked]>
Date: Sun, 02 Oct 2022 10:48:58 +0200

Jim Porter <[email-masked]> writes:

Hi Jim,

> On 10/1/2022 3:02 PM, Jim Porter wrote:
>> On 10/1/2022 1:25 PM, Michael Albinus wrote:
>>> Again, no possibility to use connection-local variables? You use them
>>> already by calling (path-separator) ...
>> I'll take a look at doing that. As I understand it, connection-local
>> variables are cleared if the associated connection gets cleaned up,
>> right? I wonder if that would be the right thing to do. For example,
>> if I cd into a remote host in Eshell, then update Eshell's $PATH for
>> that host, then clean up the connection, should the $PATH be reset
>> to the default for that host? I'm really not sure...
>
> After a bit of trying, I wasn't able to get this to work. I was doing
> something along these lines:
>
>   (defvar-local eshell-path-env-list nil)
>
>   (connection-local-set-profile-variables
>    'eshell-connection-local-profile
>    '((eshell-path-env-list . nil)))
>
>   (connection-local-set-profiles
>    nil 'eshell-connection-local-profile)
>
>   ;; When getting the $PATH...
>   (with-connection-local-variables
>    (or eshell-path-env-list
>        (setq eshell-path-env-list (butlast (exec-path)))))
>
> However, the next time I try to get the $PATH in the
> 'with-connection-local-variables' block, the value is nil again, so it
> gets recomputed. I guess 'setq' inside
> 'with-connection-local-variables' doesn't work?

Yes. with-connection-local-variables is designed to provide those
variables inside the BODY only. And you have used nil as CRITERIA in
connection-local-set-profiles, which means you get the same variables
for every kind of default-directory, which means you don't use
connection-local variables at all :-)

What you need is a permanent setting of variables. Something like

(connection-local-set-profiles
 (connection-local-criteria-for-default-directory 'eshell)
 'eshell-connection-local-profile)

(let ((enable-connection-local-variables t)
      connection-local-variables-alist) ;; I'm not sure this is needed.
  (hack-connection-local-variables-apply
   (connection-local-criteria-for-default-directory 'eshell))
  ;; The body.
  ...)

I have used `eshell' as APPLICATION, the default application would be
`tramp'. But since you care only your eshell-* variables, you could use
an own namespace I believe. Of course, you could also use `tramp' or
anything else, it's your decision.

> This is also made more complex by the fact that in an Eshell
> subcommand, we want to be able to modify the $PATH locally so that
> it's reset to the previous value after the subcommand.

In this case, you could use the with-connection-local-variables macro
indeed. Something like

(let ((connection-local-default-application 'eshell))
  (with-connection-local-variables
  ;; Some temprary modifications.
  ...)

> Since there are so many different things that can alter the $PATH
> value, making it connection-local seemed to be more complex in my
> experiments. The alist implementation is a bit more primitive, but I
> found it easier to reason through the logic. That could just be
> because I don't quite understand all the details of connection-local
> variables though.

It is more complex to set it up, indeed. (I wish we would have made it
more friendly.) But in the long term, it will be more robust I believe.

Best regards, Michael.