Startup
@chapters
@settings
@string target_language = rest
@int page_width = 60
change log
Welcome to Leo!
Tree manipulation basics
Programming
External files
Thin nodes (explanation & exercise)
@path ~
@@thin myfile_thin.py
imports & setup routines
imports
init1, init2
class Foo
<< docstring >>
spam
eggs
Auto nodes
@path ~
@@auto myfile_auto.py
imports & setup routines
imports
init1, init2
class Foo
<< docstring >>
spam
eggs
Shadow nodes
@path ~
@@shadow myfile_shadow.py
imports & setup routines
imports
init1, init2
class Foo
<< docstring >>
spam
eggs
reStructuredText (@auto-rst)
@path ~
@@auto-rst myfile_rst.txt
Main heading
subheading 1
subheading 2
Configuration (enabling plugins etc.)
Find out your ~/.leo directory (script)
@@settings
@enabled-plugins
@@string initial_split_orientation = horizontal
suggested style sheets
default look (Linux)
@@data qt-gui-plugin-style-sheet
A mac look
@@data qt-gui-plugin-style-sheet
@int qt_max_colorized_chars = 200000
@data contextmenu_commands
Search and replace
Minibuffer
Scripting Leo
Executing scripts with ctrl+b
Press ctrl+b here
Creating script buttons
@button example-btn
This node contains settings and other "machinery" that you can usually ignore.
The page width for wrapping doc parts in derived files.

Valid values: any nonzero positive integer.
Added settings to use rest by default and use a page width of 60 for wrapping paragraphs.

Created the startup node and its descendants.
Remove the first @ from @thin in the subtree below and save (ctrl+s) to create an "external" file which is directly usable outside leo - try opening the resulting myfile.py in a normal text editor (e.g. from right-click menu on the @thin node) to see what it looks like.

Note the @others directive, and the the lines that look like

#@-node:ville.20090627211608.10122:class Foo

These are called "sentinels", and they are needed to preserve the tree structure in the external files. They allow your tree structure to survive, even when someone else edits the source (or you edit it yourself in an external editor).
@language python @others
"External file" means a file that resides on your file system. If you are programming, these are the files you eventually want to create to get something useful out of Leo, for example, your C++ or Python source code files.
class Foo: << docstring >> @others

""" Some sort of useful class """

def spam(self): pass

def eggs(self): pass
import os import sys

def init1(): print "init1"

def init2(): print "init2"
If the sentinels in thin nodes are unacceptable for your workflow (typically the case when you are the only one using Leo in a particular project), you can use @auto nodes to "play well with others". @auto nodes understand the structure of the source code (parsers exist for popular languages), and create the "typical" outline for the code when the file is loaded. When you save, the outline is written back.

Do the same thing you did with @@thin - i.e.,

- Remove the first @, and save. - Check the resulting file (`/myfile_auto.py) and observe that it has no sentinels. - There is no "magic" involved. If you execute 'File -> Read auto nodes" (or right click on @auto node and choose "Refresh from disk", or reopen this document), you'll note that the outline structure was lost, and the "parsed" structure is created instead. This is the cost of using @auto nodes.
This is a brief tutorial for getting familiar with basic Leo functionality. Click around and experiment.

Note that you probably want to save your own "working copy" of this file before proceeding further. Do that by "File -> Save as".

This guide is intentionally quite brief and minimal - therefore, it merely scratches the surface of what Leo can do. You can begin leveraging Leo for mindmapping-like tasks by just reading the node "Tree manipulation basics", and moving on to other topics after acquiring some basic familiarity.
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 and processes.

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

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.

See Leo's documentation for more detailed discussion.
@language python @others
def init1(): print "init1"

def init2(): print "init2"
import os import sys

class Foo: << docstring >> @others

""" Some sort of useful class """

def spam(self): pass

def eggs(self): pass
If you are just starting, you should create your own myLeoSettings.leo in ~/.leo. We'll do that next.

Create the file first: - File -> New (or ctrl+N) - File -> Save as - Navigate to ~/.leo - save as myLeoSettings.leo

In the current tree, there is @@settings subtree. We are copying this to the new file. Go to node @@settings, and copy the whole tree to clipboard (ctrl+shift+c).

Select the document that has myLeoSettings.leo (the one you just created). Drop the settings tree there (ctrl+shift+v), Remove extra @ from @@settings, and save again.

Now, you should be all set. Verify that it worked by Help->open myLeoSettings.leo
# execute this script by ctrl+b to find out where your ~/.leo is

g.es('Homedir is at ',g.app.homeLeoDir)

In this tree, you can experiment with @shadow. It combines the benefits of @thin and @auto - namely, it publishes a file without sentinels, but still allows the tree structure to survive, even if the external file is edited outside Leo.

The cost is complexity - @shadow relies on a "shadow file" that remembers the structure, and a sophisticated diff/patch algorithm that merges the changes from the external file to the tree structure.

Experiment by editing the external file outside Leo and doing Right click -> refresh from disk on the @shadow node.
@language python @others
import os import sys

def init1(): print "init1"

def init2(): print "init2"
class Foo: << docstring >> @others

""" Some sort of useful class """

def spam(self): pass

def eggs(self): pass
Press ctrl + F to enter "minibuffer find" mode. Press F3 to "find again".

For large scale searches (classic "find in files" functionality for the whole tree), look for the "Nav" tab in the log pane (in upper right of the screen). Enter your search string and press enter, then click on the matches.

You can also activate the "Nav" functionality with ctrl+shift+f.

To perform find-and replace, press ctrl-f, enter the text to search, then press ctrl+shift+r, and enter the text to replace the matches with, and press Enter.

To limit the replace operations to particular external file, you can use your external editor. That is, right click on the @thin node (say, @thin myfile.py), choose "Edit myfile.py in MYEDITOR", and perform the necessary operations. After that, right click on the node and choose "Refresh from disk".
The minibuffer is the text input area at the bottom of the screen, familiar to users of emacs and vi.

Press alt-x to enter a minibuffer command (e.g. alt-x fill-paragraph). Press ctrl+p (repeat-complex-command) folowed by Enter to re-run a previous minibuffer command.
reStructuredText (http://docutils.sourceforge.net/rst.html) is an efficient way of authoring documentation as plain text. Leo provides first-class support for RST authoring, including the unique feature of representing RST outline structure as Leo tree. You can find an example in the tree below - again, just remove the first @ character from @@auto-rst and save, opening the external file afterwards.
@language rest @tabwidth -4 @others

.. Warning: this node is ignored when writing this file. .. However, @ @rst-options are recognized in this node.

Observe the underlining style of the headings.
Some text in first other chapter.
More text in other chapter.
horizontal: body pane to the left vertical: body pane on the botton

vertical is the default; you may prefer horizontal for small but wide screens (e.g. on laptops)
# Leo loads plugins in the order they appear here. # File names may be indented as desired.

# Standard plugins enabled in official distributions....

plugins_menu.py leo_to_html.py mod_scripting.py quicksearch.py UNL.py contextmenu.py nav_qt.py

# The plugins manager plugin does not # understand @enabled-plugins nodes. # plugin_manager.py

# The rst3 plugin is no longer needed. # It's code has been moved to Leo's core # rst3.py

# These plugins used to be enabled when using the tk plugin. # cleo.py # hoist.py # image.py # nav_buttons.py # threading_colorizer.py

# All other plugins. # Order is important for enabled plugins that # add items to the icon area.

# ConceptualSort.py # EditAttributes.py # FileActions.py # Library.py # nodeActions.py # UASearch.py # URLloader.py # UniversalScrolling.py

# add_directives.py # arrows.py # at_folder.py # at_view.py # autotrees.py # base64Packager.py # bibtex.py # chapter_hoist.py # cleo.py # color_markup.py # datenodes.py # detect_urls.py # dyna_menu.py # fastGotoNode.py # footprints.py # groupOperations.py # hoist.py # image.py # import_cisco_config.py # ipython.py # keybindings.py # leoOPML.py # leo_to_html.py # leo_to_rtf.py # leoupdate.py # macros.py # mod_autosave.py # mod_http.py # mod_labels.py # mod_read_dir_outline.py # mod_shadow.py # multifile.py # nav_buttons.py # newButtons.py # niceNosent.py # nodebar.py # nodenavigator.py # open_shell.py # open_with.py # paste_as_headlines.py # pie_menus.py # pretty_print.py # print_cp.py # quickMove.py # rClick.py # read_only_nodes.py # rowcol.py # run_nodes.py # s_menu.py # scheduler.py # searchbox.py # shortcut_button.py # slideshow.py # table.py # templates.py # trace_tags.py # vim.py # word_count.py # word_export.py # xcc_nodes.py # xemacs.py # xsltWithNodes.py # zodb.py # quicksearch.py # tomboy_import.py # ctagscompleter.py # colorize_headlines.py
If zero, all nodes are colorized, regardless of length of body text. If > 0, only nodes whose body text are smaller than this limit are colorized.
This tree containt some suggested "looks" for Leo.

To experiment, you may want to use a @button that applies the stylesheet in current node; look for "@button set-style-sheet" in scripts.leo.

For information on stylesheets, see

http://doc.trolltech.com/stylesheet.html

Style contributions are welcome.
Classic Leo colors. This should look good on Linux.
This is the classic Leo look, but with fonts that allegedly look better on Mac.
/* Documentation of Qt stylesheets at http://doc.trolltech.com/stylesheet.html

To experiment, you may want to use a @button that applies the current stylesheet; look for "@button set-style-sheet" in scripts.leo.

*/

/* Valid color names: http://www.w3.org/TR/SVG/types.html#ColorKeywords */

/* A QWidget: supports only background attributes.*/

QSplitter::handle { background-color: #CAE1FF; /* lightSteelBlue1 */ }

QStackedWidget { /* background-color:lightpink; */ border-color: red; padding: 0px; /* border-width: 0px; */ /* background-color: yellow; */ }

QSplitter { border-color: white; background-color: white; border-style: solid; }

QTreeWidget { /* These apply to the selected item, but not to editing items.*/ background-color: #ffffec; /* Leo's traditional tree color */ selection-color: black; /* was white */ selection-background-color: lightgrey; /* font-family: SansSerif; */ font-family: DejaVu Sans Mono; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal, italic,oblique */ }

/* Headline edit widgets */ QTreeWidget QLineEdit { background-color: cornsilk; selection-color: white; selection-background-color: blue; font-family: DejaVu Sans Mono; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal, italic,oblique */ }

/* The log panes */ QTextEdit { background-color: #f2fdff; selection-color: white; selection-background-color: blue; /* font-family: Courier New; */ font-family: DejaVu Sans Mono; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal, italic,oblique */ }

/* The body pane */ QTextEdit#richTextEdit { background-color: #fdf5f5; /* A kind of pink. */ selection-color: white; selection-background-color: lightgrey; font-family: DejaVu Sans Mono; /* font-family: Courier New; */ font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal,italic,oblique */ }

QLabel { font-family: DejaVu Sans Mono; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal,italic,oblique */ }

/* Editor labels */ QLineEdit#editorLabel { background-color: #ffffec; font-family: DejaVu Sans Mono; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal,italic,oblique */ border: 2px; margin: 2px; }

/* The mini-buffer */ QLineEdit#lineEdit { selection-color: white; selection-background-color: lightgrey; font-family: DejaVu Sans Mono; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal,italic,oblique */ }

QLineEdit#status1 { background-color: lightgrey; border-width: 1px; border-style: solid; border-color: darkgrey; }

QLineEdit#status2 { background-color: lightgrey; border-width: 1px; border-style: solid; border-color: darkgrey; }

XXQPushButton { background-color: #fdf5f5; /* A kind of pink. */ margin: 2px; padding; 4px; border-width: 2px; border-style: solid; border-color: darkgrey; }

/* QMenuBar works, but not QMenu... */ XXQMenuBar { font-family: DejaVu Sans Mono; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal,italic,oblique */ }
/* Documentation of Qt stylesheets at http://doc.trolltech.com/4.2/stylesheet.html */

/* Valid color names: http://www.w3.org/TR/SVG/types.html#ColorKeywords */

/* A QWidget: supports only background attributes.*/

QSplitter::handle { background-color: #CAE1FF; /* lightSteelBlue1 */ }

QStackedWidget { /* background-color:lightpink; */ border-color: red; padding: 0px; /* border-width: 0px; */ /* background-color: yellow; */ }

QSplitter { border-color: white; background-color: white; border-style: solid; }

QTreeWidget { /* These apply to the selected item, but not to editing items.*/ background-color: #ffffec; /* Leo's traditional tree color */ selection-color: black; /* was white */ selection-background-color: lightgrey; /* font-family: SansSerif; */ font-family: Lucida Grande; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal, italic,oblique */ }

/* Headline edit widgets */ QTreeWidget QLineEdit { background-color: cornsilk; selection-color: white; selection-background-color: blue; font-family: Lucida Grande; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal, italic,oblique */ }

/* The log panes */ QTextEdit { background-color: #f2fdff; selection-color: white; selection-background-color: blue; font-family: Monaco; font-size: 10px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal, italic,oblique */ }

/* The body pane */ QTextEdit#richTextEdit { background-color: #fdf5f5; /* A kind of pink. */ selection-color: white; selection-background-color: lightgrey; font-family: Monaco; /* font-family: Courier New; */ font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal,italic,oblique */ }

QLabel { font-family: Lucida Grande; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal,italic,oblique */ }

/* Editor labels */ QLineEdit#editorLabel { background-color: #ffffec; font-family: Lucida Grande; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal,italic,oblique */ border: 2px; margin: 2px; }

/* The mini-buffer */ QLineEdit#lineEdit { selection-color: white; selection-background-color: lightgrey; font-family: Monaco; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal,italic,oblique */ }

QLineEdit#status1 { background-color: lightgrey; border-width: 1px; border-style: solid; border-color: darkgrey; }

QLineEdit#status2 { background-color: lightgrey; border-width: 1px; border-style: solid; border-color: darkgrey; }

XXQPushButton { background-color: #fdf5f5; /* A kind of pink. */ margin: 2px; padding; 4px; border-width: 2px; border-style: solid; border-color: darkgrey; }

/* QMenuBar works, but not QMenu... */ XXQMenuBar { font-family: Lucida Grande; font-size: 12px; font-weight: normal; /* normal,bold,100,..,900 */ font-style: normal; /* normal,italic,oblique */ }
# Add commands to contextmenu # The format is <command> SPACE <description>

# stickynote Create a sticky note # read-at-file-nodes Read file node
Eventually, you will want to add extra functionality to your Leo documents. There are a few simple ways, and unlimited power for advanced users

You can write scripts in your document trees, and execute them with ctrl+b. Try it on the child of this node - it should display the list of nodes that have a headline starting with @ in the log pane.

It will also append the summary as a new node under itself.

@language python # c is "commander", central api object specific to current document

# get a list of "position" objects nodes = c.find_h('^@')

res = [] for n in nodes: # .b gets the body text, .h is headline body = n.b res.append("- " + n.h)

res.append(" " + str(body.count('\n')) + " lines")

# 'p' is the 'current position' child = p.insertAsLastChild() child.b = "\n".join(res) child.h = "Report"

c.redraw()
You can create buttons in the button bar by adding @button nodes to your outline.

A button does not appear automatically when you add it - you need to reopen the document to make it appear.

# p is current position

g.es("p.h is " + p.h)