Created
December 28, 2016 16:46
-
-
Save mshroyer/189d6d0bcb79eef308b38bc1c41b3b84 to your computer and use it in GitHub Desktop.
Extract plaintext TODOs from Remember the Milk (RTM) iCalendar export
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import argparse | |
import functools | |
import icalendar | |
import operator | |
import re | |
TAGS_PATTERN = re.compile(r'Tags: ([\w\d]+(?:, [\w\d]+)*)') | |
# The RTM iCalendar export doesn't include information about which list | |
# VTODO items came from, so we have to use a heuristic to separate fiction | |
# books from fiction movies. | |
BOOK_PATTERN = re.compile(r'.+\, ".*"') | |
def main(): | |
parser = argparse.ArgumentParser( | |
description='Extract TODOs from an RTM iCalendar export') | |
parser.add_argument('input') | |
parser.add_argument('--tag', default=None, | |
help='Only include items with the given tag') | |
parser.add_argument('--book', default=False, action='store_true', | |
help='Only include items that look like books') | |
parser.add_argument('--no-book', default=False, action='store_true', | |
help='Only include items that don\'t look like books') | |
args = parser.parse_args() | |
predicates = [] | |
if args.book: | |
predicates.append(lambda item: todo_is_book(item)) | |
if args.no_book: | |
predicates.append(lambda item: not todo_is_book(item)) | |
if args.tag is not None: | |
predicates.append(lambda item: todo_has_tag(item, args.tag)) | |
def predicate(item): | |
return functools.reduce(operator.and_, | |
map(lambda p: p(item), predicates), True) | |
for item in get_todos(get_ical_object(args.input), predicate): | |
print(get_scalar_property(item, 'SUMMARY')) | |
def get_ical_object(path): | |
with open(path, 'rb') as f: | |
cal = icalendar.Calendar.from_ical(f.read()) | |
return cal | |
def get_todos(cal, predicate=None): | |
if predicate is None: | |
predicate = lambda _: True | |
for item in cal.walk(name='VTODO'): | |
if predicate(item): | |
yield item | |
def get_scalar_property(item, name): | |
return item.decoded(name).decode() | |
def todo_has_tag(item, tag): | |
m = re.search(TAGS_PATTERN, get_scalar_property(item, 'DESCRIPTION')) | |
if m is None: | |
return False | |
item_tags = m.group(1).split(', ') | |
return tag in item_tags | |
def todo_is_book(item): | |
return re.match(BOOK_PATTERN, get_scalar_property(item, 'SUMMARY')) is not None | |
if __name__ == '__main__': | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment