branch: externals/denote commit fb5b4e31f6d743b9356034ed96e1923e4bedb88f Author: Protesilaos Stavrou <i...@protesilaos.com> Commit: Protesilaos Stavrou <i...@protesilaos.com>
Add optional "last modified" sort to denote-dired and denote-query-sorting --- README.org | 20 ++++++++++++-------- denote.el | 26 +++++++++++++++++++++----- 2 files changed, 33 insertions(+), 13 deletions(-) diff --git a/README.org b/README.org index f969eea6ed..b2fc3b181b 100644 --- a/README.org +++ b/README.org @@ -3581,13 +3581,15 @@ Here are some examples: :CUSTOM_ID: h:c958e087-1d23-4a25-afdd-db7bf5606b4c :END: -When sorting by =title=, =keywords=, =signature=, =identifier=, or -=random= with the ~denote-dired~ command (alias ~denote-sort-dired~), +[ The =random= and =last-modified= sort are part of {{{development-version}}}. ] + +When sorting by =title=, =keywords=, =signature=, =identifier=, +=random=, or =last-modified= with the ~denote-dired~ command (alias ~denote-sort-dired~), Denote will internally apply a sorting function that is specific to each component ([[#h:a34228cb-484f-48fe-9cbc-8e41f313127b][Configure what extra prompts ~denote-sort-dired~ issues]]). -With the exception of =random=, the sorting of file name components -is subject to user configuration: +With the exception of =random= and =last-modified=, the sorting of +file name components is subject to user configuration: #+vindex: denote-sort-identifier-comparison-function - ~denote-sort-identifier-comparison-function~ :: The function to sort @@ -3786,10 +3788,12 @@ the ~denote-grep~ command: By default, no sorting of matching files is performed. They appear in the query buffer in the order they were retrieved. -The ~denote-query-sorting~ can be set to a symbol among =title=, -=keywords=, =signature=, or =identifier= to sort by the given file -name component ([[#h:4e9c7512-84dc-4dfb-9fa9-e15d51178e5d][The file-naming scheme]]). The symbol =random= produces -a random order each time. +#+vindex: denote-sort-components +The ~denote-query-sorting~ can be set to a symbol among those listed +in the value of the variable ~denote-sort-components~ to sort by the +given file name component ([[#h:4e9c7512-84dc-4dfb-9fa9-e15d51178e5d][The file-naming scheme]]). The symbol +=random= produces a random order each time, while =last-modified= +relies on the file system to sort by the modification time. The ~denote-query-sorting~ can also be set to the symbol of a function. In that case, the given function is used to perform the diff --git a/denote.el b/denote.el index e3a4a14a60..4d0fc65130 100644 --- a/denote.el +++ b/denote.el @@ -1527,7 +1527,7 @@ is a special buffer." (defconst denote-sort-comparison-fallback-function #'string-collate-lessp "String comparison function used by `denote-sort-files' subroutines.") -(defconst denote-sort-components '(title keywords signature identifier random) +(defconst denote-sort-components '(title keywords signature identifier random last-modified) "List of sorting keys applicable for `denote-sort-files' and related.") (defcustom denote-sort-identifier-comparison-function denote-sort-comparison-fallback-function @@ -1650,6 +1650,19 @@ The `%s' performs the comparison." (push element shuffled-list))) shuffled-list)) +(defun denote-sort-modified-time-greaterp (file1 file2) + "Return non-nil if FILE1 modified time is greater than that of FILE2." + (let* ((attributes1 (file-attributes file1)) + (mod-time1-raw (file-attribute-modification-time attributes1)) + (mod-time1-seconds (time-to-seconds mod-time1-raw)) + (attributes2 (file-attributes file2)) + (mod-time2-raw (file-attribute-modification-time attributes2)) + (mod-time2-seconds (time-to-seconds mod-time2-raw))) + ;; NOTE 2025-06-23: We normally sort using a "less" approach, but + ;; here we want to capture the semantics of "last modified" + ;; without relying on a reverse sort. + (> mod-time1-seconds mod-time2-seconds))) + ;;;###autoload (defun denote-sort-files (files component &optional reverse) "Returned sorted list of Denote FILES. @@ -1673,7 +1686,8 @@ With optional REVERSE as a non-nil value, reverse the sort order." ('identifier #'denote-sort-identifier-lessp) ('title #'denote-sort-title-lessp) ('keywords #'denote-sort-keywords-lessp) - ('signature #'denote-sort-signature-lessp))) + ('signature #'denote-sort-signature-lessp) + ('last-modified #'denote-sort-modified-time-greaterp))) (sorted-files (if sort-fn (sort files sort-fn) files-to-sort))) @@ -1746,9 +1760,10 @@ OMIT-CURRENT have been applied." ("keywords" "The keywords of the file name") ("signature" "The signature of the file name") ("identifier" "The identifier of the file name") - ("random" "Random file sort")))) + ("random" "Random file sort") + ("last-modified" "File last modification time")))) (format "%s-- %s" - (propertize " " 'display '(space :align-to 12)) + (propertize " " 'display '(space :align-to 15)) (propertize text 'face 'completions-annotations)))) (defun denote-sort-component-prompt () @@ -5430,7 +5445,8 @@ order to sort file names interactively in the query buffer." (const :tag "Sort by title" title) (const :tag "Sort by keywords" keywords) (const :tag "Sort by signature" signature) - (const :tag "Random order" random)) + (const :tag "Random order" random) + (const :tag "Last modified" last-modified)) :package-version '(denote . "4.1.0") :group 'denote-query)