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

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

[elpa] externals/org-edna 8258a4d: Synced with upstream


From: Ian Dunn
Subject: [elpa] externals/org-edna 8258a4d: Synced with upstream
Date: Wed, 2 Sep 2020 09:45:10 -0400 (EDT)

branch: externals/org-edna
commit 8258a4dfa00aa522249cdf9aeea5be4de97bd7c1
Author: Ian Dunn <ian@keyspoke.net>
Commit: Ian Dunn <ian@keyspoke.net>

    Synced with upstream
---
 org-edna.el   | 118 ++++++++++++++++--------
 org-edna.info | 282 ++++++++++++++++++++++++++++++++++++++++------------------
 org-edna.org  |  78 ++++++++++++++++
 3 files changed, 357 insertions(+), 121 deletions(-)

diff --git a/org-edna.el b/org-edna.el
index f743c96..fac34ef 100644
--- a/org-edna.el
+++ b/org-edna.el
@@ -7,7 +7,7 @@
 ;; Keywords: convenience, text, org
 ;; URL: https://savannah.nongnu.org/projects/org-edna-el/
 ;; Package-Requires: ((emacs "25.1") (seq "2.19") (org "9.0.5"))
-;; Version: 1.1.1
+;; Version: 1.1.2
 
 ;; This file is part of GNU Emacs.
 
@@ -88,6 +88,20 @@ it will be used.  It should be either \"short\" or
   :type '(choice (const :tag "Short Format" short)
                  (const :tag "Long Format" long)))
 
+(defcustom org-edna-from-todo-states 'todo
+  "Category of TODO states that allow Edna to run.
+
+This is one of the following options:
+
+If `todo', Edna will run when changing TODO state from an entry
+in `org-not-done-keywords'.
+
+If `not-done', Edna will run when changing TODO state from any
+entry that's not in `org-done-keywords'.  This includes TODO
+state being empty."
+  :type '(choice (const :tag "TODO Keywords" todo)
+                 (const :tag "Not DONE Keywords" not-done)))
+
 ;;; Form Parsing
 
 ;; 3 types of "forms" here
@@ -113,6 +127,14 @@ ERROR-POS is the positiong in MSG at which the error 
occurred."
      "Org Edna Syntax Error: %s\n%s\n%s"
      msg form (concat (make-string pos ?\ ) "^"))))
 
+(defun org-edna--id-pred-p (arg)
+  "Return non-nil if ARG matches id:UUID.
+
+UUID is any UUID recognized by `org-uuidgen-p'."
+  (save-match-data
+    (when (string-match "^id:\\(.*\\)" (symbol-name arg))
+      (org-uuidgen-p (match-string 1 (symbol-name arg))))))
+
 (defun org-edna--transform-arg (arg)
   "Transform argument ARG.
 
@@ -126,6 +148,10 @@ Everything else is returned as is."
           ;; Name matches `org-uuidgen-p'
           (let (pred org-uuidgen-p) (symbol-name arg)))
      (symbol-name arg))
+    ((and (pred symbolp) ;; Symbol
+          ;; Name matches `org-uuidgen-p'
+          (pred org-edna--id-pred-p))
+     (symbol-name arg))
     (_
      arg)))
 
@@ -631,34 +657,40 @@ this after reverting Org mode buffers."
 
 ;;; Interactive Functions
 
-(defmacro org-edna-run (change-plist &rest body)
-  "Run a TODO state change.
+(defun org-enda--should-run-in-from-state-p (from)
+  (pcase org-edna-from-todo-states
+    ('todo
+     (member from (cons 'todo org-not-done-keywords)))
+    ('not-done
+     (not (member from (cons 'done org-done-keywords))))))
+
+(defun org-edna--should-run-p (change-plist)
+  "Check if Edna should run.
 
 The state information is held in CHANGE-PLIST.  If the TODO state
 is changing from a TODO state to a DONE state, run BODY."
-  (declare (indent 1))
-  `(let* ((pos (plist-get ,change-plist :position))
-          (type (plist-get ,change-plist :type))
-          (from (plist-get ,change-plist :from))
-          (to (plist-get ,change-plist :to)))
-     (if (and
-          ;; We are only handling todo-state-change
-          (eq type 'todo-state-change)
-          ;; And only from a TODO state to a DONE state
-          (member from (cons 'todo org-not-done-keywords))
-          (member to (cons 'done org-done-keywords)))
-         (condition-case-unless-debug err
-             ,@body
-           (error
-            (if (eq (car err) 'invalid-read-syntax)
-                (org-edna--print-syntax-error (cdr err))
-              (message "Edna Error at heading %s: %s" (org-get-heading t t t) 
(error-message-string err)))
-            (setq org-block-entry-blocking (org-get-heading))
-            ;; Block
-            nil))
-       ;; Return t for the blocker to let the calling function know that there
-       ;; is no block here.
-       t)))
+  (let* ((type (plist-get change-plist :type))
+         (from (plist-get change-plist :from))
+         (to (plist-get change-plist :to)))
+    (and
+     ;; We are only handling todo-state-change
+     (eq type 'todo-state-change)
+     ;; And only from a TODO state to a DONE state
+     (org-enda--should-run-in-from-state-p from)
+     (member to (cons 'done org-done-keywords)))))
+
+(defmacro org-edna-run (&rest body)
+  "Run a TODO state change."
+  (declare (indent 0))
+  `(condition-case-unless-debug err
+       ,@body
+     (error
+      (if (eq (car err) 'invalid-read-syntax)
+          (org-edna--print-syntax-error (cdr err))
+        (message "Edna Error at heading %s: %s" (org-get-heading t t t) 
(error-message-string err)))
+      (setq org-block-entry-blocking (org-get-heading))
+      ;; Block
+      nil)))
 
 (defun org-edna-trigger-function (change-plist)
   "Trigger function work-horse.
@@ -666,9 +698,11 @@ is changing from a TODO state to a DONE state, run BODY."
 See `org-edna-run' for CHANGE-PLIST explanation.
 
 This shouldn't be run from outside of `org-trigger-hook'."
-  (org-edna-run change-plist
-    (when-let* ((form (org-entry-get pos "TRIGGER" org-edna-use-inheritance)))
-      (org-edna-process-form form 'action))))
+  (when (org-edna--should-run-p change-plist)
+    (org-edna-run
+      (when-let* ((form (org-entry-get (plist-get change-plist :position)
+                                       "TRIGGER" org-edna-use-inheritance)))
+        (org-edna-process-form form 'action)))))
 
 (defun org-edna-blocker-function (change-plist)
   "Blocker function work-horse.
@@ -676,11 +710,16 @@ This shouldn't be run from outside of `org-trigger-hook'."
 See `org-edna-run' for CHANGE-PLIST explanation.
 
 This shouldn't be run from outside of `org-blocker-hook'."
-  (org-edna-run change-plist
-    (if-let* ((form (org-entry-get pos "BLOCKER" org-edna-use-inheritance)))
-        ;; Return nil if there is no blocking entry
-        (not (setq org-block-entry-blocking (org-edna-process-form form 
'condition)))
-      t)))
+  (if (org-edna--should-run-p change-plist)
+      (org-edna-run
+        (if-let* ((form (org-entry-get (plist-get change-plist :position)
+                                       "BLOCKER" org-edna-use-inheritance)))
+            ;; Return nil if there is no blocking entry
+            (not (setq org-block-entry-blocking (org-edna-process-form form 
'condition)))
+          t))
+    ;; Return t for the blocker to let the calling function know that there
+    ;; is no block here.
+    t))
 
 ;;;###autoload
 (defun org-edna--load ()
@@ -755,10 +794,17 @@ honoring any restriction (the equivalent of the nil SCOPE 
in
 
 Edna Syntax: ids(ID1 ID2 ...)
 
-Each ID is a UUID as understood by `org-id-find'.
+Each ID is a UUID as understood by `org-id-find'.  Alternatively,
+ID may also be id:UUID, where UUID is a UUID as understood by
+`org-id-find'.
 
 Note that in the edna syntax, the IDs don't need to be quoted."
-  (mapcar (lambda (id) (org-id-find id 'marker)) ids))
+  (mapcar
+   (lambda (id)
+     (if (string-prefix-p "id:" id)
+         (org-id-find (string-remove-prefix "id:" id) 'marker)
+       (org-id-find id 'marker)))
+   ids))
 
 (defun org-edna-finder/self ()
   "Finder for the current heading.
diff --git a/org-edna.info b/org-edna.info
index 0bd114c..7e2eb71 100644
--- a/org-edna.info
+++ b/org-edna.info
@@ -81,6 +81,7 @@ Advanced Features
 * Conditions::                   More than just DONE headings
 * Consideration::                Only some of them
 * Conditional Forms::            If/Then/Else
+* What Constitutes ``Not Done''?:: Changing from which states Edna will 
activate
 * Setting the Properties::       The easy way to set BLOCKER and TRIGGER
 
 Conditions
@@ -116,6 +117,9 @@ Contributing
 
 Changelog
 
+* 1.1.2: 112.
+* 1.1.1: 111.
+* 1.1.0: 110.
 * 1.0.2: 102.
 * 1.0.1: 101.
 * 1.0: 10.
@@ -134,7 +138,7 @@ File: org-edna.info,  Node: Copying,  Next: Introduction,  
Prev: Top,  Up: Top
 Copying
 *******
 
-Copyright (C) 2017-2018 Free Software Foundation, Inc.
+Copyright (C) 2017-2020 Free Software Foundation, Inc.
 
      This program is free software: you can redistribute it and/or
      modify it under the terms of the GNU General Public License as
@@ -488,6 +492,9 @@ ids
 
    Note that UUIDs need not be quoted; Edna will handle that for you.
 
+   The IDs may also be prefixed with ‘id:’, allowing the links to the
+headings themselves to be used.
+
 
 File: org-edna.info,  Node: match,  Next: next-sibling,  Prev: ids,  Up: 
Finders
 
@@ -1168,6 +1175,7 @@ Advanced Features
 * Conditions::                   More than just DONE headings
 * Consideration::                Only some of them
 * Conditional Forms::            If/Then/Else
+* What Constitutes ``Not Done''?:: Changing from which states Edna will 
activate
 * Setting the Properties::       The easy way to set BLOCKER and TRIGGER
 
 
@@ -1490,7 +1498,7 @@ applies.
 mean the same thing.
 
 
-File: org-edna.info,  Node: Conditional Forms,  Next: Setting the Properties,  
Prev: Consideration,  Up: Advanced Features
+File: org-edna.info,  Node: Conditional Forms,  Next: What Constitutes ``Not 
Done''?,  Prev: Consideration,  Up: Advanced Features
 
 Conditional Forms
 =================
@@ -1559,8 +1567,75 @@ the condition.
    The conditional block tells it to evaluate that section.  Thus, you
 can conditionally add targets, or conditionally check conditions.
 
+   Another common use case is to check for a property:
+
+     * TODO My Task
+       :PROPERTIES:
+       :TRIGGER: if self has-property?("REPEAT" "2") then self 
set-property!("REPEAT" inc) todo!("TODO") endif
+       :REPEAT: 0
+       :END:
+
+   When “My Task” is set to DONE, REPEAT will be incremented, then the
+task will be set back to TODO.  This happens until REPEAT is 2.  Once
+that happens, the task will be left alone, staying in the DONE state.
+
+   Be warned that trying the above example with a repeater will not
+work.  In order for that to work, Edna must take over the repeater:
+
+     * TODO My Task
+       SCHEDULED: <2020-09-02 Wed>
+       :PROPERTIES:
+       :TRIGGER: if self has-property?("REPEAT" "2") then self 
set-property!("REPEAT" inc) scheduled!("+1d") todo!("TODO") endif
+       :REPEAT: 0
+       :END:
+
+   This example will increment the SCHEDULED time by one day every time
+the task is marked DONE.
+
 
-File: org-edna.info,  Node: Setting the Properties,  Prev: Conditional Forms,  
Up: Advanced Features
+File: org-edna.info,  Node: What Constitutes ``Not Done''?,  Next: Setting the 
Properties,  Prev: Conditional Forms,  Up: Advanced Features
+
+What Constitutes “Not Done”?
+============================
+
+Sometimes, you have a heading like this:
+
+     * My Task
+       :PROPERTIES:
+       :TRIGGER:  self set-property!("TEST" inc)
+       :END:
+
+   You want to mark it as DONE because that’s how you do things.  Will
+Edna run when you do that?
+
+   The answer is it can.  There is user variable called
+‘org-edna-from-todo-states’ that controls the categories of TODO states
+from which changing a heading will cause Edna to run.  This has two
+possible values:
+
+todo
+     Edna will only run if the old TODO state is in
+     ‘org-not-done-keywords’.  This is the default.
+not-done
+     Edna will run if the old TODO state is *not* in
+     ‘org-done-keywords’.  This includes no state at all.
+
+   Further, using *note conditional forms: Conditional Forms, it is
+possible to take different actions depending on the new TODO state.  For
+example:
+
+     * My Task
+       :PROPERTIES:
+       :TRIGGER:  if self todo-state?("COMPLETE") then self 
set-property!("TEST" inc) endif
+       :TEST:     0
+       :END:
+
+   This will only increment the TEST property if the new TODO state is
+*not* “COMPLETE”.  Currently, there is no way to take different actions
+depending on the *old* TODO state.
+
+
+File: org-edna.info,  Node: Setting the Properties,  Prev: What Constitutes 
``Not Done''?,  Up: Advanced Features
 
 Setting the Properties
 ======================
@@ -1876,6 +1951,9 @@ Changelog
 
 * Menu:
 
+* 1.1.2: 112.
+* 1.1.1: 111.
+* 1.1.0: 110.
 * 1.0.2: 102.
 * 1.0.1: 101.
 * 1.0: 10.
@@ -1888,7 +1966,37 @@ Changelog
 * 1.0beta2: 10beta2.
 
 
-File: org-edna.info,  Node: 102,  Next: 101,  Up: Changelog
+File: org-edna.info,  Node: 112,  Next: 111,  Up: Changelog
+
+1.1.2
+=====
+
+   • Allow ‘id:’ syntax in ‘ids’ finder
+   • Added setting ‘org-edna-from-todo-states’
+        • See *note What Constitutes “Not Done”: What Constitutes ``Not
+          Done''?. for more
+
+
+File: org-edna.info,  Node: 111,  Next: 110,  Prev: 112,  Up: Changelog
+
+1.1.1
+=====
+
+   • Marked ‘org-edna-load’ and ‘org-edna-unload’ as deprecated
+   • Renamed to ‘org-edna--load’ and ‘org-edna--unload’ to reflect
+     internal use only intention
+
+
+File: org-edna.info,  Node: 110,  Next: 102,  Prev: 111,  Up: Changelog
+
+1.1.0
+=====
+
+   • Added ‘org-edna-mode’ as a minor mode, as opposed to
+     ‘org-edna-load’ and ‘org-edna-unload’
+
+
+File: org-edna.info,  Node: 102,  Next: 101,  Prev: 110,  Up: Changelog
 
 1.0.2
 =====
@@ -2038,87 +2146,91 @@ Big release here, with three new features.
 
 Tag Table:
 Node: Top225
-Node: Copying4483
-Node: Introduction5306
-Node: Installation and Setup6254
-Node: Basic Operation7060
-Node: Blockers8911
-Node: Triggers9198
-Node: Syntax9460
-Node: Basic Features10150
-Node: Finders10504
-Node: ancestors12269
-Node: children12863
-Node: descendants13273
-Node: file13795
-Node: first-child14544
-Node: ids14804
-Node: match15465
-Node: next-sibling16103
-Node: next-sibling-wrap16360
-Node: olp16674
-Node: org-file17087
-Node: parent17732
-Node: previous-sibling17930
-Node: previous-sibling-wrap18191
-Node: relatives18470
-Node: rest-of-siblings22196
-Node: rest-of-siblings-wrap22481
-Node: self22830
-Node: siblings22991
-Node: siblings-wrap23228
-Node: Actions23532
-Node: Scheduled/Deadline24295
-Node: Timestamp Format27883
-Node: TODO State28771
-Node: Archive29496
-Node: Chain Property29816
-Node: Clocking30569
-Node: Property30981
-Node: Priority33154
-Node: Tag33723
-Node: Effort33940
-Node: Getting Help34324
-Node: Advanced Features34769
-Node: Finder Cache35217
-Node: Conditions36665
-Node: Heading is DONE37550
-Node: File Has Headings37756
-Node: Heading TODO State38178
-Node: Lisp Variable Set38472
-Node: Heading Has Property39141
-Node: Regexp Search39887
-Node: Checking Tags40330
-Node: Matching Headings41232
-Node: Negating Conditions41829
-Node: Multiple Conditions42252
-Node: Consideration42934
-Node: Conditional Forms45120
-Node: Setting the Properties47809
-Node: Extending Edna48893
-Node: Naming Conventions49383
-Node: Finders (1)50177
-Node: Actions (1)50543
-Node: Conditions (1)51008
-Node: Contributing51898
-Node: Bugs52764
-Node: Working with EDE53121
-Node: Compiling Edna54206
-Node: Testing Edna55075
-Node: Before Sending Changes56057
-Node: Developing with Bazaar56744
-Node: Documentation57485
-Node: Changelog57941
-Node: 10258230
-Node: 10158510
-Node: 1058647
-Node: 10beta859161
-Node: 10beta759284
-Node: 10beta659578
-Node: 10beta559854
-Node: 10beta460241
-Node: 10beta360494
-Node: 10beta260933
+Node: Copying4606
+Node: Introduction5429
+Node: Installation and Setup6377
+Node: Basic Operation7183
+Node: Blockers9034
+Node: Triggers9321
+Node: Syntax9583
+Node: Basic Features10273
+Node: Finders10627
+Node: ancestors12392
+Node: children12986
+Node: descendants13396
+Node: file13918
+Node: first-child14667
+Node: ids14927
+Node: match15695
+Node: next-sibling16333
+Node: next-sibling-wrap16590
+Node: olp16904
+Node: org-file17317
+Node: parent17962
+Node: previous-sibling18160
+Node: previous-sibling-wrap18421
+Node: relatives18700
+Node: rest-of-siblings22426
+Node: rest-of-siblings-wrap22711
+Node: self23060
+Node: siblings23221
+Node: siblings-wrap23458
+Node: Actions23762
+Node: Scheduled/Deadline24525
+Node: Timestamp Format28113
+Node: TODO State29001
+Node: Archive29726
+Node: Chain Property30046
+Node: Clocking30799
+Node: Property31211
+Node: Priority33384
+Node: Tag33953
+Node: Effort34170
+Node: Getting Help34554
+Node: Advanced Features34999
+Node: Finder Cache35528
+Node: Conditions36976
+Node: Heading is DONE37861
+Node: File Has Headings38067
+Node: Heading TODO State38489
+Node: Lisp Variable Set38783
+Node: Heading Has Property39452
+Node: Regexp Search40198
+Node: Checking Tags40641
+Node: Matching Headings41543
+Node: Negating Conditions42140
+Node: Multiple Conditions42563
+Node: Consideration43245
+Node: Conditional Forms45431
+Node: What Constitutes ``Not Done''?49054
+Node: Setting the Properties50452
+Node: Extending Edna51549
+Node: Naming Conventions52039
+Node: Finders (1)52833
+Node: Actions (1)53199
+Node: Conditions (1)53664
+Node: Contributing54554
+Node: Bugs55420
+Node: Working with EDE55777
+Node: Compiling Edna56862
+Node: Testing Edna57731
+Node: Before Sending Changes58713
+Node: Developing with Bazaar59400
+Node: Documentation60141
+Node: Changelog60597
+Node: 11260928
+Node: 11161214
+Node: 11061487
+Node: 10261691
+Node: 10161983
+Node: 1062120
+Node: 10beta862634
+Node: 10beta762757
+Node: 10beta663051
+Node: 10beta563327
+Node: 10beta463714
+Node: 10beta363967
+Node: 10beta264406
 
 End Tag Table
 
diff --git a/org-edna.org b/org-edna.org
index eacbd76..408943c 100644
--- a/org-edna.org
+++ b/org-edna.org
@@ -338,6 +338,9 @@ Here, "Test" will block until the heading with ID
 
 Note that UUIDs need not be quoted; Edna will handle that for you.
 
+The IDs may also be prefixed with ~id:~, allowing the links to the headings
+themselves to be used.
+
 *** match
 :PROPERTIES:
 :CUSTOM_ID: match
@@ -1349,6 +1352,77 @@ The second is to switch the then and else clauses:
 The conditional block tells it to evaluate that section.  Thus, you can
 conditionally add targets, or conditionally check conditions.
 
+Another common use case is to check for a property:
+
+#+begin_src org
+,* TODO My Task
+  :PROPERTIES:
+  :TRIGGER: if self has-property?("REPEAT" "2") then self 
set-property!("REPEAT" inc) todo!("TODO") endif
+  :REPEAT: 0
+  :END:
+#+end_src
+
+When "My Task" is set to DONE, REPEAT will be incremented, then the task will 
be
+set back to TODO.  This happens until REPEAT is 2.  Once that happens, the task
+will be left alone, staying in the DONE state.
+
+Be warned that trying the above example with a repeater will not work.  In 
order
+for that to work, Edna must take over the repeater:
+
+#+begin_src org
+,* TODO My Task
+  SCHEDULED: <2020-09-02 Wed>
+  :PROPERTIES:
+  :TRIGGER: if self has-property?("REPEAT" "2") then self 
set-property!("REPEAT" inc) scheduled!("+1d") todo!("TODO") endif
+  :REPEAT: 0
+  :END:
+#+end_src
+
+This example will increment the SCHEDULED time by one day every time the task 
is
+marked DONE.
+
+** What Constitutes "Not Done"?
+:PROPERTIES:
+:CUSTOM_ID: not_done
+:DESCRIPTION: Changing from which states Edna will activate
+:END:
+
+Sometimes, you have a heading like this:
+
+#+begin_src org
+,* My Task
+  :PROPERTIES:
+  :TRIGGER:  self set-property!("TEST" inc)
+  :END:
+#+end_src
+
+You want to mark it as DONE because that's how you do things.  Will Edna run
+when you do that?
+
+The answer is it can.  There is user variable called 
~org-edna-from-todo-states~
+that controls the categories of TODO states from which changing a heading will
+cause Edna to run.  This has two possible values:
+
+- todo :: Edna will only run if the old TODO state is in
+  ~org-not-done-keywords~.  This is the default.
+- not-done :: Edna will run if the old TODO state is *not* in
+  ~org-done-keywords~.  This includes no state at all.
+
+Further, using [[#conditional_forms][conditional forms]], it is possible to 
take different actions
+depending on the new TODO state.  For example:
+
+#+begin_src org
+,* My Task
+  :PROPERTIES:
+  :TRIGGER:  if self todo-state?("COMPLETE") then self set-property!("TEST" 
inc) endif
+  :TEST:     0
+  :END:
+#+end_src
+
+This will only increment the TEST property if the new TODO state is *not*
+"COMPLETE".  Currently, there is no way to take different actions depending on
+the *old* TODO state.
+
 ** Setting the Properties
 :PROPERTIES:
 :DESCRIPTION: The easy way to set BLOCKER and TRIGGER
@@ -1643,6 +1717,10 @@ making any changes:
 :PROPERTIES:
 :DESCRIPTION: List of changes by version
 :END:
+** 1.1.2
+- Allow ~id:~ syntax in ~ids~ finder
+- Added setting ~org-edna-from-todo-states~
+  - See [[#not_done][What Constitutes "Not Done"]] for more
 ** 1.1.1
 - Marked ~org-edna-load~ and ~org-edna-unload~ as deprecated
 - Renamed to ~org-edna--load~ and ~org-edna--unload~ to reflect internal use 
only intention



reply via email to

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