]> 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>
Sat, 6 Jan 2024 12:36:19 +0000 (13:36 +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 1d2dfa8fc4f966b1bf34ab42839265b374cf5659..072b707ace3330097187b79e02844eb440baccf9 100644 (file)
@@ -399,9 +399,18 @@ the minibuffer, or completes it and then submits it, depending on the
 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 5f517b3f54ba8ac4652bc3057643214722a940bd..65db5606e940b9f0eda7483a7094202f9858772f 100644 (file)
@@ -3666,6 +3666,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."
@@ -3732,6 +3756,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