[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
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [elpa] externals/org-edna 8258a4d: Synced with upstream,
Ian Dunn <=