branch: externals/denote
commit ffd3bef12b6c266e1725fe5493d4bed786d25017
Author: Protesilaos Stavrou <i...@protesilaos.com>
Commit: Protesilaos Stavrou <i...@protesilaos.com>

    Add 'random' order for denote-sort functions
    
    This applies to the command 'denote-sort-dired' ('denote-dired'), as
    well as the Org dynamic blocks defined in the package denote-org.
    
    Thanks to experimental-code-86 for making the suggestion in issue 572:
    <https://github.com/protesilaos/denote/issues/572>.
---
 README.org | 31 +++++++++++++++++++------------
 denote.el  | 44 ++++++++++++++++++++++++++++++--------------
 2 files changed, 49 insertions(+), 26 deletions(-)

diff --git a/README.org b/README.org
index bb6c443209..70cbafe36f 100644
--- a/README.org
+++ b/README.org
@@ -3535,24 +3535,31 @@ Here are some examples:
 :CUSTOM_ID: h:c958e087-1d23-4a25-afdd-db7bf5606b4c
 :END:
 
-When sorting by =title=, =keywords=, or =signature= with the
-~denote-sort-dired~ command, 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]]).
-These are subject to user configuration:
+When sorting by =title=, =keywords=, =signature=, =identifier=, or
+=random= 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:
 
 #+vindex: denote-sort-identifier-comparison-function
-- ~denote-sort-identifier-comparison-function~
+- ~denote-sort-identifier-comparison-function~ :: The function to sort
+  by the file name identifier.
 
 #+vindex: denote-sort-title-comparison-function
-- ~denote-sort-title-comparison-function~
+- ~denote-sort-title-comparison-function~ :: The function to sort by
+  the file name title.
 
 #+vindex: denote-sort-keywords-comparison-function
-- ~denote-sort-keywords-comparison-function~
+- ~denote-sort-keywords-comparison-function~ :: The function to sort
+  by the file name keywords.
 
 #+vindex: denote-sort-signature-comparison-function
-- ~denote-sort-signature-comparison-function~
+- ~denote-sort-signature-comparison-function~ :: The function to sort
+  by the file name signature.
 
-By default, all these user options use the same sorting function,
+By default, all these user options use the same comparison function,
 namely ~string-collate-lessp~. Users who have specific needs for any
 of those file name components can write their own sorting algorithms
 ([[#h:95345870-4ccd-484f-9adf-de4747ad5760][Sort signatures that include 
Luhmann-style sequences]]).
@@ -6308,9 +6315,9 @@ Denote is meant to be a collective effort.  Every bit of 
help matters.
   Prevos, Philip Kaludercic, Quiliro Ordóñez, Stephen R. Kifer, Stefan
   Monnier, Stefan Thesing, Thibaut Benjamin, Tomasz Hołubowicz,
   TomoeMami , Vedang Manerikar, Wesley Harvey, Zhenxu Xu, arsaber101,
-  bryanrinders, eum3l, ezchi, jarofromel, leinfink (Henrik), l-o-l-h
-  (Lincoln), mattyonweb, maxbrieiev, mentalisttraceur, pmenair,
-  relict007, skissue.
+  bryanrinders, eum3l, experimental-code-86, ezchi, jarofromel,
+  leinfink (Henrik), l-o-l-h (Lincoln), mattyonweb, maxbrieiev,
+  mentalisttraceur, pmenair, relict007, skissue.
 
 + Ideas and/or user feedback :: Abin Simon, Aditya Yadav, Alan
   Schmitt, Aleksandr Vityazev, Alex Griffin, Alex Hirschfeld, Alexis
diff --git a/denote.el b/denote.el
index 03d2c8acf9..cff0964820 100644
--- a/denote.el
+++ b/denote.el
@@ -1408,7 +1408,7 @@ Return the absolute path to the matching file."
 (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)
+(defconst denote-sort-components '(title keywords signature identifier random)
   "List of sorting keys applicable for `denote-sort-files' and related.")
 
 (defcustom denote-sort-identifier-comparison-function 
denote-sort-comparison-fallback-function
@@ -1478,8 +1478,9 @@ minibuffer prompt for which file name component to sort 
by."
           (const :tag "Sort by identifier (default)" identifier)
           (const :tag "Sort by title" title)
           (const :tag "Sort by keywords" keywords)
-          (const :tag "Sort by signature" signature))
-  :package-version '(denote . "3.1.0")
+          (const :tag "Sort by signature" signature)
+          (const :tag "Random order" random))
+  :package-version '(denote . "4.1.0")
   :group 'denote-sort)
 
 (defcustom denote-sort-dired-default-reverse-sort nil
@@ -1519,6 +1520,17 @@ The `%s' performs the comparison."
 (denote-sort--define-lessp keywords)
 (denote-sort--define-lessp signature)
 
+(defun denote-sort-random (elements)
+  "Shuffle ELEMENTS of list randomly."
+  (let* ((elements (copy-sequence elements))
+         (shuffled-list nil))
+    (while elements
+      (let* ((list-length (length elements))
+             (element (nth (random list-length) elements)))
+        (setq elements (delq element elements))
+        (push element shuffled-list)))
+    shuffled-list))
+
 ;;;###autoload
 (defun denote-sort-files (files component &optional reverse)
   "Returned sorted list of Denote FILES.
@@ -1534,17 +1546,21 @@ With COMPONENT as a nil value keep the original 
date-based
 sorting which relies on the identifier of each file name.
 
 With optional REVERSE as a non-nil value, reverse the sort order."
-  (let* ((files-to-sort (copy-sequence files))
-         (sort-fn (pcase component
-                    ((pred functionp) component)
-                    ('identifier #'denote-sort-identifier-lessp)
-                    ('title #'denote-sort-title-lessp)
-                    ('keywords #'denote-sort-keywords-lessp)
-                    ('signature #'denote-sort-signature-lessp)))
-         (sorted-files (if sort-fn (sort files sort-fn) files-to-sort)))
-    (if reverse
-        (reverse sorted-files)
-      sorted-files)))
+  (let ((files-to-sort (copy-sequence files)))
+    (if (eq component 'random)
+        (denote-sort-random files)
+      (let* ((sort-fn (pcase component
+                        ((pred functionp) component)
+                        ('identifier #'denote-sort-identifier-lessp)
+                        ('title #'denote-sort-title-lessp)
+                        ('keywords #'denote-sort-keywords-lessp)
+                        ('signature #'denote-sort-signature-lessp)))
+             (sorted-files (if sort-fn
+                               (sort files sort-fn)
+                             files-to-sort)))
+        (if reverse
+            (reverse sorted-files)
+          sorted-files)))))
 
 (defun denote-sort-get-directory-files (files-matching-regexp 
sort-by-component &optional reverse omit-current exclude-regexp)
   "Return sorted list of files in variable `denote-directory'.

Reply via email to