##// END OF EJS Templates
ipy_leo: doc improvements
Ville M. Vainio -
Show More
@@ -1,409 +1,409 b''
1 """ ILeo - Leo plugin for IPython
1 """ ILeo - Leo plugin for IPython
2
2
3
3
4 """
4 """
5 import IPython.ipapi
5 import IPython.ipapi
6 import IPython.genutils
6 import IPython.genutils
7 import IPython.generics
7 import IPython.generics
8 from IPython.hooks import CommandChainDispatcher
8 from IPython.hooks import CommandChainDispatcher
9 import re
9 import re
10 import UserDict
10 import UserDict
11 from IPython.ipapi import TryNext
11 from IPython.ipapi import TryNext
12
12
13 ip = IPython.ipapi.get()
13 ip = IPython.ipapi.get()
14 leo = ip.user_ns['leox']
14 leo = ip.user_ns['leox']
15 c,g = leo.c, leo.g
15 c,g = leo.c, leo.g
16
16
17 # will probably be overwritten by user, but handy for experimentation early on
17 # will probably be overwritten by user, but handy for experimentation early on
18 ip.user_ns['c'] = c
18 ip.user_ns['c'] = c
19 ip.user_ns['g'] = g
19 ip.user_ns['g'] = g
20
20
21
21
22 from IPython.external.simplegeneric import generic
22 from IPython.external.simplegeneric import generic
23 import pprint
23 import pprint
24
24
25 def es(s):
25 def es(s):
26 g.es(s, tabName = 'IPython')
26 g.es(s, tabName = 'IPython')
27 pass
27 pass
28
28
29 @generic
29 @generic
30 def format_for_leo(obj):
30 def format_for_leo(obj):
31 """ Convert obj to string representiation (for editing in Leo)"""
31 """ Convert obj to string representiation (for editing in Leo)"""
32 return pprint.pformat(obj)
32 return pprint.pformat(obj)
33
33
34 @format_for_leo.when_type(list)
34 @format_for_leo.when_type(list)
35 def format_list(obj):
35 def format_list(obj):
36 return "\n".join(str(s) for s in obj)
36 return "\n".join(str(s) for s in obj)
37
37
38 attribute_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
38 attribute_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
39 def valid_attribute(s):
39 def valid_attribute(s):
40 return attribute_re.match(s)
40 return attribute_re.match(s)
41
41
42 def all_cells():
42 def all_cells():
43 d = {}
43 d = {}
44 for p in c.allNodes_iter():
44 for p in c.allNodes_iter():
45 h = p.headString()
45 h = p.headString()
46 if h.startswith('@a '):
46 if h.startswith('@a '):
47 d[h.lstrip('@a ').strip()] = p.parent().copy()
47 d[h.lstrip('@a ').strip()] = p.parent().copy()
48 elif not valid_attribute(h):
48 elif not valid_attribute(h):
49 continue
49 continue
50 d[h] = p.copy()
50 d[h] = p.copy()
51 return d
51 return d
52
52
53
53
54
54
55 def eval_node(n):
55 def eval_node(n):
56 body = n.b
56 body = n.b
57 if not body.startswith('@cl'):
57 if not body.startswith('@cl'):
58 # plain python repr node, just eval it
58 # plain python repr node, just eval it
59 return ip.ev(n.b)
59 return ip.ev(n.b)
60 # @cl nodes deserve special treatment - first eval the first line (minus cl), then use it to call the rest of body
60 # @cl nodes deserve special treatment - first eval the first line (minus cl), then use it to call the rest of body
61 first, rest = body.split('\n',1)
61 first, rest = body.split('\n',1)
62 tup = first.split(None, 1)
62 tup = first.split(None, 1)
63 # @cl alone SPECIAL USE-> dump var to user_ns
63 # @cl alone SPECIAL USE-> dump var to user_ns
64 if len(tup) == 1:
64 if len(tup) == 1:
65 val = ip.ev(rest)
65 val = ip.ev(rest)
66 ip.user_ns[n.h] = val
66 ip.user_ns[n.h] = val
67 es("%s = %s" % (n.h, repr(val)[:20] ))
67 es("%s = %s" % (n.h, repr(val)[:20] ))
68 return val
68 return val
69
69
70 cl, hd = tup
70 cl, hd = tup
71
71
72 xformer = ip.ev(hd.strip())
72 xformer = ip.ev(hd.strip())
73 es('Transform w/ %s' % repr(xformer))
73 es('Transform w/ %s' % repr(xformer))
74 return xformer(rest, n)
74 return xformer(rest, n)
75
75
76 class LeoNode(object, UserDict.DictMixin):
76 class LeoNode(object, UserDict.DictMixin):
77 """ Node in Leo outline
77 """ Node in Leo outline
78
78
79 Most important attributes (getters/setters available:
79 Most important attributes (getters/setters available:
80 .v - evaluate node, can also be alligned
80 .v - evaluate node, can also be alligned
81 .b, .h - body string, headline string
81 .b, .h - body string, headline string
82 .l - value as string list
82 .l - value as string list
83
83
84 Also supports iteration,
84 Also supports iteration,
85
85
86 setitem / getitem (indexing):
86 setitem / getitem (indexing):
87 wb.foo['key'] = 12
87 wb.foo['key'] = 12
88 assert wb.foo['key'].v == 12
88 assert wb.foo['key'].v == 12
89
89
90 Note the asymmetry on setitem and getitem! Also other
90 Note the asymmetry on setitem and getitem! Also other
91 dict methods are available.
91 dict methods are available.
92
92
93 .ipush() - run push-to-ipython
93 .ipush() - run push-to-ipython
94
94
95 """
95 """
96 def __init__(self,p):
96 def __init__(self,p):
97 self.p = p.copy()
97 self.p = p.copy()
98
98
99 def __get_h(self): return self.p.headString()
99 def __get_h(self): return self.p.headString()
100 def __set_h(self,val):
100 def __set_h(self,val):
101 print "set head",val
101 print "set head",val
102 c.beginUpdate()
102 c.beginUpdate()
103 try:
103 try:
104 c.setHeadString(self.p,val)
104 c.setHeadString(self.p,val)
105 finally:
105 finally:
106 c.endUpdate()
106 c.endUpdate()
107
107
108 h = property( __get_h, __set_h, doc = "Node headline string")
108 h = property( __get_h, __set_h, doc = "Node headline string")
109
109
110 def __get_b(self): return self.p.bodyString()
110 def __get_b(self): return self.p.bodyString()
111 def __set_b(self,val):
111 def __set_b(self,val):
112 print "set body",val
112 print "set body",val
113 c.beginUpdate()
113 c.beginUpdate()
114 try:
114 try:
115 c.setBodyString(self.p, val)
115 c.setBodyString(self.p, val)
116 finally:
116 finally:
117 c.endUpdate()
117 c.endUpdate()
118
118
119 b = property(__get_b, __set_b, doc = "Nody body string")
119 b = property(__get_b, __set_b, doc = "Nody body string")
120
120
121 def __set_val(self, val):
121 def __set_val(self, val):
122 self.b = format_for_leo(val)
122 self.b = format_for_leo(val)
123
123
124 v = property(lambda self: eval_node(self), __set_val, doc = "Node evaluated value")
124 v = property(lambda self: eval_node(self), __set_val, doc = "Node evaluated value")
125
125
126 def __set_l(self,val):
126 def __set_l(self,val):
127 self.b = '\n'.join(val )
127 self.b = '\n'.join(val )
128 l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
128 l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
129 __set_l, doc = "Node value as string list")
129 __set_l, doc = "Node value as string list")
130
130
131 def __iter__(self):
131 def __iter__(self):
132 """ Iterate through nodes direct children """
132 """ Iterate through nodes direct children """
133
133
134 return (LeoNode(p) for p in self.p.children_iter())
134 return (LeoNode(p) for p in self.p.children_iter())
135
135
136 def __children(self):
136 def __children(self):
137 d = {}
137 d = {}
138 for child in self:
138 for child in self:
139 head = child.h
139 head = child.h
140 tup = head.split(None,1)
140 tup = head.split(None,1)
141 if len(tup) > 1 and tup[0] == '@k':
141 if len(tup) > 1 and tup[0] == '@k':
142 d[tup[1]] = child
142 d[tup[1]] = child
143 continue
143 continue
144
144
145 if not valid_attribute(head):
145 if not valid_attribute(head):
146 d[head] = child
146 d[head] = child
147 continue
147 continue
148 return d
148 return d
149 def keys(self):
149 def keys(self):
150 d = self.__children()
150 d = self.__children()
151 return d.keys()
151 return d.keys()
152 def __getitem__(self, key):
152 def __getitem__(self, key):
153 """ wb.foo['Some stuff'] Return a child node with headline 'Some stuff'
153 """ wb.foo['Some stuff'] Return a child node with headline 'Some stuff'
154
154
155 If key is a valid python name (e.g. 'foo'), look for headline '@k foo' as well
155 If key is a valid python name (e.g. 'foo'), look for headline '@k foo' as well
156 """
156 """
157 key = str(key)
157 key = str(key)
158 d = self.__children()
158 d = self.__children()
159 return d[key]
159 return d[key]
160 def __setitem__(self, key, val):
160 def __setitem__(self, key, val):
161 """ You can do wb.foo['My Stuff'] = 12 to create children
161 """ You can do wb.foo['My Stuff'] = 12 to create children
162
162
163 This will create 'My Stuff' as a child of foo (if it does not exist), and
163 This will create 'My Stuff' as a child of foo (if it does not exist), and
164 do .v = 12 assignment.
164 do .v = 12 assignment.
165
165
166 Exception:
166 Exception:
167
167
168 wb.foo['bar'] = 12
168 wb.foo['bar'] = 12
169
169
170 will create a child with headline '@k bar', because bar is a valid python name
170 will create a child with headline '@k bar', because bar is a valid python name
171 and we don't want to crowd the WorkBook namespace with (possibly numerous) entries
171 and we don't want to crowd the WorkBook namespace with (possibly numerous) entries
172 """
172 """
173 key = str(key)
173 key = str(key)
174 d = self.__children()
174 d = self.__children()
175 if key in d:
175 if key in d:
176 d[key].v = val
176 d[key].v = val
177 return
177 return
178
178
179 if not valid_attribute(key):
179 if not valid_attribute(key):
180 head = key
180 head = key
181 else:
181 else:
182 head = '@k ' + key
182 head = '@k ' + key
183 p = c.createLastChildNode(self.p, head, '')
183 p = c.createLastChildNode(self.p, head, '')
184 LeoNode(p).v = val
184 LeoNode(p).v = val
185 def __delitem__(self,key):
185 def __delitem__(self,key):
186 pass
186 pass
187 def ipush(self):
187 def ipush(self):
188 """ Does push-to-ipython on the node """
188 """ Does push-to-ipython on the node """
189 push_from_leo(self)
189 push_from_leo(self)
190 def go(self):
190 def go(self):
191 """ Set node as current node (to quickly see it in Outline) """
191 """ Set node as current node (to quickly see it in Outline) """
192 c.beginUpdate()
192 c.beginUpdate()
193 try:
193 try:
194 c.setCurrentPosition(self.p)
194 c.setCurrentPosition(self.p)
195 finally:
195 finally:
196 c.endUpdate()
196 c.endUpdate()
197
197
198 def __get_uA(self):
198 def __get_uA(self):
199 p = self.p
199 p = self.p
200 # Create the uA if necessary.
200 # Create the uA if necessary.
201 if not hasattr(p.v.t,'unknownAttributes'):
201 if not hasattr(p.v.t,'unknownAttributes'):
202 p.v.t.unknownAttributes = {}
202 p.v.t.unknownAttributes = {}
203
203
204 d = p.v.t.unknownAttributes.setdefault('ipython', {})
204 d = p.v.t.unknownAttributes.setdefault('ipython', {})
205 return d
205 return d
206 uA = property(__get_uA, doc = "Access persistent unknownAttributes of node'")
206 uA = property(__get_uA, doc = "Access persistent unknownAttributes of node")
207
207
208
208
209 class LeoWorkbook:
209 class LeoWorkbook:
210 """ class for 'advanced' node access
210 """ class for 'advanced' node access
211
211
212 Has attributes for all "discoverable" nodes. Node is discoverable if it
212 Has attributes for all "discoverable" nodes. Node is discoverable if it
213 either
213 either
214
214
215 - has a valid python name (Foo, bar_12)
215 - has a valid python name (Foo, bar_12)
216 - is a parent of an anchor node (if it has a child '@a foo', it is visible as foo)
216 - is a parent of an anchor node (if it has a child '@a foo', it is visible as foo)
217
217
218 """
218 """
219 def __getattr__(self, key):
219 def __getattr__(self, key):
220 if key.startswith('_') or key == 'trait_names' or not valid_attribute(key):
220 if key.startswith('_') or key == 'trait_names' or not valid_attribute(key):
221 raise AttributeError
221 raise AttributeError
222 cells = all_cells()
222 cells = all_cells()
223 p = cells.get(key, None)
223 p = cells.get(key, None)
224 if p is None:
224 if p is None:
225 p = add_var(key)
225 p = add_var(key)
226
226
227 return LeoNode(p)
227 return LeoNode(p)
228
228
229 def __str__(self):
229 def __str__(self):
230 return "<LeoWorkbook>"
230 return "<LeoWorkbook>"
231 def __setattr__(self,key, val):
231 def __setattr__(self,key, val):
232 raise AttributeError("Direct assignment to workbook denied, try wb.%s.v = %s" % (key,val))
232 raise AttributeError("Direct assignment to workbook denied, try wb.%s.v = %s" % (key,val))
233
233
234 __repr__ = __str__
234 __repr__ = __str__
235
235
236 def __iter__(self):
236 def __iter__(self):
237 """ Iterate all (even non-exposed) nodes """
237 """ Iterate all (even non-exposed) nodes """
238 cells = all_cells()
238 cells = all_cells()
239 return (LeoNode(p) for p in c.allNodes_iter())
239 return (LeoNode(p) for p in c.allNodes_iter())
240
240
241 ip.user_ns['wb'] = LeoWorkbook()
241 ip.user_ns['wb'] = LeoWorkbook()
242
242
243
243
244
244
245 @IPython.generics.complete_object.when_type(LeoWorkbook)
245 @IPython.generics.complete_object.when_type(LeoWorkbook)
246 def workbook_complete(obj, prev):
246 def workbook_complete(obj, prev):
247 return all_cells().keys()
247 return all_cells().keys()
248
248
249
249
250 def add_var(varname):
250 def add_var(varname):
251 c.beginUpdate()
251 c.beginUpdate()
252 try:
252 try:
253 p2 = g.findNodeAnywhere(c,varname)
253 p2 = g.findNodeAnywhere(c,varname)
254 if p2:
254 if p2:
255 return
255 return
256
256
257 rootpos = g.findNodeAnywhere(c,'@ipy-results')
257 rootpos = g.findNodeAnywhere(c,'@ipy-results')
258 if not rootpos:
258 if not rootpos:
259 rootpos = c.currentPosition()
259 rootpos = c.currentPosition()
260 p2 = rootpos.insertAsLastChild()
260 p2 = rootpos.insertAsLastChild()
261 c.setHeadString(p2,varname)
261 c.setHeadString(p2,varname)
262 return p2
262 return p2
263 finally:
263 finally:
264 c.endUpdate()
264 c.endUpdate()
265
265
266 def add_file(self,fname):
266 def add_file(self,fname):
267 p2 = c.currentPosition().insertAfter()
267 p2 = c.currentPosition().insertAfter()
268
268
269 push_from_leo = CommandChainDispatcher()
269 push_from_leo = CommandChainDispatcher()
270
270
271 def expose_ileo_push(f, prio = 0):
271 def expose_ileo_push(f, prio = 0):
272 push_from_leo.add(f, prio)
272 push_from_leo.add(f, prio)
273
273
274 def push_ipython_script(node):
274 def push_ipython_script(node):
275 """ Execute the node body in IPython, as if it was entered in interactive prompt """
275 """ Execute the node body in IPython, as if it was entered in interactive prompt """
276 c.beginUpdate()
276 c.beginUpdate()
277 try:
277 try:
278 ohist = ip.IP.output_hist
278 ohist = ip.IP.output_hist
279 hstart = len(ip.IP.input_hist)
279 hstart = len(ip.IP.input_hist)
280 script = g.getScript(c,node.p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
280 script = g.getScript(c,node.p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
281
281
282 script = g.splitLines(script + '\n')
282 script = g.splitLines(script + '\n')
283
283
284 ip.runlines(script)
284 ip.runlines(script)
285
285
286 has_output = False
286 has_output = False
287 for idx in range(hstart,len(ip.IP.input_hist)):
287 for idx in range(hstart,len(ip.IP.input_hist)):
288 val = ohist.get(idx,None)
288 val = ohist.get(idx,None)
289 if val is None:
289 if val is None:
290 continue
290 continue
291 has_output = True
291 has_output = True
292 inp = ip.IP.input_hist[idx]
292 inp = ip.IP.input_hist[idx]
293 if inp.strip():
293 if inp.strip():
294 es('In: %s' % (inp[:40], ))
294 es('In: %s' % (inp[:40], ))
295
295
296 es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)))
296 es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)))
297
297
298 if not has_output:
298 if not has_output:
299 es('ipy run: %s (%d LL)' %( node.h,len(script)))
299 es('ipy run: %s (%d LL)' %( node.h,len(script)))
300 finally:
300 finally:
301 c.endUpdate()
301 c.endUpdate()
302
302
303 # this should be the LAST one that will be executed, and it will never raise TryNext
303 # this should be the LAST one that will be executed, and it will never raise TryNext
304 expose_ileo_push(push_ipython_script, 1000)
304 expose_ileo_push(push_ipython_script, 1000)
305
305
306 def eval_body(body):
306 def eval_body(body):
307 try:
307 try:
308 val = ip.ev(body)
308 val = ip.ev(body)
309 except:
309 except:
310 # just use stringlist if it's not completely legal python expression
310 # just use stringlist if it's not completely legal python expression
311 val = IPython.genutils.SList(body.splitlines())
311 val = IPython.genutils.SList(body.splitlines())
312 return val
312 return val
313
313
314 def push_plain_python(node):
314 def push_plain_python(node):
315 if not node.h.endswith('P'):
315 if not node.h.endswith('P'):
316 raise TryNext
316 raise TryNext
317 script = g.getScript(c,node.p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
317 script = g.getScript(c,node.p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
318 lines = script.count('\n')
318 lines = script.count('\n')
319 try:
319 try:
320 exec script in ip.user_ns
320 exec script in ip.user_ns
321 except:
321 except:
322 print " -- Exception in script:\n"+script + "\n --"
322 print " -- Exception in script:\n"+script + "\n --"
323 raise
323 raise
324 es('ipy plain: %s (%d LL)' % (node.h,lines))
324 es('ipy plain: %s (%d LL)' % (node.h,lines))
325
325
326 expose_ileo_push(push_plain_python, 100)
326 expose_ileo_push(push_plain_python, 100)
327
327
328 def push_cl_node(node):
328 def push_cl_node(node):
329 """ If node starts with @cl, eval it
329 """ If node starts with @cl, eval it
330
330
331 The result is put to root @ipy-results node
331 The result is put to root @ipy-results node
332 """
332 """
333 if not node.b.startswith('@cl'):
333 if not node.b.startswith('@cl'):
334 raise TryNext
334 raise TryNext
335
335
336 p2 = g.findNodeAnywhere(c,'@ipy-results')
336 p2 = g.findNodeAnywhere(c,'@ipy-results')
337 val = node.v
337 val = node.v
338 if p2:
338 if p2:
339 es("=> @ipy-results")
339 es("=> @ipy-results")
340 LeoNode(p2).v = val
340 LeoNode(p2).v = val
341 es(val)
341 es(val)
342
342
343 expose_ileo_push(push_cl_node,100)
343 expose_ileo_push(push_cl_node,100)
344
344
345 def push_position_from_leo(p):
345 def push_position_from_leo(p):
346 push_from_leo(LeoNode(p))
346 push_from_leo(LeoNode(p))
347
347
348 ip.user_ns['leox'].push = push_position_from_leo
348 ip.user_ns['leox'].push = push_position_from_leo
349
349
350 def leo_f(self,s):
350 def leo_f(self,s):
351 """ open file(s) in Leo
351 """ open file(s) in Leo
352
352
353 Takes an mglob pattern, e.g. '%leo *.cpp' or %leo 'rec:*.cpp'
353 Takes an mglob pattern, e.g. '%leo *.cpp' or %leo 'rec:*.cpp'
354 """
354 """
355 import os
355 import os
356 from IPython.external import mglob
356 from IPython.external import mglob
357
357
358 files = mglob.expand(s)
358 files = mglob.expand(s)
359 c.beginUpdate()
359 c.beginUpdate()
360 try:
360 try:
361 for fname in files:
361 for fname in files:
362 p = g.findNodeAnywhere(c,'@auto ' + fname)
362 p = g.findNodeAnywhere(c,'@auto ' + fname)
363 if not p:
363 if not p:
364 p = c.currentPosition().insertAfter()
364 p = c.currentPosition().insertAfter()
365
365
366 p.setHeadString('@auto ' + fname)
366 p.setHeadString('@auto ' + fname)
367 if os.path.isfile(fname):
367 if os.path.isfile(fname):
368 c.setBodyString(p,open(fname).read())
368 c.setBodyString(p,open(fname).read())
369 c.selectPosition(p)
369 c.selectPosition(p)
370 finally:
370 finally:
371 c.endUpdate()
371 c.endUpdate()
372
372
373 ip.expose_magic('leo',leo_f)
373 ip.expose_magic('leo',leo_f)
374
374
375 def leoref_f(self,s):
375 def leoref_f(self,s):
376 """ Quick reference for ILeo """
376 """ Quick reference for ILeo """
377 import textwrap
377 import textwrap
378 print textwrap.dedent("""\
378 print textwrap.dedent("""\
379 %leo file - open file in leo
379 %leo file - open file in leo
380 wb.foo.v - eval node foo (i.e. headstring is 'foo' or '@ipy foo')
380 wb.foo.v - eval node foo (i.e. headstring is 'foo' or '@ipy foo')
381 wb.foo.v = 12 - assign to body of node foo
381 wb.foo.v = 12 - assign to body of node foo
382 wb.foo.b - read or write the body of node foo
382 wb.foo.b - read or write the body of node foo
383 wb.foo.l - body of node foo as string list
383 wb.foo.l - body of node foo as string list
384
384
385 for el in wb.foo:
385 for el in wb.foo:
386 print el.v
386 print el.v
387
387
388 """
388 """
389 )
389 )
390 ip.expose_magic('leoref',leoref_f)
390 ip.expose_magic('leoref',leoref_f)
391
391
392 def show_welcome():
392 def show_welcome():
393 print "------------------"
393 print "------------------"
394 print "Welcome to Leo-enabled IPython session!"
394 print "Welcome to Leo-enabled IPython session!"
395 print "Try %leoref for quick reference."
395 print "Try %leoref for quick reference."
396 import IPython.platutils
396 import IPython.platutils
397 IPython.platutils.set_term_title('ILeo')
397 IPython.platutils.set_term_title('ILeo')
398 IPython.platutils.freeze_term_title()
398 IPython.platutils.freeze_term_title()
399
399
400 def run_leo_startup_node():
400 def run_leo_startup_node():
401 p = g.findNodeAnywhere(c,'@ipy-startup')
401 p = g.findNodeAnywhere(c,'@ipy-startup')
402 if p:
402 if p:
403 print "Running @ipy-startup nodes"
403 print "Running @ipy-startup nodes"
404 for n in LeoNode(p):
404 for n in LeoNode(p):
405 push_from_leo(n)
405 push_from_leo(n)
406
406
407 run_leo_startup_node()
407 run_leo_startup_node()
408 show_welcome()
408 show_welcome()
409
409
@@ -1,409 +1,508 b''
1 <?xml version="1.0" encoding="utf-8"?>
1 <?xml version="1.0" encoding="utf-8"?>
2 <?xml-stylesheet ekr_test?>
2 <?xml-stylesheet ekr_test?>
3 <leo_file>
3 <leo_file>
4 <leo_header file_format="2" tnodes="0" max_tnode_index="0" clone_windows="0"/>
4 <leo_header file_format="2" tnodes="0" max_tnode_index="0" clone_windows="0"/>
5 <globals body_outline_ratio="0.5">
5 <globals body_outline_ratio="0.307814992026">
6 <global_window_position top="261" left="404" height="621" width="1280"/>
6 <global_window_position top="140" left="145" height="627" width="1280"/>
7 <global_log_window_position top="0" left="0" height="0" width="0"/>
7 <global_log_window_position top="0" left="0" height="0" width="0"/>
8 </globals>
8 </globals>
9 <preferences/>
9 <preferences/>
10 <find_panel_settings/>
10 <find_panel_settings/>
11 <vnodes>
11 <vnodes>
12 <v t="vivainio.20080222193236" a="E"><vh>Documentation</vh>
13 <v t="vivainio.20080223121915" a="E" tnodeList="vivainio.20080223121915,vivainio.20080222193236.1,vivainio.20080223133858,vivainio.20080223133922,vivainio.20080223133947,vivainio.20080223134018,vivainio.20080223134100,vivainio.20080223134118,vivainio.20080223134433,vivainio.20080223142207,vivainio.20080223134136"><vh>@nosent ileointro.txt</vh>
14 <v t="vivainio.20080222193236.1" a="E"><vh>Documentation</vh>
15 <v t="vivainio.20080223133858"><vh>Introduction</vh></v>
16 <v t="vivainio.20080223133922"><vh>Installation</vh></v>
17 <v t="vivainio.20080223133947"><vh>Accessing IPython from Leo</vh></v>
18 <v t="vivainio.20080223134018" a="TV"><vh>Accessing Leo nodes from IPython</vh></v>
19 <v t="vivainio.20080223134100"><vh>Cl definitions</vh></v>
20 <v t="vivainio.20080223134118"><vh>Special node types</vh></v>
21 <v t="vivainio.20080223134433"><vh>Custom push</vh></v>
22 <v t="vivainio.20080223142207" a="E"><vh>Code snippets</vh></v>
23 <v t="vivainio.20080223134136"><vh>Acknowledgements and history</vh></v>
24 </v>
25 </v>
26 </v>
12 <v t="vivainio.20080218184525"><vh>@chapters</vh></v>
27 <v t="vivainio.20080218184525"><vh>@chapters</vh></v>
13 <v t="vivainio.20080223133721" a="E"><vh>@settings</vh>
28 <v t="vivainio.20080223133721"><vh>@settings</vh>
14 <v t="vivainio.20080223133721.1"><vh>@enabled-plugins</vh></v>
29 <v t="vivainio.20080223133721.1"><vh>@enabled-plugins</vh></v>
15 </v>
30 </v>
16 <v t="vivainio.20080218184540" a="E"><vh>@ipy-startup</vh>
31 <v t="vivainio.20080218184540" a="E"><vh>@ipy-startup</vh>
17 <v t="vivainio.20080218184613.1"><vh>b</vh></v>
32 <v t="vivainio.20080218184613.1"><vh>b</vh></v>
18 <v t="vivainio.20080218200031" a="E"><vh>Some classes P</vh>
33 <v t="vivainio.20080218200031"><vh>Some classes P</vh>
19 <v t="vivainio.20080218190816"><vh>File-like access</vh></v>
34 <v t="vivainio.20080218190816"><vh>File-like access</vh></v>
20 <v t="vivainio.20080218200106"><vh>csv data</vh></v>
35 <v t="vivainio.20080218200106"><vh>csv data</vh></v>
21 <v t="vivainio.20080219225120"><vh>String list</vh></v>
36 <v t="vivainio.20080219225120"><vh>String list</vh></v>
22 <v t="vivainio.20080219230342"><vh>slist to leo</vh></v>
37 <v t="vivainio.20080219230342"><vh>slist to leo</vh></v>
23 </v>
38 </v>
24 </v>
39 </v>
25 <v t="vivainio.20080218195413"><vh>Class tests</vh>
40 <v t="vivainio.20080218195413"><vh>Class tests</vh>
26 <v t="vivainio.20080218200509"><vh>csvr</vh></v>
41 <v t="vivainio.20080218200509"><vh>csvr</vh></v>
27 <v t="vivainio.20080218191007"><vh>tempfile</vh></v>
42 <v t="vivainio.20080218191007"><vh>tempfile</vh></v>
28 <v t="vivainio.20080218195413.1"><vh>rfile</vh></v>
43 <v t="vivainio.20080218195413.1"><vh>rfile</vh></v>
29 <v t="vivainio.20080219225804"><vh>strlist</vh></v>
44 <v t="vivainio.20080219225804"><vh>strlist</vh></v>
30 </v>
45 </v>
31 <v t="vivainio.20080218201219"><vh>Direct variables</vh>
46 <v t="vivainio.20080218201219"><vh>Direct variables</vh>
32 <v t="vivainio.20080222201226"><vh>NewHeadline</vh></v>
47 <v t="vivainio.20080222201226"><vh>NewHeadline</vh></v>
33 <v t="vivainio.20080218201219.2"><vh>bar</vh></v>
48 <v t="vivainio.20080218201219.2"><vh>bar</vh></v>
34 </v>
49 </v>
35 <v t="vivainio.20080222193236" a="E"><vh>Docs</vh>
50 <v t="vivainio.20080222202211"><vh>test stuff</vh></v>
36 <v t="vivainio.20080223121915" a="E" tnodeList="vivainio.20080223121915,vivainio.20080222193236.1,vivainio.20080223133858,vivainio.20080223133922,vivainio.20080223133947,vivainio.20080223134018,vivainio.20080223134100,vivainio.20080223134118,vivainio.20080223134433,vivainio.20080223134136"><vh>@nosent ileointro.txt</vh>
51 <v t="vivainio.20080223142403" a="E"><vh>@ipy-results</vh>
37 <v t="vivainio.20080222193236.1" a="E"><vh>Quick intro</vh>
52 <v t="vivainio.20080223142403.1"><vh>foo</vh></v>
38 <v t="vivainio.20080223133858"><vh>Introduction</vh></v>
53 <v t="vivainio.20080223152600" a="E"><vh>baz</vh>
39 <v t="vivainio.20080223133922"><vh>Installation</vh></v>
54 <v t="vivainio.20080223174603"><vh>@k hello</vh></v>
40 <v t="vivainio.20080223133947"><vh>Accessing IPython from Leo</vh></v>
41 <v t="vivainio.20080223134018"><vh>Accessing Leo nodes from IPython</vh></v>
42 <v t="vivainio.20080223134100"><vh>Cl definitions</vh></v>
43 <v t="vivainio.20080223134118"><vh>Special node types</vh></v>
44 <v t="vivainio.20080223134433" a="TV"><vh>Custom push</vh></v>
45 <v t="vivainio.20080223134136"><vh>Acknowledgements and history</vh></v>
46 </v>
55 </v>
47 </v>
56 </v>
57 <v t="vivainio.20080222202211.1"><vh>spam</vh>
58 <v t="vivainio.20080223180139"><vh>foo bar</vh></v>
48 </v>
59 </v>
49 <v t="vivainio.20080222202211"><vh>test stuff</vh></v>
50 <v t="vivainio.20080222202211.1"><vh>spam</vh></v>
51 <v t="vivainio.20080222202211.2"><vh>NewHeadline</vh></v>
60 <v t="vivainio.20080222202211.2"><vh>NewHeadline</vh></v>
52 </vnodes>
61 </vnodes>
53 <tnodes>
62 <tnodes>
54 <t tx="vivainio.20080218184525">?</t>
63 <t tx="vivainio.20080218184525">?</t>
55 <t tx="vivainio.20080218184540">?Direct children of this node will be pushed at ipython bridge startup
64 <t tx="vivainio.20080218184540">?Direct children of this node will be pushed at ipython bridge startup
56
65
57 This node itself will *not* be pushed</t>
66 This node itself will *not* be pushed</t>
58 <t tx="vivainio.20080218184613.1">print "world"</t>
67 <t tx="vivainio.20080218184613.1">print "world"</t>
59 <t tx="vivainio.20080218190816">def rfile(body,n):
68 <t tx="vivainio.20080218190816">def rfile(body,n):
60 """ @cl rfile
69 """ @cl rfile
61
70
62 produces a StringIO (file like obj of the rest of the body) """
71 produces a StringIO (file like obj of the rest of the body) """
63
72
64 import StringIO
73 import StringIO
65 return StringIO.StringIO(body)
74 return StringIO.StringIO(body)
66
75
67 def tmpfile(body,n):
76 def tmpfile(body,n):
68 """ @cl tmpfile
77 """ @cl tmpfile
69
78
70 Produces a temporary file, with node body as contents
79 Produces a temporary file, with node body as contents
71
80
72 """
81 """
73 import tempfile
82 import tempfile
74 h, fname = tempfile.mkstemp()
83 h, fname = tempfile.mkstemp()
75 f = open(fname,'w')
84 f = open(fname,'w')
76 f.write(body)
85 f.write(body)
77 f.close()
86 f.close()
78 return fname
87 return fname
79 </t>
88 </t>
80 <t tx="vivainio.20080218191007">@cl tmpfile
89 <t tx="vivainio.20080218191007">@cl tmpfile
81
90
82 Hello</t>
91 Hello</t>
83 <t tx="vivainio.20080218195413">?</t>
92 <t tx="vivainio.20080218195413">?</t>
84 <t tx="vivainio.20080218195413.1">@cl rfile
93 <t tx="vivainio.20080218195413.1">@cl rfile
85 These
94 These
86 lines
95 lines
87 should
96 should
88 be
97 be
89 readable </t>
98 readable </t>
90 <t tx="vivainio.20080218200031">@others</t>
99 <t tx="vivainio.20080218200031">@others</t>
91 <t tx="vivainio.20080218200106">def csvdata(body,n):
100 <t tx="vivainio.20080218200106">def csvdata(body,n):
92 import csv
101 import csv
93 d = csv.Sniffer().sniff(body)
102 d = csv.Sniffer().sniff(body)
94 reader = csv.reader(body.splitlines(), dialect = d)
103 reader = csv.reader(body.splitlines(), dialect = d)
95 return reader</t>
104 return reader</t>
96 <t tx="vivainio.20080218200509">@cl csvdata
105 <t tx="vivainio.20080218200509">@cl csvdata
97
106
98 a,b,b
107 a,b,b
99 1,2,2</t>
108 1,2,2</t>
100 <t tx="vivainio.20080218201219"></t>
109 <t tx="vivainio.20080218201219"></t>
101 <t tx="vivainio.20080218201219.2">@cl
110 <t tx="vivainio.20080218201219.2">@cl
102 "hello world"</t>
111 "hello world"</t>
103 <t tx="vivainio.20080219225120">import IPython.genutils
112 <t tx="vivainio.20080219225120">import IPython.genutils
104 def slist(body,n):
113 def slist(body,n):
105 return IPython.genutils.SList(body.splitlines())
114 return IPython.genutils.SList(body.splitlines())
106 </t>
115 </t>
107 <t tx="vivainio.20080219225804">@cl slist
116 <t tx="vivainio.20080219225804">@cl slist
108 hello
117 hello
109 world
118 world
110 on
119 on
111 many
120 many
112 lines
121 lines
113 </t>
122 </t>
114 <t tx="vivainio.20080219230342">import ipy_leo
123 <t tx="vivainio.20080219230342">import ipy_leo
115 @ipy_leo.format_for_leo.when_type(IPython.genutils.SList)
124 @ipy_leo.format_for_leo.when_type(IPython.genutils.SList)
116 def format_slist(obj):
125 def format_slist(obj):
117 return "@cl slist\n" + obj.n
126 return "@cl slist\n" + obj.n
118 </t>
127 </t>
119 <t tx="vivainio.20080222193236"></t>
128 <t tx="vivainio.20080222193236">?</t>
120 <t tx="vivainio.20080222193236.1">@wrap
129 <t tx="vivainio.20080222193236.1">@wrap
121 @nocolor</t>
130 @nocolor</t>
122 <t tx="vivainio.20080222201226">1+2
131 <t tx="vivainio.20080222201226">1+2
123 print "hello"
132 print "hello"
124 3+4
133 3+4
125
134
126 def f(x):
135 def f(x):
127 return x.upper()
136 return x.upper()
128
137
129 f('hello world')</t>
138 f('hello world')</t>
130 <t tx="vivainio.20080222202211"></t>
139 <t tx="vivainio.20080222202211"></t>
131 <t tx="vivainio.20080222202211.1">@cl rfile
140 <t tx="vivainio.20080222202211.1" ipython="7d71005506636f6f7264737101284b0c4bde747102732e">@cl rfile
132 hello
141 hello
133 world
142 world
134 and whatever</t>
143 and whatever</t>
135 <t tx="vivainio.20080222202211.2"></t>
144 <t tx="vivainio.20080222202211.2"></t>
136 <t tx="vivainio.20080223121915">@others
145 <t tx="vivainio.20080223121915">@others
137 </t>
146 </t>
138 <t tx="vivainio.20080223133721"></t>
147 <t tx="vivainio.20080223133721"></t>
139 <t tx="vivainio.20080223133721.1">ipython.py</t>
148 <t tx="vivainio.20080223133721.1">ipython.py</t>
140 <t tx="vivainio.20080223133858">
149 <t tx="vivainio.20080223133858">
141 Introduction
150 Introduction
142 ============
151 ============
143
152
144 The purpose of ILeo, or leo-ipython bridge, is being a two-way communication
153 The purpose of ILeo, or leo-ipython bridge, is being a two-way communication
145 channel between Leo and IPython. The level of integration is much deeper than
154 channel between Leo and IPython. The level of integration is much deeper than
146 conventional integration in IDEs; most notably, you are able to store *data* in
155 conventional integration in IDEs; most notably, you are able to store *data* in
147 Leo nodes, in addition to mere program code. The possibilities of this are
156 Leo nodes, in addition to mere program code. The possibilities of this are
148 endless, and this degree of integration has not been seen previously in the python
157 endless, and this degree of integration has not been seen previously in the python
149 world.
158 world.
150
159
151 IPython users are accustomed to using things like %edit to produce non-trivial
160 IPython users are accustomed to using things like %edit to produce non-trivial
152 functions/classes (i.e. something that they don't want to enter directly on the
161 functions/classes (i.e. something that they don't want to enter directly on the
153 interactive prompt, but creating a proper script/module involves too much
162 interactive prompt, but creating a proper script/module involves too much
154 overhead). In ILeo, this task consists just going to the Leo window, creating a node
163 overhead). In ILeo, this task consists just going to the Leo window, creating a node
155 and writing the code there, and pressing alt+I (push-to-ipython).
164 and writing the code there, and pressing alt+I (push-to-ipython).
156
165
157 Obviously, you can save the Leo document as usual - this is a great advantage
166 Obviously, you can save the Leo document as usual - this is a great advantage
158 of ILeo over using %edit, you can save your experimental scripts all at one
167 of ILeo over using %edit, you can save your experimental scripts all at one
159 time, without having to organize them into script/module files (before you
168 time, without having to organize them into script/module files (before you
160 really want to, of course!)
169 really want to, of course!)
161 </t>
170 </t>
162 <t tx="vivainio.20080223133922">
171 <t tx="vivainio.20080223133922">
163 Installation
172 Installation
164 ============
173 ============
165
174
166 You need at least Leo 4.4.7, and the development version of IPython (ILeo
175 You need at least Leo 4.4.7, and the development version of IPython (ILeo
167 will be incorporated to IPython 0.8.3).
176 will be incorporated to IPython 0.8.3).
168
177
169 You can get IPython from Launchpad by installing bzr and doing
178 You can get IPython from Launchpad by installing bzr and doing
170
179
171 bzr branch lp:ipython
180 bzr branch lp:ipython
172
181
173 and running "setup.py install".
182 and running "setup.py install".
174
183
175 You need to enable the 'ipython.py' plugin in Leo:
184 You need to enable the 'ipython.py' plugin in Leo:
176
185
177 - Help -&gt; Open LeoSettings.leo
186 - Help -&gt; Open LeoSettings.leo
178
187
179 - Edit @settings--&gt;Plugins--&gt;@enabled-plugins, add/uncomment 'ipython.py'
188 - Edit @settings--&gt;Plugins--&gt;@enabled-plugins, add/uncomment 'ipython.py'
180
189
190 - Alternatively, you can add @settings--&gt;@enabled-plugins with body ipython.py to your leo document.
191
181 - Restart Leo. Be sure that you have the console window open (start leo.py from console, or double-click leo.py on windows)
192 - Restart Leo. Be sure that you have the console window open (start leo.py from console, or double-click leo.py on windows)
182
193
183 - Press alt+5 OR alt-x start-ipython to launch IPython in the console that
194 - Press alt+5 OR alt-x start-ipython to launch IPython in the console that
184 started leo. You can start entering IPython commands normally, and Leo will keep
195 started leo. You can start entering IPython commands normally, and Leo will keep
185 running at the same time.
196 running at the same time.
186 </t>
197 </t>
187 <t tx="vivainio.20080223133947">
198 <t tx="vivainio.20080223133947">
188 Accessing IPython from Leo
199 Accessing IPython from Leo
189 ==========================
200 ==========================
190
201
191 IPython code
202 IPython code
192 ------------
203 ------------
193
204
194 Just enter IPython commands on a Leo node and press alt-I to execute
205 Just enter IPython commands on a Leo node and press alt-I to execute
195 push-to-ipython to execute the script in IPython. 'commands' is interpreted
206 push-to-ipython in order to execute the script in IPython. 'commands' is
196 loosely here - you can enter function and class definitions, in addition to the
207 interpreted loosely here - you can enter function and class definitions, in
197 things you would usually enter at IPython prompt - calculations, system commands etc.
208 addition to the things you would usually enter at IPython prompt - calculations,
209 system commands etc.
198
210
199 Everything that would be legal to enter on IPython prompt is legal to execute
211 Everything that would be legal to enter on IPython prompt is legal to execute
200 from ILeo.
212 from ILeo.
201
213
202 Results will be shows in Leo log window for convenience, in addition to the console.
214 Results will be shows in Leo log window for convenience, in addition to the console.
203
215
204 Suppose that a node had the following contents:
216 Suppose that a node had the following contents:
205 {{{
217 {{{
206 1+2
218 1+2
207 print "hello"
219 print "hello"
208 3+4
220 3+4
209
221
210 def f(x):
222 def f(x):
211 return x.upper()
223 return x.upper()
212
224
213 f('hello world')
225 f('hello world')
214 }}}
226 }}}
215
227
216 If you press alt+I on that done, you will see the following in Leo log window (IPython tab):
228 If you press alt+I on that node, you will see the following in Leo log window (IPython tab):
217
229
218 {{{
230 {{{
219 In: 1+2
231 In: 1+2
220 &lt;2&gt; 3
232 &lt;2&gt; 3
221 In: 3+4
233 In: 3+4
222 &lt;4&gt; 7
234 &lt;4&gt; 7
223 In: f('hello world')
235 In: f('hello world')
224 &lt;6&gt; 'HELLO WORLD'
236 &lt;6&gt; 'HELLO WORLD'
225 }}}
237 }}}
226
238
227 (numbers like &lt;6&gt; mean IPython output history indices).
239 (numbers like &lt;6&gt; mean IPython output history indices; the actual object can be
240 referenced with _6 as usual in IPython).
228
241
229
242
230 Plain Python code
243 Plain Python code
231 -----------------
244 -----------------
232
245
233 If the headline of the node ends with capital P, alt-I will not run the code
246 If the headline of the node ends with capital P, alt-I will not run the code
234 through IPython translation mechanism but use the direct python 'exec' statement
247 through IPython translation mechanism but use the direct python 'exec' statement
235 (in IPython user namespace) to execute the code. It wont be shown in IPython
248 (in IPython user namespace) to execute the code. It wont be shown in IPython
236 history, and sometimes it is safer (and more efficient) to execute things as
249 history, and sometimes it is safer (and more efficient) to execute things as
237 plain Python statements. Large class definitions are good candidates for P
250 plain Python statements. Large class definitions are good candidates for P
238 nodes.
251 nodes.
239 </t>
252 </t>
240 <t tx="vivainio.20080223134018">
253 <t tx="vivainio.20080223134018">
241 Accessing Leo nodes from IPython
254 Accessing Leo nodes from IPython
242 ================================
255 ================================
243
256
244 The real fun starts when you start entering text to leo nodes, and are using
257 The real fun starts when you start entering text to leo nodes, and are using
245 that as data (input/output) for your IPython work.
258 that as data (input/output) for your IPython work.
246
259
247 Accessing Leo nodes happens through the variable 'wb' (short for "WorkBook")
260 Accessing Leo nodes happens through the variable 'wb' (short for "WorkBook")
248 that exist in the IPython user namespace. Nodes that are directly accessible are
261 that exist in the IPython user namespace. Nodes that are directly accessible are
249 the ones that have simple names which could also be Python variable names;
262 the ones that have simple names which could also be Python variable names;
250 'foo_1' will be accessible directly from IPython, whereas 'my scripts' will not.
263 'foo_1' will be accessible directly from IPython, whereas 'my scripts' will not.
251 If you want to access a node with arbitrary headline, add a child node '@a foo'
264 If you want to access a node with arbitrary headline, add a child node '@a foo'
252 (@a stands for 'anchor'). Then, the parent of '@a foo' is accessible through
265 (@a stands for 'anchor'). Then, the parent of '@a foo' is accessible through
253 'wb.foo'.
266 'wb.foo'.
254
267
255 You can see what nodes are accessible be entering (in IPython) wb.&lt;TAB&gt;. Example:
268 You can see what nodes are accessible be entering (in IPython) wb.&lt;TAB&gt;. Example:
256
269
257 [C:leo/src]|12&gt; wb.
270 [C:leo/src]|12&gt; wb.
258 wb.b wb.tempfile wb.rfile wb.NewHeadline
271 wb.b wb.tempfile wb.rfile wb.NewHeadline
259 wb.bar wb.Docs wb.strlist wb.csvr
272 wb.bar wb.Docs wb.strlist wb.csvr
273 [C:leo/src]|12&gt; wb.tempfile
274 &lt;12&gt; &lt;ipy_leo.LeoNode object at 0x044B6D90&gt;
275
276 So here, we meet the 'LeoNode' class that is your key to manipulating Leo
277 content from IPython!
278
279 LeoNode
280 -------
260
281
261 Suppose that we had a node with headline 'spam' and body:
282 Suppose that we had a node with headline 'spam' and body:
262
283
263 ['12',2222+32]
284 ['12',2222+32]
264
285
265 we can access it from IPython (or from scripts entered into other Leo nodes!) by doing:
286 we can access it from IPython (or from scripts entered into other Leo nodes!) by doing:
266
287
267 C:leo/src]|19&gt; wb.spam.v
288 C:leo/src]|19&gt; wb.spam.v
268 &lt;19&gt; ['12', 2254]
289 &lt;19&gt; ['12', 2254]
269
290
270 'v' attribute stands for 'value', which means the node contents will be run
291 'v' attribute stands for 'value', which means the node contents will be run
271 through 'eval' and everything you would be able to enter into IPython prompt
292 through 'eval' and everything you would be able to enter into IPython prompt
272 will be converted to objects. This mechanism can be extended far beyond direct
293 will be converted to objects. This mechanism can be extended far beyond direct
273 evaluation (see '@cl definitions').
294 evaluation (see '@cl definitions').
274
295
275 'v' attribute also has a setter, i.e. you can do:
296 'v' attribute also has a setter, i.e. you can do:
276
297
277 wb.spam.v = "mystring"
298 wb.spam.v = "mystring"
278
299
279 Which will result in the node 'spam' having the following text:
300 Which will result in the node 'spam' having the following text:
280
301
281 'mystring'
302 'mystring'
282
303
283 What assignment to 'v' does can be configured through generic functions
304 What assignment to 'v' does can be configured through generic functions
284 (simplegeneric module, will be explained later).
305 ('simplegeneric' module, will be explained later).
306
307 Besides v, you can set the body text directly through
308
309 wb.spam.b = "some\nstring",
310
311 headline by
312
313 wb.spam.h = 'new_headline'
285
314
286 Besides v, you can set the body text directly through wb.spam.b =
315 (obviously you must access the node through wb.new_headline from that point
287 "some\nstring", headline by wb.spam.h = 'new_headline' (obviously you must
316 onwards), and access the contents as string list (IPython SList) through
288 access the node through wb.new_headline from that point onwards), and access the
317 'wb.spam.l'.
289 contents as string list (IPython SList) through 'wb.spam.l'.
290
318
291 If you do 'wb.foo.v = 12' when node named 'foo' does not exist, the node titled
319 If you do 'wb.foo.v = 12' when node named 'foo' does not exist, the node titled
292 'foo' will be automatically created and assigned body 12.
320 'foo' will be automatically created and assigned body 12.
321
322 LeoNode also supports go() that focuses the node in the Leo window, ipush that
323 simulates pressing alt+I on the node.
324
325 You can access unknownAttributes by .uA property dictionary. Unknown attributes
326 allow you to store arbitrary (pickleable) python objects in the Leo nodes;
327 the attributes are stored when you save the .leo document, and recreated when
328 you open the document again. Example::
329
330 [C:leo/src]|12&gt; wb.spam.uA['coords'] = (12,222)
331 [C:leo/src]|13&gt; wb.spam.uA
332 &lt;13&gt; {'coords': (12, 222)}
333
334 Accessing children with iteration and dict notation
335 ---------------------------------------------------
336
337 Sometimes, you may want to treat a node as a 'database', where the nodes
338 children represent elements in the database. You can create a new child node for
339 node 'spam', with headline 'foo bar' like this:
340
341 wb.spam['foo bar'] = "Hello"
342
343 And assign a new value for it by doing
344
345 wb.spam['foo bar'].v = "Hello again"
346
347 Note how you can't use .v when you first create the node - i.e. the node needs
348 to be initialized by simple assignment, that will be interpreted as assignment
349 to '.v'. This is a conscious design choice.
350
351 If you try to do wb.spam['bar'] = 'Hello', ILeo will assign '@k bar' as the
352 headline for the child instead, because 'bar' is a legal python name (and as
353 such would be incorporated in the workbook namespace). This is done to avoid
354 crowding the workbook namespace with extraneous items. The item will still be
355 accessible as wb.spam['bar']
356
357 LeoNodes are iterable, so to see the headlines of all the children of 'spam' do:
358
359 for n in wb.spam:
360 print n.h
293 </t>
361 </t>
294 <t tx="vivainio.20080223134100">
362 <t tx="vivainio.20080223134100">
295 @cl definitions
363 @cl definitions
296 ===============
364 ===============
297
365
298 If the first line in the body text is of the form '@cl sometext', IPython will
366 If the first line in the body text is of the form '@cl sometext', IPython will
299 will evaluate 'sometext' and call the result with the rest of the body when you
367 evaluate 'sometext' and call the result with the rest of the body when you do
300 do 'wb.foo.v'. An example is in place here. Suppose that we have defined a class
368 'wb.foo.v'. An example is in place here. Suppose that we have defined a class (I
301 (I use the term class in a non-python sense here)
369 use the term class in a non-python sense here)
302
370
303 {{{
371 {{{
304 def rfile(body,n):
372 def rfile(body,node):
305 """ @cl rfile
373 """ @cl rfile
306
374
307 produces a StringIO (file like obj) of the rest of the body """
375 produces a StringIO (file like obj) of the rest of the body """
308
376
309 import StringIO
377 import StringIO
310 return StringIO.StringIO(body)
378 return StringIO.StringIO(body)
311 }}}
379 }}}
312
380
313 Now, let's say you node 'spam' with text
381 (note that node is ignored here - but it could be used to access headline,
382 children etc.),
383
384 Now, let's say you have node 'spam' with text
314
385
315 {{{
386 {{{
316 @cl rfile
387 @cl rfile
317 hello
388 hello
318 world
389 world
319 and whatever
390 and whatever
320 }}}
391 }}}
321
392
322 Now, on IPython, we can do this:
393 Now, in IPython, we can do this:
323
394
324 {{{
395 {{{
325 [C:leo/src]|22&gt; f = wb.spam.v
396 [C:leo/src]|22&gt; f = wb.spam.v
326 [C:leo/src]|23&gt; f
397 [C:leo/src]|23&gt; f
327 &lt;23&gt; &lt;StringIO.StringIO instance at 0x04E7E490&gt;
398 &lt;23&gt; &lt;StringIO.StringIO instance at 0x04E7E490&gt;
328 [C:leo/src]|24&gt; f.readline()
399 [C:leo/src]|24&gt; f.readline()
329 &lt;24&gt; u'hello\n'
400 &lt;24&gt; u'hello\n'
330 [C:leo/src]|25&gt; f.readline()
401 [C:leo/src]|25&gt; f.readline()
331 &lt;25&gt; u'world\n'
402 &lt;25&gt; u'world\n'
332 [C:leo/src]|26&gt; f.readline()
403 [C:leo/src]|26&gt; f.readline()
333 &lt;26&gt; u'and whatever'
404 &lt;26&gt; u'and whatever'
334 [C:leo/src]|27&gt; f.readline()
405 [C:leo/src]|27&gt; f.readline()
335 &lt;27&gt; u''
406 &lt;27&gt; u''
336 }}}
407 }}}
337
408
338 You should declare new @cl types to make ILeo as convenient your problem domain as possible. For example, a "@cl etree" could return the elementtree object for xml content, or
409 You should declare new @cl types to make ILeo as convenient your problem domain
410 as possible. For example, a "@cl etree" could return the elementtree object for
411 xml content.
339 </t>
412 </t>
340 <t tx="vivainio.20080223134118">
413 <t tx="vivainio.20080223134118">
341 Special node types
414 Special node types
342 ==================
415 ==================
343
416
344 @ipy-startup
417 @ipy-startup
345 ------------
418 ------------
346
419
347 If this node exist, the *direct children* of this will be pushed to IPython when
420 If this node exist, the *direct children* of this will be pushed to IPython when
348 ILeo is started (you press alt+5). Use it to push your own @cl definitions etc.
421 ILeo is started (you press alt+5). Use it to push your own @cl definitions etc.
349 The contents of of the node itself will be ignored.
422 The contents of of the node itself will be ignored.
350
423
351 @ipy-results
424 @ipy-results
352 ------------
425 ------------
353
426
354 When you create a new node (wb.foo.v = 'stuff'), the node foo will be created as
427 When you create a new node (wb.foo.v = 'stuff'), the node foo will be created as
355 a child of this node. If @ipy-results does not exist, the new node will be created after the currently selected node.
428 a child of this node. If @ipy-results does not exist, the new node will be created after the currently selected node.
356
429
357 @a nodes
430 @a nodes
358 --------
431 --------
359
432
360 You can attach these as children of existing nodes to provide a way to access
433 You can attach these as children of existing nodes to provide a way to access
361 nodes with arbitrary headlines, or to provide aliases to other nodes. If
434 nodes with arbitrary headlines, or to provide aliases to other nodes. If
362 multiple @a nodes are attached as children of a node, all the names can be used
435 multiple @a nodes are attached as children of a node, all the names can be used
363 to access the same object.
436 to access the same object.
364 </t>
437 </t>
365 <t tx="vivainio.20080223134136">
438 <t tx="vivainio.20080223134136">
366 Acknowledgements &amp; History
439 Acknowledgements &amp; History
367 ==========================
440 ==========================
368
441
369 This idea got started when I (Ville) saw this post by Edward Ream (the author of
442 This idea got started when I (Ville) saw this post by Edward Ream (the author of
370 Leo) on IPython developer mailing list:
443 Leo) on IPython developer mailing list:
371
444
372 http://lists.ipython.scipy.org/pipermail/ipython-dev/2008-January/003551.html
445 http://lists.ipython.scipy.org/pipermail/ipython-dev/2008-January/003551.html
373
446
374 I was using FreeMind as mind mapping software, and so I had an immediate use
447 I was using FreeMind as mind mapping software, and so I had an immediate use
375 case for Leo (which, incidentally, is superior to FreeMind as mind mapper). The
448 case for Leo (which, incidentally, is superior to FreeMind as mind mapper). The
376 wheels started rolling, I got obsessed with the power of this concept
449 wheels started rolling, I got obsessed with the power of this concept
377 (everything clicked together), and Edwards excitement paralleled mine.
450 (everything clicked together), and Edwards excitement paralleled mine.
378 Everything was mind-bogglingly easy/trivial, something that is typical of all
451 Everything was mind-bogglingly easy/trivial, something that is typical of all
379 revolutionary technologies (think Python here).
452 revolutionary technologies (think Python here).
380
453
381 The discussion that "built" ILeo is here:
454 The discussion that "built" ILeo is here:
382 http://sourceforge.net/forum/forum.php?thread_id=1911662&amp;forum_id=10226
455 http://sourceforge.net/forum/forum.php?thread_id=1911662&amp;forum_id=10226
383
456
384 ?</t>
457 ?</t>
385 <t tx="vivainio.20080223134433">
458 <t tx="vivainio.20080223134433">
386 Declaring custom push-to-ipython handlers
459 Declaring custom push-to-ipython handlers
387 =========================================
460 =========================================
388
461
389 Sometimes, you might want to configure what alt+I on a node does. You can do
462 Sometimes, you might want to configure what alt+I on a node does. You can do
390 that by creating your own push function and expose it using
463 that by creating your own push function and expose it using
391 ipy_leo.expose_ileo_push(f, priority). The function should check whether the
464 ipy_leo.expose_ileo_push(f, priority). The function should check whether the
392 node should by handled by it and raise IPython.ipapi.TryNext if it will not do
465 node should by handled by the function and raise IPython.ipapi.TryNext if it
393 the handling.
466 will not do the handling, giving the next function in the chain a chance to see
467 whether it should handle the push.
394
468
395 This would print an uppercase version of node body if the node headline ends
469 This example would print an uppercase version of node body if the node headline ends
396 with U (yes, this is completely useless!)
470 with U (yes, this is completely useless!):
397
471
472 {{{
398 def push_upcase(node):
473 def push_upcase(node):
399 if not node.h.endswith('U'):
474 if not node.h.endswith('U'):
400 raise TryNext
475 raise TryNext
401 print node.b.upper()
476 print node.b.upper()
402
477
403 expose_ileo_push(push_upcase, 12)
478 ipy_leo.expose_ileo_push(push_upcase, 12)
479 }}}
404
480
405 (the priority should be between 0-100 - typically, you don't need to care about
481 (the priority should be between 0-100 - typically, you don't need to care about
406 it and can omit the argument altogether)
482 it and can usually omit the argument altogether)
483 </t>
484 <t tx="vivainio.20080223142207">
485 Example code snippets
486 =====================
487
488 Get list of all headlines of all the nodes in leo:
489
490 [node.h for node in wb]
491
492 Create node with headline 'baz', empty body:
493 wb.baz
494
495 Create 10 child nodes for baz, where i is headline and 'Hello ' + i is body:
496
497 for i in range(10):
498 wb.baz[i] = 'Hello %d' % i
499
500
407 </t>
501 </t>
502 <t tx="vivainio.20080223142403"></t>
503 <t tx="vivainio.20080223142403.1">12</t>
504 <t tx="vivainio.20080223152600"></t>
505 <t tx="vivainio.20080223174603"></t>
506 <t tx="vivainio.20080223180139">'hello again'</t>
408 </tnodes>
507 </tnodes>
409 </leo_file>
508 </leo_file>
General Comments 0
You need to be logged in to leave comments. Login now