##// 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 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 import re
9 import re
9 import UserDict
10 import UserDict
10
11 from IPython.ipapi import TryNext
11
12
12 ip = IPython.ipapi.get()
13 ip = IPython.ipapi.get()
13 leo = ip.user_ns['leox']
14 leo = ip.user_ns['leox']
@@ -73,6 +74,25 b' def eval_node(n):'
73 return xformer(rest, n)
74 return xformer(rest, n)
74
75
75 class LeoNode(object, UserDict.DictMixin):
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 def __init__(self,p):
96 def __init__(self,p):
77 self.p = p.copy()
97 self.p = p.copy()
78
98
@@ -85,7 +105,7 b' class LeoNode(object, UserDict.DictMixin):'
85 finally:
105 finally:
86 c.endUpdate()
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 def get_b(self): return self.p.bodyString()
110 def get_b(self): return self.p.bodyString()
91 def set_b(self,val):
111 def set_b(self,val):
@@ -96,19 +116,21 b' class LeoNode(object, UserDict.DictMixin):'
96 finally:
116 finally:
97 c.endUpdate()
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 def set_val(self, val):
121 def set_val(self, val):
102 self.b = format_for_leo(val)
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 def set_l(self,val):
126 def set_l(self,val):
107 self.b = '\n'.join(val )
127 self.b = '\n'.join(val )
108 l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
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 def __iter__(self):
131 def __iter__(self):
132 """ Iterate through nodes direct children """
133
112 return (LeoNode(p) for p in self.p.children_iter())
134 return (LeoNode(p) for p in self.p.children_iter())
113
135
114 def _children(self):
136 def _children(self):
@@ -128,10 +150,26 b' class LeoNode(object, UserDict.DictMixin):'
128 d = self._children()
150 d = self._children()
129 return d.keys()
151 return d.keys()
130 def __getitem__(self, key):
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 key = str(key)
157 key = str(key)
132 d = self._children()
158 d = self._children()
133 return d[key]
159 return d[key]
134 def __setitem__(self, key, val):
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 key = str(key)
173 key = str(key)
136 d = self._children()
174 d = self._children()
137 if key in d:
175 if key in d:
@@ -146,6 +184,11 b' class LeoNode(object, UserDict.DictMixin):'
146 LeoNode(p).v = val
184 LeoNode(p).v = val
147 def __delitem__(self,key):
185 def __delitem__(self,key):
148 pass
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 class LeoWorkbook:
194 class LeoWorkbook:
@@ -194,12 +237,18 b' def add_var(varname):'
194 def add_file(self,fname):
237 def add_file(self,fname):
195 p2 = c.currentPosition().insertAfter()
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 c.beginUpdate()
247 c.beginUpdate()
199 try:
248 try:
200 ohist = ip.IP.output_hist
249 ohist = ip.IP.output_hist
201 hstart = len(ip.IP.input_hist)
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 script = g.splitLines(script + '\n')
253 script = g.splitLines(script + '\n')
205
254
@@ -218,10 +267,12 b' def push_script(p):'
218 es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)))
267 es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)))
219
268
220 if not has_output:
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 finally:
271 finally:
223 c.endUpdate()
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 def eval_body(body):
277 def eval_body(body):
227 try:
278 try:
@@ -231,35 +282,41 b' def eval_body(body):'
231 val = IPython.genutils.SList(body.splitlines())
282 val = IPython.genutils.SList(body.splitlines())
232 return val
283 return val
233
284
234 def push_plain_python(p):
285 def push_plain_python(node):
235 script = g.getScript(c,p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
286 if not node.h.endswith('P'):
287 raise TryNext
288 script = g.getScript(c,node.p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
236 lines = script.count('\n')
289 lines = script.count('\n')
237 try:
290 try:
238 exec script in ip.user_ns
291 exec script in ip.user_ns
239 except:
292 except:
240 print " -- Exception in script:\n"+script + "\n --"
293 print " -- Exception in script:\n"+script + "\n --"
241 raise
294 raise
242 es('ipy plain: %s (%d LL)' % (p.headString(),lines))
295 es('ipy plain: %s (%d LL)' % (node.h,lines))
243
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 p2 = g.findNodeAnywhere(c,'@ipy-results')
252 if p2:
253 es("=> @ipy-results")
254 LeoNode(p2).v = nod.v
255 es(nod.v)
256 return
257
296
258 push_script(p)
297 expose_ileo_push(push_plain_python, 100)
259 return
298
299 def push_cl_node(node):
300 """ If node starts with @cl, eval it
260
301
302 The result is put to root @ipy-results node
303 """
304 if not node.b.startswith('@cl'):
305 raise TryNext
306
307 p2 = g.findNodeAnywhere(c,'@ipy-results')
308 val = node.v
309 if p2:
310 es("=> @ipy-results")
311 LeoNode(p2).v = val
312 es(val)
313
314 expose_ileo_push(push_cl_node,100)
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 def leo_f(self,s):
321 def leo_f(self,s):
265 """ open file(s) in Leo
322 """ open file(s) in Leo
@@ -316,9 +373,7 b' def run_leo_startup_node():'
316 if p:
373 if p:
317 print "Running @ipy-startup nodes"
374 print "Running @ipy-startup nodes"
318 for n in LeoNode(p):
375 for n in LeoNode(p):
319 push_from_leo(n.p)
376 push_from_leo(n)
320
321
322
377
323 run_leo_startup_node()
378 run_leo_startup_node()
324 show_welcome()
379 show_welcome()
General Comments 0
You need to be logged in to leave comments. Login now