Point 3 of the overview thread
<https://groups.google.com/forum/#!topic/leo-editor/Bzql90VQcMI> was:
> There is a close relationship between views and attributes. Indeed,
> *attributes
create views*, and vice versa. Examples: bookmarks, chapters, Nav pane
results, clone-find-all results, whatever.
This post is long and technical. It's worth doing because it unifies
several related concepts.
*Assertion*:
A view is a set of positions satisfying a Leo predicate.
A *Leo predicate* is a function/method/expression taking a position
argument that returns True or False. A position p *satisfies *a predicate
if the predicate returns True for position p.
The notion of predicate is useful for two reasons:
1. It is a unifying concept and
2. It may be possible to make predicates an explicit part of Leo's ui.
Predicates naturally define attributes, and vice versa. We want to be able
to form the union or intersection of attributes. Richard has brought my
attention to Jake's *nodetags *plugin. This plugin adds, deletes and
searches for attributes.
*Find by predicate*
The essence of the idea is the following super-simple code:
for p in c.all_unique_positions():
if predicate(p):
<< do something >>
I'll say more about this in another posting (there is now a
c.cloneFindPredicate method that does a lot of cool things).
In fact, the predicate could, as a side effect, do "the something", in
which case the code is:
for p in c.all_unique_positions():
predicate(p)
*Important*: the code is inherently dynamic. The predicate can be
re-evaluated as the outline changes.
*Important*: this code is maximally general. The quicksearch (Nav)
nodetags and bookmarks plugins are examples of this pattern. For the Nav
plugin, the predicate is that p.h matches the search string. For the
nodetags plugin the predicate is that p.v.u matches a particular tag.
Similarly for bookmarks. Do you see?
*Important*: This code is very fast.
As I was thinking about this topic I realized that the chapters code is
really, really stupid. On startup it looks for an @chapters node and
requires that all @chapter nodes be children of this node.
Instead, the code should allow the user to create an @chapter anytime,
anywhere. Yes, the code that shows available chapters must rescan the
outline, but tests show that can be done in less than 0.1 sec. As a happy
side effect, there is no need for a ChapterController class to retain
state. Stateless chapter-related commands should work.
*Summary and new directions*Predicates create a set of positions, namely
the positions that satisfy the predicate. These sets naturally form
distinct views of an outline. If we clone the nodes in the set under a
common node, we can hoist that node and see all and only those nodes that
satisfy the predicate.
The bookmarks, todo, quicksearch and nodetags plugins provide alternate,
arguably better, ways of seeing such views. Most people will find these
plugins more easy and intuitive to use than hoisting a set of clones. I'll
say more about this in another thread.
Predicates could be incorporated into any plugin. The ui would allow the
user to predicate expression. The plugin would then *filter* all nodes
based on the predicate.
Edward
P.S. We can imagine predicates being represented directly in the outline by
*@predicate* nodes. For example, the body of such a node could be:
def is_chapter(p):
return p.h.startswith('@chapter ')
or even just:
p.h.startswith('@chapter ')
Leo's support code for @predicate would take care of the details of
applying the expression or function to every node of the outline.
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 [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/leo-editor.
For more options, visit https://groups.google.com/d/optout.