##// END OF EJS Templates
ipy_leo: rename wb..val => wb..v, %leo now opens a file in leo
vivainio -
Show More
@@ -1,215 +1,248 b''
1 """ Leo plugin for IPython
1 """ Leo plugin for IPython
2
2
3 Example use:
3 Example use:
4
4
5 nodes.foo = "hello world"
5 nodes.foo = "hello world"
6
6
7 -> create '@ipy foo' node with text "hello world"
7 -> create '@ipy foo' node with text "hello world"
8
8
9 Access works also, and so does tab completion.
9 Access works also, and so does tab completion.
10
10
11 """
11 """
12 import IPython.ipapi
12 import IPython.ipapi
13 import IPython.genutils
13 import IPython.genutils
14 import IPython.generics
14 import IPython.generics
15 import re
15 import re
16
16
17
17
18
18
19 ip = IPython.ipapi.get()
19 ip = IPython.ipapi.get()
20 leo = ip.user_ns['leox']
20 leo = ip.user_ns['leox']
21 c,g = leo.c, leo.g
21 c,g = leo.c, leo.g
22
22
23 # will probably be overwritten by user, but handy for experimentation early on
23 # will probably be overwritten by user, but handy for experimentation early on
24 ip.user_ns['c'] = c
24 ip.user_ns['c'] = c
25 ip.user_ns['g'] = g
25 ip.user_ns['g'] = g
26
26
27
27
28 from IPython.external.simplegeneric import generic
28 from IPython.external.simplegeneric import generic
29 import pprint
29 import pprint
30
30
31 @generic
31 @generic
32 def format_for_leo(obj):
32 def format_for_leo(obj):
33 """ Convert obj to string representiation (for editing in Leo)"""
33 """ Convert obj to string representiation (for editing in Leo)"""
34 return pprint.pformat(obj)
34 return pprint.pformat(obj)
35
35
36 @format_for_leo.when_type(list)
36 @format_for_leo.when_type(list)
37 def format_list(obj):
37 def format_list(obj):
38 return "\n".join(str(s) for s in obj)
38 return "\n".join(str(s) for s in obj)
39
39
40 nodename_re = r'(@ipy?[\w-]+)?\s?(\w+)'
40 nodename_re = r'(@ipy?[\w-]+)?\s?(\w+)'
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('@') and len(h.split()) == 1:
46 if h.startswith('@') and len(h.split()) == 1:
47 continue
47 continue
48 mo = re.match(nodename_re, h)
48 mo = re.match(nodename_re, h)
49 if not mo:
49 if not mo:
50 continue
50 continue
51 d[mo.group(2)] = p.copy()
51 d[mo.group(2)] = p.copy()
52 return d
52 return d
53
53
54
54
55 class TrivialLeoWorkbook:
55 class TrivialLeoWorkbook:
56 """ class to find cells """
56 """ class to find cells with simple syntax
57
58 """
57 def __getattr__(self, key):
59 def __getattr__(self, key):
58 cells = all_cells()
60 cells = all_cells()
59 p = cells[key]
61 p = cells[key]
60 body = p.bodyString()
62 body = p.bodyString()
61 return eval_body(body)
63 return eval_body(body)
62 def __setattr__(self,key,val):
64 def __setattr__(self,key,val):
63 cells = all_cells()
65 cells = all_cells()
64 p = cells.get(key,None)
66 p = cells.get(key,None)
65 if p is None:
67 if p is None:
66 add_var(key,val)
68 add_var(key,val)
67 else:
69 else:
68 c.setBodyString(p,format_for_leo(val))
70 c.setBodyString(p,format_for_leo(val))
69 def __str__(self):
71 def __str__(self):
70 return "<TrivialLeoWorkbook>"
72 return "<TrivialLeoWorkbook>"
71 __repr__ = __str__
73 __repr__ = __str__
72
74
73 ip.user_ns['nodes'] = TrivialLeoWorkbook()
75 ip.user_ns['nodes'] = TrivialLeoWorkbook()
74
76
75
77
76 class LeoNode(object):
78 class LeoNode(object):
77 def __init__(self,p):
79 def __init__(self,p):
78 self.p = p.copy()
80 self.p = p.copy()
79
81
80 def get_h(self): return self.p.headString()
82 def get_h(self): return self.p.headString()
81 def set_h(self,val):
83 def set_h(self,val):
82 print "set head",val
84 print "set head",val
83 c.setHeadString(self.p,val)
85 c.beginUpdate()
86 try:
87 c.setHeadString(self.p,val)
88 finally:
89 c.endUpdate()
84
90
85 h = property( get_h, set_h)
91 h = property( get_h, set_h)
86
92
87 def get_b(self): return self.p.bodyString()
93 def get_b(self): return self.p.bodyString()
88 def set_b(self,val):
94 def set_b(self,val):
89 print "set body",val
95 print "set body",val
90 c.setBodyString(self.p, val)
96 c.beginUpdate()
97 try:
98 c.setBodyString(self.p, val)
99 finally:
100 c.endUpdate()
91
101
92 b = property(get_b, set_b)
102 b = property(get_b, set_b)
93
103
94 def set_val(self, val):
104 def set_val(self, val):
95 self.b = pprint.pformat(val)
105 self.b = pprint.pformat(val)
96
106
97 val = property(lambda self: ip.ev(self.b.strip()), set_val)
107 v = property(lambda self: ip.ev(self.b.strip()), set_val)
98
108
99 def set_l(self,val):
109 def set_l(self,val):
100 self.b = '\n'.join(val )
110 self.b = '\n'.join(val )
101 l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
111 l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
102 set_l)
112 set_l)
103
113
104 def __iter__(self):
114 def __iter__(self):
105 return (LeoNode(p) for p in self.p.children_iter())
115 return (LeoNode(p) for p in self.p.children_iter())
106
116
107
117
108 class LeoWorkbook:
118 class LeoWorkbook:
109 """ class for 'advanced' node access """
119 """ class for 'advanced' node access """
110 def __getattr__(self, key):
120 def __getattr__(self, key):
111 if key.startswith('_') or key == 'trait_names':
121 if key.startswith('_') or key == 'trait_names':
112 raise AttributeError
122 raise AttributeError
113 cells = all_cells()
123 cells = all_cells()
114 p = cells.get(key, None)
124 p = cells.get(key, None)
115 if p is None:
125 if p is None:
116 p = add_var(key,None)
126 p = add_var(key,None)
117
127
118 return LeoNode(p)
128 return LeoNode(p)
119
129
120 def __str__(self):
130 def __str__(self):
121 return "<LeoWorkbook>"
131 return "<LeoWorkbook>"
122 __repr__ = __str__
132 __repr__ = __str__
123 ip.user_ns['wb'] = LeoWorkbook()
133 ip.user_ns['wb'] = LeoWorkbook()
124
134
125
135
126 _dummyval = object()
136 _dummyval = object()
127 @IPython.generics.complete_object.when_type(LeoWorkbook)
137 @IPython.generics.complete_object.when_type(LeoWorkbook)
128 def workbook_complete(obj, prev):
138 def workbook_complete(obj, prev):
129 return all_cells().keys()
139 return all_cells().keys()
130
140
131
141
132 def add_var(varname, value = _dummyval):
142 def add_var(varname, value = _dummyval):
133 nodename = '@ipy-var ' + varname
143 c.beginUpdate()
134 p2 = g.findNodeAnywhere(c,nodename)
144 try:
135 if not c.positionExists(p2):
136 p2 = c.currentPosition().insertAfter()
137 c.setHeadString(p2,'@ipy ' + varname)
138
145
139 c.setCurrentPosition(p2)
146 nodename = '@ipy-var ' + varname
140 if value is _dummyval:
147 p2 = g.findNodeAnywhere(c,nodename)
141 val = ip.user_ns[varname]
148 if not c.positionExists(p2):
142 else:
149 p2 = c.currentPosition().insertAfter()
143 val = value
150 c.setHeadString(p2,'@ipy ' + varname)
144 if val is not None:
151
145 formatted = format_for_leo(val)
152 c.setCurrentPosition(p2)
146 c.setBodyString(p2,formatted)
153 if value is _dummyval:
147 return p2
154 val = ip.user_ns[varname]
155 else:
156 val = value
157 if val is not None:
158 formatted = format_for_leo(val)
159 c.setBodyString(p2,formatted)
160 return p2
161 finally:
162 c.endUpdate()
148
163
149 def add_file(self,fname):
164 def add_file(self,fname):
150 p2 = c.currentPosition().insertAfter()
165 p2 = c.currentPosition().insertAfter()
151
166
152 def push_script(p):
167 def push_script(p):
153 ohist = ip.IP.output_hist
168 c.beginUpdate()
154 hstart = len(ip.IP.input_hist)
169 try:
155 script = g.getScript(c,p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
170 ohist = ip.IP.output_hist
156
171 hstart = len(ip.IP.input_hist)
157 script = g.splitLines(script + '\n')
172 script = g.getScript(c,p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
158 script = ''.join(z for z in script if z.strip())
173
159
174 script = g.splitLines(script + '\n')
160 ip.runlines(script)
175 script = ''.join(z for z in script if z.strip())
161
176
162 has_output = False
177 ip.runlines(script)
163 for idx in range(hstart,len(ip.IP.input_hist)):
178
164 val = ohist.get(idx,None)
179 has_output = False
165 if val is None:
180 for idx in range(hstart,len(ip.IP.input_hist)):
166 continue
181 val = ohist.get(idx,None)
167 has_output = True
182 if val is None:
168 inp = ip.IP.input_hist[idx]
183 continue
169 if inp.strip():
184 has_output = True
170 g.es('In: %s' % (inp[:40], ), tabName = 'IPython')
185 inp = ip.IP.input_hist[idx]
171
186 if inp.strip():
172 g.es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)), tabName = 'IPython')
187 g.es('In: %s' % (inp[:40], ), tabName = 'IPython')
173
188
174 if not has_output:
189 g.es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)), tabName = 'IPython')
175 g.es('ipy run: %s' %( p.headString(),), tabName = 'IPython')
190
191 if not has_output:
192 g.es('ipy run: %s' %( p.headString(),), tabName = 'IPython')
193 finally:
194 c.endUpdate()
176
195
177
196
178 def eval_body(body):
197 def eval_body(body):
179 try:
198 try:
180 val = ip.ev(body)
199 val = ip.ev(body)
181 except:
200 except:
182 # just use stringlist if it's not completely legal python expression
201 # just use stringlist if it's not completely legal python expression
183 val = IPython.genutils.SList(body.splitlines())
202 val = IPython.genutils.SList(body.splitlines())
184 return val
203 return val
185
204
186 def push_variable(p,varname):
205 def push_variable(p,varname):
187 body = p.bodyString()
206 body = p.bodyString()
188 val = eval_body(body.strip())
207 val = eval_body(body.strip())
189 ip.user_ns[varname] = val
208 ip.user_ns[varname] = val
190 g.es('ipy var: %s' % (varname,), tabName = "IPython")
209 g.es('ipy var: %s' % (varname,), tabName = "IPython")
191
210
192 def push_from_leo(p):
211 def push_from_leo(p):
193 # headstring without @ are just scripts
194 if not p.headString().startswith('@'):
195 push_script(p)
196 return
197 tup = p.headString().split(None,1)
212 tup = p.headString().split(None,1)
198 # @ipy foo is variable foo
213 # @ipy foo is variable foo
199 if len(tup) == 2 and tup[0] == '@ipy':
214 if len(tup) == 2 and tup[0] == '@ipy':
200 varname = tup[1]
215 varname = tup[1]
201 push_variable(p,varname)
216 push_variable(p,varname)
202 return
217 return
218
219 push_script(p)
220 return
221
203
222
204 ip.user_ns['leox'].push = push_from_leo
223 ip.user_ns['leox'].push = push_from_leo
205
224
206 def leo_f(self,s):
225 def leo_f(self,s):
207 ip = self.getapi()
226 """ open file(s) in Leo
208 s = s.strip()
227
209 if s in ip.user_ns:
228 Takes an mglob pattern, e.g. '%leo *.cpp' or %leo 'rec:*.cpp'
210 add_var(s)
229 """
211 elif os.path.isfile(s):
230 import os
212 # todo open file
231 from IPython.external import mglob
213 pass
232
233 files = mglob.expand(s)
234 c.beginUpdate()
235 try:
236 for fname in files:
237 p = g.findNodeAnywhere(c,'@auto ' + fname)
238 if not p:
239 p = c.currentPosition().insertAfter()
240
241 p.setHeadString('@auto ' + fname)
242 if os.path.isfile(fname):
243 c.setBodyString(p,open(fname).read())
244 c.selectPosition(p)
245 finally:
246 c.endUpdate()
214
247
215 ip.expose_magic('leo',leo_f)
248 ip.expose_magic('leo',leo_f)
General Comments 0
You need to be logged in to leave comments. Login now