branch: externals/denote commit 875c82c85d7fdea88d5a540dcf2d1ff454501885 Merge: 322d6d493e f984340947 Author: Protesilaos Stavrou <i...@protesilaos.com> Commit: GitHub <nore...@github.com>
Merge pull request #541 from frnsd/fix-sequence-prefix Add tests for false matches addressed by pull request #540 and fix related issues --- denote-sequence.el | 57 +++++++++++------ tests/denote-test.el | 171 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 144 insertions(+), 84 deletions(-) diff --git a/denote-sequence.el b/denote-sequence.el index 858c311a0a..d448545972 100644 --- a/denote-sequence.el +++ b/denote-sequence.el @@ -340,19 +340,36 @@ With optional FILES consider only those, otherwise use the return value of `denote-directory-files'." (seq-filter #'denote-sequence-file-p (denote-sequence--get-files files))) +(defun denote-sequence--sequence-prefix-p (prefix sequence) + "Return non-nil if SEQUENCE has prefix sequence PREFIX. + +SEQUENCE is a Denote signatures that conforms with `denote-sequence-p'. +PREFIX is a list of strings containing the components of the prefix +sequence, as is returned by `denote-sequence-split'. + +If PREFIX is nil, return non-nil as if the SEQUENCE has PREFIX." + (let ((value (denote-sequence-split sequence)) + (depth (length prefix)) + (matched 0)) + (while (and value + (< matched depth) + (string-equal (pop value) (nth matched prefix))) + (setq matched (1+ matched))) + (= matched depth))) + (defun denote-sequence-get-all-files-with-prefix (sequence &optional files) "Return all files in variable `denote-directory' with prefix SEQUENCE. A sequence is a Denote signature that conforms with `denote-sequence-p'. With optional FILES, operate on them, else use the return value of `denote-directory-files'." - (delq nil - (mapcar - (lambda (file) - (when-let* ((file-sequence (denote-sequence-file-p file)) - ((string-prefix-p sequence file-sequence))) - file)) - (denote-sequence-get-all-files files)))) + (when-let* (((not (string-empty-p sequence))) + (prefix (denote-sequence-split sequence))) + (seq-filter + (lambda (file) + (when-let* ((file-sequence (denote-sequence-file-p file))) + (denote-sequence--sequence-prefix-p prefix file-sequence))) + (denote-sequence-get-all-files files)))) (defun denote-sequence-get-all-files-with-max-depth (depth &optional files) "Return all files with sequence depth up to DEPTH (inclusive). @@ -380,17 +397,11 @@ With optional SEQUENCES operate on those, else use the return value of `denote-sequence-get-all-sequences'. A sequence is a Denote signature that conforms with `denote-sequence-p'." - (let* ((prefix (denote-sequence-split sequence)) - (depth (length prefix))) + (when-let* (((not (string-empty-p sequence))) + (prefix (denote-sequence-split sequence))) (seq-filter (lambda (string) - (let ((value (denote-sequence-split string)) - (matched 0)) - (while (and value - (< matched depth) - (string-equal (pop value) (nth matched prefix))) - (setq matched (1+ matched))) - (= matched depth))) + (denote-sequence--sequence-prefix-p prefix string)) (or sequences (denote-sequence-get-all-sequences))))) (defun denote-sequence-get-all-sequences-with-max-depth (depth &optional sequences) @@ -612,7 +623,7 @@ returned by `denote-sequence-get-all-files'." (lambda (file) (= (denote-sequence-depth (denote-sequence-file-p file)) (+ depth 1))) (funcall filter-common '> sequence))) - (_ (error "The type `%s' is not among the `denote-sequence-types'" type))))) + (_ (error "The type `%s' is not among the allowed types" type))))) (defvar denote-sequence-type-history nil "Minibuffer history of `denote-sequence-type-prompt'.") @@ -908,10 +919,18 @@ For a more specialised case, see `denote-sequence-find-relatives-dired'." (defun denote-sequence-find-dired (type) "Like `denote-sequence-find' for TYPE but put the matching files in Dired. Also see `denote-sequence-dired'." - (interactive (list (denote-sequence-type-prompt "Find relatives of TYPE"))) + (interactive + (list (denote-sequence-type-prompt "Find relatives of TYPE" + '(all-parents + parent + siblings + all-children + children)))) (if-let* ((sequence (denote-sequence-file-p buffer-file-name))) (if-let* ((default-directory (denote-directory)) - (relatives (delete buffer-file-name (denote-sequence-get-relative sequence type))) + (relatives (delete buffer-file-name + (ensure-list + (denote-sequence-get-relative sequence type)))) (files-sorted (denote-sequence-sort-files relatives))) (dired (cons (format-message "*`%s' type relatives of `%s'" type sequence) (mapcar #'file-relative-name files-sorted))) diff --git a/tests/denote-test.el b/tests/denote-test.el index bcb9a624a9..209f906c7e 100644 --- a/tests/denote-test.el +++ b/tests/denote-test.el @@ -616,9 +616,15 @@ function `denote-sequence-get-relative'." "20241230T075023==1=2--test__testing.txt" "20241230T075023==1=2=1--test__testing.txt" "20241230T075023==1=2=1=1--test__testing.txt" - "20241230T075023==2--test__testing.txt"))) + "20241230T075023==2--test__testing.txt" + "20241230T075023==10--test__testing.txt" + "20241230T075023==10=1--test__testing.txt" + "20241230T075023==10=1=1--test__testing.txt" + "20241230T075023==10=2--test__testing.txt" + "20241230T075023==10=10--test__testing.txt" + "20241230T075023==10=10=1--test__testing.txt"))) (sequences (denote-sequence-get-all-sequences files))) - (should (string= (denote-sequence-get-new 'parent) "3")) + (should (string= (denote-sequence-get-new 'parent) "11")) (should (and (string= (denote-sequence-get-new 'child "1" sequences) "1=3") (string= (denote-sequence-get-new 'child "1=1" sequences) "1=1=3") @@ -626,96 +632,131 @@ function `denote-sequence-get-relative'." (string= (denote-sequence-get-new 'child "1=2" sequences) "1=2=2") (string= (denote-sequence-get-new 'child "1=2=1" sequences) "1=2=1=2") (string= (denote-sequence-get-new 'child "2" sequences) "2=1"))) - (should-error (denote-sequence-get-new 'child "3" sequences)) + (should-error (denote-sequence-get-new 'child "11" sequences)) - (should (and (string= (denote-sequence-get-new 'sibling "1" sequences) "3") + (should (and (string= (denote-sequence-get-new 'sibling "1" sequences) "11") (string= (denote-sequence-get-new 'sibling "1=1" sequences) "1=3") (string= (denote-sequence-get-new 'sibling "1=1=1" sequences) "1=1=3") (string= (denote-sequence-get-new 'sibling "1=1=2" sequences) "1=1=3") (string= (denote-sequence-get-new 'sibling "1=2" sequences) "1=3") (string= (denote-sequence-get-new 'sibling "1=2=1" sequences) "1=2=2") - (string= (denote-sequence-get-new 'sibling "2" sequences) "3"))) - (should-error (denote-sequence-get-new 'sibling "4" sequences)) + (string= (denote-sequence-get-new 'sibling "2" sequences) "11"))) + (should-error (denote-sequence-get-new 'sibling "12" sequences)) (should (string= (denote-sequence-get-relative "1=2=1=1" 'parent files) (expand-file-name "20241230T075023==1=2=1--test__testing.txt" denote-directory))) + (should (string= (denote-sequence-get-relative "10=1=1" 'parent files) + (expand-file-name "20241230T075023==10=1--test__testing.txt" denote-directory))) + (should (string= (denote-sequence-get-relative "10=10=1" 'parent files) + (expand-file-name "20241230T075023==10=10--test__testing.txt" denote-directory))) (should (equal (denote-sequence-get-relative "1=2=1=1" 'all-parents files) (list (expand-file-name "20241230T075023==1--test__testing.txt" denote-directory) (expand-file-name "20241230T075023==1=2--test__testing.txt" denote-directory) (expand-file-name "20241230T075023==1=2=1--test__testing.txt" denote-directory)))) + (should (equal (denote-sequence-get-relative "10=1=1" 'all-parents files) + (list + (expand-file-name "20241230T075023==10--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==10=1--test__testing.txt" denote-directory)))) + (should (equal (denote-sequence-get-relative "10=10=1" 'all-parents files) + (list + (expand-file-name "20241230T075023==10--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==10=10--test__testing.txt" denote-directory)))) (should (equal (denote-sequence-get-relative "1=1" 'siblings files) (list (expand-file-name "20241230T075023==1=1--test__testing.txt" denote-directory) (expand-file-name "20241230T075023==1=2--test__testing.txt" denote-directory)))) + (should (equal (denote-sequence-get-relative "10=1" 'siblings files) + (list + (expand-file-name "20241230T075023==10=1--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==10=2--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==10=10--test__testing.txt" denote-directory)))) (should (equal (denote-sequence-get-relative "1" 'children files) (list (expand-file-name "20241230T075023==1=1--test__testing.txt" denote-directory) (expand-file-name "20241230T075023==1=2--test__testing.txt" denote-directory)))) + (should (equal (denote-sequence-get-relative "10" 'children files) + (list + (expand-file-name "20241230T075023==10=1--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==10=2--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==10=10--test__testing.txt" denote-directory)))) (should (equal (denote-sequence-get-relative "1=1" 'all-children files) (list (expand-file-name "20241230T075023==1=1=1--test__testing.txt" denote-directory) (expand-file-name "20241230T075023==1=1=2--test__testing.txt" denote-directory))))) - (let* ((denote-sequence-scheme 'alphanumeric) - (denote-directory (expand-file-name "denote-test" temporary-file-directory)) - (files - (mapcar - (lambda (file) - (let ((path (expand-file-name file (denote-directory)))) - (if (file-exists-p path) - path - (with-current-buffer (find-file-noselect path) - (save-buffer) - (kill-buffer (current-buffer))) - path))) - '("20241230T075023==1--test__testing.txt" - "20241230T075023==1a--test__testing.txt" - "20241230T075023==1a1--test__testing.txt" - "20241230T075023==1a2--test__testing.txt" - "20241230T075023==1b--test__testing.txt" - "20241230T075023==1b1--test__testing.txt" - "20241230T075023==1b1a--test__testing.txt" - "20241230T075023==2--test__testing.txt"))) - (sequences (denote-sequence-get-all-sequences files))) - (should (string= (denote-sequence-get-new 'parent) "3")) - - (should (and (string= (denote-sequence-get-new 'child "1" sequences) "1c") - (string= (denote-sequence-get-new 'child "1a" sequences) "1a3") - (string= (denote-sequence-get-new 'child "1a2" sequences) "1a2a") - (string= (denote-sequence-get-new 'child "1b" sequences) "1b2") - (string= (denote-sequence-get-new 'child "1b1" sequences) "1b1b") - (string= (denote-sequence-get-new 'child "2" sequences) "2a"))) - (should-error (denote-sequence-get-new 'child "3" sequences)) - - (should (and (string= (denote-sequence-get-new 'sibling "1" sequences) "3") - (string= (denote-sequence-get-new 'sibling "1a" sequences) "1c") - (string= (denote-sequence-get-new 'sibling "1a1" sequences) "1a3") - (string= (denote-sequence-get-new 'sibling "1a2" sequences) "1a3") - (string= (denote-sequence-get-new 'sibling "1b" sequences) "1c") - (string= (denote-sequence-get-new 'sibling "1b1" sequences) "1b2") - (string= (denote-sequence-get-new 'sibling "2" sequences) "3"))) - (should-error (denote-sequence-get-new 'sibling "4" sequences)) - - (should (string= (denote-sequence-get-relative "1b1a" 'parent files) - (expand-file-name "20241230T075023==1b1--test__testing.txt" denote-directory))) - (should (equal (denote-sequence-get-relative "1b1a" 'all-parents files) - (list - (expand-file-name "20241230T075023==1--test__testing.txt" denote-directory) - (expand-file-name "20241230T075023==1b--test__testing.txt" denote-directory) - (expand-file-name "20241230T075023==1b1--test__testing.txt" denote-directory)))) - (should (equal (denote-sequence-get-relative "1a" 'siblings files) - (list - (expand-file-name "20241230T075023==1a--test__testing.txt" denote-directory) - (expand-file-name "20241230T075023==1b--test__testing.txt" denote-directory)))) - (should (equal (denote-sequence-get-relative "1" 'children files) - (list - (expand-file-name "20241230T075023==1a--test__testing.txt" denote-directory) - (expand-file-name "20241230T075023==1b--test__testing.txt" denote-directory)))) - (should (equal (denote-sequence-get-relative "1a" 'all-children files) - (list - (expand-file-name "20241230T075023==1a1--test__testing.txt" denote-directory) - (expand-file-name "20241230T075023==1a2--test__testing.txt" denote-directory)))))) + (let* ((denote-sequence-scheme 'alphanumeric) + (denote-directory (expand-file-name "denote-test" temporary-file-directory)) + (files + (mapcar + (lambda (file) + (let ((path (expand-file-name file (denote-directory)))) + (if (file-exists-p path) + path + (with-current-buffer (find-file-noselect path) + (save-buffer) + (kill-buffer (current-buffer))) + path))) + '("20241230T075023==1--test__testing.txt" + "20241230T075023==1a--test__testing.txt" + "20241230T075023==1a1--test__testing.txt" + "20241230T075023==1a2--test__testing.txt" + "20241230T075023==1b--test__testing.txt" + "20241230T075023==1b1--test__testing.txt" + "20241230T075023==1b1a--test__testing.txt" + "20241230T075023==2--test__testing.txt" + "20241230T075023==10--test__testing.txt" + "20241230T075023==10a--test__testing.txt" + "20241230T075023==10b--test__testing.txt"))) + (sequences (denote-sequence-get-all-sequences files))) + (should (string= (denote-sequence-get-new 'parent) "11")) + + (should (and (string= (denote-sequence-get-new 'child "1" sequences) "1c") + (string= (denote-sequence-get-new 'child "1a" sequences) "1a3") + (string= (denote-sequence-get-new 'child "1a2" sequences) "1a2a") + (string= (denote-sequence-get-new 'child "1b" sequences) "1b2") + (string= (denote-sequence-get-new 'child "1b1" sequences) "1b1b") + (string= (denote-sequence-get-new 'child "2" sequences) "2a"))) + (should-error (denote-sequence-get-new 'child "11" sequences)) + + (should (and (string= (denote-sequence-get-new 'sibling "1" sequences) "11") + (string= (denote-sequence-get-new 'sibling "1a" sequences) "1c") + (string= (denote-sequence-get-new 'sibling "1a1" sequences) "1a3") + (string= (denote-sequence-get-new 'sibling "1a2" sequences) "1a3") + (string= (denote-sequence-get-new 'sibling "1b" sequences) "1c") + (string= (denote-sequence-get-new 'sibling "1b1" sequences) "1b2") + (string= (denote-sequence-get-new 'sibling "2" sequences) "11"))) + (should-error (denote-sequence-get-new 'sibling "12" sequences)) + + (should (string= (denote-sequence-get-relative "1b1a" 'parent files) + (expand-file-name "20241230T075023==1b1--test__testing.txt" denote-directory))) + (should (string= (denote-sequence-get-relative "10a" 'parent files) + (expand-file-name "20241230T075023==10--test__testing.txt" denote-directory))) + (should (equal (denote-sequence-get-relative "1b1a" 'all-parents files) + (list + (expand-file-name "20241230T075023==1--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==1b--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==1b1--test__testing.txt" denote-directory)))) + (should (equal (denote-sequence-get-relative "1a" 'siblings files) + (list + (expand-file-name "20241230T075023==1a--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==1b--test__testing.txt" denote-directory)))) + (should (equal (denote-sequence-get-relative "10a" 'siblings files) + (list + (expand-file-name "20241230T075023==10a--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==10b--test__testing.txt" denote-directory)))) + (should (equal (denote-sequence-get-relative "1" 'children files) + (list + (expand-file-name "20241230T075023==1a--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==1b--test__testing.txt" denote-directory)))) + (should (equal (denote-sequence-get-relative "10" 'children files) + (list + (expand-file-name "20241230T075023==10a--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==10b--test__testing.txt" denote-directory)))) + (should (equal (denote-sequence-get-relative "1a" 'all-children files) + (list + (expand-file-name "20241230T075023==1a1--test__testing.txt" denote-directory) + (expand-file-name "20241230T075023==1a2--test__testing.txt" denote-directory)))))) (ert-deftest dt-denote-sequence-split () "Test that `denote-sequence-split' splits a sequence correctly."