bug-gnu-emacs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

bug#13575: 24.1; dired-mark-sexp misparses directory contents


From: Wolfgang Jenkner
Subject: bug#13575: 24.1; dired-mark-sexp misparses directory contents
Date: Tue, 29 Jan 2013 06:35:44 +0100
User-agent: Gnus/5.130006 (Ma Gnus v0.6) Emacs/24.3.50 (berkeley-unix)

On Mon, Jan 28 2013, Wolfgang Jenkner wrote:

> As a first attempt
> to fix this I propose the following barely tested patch.

Or perhaps rather try the patch below, which I tested a bit with GNU and
FreeBSD ls, and also with ls-lisp.el.  It's still WIP but I hope it
works for you.

Please note that the output of "ls -lh" is parsed correctly, but the
unit suffixes are simply ignored for the time being; I'll try to fix
this, though.

Also, specifying "-s" without also passing "-i" to "ls" will do the
wrong thing: the output being ambiguous in this case, a number before
the permission string is (arbitrarily) interpreted as inode number; that
can't be fixed without actually looking at dired-listing-switches.

Wolfgang

diff --git a/lisp/dired-x.el b/lisp/dired-x.el
index a2c1303..5a33479 100644
--- a/lisp/dired-x.el
+++ b/lisp/dired-x.el
@@ -1449,54 +1449,57 @@ to mark all zero length files."
         ;; to nil or the appropriate value, so they need not be initialized.
         ;; Moves point within the current line.
         (dired-move-to-filename)
-        (let (pos
-              (mode-len 10) ; length of mode string
-              ;; like in dired.el, but with subexpressions \1=inode, \2=s:
-              (dired-re-inode-size "\\s *\\([0-9]*\\)\\s *\\([0-9]*\\) ?"))
-          (beginning-of-line)
-          (forward-char 2)
-          (if (looking-at dired-re-inode-size)
-              (progn
-                (goto-char (match-end 0))
-                (setq inode (string-to-number
-                             (buffer-substring (match-beginning 1)
-                                               (match-end 1)))
-                      s (string-to-number
-                         (buffer-substring (match-beginning 2)
-                                           (match-end 2)))))
-            (setq inode nil
-                  s nil))
+        (let ((mode-len 10) ; length of mode string
+             ;; like in dired.el, but with subexpressions \1=inode, \2=s:
+             ;; GNU ls -hs suffixes the block count with a unit and
+             ;; prints it as a float, FreeBSD does neither.
+             (dired-re-inode-size "\\=\\s *\\([0-9]+\\s 
+\\)?\\(?:\\([0-9]+\\(?:\\.[0-9]*\\)?[BkKMGTPEZY]?\\)? ?\\)"))
+         (beginning-of-line)
+         (forward-char 2)
+         (search-forward-regexp dired-re-inode-size nil t)
+         ;; XXX Might be a size without unit.
+         (setq inode (when (match-string 1)
+                       (string-to-number (match-string 1))))
+         (setq s (when (match-string 2)
+                   ;; XXX Deal with units (for the -h switch).
+                   (string-to-number (match-string 2))))
           (setq mode (buffer-substring (point) (+ mode-len (point))))
           (forward-char mode-len)
           (setq nlink (read (current-buffer)))
           ;; Karsten Wenger <kw@cis.uni-muenchen.de> fixed uid.
-          (setq uid (buffer-substring (1+ (point))
-                                      (progn (forward-word 1) (point))))
-          (re-search-forward directory-listing-before-filename-regexp)
-          (goto-char (match-beginning 1))
-          (forward-char -1)
-          (setq size (string-to-number
-                      (buffer-substring (save-excursion
-                                          (backward-word 1)
-                                          (setq pos (point)))
-                                        (point))))
-          (goto-char pos)
-          (backward-word 1)
-          ;; if no gid is displayed, gid will be set to uid
-          ;; but user will then not reference it anyway in PREDICATE.
-          (setq gid (buffer-substring (save-excursion
-                                        (forward-word 1) (point))
-                                      (point))
-                time (buffer-substring (match-beginning 1)
-                                       (1- (dired-move-to-filename)))
-                name (buffer-substring (point)
-                                       (or
-                                        (dired-move-to-end-of-filename t)
-                                        (point)))
-                sym (if (looking-at " -> ")
-                        (buffer-substring (progn (forward-char 4) (point))
-                                          (line-end-position))
-                      ""))
+         ;; GNU ls -n right-justifies numerical UIDs and GIDs,
+         ;; while FreeBSD left-justifies them.  Both of them
+         ;; right-justify all other numbers.
+          (setq uid (buffer-substring (progn (forward-word 1) (point))
+                                      (progn (forward-word -1) (point))))
+         (dired-move-to-filename)
+         (save-excursion
+           ;; Don't do (forward-char -1) since the regexp search will
+           ;; then match in the preceding line.
+           (setq time (buffer-substring (1- (point))
+                                        (progn
+                                          (re-search-backward 
directory-listing-before-filename-regexp)
+                                          (forward-word 1)
+                                          (1+ (point))))
+                 ;; XXX Deal with units (for the -h switch).
+                 size (string-to-number
+                       (buffer-substring (point) (progn (forward-word -1)
+                                                        (when (= (char-before) 
?.)
+                                                          (forward-char -1)
+                                                          (forward-word -1))
+                                                        (point))))
+                 ;; if no gid is displayed, gid will be set to uid
+                 ;; but user will then not reference it anyway in PREDICATE.
+                 gid (buffer-substring (progn (forward-word -1) (point))
+                                       (progn (forward-word 1) (point)))))
+         (setq name (buffer-substring (point)
+                                      (or
+                                       (dired-move-to-end-of-filename t)
+                                       (point)))
+               sym (if (looking-at " -> ")
+                       (buffer-substring (progn (forward-char 4) (point))
+                                         (line-end-position))
+                     ""))
           t)
         (eval predicate)))
      (format "'%s file" predicate))))





reply via email to

[Prev in Thread] Current Thread [Next in Thread]