##// END OF EJS Templates
_ip.runlines() is now much more liberal about indentation - it cleans up the scripts it gets
_ip.runlines() is now much more liberal about indentation - it cleans up the scripts it gets

File last commit:

r986:6fb1e123
r987:9c4e4577
Show More
ipy_leo.py
215 lines | 5.5 KiB | text/x-python | PythonLexer
""" Leo plugin for IPython
Example use:
nodes.foo = "hello world"
-> create '@ipy foo' node with text "hello world"
Access works also, and so does tab completion.
"""
import IPython.ipapi
import IPython.genutils
import IPython.generics
import re
ip = IPython.ipapi.get()
leo = ip.user_ns['leox']
c,g = leo.c, leo.g
# will probably be overwritten by user, but handy for experimentation early on
ip.user_ns['c'] = c
ip.user_ns['g'] = g
from IPython.external.simplegeneric import generic
import pprint
@generic
def format_for_leo(obj):
""" Convert obj to string representiation (for editing in Leo)"""
return pprint.pformat(obj)
@format_for_leo.when_type(list)
def format_list(obj):
return "\n".join(str(s) for s in obj)
nodename_re = r'(@ipy?[\w-]+)?\s?(\w+)'
def all_cells():
d = {}
for p in c.allNodes_iter():
h = p.headString()
if h.startswith('@') and len(h.split()) == 1:
continue
mo = re.match(nodename_re, h)
if not mo:
continue
d[mo.group(2)] = p.copy()
return d
class TrivialLeoWorkbook:
""" class to find cells """
def __getattr__(self, key):
cells = all_cells()
p = cells[key]
body = p.bodyString()
return eval_body(body)
def __setattr__(self,key,val):
cells = all_cells()
p = cells.get(key,None)
if p is None:
add_var(key,val)
else:
c.setBodyString(p,format_for_leo(val))
def __str__(self):
return "<TrivialLeoWorkbook>"
__repr__ = __str__
ip.user_ns['nodes'] = TrivialLeoWorkbook()
class LeoNode(object):
def __init__(self,p):
self.p = p.copy()
def get_h(self): return self.p.headString()
def set_h(self,val):
print "set head",val
c.setHeadString(self.p,val)
h = property( get_h, set_h)
def get_b(self): return self.p.bodyString()
def set_b(self,val):
print "set body",val
c.setBodyString(self.p, val)
b = property(get_b, set_b)
def set_val(self, val):
self.b = pprint.pformat(val)
val = property(lambda self: ip.ev(self.b.strip()), set_val)
def set_l(self,val):
self.b = '\n'.join(val )
l = property(lambda self : IPython.genutils.SList(self.b.splitlines()),
set_l)
def __iter__(self):
return (LeoNode(p) for p in self.p.children_iter())
class LeoWorkbook:
""" class for 'advanced' node access """
def __getattr__(self, key):
if key.startswith('_') or key == 'trait_names':
raise AttributeError
cells = all_cells()
p = cells.get(key, None)
if p is None:
p = add_var(key,None)
return LeoNode(p)
def __str__(self):
return "<LeoWorkbook>"
__repr__ = __str__
ip.user_ns['wb'] = LeoWorkbook()
_dummyval = object()
@IPython.generics.complete_object.when_type(LeoWorkbook)
def workbook_complete(obj, prev):
return all_cells().keys()
def add_var(varname, value = _dummyval):
nodename = '@ipy-var ' + varname
p2 = g.findNodeAnywhere(c,nodename)
if not c.positionExists(p2):
p2 = c.currentPosition().insertAfter()
c.setHeadString(p2,'@ipy ' + varname)
c.setCurrentPosition(p2)
if value is _dummyval:
val = ip.user_ns[varname]
else:
val = value
if val is not None:
formatted = format_for_leo(val)
c.setBodyString(p2,formatted)
return p2
def add_file(self,fname):
p2 = c.currentPosition().insertAfter()
def push_script(p):
ohist = ip.IP.output_hist
hstart = len(ip.IP.input_hist)
script = g.getScript(c,p,useSelectedText=False,forcePythonSentinels=False,useSentinels=False)
script = g.splitLines(script + '\n')
script = ''.join(z for z in script if z.strip())
ip.runlines(script)
has_output = False
for idx in range(hstart,len(ip.IP.input_hist)):
val = ohist.get(idx,None)
if val is None:
continue
has_output = True
inp = ip.IP.input_hist[idx]
if inp.strip():
g.es('In: %s' % (inp[:40], ), tabName = 'IPython')
g.es('<%d> %s' % (idx, pprint.pformat(ohist[idx],width = 40)), tabName = 'IPython')
if not has_output:
g.es('ipy run: %s' %( p.headString(),), tabName = 'IPython')
def eval_body(body):
try:
val = ip.ev(body)
except:
# just use stringlist if it's not completely legal python expression
val = IPython.genutils.SList(body.splitlines())
return val
def push_variable(p,varname):
body = p.bodyString()
val = eval_body(body.strip())
ip.user_ns[varname] = val
g.es('ipy var: %s' % (varname,), tabName = "IPython")
def push_from_leo(p):
# headstring without @ are just scripts
if not p.headString().startswith('@'):
push_script(p)
return
tup = p.headString().split(None,1)
# @ipy foo is variable foo
if len(tup) == 2 and tup[0] == '@ipy':
varname = tup[1]
push_variable(p,varname)
return
ip.user_ns['leox'].push = push_from_leo
def leo_f(self,s):
ip = self.getapi()
s = s.strip()
if s in ip.user_ns:
add_var(s)
elif os.path.isfile(s):
# todo open file
pass
ip.expose_magic('leo',leo_f)