##// END OF EJS Templates
ipy_leo: LeoNode.go(), __iter__ for WorkBook
ipy_leo: LeoNode.go(), __iter__ for WorkBook

File last commit:

r1007:238f5904
r1008:2b738924
Show More
leo_bridge_demo.leo
409 lines | 13.5 KiB | text/plain | TextLexer
/ doc / examples / leo_bridge_demo.leo
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 <?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet ekr_test?>
<leo_file>
<leo_header file_format="2" tnodes="0" max_tnode_index="0" clone_windows="0"/>
<globals body_outline_ratio="0.5">
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 <global_window_position top="261" left="404" height="621" width="1280"/>
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 <global_log_window_position top="0" left="0" height="0" width="0"/>
</globals>
<preferences/>
<find_panel_settings/>
<vnodes>
<v t="vivainio.20080218184525"><vh>@chapters</vh></v>
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 <v t="vivainio.20080223133721" a="E"><vh>@settings</vh>
<v t="vivainio.20080223133721.1"><vh>@enabled-plugins</vh></v>
</v>
Ville M. Vainio
ipy_leo: @cl transform takes node ref in addition to body text
r998 <v t="vivainio.20080218184540" a="E"><vh>@ipy-startup</vh>
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 <v t="vivainio.20080218184613.1"><vh>b</vh></v>
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 <v t="vivainio.20080218200031" a="E"><vh>Some classes P</vh>
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 <v t="vivainio.20080218190816"><vh>File-like access</vh></v>
Ville M. Vainio
ipy_leo: '@ipy foo' like nodes can now contain @cl directive
r995 <v t="vivainio.20080218200106"><vh>csv data</vh></v>
Ville M. Vainio
ipy_leo: @cl transform takes node ref in addition to body text
r998 <v t="vivainio.20080219225120"><vh>String list</vh></v>
Ville M. Vainio
ipy_leo: @ipy-startup children are run in sequence, not ipy_startup itself
r999 <v t="vivainio.20080219230342"><vh>slist to leo</vh></v>
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 </v>
</v>
Ville M. Vainio
ipy_leo: @cl transform takes node ref in addition to body text
r998 <v t="vivainio.20080218195413"><vh>Class tests</vh>
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 <v t="vivainio.20080218200509"><vh>csvr</vh></v>
<v t="vivainio.20080218191007"><vh>tempfile</vh></v>
<v t="vivainio.20080218195413.1"><vh>rfile</vh></v>
Ville M. Vainio
ipy_leo: @cl transform takes node ref in addition to body text
r998 <v t="vivainio.20080219225804"><vh>strlist</vh></v>
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 </v>
Ville M. Vainio
ipy_leo: @ipy-startup children are run in sequence, not ipy_startup itself
r999 <v t="vivainio.20080218201219"><vh>Direct variables</vh>
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 <v t="vivainio.20080222201226"><vh>NewHeadline</vh></v>
<v t="vivainio.20080218201219.2"><vh>bar</vh></v>
Ville M. Vainio
ipy_leo: '@ipy foo' like nodes can now contain @cl directive
r995 </v>
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 <v t="vivainio.20080222193236" a="E"><vh>Docs</vh>
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 <v t="vivainio.20080223121915" a="E" tnodeList="vivainio.20080223121915,vivainio.20080222193236.1,vivainio.20080223133858,vivainio.20080223133922,vivainio.20080223133947,vivainio.20080223134018,vivainio.20080223134100,vivainio.20080223134118,vivainio.20080223134433,vivainio.20080223134136"><vh>@nosent ileointro.txt</vh>
<v t="vivainio.20080222193236.1" a="E"><vh>Quick intro</vh>
<v t="vivainio.20080223133858"><vh>Introduction</vh></v>
<v t="vivainio.20080223133922"><vh>Installation</vh></v>
<v t="vivainio.20080223133947"><vh>Accessing IPython from Leo</vh></v>
<v t="vivainio.20080223134018"><vh>Accessing Leo nodes from IPython</vh></v>
<v t="vivainio.20080223134100"><vh>Cl definitions</vh></v>
<v t="vivainio.20080223134118"><vh>Special node types</vh></v>
<v t="vivainio.20080223134433" a="TV"><vh>Custom push</vh></v>
<v t="vivainio.20080223134136"><vh>Acknowledgements and history</vh></v>
</v>
</v>
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 </v>
<v t="vivainio.20080222202211"><vh>test stuff</vh></v>
<v t="vivainio.20080222202211.1"><vh>spam</vh></v>
<v t="vivainio.20080222202211.2"><vh>NewHeadline</vh></v>
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 </vnodes>
<tnodes>
Ville M. Vainio
ipy_leo: '@ipy foo' like nodes can now contain @cl directive
r995 <t tx="vivainio.20080218184525">?</t>
Ville M. Vainio
ipy_leo: @ipy-startup children are run in sequence, not ipy_startup itself
r999 <t tx="vivainio.20080218184540">?Direct children of this node will be pushed at ipython bridge startup
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994
Ville M. Vainio
ipy_leo: @ipy-startup children are run in sequence, not ipy_startup itself
r999 This node itself will *not* be pushed</t>
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 <t tx="vivainio.20080218184613.1">print "world"</t>
Ville M. Vainio
ipy_leo: @cl transform takes node ref in addition to body text
r998 <t tx="vivainio.20080218190816">def rfile(body,n):
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 """ @cl rfile
produces a StringIO (file like obj of the rest of the body) """
import StringIO
return StringIO.StringIO(body)
Ville M. Vainio
ipy_leo: @cl transform takes node ref in addition to body text
r998 def tmpfile(body,n):
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 """ @cl tmpfile
Produces a temporary file, with node body as contents
"""
import tempfile
h, fname = tempfile.mkstemp()
f = open(fname,'w')
f.write(body)
f.close()
return fname
</t>
<t tx="vivainio.20080218191007">@cl tmpfile
Hello</t>
Ville M. Vainio
deprecated @ipy header prefix, use @cl alone as first body line instead...
r996 <t tx="vivainio.20080218195413">?</t>
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 <t tx="vivainio.20080218195413.1">@cl rfile
These
lines
should
be
readable </t>
Ville M. Vainio
ipy_leo: @ipy-startup children are run in sequence, not ipy_startup itself
r999 <t tx="vivainio.20080218200031">@others</t>
Ville M. Vainio
ipy_leo: @cl transform takes node ref in addition to body text
r998 <t tx="vivainio.20080218200106">def csvdata(body,n):
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 import csv
d = csv.Sniffer().sniff(body)
reader = csv.reader(body.splitlines(), dialect = d)
return reader</t>
<t tx="vivainio.20080218200509">@cl csvdata
a,b,b
1,2,2</t>
Ville M. Vainio
ipy_leo: '@ipy foo' like nodes can now contain @cl directive
r995 <t tx="vivainio.20080218201219"></t>
Ville M. Vainio
ipy_leo: @cl transform takes node ref in addition to body text
r998 <t tx="vivainio.20080218201219.2">@cl
"hello world"</t>
<t tx="vivainio.20080219225120">import IPython.genutils
def slist(body,n):
return IPython.genutils.SList(body.splitlines())
</t>
<t tx="vivainio.20080219225804">@cl slist
hello
world
on
many
lines
</t>
Ville M. Vainio
ipy_leo: @ipy-startup children are run in sequence, not ipy_startup itself
r999 <t tx="vivainio.20080219230342">import ipy_leo
@ipy_leo.format_for_leo.when_type(IPython.genutils.SList)
Ville M. Vainio
ipy_leo: @cl transform takes node ref in addition to body text
r998 def format_slist(obj):
return "@cl slist\n" + obj.n
</t>
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 <t tx="vivainio.20080222193236"></t>
<t tx="vivainio.20080222193236.1">@wrap
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 @nocolor</t>
<t tx="vivainio.20080222201226">1+2
print "hello"
3+4
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 def f(x):
return x.upper()
f('hello world')</t>
<t tx="vivainio.20080222202211"></t>
<t tx="vivainio.20080222202211.1">@cl rfile
hello
world
and whatever</t>
<t tx="vivainio.20080222202211.2"></t>
<t tx="vivainio.20080223121915">@others
</t>
<t tx="vivainio.20080223133721"></t>
<t tx="vivainio.20080223133721.1">ipython.py</t>
<t tx="vivainio.20080223133858">
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 Introduction
============
The purpose of ILeo, or leo-ipython bridge, is being a two-way communication
channel between Leo and IPython. The level of integration is much deeper than
conventional integration in IDEs; most notably, you are able to store *data* in
Leo nodes, in addition to mere program code. The possibilities of this are
endless, and this degree of integration has not been seen previously in the python
world.
IPython users are accustomed to using things like %edit to produce non-trivial
functions/classes (i.e. something that they don't want to enter directly on the
interactive prompt, but creating a proper script/module involves too much
overhead). In ILeo, this task consists just going to the Leo window, creating a node
and writing the code there, and pressing alt+I (push-to-ipython).
Obviously, you can save the Leo document as usual - this is a great advantage
of ILeo over using %edit, you can save your experimental scripts all at one
time, without having to organize them into script/module files (before you
really want to, of course!)
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 </t>
<t tx="vivainio.20080223133922">
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 Installation
============
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 You need at least Leo 4.4.7, and the development version of IPython (ILeo
will be incorporated to IPython 0.8.3).
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005
You can get IPython from Launchpad by installing bzr and doing
bzr branch lp:ipython
and running "setup.py install".
You need to enable the 'ipython.py' plugin in Leo:
- Help -&gt; Open LeoSettings.leo
- Edit @settings--&gt;Plugins--&gt;@enabled-plugins, add/uncomment 'ipython.py'
- Restart Leo. Be sure that you have the console window open (start leo.py from console, or double-click leo.py on windows)
- Press alt+5 OR alt-x start-ipython to launch IPython in the console that
started leo. You can start entering IPython commands normally, and Leo will keep
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 running at the same time.
</t>
<t tx="vivainio.20080223133947">
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 Accessing IPython from Leo
==========================
IPython code
------------
Just enter IPython commands on a Leo node and press alt-I to execute
push-to-ipython to execute the script in IPython. 'commands' is interpreted
loosely here - you can enter function and class definitions, in addition to the
things you would usually enter at IPython prompt - calculations, system commands etc.
Everything that would be legal to enter on IPython prompt is legal to execute
from ILeo.
Results will be shows in Leo log window for convenience, in addition to the console.
Suppose that a node had the following contents:
{{{
1+2
print "hello"
3+4
def f(x):
return x.upper()
f('hello world')
}}}
If you press alt+I on that done, you will see the following in Leo log window (IPython tab):
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 {{{
In: 1+2
&lt;2&gt; 3
In: 3+4
&lt;4&gt; 7
In: f('hello world')
&lt;6&gt; 'HELLO WORLD'
}}}
(numbers like &lt;6&gt; mean IPython output history indices).
Plain Python code
-----------------
If the headline of the node ends with capital P, alt-I will not run the code
through IPython translation mechanism but use the direct python 'exec' statement
(in IPython user namespace) to execute the code. It wont be shown in IPython
history, and sometimes it is safer (and more efficient) to execute things as
plain Python statements. Large class definitions are good candidates for P
nodes.
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 </t>
<t tx="vivainio.20080223134018">
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 Accessing Leo nodes from IPython
================================
The real fun starts when you start entering text to leo nodes, and are using
that as data (input/output) for your IPython work.
Accessing Leo nodes happens through the variable 'wb' (short for "WorkBook")
that exist in the IPython user namespace. Nodes that are directly accessible are
the ones that have simple names which could also be Python variable names;
'foo_1' will be accessible directly from IPython, whereas 'my scripts' will not.
If you want to access a node with arbitrary headline, add a child node '@a foo'
(@a stands for 'anchor'). Then, the parent of '@a foo' is accessible through
'wb.foo'.
You can see what nodes are accessible be entering (in IPython) wb.&lt;TAB&gt;. Example:
[C:leo/src]|12&gt; wb.
wb.b wb.tempfile wb.rfile wb.NewHeadline
wb.bar wb.Docs wb.strlist wb.csvr
Suppose that we had a node with headline 'spam' and body:
['12',2222+32]
we can access it from IPython (or from scripts entered into other Leo nodes!) by doing:
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 C:leo/src]|19&gt; wb.spam.v
&lt;19&gt; ['12', 2254]
'v' attribute stands for 'value', which means the node contents will be run
through 'eval' and everything you would be able to enter into IPython prompt
will be converted to objects. This mechanism can be extended far beyond direct
evaluation (see '@cl definitions').
'v' attribute also has a setter, i.e. you can do:
wb.spam.v = "mystring"
Which will result in the node 'spam' having the following text:
'mystring'
What assignment to 'v' does can be configured through generic functions
(simplegeneric module, will be explained later).
Besides v, you can set the body text directly through wb.spam.b =
"some\nstring", headline by wb.spam.h = 'new_headline' (obviously you must
access the node through wb.new_headline from that point onwards), and access the
contents as string list (IPython SList) through 'wb.spam.l'.
If you do 'wb.foo.v = 12' when node named 'foo' does not exist, the node titled
'foo' will be automatically created and assigned body 12.
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 </t>
<t tx="vivainio.20080223134100">
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 @cl definitions
===============
If the first line in the body text is of the form '@cl sometext', IPython will
will evaluate 'sometext' and call the result with the rest of the body when you
do 'wb.foo.v'. An example is in place here. Suppose that we have defined a class
(I use the term class in a non-python sense here)
{{{
def rfile(body,n):
""" @cl rfile
produces a StringIO (file like obj) of the rest of the body """
import StringIO
return StringIO.StringIO(body)
}}}
Now, let's say you node 'spam' with text
{{{
@cl rfile
hello
world
and whatever
}}}
Now, on IPython, we can do this:
{{{
[C:leo/src]|22&gt; f = wb.spam.v
[C:leo/src]|23&gt; f
&lt;23&gt; &lt;StringIO.StringIO instance at 0x04E7E490&gt;
[C:leo/src]|24&gt; f.readline()
&lt;24&gt; u'hello\n'
[C:leo/src]|25&gt; f.readline()
&lt;25&gt; u'world\n'
[C:leo/src]|26&gt; f.readline()
&lt;26&gt; u'and whatever'
[C:leo/src]|27&gt; f.readline()
&lt;27&gt; u''
}}}
You should declare new @cl types to make ILeo as convenient your problem domain as possible. For example, a "@cl etree" could return the elementtree object for xml content, or
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 </t>
<t tx="vivainio.20080223134118">
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 Special node types
==================
@ipy-startup
------------
If this node exist, the *direct children* of this will be pushed to IPython when
ILeo is started (you press alt+5). Use it to push your own @cl definitions etc.
The contents of of the node itself will be ignored.
@ipy-results
------------
When you create a new node (wb.foo.v = 'stuff'), the node foo will be created as
a child of this node. If @ipy-results does not exist, the new node will be created after the currently selected node.
@a nodes
--------
You can attach these as children of existing nodes to provide a way to access
nodes with arbitrary headlines, or to provide aliases to other nodes. If
multiple @a nodes are attached as children of a node, all the names can be used
to access the same object.
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 </t>
<t tx="vivainio.20080223134136">
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 Acknowledgements &amp; History
==========================
This idea got started when I (Ville) saw this post by Edward Ream (the author of
Leo) on IPython developer mailing list:
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 http://lists.ipython.scipy.org/pipermail/ipython-dev/2008-January/003551.html
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005 I was using FreeMind as mind mapping software, and so I had an immediate use
case for Leo (which, incidentally, is superior to FreeMind as mind mapper). The
wheels started rolling, I got obsessed with the power of this concept
(everything clicked together), and Edwards excitement paralleled mine.
Everything was mind-bogglingly easy/trivial, something that is typical of all
revolutionary technologies (think Python here).
The discussion that "built" ILeo is here:
http://sourceforge.net/forum/forum.php?thread_id=1911662&amp;forum_id=10226
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 ?</t>
<t tx="vivainio.20080223134433">
Declaring custom push-to-ipython handlers
=========================================
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 Sometimes, you might want to configure what alt+I on a node does. You can do
that by creating your own push function and expose it using
ipy_leo.expose_ileo_push(f, priority). The function should check whether the
node should by handled by it and raise IPython.ipapi.TryNext if it will not do
the handling.
Ville M. Vainio
add quick intro to leo_bridge_demo
r1005
Ville M. Vainio
ipy_leo: improved ipy_leo docs
r1007 This would print an uppercase version of node body if the node headline ends
with U (yes, this is completely useless!)
def push_upcase(node):
if not node.h.endswith('U'):
raise TryNext
print node.b.upper()
expose_ileo_push(push_upcase, 12)
(the priority should be between 0-100 - typically, you don't need to care about
it and can omit the argument altogether)
</t>
Ville M. Vainio
add leo_bridge_demo example, add @cl (data class) support (e.g. @cl csvdata, @cl tmpfile, @cl rfile)
r994 </tnodes>
</leo_file>