back leo next

Chapter 2: A Tutorial Introduction to Leo

This tutorial shows you Leo's basic features. These features are simple to use, yet they interact with each other in powerful ways. All Leo's features relate in some way to outlines. Indeed, outline structure is significant everywhere.

Quick start for programmers contains the heart of this chapter. It briefly describes everything a Python programmer needs to know in order to understand Leo's source code. Good style and bad answers common question about when to use the features described in the quickstart. The section Scripting Leo is an introduction to scripting Leo with Python. For full details, see Chapter 7: Scripting Leo with Python.

Introduction

Important: please install Leo before reading this tutorial, If you have any problem, please do ask for help on Leo's help forum.

Now that you have Leo installed, please launch Leo. You should see Leo's main window, something like this: Note: the actual contents of the icon area at the top depends on what plugins are active.

leoMainWinow

Leo's main window

The main window represents an entire project and is stored in a single Leo file, a file with a .leo extension. As you can see, the main window contains three panes: the outline pane at the top left, the log pane at the top right, and the body pane at the bottom. The window also contains an icon area at the very top and a status area at the very bottom.

Outline pane & nodes
The outline pane shows your project as an outline. The outline contains all your project's data. An outline consists of nodes. Nodes have two parts, a headline and body text. The outline pane shows headlines. Selecting a headline selects the entire node; the node's body text appears in the body pane. The icon box is a small icon directly to the left of the headline text. If a node contains children, a smaller icon appears to the left of the icon box. This icon contains a + or - symbol. Clicking this expansion box expands or contracts the node.
Body pane
The body pane contains the body text of the node selected in the outline pane. You can control how Leo shows body text using Leo directives and settings. For example, directives specify whether to syntax color the body text and whether to wrap the text.
Log pane
The log pane contains informational messages from Leo. Scripts and plugins may also write message to the log pane.
Icon area
Depending on what plugins are enabled, the icon area may contain buttons and other widgets that extend what Leo can do. The scripting plugin makes it easy to add buttons to the icon area.
Status area
The status area shows the line and column containing the body text's cursor. Other information may follow. Usually this is the UNL (Uniform Node Location) that describes the path in the outline to the selected node. Please select nodes at several levels of the outline to see how the UNL changes.

Now that we are familiar with Leo's main window, let's see how to use Leo as a simple outliner.

Using Leo as an outliner

You can use Leo as fairly typical outliner. Play around with some of the commands from the Outline menu:

  • Click the expansion box of nodes to show and hide their children.
  • The Insert Node command inserts a new headline into the outline.
  • The Delete Node command deletes a headline and all its children.
  • The Move Up, Move Down, Move Left and Move Right commands move the currently selected node, along with all its descendants.
  • The Promote command makes all the children of a headline siblings of the headline. The Demote command makes all following siblings of a headline children of the headline.
  • You can cut, copy and paste entire nodes (including their descendants) with the Cut Node, Copy Node and Paste Node commands.
  • We'll discuss the Clone Node command in the next section.

You enter body text for any node by selecting the node's headline in the outline pane and then typing in the body pane. Leo has a full range of editing commands that apply to the body pane.

Key features of Leo

So far we have discussed features that Leo shares with other editors and outliners. The following sections explain what makes Leo unique.

Derived files

You don't have to store all outline data in Leo (.leo) files. Leo allows you to store outline data in external files called derived files. This is useful for creating programming files, documentation files such as LaTeX files, and web pages.

Important: You can edit derived files outside of Leo. Leo will update the outline to reflect those changes when Leo next opens the outline.

It is easy to create derived files; just put @thin filename in a headline. That creates an @thin node. The @thin tree (the @thin node and all its descendants) corresponds to the derived file filename. Leo writes a derived file corresponding to the @thin tree to your hard drive when Leo saves your outline (.leo file). When opening a .leo file, Leo reads all the derived files corresponding to @thin nodes in the outline.

Note: you can @file instead of @thin to create derived files. @thin is more friendly to CVS and other Source Code Control Systems. This tutorial only discusses @thin nodes. A good rule of thumb is to use @thin nodes unless you have a specific reason to do otherwise. See Chapter 4: Writing Programs in Leo for a full discussions of the various ways of creating derived files.

Important: You must tell Leo the order in which to write data from the @thin tree to the derived file. The simplest way to specify the contents of a derived file is to insert:

@all

in the body text of the @thin node. @all is a Leo directive.

When writing a derived file, Leo writes the body text of the @thin node, replacing the @all directive by the body text of all the descendant nodes in outline order, the order that nodes appear on the screen when all nodes are expanded. Leo for Programmers discusses other, more flexible, ways of creating derived files from @thin trees. Note: Leo copies headlines to the derived file as comments. This means that headlines do not affect the meaning of derived files and you can use headlines to contain whatever data you wish. Usually, headlines describe what's in the node.

Clones & views

A cloned node is a copy of a node that changes when the original changes. Changes to the children, grandchildren, etc. of a node are simultaneously made to the corresponding nodes contained in all cloned nodes. A small red arrow in icon boxes marks clones.

Please take a few moments to experiment with clones. Start with a single node, say a node whose headline is A. Clone node A using the Clone Node command in Leo's Outline menu. Both clones are identical; there is no distinction between the original node and any of its clones.

Type some text into the body of either node A. The same text appears in the bodies of all other clones of A. Now insert a node, say B, as a child of any of the A nodes. All the A nodes now have a B child. See what happens if you clone B. See what happens if you insert, delete or move nodes that are children of A. Verify that when the second-to-last cloned node is deleted the last cloned node becomes a regular node again.

Clones are much more than a cute feature. Clones allow multiple views of data to exist within a single outline. The ability to create multiple views of data is crucial; you don't have to try to decide what is the 'correct' view of data. You can create as many views as you like, each tailored exactly to the task at hand.

To create a new view of the data, just create any ordinary node. This node will represent the new view. Let us call it a view node. Now just put any nodes that are related to the view as descendant nodes of your view node. Let us call the descendants of the view nodes the components of the view. Component nodes are typically clones of other nodes in the outline. This is what gives the view its power: a view can contain nodes gathered from all over the outline. However, it is also sometimes useful to add non-cloned nodes as components of views.

For example, when I begin to fix a bug I first create a view node to represent the bug. I then create a component node (not cloned) that contains the original bug report. I may also create other non-cloned nodes to contain notes and documentation. Next, I go looking throughout Leo's code for nodes that relate in some way to the bug. When I find such a node I clone it and move one of the clones so it becomes a component of the view node for the bug. Note: I can organize the components of the view node as I please. In particular, I can create organizer nodes whose only purpose is to contain groups of component nodes. In other words, the full power of Leo outlines is available within view nodes.

Important: Once I have created the view of the bug, I can concentrate only on that view. In particular, I can fix code by changing component nodes. Because the code nodes are cloned, any changes I make to a component node also get made to the other cloned nodes throughout the outline. In effect, my view node for the bug lets me work only on the nodes of the outline that are directly related to the bug. In other words, the view nodes lets me focus only on the task at hand, and lets me ignore all other details.

Clones are the basis for Leo's project management capabilities. Indeed, the ability to create multiple views of a project is most helpful.

Outline structure is significant everywhere

So far we have been focusing on Leo's outline pane: creating and cloning nodes. In fact, outline structure affects all aspects of Leo. For example:

  • As mentioned earlier, body text can contain Leo directives that control how Leo works. By default, a Leo directive applies to a node and all its descendants, but a Leo directive in a descendant node can override a directive in an ancestor node.
  • Programs in body text can contain optional markup consisting of sections and section references. (See Quick start for programmers for details.) Leo outlines limits the visibility of such sections: sections must be defined in a node descending from the node containing the section reference.
  • You can organize scripts and programs using outlines, and scripts can use outline structure to access data. Plugins and scripts often confine their effects to the presently selected outline.

Leo directives

Leo directives control such things as syntax coloring, line wrapping within the body pane and the width of tabs. Leo directives start with '@' in the leftmost column, followed by the name of the directive. Some examples:

@language python
@tabwidth -4
@wrap
@nowrap
@color
@nocolor
@killcolor

The following directives are useful for non-programmers; Directives for programming lists the directives used for computer programming.

  • @color, @nocolor and @killcolor control syntax coloring.
  • @language sets the language used for syntax coloring.
  • @tabwidth sets the width of tabs. Negative tab widths cause Leo to convert tabs to spaces (highly recommended for Python programming.)
  • @wrap and @nowrap enable or disable line wrapping the Leo's body pane.

Note: You can mix @nocolor and @color directives in a single node, but these directives apply to descendant nodes only if they are unambiguous, that is, only if the ancestor node contains exactly one @color or @nocolor directive.

Leo for Programmers

The previous sections have discussed the basics of Leo. Non-programmers can stop reading this tutorial now!

The following sections tell how to create derived files that contain computer programs. Yes, you could create program files using the @all directive, but the following section explain how you can take advantage of power-user features designed specifically for computer programmers. Even if you don't read manuals, please read the following short Quick start for programmers section.

Quick start for programmers

@thin trees create derived files containing your program. Within @thin trees you can write functional pseudo-code, like this:

<< imports >>  (in body text)

This is a reference to a section called << imports >>. When writing a derived file, Leo replaces all section references by their definition. You define sections with section definition nodes. A section definition node is a node whose headline starts with a section name:

<< imports >>   (in a headline)

The body text of this node is its definition. For example:

import leoGlobals as g
import sys

As you can see, section definitions can be fragments of code; they don't have to be complete functions or methods.

Notes:

You now know enough to understand Leo's source code. Hurray! The following sections discuss some relatively minor details. However, I recommend reading Good style and bad; you might save yourself some extra work.

Beginner`s reference guide

This section covers all the details of programming with Leo that beginners are likely to need. Chapter 4: Writing Programs in Leo is the full reference guide. I recommend avoiding that chapter until you have been programming with Leo for some time.

Syntax of section names

A section name has the form:

<< any text >>

Any text is just that: any sequence of text not containing '>>'. For example:

<< initialize ivars >>

Leo ignores case and whitespace in section names, so the following are all equivalent:

<< Peanut Butter & Jelly >>
<< peanut butter&jelly >>
<<peanut butter & jelly>>
<<peanutbutter&jelly>>
<<PEANUTBUTTER&JELLY>>

When << and >> are not paired on a line, they are treated as ordinary << and >> characters. Leo has no escape mechanism for section names. That is, paired << and >> characters on the same line always denote a section name, even within comments and strings. This means that << and >> characters that do not delimit a section name must be placed on separate lines. In practice, this requirement seldom causes problems.

The syntax of section names is based on Norman Ramsey's noweb markup language, but without noweb's escape conventions. Eliminating these escape conventions may seem odd, but it has turned out to be one of the best design decisions I ever made.

Code and doc parts

Doc parts are blocks of text that Leo treats as comments. Leo syntax colors doc parts as comments, and Leo converts doc parts into comments in derived files. Doc parts start with an @ directive and continue until an @c directive or the end of the body text. For example:

@ This is a comment in a doc part.
Doc parts can span multiple lines.
The next line ends the doc part
@c

Doc parts are entirely optional; you could simply use comments in the language specified by the @language directive. Using doc parts for lengthy comments is convenient, however. Not only do you not need to specify comment delimiters, but Leo breaks doc parts into lines automatically. The @pagewidth directive specifies the width of those lines.

Notes:

  • In body text, everything not in a doc part is in a code part. If a node does not contain a doc part, the entire body text is a code part.

  • @doc is a synonym for @ and @code is a synonym for @c. However, @ and @c are preferred.

  • A doc part of the form:

    @ %def identifiers
    

declares that the preceding code part contains the list of identifiers. Whitespace separate the identifiers; everything else is taken to be the identifiers. This construct is a convention of the noweb language, and will be of use only for those who want to create .nw output files for use with the official noweb system.

Directives for programming

The following directives are commonly used by Leo programmers. See Chapter 4: Writing Programs in Leo for full details.

  • @ Starts doc parts (and ends code parts).
  • @all Copies all descendant nodes to the derived file.
  • @c Starts code parts (and ends doc parts).
  • @encoding Sets the Unicode encoding used in derived files.
  • @first Forces lines to appear before the first sentinel of a derived file.
  • @language Sets the language used for syntax coloring and sets the comment delimiters used in sentinel lines and in doc parts.
  • @last Forces lines to appear after the last sentinel of a derived file.
  • @lineending Specifies the line ending to be used in derived files.
  • @others Copies all nodes except section definition nodes to the derived file.
  • @pagewidth Sets the page width used to break doc parts into lines.
  • @path Sets the path to be prepended to filenames in descendant @file nodes.

Orphan nodes

An orphan node is a descendant of an @thin node that will not be copied to the derived file. Orphan nodes can arise because an @thin tree has no @others or @all directives. Sections that are defined but not used also create orphan nodes. Leo issues a warning when attempting to write an @thin tree containing orphan nodes, and does not save the derived file. Instead Leo saves the information in the @thin tree in the .leo file. No information is lost; Leo will load the @thin tree from the .leo file the next time Leo opens the .leo file.

Sentinel lines

When writing derived files, Leo stores information about the outline structure in special comments called sentinel lines. Sentinel lines are comment lines with '@' following the comment delimiter. For example, here are some actual sentinel line for the derived file containing Python code:

#@+leo-ver=4-thin
#@+node:ekr.20031218072017.2794:@thin leoColor.py
#@@language python
#@@tabwidth -4
#@@pagewidth 80
#@-node:ekr.20031218072017.2794:@thin leoColor.py
#@-leo

You must not change sentinel lines when editing a derived file in another editor! Doing so will corrupt the derived file and make it impossible for Leo to read it normally. If you do accidentally alter a sentinel line, don't panic! Leo's Import Derived File command can recover information from corrupted derived files.

The main difference between @file trees, @thin trees (and other kinds of trees that create derived files) is the kind of sentinel lines that Leo writes:

  • Sentinels in files derived from @thin reduce spurious cvs conflicts by marking each node with unique, unchanging timestamp as shown above.
  • Sentinels in files derived from @file are as friendly as possible for human readers.
  • Files derived from @nosent have no sentinels at all. Important: without sentinels Leo can not automatically update @nosent trees from changes made in external editors.

Chapter 4: Writing Programs in Leo discusses the various ways of creating derived files. This is a highly complex subject: you should ignore these details at first. Just use @thin to create your derived files.

Leo and literate programming

Leo can support a style of programming similar to Literate Programming (LP). LP has a bad reputation in some quarters. That's too bad; Leo fixes all the problems with traditional LP. See Chapter 6: Leo and Literate Programming in Leo's Users Guide for more details. Please don't let the words 'Literate Programming' get in the way of your using Leo effectively. That would be your mistake, and a big one.

Good style and bad: sections vs. @others

Newcomers to Leo frequently ask when to use the @others directive and when to use sections. It is good style to use section references only when the order of text within a derived file matters. For example, Python programmers put docstrings and imports at the start of files. So the body text of @file nodes typically look something like this:

<< docstring >>
@language python
@tabwidth -4
<< imports >>
@others

This ensures that the docstring is first in the file, followed by imports, followed by everything else. Note that the order in which functions are defined in a file, or methods defined within a class, typically does not matter. Thus, it is good style to define classes like this:

class myClass:
      << class attributes >>
      @others

It would be bad style to define a class like this:

class myClass:
      << class attributes >>
      << method 1 >>
      << method 2 >>
      ...

Not only does this over-specify the order in which methods are defined, but it requires lots of extra typing. Not only must you add a line for each method, but headlines must contain section names such as << method 1 >>, <<method 2>>, etc. When using @others it is good style simply to put the name of each method in the headline.

A few more words about style:

  • It is good style to put each class, function or method in its own node. This makes it easy to see the shape of your code.

  • It is good style to use organizer nodes to group related functions or methods. An organizer node has no content except maybe for comments. Like this:

    + myClass
        + birth and death
            + __init__
            etc.
        + getters
            etc.
        + setters
            etc.
        + misc methods
            etc.
    

    (In this notation, '+' denotes a headline.) This organization is far superior to using hideous comments like:

    ###########
    # Getters #
    ###########
    
  • It is bad style to use @others in organizer nodes. There is no need to do so.

  • It is bad style to use @others when order does matter. The reason is that it is very easy to move nodes in a tree by mistake, say by alphabetizing nodes. One wants to make the meaning of a derived file immune from such movements.

One last word about style. The world won't end if you happen to use bad style by mistake: you just might cause a bit more work for yourself than was strictly necessary. Feel free to invent your own style of using Leo. Still, it would be wise to "know the rules before you break them."

Scripting Leo

Leo is fully scriptable using the Python language. Leo can execute any body text as a Python script. To run the entire body text as a script, simply choose the node and execute the Execute Script command. If text is selected, the Execute Script command will run just the selected text as the script.

The Execute Script command preprocesses the script before executing it. Leo preprocesses scripts in exactly the same way that Leo writes derived files. That is, Leo expands section references and processes @others directives before executing the script. This allows you to use all of Leo's normal capabilities to organize your scripts. Note: test.leo contains dozens of examples of using Leo outline structure to organize stand-alone scripts.

Your Python scripts can easily access data in an outline. For example, the following script will print all the headlines in an outline:

for p in c.allNodes_iter():
    print ' '*p.level(),p.headString()

Your scripts can use outline structure to avoid having to parse data. With a little forethought you can arrange outlines to make scripts easier to write. The example above is only the beginning of what scripts can do. See Chapter 7: Scripting Leo with Python for a complete discussion of scripting.

Plugins & settings

Plugins are Python modules that change how Leo works, yet are not part of Leo's core code. Leo's user have contributed dozens of plugins that have extended Leo's capabilities in many new directions. The file leoPlugins.leo contains all plugins that are included in Leo distributions.

Plugins and other parts of Leo can get options from @settings trees, outlines whose headline is @settings. When opening a .leo file, Leo looks for @settings trees in the outline being opened and also in various leoSettings.leo files. @settings trees allow plugins to get options without any further support from Leo's core code. For a full discussion plugins and @settings trees, see Chapter 8: Customizing Leo.

Further study

LeoPy.leo (in the src subdirectory of the leo folder) contains almost all of Leo's source code. It provides hundreds of examples of everything discussed here. This file will repay close study. For full details on all aspects of Leo see LeoDocs.leo or Leo's Users Guide.


back leo next