Re: Code Academy: find by predicate or attribute

2016-02-26 Thread Richard Andersen
I had a minor cut/paste syntax error...

hasOpenTask(p) 

... instead of ...

isOpenTask(p)

... but resolved it, and it is working now.It creates the list.

In my case, I put tasks under a parent node, which is usually either myself 
or another person.Showing the parents, but only the parents with tasks 
and only the tasks with parents, is what I'm striving for.

The power of clones is becoming more evident as I continue to refine these 
searches.Thanks again!

On Friday, February 26, 2016 at 9:19:23 AM UTC-8, Edward K. Ream wrote:
>
>
>
> On Fri, Feb 26, 2016 at 9:49 AM, Richard Andersen  > wrote:
>
>> Thank you very much, Edward.
>>
>> I have the code working now.It is finding all my nodes, so I'll see 
>> if I can figure out what further changes will limit the result set to just 
>> those with open and todo tags.
>>
>
> ​Huh?  Didn't this do it?
>
> def isOpenTask(p):
> tags = tc.get_tags(p)
> return 'open' in tags and 'todo' in tags
>
> ​
>  
> ​EKR
>

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Code Academy: find by predicate or attribute

2016-02-26 Thread Edward K. Ream
On Fri, Feb 26, 2016 at 9:49 AM, Richard Andersen 
wrote:

> Thank you very much, Edward.
>
> I have the code working now.It is finding all my nodes, so I'll see if
> I can figure out what further changes will limit the result set to just
> those with open and todo tags.
>

​Huh?  Didn't this do it?

def isOpenTask(p):
tags = tc.get_tags(p)
return 'open' in tags and 'todo' in tags

​

​EKR

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Code Academy: find by predicate or attribute

2016-02-26 Thread Edward K. Ream
On Fri, Feb 26, 2016 at 9:23 AM, 'Terry Brown' via leo-editor <
leo-editor@googlegroups.com> wrote:

Sorry to bring up the "inadmissible" ;-) solutions again, but todo.py
> includes icons, of course, and a "go to next todo node" which seems to
> cover similar ground to the finding nodes which have open / todo tags.
>

​Yes. todo.py has been in my thoughts. I think it points the way to a new
direction for Leo: more visible attributes.

In my last post I implied that nodetags.py might make tags visible via
icons. Still true, but an optional 'icon' keyword argument to
c.cloneFindByPredicate is just too good to pass up.  I'll do it today if I
can.

>
> To digress (the real point of my response is the next para :-) I have
> scripts which search across a long list of .leo files for open todo items
> (using leosax for speed), and generate flattened lists (views) of the same
> in various orders.


​They can now use c.cloneFindByPredicate.
​


> Further, UNLs pointing into the (possibly unloaded) leo file containing
> the real todo node are stored on the shadow todo items in the collected
> lists and changes to attributes trigger loading of the target file and
> change of the corresponding attribute on the real todo node.


​Cool.
​


> Still think the "declutter" machinery might work for this - basically it
> applies "beyond stylesheet" style / visualization changes to nodes,
> currently it uses rules like this:
>
> # remove @clean etc. and use an icon
> RULE ^@clean (.*)
> REPLACE \1
> ICON file_icons/file_clean.png
> RULE ^@auto (.*)
> REPLACE \1
> ICON file_icons/file_auto.png
>

​I think we may be converging on something really cool.​


​> ​
So all it needs is a different sort of RULE that looks into p.v.u, maybe a
also variant that deals
​ ​
specifically with tags, seeing I'm guessing any generic rule for getting
into p.v.u['path']['morepath']['list_of_strings'], which worth having, may
be cumbersome of the specific case of tag driven icons.

​I don't ​have time to follow this in detail, but it's clear that p.v.u can
handle whatever data we want to store.

c.cloneFindByPredicate is only one way of creating "views". Otoh, I suspect
that your RULE's are equivalent to predicate, perhaps more dynamic. I am
quite sure that we are about to get something spectacular.  Good work,
Terry, Richard and all of us.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Code Academy: find by predicate or attribute

2016-02-26 Thread Richard Andersen
Thank you very much, Edward.

I have the code working now.It is finding all my nodes, so I'll see if 
I can figure out what further changes will limit the result set to just 
those with open and todo tags.

-Richard

On Friday, February 26, 2016 at 6:47:29 AM UTC-8, Edward K. Ream wrote:
>
> On Friday, February 26, 2016 at 6:42:34 AM UTC-6, Edward K. Ream wrote:
>
> > On Thu, Feb 25, 2016 at 6:42 PM, Richard Andersen  > wrote:
>
> >> ​I'd like...to use the Clone Find All Flattened command to find all my 
> Nodes which are "open tasks"...Ideally, these would be shown in context 
> with the parent tags down to the "found" tags
>
> > An interesting problem.  It just needs a different predicate. Here is 
> tested code:
> [snip]
> >I'm not sure this is all that useful, but it's what you *said* you 
> wanted...
>
> On second thought, I think the solution is fine, *provided* that there is 
> a *visual* indication of which nodes actually have 'open' and 'todo' 
> tags.  This is easy to do: the nodetags plugin simply needs to attach 
> distinct icons for each tag. That way all you have to do is to expand all 
> the nodes provided by the cloneFindByPredicate. Easy, straightforward.
>
> In short, we urgently need ways to attach icons to tags (or any other 
> attribute). Once we have that, the user can find the desired nodes either 
> by looking through the outline or by looking at the nodes provided by 
> cloneFindByPredicate.
>
> Edward
>

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Code Academy: find by predicate or attribute

2016-02-26 Thread 'Terry Brown' via leo-editor


>
> From: Edward K. Ream 
>To: leo-editor  
>Sent: Friday, February 26, 2016 8:47 AM
>Subject: Re: Code Academy: find by predicate or attribute
> 
>On Friday, February 26, 2016 at 6:42:34 AM UTC-6, Edward K. Ream wrote:
>
>> On Thu, Feb 25, 2016 at 6:42 PM, Richard Andersen  wrote:
>
>>> ​I'd like...to use the Clone Find All Flattened command to find all my 
>>> Nodes which are "open tasks"...Ideally, these would be shown in context 
>>> with the parent tags down to the "found" tags
>
>> An interesting problem.  It just needs a different predicate. Here is tested 
>> code:
>[snip]
>>I'm not sure this is all that useful, but it's what you said you wanted...
>
>On second thought, I think the solution is fine, provided that there is a 
>visual indication of which nodes actually have 'open' and 'todo' tags.  This 
>is easy to do: the nodetags plugin simply needs to attach distinct icons for 
>each tag. That way all you have to do is to expand all the nodes provided by 
>the cloneFindByPredicate. Easy, straightforward.


Sorry to bring up the "inadmissible" ;-) solutions again, but todo.py includes 
icons, of course, and a "go to next todo node" which seems to cover similar 
ground to the finding nodes which have open / todo tags.

To digress (the real point of my response is the next para :-) I have scripts 
which search across a long list of .leo files for open todo items (using leosax 
for speed), and generate flattened lists (views) of the same in various orders. 
Further, UNLs pointing into the (possibly unloaded) leo file containing the 
real todo node are stored on the shadow todo items in the collected lists and 
changes to attributes trigger loading of the target file and change of the 
corresponding attribute on the real todo node. Obviously limited point going on 
about all this unreleased kind of messy code - I guess part of the reason for 
not trying to package it up is that I suspect people attracted to Leo are 
inclined to want to homebrew there own take on the perfect task management 
system... anyway, just some approaches that have worked for me.
>In short, we urgently need ways to attach icons to tags (or any other 
>attribute). Once we have that, the user can find the desired nodes either by 
>looking through the outline or by looking at the nodes provided by 
>cloneFindByPredicate.


Still think the "declutter" machinery might work for this - basically it 
applies "beyond stylesheet" style / visualization changes to nodes, currently 
it uses rules like this:

# remove @clean etc. and use an icon 
RULE ^@clean (.*) 
REPLACE \1 
ICON file_icons/file_clean.png 
RULE ^@auto (.*) 
REPLACE \1 
ICON file_icons/file_auto.png 

...

# if the node name starts with 'peacock node DEMO', make a mess of it 
RULE ^(peacock node DEMO) 
REPLACE LOOK: \1 
ICON Tango/16x16/emotes/face-grin.png 
ICON Tango/16x16/emotes/face-wink.png 
FG @solarized-magenta 
BG white 
FONT Times 
PX 40 
ITALIC 1 
WEIGHT Bold 


So all it needs is a different sort of RULE that looks into p.v.u, maybe a also 
variant that deals
specifically with tags, seeing I'm guessing any generic rule for getting into 
p.v.u['path']['morepath']['list_of_strings'], which worth having, may be 
cumbersome of the specific case of tag driven icons.

Cheers -Terry

>Edward
>
>
-- 
>You received this message because you are subscribed to the Google Groups 
>"leo-editor" group.
>To unsubscribe from this group and stop receiving emails from it, send an 
>email to leo-editor+unsubscr...@googlegroups.com.
>To post to this group, send email to leo-editor@googlegroups.com.
>Visit this group at https://groups.google.com/group/leo-editor.
>For more options, visit https://groups.google.com/d/optout.
>
>
>

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Code Academy: find by predicate or attribute

2016-02-26 Thread Edward K. Ream
On Friday, February 26, 2016 at 6:42:34 AM UTC-6, Edward K. Ream wrote:

> On Thu, Feb 25, 2016 at 6:42 PM, Richard Andersen  
wrote:

>> ​I'd like...to use the Clone Find All Flattened command to find all my 
Nodes which are "open tasks"...Ideally, these would be shown in context 
with the parent tags down to the "found" tags

> An interesting problem.  It just needs a different predicate. Here is 
tested code:
[snip]
>I'm not sure this is all that useful, but it's what you *said* you 
wanted...

On second thought, I think the solution is fine, *provided* that there is a 
*visual* indication of which nodes actually have 'open' and 'todo' tags.  
This is easy to do: the nodetags plugin simply needs to attach distinct 
icons for each tag. That way all you have to do is to expand all the nodes 
provided by the cloneFindByPredicate. Easy, straightforward.

In short, we urgently need ways to attach icons to tags (or any other 
attribute). Once we have that, the user can find the desired nodes either 
by looking through the outline or by looking at the nodes provided by 
cloneFindByPredicate.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Code Academy: find by predicate or attribute

2016-02-26 Thread Edward K. Ream
On Fri, Feb 26, 2016 at 6:42 AM, Edward K. Ream  wrote:

​Oops. hasOpenTask misuses the else clause after a for loop.  There is no
break statement, so it should be this:

def hasOpenTask(p):
> '''Return True if p is a top-level node containing any open task.'''
> if p.parent():
> return False # Not a top-level node.
> for p2 in p.self_and_subtree():
> tags = tc.get_tags(p2)
> if 'open' in tags and 'todo' in tags:
> return True
> # p, the ultimate parent, has an open task within.
> return False
>

​EKR​

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Code Academy: find by predicate or attribute

2016-02-26 Thread Edward K. Ream
On Thu, Feb 25, 2016 at 6:42 PM, Richard Andersen 
wrote:

​> ​
What I'd like to do next is to use the Clone Find All Flattened command to
find all my Nodes which are "open tasks"
​...

​Use c.cloneFindByPredicate. Like this (tested code):

tc = c.theTagController

def isOpenTask(p):
tags = tc.get_tags(p)
return 'open' in tags and 'todo' in tags

c.cloneFindByPredicate(
generator = c.all_unique_positions,
predicate = isOpenTask,
flatten = True,
undoType = 'clone-open-tasks',
)

​> ​
Ideally, these would be shown in context with the parent tags down to the
"found" tags
​.​


​An interesting problem.  It just needs a different predicate. Here is
tested code:

tc = c.theTagController

def hasOpenTask(p):
'''Return True if p is a top-level node containing any open task.'''
if p.parent():
return False # Not a top-level node.
for p2 in p.self_and_subtree():
tags = tc.get_tags(p2)
if 'open' in tags and 'todo' in tags:
return True
# p, the ultimate parent, has an open task within.
else:
return False

c.cloneFindByPredicate(
generator = c.all_unique_positions,
predicate = hasOpenTask,
flatten = True,
undoType = 'clone-trees-with-open-tasks',
)

​I'm not sure this is all that useful, but it's what you *said* you wanted,
hehe.

In any case, I hope this convinces you that predicates rock.

Edward​

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Code Academy: find by predicate or attribute

2016-02-26 Thread Edward K. Ream
On Thu, Feb 25, 2016 at 6:12 AM, Edward K. Ream  wrote:

> Writing the cffm and cfam commands was snap using c.cloneFindByPredicate,
> a powerful new addition to Leo.
>

​Recent revs add the following new position methods:

- p.is_at_all():  True if p is an @ node containing an @all directive.
- p.in_at_all(): True if p is in an @ tree whose root contains @all.
- p.is_at_ignore(): True if p is an @ignore node
- p.in_at_ignore_tree(): True if p is in an @ignore tree.

These predicates make it easy to create other predicates that skip @ignore
trees or @ trees containing @all.  cffm and cfam do *not *skip such
trees, on the theory that one would typically unmark nodes first before
marking nodes to be cloned.

So here is how to gather only those marked nodes that lie outside any
@ignore tree:

def isMarked(p):
return p.isMarked() and not p.in_at_ignore_tree()

self.cloneFindByPredicate(
generator = self.all_unique_positions,
predicate = isMarked,
flatten = flatten,
undoType = 'gather-marked',
)

​EKR

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Code Academy: find by predicate or attribute

2016-02-26 Thread Edward K. Ream
On Thu, Feb 25, 2016 at 6:12 AM, Edward K. Ream  wrote:

> Writing the cffm and cfam commands was snap using c.cloneFindByPredicate,
> a powerful new addition to Leo.
>

​c.cloneFindByPredicate now supports an optional failMsg keyword arg. This
is the warning given if no nodes are found.​

EKR

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.


Re: Code Academy: find by predicate or attribute

2016-02-25 Thread Richard Andersen
Edward -- these are really useful improvements!

I have the latest build and am testing out the new commands. Clone Find 
All Flattened is really useful.I am using a combination of Tags and 
Icons to track open and closed tasks.

Here's an example of one script to mark a node as an open task...

@language python


''' add the tags "open" and "todo" to the node, then add an icon '''


tc = c.theTagController
tag = 'open'
tag2 = 'todo'

tc.add_tag(p.copy(), tag)
tc.add_tag(p.copy(), tag2)

table = (
'chkboxblk.png',
)
for icon in table:
fn = g.os_path_finalize_join(g.app.loadDir,
'..', 'Icons', 'cleo', icon)
if g.os_path_exists(fn):
c.editCommands.insertIconFromFile(path=fn)



What I'd like to do next is to use the Clone Find All Flattened command to 
find all my Nodes which are "open tasks", and would appreciate any 
suggestions from others as to how to accomplish.Ideally, these would be 
shown in context with the parent tags down to the "found" tags, but that 
might be a more involved evolutionary coding step.

-Richard

On Thursday, February 25, 2016 at 4:12:52 AM UTC-8, Edward K. Ream wrote:
>
> Writing the cffm and cfam commands was snap using c.cloneFindByPredicate, 
> a powerful new addition to Leo. Here is the entire code for the new 
> commands:
>
> @cmd('clone-find-all-marked')
> @cmd('cfam')
> def cloneFindAllMarked(self, event=None):
> '''The clone-find-all-marked command.'''
> self.cloneFindMarkedHelper(flatten=False)
> 
> @cmd('clone-find-all-flattened-marked')
> @cmd('cffm')
> def cloneFindAllFlattenedMarked(self, event=None):
> '''The clone-find-all-flattened-marked command.'''
> self.cloneFindMarkedHelper(flatten=True)
>
> def cloneFindMarkedHelper(self, flatten):
> '''Helper for clone-find-marked commands.'''
> 
> def isMarked(p):
> return p.isMarked()
> 
> self.cloneFindByPredicate(
> generator = self.all_unique_positions,
> predicate = isMarked,
> flatten = flatten,
> undoType = 'clone-find-marked',
> )
>
> It's hard to imagine anything simpler. *Important*: the predicate could 
> filter on an attribute or *combination *of attributes. For example, the 
> predicate could return p has attributes A and B but *not* attribute C. 
> Instantly we have full database query capabilities. If we then hoist the 
> resulting node we see *all and only* those nodes satisfying the query.
>
> Here is c.findNodeByPredicate. *Important*: Rev c8a3581c9b corrects a 
> serious blunder in c.cloneFindByPredicate. Don't use previous versions!
> 
> def cloneFindByPredicate(self,
> generator, # The generator used to traverse the tree.   
> predicate, # A function of one argument p, returning True
># if p should be included in the results.
> flatten=False, # True: Put all matches at the top level.
> undoType=None, # The undo name, shown in the Edit:Undo menu.
># The default is 'clone-find-predicate'
> ):
> '''
> Traverse the tree given using the generator, cloning all positions
> for which predicate(p) is True. Undoably move all clones to a new
> node, created as the last top-level node. Arguments:
> 
> generator,  The generator used to traverse the tree.
> predicate,  A function of one argument p returning true if
> p should be included.
> flatten=False,  True: Move all node to be parents of the root node.
> undo_type=None, The undo/redo name shown in the Edit:Undo menu.
> The default is 'clone-find-predicate'
> '''
> c = self
> u, undoType = c.undoer, undoType or 'clone-find-predicate'
> clones, seen = [], set(), 
> for p in generator():
> if predicate(p) and p.v not in seen:
> if flatten:
> seen.add(p.v)
> else:
> for p2 in p.self_and_subtree():
> seen.add(p2.v)
> clones.append(p.copy())
> if clones:
> undoData = u.beforeInsertNode(c.p)
> root = c.createCloneFindPredicateRoot(flatten, undoType)
> # This was botched in previous versions.
> # The result was low-level vnode failures.
> for p in clones: 
> clone = p.clone()
> clone.moveToLastChildOf(root)
> u.afterInsertNode(root, undoType, undoData, dirtyVnodeList=[])
> c.selectPosition(root)
> c.setChanged(True)
> c.redraw()
> else:
> g.es_print('not found:', undoType)
>
> Imo, this is the dawn of a new era in Leo's database capabilities.
>
> Edward
>

-- 
You received this message because you are su

Code Academy: find by predicate or attribute

2016-02-25 Thread Edward K. Ream
Writing the cffm and cfam commands was snap using c.cloneFindByPredicate, a 
powerful new addition to Leo. Here is the entire code for the new commands:

@cmd('clone-find-all-marked')
@cmd('cfam')
def cloneFindAllMarked(self, event=None):
'''The clone-find-all-marked command.'''
self.cloneFindMarkedHelper(flatten=False)

@cmd('clone-find-all-flattened-marked')
@cmd('cffm')
def cloneFindAllFlattenedMarked(self, event=None):
'''The clone-find-all-flattened-marked command.'''
self.cloneFindMarkedHelper(flatten=True)

def cloneFindMarkedHelper(self, flatten):
'''Helper for clone-find-marked commands.'''

def isMarked(p):
return p.isMarked()

self.cloneFindByPredicate(
generator = self.all_unique_positions,
predicate = isMarked,
flatten = flatten,
undoType = 'clone-find-marked',
)

It's hard to imagine anything simpler. *Important*: the predicate could 
filter on an attribute or *combination *of attributes. For example, the 
predicate could return p has attributes A and B but *not* attribute C. 
Instantly we have full database query capabilities. If we then hoist the 
resulting node we see *all and only* those nodes satisfying the query.

Here is c.findNodeByPredicate. *Important*: Rev c8a3581c9b corrects a 
serious blunder in c.cloneFindByPredicate. Don't use previous versions!

def cloneFindByPredicate(self,
generator, # The generator used to traverse the tree.   
predicate, # A function of one argument p, returning True
   # if p should be included in the results.
flatten=False, # True: Put all matches at the top level.
undoType=None, # The undo name, shown in the Edit:Undo menu.
   # The default is 'clone-find-predicate'
):
'''
Traverse the tree given using the generator, cloning all positions
for which predicate(p) is True. Undoably move all clones to a new
node, created as the last top-level node. Arguments:

generator,  The generator used to traverse the tree.
predicate,  A function of one argument p returning true if
p should be included.
flatten=False,  True: Move all node to be parents of the root node.
undo_type=None, The undo/redo name shown in the Edit:Undo menu.
The default is 'clone-find-predicate'
'''
c = self
u, undoType = c.undoer, undoType or 'clone-find-predicate'
clones, seen = [], set(), 
for p in generator():
if predicate(p) and p.v not in seen:
if flatten:
seen.add(p.v)
else:
for p2 in p.self_and_subtree():
seen.add(p2.v)
clones.append(p.copy())
if clones:
undoData = u.beforeInsertNode(c.p)
root = c.createCloneFindPredicateRoot(flatten, undoType)
# This was botched in previous versions.
# The result was low-level vnode failures.
for p in clones: 
clone = p.clone()
clone.moveToLastChildOf(root)
u.afterInsertNode(root, undoType, undoData, dirtyVnodeList=[])
c.selectPosition(root)
c.setChanged(True)
c.redraw()
else:
g.es_print('not found:', undoType)

Imo, this is the dawn of a new era in Leo's database capabilities.

Edward

-- 
You received this message because you are subscribed to the Google Groups 
"leo-editor" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to leo-editor+unsubscr...@googlegroups.com.
To post to this group, send email to leo-editor@googlegroups.com.
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.