GNU bug report logs - #79441
shell-resync-dirs breaks on PS1 with newline

Previous Next

Package: emacs;

Reported by: Janneke Nieuwenhuizen <janneke <at> gnu.org>

Date: Sat, 13 Sep 2025 06:53:02 UTC

Severity: normal

To reply to this bug, email your comments to 79441 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#79441; Package emacs. (Sat, 13 Sep 2025 06:53:02 GMT) Full text and rfc822 format available.

Acknowledgement sent to Janneke Nieuwenhuizen <janneke <at> gnu.org>:
New bug report received and forwarded. Copy sent to bug-gnu-emacs <at> gnu.org. (Sat, 13 Sep 2025 06:53:02 GMT) Full text and rfc822 format available.

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

From: Janneke Nieuwenhuizen <janneke <at> gnu.org>
To: bug-gnu-emacs <at> gnu.org
Subject: shell-resync-dirs breaks on PS1 with newline
Date: Sat, 13 Sep 2025 08:52:15 +0200
Hi!

It's great that shell-resync-dirs no longer hangs, but now (30.2) it
breaks on my prompt:

--8<---------------cut here---------------start------------->8---
PS1='$(_q=$?; if [ $_q != 0 ]; then echo "[$_q] ";fi)\t \u@\h:\w'" $PSG"'\n$ '
--8<---------------cut here---------------end--------------->8---

saying

    Couldn’t cd: (wrong-type-argument stringp nil)

and failing to update the buffer's directory.

I've been using it for ages: It shows the last exit value if non-zero,
the time, the user, pwd and uses a newline always leave plenty of typing
space.  (PSG is set to "[env]" when inside a GUIX_ENVIRONMENT.)

Anyway, typing:

    PS1='$ '

(or even PS1='\w$ ') fixes it, i.e., M-RET works again.  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.

Greetings,
Janneke

-- 
Janneke Nieuwenhuizen <janneke <at> gnu.org>  | GNU LilyPond https://LilyPond.org
Freelance IT https://www.JoyOfSource.com | Avatar® https://AvatarAcademy.com




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79441; Package emacs. (Sat, 13 Sep 2025 10:50:02 GMT) Full text and rfc822 format available.

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

From: Eli Zaretskii <eliz <at> gnu.org>
To: Janneke Nieuwenhuizen <janneke <at> gnu.org>
Cc: 79441 <at> debbugs.gnu.org
Subject: Re: bug#79441: shell-resync-dirs breaks on PS1 with newline
Date: Sat, 13 Sep 2025 13:49:40 +0300
> From: Janneke Nieuwenhuizen <janneke <at> gnu.org>
> Date: Sat, 13 Sep 2025 08:52:15 +0200
> 
> Hi!
> 
> It's great that shell-resync-dirs no longer hangs, but now (30.2) it
> breaks on my prompt:
> 
> --8<---------------cut here---------------start------------->8---
> PS1='$(_q=$?; if [ $_q != 0 ]; then echo "[$_q] ";fi)\t \u@\h:\w'" $PSG"'\n$ '
> --8<---------------cut here---------------end--------------->8---
> 
> saying
> 
>     Couldn’t cd: (wrong-type-argument stringp nil)
> 
> and failing to update the buffer's directory.
> 
> I've been using it for ages: It shows the last exit value if non-zero,
> the time, the user, pwd and uses a newline always leave plenty of typing
> space.  (PSG is set to "[env]" when inside a GUIX_ENVIRONMENT.)
> 
> Anyway, typing:
> 
>     PS1='$ '
> 
> (or even PS1='\w$ ') fixes it, i.e., M-RET works again.  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?




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79441; Package emacs. (Sat, 13 Sep 2025 15:02:01 GMT) Full text and rfc822 format available.

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

From: Janneke Nieuwenhuizen <janneke <at> gnu.org>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 79441 <at> debbugs.gnu.org
Subject: [PATCH] Re: bug#79441: shell-resync-dirs breaks on PS1 with newline
Date: Sat, 13 Sep 2025 17:01:45 +0200
[Message part 1 (text/plain, inline)]
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

[0001-Fix-shell-resync-dirs-for-multi-line-prompt.patch (text/x-patch, inline)]
From f56b284e5423b2fe37d07a477008b12f6b1107c1 Mon Sep 17 00:00:00 2001
From: Janneke Nieuwenhuizen <janneke <at> gnu.org>
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

[Message part 3 (text/plain, inline)]
-- 
Janneke Nieuwenhuizen <janneke <at> gnu.org>  | GNU LilyPond https://LilyPond.org
Freelance IT https://www.JoyOfSource.com | Avatar® https://AvatarAcademy.com

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79441; Package emacs. (Sun, 14 Sep 2025 05:51:01 GMT) Full text and rfc822 format available.

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

From: Janneke Nieuwenhuizen <janneke <at> gnu.org>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 79441 <at> debbugs.gnu.org
Subject: Re: bug#79441: [PATCH v2] Re: bug#79441: shell-resync-dirs breaks
 on PS1 with newline
Date: Sun, 14 Sep 2025 07:50:38 +0200
[Message part 1 (text/plain, inline)]
Janneke Nieuwenhuizen writes:

Hello!

> [.]
>
>>> 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).

[..]  Snip rationale that still holds...but

...initially I only used `seq-filter' in my patch, so I removed the
stripping of the optional final newline.  When I added the fall-back to
takk the last element of the list, we'd need to bring back that final
newline removal.  Version 2 attached.

Greetings,
Janneke

[v2-0001-Fix-shell-resync-dirs-for-multi-line-prompt.patch (text/x-patch, inline)]
From a08fc315b30044c7feb86a04a135ea7de434bf11 Mon Sep 17 00:00:00 2001
From: Janneke Nieuwenhuizen <janneke <at> gnu.org>
Date: Sat, 13 Sep 2025 16:30:42 +0200
Subject: [PATCH v2] 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 | 11 ++++++-----
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/lisp/shell.el b/lisp/shell.el
index 09d4161ba7a..a9c71488f2d 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -1236,11 +1236,12 @@ 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
+                  (string-chop-newline
+                   (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

[Message part 3 (text/plain, inline)]
-- 
Janneke Nieuwenhuizen <janneke <at> gnu.org>  | GNU LilyPond https://LilyPond.org
Freelance IT https://www.JoyOfSource.com | Avatar® https://AvatarAcademy.com

Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79441; Package emacs. (Sun, 14 Sep 2025 06:09:02 GMT) Full text and rfc822 format available.

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

From: Eli Zaretskii <eliz <at> gnu.org>
To: Janneke Nieuwenhuizen <janneke <at> gnu.org>
Cc: 79441 <at> debbugs.gnu.org
Subject: Re: [PATCH] Re: bug#79441: shell-resync-dirs breaks on PS1 with
 newline
Date: Sun, 14 Sep 2025 09:08:42 +0300
> From: Janneke Nieuwenhuizen <janneke <at> gnu.org>
> Cc: 79441 <at> debbugs.gnu.org
> Date: Sat, 13 Sep 2025 17:01:45 +0200
> 
> > 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.

Yes, these all can happen.  I think if you use "git log -L" to show
changes in the relevant portions of the code, you will find bug
reports that describe those cases.

> 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 ;)

Thanks.  However, if it doesn't handle the case of receiving a partial
directory from the shell, it will cause regressions.




Information forwarded to bug-gnu-emacs <at> gnu.org:
bug#79441; Package emacs. (Sun, 14 Sep 2025 10:48:02 GMT) Full text and rfc822 format available.

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

From: Janneke Nieuwenhuizen <janneke <at> gnu.org>
To: Eli Zaretskii <eliz <at> gnu.org>
Cc: 79441 <at> debbugs.gnu.org
Subject: Re: bug#79441: [PATCH] Re: bug#79441: shell-resync-dirs breaks on
 PS1 with newline
Date: Sun, 14 Sep 2025 12:47:06 +0200
Eli Zaretskii writes:

>> From: Janneke Nieuwenhuizen <janneke <at> gnu.org>
>> Cc: 79441 <at> debbugs.gnu.org
>> Date: Sat, 13 Sep 2025 17:01:45 +0200
>> 
>> > Can you suggest how to solve this?
>> 
>> Good question!

[..]

>> 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.
>
> Yes, these all can happen.  I think if you use "git log -L" to show
> changes in the relevant portions of the code, you will find bug
> reports that describe those cases.

Okay.  I did not attempt to simplify the code, just tried to address
the regression.

-- 
Janneke Nieuwenhuizen <janneke <at> gnu.org>  | GNU LilyPond https://LilyPond.org
Freelance IT https://www.JoyOfSource.com | Avatar® https://AvatarAcademy.com




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.