]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix sorting in ls-lisp.el under -v
authorEli Zaretskii <eliz@gnu.org>
Sun, 5 Jun 2022 06:52:09 +0000 (09:52 +0300)
committerEli Zaretskii <eliz@gnu.org>
Sun, 5 Jun 2022 06:52:09 +0000 (09:52 +0300)
* lisp/ls-lisp.el (ls-lisp-version-lessp): Handle correctly the
case where strings begin with numerical parts.  More faithful
implementation of the 'strverscmp' spec for fractional parts.
(Bug#55787)

* test/lisp/ls-lisp-tests.el (ls-lisp-test-bug55787): New test.

lisp/ls-lisp.el
test/lisp/ls-lisp-tests.el

index 33dd98ef8d2b64fee882f83001042b26813f1569..6d1f449568ad42072f7a56bed8d554e4c991051b 100644 (file)
@@ -621,14 +621,22 @@ in some standard C libraries does."
                 (sub2 (substring s2 ni2 e2))
                 ;; "Fraction" is a numerical sequence with leading zeros.
                 (fr1 (string-match "\\`0+" sub1))
-                (fr2 (string-match "\\`0+" sub2)))
+                (efr1 (match-end 0))
+                (fr2 (string-match "\\`0+" sub2))
+                (efr2 (match-end 0)))
            (cond
-            ((and fr1 fr2)     ; two fractions, the shortest wins
-             (setq val (- val (- (length sub1) (length sub2)))))
+             ;; Two fractions: the longer one is less than the other,
+             ;; but only if the "common prefix" is all-zeroes,
+             ;; otherwise fall back on numerical comparison.
+            ((and fr1 fr2)
+             (if (or (and (< efr1 (- e1 ni1)) (< efr2 (- e2 ni2))
+                          (not (eq (aref sub1 efr1) (aref sub2 efr2))))
+                     (= efr1 (- e1 ni1)) (=  efr2 (- e2 ni2)))
+                 (setq val (- val (- (length sub1) (length sub2))))))
             (fr1               ; a fraction is always less than an integral
-             (setq val (- ni1)))
+             (setq val (- 0 ni1 1)))   ; make sure val is non-zero
             (fr2
-             (setq val ni2)))
+             (setq val (1+ ni2))))     ; make sure val is non-zero
            (if (zerop val)     ; fall back on numerical comparison
                (setq val (- (string-to-number sub1)
                             (string-to-number sub2))))
index 3e23fc74540a86e7c8664925608fa6129eda1a9b..39843defc2e314accb5d9e1b635c7b077ae8d708 100644 (file)
           (should (looking-back "[[:space:]]" (1- (point)))))
       (when (buffer-live-p buf) (kill-buffer buf)))))
 
+(ert-deftest ls-lisp-test-bug55787 ()
+  "Test proper sorting by version."
+  (let ((files1 (vector "34 klmn-300dpi.jpg"
+                        "34 klmn-300dpi.png"
+                        "054_xyz.jpg"
+                        "054_xyz.png"
+                        "91 opqrs.jpg"
+                        "91 opqrs.png"
+                        "0717-abcd.jpg"
+                        "0717-abcd.png"
+                        "1935 uv.jpg"
+                        "1935 uv.png"
+                        "FFFF_fghk.jpg"
+                        "FFFF_fghk.png"
+                        "hhhh.jpg"
+                       "hhhh.png"))
+        (files2 (vector "01.0" "10" "010" "01.2")))
+    (should (equal (sort files1
+                         (lambda (x y)
+                           (ls-lisp-version-lessp x y)))
+                   '["0717-abcd.jpg"
+                     "0717-abcd.png"
+                     "054_xyz.jpg"
+                     "054_xyz.png"
+                     "34 klmn-300dpi.jpg"
+                     "34 klmn-300dpi.png"
+                     "91 opqrs.jpg"
+                     "91 opqrs.png"
+                     "1935 uv.jpg"
+                     "1935 uv.png"
+                     "FFFF_fghk.jpg"
+                     "FFFF_fghk.png"
+                     "hhhh.jpg"
+                     "hhhh.png"]))
+    (should (equal (sort files2
+                         (lambda (x y)
+                           (ls-lisp-version-lessp x y)))
+                   '["01.0" "01.2" "010" "10"]))))
+
 (provide 'ls-lisp-tests)
 ;;; ls-lisp-tests.el ends here