timewarrior icon indicating copy to clipboard operation
timewarrior copied to clipboard

How to query multiple tags?

Open rudolfschmidt opened this issue 4 years ago • 8 comments

timew summary tag1 tag2 searches for intervals with both tag1 and tag2 in the same time, but what if I do several things during the day and just want to exclude a certain tag from the summary or include more than one tag into the summary?

rudolfschmidt avatar Aug 07 '20 02:08 rudolfschmidt

Currently this is impossible without writing your own report.

There are open issues (#209, #64) that ask for this capability, which based on my understanding, will most likely be implemented as described in the complex filtering section of https://taskwarrior.org/docs/filter.html.

sruffell avatar Aug 07 '20 03:08 sruffell

I would highly recommend adding this feature. It's crucial to have it in my opinion. Often you track times just to not have gaps but you do not want to have them in your summary because they do not relate to your work or important tasks.

I need a time tracker for the command line and I need this feature. If there is no easier solution I consider to develop a time tracker in Rust. Are you open for any colaboration?

rudolfschmidt avatar Aug 07 '20 07:08 rudolfschmidt

Personally, I look at timewarrior as a way to record intervals. I rely on a custom report for reporting intervals that a) ensures each interval I report on is associated with a valid charge code, and b) converts the time into 10ths of hours for entry into the company time tracking system.

For recording time, timewarrior has been excellent for me, and I think my time is best spent working with @lauft to help improve it. For reporting my time, I use https://github.com/sruffell/timewarrior-timesheet-report, which is very rough around the edges but does what i need.

Of the two most reacted to outstanding features--more flexible time parsing, and more flexible tag filtering--the time parsing is a higher priority for me since I already use an external report for filtering and validating tags that produces output like:

Wk  Date       Day ID  Tags       Annotation         Start      End     Time    Total
--- ---------- --- --- ---------- --------------- -------- -------- -------- --------
W31 2020-07-27 Mon @14 proja                       7:45:00 11:45:18  4:00:18
                   @13 proja                      12:46:41 17:38:15  4:51:34  8:51:52
W31 2020-07-28 Tue @12 proja      Looking at c...  7:56:16 10:28:11  2:31:55
                   @11 proja      Looking at c... 11:12:12 16:18:54  5:06:42  7:38:37
W31 2020-07-29 Wed @10 projc                       8:54:01 13:33:39  4:39:38  4:39:38
W31 2020-07-30 Thu @9  projc                       8:45:00  9:30:00  0:45:00  0:45:00
W31 2020-07-31 Fri @8  projb                       8:00:00  0:00:00 16:00:00 16:00:00
W31 2020-08-01 Sat @8  projb                       0:00:00  2:00:00  2:00:00  2:00:00

                                                                             39:55:07

           |    Mon |    Tue |    Wed |    Thu |    Fri |    Sat |    Sun |    Tot |
===========|========|========|========|========|========|========|========|========|
proja      |    8.9 |    7.6 |        |        |        |        |        |   16.5 |
projb      |        |        |        |        |     18 |        |        |     18 |
projc      |        |        |    4.7 |    0.8 |        |        |        |    5.5 |
===========|========|========|========|========|========|========|========|========|
totals     |    8.9 |    7.6 |    4.7 |    0.8 |     18 |        |        |   40.0 |

It sounds like you may be in a similar position to me. I would be happy to collaborate to make the report more generally useful.

sruffell avatar Aug 07 '20 13:08 sruffell

It sounds like you may be in a similar position to me. I would be happy to collaborate to make the report more generally useful.

Unfortunately I do not develop much c++. I would consider implementing time warrior in Rust to be able to extend it. I have another Rust project that I have to finish but I really need an efficient time tracker. Reports are everything. Tracking alone is useless without the information you can extract from it. Then I would be happy to help you or to start my own time tracking project. I find the summary feature at the moment enough for me, even your report looks awesome too, and I consider to implement such a view in Rust, but what I cannot life with is the lack of query multiple tags at once.

rudolfschmidt avatar Aug 08 '20 02:08 rudolfschmidt

My report is written in Rust (originally in Python but I use the Rust version primarily now), and you can filter by multiple tags in your report if you so desire.

So in other words, when it comes to reporting, timewarrior is easy to extend with Rust. You just need to be able to do some light text (mostly JSON) parsing.

sruffell avatar Aug 08 '20 04:08 sruffell

@rudolfschmidt unless you have too much time on your hands or disagree with fundamental design decisions, why would you create a completely new tool if you only dislike its interface? With CLI-tools it's a breeze to create custom output, whether in your preferred programming language or even with a simple script.

xeruf avatar Aug 21 '20 11:08 xeruf

I'm not familiar with the codebase, but this seemed like a simple change to matchesFilter(). Here's a demonstration:

% timew summary work OR school

Wk  Date       Day Tags      Start      End    Time   Total
W42 2021-10-23 Sat school  5:00:00  5:21:05 0:21:05
                   school 15:19:12 15:49:17 0:30:05
                   school 16:30:50 17:07:16 0:36:26
                   work   17:07:16 17:52:42 0:45:26
                   school 21:33:54 21:34:33 0:00:39
                   work   21:34:33        - 0:32:45 2:46:26

                                                    2:46:26

As long as there is an "OR" as one of the tags, matchesFilter() would switch to OR logic instead of the default AND. I think it might be possible to make this more robust as well by letting matchesFilter() evaluate tags as a boolean expression (with AND by default) instead of just using OR or AND for all tags.

bool matchesFilter (const Interval& interval, const Interval& filter)
{
  if (matchesRange (interval, filter))
  {

    // OR PATCH
    
    bool isOr = false;
    for (auto& tag : filter.tags ())
    {
      if (tag == "OR") {
        isOr = true;
        break;
      }
    }

    for (auto& tag : filter.tags ())
    {
      bool isNegative = tag[0] == '-';
      std::string tagName = isNegative ? tag.substr(1) : tag;
      bool hasTag = interval.hasTag(tagName);
      if (isNegative) hasTag = !hasTag;

      if (isOr && hasTag) {
        return true;
      }

      if (!isOr && !hasTag) {
        return false;
      }

    }
    return isOr ? false : true;

    // OR PATCH

  }

  return false;
}

Also, I'm quite new to contributing to open source, so please do tell me if I'm doing something wrong. :) Thanks!

Edit: This works well even with timew day or timew summary :ids! This codebase is a joy to edit. I haven't run any tests yet though, and I would like to ask for others' opinions before making a PR.

Edit 2: I will try implementing a boolean parser tomorrow. Interested in doing things like timew summary !school !work to find any intervals that aren't tagged school or work.

Edit 3: Realised a problem with making a boolean parser. The tags are in a set, not ordered. I'll stick to the simple OR version for myself for now, unless there's interest in needing this.

Edit 4: An idea; maybe this will work better as a hint? Like :or.

Edit 5: Not really related to this issue, but since the OP mentioned it, here's excluding functionality as well. I've edited the snippet above.

% timew summary -lazy -school

Wk  Date       Day Tags     Start      End    Time    Total
W42 2021-10-23 Sat sleep  5:21:05 14:10:32 8:49:27
                   body  15:49:17 16:30:50 0:41:33
                   work  17:07:16 17:52:42 0:45:26
                   fun   17:52:42 21:33:54 3:41:12
                   work  21:34:33 22:56:28 1:21:55
                   work  22:56:36 23:09:00 0:12:24 15:31:57

                                                   15:31:57

limdingwen avatar Oct 23 '21 14:10 limdingwen

Any progress here?

Or should I try learning sruffell/timewarrior-timesheet-report ?

sskras avatar Jun 09 '23 11:06 sskras