emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] master e6d38ec 086/135: Added relatives finder


From: Ian Dunn
Subject: [elpa] master e6d38ec 086/135: Added relatives finder
Date: Mon, 17 Feb 2020 10:52:58 -0500 (EST)

branch: master
commit e6d38ecc0b7545fa5a3b32da8fbac42633e67658
Author: Ian Dunn <address@hidden>
Commit: Ian Dunn <address@hidden>

    Added relatives finder
    
    * org-edna.el (org-edna-first-sibling):
      (org-edna-last-sibling):
      (org-edna-goto-sibling):
      (org-edna-self-marker):
      (org-edna-collect-current-level):
      (org-edna-collect-ancestors):
      (org-edna-collect-descendants):
      (org-edna-entry-has-tags-p): New helper functions for relatives finder.
      (org-edna-finder/relatives): New defun.
      (org-edna-finder/chain-find): Alias to org-edna-finder/relatives.
      (org-edna-finder/siblings):
      (org-edna-finder/siblings-wrap):
      (org-edna-finder/rest-of-siblings):
      (org-edna-finder/rest-of-siblings-wrap):
      (org-edna-finder/next-sibling):
      (org-edna-finder/next-sibling-wrap):
      (org-edna-finder/previous-sibling):
      (org-edna-finder/previous-sibling-wrap):
      (org-edna-finder/first-child):
      (org-edna-finder/ancestors):
      (org-edna-finder/descendants):
      (org-edna-finder/children): Implemented in terms of 
org-edna-finder/relatives.
    
    * org-edna-tests.el: Added tests for every form of relatives.
    
    * org-edna.org: Added documentation for relatives, and added new options 
for all
      other relative finders.
    
    * org-edna.info: Updated.
    
    * org-edna-tests.org: Added section for relative tests.
---
 org-edna-tests.el  | 479 ++++++++++++++++++++++++++++++++++++++++-
 org-edna-tests.org |  56 +++++
 org-edna.el        | 608 +++++++++++++++++++++++++++++++++++------------------
 org-edna.info      | 334 ++++++++++++++++++-----------
 org-edna.org       | 184 +++++++++++-----
 5 files changed, 1275 insertions(+), 386 deletions(-)

diff --git a/org-edna-tests.el b/org-edna-tests.el
index 52d1540..d3911db 100644
--- a/org-edna-tests.el
+++ b/org-edna-tests.el
@@ -52,6 +52,18 @@
 (defconst org-edna-test-id-heading-four  
"7d4d564b-18b2-445c-a0c8-b1b3fb9ad29e")
 (defconst org-edna-test-archive-heading  
"d7668277-f959-43ba-8e85-8a3c76996862")
 
+(defconst org-edna-test-relative-grandparent 
"c07cf4c1-3693-443a-9d79-b581f7cbd62c")
+(defconst org-edna-test-relative-parent-one  
"5a35daf7-4957-4588-9a68-21d8763a9e0d")
+(defconst org-edna-test-relative-parent-two  
"4fe67f03-2b35-4708-8c38-54d2c4dfab81")
+(defconst org-edna-test-relative-standard-child 
"7c542695-8165-4c8b-b44d-4c12fa009548")
+(defconst org-edna-test-relative-child-with-children 
"c7a986df-8d89-4509-b086-6db429b5607b")
+(defconst org-edna-test-relative-grandchild-one 
"588bbd29-2e07-437f-b74d-f72459b545a1")
+(defconst org-edna-test-relative-grandchild-two 
"a7047c81-21ec-46cd-8289-60ad515900ff")
+(defconst org-edna-test-relative-child-with-todo 
"8c0b31a1-af49-473c-92ea-a5c1c3bace33")
+(defconst org-edna-test-relative-commented-child 
"0a1b9508-17ce-49c5-8ff3-28a0076374f5")
+(defconst org-edna-test-relative-archived-child 
"a4b6131e-0560-4201-86d5-f32b36363431")
+(defconst org-edna-test-relative-child-with-done 
"4a1d74a2-b032-47da-a823-b32f5cab0aae")
+
 (defun org-edna-find-test-heading (id)
   "Find the test heading with id ID."
   (org-id-find-id-in-file id org-edna-test-file t))
@@ -210,14 +222,14 @@
 
 (ert-deftest org-edna-finder/siblings ()
   (let* ((org-agenda-files `(,org-edna-test-file))
-         (current (org-id-find "82a4ac3d-9565-4f94-bc84-2bbfd8d7d96c" t))
+         (current (org-id-find org-edna-test-sibling-one-id t))
          (siblings (mapcar
                     (lambda (uuid) (org-id-find uuid t))
-                    '("72534efa-e932-460b-ae2d-f044a0074815"
-                      "06aca55e-ce09-46df-80d7-5b52e55d6505")))
+                    `(,org-edna-test-sibling-one-id
+                      ,org-edna-test-sibling-two-id
+                      ,org-edna-test-sibling-three-id)))
          (targets (org-with-point-at current
                     (org-edna-finder/siblings))))
-    (should (= (length targets) 2))
     (should (equal siblings targets))))
 
 (ert-deftest org-edna-finder/siblings-wrap ()
@@ -318,6 +330,465 @@
     (should (= (length targets) 1))
     (should (equal parent targets))))
 
+(ert-deftest org-edna-relatives/from-top ()
+  (let* ((org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find org-edna-test-sibling-one-id t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    `(,org-edna-test-sibling-one-id)))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives 'from-top 1))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/from-bottom ()
+  (let* ((org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find org-edna-test-sibling-one-id t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    `(,org-edna-test-sibling-three-id)))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives 'from-bottom 1))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/forward-wrap-no-wrap ()
+  (let* ((start-marker org-edna-test-sibling-one-id)
+         (target-list `(,org-edna-test-sibling-two-id))
+         (arg 'forward-wrap)
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg 1))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/forward-wrap-wrap ()
+  (let* ((start-marker org-edna-test-sibling-three-id)
+         (target-list `(,org-edna-test-sibling-one-id))
+         (arg 'forward-wrap)
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg 1))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/forward-no-wrap-no-wrap ()
+  (let* ((start-marker org-edna-test-sibling-one-id)
+         (target-list `(,org-edna-test-sibling-two-id))
+         (arg 'forward-no-wrap)
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg 1))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/forward-no-wrap-wrap ()
+  (let* ((start-marker org-edna-test-sibling-three-id)
+         (target-list nil)
+         (arg 'forward-no-wrap)
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/backward-wrap-no-wrap ()
+  (let* ((start-marker org-edna-test-sibling-three-id)
+         (target-list `(,org-edna-test-sibling-two-id))
+         (arg 'backward-wrap)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/backward-wrap-wrap ()
+  (let* ((start-marker org-edna-test-sibling-one-id)
+         (target-list `(,org-edna-test-sibling-three-id))
+         (arg 'backward-wrap)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/backward-no-wrap-no-wrap ()
+  (let* ((start-marker org-edna-test-sibling-three-id)
+         (target-list `(,org-edna-test-sibling-two-id))
+         (arg 'backward-no-wrap)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/backward-no-wrap-wrap ()
+  (let* ((start-marker org-edna-test-sibling-one-id)
+         (target-list nil)
+         (arg 'backward-no-wrap)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/walk-up ()
+  (let* ((start-marker org-edna-test-sibling-one-id)
+         (target-list `(,org-edna-test-parent-id))
+         (arg 'walk-up)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/walk-up-with-self ()
+  (let* ((start-marker org-edna-test-sibling-one-id)
+         (target-list `(,org-edna-test-sibling-one-id))
+         (arg 'walk-up-with-self)
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg 1))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/walk-down ()
+  (let* ((start-marker org-edna-test-parent-id)
+         (target-list `(,org-edna-test-sibling-one-id))
+         (arg 'walk-down)
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg 1))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/walk-down-with-self ()
+  (let* ((start-marker org-edna-test-parent-id)
+         (target-list `(,org-edna-test-parent-id))
+         (arg 'walk-down-with-self)
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg 1))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/walk-down ()
+  (let* ((start-marker org-edna-test-parent-id)
+         (target-list `(,org-edna-test-sibling-one-id))
+         (arg 'walk-down)
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg 1))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/walk-down-full ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-standard-child
+                        ,org-edna-test-relative-child-with-children
+                        ,org-edna-test-relative-grandchild-one
+                        ,org-edna-test-relative-grandchild-two
+                        ,org-edna-test-relative-child-with-todo
+                        ,org-edna-test-relative-commented-child
+                        ,org-edna-test-relative-archived-child
+                        ,org-edna-test-relative-child-with-done))
+         (arg 'walk-down)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/step-down-full ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-standard-child
+                        ,org-edna-test-relative-child-with-children
+                        ,org-edna-test-relative-child-with-todo
+                        ,org-edna-test-relative-commented-child
+                        ,org-edna-test-relative-archived-child
+                        ,org-edna-test-relative-child-with-done))
+         (arg 'step-down)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/filter-todo-only ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-child-with-todo))
+         (arg 'step-down)
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg 'todo-only))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/filter-todo-and-done-only ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-child-with-todo
+                        ,org-edna-test-relative-child-with-done))
+         (arg 'step-down)
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg 'todo-and-done-only))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/filter-no-comments ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-standard-child
+                        ,org-edna-test-relative-child-with-children
+                        ,org-edna-test-relative-child-with-todo
+                        ,org-edna-test-relative-archived-child
+                        ,org-edna-test-relative-child-with-done))
+         (arg 'step-down)
+         (filter 'no-comment)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg filter size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/filter-no-archive ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-standard-child
+                        ,org-edna-test-relative-child-with-children
+                        ,org-edna-test-relative-child-with-todo
+                        ,org-edna-test-relative-commented-child
+                        ,org-edna-test-relative-child-with-done))
+         (arg 'step-down)
+         (filter 'no-archive)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg filter size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/filter-has-tag ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-archived-child))
+         (arg 'step-down)
+         (filter "+ARCHIVE")
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg filter size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/filter-no-tag ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-standard-child
+                        ,org-edna-test-relative-child-with-children
+                        ,org-edna-test-relative-child-with-todo
+                        ,org-edna-test-relative-commented-child
+                        ,org-edna-test-relative-child-with-done))
+         (arg 'step-down)
+         (filter "-ARCHIVE")
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg filter size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/filter-matches-regexp ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-child-with-children
+                        ,org-edna-test-relative-child-with-todo
+                        ,org-edna-test-relative-child-with-done))
+         (arg 'step-down)
+         (filter "Child Heading With .*")
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg filter size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/sort-reverse ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-child-with-done
+                        ,org-edna-test-relative-archived-child
+                        ,org-edna-test-relative-commented-child
+                        ,org-edna-test-relative-child-with-todo
+                        ,org-edna-test-relative-child-with-children
+                        ,org-edna-test-relative-standard-child))
+         (arg 'step-down)
+         (sort 'reverse-sort)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets (org-with-point-at current
+                    (org-edna-finder/relatives arg sort size))))
+    (should (equal siblings targets))))
+
+(ert-deftest org-edna-relatives/sort-priority ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-child-with-todo
+                        ,org-edna-test-relative-archived-child
+                        ,org-edna-test-relative-child-with-children
+                        ,org-edna-test-relative-commented-child
+                        ,org-edna-test-relative-standard-child
+                        ,org-edna-test-relative-child-with-done))
+         (arg 'step-down)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list))
+         (targets ))
+    (should (equal siblings
+                   (org-with-point-at current
+                     (org-edna-finder/relatives arg 'priority-up size))))
+    (should (equal (nreverse siblings)
+                   (org-with-point-at current
+                     (org-edna-finder/relatives arg 'priority-down size))))))
+
+(ert-deftest org-edna-relatives/sort-effort ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-child-with-done
+                        ,org-edna-test-relative-commented-child
+                        ,org-edna-test-relative-archived-child
+                        ,org-edna-test-relative-child-with-children
+                        ,org-edna-test-relative-child-with-todo
+                        ,org-edna-test-relative-standard-child))
+         (arg 'step-down)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list)))
+    (should (equal siblings
+                   (org-with-point-at current
+                     (org-edna-finder/relatives arg 'effort-up size))))
+    (should (equal (nreverse siblings)
+                   (org-with-point-at current
+                     (org-edna-finder/relatives arg 'effort-down size))))))
+
+(ert-deftest org-edna-relatives/sort-scheduled ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-child-with-todo
+                        ,org-edna-test-relative-child-with-done
+                        ,org-edna-test-relative-commented-child
+                        ,org-edna-test-relative-child-with-children
+                        ,org-edna-test-relative-standard-child
+                        ,org-edna-test-relative-archived-child))
+         (arg 'step-down)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list)))
+    (should (equal siblings
+                   (org-with-point-at current
+                     (org-edna-finder/relatives arg 'scheduled-up size))))
+    (should (equal (nreverse siblings)
+                   (org-with-point-at current
+                     (org-edna-finder/relatives arg 'scheduled-down size))))))
+
+(ert-deftest org-edna-relatives/sort-deadline ()
+  (let* ((start-marker org-edna-test-relative-parent-one)
+         (target-list `(,org-edna-test-relative-commented-child
+                        ,org-edna-test-relative-standard-child
+                        ,org-edna-test-relative-child-with-done
+                        ,org-edna-test-relative-child-with-children
+                        ,org-edna-test-relative-archived-child
+                        ,org-edna-test-relative-child-with-todo))
+         (arg 'step-down)
+         (size (length target-list))
+         (org-agenda-files `(,org-edna-test-file))
+         (current (org-id-find start-marker t))
+         (siblings (mapcar
+                    (lambda (uuid) (org-id-find uuid t))
+                    target-list)))
+    (should (equal siblings
+                   (org-with-point-at current
+                     (org-edna-finder/relatives arg 'deadline-up size))))
+    (should (equal (nreverse siblings)
+                   (org-with-point-at current
+                     (org-edna-finder/relatives arg 'deadline-down size))))))
+
 
 ;; Actions
 
diff --git a/org-edna-tests.org b/org-edna-tests.org
index 0c2c24e..01c0dcc 100644
--- a/org-edna-tests.org
+++ b/org-edna-tests.org
@@ -80,3 +80,59 @@ SCHEDULED: <2017-01-01 Sun>
 :ID:       caccd0a6-d400-410a-9018-b0635b07a37e
 :LOGGING:  nil
 :END:
+* Relatives Tests
+:PROPERTIES:
+:ID:       c07cf4c1-3693-443a-9d79-b581f7cbd62c
+:END:
+** Parent Heading #1
+:PROPERTIES:
+:ID:       5a35daf7-4957-4588-9a68-21d8763a9e0d
+:END:
+*** [#C] Standard Child Heading
+DEADLINE: <2017-01-07 Sat> SCHEDULED: <2017-01-02 Mon>
+:PROPERTIES:
+:ID:       7c542695-8165-4c8b-b44d-4c12fa009548
+:Effort:   0:01
+:END:
+*** [#B] Child Heading with Children
+DEADLINE: <2017-01-03 Tue> SCHEDULED: <2017-01-03 Tue>
+:PROPERTIES:
+:ID:       c7a986df-8d89-4509-b086-6db429b5607b
+:Effort:   0:03
+:END:
+**** Child Heading One
+:PROPERTIES:
+:ID:       588bbd29-2e07-437f-b74d-f72459b545a1
+:END:
+**** Child Heading Two
+:PROPERTIES:
+:ID:       a7047c81-21ec-46cd-8289-60ad515900ff
+:END:
+*** TODO [#A] Child Heading with TODO
+DEADLINE: <2017-01-01 Sun> SCHEDULED: <2017-01-06 Fri>
+:PROPERTIES:
+:ID:       8c0b31a1-af49-473c-92ea-a5c1c3bace33
+:Effort:   0:02
+:END:
+*** [#B] COMMENT Commented Child Heading
+DEADLINE: <2017-01-08 Sun> SCHEDULED: <2017-01-04 Wed>
+:PROPERTIES:
+:ID:       0a1b9508-17ce-49c5-8ff3-28a0076374f5
+:Effort:   0:06
+:END:
+*** [#A] Archived Child Heading                                   :ARCHIVE:
+DEADLINE: <2017-01-02 Mon> SCHEDULED: <2017-01-01 Sun>
+:PROPERTIES:
+:ID:       a4b6131e-0560-4201-86d5-f32b36363431
+:Effort:   0:05
+:END:
+*** DONE [#C] Child Heading with DONE
+DEADLINE: <2017-01-05 Thu> SCHEDULED: <2017-01-05 Thu>
+:PROPERTIES:
+:ID:       4a1d74a2-b032-47da-a823-b32f5cab0aae
+:Effort:   0:08
+:END:
+** Parent Sub Heading #2
+:PROPERTIES:
+:ID:       4fe67f03-2b35-4708-8c38-54d2c4dfab81
+:END:
diff --git a/org-edna.el b/org-edna.el
index 364aa8b..d460543 100644
--- a/org-edna.el
+++ b/org-edna.el
@@ -339,152 +339,452 @@ Note that in the edna syntax, the IDs don't need to be 
quoted."
 Edna Syntax: self"
   (list (point-marker)))
 
-(defun org-edna-finder/siblings ()
-  "Finder for all siblings of the source heading.
+(defun org-edna-first-sibling ()
+  "Return a marker to the first child of the current level."
+  (org-with-wide-buffer
+   (org-up-heading-safe)
+   (org-goto-first-child)
+   (point-marker)))
+
+(defun org-edna-last-sibling ()
+  "Return a marker to the first child of the current level."
+  ;; Unfortunately, we have to iterate through every heading on this level to
+  ;; find the first one.
+  (org-with-wide-buffer
+   (while (org-goto-sibling)
+     ;; Do nothing, just keep going down
+     )
+   (point-marker)))
+
+(defun org-edna-goto-sibling (&optional previous wrap)
+  "Move to the next sibling on the same level as the current heading."
+  (let ((next (save-excursion
+                (if previous (org-get-last-sibling) (org-get-next-sibling)))))
+    (cond
+     ;; We have a sibling, so go to it and return non-nil
+     (next (goto-char next))
+     ;; We have no sibling, and we're not wrapping, so return nil
+     ((not wrap) nil)
+     (t
+      ;; Go to the first child if going forward, or the last if going backward,
+      ;; and return non-nil.
+      (goto-char
+       (if previous
+           (org-edna-last-sibling)
+         (org-edna-first-sibling)))
+      t))))
+
+(defun org-edna-self-marker ()
+  "Return a marker to the current heading."
+  (org-with-wide-buffer
+   (and (ignore-errors (org-back-to-heading t) (point-marker)))))
 
-Edna Syntax: siblings
+(defun org-edna-collect-current-level (start backward wrap include-point)
+  "Collect the headings on the current level.
 
-Siblings are returned in order, starting from the first heading,
-and ignoring the source heading."
+START is a point or marker from which to start collection.
+
+BACKWARDS means go backward through the level instead of forward.
+
+If WRAP is non-nil, wrap around when the end of the current level
+is reached.
+
+If INCLUDE-START is non-nil, include the current point."
   (org-with-wide-buffer
-   (let ((self (and (ignore-errors (org-back-to-heading t)) (point)))
-         (markers))
-     (org-up-heading-safe)
-     (org-goto-first-child)
-     (unless (equal (point) self)
+   (let ((markers))
+     (goto-char start)
+     ;; Handle including point
+     (when include-point
+       (push (point-marker) markers))
+     (while (and (org-edna-goto-sibling backward wrap)
+                 (not (equal (point-marker) start)))
        (push (point-marker) markers))
-     (while (org-get-next-sibling)
-       (unless (equal (point) self)
-         (push (point-marker) markers)))
      (nreverse markers))))
 
-(defun org-edna-finder/siblings-wrap ()
+(defun org-edna-collect-ancestors (&optional with-self)
+  (let ((markers))
+    (when with-self
+      (push (point-marker) markers))
+    (org-with-wide-buffer
+     (while (org-up-heading-safe)
+       (push (point-marker) markers)))
+    (nreverse markers)))
+
+(defun org-edna-collect-descendants (&optional with-self)
+  (let ((targets
+         (org-with-wide-buffer
+          (org-map-entries
+           (lambda nil (point-marker))
+           nil 'tree))))
+    ;; Remove the first one (self) if we didn't want self
+    (unless with-self
+      (pop targets))
+    targets))
+
+(defun org-edna-entry-has-tags-p (&rest tags)
+  "Returns non-nil if the current entry has any tags in TAGS."
+  (when-let* ((entry-tags (org-get-tags-at)))
+    (seq-intersection tags entry-tags)))
+
+(defun org-edna-finder/relatives (&rest options)
+  "Find some relative of the current heading.
+
+Edna Syntax: relatives(OPTION OPTION...)
+Edna Syntax: chain-find(OPTION OPTION...)
+
+Identical to the chain argument in org-depend, relatives selects
+its single target using the following method:
+
+1. Creates a list of possible targets
+2. Filters the targets from Step 1
+3. Sorts the targets from Step 2
+
+One option from each of the following three categories may be
+used; if more than one is specified, the last will be used.
+Filtering is the exception to this; each filter argument adds to
+the current filter.  Apart from that, argument order is
+irrelevant.
+
+The chain-find finder is also provided for backwards
+compatibility, and for similarity to org-depend.
+
+All arguments are symbols, unless noted otherwise.
+
+*Selection*
+
+- from-top:             Select siblings of the current heading, starting at 
the top
+- from-bottom:          As above, but from the bottom
+- from-current:         Selects siblings, starting from the heading (wraps)
+- no-wrap:              As above, but without wrapping
+- forward-no-wrap:      Find entries on the same level, going forward
+- forward-wrap:         As above, but wrap when the end is reached
+- backward-no-wrap:     Find entries on the same level, going backward
+- backward-wrap:        As above, but wrap when the start is reached
+- walk-up:              Walk up the tree, excluding self
+- walk-up-with-self:    As above, but including self
+- walk-down:            Recursively walk down the tree, excluding self
+- walk-down-with-self:  As above, but including self
+- step-down:            Collect headings from one level down
+
+*Filtering*
+
+- todo-only:          Select only targets with TODO state set that isn't a 
DONE state
+- todo-and-done-only: Select all targets with a TODO state set
+- no-comments:        Skip commented headings
+- no-archive:         Skip archived headings
+- NUMBER:             Only use that many headings, starting from the first one
+                      If passed 0, use all headings
+                      If <0, omit that many headings from the end
+- \"+tag\":           Only select headings with given tag
+- \"-tag\":           Only select headings without tag
+- \"REGEX\":          select headings whose titles match REGEX
+
+*Sorting*
+
+- no-sort:         Remove other sorting in affect
+- reverse-sort:    Reverse other sorts (stacks with other sort methods)
+- random-sort:     Sort in a random order
+- priority-up:     Sort by priority, highest first
+- priority-down:   Same, but lowest first
+- effort-up:       Sort by effort, highest first
+- effort-down:     Sort by effort, lowest first
+- scheduled-up:    Scheduled time, farthest first
+- scheduled-down:  Scheduled time, closest first
+- deadline-up:     Deadline time, farthest first
+- deadline-down:   Deadline time, closest first
+"
+  (let (targets
+        sortfun
+        reverse-sort
+        (idx 0) ;; By default, use all entries
+        filterfuns ;; No filtering by default
+        ;; From org-depend.el:
+        ;; (and (not todo-and-done-only)
+        ;;      (member (second item) org-done-keywords))
+        )
+    (dolist (opt options)
+      (pcase opt
+        ('from-top
+         (setq targets (org-edna-collect-current-level 
(org-edna-first-sibling) nil nil t)))
+        ('from-bottom
+         (setq targets (org-edna-collect-current-level (org-edna-last-sibling) 
t nil t)))
+        ((or 'from-current 'forward-wrap)
+         (setq targets (org-edna-collect-current-level (org-edna-self-marker) 
nil t nil)))
+        ((or 'no-wrap 'forward-no-wrap)
+         (setq targets (org-edna-collect-current-level (org-edna-self-marker) 
nil nil nil)))
+        ('backward-no-wrap
+         (setq targets (org-edna-collect-current-level (org-edna-self-marker) 
t nil nil)))
+        ('backward-wrap
+         (setq targets (org-edna-collect-current-level (org-edna-self-marker) 
t t nil)))
+        ('walk-up
+         (setq targets (org-edna-collect-ancestors nil)))
+        ('walk-up-with-self
+         (setq targets (org-edna-collect-ancestors t)))
+        ('walk-down
+         (setq targets (org-edna-collect-descendants nil)))
+        ('walk-down-with-self
+         (setq targets (org-edna-collect-descendants t)))
+        ('step-down
+         (setq targets
+               (org-with-wide-buffer
+                (org-goto-first-child)
+                (org-edna-collect-current-level (org-edna-self-marker) nil nil 
t))))
+        ('todo-only
+         ;; Remove any entry without a TODO keyword, or with a DONE keyword
+         (cl-pushnew
+          (lambda (target)
+            (let ((kwd (org-entry-get target "TODO")))
+              (or (not kwd)
+                  (member kwd org-done-keywords))))
+          filterfuns
+          :test 'equal))
+        ('todo-and-done-only
+         ;; Remove any entry without a TODO keyword
+         (cl-pushnew
+          (lambda (target)
+            (not (org-entry-get target "TODO")))
+          filterfuns :test 'equal))
+        ((pred numberp)
+         (setq idx opt))
+        ((and (pred stringp)
+              (pred (lambda (opt) (string-match-p "^\\+" opt))))
+         (cl-pushnew
+          (lambda (target)
+            ;; This is a function that will return non-nil if the entry should
+            ;; be removed, so remove those entries that don't have the tag
+            (org-with-point-at target
+              (not (org-edna-entry-has-tags-p (string-remove-prefix "+" 
opt)))))
+          filterfuns :test 'equal))
+        ((and (pred stringp)
+              (pred (lambda (opt) (string-match-p "^\\-" opt))))
+         (cl-pushnew
+          (lambda (target)
+            ;; This is a function that will return non-nil if the entry should
+            ;; be removed, so remove those entries that DO have the tag
+            (org-with-point-at target
+              (org-edna-entry-has-tags-p (string-remove-prefix "-" opt))))
+          filterfuns :test 'equal))
+        ((pred stringp)
+         (cl-pushnew
+          (lambda (target)
+            ;; Return non-nil if entry doesn't match the regular expression, so
+            ;; it will be removed.
+            (not (string-match-p opt
+                               (org-with-point-at target
+                                 (org-get-heading t t t t)))))
+          filterfuns :test 'equal))
+        ('no-comment
+         (cl-pushnew
+          (lambda (target)
+            (org-with-point-at target
+              (org-in-commented-heading-p)))
+          filterfuns :test 'equal))
+        ('no-archive
+         (cl-pushnew
+          (lambda (target)
+            (org-with-point-at target
+              (org-edna-entry-has-tags-p org-archive-tag)))
+          filterfuns :test 'equal))
+        ('no-sort
+         (setq sortfun nil
+               reverse-sort nil))
+        ('random-sort
+         (setq sortfun
+               (lambda (_rhs _lhs)
+                 (let ((l (random 100))
+                       (r (random 100)))
+                   (< l r)))))
+        ('reverse-sort
+         (setq reverse-sort t))
+        ('priority-up
+         ;; A is highest priority, but assigned the lowest value, so we need to
+         ;; reverse the sort here.
+         (setq sortfun
+               (lambda (lhs rhs)
+                 (let ((priority-lhs (org-entry-get lhs "PRIORITY"))
+                       (priority-rhs (org-entry-get rhs "PRIORITY")))
+                   (string-lessp priority-lhs priority-rhs)))))
+        ('priority-down
+         (setq sortfun
+               (lambda (lhs rhs)
+                 (let ((priority-lhs (org-entry-get lhs "PRIORITY"))
+                       (priority-rhs (org-entry-get rhs "PRIORITY")))
+                   (not (string-lessp priority-lhs priority-rhs))))))
+        ('effort-up
+         (setq sortfun
+               (lambda (lhs rhs)
+                 (let ((effort-lhs (org-duration-to-minutes (org-entry-get lhs 
"EFFORT")))
+                       (effort-rhs (org-duration-to-minutes (org-entry-get rhs 
"EFFORT"))))
+                   (not (< effort-lhs effort-rhs))))))
+        ('effort-down
+         (setq sortfun
+               (lambda (lhs rhs)
+                 (let ((effort-lhs (org-duration-to-minutes (org-entry-get lhs 
"EFFORT")))
+                       (effort-rhs (org-duration-to-minutes (org-entry-get rhs 
"EFFORT"))))
+                   (< effort-lhs effort-rhs)))))
+        ('scheduled-up
+         (setq sortfun
+               (lambda (lhs rhs)
+                 (let ((time-lhs (org-get-scheduled-time lhs))
+                       (time-rhs (org-get-scheduled-time rhs)))
+                   (not (time-less-p time-lhs time-rhs))))))
+        ('scheduled-down
+         (setq sortfun
+               (lambda (lhs rhs)
+                 (let ((time-lhs (org-get-scheduled-time lhs))
+                       (time-rhs (org-get-scheduled-time rhs)))
+                   (time-less-p time-lhs time-rhs)))))
+        ('deadline-up
+         (setq sortfun
+               (lambda (lhs rhs)
+                 (let ((time-lhs (org-get-deadline-time lhs))
+                       (time-rhs (org-get-deadline-time rhs)))
+                   (not (time-less-p time-lhs time-rhs))))))
+        ('deadline-down
+         (setq sortfun
+               (lambda (lhs rhs)
+                 (let ((time-lhs (org-get-deadline-time lhs))
+                       (time-rhs (org-get-deadline-time rhs)))
+                   (time-less-p time-lhs time-rhs)))))))
+    (setq filterfuns (nreverse filterfuns))
+    (when (and targets sortfun)
+      (setq targets (seq-sort sortfun targets)))
+    (dolist (filterfun filterfuns)
+      (setq targets (seq-remove filterfun targets)))
+    (when reverse-sort
+      (setq targets (nreverse targets)))
+    (when (and targets (/= idx 0))
+      (if (> idx (seq-length targets))
+          (message "Edna relatives finder got index %s out of bounds of target 
size; ignoring" idx)
+        (setq targets (seq-subseq targets 0 idx))))
+    targets))
+
+(defalias 'org-edna-finder/chain-find 'org-edna-finder/relatives)
+
+(defun org-edna-finder/siblings (&rest options)
   "Finder for all siblings of the source heading.
 
-Edna Syntax: siblings-wrap
+Edna Syntax: siblings(OPTIONS...)
 
-Siblings are returned in order, starting from the first heading
-after the source heading and wrapping when it reaches the end."
-  (org-with-wide-buffer
-   (let ((self (and (ignore-errors (org-back-to-heading t)) (point)))
-         (markers))
-     ;; Go from this heading to the end
-     (save-excursion
-       (while (org-get-next-sibling)
-         (unless (equal (point) self)
-           (push (point-marker) markers))))
-     ;; Go to the first heading
-     (org-up-heading-safe)
-     (org-goto-first-child)
-     (save-excursion
-       (while (not (equal (point) self))
-         (push (point-marker) markers)
-         (org-get-next-sibling)))
-     (nreverse markers))))
+Siblings are returned in order, starting from the first heading.
 
-(defun org-edna-finder/rest-of-siblings ()
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 'from-top options))
+
+(defun org-edna-finder/rest-of-siblings (&rest options)
   "Finder for the siblings after the source heading.
 
-Edna Syntax: rest-of-siblings
+Edna Syntax: rest-of-siblings(OPTIONS...)
 
 Siblings are returned in order, starting from the first heading
-after the source heading."
-  (org-with-wide-buffer
-   (let ((self (and (ignore-errors (org-back-to-heading t)) (point)))
-         (markers))
-     ;; Go from this heading to the end
-     (while (org-get-next-sibling)
-       (unless (equal (point) self)
-         (push (point-marker) markers)))
-     (nreverse markers))))
+after the source heading.
+
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 'forward-no-wrap options))
+
+(defun org-edna-finder/rest-of-siblings-wrap (&rest options)
+  "Finder for all siblings of the source heading.
+
+Edna Syntax: rest-of-siblings-wrap(OPTIONS...)
+
+Siblings are returned in order, starting from the first heading
+after the source heading and wrapping when it reaches the end.
+
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 'forward-wrap options))
+
+(defalias 'org-edna-finder/siblings-wrap 
'org-edna-finder/rest-of-siblings-wrap)
 
-(defun org-edna-finder/next-sibling ()
+(defun org-edna-finder/next-sibling (&rest options)
   "Finder for the next sibling after the source heading.
 
-Edna Syntax: next-sibling
+Edna Syntax: next-sibling(OPTIONS...)
 
 If the source heading is the last of its siblings, no target is
-returned."
-  (org-with-wide-buffer
-   (and (org-get-next-sibling)
-        (list (point-marker)))))
+returned.
+
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 1 'forward-no-wrap options))
 
-(defun org-edna-finder/next-sibling-wrap ()
+(defun org-edna-finder/next-sibling-wrap (&rest options)
   "Finder for the next sibling after the source heading.
 
-Edna Syntax: next-sibling-wrap
+Edna Syntax: next-sibling-wrap(OPTIONS...)
 
 If the source heading is the last of its siblings, its first
-sibling is returned."
-  (org-with-wide-buffer
-   (if (org-goto-sibling)
-       (list (point-marker))
-     (org-up-heading-safe)
-     (org-goto-first-child)
-     (list (point-marker)))))
+sibling is returned.
 
-(defun org-edna-finder/previous-sibling ()
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 1 'forward-wrap options))
+
+(defun org-edna-finder/previous-sibling (&rest options)
   "Finder for the first sibling before the source heading.
 
-Edna Syntax: previous-sibling
+Edna Syntax: previous-sibling(OPTIONS...)
 
 If the source heading is the first of its siblings, no target is
-returned."
-  (org-with-wide-buffer
-   (and (org-get-last-sibling)
-        (list (point-marker)))))
+returned.
+
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 1 'backward-no-wrap options))
+
+(defun org-edna-finder/previous-sibling-wrap (&rest options)
+  "Finder for the first sibling before the source heading.
+
+Edna Syntax: previous-sibling-wrap(OPTIONS...)
 
-(defun org-edna-finder/first-child ()
+If the source heading is the first of its siblings, no target is
+returned.
+
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 1 'backward-wrap options))
+
+(defun org-edna-finder/first-child (&rest options)
   "Return the first child of the source heading.
 
-Edna Syntax: first-child
+Edna Syntax: first-child(OPTIONS...)
 
-If the source heading has no children, no target is returned."
-  (org-with-wide-buffer
-   (and (org-goto-first-child)
-        (list (point-marker)))))
+If the source heading has no children, no target is returned.
+
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 1 'step-down options))
 
-(defun org-edna-finder/children ()
+(defun org-edna-finder/children (&rest options)
   "Finder for the immediate children of the source heading.
 
-Edna Syntax: children
+Edna Syntax: children(OPTIONS...)
 
-If the source has no children, no target is returned."
-  (org-with-wide-buffer
-   (let ((markers))
-     (org-goto-first-child)
-     (push (point-marker) markers)
-     (while (org-get-next-sibling)
-       (push (point-marker) markers))
-     (nreverse markers))))
+If the source has no children, no target is returned.
 
-(defun org-edna-finder/parent ()
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 'step-down options))
+
+(defun org-edna-finder/parent (&rest options)
   "Finder for the parent of the source heading.
 
-Edna Syntax: parent
+Edna Syntax: parent(OPTIONS...)
 
 If the source heading is a top-level heading, no target is
-returned."
-  (org-with-wide-buffer
-   (and (org-up-heading-safe)
-        (list (point-marker)))))
+returned.
+
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 1 'walk-up options))
 
-(defun org-edna-finder/descendants ()
+(defun org-edna-finder/descendants (&rest options)
   "Finder for all descendants of the source heading.
 
-Edna Syntax: descendants
+Edna Syntax: descendants(OPTIONS...)
 
 This is ALL descendants of the source heading, across all
-levels.  This also includes the source heading."
-  (org-with-wide-buffer
-   (org-map-entries
-    (lambda nil (point-marker))
-    nil 'tree)))
+levels.  This also includes the source heading.
+
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 'walk-down options))
 
-(defun org-edna-finder/ancestors ()
+(defun org-edna-finder/ancestors (&rest options)
   "Finder for the ancestors of the source heading.
 
-Edna Syntax: ancestors
+Edna Syntax: ancestors(OPTIONS...)
 
 Example:
 
@@ -499,12 +799,10 @@ Example:
 
 In the above example, Heading 5 will be blocked until Heading 1,
 Heading 3, and Heading 4 are marked DONE, while Heading 2 is
-ignored."
-  (org-with-wide-buffer
-   (let ((markers))
-     (while (org-up-heading-safe)
-       (push (point-marker) markers))
-     (nreverse markers))))
+ignored.
+
+See `org-edna-finder/relatives' for the OPTIONS argument."
+  (apply 'org-edna-finder/relatives 'walk-up options))
 
 (defun org-edna-finder/olp (file olp)
   "Finder for heading by its outline path.
@@ -576,108 +874,6 @@ which ones will and won't work."
   (with-current-buffer (find-file-noselect (expand-file-name file 
org-directory))
     (list (point-min-marker))))
 
-(defun org-edna-finder/chain-find (&rest options)
-  "Find a target as org-depend does.
-
-Edna Syntax: chain-find(OPTION OPTION...)
-
-Identical to the chain argument in org-depend, chain-find selects its single
-target using the following method:
-
-1. Creates a list of possible targets
-2. Filters the targets from Step 1
-3. Sorts the targets from Step 2
-
-After this is finished, chain-find selects the first target in
-the list and returns it.
-
-One option from each of the following three categories may be
-used; if more than one is specified, the last will be used.
-Apart from that, argument order is irrelevant.
-
-All arguments are symbols.
-
-*Selection*
-
-- from-top:     Select siblings of the current heading, starting at the top
-- from-bottom:  As above, but from the bottom
-- from-current: Selects siblings, starting from the heading (wraps)
-- no-wrap:      As above, but without wrapping
-
-*Filtering*
-
-- todo-only:          Select only targets with TODO state set that isn't a 
DONE state
-- todo-and-done-only: Select all targets with a TODO state set
-
-*Sorting*
-
-- priority-up:   Sort by priority, highest first
-- priority-down: Same, but lowest first
-- effort-up:     Sort by effort, highest first
-- effort-down:   Sort by effort, lowest first"
-  ;; sortfun - function to use to sort elements
-  ;; filterfun - Function to use to filter elements
-  ;; Both should handle positioning point
-  (let (targets
-        sortfun
-        ;; From org-depend.el:
-        ;; (and (not todo-and-done-only)
-        ;;      (member (second item) org-done-keywords))
-        (filterfun (lambda (target)
-                     (member (org-entry-get target "TODO") 
org-done-keywords))))
-    (dolist (opt options)
-      (pcase opt
-        ('from-top
-         (setq targets (org-edna-finder/siblings)))
-        ('from-bottom
-         (setq targets (seq-reverse (org-edna-finder/siblings))))
-        ('from-current
-         (setq targets (org-edna-finder/siblings-wrap)))
-        ('no-wrap
-         (setq targets (org-edna-finder/rest-of-siblings)))
-        ('todo-only
-         ;; Remove any entry without a TODO keyword, or with a DONE keyword
-         (setq filterfun
-               (lambda (target)
-                 (let ((kwd (org-entry-get target "TODO")))
-                   (or (not kwd)
-                       (member kwd org-done-keywords))))))
-        ('todo-and-done-only
-         ;; Remove any entry without a TODO keyword
-         (setq filterfun
-               (lambda (target)
-                 (not (org-entry-get target "TODO")))))
-        ('priority-up
-         (setq sortfun
-               (lambda (lhs rhs)
-                 (let ((priority-lhs (org-entry-get lhs "PRIORITY"))
-                       (priority-rhs (org-entry-get rhs "PRIORITY")))
-                   (not (string-lessp priority-lhs priority-rhs))))))
-        ('priority-down
-         (setq sortfun
-               (lambda (lhs rhs)
-                 (let ((priority-lhs (org-entry-get lhs "PRIORITY"))
-                       (priority-rhs (org-entry-get rhs "PRIORITY")))
-                   (string-lessp priority-lhs priority-rhs)))))
-        ('effort-up
-         (setq sortfun
-               (lambda (lhs rhs)
-                 (let ((effort-lhs (org-duration-to-minutes (org-entry-get lhs 
"EFFORT")))
-                       (effort-rhs (org-duration-to-minutes (org-entry-get rhs 
"EFFORT"))))
-                   (not (< effort-lhs effort-rhs))))))
-        ('effort-down
-         (setq sortfun
-               (lambda (lhs rhs)
-                 (let ((effort-lhs (org-duration-to-minutes (org-entry-get lhs 
"EFFORT")))
-                       (effort-rhs (org-duration-to-minutes (org-entry-get rhs 
"EFFORT"))))
-                   (< effort-lhs effort-rhs)))))))
-    (when (and targets sortfun)
-      (setq targets (seq-sort sortfun targets)))
-    (when (and targets filterfun)
-      (setq targets (seq-remove filterfun targets)))
-    (when targets
-      (list (seq-elt 0 targets)))))
-
 
 
 ;; Set TODO state
@@ -748,8 +944,7 @@ DEF-FLAG   is t when a double ++ or -- indicates shift 
relative to
 Examples:
 
 \"+1d +wkdy\" finds the number of days to move ahead in order to
-find a weekday.  This is the same as \"+1wkdy\", and returns
-\(N \"d\" nil).
+find a weekday.  This is the same as \"+1wkdy\", and returns (N \"d\" nil).
 
 \"+5d -wkdy\" means move forward 5 days, then backward until a
 weekday is found.  Returns (N \"d\" nil).
@@ -964,7 +1159,6 @@ forward) or the last day of MONTH (backward)."
                                                              act-month
                                                              act-year
                                                              act-day)))
-        (message "act day = %s" act-day)
         ;; Return the same arguments as `org-edna--read-date-get-relative' 
above.
         (list (- abs-days-then abs-days-now) "d" rel)))))
 
diff --git a/org-edna.info b/org-edna.info
index 4bc75e0..00bfa6e 100644
--- a/org-edna.info
+++ b/org-edna.info
@@ -39,7 +39,6 @@ Basic Features
 Finders
 
 * ancestors::                    Find a list of ancestors
-* chain-find::                   Find a target as org-depend does
 * children::                     Find all immediate children
 * descendants::                  Find all descendants
 * file::                         Find a file by name
@@ -52,7 +51,10 @@ Finders
 * org-file::                     Find a file in org-directory
 * parent::                       Find a parent
 * previous-sibling::             Find the previous sibling
+* previous-sibling-wrap::        Find the previous sibling, with wrapping
+* relatives::                    Generic relative finder
 * rest-of-siblings::             Find the remaining siblings
+* rest-of-siblings-wrap::        Find the remaining siblings, with wrapping
 * self::
 * siblings::                     Find all the siblings
 * siblings-wrap::                Find the siblings, but wrap around
@@ -310,10 +312,12 @@ to as the “source” heading.
    More than one finder may be used.  In this case, the targets are
 merged together, removing any duplicates.
 
+   Many finders take additional options, marked “OPTIONS”.  See *note
+relatives:: for information on these options.
+
 * Menu:
 
 * ancestors::                    Find a list of ancestors
-* chain-find::                   Find a target as org-depend does
 * children::                     Find all immediate children
 * descendants::                  Find all descendants
 * file::                         Find a file by name
@@ -326,18 +330,21 @@ merged together, removing any duplicates.
 * org-file::                     Find a file in org-directory
 * parent::                       Find a parent
 * previous-sibling::             Find the previous sibling
+* previous-sibling-wrap::        Find the previous sibling, with wrapping
+* relatives::                    Generic relative finder
 * rest-of-siblings::             Find the remaining siblings
+* rest-of-siblings-wrap::        Find the remaining siblings, with wrapping
 * self::
 * siblings::                     Find all the siblings
 * siblings-wrap::                Find the siblings, but wrap around
 
 
-File: org-edna.info,  Node: ancestors,  Next: chain-find,  Up: Finders
+File: org-edna.info,  Node: ancestors,  Next: children,  Up: Finders
 
 ancestors
 ---------
 
-   • Syntax: ancestors
+   • Syntax: ancestors(OPTIONS...)
 
    The ‘ancestors’ finder returns a list of the source heading’s
 ancestors.
@@ -358,57 +365,12 @@ ancestors.
 ignored.
 
 
-File: org-edna.info,  Node: chain-find,  Next: children,  Prev: ancestors,  
Up: Finders
-
-chain-find
-----------
-
-   • Syntax: chain-find(OPTION OPTION...)
-
-   Identical to the chain argument in org-depend, chain-find selects its
-single target using the following method:
-
-  1. Creates a list of possible targets
-  2. Filters the targets from Step 1
-  3. Sorts the targets from Step 2
-
-   After this is finished, chain-find selects the first target in the
-list and returns it.
-
-   One option from each of the following three categories may be used;
-if more than one is specified, the last will be used.  Apart from that,
-argument order is irrelevant.
-
-   All arguments are symbols.
-
-   *Selection*
-
-   • from-top: Select siblings of the source heading, starting at the
-     top
-   • from-bottom: As above, but from the bottom
-   • from-current: Selects siblings, starting from the heading (wraps)
-   • no-wrap: As above, but without wrapping
-
-   *Filtering*
-
-   • todo-only: Select only targets with TODO state set that isn’t a
-     DONE keyword
-   • todo-and-done-only: Select all targets with a TODO state set
-
-   *Sorting*
-
-   • priority-up: Sort by priority, highest first
-   • priority-down: Same, but lowest first
-   • effort-up: Sort by effort, highest first
-   • effort-down: Sort by effort, lowest first
-
-
-File: org-edna.info,  Node: children,  Next: descendants,  Prev: chain-find,  
Up: Finders
+File: org-edna.info,  Node: children,  Next: descendants,  Prev: ancestors,  
Up: Finders
 
 children
 --------
 
-   • Syntax: children
+   • Syntax: children(OPTIONS...)
 
    The ‘children’ finder returns a list of the *immediate* children of
 the source heading.  If the source has no children, no target is
@@ -423,7 +385,7 @@ File: org-edna.info,  Node: descendants,  Next: file,  
Prev: children,  Up: Find
 descendants
 -----------
 
-   • Syntax: descendants
+   • Syntax: descendants(OPTIONS...)
 
    The ‘descendants’ finder returns a list of all descendants of the
 source heading.
@@ -472,7 +434,7 @@ File: org-edna.info,  Node: first-child,  Next: ids,  Prev: 
file,  Up: Finders
 first-child
 -----------
 
-   • Syntax: first-child
+   • Syntax: first-child(OPTIONS...)
 
    Return the first child of the source heading.  If the source heading
 has no children, no target is returned.
@@ -528,7 +490,7 @@ File: org-edna.info,  Node: next-sibling,  Next: 
next-sibling-wrap,  Prev: match
 next-sibling
 ------------
 
-   • Syntax: next-sibling
+   • Syntax: next-sibling(OPTIONS...)
 
    The ‘next-sibling’ keyword returns the next sibling of the source
 heading, if any.
@@ -539,7 +501,7 @@ File: org-edna.info,  Node: next-sibling-wrap,  Next: olp,  
Prev: next-sibling,
 next-sibling-wrap
 -----------------
 
-   • Syntax: next-sibling-wrap
+   • Syntax: next-sibling-wrap(OPTIONS...)
 
    Find the next sibling of the source heading, if any.  If there isn’t,
 wrap back around to the first heading in the same subtree.
@@ -591,33 +553,161 @@ File: org-edna.info,  Node: parent,  Next: 
previous-sibling,  Prev: org-file,  U
 parent
 ------
 
-   • Syntax: parent
+   • Syntax: parent(OPTIONS...)
 
    Returns the parent of the source heading, if any.
 
 
-File: org-edna.info,  Node: previous-sibling,  Next: rest-of-siblings,  Prev: 
parent,  Up: Finders
+File: org-edna.info,  Node: previous-sibling,  Next: previous-sibling-wrap,  
Prev: parent,  Up: Finders
 
 previous-sibling
 ----------------
 
-   • Syntax: previous-sibling
+   • Syntax: previous-sibling(OPTIONS...)
+
+   Returns the previous sibling of the source heading on the same level.
+
+
+File: org-edna.info,  Node: previous-sibling-wrap,  Next: relatives,  Prev: 
previous-sibling,  Up: Finders
+
+previous-sibling-wrap
+---------------------
+
+   • Syntax: previous-sibling-wrap(OPTIONS...)
 
    Returns the previous sibling of the source heading on the same level.
 
 
-File: org-edna.info,  Node: rest-of-siblings,  Next: self,  Prev: 
previous-sibling,  Up: Finders
+File: org-edna.info,  Node: relatives,  Next: rest-of-siblings,  Prev: 
previous-sibling-wrap,  Up: Finders
+
+relatives
+---------
+
+Find some relative of the current heading.
+
+   • Syntax: relatives(OPTION OPTION...)
+   • Syntax: chain-find(OPTION OPTION...)
+
+   Identical to the chain argument in org-depend, relatives selects its
+single target using the following method:
+
+  1. Creates a list of possible targets
+  2. Filters the targets from Step 1
+  3. Sorts the targets from Step 2
+
+   One option from each of the following three categories may be used;
+if more than one is specified, the last will be used.  Filtering is the
+exception to this; each filter argument adds to the current filter.
+Apart from that, argument order is irrelevant.
+
+   The chain-find finder is also provided for backwards compatibility,
+and for similarity to org-depend.
+
+   All arguments are symbols, unless noted otherwise.
+
+   *Selection*
+
+   • from-top: Select siblings of the current heading, starting at the
+     top
+   • from-bottom: As above, but from the bottom
+   • from-current: Selects siblings, starting from the heading (wraps)
+   • no-wrap: As above, but without wrapping
+   • forward-no-wrap: Find entries on the same level, going forward
+   • forward-wrap: As above, but wrap when the end is reached
+   • backward-no-wrap: Find entries on the same level, going backward
+   • backward-wrap: As above, but wrap when the start is reached
+   • walk-up: Walk up the tree, excluding self
+   • walk-up-with-self: As above, but including self
+   • walk-down: Recursively walk down the tree, excluding self
+   • walk-down-with-self: As above, but including self
+   • step-down: Collect headings from one level down
+
+   *Filtering*
+
+   • todo-only: Select only targets with TODO state set that isn’t a
+     DONE state
+   • todo-and-done-only: Select all targets with a TODO state set
+   • no-comments: Skip commented headings
+   • no-archive: Skip archived headings
+   • NUMBER: Only use that many headings, starting from the first one If
+     passed 0, use all headings If <0, omit that many headings from the
+     end
+   • “+tag”: Only select headings with given tag
+   • “-tag”: Only select headings without tag
+   • “REGEX”: select headings whose titles match REGEX
+
+   *Sorting*
+
+   • no-sort: Remove other sorting in affect
+   • reverse-sort: Reverse other sorts (stacks with other sort methods)
+   • random-sort: Sort in a random order
+   • priority-up: Sort by priority, highest first
+   • priority-down: Same, but lowest first
+   • effort-up: Sort by effort, highest first
+   • effort-down: Sort by effort, lowest first
+   • scheduled-up: Scheduled time, farthest first
+   • scheduled-down: Scheduled time, closest first
+   • deadline-up: Deadline time, farthest first
+   • deadline-down: Deadline time, closest first
+
+   Many of the other finders are shorthand for argument combinations of
+relative:
+
+*note ancestors::
+     walk-up
+*note children::
+     step-down
+*note descendants::
+     walk-down
+*note first-child::
+     step-down 1
+*note next-sibling::
+     forward-no-wrap 1
+*note next-sibling-wrap::
+     forward-wrap 1
+*note parent::
+     walk-up 1
+*note previous-sibling::
+     backward-no-wrap 1
+*note previous-sibling-wrap::
+     backward-wrap 1
+*note rest-of-siblings::
+     forward-no-wrap
+*note rest-of-siblings-wrap::
+     forward-wrap
+*note siblings::
+     from-top
+*note siblings-wrap::
+     forward-wrap
+
+   Because these are implemented as shorthand, any arguments for
+relatives may also be passed to one of these finders.
+
+
+File: org-edna.info,  Node: rest-of-siblings,  Next: rest-of-siblings-wrap,  
Prev: relatives,  Up: Finders
 
 rest-of-siblings
 ----------------
 
-   • Syntax: rest-of-siblings
+   • Syntax: rest-of-siblings(OPTIONS...)
 
    Starting from the heading following the current one, all same-level
 siblings are returned.
 
 
-File: org-edna.info,  Node: self,  Next: siblings,  Prev: rest-of-siblings,  
Up: Finders
+File: org-edna.info,  Node: rest-of-siblings-wrap,  Next: self,  Prev: 
rest-of-siblings,  Up: Finders
+
+rest-of-siblings-wrap
+---------------------
+
+   • Syntax: rest-of-siblings-wrap(OPTIONS...)
+
+   Starting from the heading following the current one, all same-level
+siblings are returned.  When the end is reached, wrap back to the
+beginning.
+
+
+File: org-edna.info,  Node: self,  Next: siblings,  Prev: 
rest-of-siblings-wrap,  Up: Finders
 
 self
 ----
@@ -632,10 +722,10 @@ File: org-edna.info,  Node: siblings,  Next: 
siblings-wrap,  Prev: self,  Up: Fi
 siblings
 --------
 
-   • Syntax: siblings
+   • Syntax: siblings(OPTIONS...)
 
    Returns all siblings of the source heading as targets, starting from
-the first sibling, and ignoring the source heading.
+the first sibling.
 
 
 File: org-edna.info,  Node: siblings-wrap,  Prev: siblings,  Up: Finders
@@ -643,11 +733,13 @@ File: org-edna.info,  Node: siblings-wrap,  Prev: 
siblings,  Up: Finders
 siblings-wrap
 -------------
 
-   • Syntax: siblings-wrap
+   • Syntax: siblings-wrap(OPTIONS...)
 
    Finds the siblings on the same level as the source heading, wrapping
 when it reaches the end.
 
+   Identical to the *note rest-of-siblings-wrap:: finder.
+
 
 File: org-edna.info,  Node: Actions,  Prev: Finders,  Up: Basic Features
 
@@ -1252,62 +1344,64 @@ We can then merge that into the main development branch.
 
 Tag Table:
 Node: Top225
-Node: Copying3268
-Node: Introduction4085
-Node: Installation and Setup5033
-Node: Basic Operation5826
-Node: Blockers7677
-Node: Triggers7963
-Node: Syntax8225
-Node: Basic Features8915
-Node: Finders9218
-Node: ancestors10721
-Node: chain-find11305
-Node: children12643
-Node: descendants13042
-Node: file13552
-Node: first-child14301
-Node: ids14549
-Node: match15210
-Node: next-sibling15848
-Node: next-sibling-wrap16093
-Node: olp16395
-Node: org-file16807
-Node: parent17452
-Node: previous-sibling17638
-Node: rest-of-siblings17882
-Node: self18145
-Node: siblings18301
-Node: siblings-wrap18559
-Node: Actions18792
-Node: Scheduled/Deadline19534
-Node: TODO State23109
-Node: Archive23477
-Node: Chain Property23797
-Node: Clocking24080
-Node: Property24492
-Node: Priority24814
-Node: Tag25383
-Node: Effort25600
-Node: Advanced Features25989
-Node: Conditions26327
-Node: done26942
-Node: headings27106
-Node: todo-state27482
-Node: variable-set27738
-Node: has-property28167
-Node: re-search28436
-Node: Negating Conditions28796
-Node: Consideration29183
-Node: Setting the properties30415
-Node: Extending Edna31495
-Node: Naming Conventions31985
-Node: Finders (1)32448
-Node: Actions (1)32814
-Node: Conditions (1)33279
-Node: Contributing34169
-Node: Bugs34641
-Node: Development34993
+Node: Copying3409
+Node: Introduction4226
+Node: Installation and Setup5174
+Node: Basic Operation5967
+Node: Blockers7818
+Node: Triggers8104
+Node: Syntax8366
+Node: Basic Features9056
+Node: Finders9359
+Node: ancestors11124
+Node: children11718
+Node: descendants12128
+Node: file12650
+Node: first-child13399
+Node: ids13659
+Node: match14320
+Node: next-sibling14958
+Node: next-sibling-wrap15215
+Node: olp15529
+Node: org-file15941
+Node: parent16586
+Node: previous-sibling16784
+Node: previous-sibling-wrap17045
+Node: relatives17324
+Node: rest-of-siblings20945
+Node: rest-of-siblings-wrap21230
+Node: self21579
+Node: siblings21740
+Node: siblings-wrap21977
+Node: Actions22281
+Node: Scheduled/Deadline23023
+Node: TODO State26598
+Node: Archive26966
+Node: Chain Property27286
+Node: Clocking27569
+Node: Property27981
+Node: Priority28303
+Node: Tag28872
+Node: Effort29089
+Node: Advanced Features29478
+Node: Conditions29816
+Node: done30431
+Node: headings30595
+Node: todo-state30971
+Node: variable-set31227
+Node: has-property31656
+Node: re-search31925
+Node: Negating Conditions32285
+Node: Consideration32672
+Node: Setting the properties33904
+Node: Extending Edna34984
+Node: Naming Conventions35474
+Node: Finders (1)35937
+Node: Actions (1)36303
+Node: Conditions (1)36768
+Node: Contributing37658
+Node: Bugs38130
+Node: Development38482
 
 End Tag Table
 
diff --git a/org-edna.org b/org-edna.org
index 804ee5e..f42e445 100644
--- a/org-edna.org
+++ b/org-edna.org
@@ -208,13 +208,16 @@ that is being blocked or triggered, is referred to as the 
"source" heading.
 More than one finder may be used.  In this case, the targets are merged
 together, removing any duplicates.
 
+Many finders take additional options, marked "OPTIONS".  See 
[[#relatives][relatives]] for
+information on these options.
+
 *** ancestors
 :PROPERTIES:
 :DESCRIPTION: Find a list of ancestors
 :CUSTOM_ID: ancestors
 :END:
 
-- Syntax: ancestors
+- Syntax: ancestors(OPTIONS...)
 
 The ~ancestors~ finder returns a list of the source heading's ancestors.
 
@@ -234,56 +237,13 @@ For example:
 In the above example, "Heading 5" will be blocked until "Heading 1", "Heading
 3", and "Heading 4" are marked "DONE", while "Heading 2" is ignored.
 
-*** chain-find
-:PROPERTIES:
-:CUSTOM_ID: chain-find
-:DESCRIPTION: Find a target as org-depend does
-:END:
-
-- Syntax: chain-find(OPTION OPTION...)
-
-Identical to the chain argument in org-depend, chain-find selects its single
-target using the following method:
-
-1. Creates a list of possible targets
-2. Filters the targets from Step 1
-3. Sorts the targets from Step 2
-
-After this is finished, chain-find selects the first target in the list and
-returns it.
-
-One option from each of the following three categories may be used; if more 
than
-one is specified, the last will be used.  Apart from that, argument order is
-irrelevant.
-
-All arguments are symbols.
-
-*Selection*
-
-- from-top:     Select siblings of the source heading, starting at the top
-- from-bottom:  As above, but from the bottom
-- from-current: Selects siblings, starting from the heading (wraps)
-- no-wrap:      As above, but without wrapping
-
-*Filtering*
-
-- todo-only:          Select only targets with TODO state set that isn't a 
DONE keyword
-- todo-and-done-only: Select all targets with a TODO state set
-
-*Sorting*
-
-- priority-up:   Sort by priority, highest first
-- priority-down: Same, but lowest first
-- effort-up:     Sort by effort, highest first
-- effort-down:   Sort by effort, lowest first
-
 *** children
 :PROPERTIES:
 :CUSTOM_ID: children
 :DESCRIPTION: Find all immediate children
 :END:
 
-- Syntax: children
+- Syntax: children(OPTIONS...)
 
 The ~children~ finder returns a list of the *immediate* children of the source
 heading.  If the source has no children, no target is returned.
@@ -297,7 +257,7 @@ In order to get all levels of children of the source 
heading, use the
 :DESCRIPTION: Find all descendants
 :END:
 
-- Syntax: descendants
+- Syntax: descendants(OPTIONS...)
 
 The ~descendants~ finder returns a list of all descendants of the source 
heading.
 
@@ -348,7 +308,7 @@ Here, "Test" will block until myfile.org is clear of 
headings.
 :DESCRIPTION: Find the first child of a heading
 :END:
 
-- Syntax: first-child
+- Syntax: first-child(OPTIONS...)
 
 Return the first child of the source heading.  If the source heading has no
 children, no target is returned.
@@ -407,7 +367,7 @@ argument.
 :DESCRIPTION: Find the next sibling
 :END:
 
-- Syntax: next-sibling
+- Syntax: next-sibling(OPTIONS...)
 
 The ~next-sibling~ keyword returns the next sibling of the source heading, if 
any.
 
@@ -417,7 +377,7 @@ The ~next-sibling~ keyword returns the next sibling of the 
source heading, if an
 :DESCRIPTION: Find the next sibling, wrapping around
 :END:
 
-- Syntax: next-sibling-wrap
+- Syntax: next-sibling-wrap(OPTIONS...)
 
 Find the next sibling of the source heading, if any.  If there isn't, wrap back
 around to the first heading in the same subtree.
@@ -472,7 +432,7 @@ Org mode file.
 :DESCRIPTION: Find a parent
 :END:
 
-- Syntax: parent
+- Syntax: parent(OPTIONS...)
 
 Returns the parent of the source heading, if any.
 
@@ -482,21 +442,133 @@ Returns the parent of the source heading, if any.
 :DESCRIPTION: Find the previous sibling
 :END:
 
-- Syntax: previous-sibling
+- Syntax: previous-sibling(OPTIONS...)
+
+Returns the previous sibling of the source heading on the same level.
+
+*** previous-sibling-wrap
+:PROPERTIES:
+:CUSTOM_ID: previous-sibling-wrap
+:DESCRIPTION: Find the previous sibling, with wrapping
+:END:
+
+- Syntax: previous-sibling-wrap(OPTIONS...)
 
 Returns the previous sibling of the source heading on the same level.
 
+*** relatives
+:PROPERTIES:
+:CUSTOM_ID: relatives
+:DESCRIPTION: Generic relative finder
+:END:
+
+Find some relative of the current heading.
+
+- Syntax: relatives(OPTION OPTION...)
+- Syntax: chain-find(OPTION OPTION...)
+
+Identical to the chain argument in org-depend, relatives selects its single
+target using the following method:
+
+1. Creates a list of possible targets
+2. Filters the targets from Step 1
+3. Sorts the targets from Step 2
+
+One option from each of the following three categories may be
+used; if more than one is specified, the last will be used.
+Filtering is the exception to this; each filter argument adds to
+the current filter.  Apart from that, argument order is
+irrelevant.
+
+The chain-find finder is also provided for backwards
+compatibility, and for similarity to org-depend.
+
+All arguments are symbols, unless noted otherwise.
+
+*Selection*
+
+- from-top:             Select siblings of the current heading, starting at 
the top
+- from-bottom:          As above, but from the bottom
+- from-current:         Selects siblings, starting from the heading (wraps)
+- no-wrap:              As above, but without wrapping
+- forward-no-wrap:      Find entries on the same level, going forward
+- forward-wrap:         As above, but wrap when the end is reached
+- backward-no-wrap:     Find entries on the same level, going backward
+- backward-wrap:        As above, but wrap when the start is reached
+- walk-up:              Walk up the tree, excluding self
+- walk-up-with-self:    As above, but including self
+- walk-down:            Recursively walk down the tree, excluding self
+- walk-down-with-self:  As above, but including self
+- step-down:            Collect headings from one level down
+
+*Filtering*
+
+- todo-only:          Select only targets with TODO state set that isn't a 
DONE state
+- todo-and-done-only: Select all targets with a TODO state set
+- no-comments:        Skip commented headings
+- no-archive:         Skip archived headings
+- NUMBER:             Only use that many headings, starting from the first one
+                      If passed 0, use all headings
+                      If <0, omit that many headings from the end
+- "+tag":             Only select headings with given tag
+- "-tag":             Only select headings without tag
+- "REGEX":            select headings whose titles match REGEX
+
+*Sorting*
+
+- no-sort:         Remove other sorting in affect
+- reverse-sort:    Reverse other sorts (stacks with other sort methods)
+- random-sort:     Sort in a random order
+- priority-up:     Sort by priority, highest first
+- priority-down:   Same, but lowest first
+- effort-up:       Sort by effort, highest first
+- effort-down:     Sort by effort, lowest first
+- scheduled-up:    Scheduled time, farthest first
+- scheduled-down:  Scheduled time, closest first
+- deadline-up:     Deadline time, farthest first
+- deadline-down:   Deadline time, closest first
+
+Many of the other finders are shorthand for argument combinations of relative:
+
+- [[#ancestors][ancestors]] :: walk-up
+- [[#children][children]] :: step-down
+- [[#descendants][descendants]] :: walk-down
+- [[#first-child][first-child]] :: step-down 1
+- [[#next-sibling][next-sibling]] :: forward-no-wrap 1
+- [[#next-sibling-wrap][next-sibling-wrap]] :: forward-wrap 1
+- [[#parent][parent]] :: walk-up 1
+- [[#previous-sibling][previous-sibling]] :: backward-no-wrap 1
+- [[#previous-sibling-wrap][previous-sibling-wrap]] :: backward-wrap 1
+- [[#rest-of-siblings][rest-of-siblings]] :: forward-no-wrap
+- [[#rest-of-siblings-wrap][rest-of-siblings-wrap]] :: forward-wrap
+- [[#siblings][siblings]] :: from-top
+- [[#siblings-wrap][siblings-wrap]] :: forward-wrap
+
+Because these are implemented as shorthand, any arguments for relatives may 
also
+be passed to one of these finders.
+
 *** rest-of-siblings
 :PROPERTIES:
 :CUSTOM_ID: rest-of-siblings
 :DESCRIPTION: Find the remaining siblings
 :END:
 
-- Syntax: rest-of-siblings
+- Syntax: rest-of-siblings(OPTIONS...)
 
 Starting from the heading following the current one, all same-level siblings
 are returned.
 
+*** rest-of-siblings-wrap
+:PROPERTIES:
+:CUSTOM_ID: rest-of-siblings-wrap
+:DESCRIPTION: Find the remaining siblings, with wrapping
+:END:
+
+- Syntax: rest-of-siblings-wrap(OPTIONS...)
+
+Starting from the heading following the current one, all same-level siblings
+are returned.  When the end is reached, wrap back to the beginning.
+
 *** self
 :PROPERTIES:
 :CUSTOM_ID: self
@@ -512,10 +584,10 @@ Returns the source heading.
 :DESCRIPTION: Find all the siblings
 :END:
 
-- Syntax: siblings
+- Syntax: siblings(OPTIONS...)
 
 Returns all siblings of the source heading as targets, starting from the first
-sibling, and ignoring the source heading.
+sibling.
 
 *** siblings-wrap
 :PROPERTIES:
@@ -523,11 +595,13 @@ sibling, and ignoring the source heading.
 :DESCRIPTION: Find the siblings, but wrap around
 :END:
 
-- Syntax: siblings-wrap
+- Syntax: siblings-wrap(OPTIONS...)
 
 Finds the siblings on the same level as the source heading, wrapping when it
 reaches the end.
 
+Identical to the [[#rest-of-siblings-wrap][rest-of-siblings-wrap]] finder.
+
 ** Actions
 :PROPERTIES:
 :DESCRIPTION: Next steps



reply via email to

[Prev in Thread] Current Thread [Next in Thread]