PoiScript / orgize

A Rust library for parsing org-mode files.
https://poiscript.github.io/orgize/
MIT License
278 stars 34 forks source link

FR: Timestamps: Repeater/delay may be specified (and different) for both parts of a range #29

Closed calmofthestorm closed 7 months ago

calmofthestorm commented 4 years ago

Org allows you to have a range with a different repeater for start and end. I've actually found this useful on occasion, when you want the interval to grow every time something is marked done, when combined with org-habit.

For example: <2020-01-01 ++1w -1d>--<2020-01-08 .+1w -2d> is valid, and will act as expected when marked done.

I know repeater and delay parsing is not yet implemented, but currently the Timestamp type does not even model this, giving ActiveRange and InactiveRange a single repeater/delay.

I started writing a PR to change just the data structures to have start_repeater, start_delay, end_repeater, end_delay, but it was fairly verbose, and decided I should instead open an issue to consider how to model ranges. If start and end are Datetimes, then we can treat a timestamp like [2020-01-10 03:55-04:00] and [2020-01-10 03:55]--[2020-01-10 04:00] identically if they have no repeater (or they have the same repeater), but need to use the latter form if there are two.

Another option would be to make [in]ActiveTimeRange in additon to [in]ActiveRange, but this adds yet more types to an already complex enum.

Because it's such a hard problem (I've struggled before with modeling Org timestamps using types), and one that is likely to have different opinions, I'll just file this issue instead of a PR because I'm concerned there's a high risk of disagreement on any particular solution.

But if nothing else, I did want to open an issue to note that at present, the types cannot model Org timestamps as defined in the spec and parsed by org-element.

calmofthestorm commented 4 years ago

32 "fixes" this issue by adding start_delay, start_repeater, end_delay, end_repeater to closed clocks and timestamp ranges. I think we should consider further simplification to the types, however, as there's a lot of redundant code there.

PoiScript commented 7 months ago

I just implemented the repeater/delay feature in v0.10.0-alpha.4, and it currently supports arbitrary number of repeater/delay in both range and non-range timestamp:

[2003-09-16 09:39 +1w +1d +1y --1w --1d --1y]
[2003-09-16 09:39 +1w +1d +1y]--[2003-09-16 10:39 --1w --1d --1y]

However, Timestamp::repeater_* and Timestamp::delay_* will always return the value from first repeater/delay. Beacuse this is the same way how org-elements handles multiple repeater/delay:

(timestamp (:type inactive-range
:raw-value "[2003-09-16 09:39 +1w +1d +1y]--[2003-09-16 10:39 --1w --1d --1y]"
:year-start 2003 :month-start 9 :day-start 16 :hour-start 9 :minute-start 39
:year-end 2003 :month-end 9 :day-end 16 :hour-end 10 :minute-end 39
:begin 1 :end 66 :post-blank 0
:repeater-type cumulate :repeater-value 1 :repeater-unit week
:warning-type first :warning-value 1 :warning-unit week :parent #2))

Closing this issue since we aim to provide identical api with org-element. If you think end_delay, end_repeater is still necessary, feel free to reopen.

calmofthestorm commented 7 months ago

I think that's a fine solution. It wouldn't work for my use case (idiosyncratic custom agenda stuff), but I wrote my own parser that does exactly what I want for headlines, planning, etc, and only use Orgize to parse the lazily parse entire headline bodies as needed.

I admire the focus of this library on matching org-element. It's good to have a clear purpose to resolve edge case behavior.

PoiScript commented 7 months ago

It wouldn't work for my use case (idiosyncratic custom agenda stuff),

would you like to share which format of timestamp are you using?

Actually I do plan to add some api like nth_repeater nth_delay, which will look like:

image

But this requires you to know the position beforehand. I don't know if it serves your use case well.