Chapter 2: The Leo Tutorial

Leo is an easy to learn, powerful programming editor, data management tool and scripting environment for the Python language. Many people say that Leo is fun to use, even addicting.

Leo is a powerful & easy to learn. It’s a programming editor, data management tool, and python scripting environment.

Leo is freely available in source or binary form for all major platforms. You may download Leo from http://sourceforge.net/projects/leo/files/Leo/ Leo is Open Software and may be freely distributed.

Leo’s home page contains additional documentation and links to other resources. For another introduction to Leo, open the file quickstart.leo in the leo/doc folder.

This tutorial introduces the reader to the basic concepts and features of Leo. It helps to have Leo running for hands-on experience, but all examples here are self-contained, so the tutorial can be read off-line as well. See Leo’s Installation Guide. for detailed installation instructions. If you have problems installing Leo, please ask for help on Leo’s help forum.

This tutorial does not attempt to be comprehensive and cover every single feature of Leo, or even every commonly used feature. Instead, it introduces many of Leo’s most noteworthy features, and will give you a good idea of Leo’s flavor and style. After reading it, you will be able to use Leo in basic ways to create external files and organize data. You will then be ready to learn more about Leo’s many advanced features in Leo’s Users Guide.

Whetting your appetite

If you do much work on computers, you’ll eventually want to organize lots of data. You may also want to automate tasks that operate on those data.

For example, you may want to organize photos into a photo album, or organize notes about interesting web sites. You might want organize your data, whether it be photos, notes or anything else, in various ways. You might want to include a particular photo in several slideshows, but not in all of your slideshows, and you might want to put that photo at the start of one slideshow, but in the middle of another.

Or you might be a computer programmer who wants to have all the data for a computer project in a single place. You want to organize the source files of your program along with related scripts, design notes, documentation, bug fixes and unit tests. And like the photographer who wants to organize slides in a variety of different slideshows, you want the organize all the data in your project in many task-oriented ways simultaneously. Finally, you would like to be able apply scripts to all the data in your project so you can automate project-specific tasks. You might even want to create scripts that analyze, modify and refactor the source code in your project.

Leo is just the tool for you.

Leo stores all its data in a tree of nodes, represented on the screen as an outline. Leo outline ares more flexible than usual: clones are nodes that may appear in multiple places within an outline. Using clones, Leo can act like a flexible filing cabinet in which nodes may be filed in many folders at once.

Any part of a Leo tree may generate an external file (a file on your computer’s file system). Leo defines simple, outline-oriented markup that tells Leo how to create the external file from an outline. Thus, a single Leo outline can contain all the files of a programming project or any other set of related files.

Any node in a Leo outline may contain a Python script. We call these scripts Leo scripts to emphasize that they are fully integrated with Leo. All of Leo is written in Python, so Leo scripts can use (or change!) any part of Leo while Leo is running. Furthermore, Leo scripts have easy access to all the data in any Leo outline. Because Leo scripts have full access to both Leo’s source code and Leo outlines, it is easy for Leo scripts to create new commands that act on any part of an outline. This is a big reason why Leo is so much fun to use. You don’t have to wait for somebody to add a new feature to Leo–you can do often do it yourself in a matter of minutes. Many of Leo’s commands started out this way.

Now that you have some insight into Leo, you’ll want to examine it in some more detail. Since the best way to learn a language is to use it, the tutorial invites you to play with Leo as you read.

Leo’s name

Leo’s name used to be an acronym but that acronym is obsolete. However, the term Leonine describes how people treat data in “the world according to Leo”.

Leo’s main window

Leo’s main window, shown below, 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, a status area and a mini-buffer at the very bottom.

leoMainWindow

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.
Mini-buffer
It is used like the Emacs mini-buffer to invoke commands. For full details, see Chapter 5: Using Leo’s Commands.

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 (Ctrl+I) inserts a new headline into the outline.
  • The Cut Node command (Ctrl+Shift+X) deletes a headline and all its children, and copies the structure to clipboard - ready to paste with Paste Node command (Ctrl+Shift+V). Use Copy Node command (Ctrl+Shift+C) to copy node to clipboard without deleting it from outline. Copy-paste command family works across different Leo documents.
  • The Move Up (Ctrl+U), Move Down (Ctrl+D), Move Left (Ctrl+L) and Move Right (Ctrl+R) commands move the currently selected node, along with all its descendants.
  • The Promote (Ctrl+}) command makes all the children of a headline siblings of the headline. The Demote (Ctrl+{) command makes all following siblings of a headline children of the headline.
  • Move around the tree and expand/collapse nodes by pressing Alt + arrow keys. This also moves the focus to tree, so, after pressing Alt + arrow, you can move around by using arrow keys alone. Return the focus to the body control by pressing Enter.
  • To edit the headline, use press Ctrl+H. This works regardless of whether body or headline has focus.
  • 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.

External 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 external files. This is useful for creating programming files, documentation files such as LaTeX files, and web pages.

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

It is easy to create external 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 external file filename. Leo writes a external 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 external files corresponding to @thin nodes in the outline.

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 external files.

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

@all

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

When writing a external 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 external files from @thin trees. Note: Leo copies headlines to the external file as comments. This means that headlines do not affect the meaning of external files and you can use headlines to contain whatever data you wish. Usually, headlines describe what’s in the node.

Clones & views

A clone is a node that appears in more than one place in the outline. Clones are marked with a small red arrow in the icon box. All clones of a node are actually the same node, so any change to one clone affects all clones. For example, inserting, moving or deleting any child of a clone will change all other clones on the screen.

Please take a few moments to experiment with clones. Create a node whose headline is A. Clone node A using the Clone Node command in Leo’s Outline menu.

Type some text into the body of either clone of 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 you delete the penultimate clone, the last clone 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. With Leo, there is no such thing as a single, “correct” view of data. You can have as many views of data as you like.

To create a new view of the data in your outline, just do the following:

  1. Create an ordinary node, that will represent the view. We call these nodes view nodes merely to indicate they represent a view.
  2. Clone all the nodes from the outline that you want the view to contain. Move these clones so they become children of the view node.
  3. (Optional) You can add regular nodes as children of the view node too.

For example, when I fix a bug in Leo, I create an ordinary node to represent the bug. This bug node is my view of all the data in Leo’s source code that relates to the bug. As I discover code related to the bug, I clone their nodes and move them under the bug node. I’ll also add ordinary nodes as children of the bug node. These nodes contain the original bug report, descriptions of how I fixed the bug, test data, or any other notes I might want to keep.

Once I have created the bug node, I concentrate only on that node and its children. I can examine the bug node and its children without having to jump around the outline. Everything I need is in one place. When I get around to actually fixing the bug I can do so by changing the clones. Again, I do not have to jump around the outline. It doesn’t matter how big or complex the entire outline is: I am only dealing with the bug node and its children. This extremely narrow focus makes it much easier to fix bugs.

By the way, I never have to remember to save external files. When I change any clone, Leo marks all instances of that clone throughout the entire outline as dirty (changed). When I save the Leo outline, Leo automatically writes all the external files that contain dirty nodes.

Views have an unlimited number of uses. Use them whenever you want to focus your attention on some smaller set of nodes. For example, I often create view nodes when studying other people’s code. The view node helps me concentrate on just the part of the code that interests me at the moment.

Basic directives (for everybody)

Leo directives control such things as syntax coloring, line wrapping within the body pane and the width of tabs. Leo directives may appear in headlines or body text. Leo directives start with ‘@’ in the leftmost column, followed by the name of the directive. The following directives are useful for non-programmers:

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

@color, @nocolor and @killcolor control syntax coloring.

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.

@language sets the language used for syntax coloring.

@tabwidth sets the width of tabs.

Negative tab widths cause Leo to convert tabs to spaces and are highly recommended for Python programming.

@wrap and @nowrap enable or disable line wrapping the Leo’s body pane.

Leo for programmers

The previous sections have discussed the basics of Leo. The rest of this tutorial discusses topics related to programming and scripting.

running Python scripts inside Leo.

We call these scripts Leo scripts to emphasize that these scripts have full and easy access to all parts of Leo’s source code and all parts of the outline containing the scripts.

Scripting is one of Leo’s biggest strengths. Simple Python scripts can do a lot.

Because Leo is written entirely in

The following sections tell how to create external 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 (parts of the outline whose headline starts with @thin) create external 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 external 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 leo.core.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.

@auto trees allow you to edit external files that do not contain sentinels. Leo imports such external files every time Leo reads the .leo file.

Beginning programmer’s reference guide

This section covers all the details of programming with Leo that programmers new to Leo 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 external 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.

Programming directives

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 external file.
  • @c Starts code parts (and ends doc parts).
  • @encoding Sets the Unicode encoding used in external files.
  • @first Forces lines to appear before the first sentinel of a external 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 external file.
  • @lineending Specifies the line ending to be used in external files.
  • @others Copies all nodes except section definition nodes to the external 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.

Important: Leo treats lines starting with @ as a normal code line unless the @ starts a Leo directive. In particular, Leo will output Python decorators correctly, provided the name of the decorator is not a Leo directive.

Orphan nodes

An orphan node is a descendant of an @thin node that will not be copied to the external 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 external 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 external 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 external 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 external file in another editor! Doing so will corrupt the external 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 external file command can recover information from corrupted external files.

The main difference between @file trees, @thin trees (and other kinds of trees that create external 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 external files. This is a highly complex subject: you should ignore these details at first. Just use @thin to create your external 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 Leo style

The following paragraphs discuss what I call good Leo style, which means how you choose to organize your data, programs and scripts as outlines. These choices simply don’t exist with other editors, and the choices you make will influence how easy it is to work with your data. We say an organization is Leonine if it uses Leo effectively and naturally.

Newcomers to Leo often have questions about how to use Leo’s outline-oriented markup. The following paragraphs answer those questions and present a straightforward, easy-to-use style of organizing your scripts and programs. I developed this style within an hour of using the first prototype of Leo, and it has remained mostly unchanged ever since. You may want to modify this style to suit your particular needs. By all means, do so. With just a bit of experimentation, you should be able to your own Leonine style.

Choosing between @others and sections

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 external 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.

Organizing programs as outlines

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 external 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 (Ctrl+B). 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 external 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.all_positions():
    print ' '*p.level(),p.h

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 of @settings trees, see Chapter 8: Customizing Leo.

Further study

LeoPyRef.leo (in the core 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.