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

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

[elpa] externals/taxy fcc780f 27/39: Add: (taxy-take-keyed*)


From: ELPA Syncer
Subject: [elpa] externals/taxy fcc780f 27/39: Add: (taxy-take-keyed*)
Date: Fri, 27 Aug 2021 10:57:34 -0400 (EDT)

branch: externals/taxy
commit fcc780f44a0a354519f190d96d71b57874ad2e00
Author: Adam Porter <adam@alphapapa.net>
Commit: Adam Porter <adam@alphapapa.net>

    Add: (taxy-take-keyed*)
---
 README.org | 54 ++++++++++++++++++++++++++++++++++++---
 taxy.el    | 29 +++++++++++++++++++++
 taxy.info  | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++---------
 3 files changed, 154 insertions(+), 15 deletions(-)

diff --git a/README.org b/README.org
index e062744..722e0a6 100644
--- a/README.org
+++ b/README.org
@@ -250,6 +250,12 @@ After defining a taxy, call ~taxy-fill~ with it and a list 
of objects to fill th
 To return a taxy in a more human-readable format (with only relevant fields 
included), use ~taxy-plain~.  You may also use ~taxy-map~ to replace objects in 
a taxy with, e.g. a more useful representation.
 
 ** Dynamic taxys
+:PROPERTIES:
+:TOC:      :include descendants
+:END:
+:CONTENTS:
+- [[#multi-level-dynamic-taxys][Multi-level dynamic taxys]]
+:END:
 
 You may not always know in advance what taxonomy a set of objects fits into, 
so =taxy= lets you add taxys dynamically by using the ~:take~ function to add a 
taxy when an object is "taken into" a parent taxy.  For example, you could 
dynamically classify buffers by their major mode like so:
 
@@ -302,9 +308,51 @@ The taxy's ~:take~ function is set to the 
~taxy-take-keyed~ function, partially
                  #<buffer dash.el> #<buffer *Pp Eval Output*> #<buffer 
taxy.el> #<buffer scratch.el>))))))
 #+END_SRC
 
-# ** Tips
-# 
-# + You can customize settings in the =taxy= group.
+*** Multi-level dynamic taxys
+
+Of course, the point of taxonomies is that they aren't restricted to a single 
level of depth, so you may also use the function ~taxy-take-keyed*~ (notice the 
~*~) to dynamically make multi-level taxys.  Expanding on the previous example, 
we use ~cl-labels~ to define functions which are used in the taxy's definition, 
which are used in the ~:take~ function, which calls ~taxy-take-keyed*~ (rather 
than using ~apply-partially~ like in the previous example, we use a lambda 
function, which perf [...]
+
+# MAYBE: A macro to define :take functions more concisely.
+
+#+BEGIN_SRC elisp :exports code
+  (defvar buffery
+    (cl-labels ((buffer-mode (buffer) (buffer-local-value 'major-mode buffer))
+                (buffer-directory (buffer) (buffer-local-value 
'default-directory buffer)))
+      (make-taxy
+       :name "Buffers"
+       :taxys (list
+               (make-taxy
+                :name "Directories"
+                :take (lambda (object taxy)
+                        (taxy-take-keyed* (list #'buffer-directory 
#'buffer-mode) object taxy)))))))
+
+  (taxy-plain
+   (taxy-fill (buffer-list)
+              (taxy-emptied buffery)))
+#+END_SRC
+
+That produces a list like:
+
+#+BEGIN_SRC elisp
+  ("Buffers"
+   (("Directories"
+     (("~/src/emacs/ement.el/"
+       ((dired-mode
+         (#<buffer ement.el<emacs>))
+        (emacs-lisp-mode
+         (#<buffer ement.el<ement.el> #<buffer ement-room-list.el> #<buffer 
ement-room.el>))
+        (magit-diff-mode
+         (#<buffer magit-diff: ement.el>))))
+      ("~/src/emacs/taxy.el/"
+       ((dired-mode
+         (#<buffer taxy.el<emacs>))
+        (Info-mode
+         (#<buffer *info*>))
+        (magit-status-mode
+         (#<buffer magit: taxy.el>))
+        (emacs-lisp-mode
+         (#<buffer taxy-magit-section.el> #<buffer taxy.el<taxy.el> #<buffer 
scratch.el>))))))))
+#+END_SRC
 
 ** Reusable taxys
 
diff --git a/taxy.el b/taxy.el
index 03e09b9..47bfb8c 100644
--- a/taxy.el
+++ b/taxy.el
@@ -133,6 +133,35 @@ by KEY-NAME-FN called with OBJECT."
                      (taxy-taxys taxy))))))
     (push object (taxy-objects key-taxy))))
 
+(cl-defun taxy-take-keyed* (key-fns object taxy &key (key-name-fn #'identity))
+  "Take OBJECT into TAXY, adding new taxys dynamically and recursively.
+Places OBJECT into a taxy in TAXY for the value returned by
+KEY-FNS called with OBJECT.  The new taxys are added to TAXY
+recursively as necessary.  Each new taxy's name is that returned
+by KEY-NAME-FN called with OBJECT."
+  (let ((key-fn (car key-fns)))
+    (if-let ((key (funcall key-fn object)))
+        (let ((key-taxy (or (cl-find-if (lambda (taxy-key)
+                                          (equal key taxy-key))
+                                        (taxy-taxys taxy)
+                                        :key #'taxy-key)
+                            (car
+                             (push (make-taxy
+                                    :name (funcall key-name-fn key) :key key
+                                    :predicate (lambda (object)
+                                                 (equal key (funcall key-fn 
object)))
+                                    :take (when (cdr key-fns)
+                                            (lambda (object taxy)
+                                              (taxy-take-keyed* (cdr key-fns) 
object taxy))))
+                                   (taxy-taxys taxy))))))
+          (if (cdr key-fns)
+              (taxy-take-keyed* (cdr key-fns) object key-taxy)
+            (push object (taxy-objects key-taxy))))
+      ;; No key value: push to this taxy.
+      (if (cdr key-fns)
+          (taxy-take-keyed* (cdr key-fns) object taxy)
+        (push object (taxy-objects taxy))))))
+
 ;;;; Footer
 
 (provide 'taxy)
diff --git a/taxy.info b/taxy.info
index f0d0a8b..ac6b346 100644
--- a/taxy.info
+++ b/taxy.info
@@ -29,7 +29,9 @@ Usage
 * Threading macros::
 * Magit section::
 
+Dynamic taxys
 
+* Multi-level dynamic taxys::
 
 Changelog
 
@@ -263,8 +265,9 @@ File: README.info,  Node: Dynamic taxys,  Next: Reusable 
taxys,  Up: Usage
 2.1 Dynamic taxys
 =================
 
-You may not always know in advance what taxonomy a set of objects fits
-into, so taxy lets you add taxys dynamically by using the ‘:take’
+   • 
+   You may not always know in advance what taxonomy a set of objects
+fits into, so taxy lets you add taxys dynamically by using the ‘:take’
 function to add a taxy when an object is "taken into" a parent taxy.
 For example, you could dynamically classify buffers by their major mode
 like so:
@@ -317,6 +320,64 @@ produces this taxonomy of buffers:
                     #<buffer ement-room.el> #<buffer init.el> #<buffer 
bufler.el>
                     #<buffer dash.el> #<buffer *Pp Eval Output*> #<buffer 
taxy.el> #<buffer scratch.el>))))))
 
+* Menu:
+
+* Multi-level dynamic taxys::
+
+
+File: README.info,  Node: Multi-level dynamic taxys,  Up: Dynamic taxys
+
+2.1.1 Multi-level dynamic taxys
+-------------------------------
+
+Of course, the point of taxonomies is that they aren’t restricted to a
+single level of depth, so you may also use the function
+‘taxy-take-keyed*’ (notice the ‘*’) to dynamically make multi-level
+taxys.  Expanding on the previous example, we use ‘cl-labels’ to define
+functions which are used in the taxy’s definition, which are used in the
+‘:take’ function, which calls ‘taxy-take-keyed*’ (rather than using
+‘apply-partially’ like in the previous example, we use a lambda
+function, which performs better than partially applied functions).  Then
+when the taxy is filled, a multi-level hierarchy is created dynamically,
+organizing buffers first by their directory, and then by mode in each
+directory.
+
+     (defvar buffery
+       (cl-labels ((buffer-mode (buffer) (buffer-local-value 'major-mode 
buffer))
+                   (buffer-directory (buffer) (buffer-local-value 
'default-directory buffer)))
+         (make-taxy
+          :name "Buffers"
+          :taxys (list
+                  (make-taxy
+                   :name "Directories"
+                   :take (lambda (object taxy)
+                           (taxy-take-keyed* (list #'buffer-directory 
#'buffer-mode) object taxy)))))))
+
+     (taxy-plain
+      (taxy-fill (buffer-list)
+                 (taxy-emptied buffery)))
+
+   That produces a list like:
+
+     ("Buffers"
+      (("Directories"
+        (("~/src/emacs/ement.el/"
+          ((dired-mode
+            (#<buffer ement.el<emacs>))
+           (emacs-lisp-mode
+            (#<buffer ement.el<ement.el> #<buffer ement-room-list.el> #<buffer 
ement-room.el>))
+           (magit-diff-mode
+            (#<buffer magit-diff: ement.el>))))
+         ("~/src/emacs/taxy.el/"
+          ((dired-mode
+            (#<buffer taxy.el<emacs>))
+           (Info-mode
+            (#<buffer *info*>))
+           (magit-status-mode
+            (#<buffer magit: taxy.el>))
+           (emacs-lisp-mode
+            (#<buffer taxy-magit-section.el> #<buffer taxy.el<taxy.el> 
#<buffer scratch.el>))))))))
+
 
 File: README.info,  Node: Reusable taxys,  Next: Threading macros,  Prev: 
Dynamic taxys,  Up: Usage
 
@@ -489,16 +550,17 @@ GPLv3
 
 Tag Table:
 Node: Top218
-Node: Examples1057
-Node: Usage8957
-Node: Dynamic taxys11040
-Node: Reusable taxys13407
-Node: Threading macros17564
-Node: Magit section18085
-Node: Changelog18680
-Node: 01-pre18818
-Node: Development18912
-Node: License19083
+Node: Examples1101
+Node: Usage9001
+Node: Dynamic taxys11084
+Node: Multi-level dynamic taxys13502
+Node: Reusable taxys15662
+Node: Threading macros19819
+Node: Magit section20340
+Node: Changelog20935
+Node: 01-pre21073
+Node: Development21167
+Node: License21338
 
 End Tag Table
 



reply via email to

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