Re: [PATCH] lisp/org-element.el: Add repeater-deadline support to org-element

2024-04-11 Thread Ihor Radchenko
Morgan Smith  writes:

> See two patches attached again.  All tests pass on my computer.

Thanks!
Applied, onto main, with amendments (see the attached diffs).
https://git.savannah.gnu.org/cgit/emacs/org-mode.git/commit/?id=66e307b41
https://git.sr.ht/~bzg/worg/commit/f1486f42

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index 2b418cd3c..e61bd6988 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -516,7 +516,9 @@ and returns an appropriate timestamp string.
 
 ~org-element-timestamp-parser~ now adds =:repeater-deadline-value= and
 =:repeater-deadline-unit= properties to each timestamp object that has
-a repeater deadline.
+a repeater deadline.  For example, in =<2012-03-29 Thu ++1y/2y>=, =2y=
+is the repeater deadline with a value of =2= and unit of =y=.  See
+"5.3.3 Tracking your habits" section in the manual.
 
 Possible values for =:repeater-deadline-value=: ~positive integer~, ~nil~.
 
diff --git a/lisp/org-element.el b/lisp/org-element.el
index 49a312694..e7561f16f 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -4331,13 +4331,13 @@ (defun org-element-timestamp-parser ()
   (and (not diaryp)
(string-match
 (rx
- (group (or "+" "++" ".+"))
- (group (+ digit))
- (group (or "h" "d" "w" "m" "y"))
- (\?
+ (group-n 1 (or "+" "++" ".+"))
+ (group-n 2 (+ digit))
+ (group-n 3 (any "hdwmy"))
+ (optional
   "/"
-  (group (+ digit))
-  (group (or "h" "d" "w" "m" "y"
+  (group-n 4 (+ digit))
+  (group-n 5 (any "hdwmy"
 raw-value)
(nconc
 (list
@@ -4427,17 +4427,15 @@ (defun org-element-timestamp-interpreter (timestamp _)
 	   (and val (number-to-string val)))
 	 (pcase (org-element-property :repeater-unit timestamp)
 	   (`hour "h") (`day "d") (`week "w") (`month "m") (`year "y"))
- (let ((repeater-deadline-value
-(org-element-property :repeater-deadline-value timestamp))
-   (repeater-deadline-unit
-(org-element-property :repeater-deadline-unit timestamp)))
-   (if (and repeater-deadline-value repeater-deadline-unit)
-   (concat
-"/"
-(number-to-string repeater-deadline-value)
-(pcase repeater-deadline-unit
-  (`hour "h") (`day "d") (`week "w") (`month "m") (`year "y")))
- ""
+ (when-let ((repeater-deadline-value
+ (org-element-property :repeater-deadline-value timestamp))
+(repeater-deadline-unit
+ (org-element-property :repeater-deadline-unit timestamp)))
+   (concat
+"/"
+(number-to-string repeater-deadline-value)
+(pcase repeater-deadline-unit
+  (`hour "h") (`day "d") (`week "w") (`month "m") (`year "y"))
(range-type (org-element-property :range-type timestamp))
(warning-string
 	(concat
diff --git a/org-syntax.org b/org-syntax.org
index c8eb7f77..70a46dcf 100644
--- a/org-syntax.org
+++ b/org-syntax.org
@@ -1776,8 +1776,8 @@ ** Timestamps
 + TIME (optional) :: An instance of the pattern =H:MM= where =H=
   represents a one to two digit number (and can start with =0=), and =M=
   represents a single digit.
-+ REPEATER-OR-DELAY (optional) :: An instance of a single REPEATER and/or an
-  instance of a single DELAY in any order.
++ REPEATER-OR-DELAY (optional) :: An instance of a single =REPEATER= and/or an
+  instance of a single =DELAY= in any order.
 + REPEATER (optional) :: An instance of the following pattern:
   #+begin_example
 MARK VALUE UNIT
@@ -1786,18 +1786,18 @@ ** Timestamps
   Where MARK, VALUE and UNIT are not separated by whitespace characters.
   - MARK :: Either the string =+= (cumulative type), =++= (catch-up type),
 or =.+= (restart type).
-  - VALUE :: A number
+  - VALUE :: A number.
   - UNIT :: Either the character =h= (hour), =d= (day), =w= (week), =m=
-(month), or =y= (year)
+(month), or =y= (year).
 + DELAY (optional) :: An instance of the following pattern:
   #+begin_example
 MARK VALUE UNIT
   #+end_example
   Where MARK, VALUE and UNIT are not separated by whitespace characters.
   - MARK :: Either  =-= (all type) or =--= (first type).
-  - VALUE :: A number
+  - VALUE :: A number.
   - UNIT :: Either the character =h= (hour), =d= (day), =w= (week), =m=
-(month), or =y= (year)
+(mont

Re: [PATCH] lisp/org-element.el: Add repeater-deadline support to org-element

2024-04-10 Thread Morgan Smith
Apologies for the delay.  I had lots of social events surrounding the
solar eclipse.  The eclipse was really cool, I do recommend.

See two patches attached again.  All tests pass on my computer.

I decided to add an extra `let' statement to my changes to
`org-element-timestamp-parser'.  I think it adds a touch of clarity and
maybe performance.

Ihor Radchenko  writes:

>> My change in org-syntax.org now implies that a repeater
>> must come before a delay.  I don't know what syntax to use that doesn't
>> make that implication.  Although I don't see the harm in telling people
>> to put the repeater first.
>
> We can simply leave the previous REPEATER-OR-DELAY, but expand on it
> that REPEATER-OR-DELAY is an instance of REPEATER or an instance of
> DELAY. Does it make sense?

Done.

>> Done.  It's my first time using rx though.  I don't know if I should be
>> compiling it or something for performance?
>
> `rx' is a macro. It will be expanded during compilation.

Thank you for the piece of mind.  I'll have to use `rx' more often :).


Thanks for the reviews!  I'll start switching org-habit over to the
element API soon.  I've already played with that a bit

>From 582d4e7372c005f098f213b496de6f85c0c11d2f Mon Sep 17 00:00:00 2001
From: Morgan Smith 
Date: Wed, 3 Apr 2024 16:30:42 -0400
Subject: [PATCH] lisp/org-element.el: Add repeater-deadline support to
 org-element

* lisp/org-element.el (org-element-timestamp-parser,
org-element-timestamp-interpreter): Add support for repeater
deadlines.  Adds two new properties: ':repeater-deadline-value' and
':repeater-deadline-unit'.

* testing/lisp/test-org-element.el (test-org-element/timestamp-parser,
test-org-element/timestamp-interpreter): Test support for repeater
deadlines.

* etc/ORG-NEWS: Add relevant news.
---
 etc/ORG-NEWS | 14 +++
 lisp/org-element.el  | 70 +++-
 testing/lisp/test-org-element.el | 38 -
 3 files changed, 100 insertions(+), 22 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index aeb7ffd4b..2b418cd3c 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -512,6 +512,20 @@ timestamp object.  Possible values: ~timerange~, ~daterange~, ~nil~.
 ~org-element-timestamp-interpreter~ takes into account this property
 and returns an appropriate timestamp string.
 
+ New properties =:repeater-deadline-value= and =:repeater-deadline-unit= for org-element timestamp object
+
+~org-element-timestamp-parser~ now adds =:repeater-deadline-value= and
+=:repeater-deadline-unit= properties to each timestamp object that has
+a repeater deadline.
+
+Possible values for =:repeater-deadline-value=: ~positive integer~, ~nil~.
+
+Possible values for =:repeater-deadline-unit=: ~hour~, ~day~, ~week~,
+~month~, ~year~.
+
+~org-element-timestamp-interpreter~ takes into account these properties
+and returns an appropriate timestamp string.
+
  =org-link= store functions are passed an ~interactive?~ argument
 
 The ~:store:~ functions set for link types using
diff --git a/lisp/org-element.el b/lisp/org-element.el
index 8e5416d8b..49a312694 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -4288,12 +4288,13 @@ Assume point is at the target."
   "Parse time stamp at point, if any.
 
 When at a time stamp, return a new syntax node of `timestamp' type
-containing `:type', `:range-type', `:raw-value', `:year-start', `:month-start',
-`:day-start', `:hour-start', `:minute-start', `:year-end',
-`:month-end', `:day-end', `:hour-end', `:minute-end',
+containing `:type', `:range-type', `:raw-value', `:year-start',
+`:month-start', `:day-start', `:hour-start', `:minute-start',
+`:year-end', `:month-end', `:day-end', `:hour-end', `:minute-end',
 `:repeater-type', `:repeater-value', `:repeater-unit',
-`:warning-type', `:warning-value', `:warning-unit', `:begin', `:end'
-and `:post-blank' properties.  Otherwise, return nil.
+`:repeater-deadline-value', `:repeater-deadline-unit', `:warning-type',
+`:warning-value', `:warning-unit', `:begin', `:end' and `:post-blank'
+properties.  Otherwise, return nil.
 
 Assume point is at the beginning of the timestamp."
   (when (looking-at-p org-element--timestamp-regexp)
@@ -4326,20 +4327,38 @@ Assume point is at the beginning of the timestamp."
   (date-end 'daterange)
   (time-range 'timerange)
   (t nil)))
-	 (repeater-props
-	  (and (not diaryp)
-		   (string-match "\\([.+]?\\+\\)\\([0-9]+\\)\\([hdwmy]\\)"
- raw-value)
-		   (list
-		:repeater-type
-		(let ((type (match-s

Re: [PATCH] lisp/org-element.el: Add repeater-deadline support to org-element

2024-04-07 Thread Ihor Radchenko
Morgan Smith  writes:

> See two patches attached.  One for org and one for worg.  Tests still
> pass on my end.

Thanks!

>> In addition to changes in Org git, you also need to update
>> https://orgmode.org/worg/org-syntax.html#Timestamps and
>> https://orgmode.org/worg/dev/org-element-api.html(the page source is at 
>> https://git.sr.ht/~bzg/worg)
>
> Done.  Sort of.  My change in org-syntax.org now implies that a repeater
> must come before a delay.  I don't know what syntax to use that doesn't
> make that implication.  Although I don't see the harm in telling people
> to put the repeater first.

We can simply leave the previous REPEATER-OR-DELAY, but expand on it
that REPEATER-OR-DELAY is an instance of REPEATER or an instance of
DELAY. Does it make sense?

>> This will match timestamps like <2012-03-29 Thu +1y2y>. You may instead
>> use shy group \(?:...\)? around the whole /2y regexp match. (Or even
>> rewrite the regexp via rx for better readability, while we are on it).
>
> Done.  It's my first time using rx though.  I don't know if I should be
> compiling it or something for performance?

`rx' is a macro. It will be expanded during compilation.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at .
Support Org development at ,
or support my work at 



Re: [PATCH] lisp/org-element.el: Add repeater-deadline support to org-element

2024-04-04 Thread Morgan Smith
 (month), or =y= (year)
-
-There can be two instances of =REPEATER-OR-DELAY= in the timestamp: one
-as a repeater and one as a warning delay.
 
 *Examples*
 
-- 
2.41.0

>From 35af811225918d7bb19e54c1c0a6fb4858c8a33f Mon Sep 17 00:00:00 2001
From: Morgan Smith 
Date: Wed, 3 Apr 2024 16:30:42 -0400
Subject: [PATCH] lisp/org-element.el: Add repeater-deadline support to
 org-element

* lisp/org-element.el (org-element-timestamp-parser,
org-element-timestamp-interpreter): Add support for repeater
deadlines.  Adds two new properties: ':repeater-deadline-value' and
':repeater-deadline-unit'.

* testing/lisp/test-org-element.el (test-org-element/timestamp-parser,
test-org-element/timestamp-interpreter): Test support for repeater
deadlines.

* etc/ORG-NEWS: Add relevant news.
---
 etc/ORG-NEWS | 14 +++
 lisp/org-element.el  | 67 ++--
 testing/lisp/test-org-element.el | 38 +-
 3 files changed, 97 insertions(+), 22 deletions(-)

diff --git a/etc/ORG-NEWS b/etc/ORG-NEWS
index fff4f47de..ef205c228 100644
--- a/etc/ORG-NEWS
+++ b/etc/ORG-NEWS
@@ -512,6 +512,20 @@ timestamp object.  Possible values: ~timerange~, ~daterange~, ~nil~.
 ~org-element-timestamp-interpreter~ takes into account this property
 and returns an appropriate timestamp string.
 
+ New properties =:repeater-deadline-value= and =:repeater-deadline-unit= for org-element timestamp object
+
+~org-element-timestamp-parser~ now adds =:repeater-deadline-value= and
+=:repeater-deadline-unit= properties to each timestamp object that has
+a repeater deadline.
+
+Possible values for =:repeater-deadline-value=: ~positive integer~, ~nil~.
+
+Possible values for =:repeater-deadline-unit=: ~hour~, ~day~, ~week~,
+~month~, ~year~.
+
+~org-element-timestamp-interpreter~ takes into account these properties
+and returns an appropriate timestamp string.
+
  =org-link= store functions are passed an ~interactive?~ argument
 
 The ~:store:~ functions set for link types using
diff --git a/lisp/org-element.el b/lisp/org-element.el
index 8e5416d8b..79eb5eb29 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -4288,12 +4288,13 @@ Assume point is at the target."
   "Parse time stamp at point, if any.
 
 When at a time stamp, return a new syntax node of `timestamp' type
-containing `:type', `:range-type', `:raw-value', `:year-start', `:month-start',
-`:day-start', `:hour-start', `:minute-start', `:year-end',
-`:month-end', `:day-end', `:hour-end', `:minute-end',
+containing `:type', `:range-type', `:raw-value', `:year-start',
+`:month-start', `:day-start', `:hour-start', `:minute-start',
+`:year-end', `:month-end', `:day-end', `:hour-end', `:minute-end',
 `:repeater-type', `:repeater-value', `:repeater-unit',
-`:warning-type', `:warning-value', `:warning-unit', `:begin', `:end'
-and `:post-blank' properties.  Otherwise, return nil.
+`:repeater-deadline-value', `:repeater-deadline-unit', `:warning-type',
+`:warning-value', `:warning-unit', `:begin', `:end' and `:post-blank'
+properties.  Otherwise, return nil.
 
 Assume point is at the beginning of the timestamp."
   (when (looking-at-p org-element--timestamp-regexp)
@@ -4326,20 +4327,35 @@ Assume point is at the beginning of the timestamp."
   (date-end 'daterange)
   (time-range 'timerange)
   (t nil)))
-	 (repeater-props
-	  (and (not diaryp)
-		   (string-match "\\([.+]?\\+\\)\\([0-9]+\\)\\([hdwmy]\\)"
- raw-value)
-		   (list
-		:repeater-type
-		(let ((type (match-string 1 raw-value)))
-		  (cond ((equal "++" type) 'catch-up)
-			((equal ".+" type) 'restart)
-			(t 'cumulate)))
-		:repeater-value (string-to-number (match-string 2 raw-value))
-		:repeater-unit
-		(pcase (string-to-char (match-string 3 raw-value))
-		  (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (_ 'year)
+ (repeater-props
+  (and (not diaryp)
+   (string-match
+(rx
+ (group (or "+" "++" ".+"))
+ (group (+ digit))
+ (group (or "h" "d" "w" "m" "y"))
+ (\?
+  "/"
+  (group (+ digit))
+  (group (or "h" "d" "w" "m" "y"
+raw-value)
+   (nconc
+(list
+ :repeater-type
+ (le

Re: [PATCH] lisp/org-element.el: Add repeater-deadline support to org-element

2024-04-04 Thread Ihor Radchenko
Morgan Smith  writes:

> I would like to add some features to org-habit (something I have tried
> unsuccessfully in the past).  Before I do that, I would like to switch
> org-habit over to the org-element api.  Before I do that, I would like to
> extend org-element to support the org-habit syntax.
>
> Let me know what you think!  All the tests pass on my machine.

This is a welcome addition. Thanks!

Please also add etc/ORG-NEWS entry - it is org-element API change.

In addition to changes in Org git, you also need to update
https://orgmode.org/worg/org-syntax.html#Timestamps and
https://orgmode.org/worg/dev/org-element-api.html
(the page source is at https://git.sr.ht/~bzg/worg)

> +   (string-match
> +
> "\\([.+]?\\+\\)\\([0-9]+\\)\\([hdwmy]\\)/?\\([0-9]+\\)?\\([hdwmy]\\)?"

This will match timestamps like <2012-03-29 Thu +1y2y>. You may instead
use shy group \(?:...\)? around the whole /2y regexp match. (Or even
rewrite the regexp via rx for better readability, while we are on it).

> + (let ((deadline-value (org-element-property 
> :repeater-deadline-value timestamp))
> +   (deadline-unit (org-element-property 
> :repeater-deadline-unit timestamp)))

This is slightly confusing, because "deadline" has multiple meanings in
Org. repeater-deadline-value/unit would be more readable as the variable name.

-- 
Ihor Radchenko // yantar92,
Org mode contributor,
Learn more about Org mode at .
Support Org development at ,
or support my work at 



[PATCH] lisp/org-element.el: Add repeater-deadline support to org-element

2024-04-03 Thread Morgan Smith
* lisp/org-element.el (org-element-timestamp-parser,
org-element-timestamp-interpreter): Add support for repeater
deadlines.  Adds two new properties: ':repeater-deadline-value' and
':repeater-deadline-unit'.

* testing/lisp/test-org-element.el (test-org-element/timestamp-parser,
test-org-element/timestamp-interpreter): Test support for repeater
deadlines.
---

Hello!

I would like to add some features to org-habit (something I have tried
unsuccessfully in the past).  Before I do that, I would like to switch
org-habit over to the org-element api.  Before I do that, I would like to
extend org-element to support the org-habit syntax.

Let me know what you think!  All the tests pass on my machine.

Thanks,

Morgan

 lisp/org-element.el  | 58 +---
 testing/lisp/test-org-element.el | 38 +++--
 2 files changed, 74 insertions(+), 22 deletions(-)

diff --git a/lisp/org-element.el b/lisp/org-element.el
index f4eec1695..8d3b8ce44 100644
--- a/lisp/org-element.el
+++ b/lisp/org-element.el
@@ -4288,12 +4288,13 @@ Assume point is at the target."
   "Parse time stamp at point, if any.
 
 When at a time stamp, return a new syntax node of `timestamp' type
-containing `:type', `:range-type', `:raw-value', `:year-start', `:month-start',
-`:day-start', `:hour-start', `:minute-start', `:year-end',
-`:month-end', `:day-end', `:hour-end', `:minute-end',
+containing `:type', `:range-type', `:raw-value', `:year-start',
+`:month-start', `:day-start', `:hour-start', `:minute-start',
+`:year-end', `:month-end', `:day-end', `:hour-end', `:minute-end',
 `:repeater-type', `:repeater-value', `:repeater-unit',
-`:warning-type', `:warning-value', `:warning-unit', `:begin', `:end'
-and `:post-blank' properties.  Otherwise, return nil.
+`:repeater-deadline-value', `:repeater-deadline-unit', `:warning-type',
+`:warning-value', `:warning-unit', `:begin', `:end' and `:post-blank'
+properties.  Otherwise, return nil.
 
 Assume point is at the beginning of the timestamp."
   (when (looking-at-p org-element--timestamp-regexp)
@@ -4326,20 +4327,28 @@ Assume point is at the beginning of the timestamp."
   (date-end 'daterange)
   (time-range 'timerange)
   (t nil)))
-(repeater-props
- (and (not diaryp)
-  (string-match "\\([.+]?\\+\\)\\([0-9]+\\)\\([hdwmy]\\)"
-raw-value)
-  (list
-   :repeater-type
-   (let ((type (match-string 1 raw-value)))
- (cond ((equal "++" type) 'catch-up)
-   ((equal ".+" type) 'restart)
-   (t 'cumulate)))
-   :repeater-value (string-to-number (match-string 2 
raw-value))
-   :repeater-unit
-   (pcase (string-to-char (match-string 3 raw-value))
- (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (_ 'year)
+ (repeater-props
+  (and (not diaryp)
+   (string-match
+
"\\([.+]?\\+\\)\\([0-9]+\\)\\([hdwmy]\\)/?\\([0-9]+\\)?\\([hdwmy]\\)?"
+raw-value)
+   (nconc
+(list
+ :repeater-type
+ (let ((type (match-string 1 raw-value)))
+   (cond ((equal "++" type) 'catch-up)
+ ((equal ".+" type) 'restart)
+ (t 'cumulate)))
+ :repeater-value (string-to-number (match-string 2 
raw-value))
+ :repeater-unit
+ (pcase (string-to-char (match-string 3 raw-value))
+   (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (_ 'year)))
+(when (and (match-string 4 raw-value) (match-string 5 
raw-value))
+  (list
+   :repeater-deadline-value (string-to-number 
(match-string 4 raw-value))
+   :repeater-deadline-unit
+   (pcase (string-to-char (match-string 5 raw-value))
+ (?h 'hour) (?d 'day) (?w 'week) (?m 'month) (_ 
'year)))
 (warning-props
  (and (not diaryp)
   (string-match "\\(-\\)?-\\([0-9]+\\)\\([hdwmy]\\)" raw-value)
@@ -4407,7 +4416,16 @@ Assume point is at the beginning of the timestamp."
 (let ((val (org-element-property :repeater-value 
timestamp)))
   (and val (number-to-string val)))
 (pcase (org-element-property :repeater-unit timestamp)
-  (`hour "h") (`day "d") (`week "w") (`month "m") (`year 
"y"
+  (`hour "h") (`day "d") (`week "w") (`month "m") (`year 
"y"))
+ (let ((deadline-value (org-element-property 
:repeater-deadline-value timestamp))
+   (dea