##// END OF EJS Templates
ipy_leo: remove more @ipy stuff, use format_for_leo generic for LeoNode.v
Ville M. Vainio -
Show More
@@ -1,334 +1,332 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 import re
8 import re
9 import UserDict
9 import UserDict
10
10
11
11
12 ip = IPython.ipapi.get()
12 ip = IPython.ipapi.get()
13 leo = ip.user_ns['leox']
13 leo = ip.user_ns['leox']
14 c,g = leo.c, leo.g
14 c,g = leo.c, leo.g
15
15
16 # will probably be overwritten by user, but handy for experimentation early on
16 # will probably be overwritten by user, but handy for experimentation early on
17 ip.user_ns['c'] = c
17 ip.user_ns['c'] = c
18 ip.user_ns['g'] = g
18 ip.user_ns['g'] = g
19
19
20
20
21 from IPython.external.simplegeneric import generic
21 from IPython.external.simplegeneric import generic
22 import pprint
22 import pprint
23
23
24 def es(s):
24 def es(s):
25 g.es(s, tabName = 'IPython')
25 g.es(s, tabName = 'IPython')
26 pass
26 pass
27
27
28 @generic
28 @generic
29 def format_for_leo(obj):
29 def format_for_leo(obj):
30 """ Convert obj to string representiation (for editing in Leo)"""
30 """ Convert obj to string representiation (for editing in Leo)"""
31 return pprint.pformat(obj)
31 return pprint.pformat(obj)
32
32
33 @format_for_leo.when_type(list)
33 @format_for_leo.when_type(list)
34 def format_list(obj):
34 def format_list(obj):
35 return "\n".join(str(s) for s in obj)
35 return "\n".join(str(s) for s in obj)
36
36
37 attribute_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
37 attribute_re = re.compile('^[a-zA-Z_][a-zA-Z0-9_]*$')
38 def valid_attribute(s):
38 def valid_attribute(s):
39 return attribute_re.match(s)
39 return attribute_re.match(s)
40
40
41 def all_cells():
41 def all_cells():
42 d = {}
42 d = {}
43 for p in c.allNodes_iter():
43 for p in c.allNodes_iter():
44 h = p.headString()
44 h = p.headString()
45 if not valid_attribute(h):
45 if not valid_attribute(h):
46 continue
46 continue
47 d[h] = p.copy()
47 d[h] = p.copy()
48 return d
48 return d
49
49
50
50
51
51
52 def eval_node(n):
52 def eval_node(n):
53 body = n.b
53 body = n.b
54 if not body.startswith('@cl'):
54 if not body.startswith('@cl'):
55 # plain python repr node, just eval it
55 # plain python repr node, just eval it
56 return ip.ev(n.b)
56 return ip.ev(n.b)
57 # @cl nodes deserve special treatment - first eval the first line (minus cl), then use it to call the rest of body
57 # @cl nodes deserve special treatment - first eval the first line (minus cl), then use it to call the rest of body
58 first, rest = body.split('\n',1)
58 first, rest = body.split('\n',1)
59 tup = first.split(None, 1)
59 tup = first.split(None, 1)
60 # @cl alone SPECIAL USE-> dump var to user_ns
60 # @cl alone SPECIAL USE-> dump var to user_ns
61 if len(tup) == 1:
61 if len(tup) == 1:
62 val = ip.ev(rest)
62 val = ip.ev(rest)
63 ip.user_ns[n.h] = val
63 ip.user_ns[n.h] = val
64 es("%s = %s" % (n.h, repr(val)[:20] ))
64 es("%s = %s" % (n.h, repr(val)[:20] ))
65 return val
65 return val
66
66
67 cl, hd = tup
67 cl, hd = tup
68
68
69 xformer = ip.ev(hd.strip())
69 xformer = ip.ev(hd.strip())
70 es('Transform w/ %s' % repr(xformer))
70 es('Transform w/ %s' % repr(xformer))
71 return xformer(rest)
71 return xformer(rest)
72
72
73 class LeoNode(object, UserDict.DictMixin):
73 class LeoNode(object, UserDict.DictMixin):
74 def __init__(self,p):
74 def __init__(self,p):
75 self.p = p.copy()
75 self.p = p.copy()
76
76
77 def get_h(self): return self.p.headString()
77 def get_h(self): return self.p.headString()
78 def set_h(self,val):
78 def set_h(self,val):
79 print "set head",val
79 print "set head",val
80 c.beginUpdate()
80 c.beginUpdate()
81 try:
81 try:
82 c.setHeadString(self.p,val)
82 c.setHeadString(self.p,val)
83 finally:
83 finally:
84 c.endUpdate()
84 c.endUpdate()
85
85
86 h = property( get_h, set_h)
86 h = property( get_h, set_h)
87
87
88 def get_b(self): return self.p.bodyString()
88 def get_b(self): return self.p.bodyString()
89 def set_b(self,val):
89 def set_b(self,val):
90 print "set body",val
90 print "set body",val
91 c.beginUpdate()
91 c.beginUpdate()
92 try:
92 try:
93 c.setBodyString(self.p, val)
93 c.setBodyString(self.p, val)
94 finally:
94 finally:
95 c.endUpdate()
95 c.endUpdate()
96
96
97 b = property(get_b, set_b)
97 b = property(get_b, set_b)
98
98
99 def set_val(self, val):
99 def set_val(self, val):
100 self.b = pprint.pformat(val)
100 self.b = format_for_leo(val)
101
101
102 v = property(lambda self: eval_node(self), set_val)
102 v = property(lambda self: eval_node(self), set_val)
103
103
104 def set_l(self,val):
104 def set_l(self,val):
105 self.b = '\n'.join(val )
105 self.b = '\n'.join(val )
106 l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
106 l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
107 set_l)
107 set_l)
108
108
109 def __iter__(self):
109 def __iter__(self):
110 return (LeoNode(p) for p in self.p.children_iter())
110 return (LeoNode(p) for p in self.p.children_iter())
111
111
112 def _children(self):
112 def _children(self):
113 d = {}
113 d = {}
114 for child in self:
114 for child in self:
115 head = child.h
115 head = child.h
116 tup = head.split(None,1)
116 tup = head.split(None,1)
117 if len(tup) > 1 and tup[0] == '@k':
117 if len(tup) > 1 and tup[0] == '@k':
118 d[tup[1]] = child
118 d[tup[1]] = child
119 continue
119 continue
120
120
121 if not valid_attribute(head):
121 if not valid_attribute(head):
122 d[head] = child
122 d[head] = child
123 continue
123 continue
124 return d
124 return d
125 def keys(self):
125 def keys(self):
126 d = self._children()
126 d = self._children()
127 return d.keys()
127 return d.keys()
128 def __getitem__(self, key):
128 def __getitem__(self, key):
129 key = str(key)
129 key = str(key)
130 d = self._children()
130 d = self._children()
131 return d[key]
131 return d[key]
132 def __setitem__(self, key, val):
132 def __setitem__(self, key, val):
133 key = str(key)
133 key = str(key)
134 d = self._children()
134 d = self._children()
135 if key in d:
135 if key in d:
136 d[key].v = val
136 d[key].v = val
137 return
137 return
138
138
139 if not valid_attribute(key):
139 if not valid_attribute(key):
140 head = key
140 head = key
141 else:
141 else:
142 head = '@k ' + key
142 head = '@k ' + key
143 p = c.createLastChildNode(self.p, head, '')
143 p = c.createLastChildNode(self.p, head, '')
144 LeoNode(p).v = val
144 LeoNode(p).v = val
145 def __delitem__(self,key):
145 def __delitem__(self,key):
146 pass
146 pass
147
147
148
148
149 class LeoWorkbook:
149 class LeoWorkbook:
150 """ class for 'advanced' node access """
150 """ class for 'advanced' node access """
151 def __getattr__(self, key):
151 def __getattr__(self, key):
152 if key.startswith('_') or key == 'trait_names' or not valid_attribute(key):
152 if key.startswith('_') or key == 'trait_names' or not valid_attribute(key):
153 raise AttributeError
153 raise AttributeError
154 cells = all_cells()
154 cells = all_cells()
155 p = cells.get(key, None)
155 p = cells.get(key, None)
156 if p is None:
156 if p is None:
157 p = add_var(key,None)
157 p = add_var(key,None)
158
158
159 return LeoNode(p)
159 return LeoNode(p)
160
160
161 def __str__(self):
161 def __str__(self):
162 return "<LeoWorkbook>"
162 return "<LeoWorkbook>"
163 def __setattr__(self,key, val):
163 def __setattr__(self,key, val):
164 raise AttributeError("Direct assignment to workbook denied, try wb.%s.v = %s" % (key,val))
164 raise AttributeError("Direct assignment to workbook denied, try wb.%s.v = %s" % (key,val))
165
165
166 __repr__ = __str__
166 __repr__ = __str__
167 ip.user_ns['wb'] = LeoWorkbook()
167 ip.user_ns['wb'] = LeoWorkbook()
168
168
169
169
170 _dummyval = object()
170 _dummyval = object()
171 @IPython.generics.complete_object.when_type(LeoWorkbook)
171 @IPython.generics.complete_object.when_type(LeoWorkbook)
172 def workbook_complete(obj, prev):
172 def workbook_complete(obj, prev):
173 return all_cells().keys()
173 return all_cells().keys()
174
174
175
175
176 def add_var(varname, value = _dummyval):
176 def add_var(varname, value = _dummyval):
177 c.beginUpdate()
177 c.beginUpdate()
178 try:
178 try:
179
179 p2 = g.findNodeAnywhere(c,varname)
180 nodename = '@ipy-var ' + varname
181 p2 = g.findNodeAnywhere(c,nodename)
182 if not c.positionExists(p2):
180 if not c.positionExists(p2):
183 p2 = c.currentPosition().insertAfter()
181 p2 = c.currentPosition().insertAfter()
184 c.setHeadString(p2,'@ipy ' + varname)
182 c.setHeadString(p2,varname)
185
183
186 c.setCurrentPosition(p2)
184 c.setCurrentPosition(p2)
187 if value is _dummyval:
185 if value is _dummyval:
188 val = ip.user_ns[varname]
186 val = ip.user_ns[varname]
189 else:
187 else:
190 val = value
188 val = value
191 if val is not None:
189 if val is not None:
192 formatted = format_for_leo(val)
190 formatted = format_for_leo(val)
193 c.setBodyString(p2,formatted)
191 c.setBodyString(p2,formatted)
194 return p2
192 return p2
195 finally:
193 finally:
196 c.endUpdate()
194 c.endUpdate()
197
195
198 def add_file(self,fname):
196 def add_file(self,fname):
199 p2 = c.currentPosition().insertAfter()
197 p2 = c.currentPosition().insertAfter()
200
198
201 def push_script(p):
199 def push_script(p):
202 c.beginUpdate()
200 c.beginUpdate()
203 try:
201 try:
204 ohist = ip.IP.output_hist
202 ohist = ip.IP.output_hist
205 hstart = len(ip.IP.input_hist)
203 hstart = len(ip.IP.input_hist)
206 script = g.getScript(c,p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
204 script = g.getScript(c,p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
207
205
208 script = g.splitLines(script + '\n')
206 script = g.splitLines(script + '\n')
209 script = ''.join(z for z in script if z.strip())
207 script = ''.join(z for z in script if z.strip())
210
208
211 ip.runlines(script)
209 ip.runlines(script)
212
210
213 has_output = False
211 has_output = False
214 for idx in range(hstart,len(ip.IP.input_hist)):
212 for idx in range(hstart,len(ip.IP.input_hist)):
215 val = ohist.get(idx,None)
213 val = ohist.get(idx,None)
216 if val is None:
214 if val is None:
217 continue
215 continue
218 has_output = True
216 has_output = True
219 inp = ip.IP.input_hist[idx]
217 inp = ip.IP.input_hist[idx]
220 if inp.strip():
218 if inp.strip():
221 es('In: %s' % (inp[:40], ))
219 es('In: %s' % (inp[:40], ))
222
220
223 es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)))
221 es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)))
224
222
225 if not has_output:
223 if not has_output:
226 es('ipy run: %s' %( p.headString(),))
224 es('ipy run: %s' %( p.headString(),))
227 finally:
225 finally:
228 c.endUpdate()
226 c.endUpdate()
229
227
230
228
231 def eval_body(body):
229 def eval_body(body):
232 try:
230 try:
233 val = ip.ev(body)
231 val = ip.ev(body)
234 except:
232 except:
235 # just use stringlist if it's not completely legal python expression
233 # just use stringlist if it's not completely legal python expression
236 val = IPython.genutils.SList(body.splitlines())
234 val = IPython.genutils.SList(body.splitlines())
237 return val
235 return val
238
236
239 def push_variable(p,varname):
237 def push_variable(p,varname):
240 try:
238 try:
241 val = eval_node(LeoNode(p))
239 val = eval_node(LeoNode(p))
242 except:
240 except:
243
241
244 body = p.bodyString()
242 body = p.bodyString()
245 val = IPython.genutils.SList(body.splitlines())
243 val = IPython.genutils.SList(body.splitlines())
246
244
247 ip.user_ns[varname] = val
245 ip.user_ns[varname] = val
248 es('ipy var: %s' % (varname,))
246 es('ipy var: %s' % (varname,))
249
247
250 def push_plain_python(p):
248 def push_plain_python(p):
251 script = g.getScript(c,p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
249 script = g.getScript(c,p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
252 exec script in ip.user_ns
250 exec script in ip.user_ns
253 es('ipy plain: %s' % (p.headString(),))
251 es('ipy plain: %s' % (p.headString(),))
254
252
255 def push_from_leo(p):
253 def push_from_leo(p):
256 nod = LeoNode(p)
254 nod = LeoNode(p)
257 h = p.headString()
255 h = p.headString()
258 tup = h.split(None,1)
256 tup = h.split(None,1)
259 # @ipy foo is variable foo
257 # @ipy foo is variable foo
260 if len(tup) == 2 and tup[0] == '@ipy':
258 if len(tup) == 2 and tup[0] == '@ipy':
261 varname = tup[1]
259 varname = tup[1]
262 push_variable(p,varname)
260 push_variable(p,varname)
263 return
261 return
264 if h.endswith('P'):
262 if h.endswith('P'):
265 push_plain_python(p)
263 push_plain_python(p)
266 return
264 return
267 if nod.b.startswith('@cl'):
265 if nod.b.startswith('@cl'):
268 es(nod.v)
266 es(nod.v)
269 return
267 return
270
268
271 push_script(p)
269 push_script(p)
272 return
270 return
273
271
274
272
275 ip.user_ns['leox'].push = push_from_leo
273 ip.user_ns['leox'].push = push_from_leo
276
274
277 def leo_f(self,s):
275 def leo_f(self,s):
278 """ open file(s) in Leo
276 """ open file(s) in Leo
279
277
280 Takes an mglob pattern, e.g. '%leo *.cpp' or %leo 'rec:*.cpp'
278 Takes an mglob pattern, e.g. '%leo *.cpp' or %leo 'rec:*.cpp'
281 """
279 """
282 import os
280 import os
283 from IPython.external import mglob
281 from IPython.external import mglob
284
282
285 files = mglob.expand(s)
283 files = mglob.expand(s)
286 c.beginUpdate()
284 c.beginUpdate()
287 try:
285 try:
288 for fname in files:
286 for fname in files:
289 p = g.findNodeAnywhere(c,'@auto ' + fname)
287 p = g.findNodeAnywhere(c,'@auto ' + fname)
290 if not p:
288 if not p:
291 p = c.currentPosition().insertAfter()
289 p = c.currentPosition().insertAfter()
292
290
293 p.setHeadString('@auto ' + fname)
291 p.setHeadString('@auto ' + fname)
294 if os.path.isfile(fname):
292 if os.path.isfile(fname):
295 c.setBodyString(p,open(fname).read())
293 c.setBodyString(p,open(fname).read())
296 c.selectPosition(p)
294 c.selectPosition(p)
297 finally:
295 finally:
298 c.endUpdate()
296 c.endUpdate()
299
297
300 ip.expose_magic('leo',leo_f)
298 ip.expose_magic('leo',leo_f)
301
299
302 def leoref_f(self,s):
300 def leoref_f(self,s):
303 import textwrap
301 import textwrap
304 print textwrap.dedent("""\
302 print textwrap.dedent("""\
305 %leo file - open file in leo
303 %leo file - open file in leo
306 wb.foo.v - eval node foo (i.e. headstring is 'foo' or '@ipy foo')
304 wb.foo.v - eval node foo (i.e. headstring is 'foo' or '@ipy foo')
307 wb.foo.v = 12 - assign to body of node foo
305 wb.foo.v = 12 - assign to body of node foo
308 wb.foo.b - read or write the body of node foo
306 wb.foo.b - read or write the body of node foo
309 wb.foo.l - body of node foo as string list
307 wb.foo.l - body of node foo as string list
310
308
311 for el in wb.foo:
309 for el in wb.foo:
312 print el.v
310 print el.v
313
311
314 """
312 """
315 )
313 )
316 ip.expose_magic('leoref',leoref_f)
314 ip.expose_magic('leoref',leoref_f)
317
315
318 def show_welcome():
316 def show_welcome():
319 print "------------------"
317 print "------------------"
320 print "Welcome to Leo-enabled IPython session!"
318 print "Welcome to Leo-enabled IPython session!"
321 print "Try %leoref for quick reference."
319 print "Try %leoref for quick reference."
322 import IPython.platutils
320 import IPython.platutils
323 IPython.platutils.set_term_title('ILeo')
321 IPython.platutils.set_term_title('ILeo')
324 IPython.platutils.freeze_term_title()
322 IPython.platutils.freeze_term_title()
325
323
326 def run_leo_startup_node():
324 def run_leo_startup_node():
327 p = g.findNodeAnywhere(c,'@ipy-startup')
325 p = g.findNodeAnywhere(c,'@ipy-startup')
328 if p:
326 if p:
329 print "Running @ipy-startup"
327 print "Running @ipy-startup"
330 push_script(p)
328 push_script(p)
331
329
332 run_leo_startup_node()
330 run_leo_startup_node()
333 show_welcome()
331 show_welcome()
334
332
General Comments 0
You need to be logged in to leave comments. Login now