]> git.eshelyaron.com Git - emacs.git/commitdiff
Support sorting file name completions list by last modified time
authorEshel Yaron <me@eshelyaron.com>
Sat, 6 Jan 2024 12:31:23 +0000 (13:31 +0100)
committerEshel Yaron <me@eshelyaron.com>
Fri, 19 Jan 2024 10:33:54 +0000 (11:33 +0100)
(minibuffer--sort-file-names-by-last-modified-time): New function.
(read-file-name-default): Add it to
'minibuffer-completions-sort-orders' buffer-locally.
* doc/emacs/mini.texi (Completion Commands): Elaborate about
'minibuffer-sort-completions'.

doc/emacs/mini.texi
lisp/minibuffer.el

index 40d9ae7d4dc07ceea47b94f40d842be86af3ca55..320b88ea59458de834aaedfbaf9ab0b4b1891b76 100644 (file)
@@ -445,9 +445,18 @@ complete again.
 of the completions list.  By default, Emacs sorts the list of possible
 completion candidates in the order that you specify in user option
 @code{completions-sort} (@pxref{Completion Options}).  This command
-lets you change the order of the current completions list interactively.
-You can invoke it with a negative prefix argument (@kbd{C-- C-x C-v}) to
-reverse the current order.
+lets you change the order of the current completions list
+interactively.  You can invoke it with a negative prefix argument
+(@kbd{C-- C-x C-v}) to reverse the current order.  The user option
+@code{minibuffer-completions-sort-orders} determines which orders this
+command suggests for sorting the completions list.  By default, this
+includes alphabetical sorting, sorting by candidate position in the
+minibuffer history, and no sorting at all.  Some commands that use
+minibuffer completion also provide additional sorting options that are
+specifically useful with their completion candidates.  For example,
+during file name completion, as in @kbd{C-x C-f} (@pxref{Visiting}),
+you can use @key{C-x C-v} to sort candidate file names chronologically
+by their last modified time.
 
 @kindex C-x n n @r{(completion)}
 @findex minibuffer-narrow-completions-to-current
index b9fe3df7f8473a318c4a387d77ba91fb5c0cced1..31e70014d2d729e0653c3a94e52fb90f315354db 100644 (file)
@@ -3937,6 +3937,30 @@ and `read-file-name-function'."
 ;; instead, but for now, let's keep this non-obsolete.
 ;;(make-obsolete-variable 'minibuffer-completing-file-name nil "future" 'get)
 
+(defun minibuffer--sort-file-names-by-last-modified-time (files)
+  "Sort file name completion candidates FILES by last modified time."
+  (let ((file-time-alist
+         (mapcar (lambda (file)
+                   (cons file
+                         (file-attribute-modification-time
+                          (ignore-errors
+                            (file-attributes
+                             (substitute-in-file-name
+                              (concat minibuffer-completion-base file)))))))
+                 files)))
+    (sort files (lambda (a b)
+                  (let ((atime (alist-get a file-time-alist
+                                          nil nil #'string=))
+                        (btime (alist-get b file-time-alist
+                                          nil nil #'string=)))
+                    (if atime
+                        (or (not btime)
+                            ;; Put more recently modified files first.
+                            (time-less-p btime atime)
+                            (and (time-equal-p atime btime)
+                                 (string-lessp a b)))
+                      (and (not btime) (string-lessp a b))))))))
+
 (defun read-file-name-default (prompt &optional dir default-filename mustmatch initial predicate)
   "Default method for reading file names.
 See `read-file-name' for the meaning of the arguments."
@@ -4003,6 +4027,12 @@ See `read-file-name' for the meaning of the arguments."
                                  (with-current-buffer
                                      (window-buffer (minibuffer-selected-window))
                                   (read-file-name--defaults dir initial))))
+                          (setq-local
+                           minibuffer-completions-sort-orders
+                           (cons '(?m "modified" "Sort by last modified time"
+                                      minibuffer--sort-file-names-by-last-modified-time
+                                      "latest modified first")
+                                 minibuffer-completions-sort-orders))
                          (set-syntax-table minibuffer-local-filename-syntax))
                       (completing-read prompt 'read-file-name-internal
                                        pred mustmatch insdef