I love todo.txt. It’s a simple task system where pretty much everything lives in a single folder called “todo.txt.” After trying about 15 different task managers, I have found this system to be my favorite, and I’ve been using it for more than a year. Using Gina Trapani’s “todo.sh” script along with a bunch of my own bash scripts, most of my task-related needs are met… except for a calendar. After not finding a suitable existing todo.txt to calendar system, I decided to try writing my own. It took a few hours of tinkering, but it works!
To run this script, you’ll need a web server running php, and of course a todo.txt file somewhere on the same server. Load the script in a browser and it will give you an ics file with any todo items that have a due date. Load the script from an external calendar – like Google Calendar – and your due-dated todo items will appear on the calendar. Hooray!
<?php // CB's Todo.txt to ics script // goes through todo.txt and generates a calendar // 2018-06-06 // // HOW TO USE THIS // this script parses a file in the todo.txt format and generates an ics file // the ics file will have "all-day" calendar entries for todo.txt items // that have due dates // you can load this calendar into google calendar ("load public calendar") or // other systems (like Fastmail's calendar) // // WHY? // I love todo.txt but sometimes it's tough to get a picture of what I really // need to do. Sticking my dated tasks on a calendar really helps me! // inspiration from here: // https://gist.github.com/jakebellacera/635416 // hide all errors, we don't want them mucking up our ics output error_reporting(0); ini_set('display_errors', 0); // where does the todo.txt file live? $todopath = "/path/to/your/todo/txt/file.txt"; // load the todo file, give us an error if we can't open it $todofile = fopen($todopath, "r") or die("Unable to open todo file!"); // calendar file top stuff $ical = "BEGIN:VCALENDAR VERSION:2.0 PRODID:-//hacksw/handcal//NONSGML v1.0//EN"; // iterate through each line of the file while(!feof($todofile)) $line = fgets($todofile); //echo "line: $line <br>"; // ONLY operate on the line if it contains a due date (due:YYYY-MM-DD)jk if (strpos($line, "due:") !== false) //print "line contains DUE! doing stuff <br>"; // explode the string into an array $array = explode(" ", $line); // iterate through each word and figure out what it is // i.e. a due date, a context, a project, threshold, hidden, etc. foreach ($array as &$word) //print "value: $value <br>"; // IF WORD CONTAINS "due:" if (strpos($word, "due:") !== false) //echo "--- this word contains DUE! <br>"; // remove "due:" $due = str_replace("due:","",$word); // remove newlines $due = str_replace("\n","",$due); // remove dashes //$due = str_replace("-","",$due); // IF WORD CONTAINS "@" if (strpos($word, "@") !== false) //echo "--- this word has a context! <br>"; $context = str_replace("\n","",$word); // IF WORD CONTAINS "+" if (strpos($word, "+") !== false) //echo "--- this word has a project! <br>"; $project = $word; // IF WORD CONTAINS "t:" if (strpos($word, "t:") !== false) //echo "--- this word contains t: <br>"; $threshold = $word; // IF WORD CONTAINS "h:" if (strpos($word, "h:") !== false) //echo "--- this word contains h: <br>"; $hide = $word; // IS THIS A DATE? if (DateTime::createFromFormat('Y-m-d', $word) !== FALSE) //echo "---this word is a date! <br>"; $dateAdded = $word; // IS THIS A URL? if (strpos($word, "http") !== false) //echo "--- this word is a URL!<br>"; $url = $word; // put together a summary // summary: the name of the calendar event // description: more info when you click on the calendar event // BUILD THE SUMMARY // +projectname something something // get rid of due date $summary = (str_replace("due:".$due,"",$line)); // remove dashes from the due date $due = str_replace("-","",$due); // get rid of the added date $summary = (str_replace($dateAdded,"",$summary)); // get rid of the context $summary = (str_replace($context,"",$summary)); // get rid of the threshold $summary = (str_replace($threshold,"",$summary)); // get rid of the URL $summary = (str_replace($url,"",$summary)); // remove project.... $summary = (str_replace($project,"",$summary)); //... so we can make it first $summary = $project . " " . $summary; // remove newlines $summary = (str_replace("\n","",$summary)); // remove double spaces $summary = (str_replace(" "," ",$summary)); //print "summary: $summary <br>"; // create the ICS entry $ical = $ical . " BEGIN:VEVENT DTSTART:$due DTEND:$due SUMMARY:$summary DESCRIPTION:$line URL:$url END:VEVENT"; fclose($todofile); // close the todofile $ical = $ical . " END:VCALENDAR"; // comment these headers out to load the text in a web browser // uncomment to generate an ics file when loading this script header('Content-Type: text/calendar; charset=utf-8'); header('Content-Disposition: attachment; filename=invite.ics'); echo $ical; exit; ?>