[project @ sridhar.ratna@gmail.com-20071014222037-a1eeg9w72jst5ept]
[orgweb.git] / org2json.py
blobc58cf9c49afecf1093cf798c92f7dbbc332544f4
1 # org2json
2 # parse a org-mode file and convert it to JSON
4 __author__ = "Sridhar Ratnakumar <http://nearfar.org/>"
6 import re
7 from itertools import count
9 from simplejson import dumps
11 def rindexed(seq):
12 """
13 >>> l = [5,7,9]
14 >>> print list(rindexed(l))
15 [(2, 9), (1, 7), (0, 5)]
16 """
17 return zip(
18 range(len(seq))[::-1],
19 reversed(seq))
21 def reverse(iter):
22 l = list(iter)
23 l.reverse()
24 return l
27 def org2py(orgtext):
28 """Parse the given org file text and return the Python data structure
30 >>> j = org2py(open('sample.org').read())
31 >>> j=list(j)
32 >>> j[-1][0]
33 '* Projects'
34 >>> j[-2][0]
35 '* Whims'
36 >>> j[-3][0]
37 '* Online Stuff'
38 >>> j[-4][0]
39 '* Stuff'
40 >>> j[-5][0]
41 '* Travels'
42 """
43 lines = orgtext.splitlines()
44 def e(i1, i2):
45 return '\n'.join(lines[i1:i2])
47 def by_star():
48 last_index = len(lines)
49 for index, line in rindexed(lines):
50 if line.startswith("*"):
51 yield [index, e(index, last_index)]
52 last_index = index
54 def hier(items):
55 STARS_PAT = re.compile(r"^(\**) ")
56 def nstars(line):
57 """
58 >>> nstars("*** Foo Bar")
60 """
61 return len(STARS_PAT.match(line).group(1))
63 def node(text, children):
64 return (text, children)
66 items = list(items) # exhaust the iterator, if any.
68 # Create [[], [], [], ...] to hold stack values
69 # for level=k at index k.
70 # hence, we need a stack of length 1+max(k)
71 max_level = max([nstars(t) for i,t in items])
72 istack = [[] for x in range(1+max_level)]
74 pn = nstars(items[0][1]) # last item
75 for index, text in items:
76 n = nstars(text)
77 assert n>0
78 if n == pn:
79 # previous sibling
80 istack[pn].append(node(text, []))
81 elif n < pn:
82 # up to the parent
83 istack[n].append(node(text, reverse(istack[pn])))
84 istack[pn] = []
85 elif n > pn:
86 # children of one of the top nodes
87 istack[n].append(node(text, []))
88 pn = n
90 return reverse(istack[1])
92 return hier(by_star())
94 def org2json(orgtext):
95 """
96 >>> org2py(open('sample.org').read())
97 """
98 return dumps(org2py(orgtext))
101 if __name__ == '__main__':
102 from doctest import testmod
103 testmod()