timewarrior icon indicating copy to clipboard operation
timewarrior copied to clipboard

on-modify.timewarrior: The start command does not accept ranges but only a single datetime.

Open jkirk opened this issue 2 years ago • 14 comments

It seems like the hook script doesn't like it, when a given tag can be read as time/date:

The script works fine without a tag:

tasksh> add 'Test Timewarrior'
[task add 'Test Timewarrior']
Created task 302.
tasksh> start 302
[task start 302]
Starting task a36684d6 'Test Timewarrior'.
Started 1 task.
Tracking "Test Timewarrior"
  Started 2021-09-24T08:12:10
  Current                  10
  Total               0:00:00
You have more urgent tasks.
tasksh> stop 302
[task stop 302]
Stopping task a36684d6 'Test Timewarrior'.
Stopped 1 task.
Recorded "Test Timewarrior"
  Started 2021-09-24T08:12:10
  Ended                    12
  Total               0:00:02

Script fails with the tag today:

tasksh> 302 mod +today
[task 302 mod +today]
Modifying task 302 'Test Timewarrior'.
Modified 1 task.
tasksh> start 302
[task start 302]
The start command does not accept ranges but only a single datetime. Perhaps you want the track command?
Starting task a36684d6 'Test Timewarrior'.
Started 1 task.

tasksh> stop 302
[task stop 302]
There is no active time tracking.
Stopping task a36684d6 'Test Timewarrior'.
Stopped 1 task.

Tag anything works fine again:

tasksh> 302 mod -today +anything
[task 302 mod -today +anything]
Modifying task 302 'Test Timewarrior'.
Modified 1 task.
tasksh> start 302
[task start 302]
Starting task a36684d6 'Test Timewarrior'.
Started 1 task.
Note: 'anything' is a new tag.
Tracking "Test Timewarrior" anything
  Started 2021-09-24T08:14:21
  Current                  21
  Total               0:00:00
You have more urgent tasks.
tasksh> stop 302
[task stop 302]
Stopping task a36684d6 'Test Timewarrior'.
Stopped 1 task.
Recorded "Test Timewarrior" anything
  Started 2021-09-24T08:14:21
  Ended                    23
  Total               0:00:02

Anything I can do to fix of help to solve the problem?

Thanks for your work!

jkirk avatar Sep 24 '21 06:09 jkirk

It just found and tried the debug hook script:

Installed the file as on-modify-debug.timewarrior in ~/.task/hooks and made it executable with chmod +x on-modify-debug.timewarrior but receive the following error:

tasksh> start 302
[task start 302]
Hook Error: Expected 1 JSON task(s), found 2, in hook script: on-modify-debug.timewarrior

What did I do wrong? Anything I can provide to help to solve the problem? Thanks!

jkirk avatar Sep 24 '21 06:09 jkirk

Not sure what is going on, but the hooks docs states for the input:

Input to hook scripts consists of JSON-formatted objects, one per line [...] the task must occupy only one line of output.

and for the output:

The output is a single line JSON object which represents an optionally modified task, and a single line of feedback text to be displayed. There may only be one line of JSON, and it must be for the same task that was provided as input.

But this does not seem be true in my setup:

❯ task 302 export        
[
{"id":302,"description":"Test Timewarrior","entry":"20210924T061208Z","modified":"20210924T063353Z","status":"pending","uuid":"a36684d6-253e-4bae-9cc6-4496de260519","urgency":0}
]
❯ task 302 export | wc -l
3

❯ task 302 export | ./on-modify-debug.timewarrior        
[
{"id":302,"description":"Test Timewarrior","entry":"20210924T061208Z","modified":"20210924T063353Z","status":"pending","uuid":"a36684d6-253e-4bae-9cc6-4496de260519","urgency":0}
]
❯ task 302 export | ./on-modify-debug.timewarrior | wc -l
3

Im on Debian/bullseye with the following versions of timewarrior/taskwarrior:

❯ dpkg -l taskwarrior timewarrior | tail -2
ii  taskwarrior    2.5.3+dfsg-4 amd64        feature-rich console based todo list manager
ii  timewarrior    1.4.2+ds.1-3 amd64        feature-rich time tracking utility

jkirk avatar Sep 24 '21 06:09 jkirk

❯ task config debug 1
❯ task config debug.hooks 2

❯ task start 302 
Timer Config::load (/home/jkirk/.taskrc) 0.000341 sec
No context.
Found misnamed hook script /home/jkirk/.task/hooks/disable.on-modify.timewarrior
Found hook script /home/jkirk/.task/hooks/on-modify-debug.timewarrior
Parse Tree (before command-specifіc processing)
  _original_args
    task start 302
  _args
    word basename='task' raw='task' BINARY 
    dom canonical='start' raw='start' ORIGINAL CMD USESCONTEXT ALLOWSFILTER ALLOWSMODIFICATIONS 
    number raw='302' ORIGINAL MODIFICATION 

Filtered 302 tasks --> 1 tasks [pending only]
Hook: Calling /home/jkirk/.task/hooks/on-modify-debug.timewarrior
Hook: input
  {"description":"Test Timewarrior","entry":"20210924T061208Z","modified":"20210924T063353Z","status":"pending","uuid":"a36684d6-253e-4bae-9cc6-4496de260519"}
  {"description":"Test Timewarrior","entry":"20210924T061208Z","modified":"20210924T063353Z","start":"20210924T090024Z","status":"pending","uuid":"a36684d6-253e-4bae-9cc6-4496de260519"}
Hooks: args
  api:2
  args:task start 302
  command:start
  rc:/home/jkirk/.taskrc
  data:/home/jkirk/.task
  version:2.5.3
Timer Hooks::execute (/home/jkirk/.task/hooks/on-modify-debug.timewarrior) 0.023575 sec
Hook: output
  {"description":"Test Timewarrior","entry":"20210924T061208Z","modified":"20210924T063353Z","status":"pending","uuid":"a36684d6-253e-4bae-9cc6-4496de260519"}
  {"description":"Test Timewarrior","entry":"20210924T061208Z","modified":"20210924T063353Z","start":"20210924T090024Z","status":"pending","uuid":"a36684d6-253e-4bae-9cc6-4496de260519"}
Hook: Completed with status 0
 
Hook Error: Expected 1 JSON task(s), found 2, in hook script: on-modify-debug.timewarrior

So the debug hook script doesn't seem to return what is expected:

❯ (echo "{"description":"Test Timewarrior","entry":"20210924T061208Z","modified":"20210924T063353Z","status":"pending","uuid":"a36684d6-253e-4bae-9cc6-4496de260519"}"; echo "{"description":"Test Timewarrior","entry":"20210924T061208Z","modified":"20210924T063353Z","start":"20210924T090829Z","status":"pending","uuid":"a36684d6-253e-4bae-9cc6-4496de260519"}") | ./on-modify-debug.timewarrior

{description:Test Timewarrior,entry:20210924T061208Z,modified:20210924T063353Z,status:pending,uuid:a36684d6-253e-4bae-9cc6-4496de260519}
{description:Test Timewarrior,entry:20210924T061208Z,modified:20210924T063353Z,start:20210924T090829Z,status:pending,uuid:a36684d6-253e-4bae-9cc6-4496de260519}

But ok, this seems to be another problem. Finally I ended up here...

❯ (echo "{"description":"Test Timewarrior","entry":"20210924T061208Z","modified":"20210924T063353Z","status":"pending","uuid":"a36684d6-253e-4bae-9cc6-4496de260519"}"; echo "{"description":"Test Timewarrior","entry":"20210924T061208Z","modified":"20210924T063353Z","start":"20210924T090829Z","status":"pending","uuid":"a36684d6-253e-4bae-9cc6-4496de260519"}") | ./disable.on-modify.timewarrior
Traceback (most recent call last):
  File "/home/jkirk/Documents/taskwarrior/.task/hooks/./disable.on-modify.timewarrior", line 48, in <module>
    old = json.loads(input_stream.readline().decode("utf-8", errors="replace"))
  File "/usr/lib/python3.9/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python3.9/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python3.9/json/decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes: line 1 column 2 (char 1)

jkirk avatar Sep 24 '21 09:09 jkirk

Silly me, the quotes were wrong:

❯ (echo '{"description":"Test Timewarrior","entry":"20210924T061036Z","modified":"20210924T061054Z","status":"pending","tags":["today"],"uuid":"e605becc-0e83-4e32-92f7-c61ff688e7ed"}'; echo '{"description":"Test Timewarrior","entry":"20210924T061036Z","modified":"20210924T061054Z","start":"20210924T100015Z","status":"pending","tags":["today"],"uuid":"e605becc-0e83-4e32-92f7-c61ff688e7ed"}') | ./disable.on-modify.timewarrior 
{"description": "Test Timewarrior", "entry": "20210924T061036Z", "modified": "20210924T061054Z", "start": "20210924T100015Z", "status": "pending", "tags": ["today"], "uuid": "e605becc-0e83-4e32-92f7-c61ff688e7ed"}
The start command does not accept ranges but only a single datetime. Perhaps you want the track command?

Which finally leads to this:

❯ timew start Test Timewarrior today :yes
The start command does not accept ranges but only a single datetime. Perhaps you want the track command?

Sorry for my debug noise above, but it was quite hard for me (as this was my first time debugging taskwarrior/timewarrior).

jkirk avatar Sep 24 '21 10:09 jkirk

Hi @jkirk! Thanks for your detailled analysis. I am currently still looking at it and analyzing the issue myself.

lauft avatar Sep 27 '21 12:09 lauft

Ran into a similar (same?) issue, took me a while after reading this thread to realise that the tag "sep" I was using is considered time-related if interpreted as shorthand for "September" (which I didn't even mean, it was an acronym). I'm on Arch with TaskWarrior version 2.5.3 and TimeWarrior 1.4.3.

ghost avatar Sep 28 '21 08:09 ghost

I'm having the same problem with a tag friday I was using. Changing to other tag name fixed the problem. Thanks.

dimas-cyriaco avatar Oct 01 '21 19:10 dimas-cyriaco

@jkirk it is not a problem of the on-modify.timewarrior hook.

It is a general problem of Timewarrior that it does not accept tags which resemble date values. The reasons is the command line parser which is a bit to eager to interpret them as date values/ranges even if there is none required. It will require a bit more restructuring to solve this... 🤔

(see #60 #154 #383)

lauft avatar Oct 08 '21 19:10 lauft

I've found a workaround that works for me. I use GTD methodology with taskwarrior (I believe I came to something that works wonderfully by the way) and so I have some context tags as the time I think the task will take, so depending on the time context I can filter tasks that will take 5, 15, 30 45 or 60 minutes, then 1, 2 or 4 hours.

What "fixed" it for me was replacing, for example, the tag +15min with the tag +_15min. Having an underscore in front of it made all the difference.

I hope this is useful for most of you guys (and you can check the attachment too where I show a task was correctly logged in TimeWarrior; I've obfuscated some confidential company stuff that can identify where it is, but you can see it fine). taskwarriorDebug

tiagommmelo avatar Oct 20 '21 15:10 tiagommmelo

timewarrior should just interpret everything after it sees 'start' as a tag, without further interpretation. I am having a similar issue in #455, perhaps this is same root issue that parser keeps looking for more after it shouldn't

smemsh avatar Oct 21 '21 06:10 smemsh

A better solution is to make tags special, may be tags must be prefixed with + like in taskwarrior so the command be: timew start [<date>] [<+tag> ...]

omarmohamedkh avatar Jun 07 '22 03:06 omarmohamedkh

note that I use tags that start with a + to mean "tags that came from taskwarrior" and not all of them do. we could say exactly one + will be stripped, and the rest is a tag. So ++foo would give me a tag of +foo.

smemsh avatar Jun 08 '22 05:06 smemsh

Each ++ should be replaced with + thus allowing ++++tag to be parsed as ++tag and +today to be enforced as a tag today

prevPlus = false
newArg = ""
for (char : arg) {
  if (char == '+') {
    if (prevPlus) {
      newTag += '+'
      prevPlus = false
    } else {
      prevPlus = true
    }
  } else {
    newTag += char
  }
}
return arg[0] == '+' ? parseAsTag(newArg) : parseNotTag(newArg)

omarmohamedkh avatar Jun 15 '22 20:06 omarmohamedkh

Ran into this today using taskwarrior tag weekly, changing it to _weekly worked around the issue. Thanks for the debugging @jkirk and suggestion @tiagommmelo

webbj74-acquia avatar Jul 18 '22 15:07 webbj74-acquia