[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] externals/taxy 8797141 02/39: Dynamic, consuming, and non-consumi
From: |
ELPA Syncer |
Subject: |
[elpa] externals/taxy 8797141 02/39: Dynamic, consuming, and non-consuming |
Date: |
Fri, 27 Aug 2021 10:57:29 -0400 (EDT) |
branch: externals/taxy
commit 8797141334f03dd02dc5d9fe1f7f679491da3d8d
Author: Adam Porter <adam@alphapapa.net>
Commit: Adam Porter <adam@alphapapa.net>
Dynamic, consuming, and non-consuming
Squashed commit of the following:
commit 3f2d7ee535a74518ebc04fa7da751d72698c6c13
Author: Adam Porter <adam@alphapapa.net>
Date: Wed Aug 25 06:17:31 2021 -0500
WIP: Dynamic, consuming, and non-consuming
commit 41209b371ee98e12a0939264f293cd1a8652c401
Author: Adam Porter <adam@alphapapa.net>
Date: Wed Aug 25 05:18:25 2021 -0500
WIP: Dynamic taxys
---
README.org | 145 ++++++++++++++++++++++++++++++++++++++++++++-----------------
taxy.el | 30 ++++++++-----
2 files changed, 125 insertions(+), 50 deletions(-)
diff --git a/README.org b/README.org
index 279e27e..ea7d72f 100644
--- a/README.org
+++ b/README.org
@@ -15,22 +15,24 @@ This is a silly taxonomy of numbers below 100:
#+BEGIN_SRC elisp
("Numbery" "A silly taxonomy of numbers."
(("< 10" "Numbers below 10"
- (("Odd"
+ (0 2 4 6 8)
+ (("Odd (consuming)"
(1 3 5 7 9))
- ("Even"
+ ("Even (non-consuming)"
(0 2 4 6 8))))
- ("> 10" "Numbers above 9"
- (("Divisible by 3"
+ (">= 10" "Numbers above 9"
+ (10 11 13 14 17 19 22 23 25 26 29 31 34 35 37 38 41 43 46 47 49 50 53 55
58
+ 59 61 62 65 67 70 71 73 74 77 79 82 83 85 86 89 91 94 95 97 98)
+ (("Divisible by 3 (non-consuming)"
(12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78
81 84
87 90 93 96 99))
- ("Divisible by 4"
+ ("Divisible by 4 (non-consuming)"
(12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80 84 88 92 96))
- ("Divisible by 3 or 4"
+ ("Divisible by 3 or 4 (consuming)"
(12 15 16 18 20 21 24 27 28 30 32 33 36 39 40 42 44 45 48 51 52 54 56
57 60
63 64 66 68 69 72 75 76 78 80 81 84 87 88 90 92 93 96 99))
- ("Not divisible by 3 or 4"
- (10 11 13 14 17 19 22 23 25 26 29 31 34 35 37 38 41 43 46 47 49 50 53
55 58
- 59 61 62 65 67 70 71 73 74 77 79 82 83 85 86 89 91 94 95 97 98))))))
+ ("Divisible by 5 (non-consuming)"
+ (10 25 35 50 55 65 70 85 95))))))
#+END_SRC
You might think about how to produce that by writing some imperative code, but
=taxy= allows you to do so in a more declarative and functional manner:
@@ -39,37 +41,39 @@ You might think about how to produce that by writing some
imperative code, but =
(require 'taxy)
(let ((numbery
- (make-taxy :name "Numbery"
- :description "A silly taxonomy of numbers."
- :predicate #'numberp
- :then #'ignore
- :taxys (list (make-taxy :name "< 10"
- :description "Numbers below 10"
- :predicate (lambda (n) (< n 10))
- :then #'ignore
- :taxys (list (make-taxy :name "Odd"
- :predicate
#'oddp
- :then
#'ignore)
- (make-taxy :name
"Even"
- :predicate
#'evenp
- :then
#'ignore)))
- (make-taxy :name "> 10"
- :description "Numbers above 9"
- :predicate (lambda (n) (>= n 10))
- :then #'ignore
- :taxys (list (make-taxy :name
"Divisible by 3"
- :predicate
(lambda (n) (zerop (mod n 3)))
- :then
#'identity)
- (make-taxy :name
"Divisible by 4"
- :predicate
(lambda (n) (zerop (mod n 4)))
- :then
#'identity)
- (make-taxy :name
"Divisible by 3 or 4"
- :predicate
(lambda (n) (or (zerop (mod n 3))
-
(zerop (mod n 4))))
- :then
#'ignore)
- (make-taxy :name "Not
divisible by 3 or 4"
- :predicate
#'identity
- :then
#'ignore))))))
+ (make-taxy
+ :name "Numbery"
+ :description "A silly taxonomy of numbers."
+ :predicate #'numberp
+ :then #'ignore
+ :taxys (list (make-taxy
+ :name "< 10"
+ :description "Numbers below 10"
+ :predicate (lambda (n) (< n 10))
+ :then #'ignore
+ :taxys (list (make-taxy :name "Odd (consuming)"
+ :predicate #'oddp
+ :then #'ignore)
+ (make-taxy :name "Even (non-consuming)"
+ :predicate #'evenp
+ :then #'identity)))
+ (make-taxy
+ :name ">= 10"
+ :description "Numbers above 9"
+ :predicate (lambda (n) (>= n 10))
+ :then #'ignore
+ :taxys (list (make-taxy :name "Divisible by 3
(non-consuming)"
+ :predicate (lambda (n) (zerop
(mod n 3)))
+ :then #'identity)
+ (make-taxy :name "Divisible by 4
(non-consuming)"
+ :predicate (lambda (n) (zerop
(mod n 4)))
+ :then #'identity)
+ (make-taxy :name "Divisible by 3 or 4
(consuming)"
+ :predicate (lambda (n) (or
(zerop (mod n 3))
+
(zerop (mod n 4)))))
+ (make-taxy :name "Divisible by 5
(non-consuming)"
+ :predicate (lambda (n) (zerop
(mod n 5)))
+ :then #'identity))))))
(numbers (cl-loop for i below 100 collect i)))
(taxy-simple (taxy-apply numbery (reverse numbers))))
#+END_SRC
@@ -134,6 +138,67 @@ After defining a taxy, call ~taxy-apply~ with it and a
list of objects to fill t
To return a taxy in a more human-readable format (with only relevant fields
included), use ~taxy-simple~.
+** 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~ 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:
+
+#+BEGIN_SRC elisp :exports code
+ (let* ((key-fn (lambda (buffer)
+ (buffer-local-value 'major-mode buffer)))
+ (buffery
+ (make-taxy
+ :name "Buffers"
+ :taxys (list
+ (make-taxy
+ :name "Modes"
+ :take (lambda (buffer taxy)
+ (let* ((key (funcall key-fn buffer))
+ (key-taxy
+ (or (cl-find-if (lambda (taxy-key)
+ (equal key taxy-key))
+ (taxy-taxys taxy)
+ :key #'taxy-key)
+ (car
+ (push (make-taxy
+ :name key :key key
+ :predicate (lambda (buffer)
+ (equal key
(funcall key-fn buffer))))
+ (taxy-taxys taxy))))))
+ (push buffer (taxy-objects key-taxy)))))))))
+ (taxy-simple (taxy-apply buffery (buffer-list))))
+#+END_SRC
+
+Which produces this taxonomy of buffers:
+
+#+BEGIN_SRC elisp
+ ("Buffers"
+ (("Modes"
+ ((magit-process-mode
+ (#<buffer magit-process: taxy.el> #<buffer magit-process: > #<buffer
magit-process: notes>))
+ (messages-buffer-mode
+ (#<buffer *Messages*>))
+ (special-mode
+ (#<buffer *Warnings*> #<buffer *elfeed-log*>))
+ (dired-mode
+ (#<buffer ement.el<emacs>>))
+ (Custom-mode
+ (#<buffer *Customize Apropos*>))
+ (fundamental-mode
+ (#<buffer *helm candidates:Bookmarks*> #<buffer *Backtrace*>))
+ (magit-diff-mode
+ (#<buffer magit-diff: taxy.el> #<buffer magit-diff: notes> #<buffer
magit-diff: ement.el>))
+ (compilation-mode
+ (#<buffer *compilation*> #<buffer *Compile-Log*>))
+ (Info-mode
+ (#<buffer *helm info temp buffer*> #<buffer *info*>))
+ (help-mode
+ (#<buffer *Help*>))
+ (emacs-lisp-mode
+ (#<buffer ement.el<ement.el>> #<buffer ement-room-list.el> #<buffer
*scratch*>
+ #<buffer ement-room.el> #<buffer init.el> #<buffer bufler.el>
+ #<buffer dash.el> #<buffer *Pp Eval Output*> #<buffer
taxy.el> #<buffer scratch.el>))))))
+#+END_SRC
+
# ** Tips
#
# + You can customize settings in the =taxy= group.
diff --git a/taxy.el b/taxy.el
index ddbe311..0070f27 100644
--- a/taxy.el
+++ b/taxy.el
@@ -31,8 +31,9 @@
;;;; Structs
(cl-defstruct taxy
- name description objects
- predicate then taxys)
+ name description key objects taxys dynamic
+ (predicate #'identity) (then #'ignore)
+ take)
;;;; Variables
@@ -47,14 +48,23 @@
(defun taxy-apply (taxy objects)
(cl-labels ((apply-object (taxy object)
- (cl-loop for taxy in (taxy-taxys taxy)
- while object
+ (cl-loop with taken
+ for taxy in (taxy-taxys taxy)
when (funcall (taxy-predicate taxy)
object)
- do (setf object
- (if-let* ((taxys (taxy-taxys
taxy)))
- (apply-object taxy object)
- (push object (taxy-objects
taxy))
- (funcall (taxy-then taxy)
object))))))
+ do (setf taken t
+ object (if (taxy-take taxy)
+ (progn
+ (funcall (taxy-take
taxy) object taxy)
+ (funcall (taxy-then
taxy) object))
+ (if (taxy-taxys taxy)
+ (progn
+ (or (apply-object
taxy object)
+ (push object
(taxy-objects taxy)))
+ (funcall
(taxy-then taxy) object))
+ (push object
(taxy-objects taxy))
+ (funcall (taxy-then
taxy) object))))
+ unless object return t
+ finally return nil)))
(dolist (object objects taxy)
(apply-object taxy object))))
@@ -63,7 +73,7 @@
(list (taxy-name taxy)
(taxy-description taxy)
(taxy-objects taxy)
- (mapcar #'taxy-print (taxy-taxys taxy)))))
+ (mapcar #'taxy-simple (taxy-taxys taxy)))))
;;;; Footer
- [elpa] branch externals/taxy created (now 2c044ed), ELPA Syncer, 2021/08/27
- [elpa] externals/taxy dbad5b9 01/39: Let there be taxonomy!, ELPA Syncer, 2021/08/27
- [elpa] externals/taxy 8797141 02/39: Dynamic, consuming, and non-consuming,
ELPA Syncer <=
- [elpa] externals/taxy 6c5b7c7 07/39: Add: taxy-apply, ELPA Syncer, 2021/08/27
- [elpa] externals/taxy 02217c4 11/39: Docs: Add comments, ELPA Syncer, 2021/08/27
- [elpa] externals/taxy 408a32b 09/39: Docs: Tidy, ELPA Syncer, 2021/08/27
- [elpa] externals/taxy 09724dd 10/39: Add: taxy-take-keyed, ELPA Syncer, 2021/08/27
- [elpa] externals/taxy 9d44dba 13/39: Change: taxy-apply -> taxy-map, ELPA Syncer, 2021/08/27
- [elpa] externals/taxy 6eff6ae 18/39: Docs: Put Contents first, ELPA Syncer, 2021/08/27
- [elpa] externals/taxy 0a57638 17/39: Docs: Mention threading macros, ELPA Syncer, 2021/08/27
- [elpa] externals/taxy 0dce844 16/39: Docs: Add example of incremental filling, ELPA Syncer, 2021/08/27
- [elpa] externals/taxy e09dc38 32/39: Add: (taxy-mapc*) And musicy.el example, ELPA Syncer, 2021/08/27
- [elpa] externals/taxy bd28836 24/39: Meta: Headers, ELPA Syncer, 2021/08/27