Skip to content

Instantly share code, notes, and snippets.

@ngoffee
Created November 19, 2011 17:50
Show Gist options
  • Save ngoffee/1379125 to your computer and use it in GitHub Desktop.
Save ngoffee/1379125 to your computer and use it in GitHub Desktop.
Convert Remember the Milk tasks feed to Emacs org-mode file
#!/usr/bin/env python
# rtm2org.py
#
# Convert Remember the Milk tasks feed to Emacs org-mode file
#
# requires Python >= 2.7 (for ElementTree.iter())
#
# Find your RTM Atom feed here:
# https://www.rememberthemilk.com/atom/<username>
#
# Assumes you organize your RTM todos by tags, not by lists (should be
# easily modifiable to do the latter). Outputs an org-mode hierarchy
# organized by first tag, like so:
#
# * <first tag> :<first tag>:
# ** TODO [<priority] Item 1
# ** TODO Item 2 :<othertags>:
# ** TODO Item 3
# <note title>
# <note content>
from collections import defaultdict
import os.path
import sys
import xml.etree.ElementTree as ET
_atom_ns = 'http://www.w3.org/2005/Atom'
_xhtml_ns = 'http://www.w3.org/1999/xhtml'
_priority_map = {'none': None, '1': 'A', '2': 'B', '3': 'C'}
class Rtm2Org(object):
def __init__(self):
self._by_tag = defaultdict(list)
def parseAtom(self, source):
tree = ET.parse(source)
for entry in tree.iter('{%s}entry' % _atom_ns):
title = entry.find('{%s}title' % _atom_ns).text
priority, tags, note = None, None, None
for span in entry.iter('{%s}span' % _xhtml_ns):
if span.get('class') == 'rtm_priority_value':
priority = _priority_map.get(span.text, span.text)
elif span.get('class') == 'rtm_tags_value':
if tags == 'none':
tags = []
else:
tags = [x.strip() for x in span.text.split(',')]
for div in entry.iter('{%s}div' % _xhtml_ns):
# First line of a note appears in one XML element as the
# note's "title", and the remainder appears in a second
# XML element as the note's "content", so concatenate them
# BUG: I think RTM supports more than one note per item;
# should really put them all in a list and output
# as Org subitems or plain list
if div.get('class') == 'rtm_note_title_container':
span = div.find('{%s}span' % _xhtml_ns)
note = span.text
elif div.get('class') == 'rtm_note_content':
note += '\n' + div.text
self._by_tag[tags[0]].append((title, priority, tags, note))
def writeOrg(self, stream=sys.stdout):
print >> stream, '#+STARTUP: content indent hidestars'
for tag in sorted(self._by_tag.keys()):
print >> stream
print >> stream, '* %s :%s:' % (tag, tag)
for title, priority, tags, note in self._by_tag[tag]:
priority = ' [#%s]' % priority if priority else ''
tags = filter(lambda x: x != tag, tags)
tags = ' :%s:' % ':'.join(tags) if tags else ''
print >> stream, '** TODO%s %s%s' % (priority, title, tags)
if note:
print >> stream, note
def main():
args = sys.argv[1:]
if len(args) != 1:
print >> sys.stderr, \
"usage: %s <file>" % os.path.basename(sys.argv[0])
sys.exit(1)
rtm2org = Rtm2Org()
rtm2org.parseAtom(args[0])
rtm2org.writeOrg()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment