##// END OF EJS Templates
Can register custom push-to-ipython handlers, e.g. 'expose_ileo_push(push_plain_python, 100)'...
Ville M. Vainio -
Show More
@@ -5,9 +5,10 b''
5 5 import IPython.ipapi
6 6 import IPython.genutils
7 7 import IPython.generics
8 from IPython.hooks import CommandChainDispatcher
8 9 import re
9 10 import UserDict
10
11 from IPython.ipapi import TryNext
11 12
12 13 ip = IPython.ipapi.get()
13 14 leo = ip.user_ns['leox']
@@ -73,6 +74,25 b' def eval_node(n):'
73 74 return xformer(rest, n)
74 75
75 76 class LeoNode(object, UserDict.DictMixin):
77 """ Node in Leo outline
78
79 Most important attributes (getters/setters available:
80 .v - evaluate node, can also be alligned
81 .b, .h - body string, headline string
82 .l - value as string list
83
84 Also supports iteration,
85
86 setitem / getitem (indexing):
87 wb.foo['key'] = 12
88 assert wb.foo['key'].v == 12
89
90 Note the asymmetry on setitem and getitem! Also other
91 dict methods are available.
92
93 .ipush() - run push-to-ipython
94
95 """
76 96 def __init__(self,p):
77 97 self.p = p.copy()
78 98
@@ -85,7 +105,7 b' class LeoNode(object, UserDict.DictMixin):'
85 105 finally:
86 106 c.endUpdate()
87 107
88 h = property( get_h, set_h)
108 h = property( get_h, set_h, doc = "Node headline string")
89 109
90 110 def get_b(self): return self.p.bodyString()
91 111 def set_b(self,val):
@@ -96,19 +116,21 b' class LeoNode(object, UserDict.DictMixin):'
96 116 finally:
97 117 c.endUpdate()
98 118
99 b = property(get_b, set_b)
119 b = property(get_b, set_b, doc = "Nody body string")
100 120
101 121 def set_val(self, val):
102 122 self.b = format_for_leo(val)
103 123
104 v = property(lambda self: eval_node(self), set_val)
124 v = property(lambda self: eval_node(self), set_val, doc = "Node evaluated value")
105 125
106 126 def set_l(self,val):
107 127 self.b = '\n'.join(val )
108 128 l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
109 set_l)
129 set_l, doc = "Node value as string list")
110 130
111 131 def __iter__(self):
132 """ Iterate through nodes direct children """
133
112 134 return (LeoNode(p) for p in self.p.children_iter())
113 135
114 136 def _children(self):
@@ -128,10 +150,26 b' class LeoNode(object, UserDict.DictMixin):'
128 150 d = self._children()
129 151 return d.keys()
130 152 def __getitem__(self, key):
153 """ wb.foo['Some stuff'] Return a child node with headline 'Some stuff'
154
155 If key is a valid python name (e.g. 'foo'), look for headline '@k foo' as well
156 """
131 157 key = str(key)
132 158 d = self._children()
133 159 return d[key]
134 160 def __setitem__(self, key, val):
161 """ You can do wb.foo['My Stuff'] = 12 to create children
162
163 This will create 'My Stuff' as a child of foo (if it does not exist), and
164 do .v = 12 assignment.
165
166 Exception:
167
168 wb.foo['bar'] = 12
169
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
172 """
135 173 key = str(key)
136 174 d = self._children()
137 175 if key in d:
@@ -146,6 +184,11 b' class LeoNode(object, UserDict.DictMixin):'
146 184 LeoNode(p).v = val
147 185 def __delitem__(self,key):
148 186 pass
187 def ipush(self):
188 """ Does push-to-ipython on the node """
189 push_from_leo(self)
190
191
149 192
150 193
151 194 class LeoWorkbook:
@@ -194,12 +237,18 b' def add_var(varname):'
194 237 def add_file(self,fname):
195 238 p2 = c.currentPosition().insertAfter()
196 239
197 def push_script(p):
240 push_from_leo = CommandChainDispatcher()
241
242 def expose_ileo_push(f, prio = 0):
243 push_from_leo.add(f, prio)
244
245 def push_ipython_script(node):
246 """ Execute the node body in IPython, as if it was entered in interactive prompt """
198 247 c.beginUpdate()
199 248 try:
200 249 ohist = ip.IP.output_hist
201 250 hstart = len(ip.IP.input_hist)
202 script = g.getScript(c,p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
251 script = g.getScript(c,node.p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
203 252
204 253 script = g.splitLines(script + '\n')
205 254
@@ -218,10 +267,12 b' def push_script(p):'
218 267 es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)))
219 268
220 269 if not has_output:
221 es('ipy run: %s (%d LL)' %( p.headString(),len(script)))
270 es('ipy run: %s (%d LL)' %( node.h,len(script)))
222 271 finally:
223 272 c.endUpdate()
224 273
274 # this should be the LAST one that will be executed, and it will never raise TryNext
275 expose_ileo_push(push_ipython_script, 1000)
225 276
226 277 def eval_body(body):
227 278 try:
@@ -231,35 +282,41 b' def eval_body(body):'
231 282 val = IPython.genutils.SList(body.splitlines())
232 283 return val
233 284
234 def push_plain_python(p):
235 script = g.getScript(c,p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
285 def push_plain_python(node):
286 if not node.h.endswith('P'):
287 raise TryNext
288 script = g.getScript(c,node.p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
236 289 lines = script.count('\n')
237 290 try:
238 291 exec script in ip.user_ns
239 292 except:
240 293 print " -- Exception in script:\n"+script + "\n --"
241 294 raise
242 es('ipy plain: %s (%d LL)' % (p.headString(),lines))
295 es('ipy plain: %s (%d LL)' % (node.h,lines))
296
297 expose_ileo_push(push_plain_python, 100)
298
299 def push_cl_node(node):
300 """ If node starts with @cl, eval it
301
302 The result is put to root @ipy-results node
303 """
304 if not node.b.startswith('@cl'):
305 raise TryNext
243 306
244 def push_from_leo(p):
245 nod = LeoNode(p)
246 h = p.headString()
247 if h.endswith('P'):
248 push_plain_python(p)
249 return
250 if nod.b.startswith('@cl'):
251 307 p2 = g.findNodeAnywhere(c,'@ipy-results')
308 val = node.v
252 309 if p2:
253 310 es("=> @ipy-results")
254 LeoNode(p2).v = nod.v
255 es(nod.v)
256 return
311 LeoNode(p2).v = val
312 es(val)
257 313
258 push_script(p)
259 return
314 expose_ileo_push(push_cl_node,100)
260 315
316 def push_position_from_leo(p):
317 push_from_leo(LeoNode(p))
261 318
262 ip.user_ns['leox'].push = push_from_leo
319 ip.user_ns['leox'].push = push_position_from_leo
263 320
264 321 def leo_f(self,s):
265 322 """ open file(s) in Leo
@@ -316,9 +373,7 b' def run_leo_startup_node():'
316 373 if p:
317 374 print "Running @ipy-startup nodes"
318 375 for n in LeoNode(p):
319 push_from_leo(n.p)
320
321
376 push_from_leo(n)
322 377
323 378 run_leo_startup_node()
324 379 show_welcome()
General Comments 0
You need to be logged in to leave comments. Login now