all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Lars Ingebrigtsen <larsi@gnus.org>
To: Noam Postavsky <npostavs@gmail.com>
Cc: 23324@debbugs.gnu.org, Noah Friedman <friedman@splode.com>
Subject: bug#23324: shell-resync-dirs does not handle dirs with whitespace
Date: Wed, 12 Aug 2020 13:44:51 +0200	[thread overview]
Message-ID: <87eeocnl58.fsf@gnus.org> (raw)
In-Reply-To: <8736uqik4l.fsf@gmail.com> (Noam Postavsky's message of "Mon, 03 Sep 2018 13:08:42 -0400")

Noam Postavsky <npostavs@gmail.com> writes:

> I think this loop is going in the wrong direction (i.e., it should
> rather be appending leading entries).  Because of this, it can be fooled
> by subdirectories with a name matching a substring of a dirs entry:
>
>     ~$ mkdir -p 'foo bar/bar/'
>     ~$ cd 'foo bar/'
>     ~/foo bar$ command dirs # M-x dirs
>     # infloops...
>
>> +          (let ((newelt "")
>> +                tem1 tem2)
>
> I'm also not a fan of the somewhat inscrutable tem1 & tem2 names.

I've respun the patch so that it actually works (tem1 was mis-spelled in
one place, and there was a bunch of unrelated white space fix-ups that
I've remove), but haven't done anything else to it.

Noam, I tried your test case, but I couldn't get it to infloop.  Is
there some additional steps needed to make it infloop?

diff --git a/lisp/shell.el b/lisp/shell.el
index f5e18bbc72..ed4b1efde0 100644
--- a/lisp/shell.el
+++ b/lisp/shell.el
@@ -1039,24 +1039,40 @@ shell-resync-dirs
 	  (goto-char pt)))
       (goto-char pmark) (delete-char 1) ; remove the extra newline
       ;; That's the dirlist. grab it & parse it.
-      (let* ((dl (buffer-substring (match-beginning 2) (1- (match-end 2))))
-	     (dl-len (length dl))
-	     (ds '())			; new dir stack
-	     (i 0))
-	(while (< i dl-len)
-	  ;; regexp = optional whitespace, (non-whitespace), optional whitespace
-	  (string-match "\\s *\\(\\S +\\)\\s *" dl i) ; pick off next dir
-	  (setq ds (cons (concat comint-file-name-prefix
-				 (substring dl (match-beginning 1)
-					    (match-end 1)))
-			 ds))
-	  (setq i (match-end 0)))
-	(let ((ds (nreverse ds)))
-	  (with-demoted-errors "Couldn't cd: %s"
-	    (shell-cd (car ds))
-	    (setq shell-dirstack (cdr ds)
-		  shell-last-dir (car shell-dirstack))
-	    (shell-dirstack-message)))))
+      (let* ((dls (buffer-substring-no-properties
+                   (match-beginning 0) (1- (match-end 0))))
+             (dlsl '())
+             (pos 0)
+             (ds '()))
+        ;; Split the dirlist into whitespace and non-whitespace chunks.
+        ;; dlsl will be a reversed list of tokens.
+        (while (string-match "\\(\\S-+\\|\\s-+\\)" dls pos)
+          (push (match-string 1 dls) dlsl)
+          (setq pos (match-end 1)))
+
+        ;; prepend trailing entries until they form an existing directory,
+        ;; whitespace and all.  discard the next whitespace and repeat.
+        (while dlsl
+          (let ((newelt "")
+                tem1 tem2)
+            (while newelt
+              ;; We need tem1 because we don't want to prepend
+              ;; comint-file-name-prefix repeatedly into newelt via tem2.
+              (setq tem1 (pop dlsl)
+                    tem2 (concat comint-file-name-prefix tem1 newelt))
+              (cond ((file-directory-p tem2)
+                     (push tem2 ds)
+                     (when (string= " " (car dlsl))
+                       (pop dlsl))
+                     (setq newelt nil))
+                    (t
+                     (setq newelt (concat tem1 newelt)))))))
+
+        (with-demoted-errors "Couldn't cd: %s"
+          (shell-cd (car ds))
+          (setq shell-dirstack (cdr ds)
+                shell-last-dir (car shell-dirstack))
+          (shell-dirstack-message))))
     (if started-at-pmark (goto-char (marker-position pmark)))))
 
 ;; For your typing convenience:

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





  reply	other threads:[~2020-08-12 11:44 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-04-21  2:38 bug#23324: shell-resync-dirs does not handle dirs with whitespace Noah Friedman
2018-09-03 17:08 ` Noam Postavsky
2020-08-12 11:44   ` Lars Ingebrigtsen [this message]
2020-08-19 14:00     ` bug#11608: " Lars Ingebrigtsen
2019-06-27 16:25 ` bug#9379: " Lars Ingebrigtsen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87eeocnl58.fsf@gnus.org \
    --to=larsi@gnus.org \
    --cc=23324@debbugs.gnu.org \
    --cc=friedman@splode.com \
    --cc=npostavs@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.