Subject: [PATCH] Re: bug#79441: shell-resync-dirs breaks on PS1 with newline

From: Janneke Nieuwenhuizen <[email-masked]>
Date: Sat, 13 Sep 2025 17:01:45 +0200

Eli Zaretskii writes:

Hi Eli,

[.]

>> To reproduce, a
>> single character (that is not '.') and a newline suffices, typing
>> something like:
>> 
>>     PS1='0\n$ '
>> 
>> in an emacs shell and typing M-RET reproduces the problem.
>
> Can you suggest how to solve this?

Good question!  When I tried to add (message ...) debugging this
morning, it started (and kept) looping; so I had no idea how to proceed.
However, I tried again and got better results this time and have created
a patch that "works for me" (see attached).

The puzzle is that I don't know all the requirements, e.g., I have no
idea why the code was (blindly) using `last' to set `dsl' from the
shell-dirtrack-query's result, and only much later using
file-directory-p.

The code using `last' suggests to me that there could me more (partial?)
directory-like elements coming back from `shell-dirtrack-query' and that
in such a case, that I haven't oberved, the last must be the most
relevant?

Also, the nested while loops lateron with the concatenations suggest
that `shell-dirtrack-query' may not always return the needed directory
element as one string, but that it could be split up in parts that would
need to be concatenated?  Also, something that I didn't observe.

So, I've changed the code to prefer `seq-find' with `file-directory-p'
and reverse the list first, so that the last element remains the most
relevant.  Also, I've kept selecting the last element in case the
`seq-find' does not return a result.

Anyway, naively looking at my case only, it seems the code could be a
lot simpler, using just the `seq-find' and without the nested `while'
loops...so yeah, dunno ;)

Greetings,
Janneke

>From f56b284e5423b2fe37d07a477008b12f6b1107c1 Mon Sep 17 00:00:00 2001
From: Janneke Nieuwenhuizen <[email-masked]>
Date: Sat, 13 Sep 2025 16:30:42 +0200
Subject: [PATCH] Fix 'shell-resync-dirs' for multi-line prompt.

* lisp/shell.el (shell-eval-command): Instead of always taking the last
element from the shell-dirtrack-query command, first try selecting the
last directory.  (Bug#79441)
---
 lisp/shell.el | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/lisp/shell.el b/lisp/shell.el
index 09d4161ba7a..927dec52304 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -1236,11 +1236,11 @@ shell-resync-dirs
 `shell-dirstack-query' (default \"dirs\"), reads the next
 line output and parses it to form the new directory stack."
   (interactive)
-  (let* ((dls (car
-               (last
-                (string-lines
-                 (string-chop-newline
-                  (shell-eval-command (concat shell-dirstack-query "\n")))))))
+  (let* ((lines (nreverse
+                 (string-lines
+                  (shell-eval-command (concat shell-dirstack-query "\n")))))
+         (dls (or (seq-find #'file-directory-p lines)
+                  (car lines)))
          (dlsl nil)
          (pos 0)
          (ds nil))
-- 
2.51.0

-- 
Janneke Nieuwenhuizen <[email-masked]>  | GNU LilyPond https://LilyPond.org
Freelance IT https://www.JoyOfSource.com | Avatar® https://AvatarAcademy.com