VladimirMarkelov / ttdl

TTDL - Terminal Todo List Manager
MIT License
210 stars 17 forks source link

Make all dates potentially relative to other date fields #89

Open cyruseuros opened 10 months ago

cyruseuros commented 10 months ago

It would be cool if a threashold date could be thr:due-7d

VladimirMarkelov commented 10 months ago

Thank you for the suggestion. Though, I have some doubt about it.

On the one hand, it looks useful. On the other hand, it needs implementing a simple math parser almost only just for threshold date. And taking into account that threshold date is hardly used by anyone (there was an obvious bug in threshold and nobody noticed for 1-2 years or even for longer that threshold worked not as expected), it makes me think it would be a lot of work that would be almost never used.

Please, share your thoughts. I can miss something. Here is my reasoning:

  1. In TTDL there are only 4 fields that TTDL treats as dates: created, finished, due, and threshold. None of user-defined tags is a date from TTDL point of view. Yes, one can set rules to display a tag as a date in its own column via the app configuration, but it does not affect adding/editing of any task
  2. "Created" field is filled automatically at creation time. So, it does not need any calculation (at least, I cannot make up a situation when a user wants to set a custom create date. Especially based on due or threshold). Moreover, "created" field can be disabled and missing in a task
  3. "Finished" field is also filled automatically. The same argument as for "created"
  4. "Due". To me, "due" field should be calculated only from the current date. In this case, we already have simple parser (without supporting math operations - see section "Human-readable dates" in README) that allows a user to add tasks like this "due:3d" - in 3 days from the current date or "due:Fri" - nearest Friday in the future. I can imagine when a user needs something like "due:Fri+3d" but adding a full-featured parser even with only + and - seems too much for such cases
  5. "Threshold'. It is the only field that can be based on a date that is not the current one. Strictly speaking, it can be based only either on the current date(in this case, see "Due" bullet point about simple parser) or on the "due" date.

Let's assume, we allow threshold to be based on due. In this case, the only possible position where due can be is the first argument: due+1w is valid but 1w+due is not. It makes parser very simple: just check if an expression starts with due and use due date instead of the current date. But it is not as easy as it sounds. The current parser is stateless, e.g, it does not care in what order dates are in the text or what tag it processes. But dependency on due requires the parser to be stateful with some consequences (e.g. rewrite the parser to be 2-pass one, because a user can add a task with inverse order of tags: `do something threshold:due-15d due:2023-12-01".

Hence, my conclusion that it is too much hassle for the single tag that is hardly used.

I am not saying that it is my final words. If there are some good arguments about adding a more powerful parser, I can change my mind.

cyruseuros commented 10 months ago

All fair points. After reading your thoughts, here are mine: If ttdl starts allowing tags to have explicit data types (inclusive of date, and internally, not just visually), it makes sense to make parsing stateful, introduce something like a todo.txt DOM, and introduce a parser for relative offsets.

Just supporting the threshold date makes no sense. Being able to say something like my-prop:2d thr:my-prop-1w due:thr+2w does.

Thoughts?

VladimirMarkelov commented 10 months ago

I see. I missed the option to set due date from threshold one. Another possible usage is to allow using expression in command-line options. E.g, --set-due=due+1w postpones the task by a week. Yes, it duplicates the existing postpone command, but the new way is more generic.

I even did not think about using custom fields as custom variables. On the one hand, it is unclear what custom field is a date one. On the other hand, if TTDL allows only first argument to be a field reference(in other words, there are only two possible formats: #d - that is kind of a shorthand for created+#d and <field>+/-#d, it is not a big deal.

Another trouble that needs some attention is detecting endless recursion. E.g, task due:t+1w t:my-dt+10d my-dt:due+1. It can be "solved" by limiting the recursion depth.

It also can trigger non-obvious side-effects for custom fields because we cannot tell the type a custom field. The side-effect will be like this: if you add a task do my-dt:1d, it is always displayed as do my-dt:1d because TTDL won't try to convert all custom tags to dates. But if you run then ttdl --set-due=my-dt+3d it changes the value of my-dt tag and adds a due tag. Moreover, the value of both fields may be a surprise for a user. From what date to calculate my-dt for an old task? From created? But adding created date to tasks can be disabled. From today? It is not clear what a user expects. Adding a new command-line option to choose automatically seems an overkill. Though, I guess this situation is way rare and I can choose any solution and then describe it in the doc.

cyruseuros commented 10 months ago

I think sane defaults are definitely the way to go here as opposed to a number of switches. Taskwarrior's DOM & calc are good inspiration here I think (not saying a DOM should be implemented necessarily, just that the functionality there is satisfactory)