Making Agenda List from Timer Tool plugin

I have many tiddlers (events/tasks/etc.) with the field due set to some date in the future. To show the agenda, I use the code:

<$vars today=<<now format:"YYYY0MM0DD">>>
<ul>
<$list filter="[has[due]] :filter[get[due]compare:date:gteq<today>] +[sort[due]first[10]]">
		<li><$view field="due" format="date" template="ddd DD mmm"/> - <$link to=<<currentTiddler>>><$view field="caption">{{!!title}}</$view></$link> -   (<$view field="due" format="relativedate"/>)</li>
</$list>
</ul>
<$vars>

This will produce something like

  • Wed 8 Sep - Do some work - (4 days from now)
  • Thu 9 Sep - Go some place - (5 days from now)

so I can quickly see what is coming up and how long until then.

I also have the sidebar calendar which installed from Timer Tool. The calendar reads events from a file that looks like

20200308;Daylight Saving Time starts
20201101;Daylight Saving Time ends
20201103;Election Day (US)
20201211;Hanukkah (first day)

I want to be able to list what’s coming up next (similar to what I did above). I can use the first part 20200308 for the due information. But the problem is how do I process each line?

I prefer not to turn each line into a new tiddler as some events/tasks are not important enough to worth making a new tiddler for.

1 Like

In TiddlyTools Timers (a.k.a, “It’s About Time”), an “Event List” is stored as text in a tiddler tagged with “events”

You want to know how to parse the lines in an Event List tiddler in order to generate the same kind of formatted $list output as you are producing from separate tiddlers that have a “due” field.

As you’ve already noted, the first part of each line is an 8-digit date using “YYYY0MM0DD” format. The remainder of each line – separated by a semi-colon (;) delimiter – is a text description the event.

Here’s the code to parse this text and produce a list of the first 10 upcoming events using your desired output format:

<$vars today=<<now format:"YYYY0MM0DD">>>
<ul>
<$list filter="[tag[events]get[text]splitregexp[\n]!match[]]
               :filter[split[;]first[]compare:date:gteq<today>]
               +[sort[]first[10]]">
   <$vars when={{{ [<currentTiddler>split[;]first[]] }}}>
   <$vars what={{{ [<currentTiddler>split[;]rest[]]  }}}>
   <li>
      <$text text={{{ [<when>format:date[ddd DD mmm]] }}}/> -
      <$link to=<<what>>/> -
      (<$text text={{{ [<when>format:relativedate[ddd DD mmm]] }}}/>)
   </li>
   </$vars>
   </$vars>
</$list>
</ul>
<$vars>
  • Instead of has[due], we use [tag[events]get[text]splitregexp[\n]!match[]]to find all tiddlers tagged with “events” and split the text of those tiddlers into separate lines, ignoring any blank lines

  • Next, we use :filter[split[;]first[]compare:date:gteq<today>] to get the date portion of each line and compare it with the current date to get only the upcoming events.

  • Then, we use [sort[]first[10]] to get the first 10 matching results, sorted by the event date.

  • For each matching event, we extract the date (“when”) and description (“what”), using:

    • <$vars when={{{ [<currentTiddler>split[;]first[]] }}}>
    • <$vars what={{{ [<currentTiddler>split[;]rest[]] }}}>
  • This is then output as a bullet item, to show:

    • the formatted date: {{{ [<when>format:date[ddd DD mmm]] }}}
    • a link to the description text: <$link to=<<what>>/>, so you can make notes about the event
    • and the relative date: {{{ [<when>format:relativedate[ddd DD mmm]] }}}.
  • Note: an Event List can also contain “annual recurring events” where the YYYY portion of the date is replaced with ....(four dots). The above code ignores those events, since they will always fail the compare:date:gteq<today> filter.

enjoy,
-e

Hi @EricShulman, Thank you! Your code works great! This produces the agenda list from lines in text files tagged with events. However, now I have two separate lists. How do I combine the two types of events (from tiddler title and from lines) and present them in the same list, sorted by due?

This is my attempt:

<$vars today=<<now format:"YYYY0MM0DD">>>
<ul>
<$list filter="......">
   <$list filter="[all[current]has[due]]">
			 <li>
			     <$view field="due" format="date" template="ddd DD mmm"/> - 
					 <$link to=<<currentTiddler>>><$view field="caption">{{!!title}}</$view></$link> -
					 (<$view field="due" format="relativedate"/>)
			 </li>
	 </$list>
	 <$list filter="[all[current]!has[due]]">
	     <$vars when={{{ [<currentTiddler>split[;]first[]] }}}>
         <$vars what={{{ [<currentTiddler>split[;]rest[]]  }}}>
	     <li>
               <$text text={{{ [<when>format:date[ddd DD mmm]] }}}/> -
               <$link to=<<what>>/> -
               (<$text text={{{ [<when>format:relativedate[ddd DD mmm]] }}}/>)
         </li>
	   </$vars>
       </$vars>
	 </$list>   
</$list>
</ul>
</$vars>

where the filter … should produce the union of {tiddler titles that have due field} and {lines in events text file}. I used the condition has[due] to differentiate the two types of titles which are processed differently.

I tried

filter="[has[due]] :filter[get[due]compare:date:gteq<today>] 
+[sort[due]first[10]]"

and

filter="[tag[events]get[text]splitregexp[\n]!match[]]
               :filter[split[;]first[]compare:date:gteq<today>]
               +[sort[]first[10]]"

It works as expected in both cases. But how do we combine the two filter results and sort by due information?

First… I found a BUG in my original code… the output date was being adjusted for timezone, so all the displayed dates were off by 1 day (for me, at least, since I’m in California, which is UTC-8).

To avoid this, we need to put “[UTC]” in front of the format, like this: [UTC]ddd DD mmm. However, this causes a parsing issue with the [<when>format:date[...]] filter, since it can’t contain nested square brackets. The workaround is to put the date format into a variable (i.e, <$vars dateformat="[UTC]ddd DD mmm">) and then reference that variable in the filter that produces the date output: [<when>format:date<dateformat>].

Now… on to the “join the lists” solution:

<$vars  today=<<now format:"YYYY0MM0DD">> dateformat="[UTC]ddd DD mmm">
<$set    name="events" filter="[tag[events]get[text]splitregexp[\n]!match[]]">
<$wikify name="due"      text="<$list filter='[has[due]]'>//[//[{{{ [<currentTiddler>get[due]] }}};<$link/>]//]//</$list>">
<ul>
<$list filter="[enlist<events>] [enlist<due>] :filter[split[;]first[]compare:date:gteq<today>] +[sort[]first[20]]">
   <$vars when={{{ [<currentTiddler>split[;]first[]] }}}>
   <$vars what={{{ [<currentTiddler>split[;]rest[]]  }}}>
   <li>
      <$text text={{{ [<when>format:date<dateformat>] }}}/>
      <$link to=<<what>>/> -
      (<$text text={{{ [<when>format:relativedate[ddd DD mmm]] }}}/>)
   </li>
   </$vars>
   </$vars>
</$list>
</ul>
</$wikify>
</$set>
</$vars>
  • The <$set> widget gets the Event List dates, just as before
  • The <$wikify> widget gets the “due date tiddlers” and converts them to same format as an Event List using [[YYYYMMDD;TiddlerTitle]] as the output for each.
  • Note that the items in the converted list are enclosed in doubled squarebrackets to support handling tiddler titles that contains spaces. I used “//[//[” and “]//]//” to separate the brackets so the enclosed output won’t be treated as a wikilink!. By default, the $wikify widget produces plain text output, so the “italics” format is not included in the result.
  • Next, we combine both lists using [enlist<events>] [enlist<due>], and filter for upcoming dates and sort/limit the results.
  • The rest is the same as my previous Event List output code (plus the fix for the UTC date format issue).

enjoy,
-e

Hi @EricShulman Thank you very much for your help. I really do appreciate your time.

You code seems to produce a weird result for events from tiddlers with due field. Here I provide a small sample data to try in any tiddlywiki.

sample-data.json (431 Bytes)

Your code produced the following output

Sun 5 Sep Event A]][[20210906 - (8 hours from now)
Sun 12 Sep Holiday - (7 days from now)
Mon 13 Sep Holiday - (8 days from now)
Tue 14 Sep Holiday - (9 days from now)

Ah!.. the problem is that the items output by the $list in the $wikify needs to be space-separated. The fix is to add a literal space immediately before the closing </$list>, like this:

<$wikify name="due" text="<$list filter='[has[due]]'>//[//[{{{ [<currentTiddler>get[due]] }}};<$link/>]//]// </$list>">

Another small issue I just noted: the relative date output is calculated by the TWCore using UTC-0 timezone. So, for example, 20210905 (which is tomorrow), shows as “(8 hours from now)”, even though it is only 8am here in California (UTC-8), where tomorrow is actually “16 hours from now”.

-e

It finally works! Thank you! :slight_smile:

I wants to share something I discovered about your “Even List” (plain text file format). It seems to read the results from wikitext as well. So if I put

<$list filter="[has[due]]">
<$view field="due" format="date" template="YYYY0MM0DD"/>; {{!!title}}<br>
</$list>

in the event list file tagged with events, then it’s equivalent to entering the event data manually line by line. Thus you can have the calendar colored on the dates that correspond to the due field of some tiddlers!

Thank you for making the calendar plugin. You calendar is indispensable for my productivity wiki :slight_smile:

Indeed, I did that deliberately. In the TiddlyTools/Time/Calendar code, the getevents_listed() macro definition includes this line:

<$wikify name="eventdata" text={{{ [<event_source>get[text]] }}} mode="inline">

This is what allows you generate Event List formatted output using whatever wikitext logic you like.