Startup
@chapters
Buttons
@button Spell
@button rst3
@@button Save
@@button promote
@@button def list
createDefList
@@button sentence
splitSentences
@@button reformat-paragraph
@@button rst->html
@@button rst->pdf
@@button rst->tex
@@button rst->rst
@settings
@page http plugin
@bool http_active = False
@int port = 8080
@string rst_http_attributename = rst_http_attribute
@page rst3 options
Http options...
@bool rst3_clear_http_attributes = False
@string rst3_http_attributename = 'rst_http_attribute'
@bool rst3_http_server_support = False
@string rst3_node_begin_marker = 'http-node-marker-'
@bool rst3_massage_body = False
@bool rst3_format_headlines = True
@bool rst3_write_intermediate_file = True
@string rst3_default_path =
Read me first
Home page
<< download ref >> (contains version number)
@thin html/front.html
Users Guide
Table of contents
@rst html\leo_TOC.html
@rst-no-head All links (TOC)
Table of Contents
@rst-no-head end
Front matter
@rst html\frontMatter.html
@rst-no-head Links
@rst-ignore Old Preface
Acknowledgements
@rst-no-head special mentions
Copyright
DISCLAIMER OF LIABILITY
@rst-no-head End stuff
Preface
@rst html\preface.html
@rst-no-head Links
@rst-no-head preface
@rst-ignore @rst-no-head preface (old)
@rst-no-head End stuff
What people are saying about Leo
@rst html\testimonials.html
@rst-no-head Links
Leo is revolutionary
Leo is a showcase Python/Tkinter application
Leo is fun, even addicting
Leo is a flexible, powerful IDE
Leo is a superb outliner
Leo is an excellent PIM
Leo extends, completes and simplifies literate programming
Leo is a superb documentation tool
Leo simplifies the understanding of complex systems
Leo is stable, well designed and well supported
Longer quotes...
Speed Ream's slashdot article
Joe Orr
Dan Winkler
Dan Winkler 2
Dan Winkler 3
@rst-no-head end stuff
FAQ
@rst html\FAQ.html
@rst-no-head Links
Installing Leo
Nothing (or almost nothing) happens when I start Leo. What should I do?
Leo is hanging on my Linux box. What should I do?
Running Python setup.py install from the leo directory doesn't work. Why not?
Learning to use Leo
What's the best way to learn to use Leo?
Why should I use clones?
Which should I use: @root trees or @file trees?
When is using a section better than using a method?
When is deleting a node dangerous?
How should I use Leo with CVS?
Using derived files
How do I inhibit sentinels in derived files?
How do I prevent Leo from expanding sections?
How can I create Javascript comments?
How can I disable PHP comments?
How can I use Leo with unsuppoorted languages?
How do I make derived files start with a shebang line?
How do I use Leo to create CWEB files?
Can @file trees contain material not in the derived file?
How can I use Leo with older C compilers
Why can't I use @ignore directives in @thin and @file trees?
Customizing Leo
How can I add support for a new language?
How do I submit a plugin?
How do I add a new menu item from a plugin?
How can I use Leo's legacy key bindings?
How can I enable and disable support for psyco?
Tips and techniques
How can I do a simple find and replace?
How can I use Leo to develop Leo itself?
How can I import many files at once?
How can I use two copies of Leo to advantage?
How can I display graphics in Leo?
How can I create a template .leo file?
How can I show Leo files with Excel?
How can I reuse @button nodes in multiple files?
Trouble shooting
@rst-ignore I can't run Leo from a cvs sandbox. What's going on?
Can I scroll the outline pane with the mouse wheel?
Control-Shift backspace doesn't work. What should I do?
Error messages from the rst3 plugin aren't helpful. What can I do?
How can I run Leo from a console window?
How can I use Python's pdb debugger with Leo?
I can't write Imported files. What's going on?
I don't see the Leo icon in Leo windows
Leo doesn't recognize commands with the caps-lock key down
Leo is hanging on my Linux box. What should I do?
Leo's Recent Files menu doesn't work from a cvs shandbox. What's going on?
Nothing (or almost nothing) happens when I start Leo. What should I do?
The new Python decorator syntax causes problems. What can I do?
Running Python setup.py install from the leo directory doesn't work. Why not?
I can't run the LeoBridge module outside of leo/src. What should I do?
Unicode issues
I can not enter non-ascii characters. What can I do?
Some characters in derived files look funny. What can I do?
I get weird results when defining unicode strings in scripts. What is going on?
Some characters are garbled when importing files. What can I do?
Python's print statement shows 'byte hash' for unicode characters. What can I do?
@rst-no-head end stuff
Chapter 1: Installing Leo
@rst html\install.html
@rst-no-head links
System requirements
How to install Leo on Linux
Installing Leo on Windows
How to associate Leo with .leo files on Windows
Installing Leo on MacOS X
How to use Platypus to create a Mac launcher for Leo
How to create MacOS X .pkg files
Running Leo
Running Leo in batch mode
How to install the Aspell spell checker
@rst-no-head end stuff
Chapter 2: A Tutorial Introduction to Leo
@rst html\intro.html
@rst-no-head links
Introduction
Leo's main window
Using Leo as an outliner
Unique features of Leo
Derived files
Clones & views
Outline structure is significant everywhere
Leo directives
Leo for Programmers
Quick start for programmers
Beginner`s reference guide
Syntax of section names
Code and doc parts
Directives for programming
Orphan nodes
Sentinel lines
Leo and literate programming
Good style and bad: sections vs. @others
Scripting Leo
Plugins & settings
Further study
@rst-no-head end stuff
Chapter 3: Using Outlines
@rst html\outlines.html
@rst-no-head links
Autocompletion and calltips
Cloning nodes
Creating and destroying nodes
Creating and destroying multiple body editors
Cutting, pasting and deleting nodes
Dragging nodes
Editing body text
Expanding & contracting nodes
Indenting body text automatically
Marking nodes
Moving & Reorganizing nodes
Navigating through the outline
Opening URL's automatically
Resizing panes
Undoing operations
Using chapters
@rst-no-head end stuff
Chapter 4: Programming with Leo
@rst html\directives.html
@rst-no-head links
@rst-no-head Intro.
Overview: the seven ways of creating derived files
Overview: summary of directives
@rst-ignore alternate representation
Reference: all about directives
@ and @doc
@all
@c and @code
@color, @nocolor and @killcolor
@comment
@delims
@encoding
@first
@ignore
@language
@last
@lineending
@others
@path
@pagewidth
@tabwidth
@raw and @end_raw
@root-code and @root-doc
@verbose, @terse, @quiet and @silent
@wrap and @nowrap
Reference: the seven ways of creating derived files
\@auto
Perfect import checks
Commands related to @auto
\@thin and @file
\@nosent
\@asis and @noref
\@root
Sections and section definitions
Tangling @root trees with the Tangle commands
Untangling @root trees with the Untangle commands
Converting @root trees to @file trees
CWEB mode
@rst-no-head end stuff
Chapter 5: Using Leo's Commands
@rst html\commands.html
@rst-no-head links
The minibuffer
Basic editing commands
Debugging commands
Emacs commands
Find commands
Gui commands
Help commands
Mode commands
Outline commands
Miscellaneous commands
The File Menu
Loading, Saving and Reverting Files
Communicating with external editors
Tangling an outline: Producing Derived Files
Untangling: updating an outline
Importing Files into Leo Outlines
Exporting Files from Leo Outlines
Quitting Leo
The Edit Menu
Undoing changes
Cutting, pasting and selecting text
Shifting body text
Adding and deleting comments in body text
Creating nodes from body text
Converting leading blanks and tabs in body text
Executing Python scripts in body text
Finding and changing text
Script search
Go To Line Number
Inserting the date and time
Reformatting paragraphs in body text
Matching brackets and parenthesis
The Outline Menu
Checking outlines
Creating & cloning nodes
Cutting, pasting and deleting nodes
Expanding and contracting nodes
Marking nodes
Moving, sorting and reorganizing nodes
Hoisting & De-hoisting nodes
The Window Menu
The Help Menu
@rst-no-head end stuff
Chapter 6: Leo and Literate Programming
@rst html\design.html
@rst-no-head links
Why I like Literate Programming
How Leo Improves Literate Programming
How Leo Changes the Notion of Literate Programming
@rst-no-head end stuff
Chapter 7: Scripting Leo with Python
@rst html\scripting.html
@rst-no-head Links
@rst-ignore Important: you can run these examples!
Commonly used classes
Predefined objects
g.es writes to the log pane
app.windowList: the list of all open frames
Getting and setting headline and body text
Ensuring that positions are valid
About copying positions
Traversing outlines
c.allNodes_iter
p.children_iter
p.parents_iter & p.self_and_parents_iter
p.siblings_iter & p.following_siblings_iter
p.subtree_iter & p.self_and_subtree_iter
Testing whether a position is valid
Visiting each node once
Updating the screen
Invoking commands from scripts
Getting settings from @settings trees
Getting and setting preferences
Functions for finding and changing text from scripts
Functions defined in leoGlobals.py
Event handlers
@rst-no-head Summary of event handlers
Enabling idle time event handlers
How to make operations undoable
Redirecting output from scripts
Writing to different log tabs
Invoking dialogs using the g.app.gui class
Inserting and deleting icons
Customizing panes with different widgets
Official ivars
Common operations on Tk.Text widgets
Customizing the log pane
Customizing the body pane
Customizing the outine pane
Summary of the vnode and position classes
Iterators
Getters
Setters
Creating script buttons
Running Leo in batch mode
@rst-no-head end stuff
Chapter 8: Customizing Leo
@rst html\customizing.html
@rst-no-head links
Specifying settings
Organizer nodes
@ignore nodes
Simple settings nodes
Complex settings nodes
Input modes
Adding extensible attributes to nodes and .leo files
Specifying Tk options using .leo_xresources
Translating Leo's menus and messages
@rst-no-head end stuff
Chapter 9: History of Leo
@rst html\history.html
@rst-no-head links
Beginnings
Breakthrough
Apple and YellowBox
Borland C++
Discovering Python
SourceForge
Allowing sentinel lines in derived files
Untangling @file is easy!
Leo 3.x: Continuous improvement
Leo 4.0: Eliminating error 'recovery'
Leo 4.1: The debut of gnx's
Leo 4.2: Complete at last
Leo 4.3 Settings
Leo 4.4 The minibuffer and key bindings
Leo 4.4.4 Improvements
Leo 4.4.1
Leo 4.4.2
Leo 4.4.3
Leo 4.4.4
Leo 4.4.5
Leo 4.4.7 and Leo 4.4.8
@rst-ignore-tree Details
Versions
Designing @file trees
Deciding to do Leo2
A prototype
User interaction
The write code
The read code
The load/save code
Attributes, mirroring and dummy nodes
Clones
Error recovery, at last
@rst-no-head end stuff
Chapter 10: Theory of Operation
@rst html\theory.html
@rst-no-head links
Overview
Nodes
Drawing and events
Clones
Find and change commands
Tangle and untangle commands
Unicode
Unlimited undo
Key bindings
@rst-no-head end stuff
Chapter 11: White papers
@rst html\whitepapers.html
@rst-no-head links
Tk is the future of Leo
Why I like Python
Clarity
Power
Safety
Speed
Conclusions
@rst-ignore Why Leo is special
1. You can execute Python scripts directly from anywhere in a Leo outline
2. Leo's outlines are the perfect tool for organizing scripts
3. Scripts can access the structure of Leo's outlines
4. Leo's nodes naturally separate data from meta-data
5. Leo is the ultimate platform for unit testing
6. Leo is the ultimate platform for finding and changing text.
7. Leo outlines are the ultimate filing cabinet
8: Script buttons
9: The rst3 plugin
Conclusion
Allocating storage using lifetimes
Lifetime allocation
Typical lifetimes
Implications for pypy
@rst-no-head end stuff
Chapter 12: Plugins
@rst html\plugins.html
@rst-no-head links
Enabling plugins
Body pane
arrows.py
image.py
rClick.py
autocompleter.py
color_markup.py
script_io_to_body.py
Commands & directives
add_directives.py
bibtex.py
ConceptualSort.py
datenodes.py
FileActions.py
groupOperations.py
import_cisco_config.py
Library.py
macros.py
mod_autosave.py
mod_read_dir_outline.py
mod_timestamp.py
outline_export.py
paste_as_headlines.py
pretty_print.py
scheduler.py
table.py
templates.py
word_cound.py
Dialogs
gtkDialogs
Debugging & testing
failed_import.py
dump_globals.py
enable_gc.py
trace_gc.py
trace_keys.py
trace_tags.py
External editors & Open With
mod_tempfname.py
open_shell.py
open_with.py
temacs.py & usetemacs.py
vim.py
word_export.py
xemacs.py
Files
empty_leo_file.py
leoOPML.py
lineNumbers.py
multifile.py
niceNosent.py
leoToRTF
leoToHTML
leoOPML
Guis
__wx_alt_gui.py
Icon and status areas
chapter_hoist.py
nav_buttons.py
newButtons.py
hoist.py
nodenavigator.py
searchbox.py
shortcut_button.py
UNL.py
LeoN
Menus & translations
chinese_menu.py
french_fm.py
pie_menus.py
Nodes
at_folder.py
at_produce.py
at_view.py
autotrees.py
base64Packager.py
fastGotoNode.py
mod_labels.py
read_only_nodes.py
run_nodes.py
slideshow.py
startfile.py
Plugins manager & menu
leoupdate.py
plugin_manager.py
plugins_menu.py
Scripting
dyna_menu
mod_scripting
Servers
mod_http.py
Shadow files
mod_shadow.py
Spell checking
spellpyx.py
Text formatting
Leo to AsciiDoc
rst3.py
xsltWithNodes.py
Windows
cleo.py
footprints.py
EditAttributes.py
maximizeNewWindows.py
nodebar.py
redirect_to_log.py
TabbedLog.py
UASearch.py
UniversalScrolling.py
URLloader.py
@rst-no-head end stuff
Chapter 13: Writing Plugins
@rst html\writingPlugins.html
@rst-no-head links
Overview
Support for unit testing
Turning script buttons into plugins
Important security warnings
@rst-ignore menu convenience routines
@rst-no-head end-of-page stuff
Chapter 14: Using the rst3 plugin
@rst html\rstplugin3.html
@rst-no-head links
Overview
Comparison with previous rst plugins
Options
Options supporting the http plugin
Options that set command names
Headline Commands
Using doc parts
Setting defaults
The code-block directive
Required cascading style sheets
Notes about rST markup
Examples
Theory of operation
Controlling the rst3 plugin from scripts
Acknowledgements
@rst-no-head end-of-page stuff
Chapter 15: Controlling syntax coloring
@rst html\coloring.html
@rst-no-head links
Files
The colorizer's inner loop
Format of colorizer control files
Ruleset names
x.properties
Attribute dictionaries and x.attributesDictDict
Keyword dictionaries and x.keywordsDictDict
Rules, rules dictionaries and x.rulesDictDict
x.importDict and imported versus delegated rulesets
Rule methods
Arguments to rule methods
match_eol_span
match_eol_span_regexp
match_keywords
match_mark_following
match_mark_previous
match_seq
match_seq_regexp
match_span
match_span_regexp
match_terminate
Syntax coloring settings
The threading_colorizer plugin
@rst-no-head end stuff
Chapter 16: Debugging with Leo
@rst html\debuggers.html
@rst-no-head links
Using g.trace and g.pdb
Settings for winpdb
Debugging scripts with winpdb
The debug command
@button winpdb
The execute-script command with explicit debugger breaks
@rst-no-head end stuff
Chapter 17: Using ZODB with Leo
@rst html\zodb.html
@rst-no-head links
Configuring Leo to use zodb
Initing zodb
Writing data to zodb
Defining zodb keys
Reading data from zodb
About connections
Convenience routines
g.init_zodb (pathToZodbStorage,verbose=True)
v.detach()
@rst-no-head end stuff
Chapter 18: Leo and Emacs
@rst html\emacs.html
@rst-no-head links
Controlling Leo from Emacs using Pymacs
Functions in leoPymacs.py
The minibuffer
@rst-no-head end stuff
Chapter 19: Embedding Leo with the leoBridge module
@rst html\leoBridge.html
@rst-no-head links
The basics
Running leoBridge from within Leo
@rst-no-head end stuff
Chapter 20: Unit testing with Leo
@rst html\unitTesting.html
@rst-no-head links
Overview
Using @test nodes
Using @suite nodes
@rst-ignore How unit tests commands find tests
@rst-ignore Including other nodes in unit tests
@rst-ignore Unit test buttons
How the unit test commands work
@rst-no-head end stuff
Chapter 21: ILeo - the IPython bridge
@rst html\IPythonBridge.html
@rst-no-head links
Introduction
Installation and startup
Accessing IPython from Leo
Accessing Leo nodes from IPython
@cl definitions
Special node types
Launching ILeo from IPython
Declaring custom push-to-ipython handlers
Example code snippets
Example use case: pylab
Magic functions
Acknowledgements and history
@rst-no-head end stuff
@rst-ignore Old documentation - not completely valid anymore
Commands
Startup
Scripting IPython from Leo
Scripting Leo from IPython
@rst-ignore User Settings
Acknowledgements
Appendices
@rst html\appendices.html
@rst-no-head links
Bugs
Errors while tangling
Errors while untangling
Errors while reading @file nodes
Errors while writing @file nodes
Format of .leo files
Format of derived files
Unicode reference
@rst-no-head end stuff
Glossary
@rst html\glossary.html
@rst-no-head links
@rst-no-head glossary
@rst-no-head end stuff
What's New...
What's New in Leo 4.4.8
@rst html\new-4-4-8.html
@rst-no-head links
New features
New and improved plugins
New settings
@rst-no-head end stuff
What's New in Leo 4.4.6
@rst html\new-4-4-6.html
@rst-no-head links
New commands
New features
New settings
@rst-no-head end stuff
What's New in Leo 4.4.5
@rst html\new-4-4-5.html
@rst-no-head links
Bug fixed
New features
New commands
New settings
@rst-no-head end stuff
What's New in Leo 4.4.4
@rst html\new-4-4-4.html
@rst-no-head links
@rst-ignore Important new features
The Great Graph Aha
Added support for @auto files
What @auto does
Perfect import checks
Commands related to @auto
Extending the code: adding new parsers
New commands for resolving cvs conflicts
New kinds of settings trees
@buttons trees
@menus trees
New plugins
Leo's core is now compatible with jython
Improved prototype for icons in headlines
Minor improvements
Summary of new commands
@rst-no-head end stuff
What's New in Leo 4.4.3
@rst html\new-4-4-3.html
@rst-no-head links
Important new features
New commands
New settings
Plugins
Minor improvements
@rst-no-head end stuff
What's New in Leo 4.4.2
@rst html\new-4-4-2.html
@rst-no-head links
A major code reorg
New commands
New features
New and improved plugins
Settings
ZODB scripting
@rst-no-head end stuff
What's New in Leo 4.4.1 and 4.4.1.1
@rst html\new-4-4-1.html
@rst-no-head links
New commands
New features
New and improved plugins
New settings
Improved settings
Minor improvements
@rst-no-head end stuff
What's New in Leo 4.4
@rst html\new-4-4.html
@rst-no-head links
New commands
New features
Added new convenience methods for scripts and plugins
New and improved plugins
New and improved settings
@rst-no-head end stuff
Other docs
JythonShell help
original
@rst html\jythonShell.html
@rst-no-head links
Autocompleter Actions
Keystrokes
Alt Slash: Dynamic Abbreviations
Object Introspection
System access
Magic Commands
%alias anAlias
%autocall
%autoindent
%bg
%cd
%clean
%clear
%cwd
%cwd aReference
%deserialize aReference
%ed
%edit [options] [args]
%env
%hist [-n] [n1] [n2]
%kill n
%ls
%ls aReference
%lsmagic
%macro aMacro
%magic
%p
%pdb
%pdoc anObject
%pfile obj
%pinfo aReference
%prun statement
%ps
%r
%rehash and %rehashx
%reset
%run [-n -i -t [-N n] -d [-b n] -p [profile options]] file [args]
%save filename n1:n2 n3:n4 ... n5 .. n6 ...
%sc [options] varname=command
%see
%send n aReference
%serialize aReference
%swing aReference
%sx aCommand
%threads
%unalias anAlias
%url ref aUrl
%wait n
%who
%who_ls
%whos
%xslt ref1 ref2 ref3
A Note on JPIDs and the CWD
@rst-no-head end-of-page stuff
Leo Tech report
@rst html\techReport.html
Leo’s window, outlines & clones
Relations: organizer nodes, views, tasks and metadata
Plugins
Derived files and special nodes
Markup for scripts
Scripting Leo
Leo’s modules and classes
Predefined symbols in scripts
Accessing data
Traversing outlines
Executing commands from scripts
Bringing scripts to data
Unit Testing with @test and @suite nodes
Plugins and hooks
Contacts
Not used (pdf sources)
@@rst pdf docs\directives.pdf
@rst-no-head links
@rst-ignore-node To do
@rst-no-head Intro.
Overview: the six ways of creating derived files
Overview: summary of directives
@rst-ignore-node alternate representation
Reference: all about directives
@ and @doc
@all
@c and @code
@color, @nocolor and @killcolor
@comment
@delims
@encoding
@first
@ignore
@language
@last
@lineending
@others
@path
@pagewidth
@tabwidth
@raw and @end_raw
@root-code and @root-doc
@verbose, @terse, @quiet and @silent
@wrap and @nowrap
Reference: the six ways of creating derived files
@file and @thin
@nosent
@asis and @noref
@root
Sections and section definitions
Tangling @root trees with the Tangle commands
Untangling @root trees with the Untangle commands
Cweb mode
@rst-ignore-node original
@rst-no-head end stuff
@@rst pdf docs\rstplugin3.pdf
@rst-no-head links
Overview
Comparison with previous rst plugins
Options
Options supporting the http plugin
Options that set command names
Headline Commands
Using doc parts
Setting defaults
The code-block directive
Required cascading style sheets
Notes about rST markup
Examples
Theory of operation
@rst-no-head end stuff
Acknowledgements
@rst-ignore-tree Footnotes
@rst-no-head end-of-page stuff
suggestions for tutorial
@rst html\docModeOnlyTest.html
@rst-no-head links
leoFind.py
<< Theory of operation of find/change >>
leoFind.__init__
<< compute self.title >>
<< init the gui-independent ivars >>
<< do dummy initialization to keep Pychecker happy >>
Top Level Buttons
changeAllButton
changeButton
changeThenFindButton
findAllButton
findButton
setup_button
Top Level Commands
changeCommand
changeThenFindCommand
dismiss: defined in subclass class
findNextCommand
findPreviousCommand
handleUserClick
setup_command
Find/change utils
find.adjust_ivars
batchChange (sets start of change-all group)
<< change headline >>
<< change body >>
change
changeAll (sets end of change-all group)
changeSelection
makeRegexSubs
changeThenFind
doChange...Script
doFind...Script
findAll
<< create the found node and begin the undo group >>
<< create a clone of p under the find node >>
findNext
findNextMatch
resetWrap
search & helpers
<< fail if we are passed the wrap point >>
Search helpers...
regexHelper
backwardsHelper
plainHelper
matchWord
selectNextPosition
Initing & finalizing
checkArgs
initBatchCommands
initBatchText & initNextText
initInHeadline
initInteractiveCommands
printLine
restore
save
showSuccess
Must be overridden in subclasses
@rst-no-head end stuff
Release Notes
What's New...
What's New in Leo 4.4.8
@rst html\new-4-4-8.html
@rst-no-head links
New features
New and improved plugins
New settings
@rst-no-head end stuff
What's New in Leo 4.4.6
@rst html\new-4-4-6.html
@rst-no-head links
New commands
New features
New settings
@rst-no-head end stuff
What's New in Leo 4.4.5
@rst html\new-4-4-5.html
@rst-no-head links
Bug fixed
New features
New commands
New settings
@rst-no-head end stuff
What's New in Leo 4.4.4
@rst html\new-4-4-4.html
@rst-no-head links
@rst-ignore Important new features
The Great Graph Aha
Added support for @auto files
What @auto does
Perfect import checks
Commands related to @auto
Extending the code: adding new parsers
New commands for resolving cvs conflicts
New kinds of settings trees
@buttons trees
@menus trees
New plugins
Leo's core is now compatible with jython
Improved prototype for icons in headlines
Minor improvements
Summary of new commands
@rst-no-head end stuff
What's New in Leo 4.4.3
@rst html\new-4-4-3.html
@rst-no-head links
Important new features
New commands
New settings
Plugins
Minor improvements
@rst-no-head end stuff
What's New in Leo 4.4.2
@rst html\new-4-4-2.html
@rst-no-head links
A major code reorg
New commands
New features
New and improved plugins
Settings
ZODB scripting
@rst-no-head end stuff
What's New in Leo 4.4.1 and 4.4.1.1
@rst html\new-4-4-1.html
@rst-no-head links
New commands
New features
New and improved plugins
New settings
Improved settings
Minor improvements
@rst-no-head end stuff
What's New in Leo 4.4
@rst html\new-4-4.html
@rst-no-head links
New commands
New features
Added new convenience methods for scripts and plugins
New and improved plugins
New and improved settings
@rst-no-head end stuff
Previous versions...
Ancient...
Borland PC versions...
Borland 2.7 Major bug fix: please upgrade
Borland 2.6 Major changes: please upgrade
Format change: no blank lines between sentinels in derived files
Eliminated spurious read errors
@c now is the same as @code
Fixed old bugs in Untangle
Compatibility with leo.py v2.0
Changed "Batch" check box to "Show Context"
Can not ensure .leo extension
version 2.5: Fixed several serious bugs
version 2.4: The new Leo2 (Do not use this version)
Fixed clone bugs
.leo files now contain all data
Replaced archive command
Automatic update of @file trees
Errors while reading
Errors while writing
Drawbacks of @file trees
version 2.3: Do not use this version
@first directive
Archive Entire Outline command
Fixed @c syntax coloring
Fixed bugs in the find command
Fixed bug involving @file dirty bits
The Log window is now part of the Leo window
version 2.2 (beta)
version 2.1 (beta)
1.x versions
Changes made in version 1.15
Changes made in version 1.14
Changes made in version 1.13
Changes made in version 1.12
Changes made in version 1.11
Multiple parts not allowed for << section name >>
Untangling: updating an outline
Changes made in version 1.10
Changes made in version 1.9
New Execute Script command
Python window improved
Changes made in version 1.8
Changes made in version 1.7
Changes made in version 1.6
Changes made in version 1.5
Changes made in version 1.4
Outline To Noweb command
find/change Python scripts
v.commands() Python method
Changes made in version 1.3
Changes made in version 1.2
Changes made in version 1.1
Changes made in version 1.0
Changes made in version 0.19
Fixed directory bug
Added @language HTML, perl and perlpod
Eliminated @noweb & replaced @cweb with @language cweb
About cweb mode
Improved syntax coloring
Improved Print command
Improved how Untangle handles block comments
Eliminated clone windows (but not clone nodes!)
Eliminated Extended noweb Syntax
Changes made in version 0.18
File format extended
Fixed bug in languages without block comments
Added @header and @noheader directives
Added @language fortran90
Added @language perlpod
Changes made in version 0.17
Support for noweb <<*>> convention
new @cweb, @noweb, @path, @tabwidth and @pagewidth directives
CWEB mode now has a chance of working
Reduced default screen size
Changes made in version 0.16
Bug fixes
Fixed crasher involving switching windows
new @language directive
@language and @comment directives can be inherited
Untangle can now handle non-C files
Untangle now removes trailing blank lines
new @verbose, @terse and @silent directives
Default directories
Import Files command now handles Pascal , Python and Java files.
Toggle Active Pane command
Path delimiters are now '\' instead of '/'
Cleaned up code
Fixed crasher involving empty section names
Untangle warns about sections not in the outline
A limitations involving Untangle
Known Bugs & Limitations
2.x...
leo.py 2.5.1 Many improvements
New & improved commands
Tabs and spaces
Added Convert All Blanks and Convert All Tabs commands
Added Convert Tabs command
Tab widths work
Negative tab width converts tabs to spaces
Improved Preferences panel
Obsolete: Using leoConfig.leo and leoConfig.txt
Cut and Paste now works properly in all situations
Added Recent Files menu
All Extract and Import commands are now undoable
Made Cascade and Minimize All commands functional
Significant bug fixes
Fixed several bugs in the Import commands
Invalid directories no longer cause read errors
Fixed crashers
Fixed crasher when saving a new file
Fixed crashers in Remove Sentinels command
Fixed crasher in Import commands
Fixed minor bugs & improvements
Recolored body text after extract commands
Fixed bug involving missing clone mark after Move Right command
Changed defaultextension from "x" to ".x" in dialogs.
Fixed minor bug in Save and Save As commands
Fixed minor problems with documentation
Renamed Font to Set Font... and Syntax Coloring... to Set Colors...
leo.py 2.4
Fixed several bugs
Added better error recovery when writing .leo files
Dragging headlines
How to associate Leo with .leo files on Windows
leo.py 2.3
leo.py 2.2 Bug fixes and documentation revised
2.1 Import & Export commands
Import and Export commands
Fixed moves up to root position
Improved the syntax colorer
2.0 Untangle, Unlimited Undo/Redo, Syntax Coloring, etc.
Format change: no blank lines between sentinels in derived files
Unlimited Undo and Redo
Drawing and syntax coloring
Syntax coloring works for all languages
Fixed minor syntax coloring bugs
Headlines given more space
Suppressed auto-indent for Python in @nocolor mode
Tangle/Untangle
Fixed old bugs in Untangle
@c now is the same as @code
Untangle only trims trailing lines from updated nodes
Fixed Linux-specific bugs
1.0 New commands and bug fixes
Unfinished commands
How to copy an outline from Borland Leo to Leo.py
Fixed bugs
Remaining minor problems
0.08 Find, Change and Tangle commands & major bugs fixed
About the Find and Change commands
About the Tangle command
About hyperlinking
Fixed significant bugs
Other improvements
Improved memory management
The trace function (Sherlock tracing)
Improved directory and file name handling
Improvements that will be propagated back to LeoCB
0.07 Stability and scripting
Thorough testing
Removed many irritations. Some remain
Fixed bug that can drop data
Added Python window and scripting support
Added Script to convert from Leo 1 to Leo 2
Added Leo Documentation command
Added Auto indent
0.06 Minor changes for Linux
0.05 The first functional version
Testing & Performance
Installing and Running leo.py
Files & Folders
Functional Commands and Features
Non-Functional Commands and Features
Bugs, Problems and Code Quality
New Things To Do
3.x...
3.12 final
Bug fixes (major)
Fixed major undo bug
Fixed huge performance bug when handling read errors
Fixed memory leaks: one minor, one huge
Bug fixes (minor)
Fixed bug affecting encoding in headlines
Fixed bug affecting log pane
Fixed bug importing files with upper case extensions
Fixed bug involving log messages during Open commands
Fixed bug that caused some log messages to disappear
Fixed bug that disabled double-clicking when when windows were first opened
Fixed bug that forced body_pane_wraps setting to 1
Fixed bug when deleting trailing newlines in the body pane
Fixed colorizer exception when undoing paste
Fixed Go To Line Number bug
Fixed line-break bug with @nosent files
Fixed new Open With problems
Fixed problems with Convert tabs to blanks preference panel setting
Fixed problems with the code that destroys Leo windows
Fixed recent bug in the Reformat Paragraph command
Fixed refresh problem after Read @file Node command
Fixed several problems with the Open With command
Fixed Sort bug
Leo now updates ow/col numbers when plugins not enabled
Made dragging nodes more robust
Removed improper clones from LeoPy.leo
Removed unused fractional widths from leoFind code
updateRecentFiles now handles Null filenames properly
Code improvements
New functions in leoGlobals.py
New scripts
Rewrote dialog code
Reorganized vnodes and tnodes
Simplified startup code
Replaced exec with getattr/setattr throughout the code
Features
Added @wrap and @nowrap directives
Added apply button to Font panel
Added Icon & Status areas to Leo window
Added minimal support for Rebol and activescript languages
Added Write Dirty @file Nodes command
Changed OnIconDoubleClick to allow @url url comments
Hyperlinks are now enabled by default
Improved how headlines are highlighted
Improved startup logic so only one frame ever gets opened
Improved the reporting of characters that do not exist in the present encoding
Leo now correctly remembers the sizes of windows
Removed toggle << >> command
Undo now restores cursor
Updated Marks window in Mark Find and Mark Changes commands
Use "file in directory" format for entries in Recent Files list
Hooks
About hooks
Added "clear-mark" and "set-mark" hooks
Added hooks to customize popup menus
Added new hooks so that plugins may extend popup menus
Plugins
Added add_directives.py plugin
Added color_markup.py plugin
Added nav_buttons.py plugin
Added plugins_menu.py plugin
Added scripts_menu.py plugin
Improved how Leo loads plugins
Reorganized Leo folder: big change to cvs
Added scripts for Linux
3.11.1
3.11
New in 3.11 final
Bug fixes
Added call to c.redraw() in fileCommands.readAtFileNodes
Added getpreferredencoding to leoGlobals.py
Eliminated caught exception in frame.setTabWidth
Fixed bug in skip_long
Fixed bug that prevented email line in About Leo from working
Fixed unicode bugs when Tangling and Untangling
Fixed various bugs reported by Pychecker
Removed all __del__ methods
New and improved features and commands
Added patch by Davide Salomoni to OnIconDoubleClick
@lineending directive specifies line endings
Added thin_at_file_trees & load_derived_files_immediately options
** Leo now uses unicode internally
Added calls to toEncodedString before all calls to write
Check for valid encoding when setting app().tkEncoding
How Leo handles unicode
Unicode settings
Unicode theory of operation
Use app().tkEncoding when writing to log pane
** Improved hooks & a new plugin architecture
New plugin architecture
Major reorganization of hooks
About hooks
Added several new plugins
Improved Open With plugin
Added logic to retain log output until a log exists
New configuration options & plugins
Plugins
Unicode settings
Colors for Show Invisibibles command
look_for_control_drag_on_mouse_down option
body_insertion_cursor_color setting
time/date settings
New commands
Toggle Angle Brackets
Insert Body/Headline Time/Date
Go To First/last Node
Go To Parent
Go To Next/Previous Sibling
Write Missing @file Nodes
Improved commands
Added support for body/headline_gmt_time settings
Tangle now supports output_newline option
Major improvements to expand/contract commands
Leo now allows multiple writes of cloned nodes
The Sort Siblings command can now sort top-level nodes
Changed locks on customizeLeo.py
Other improvements
Allow color param when queuing messages to log pane
Improved scrolling when moving right
Put file name first in window title
Leo scrolls partially visible headlines into full view
Allowed @comment with @language plain
The Find button is now default button in the Find panel
Improved syntax coloring for html and xml
example of syntax coloring for html
Improved Prefs panel
Removed setup.py from distributed files
Bug fixes
Eliminated potential hang in Open With command
Fixed 2 line number bugs
Fixed bug involving nested comments in sentinel lines
Fixed bugs in promote/demote
Fixed configuration bug.
Fixed crasher in undo logic
Fixed drag problem
Fixed huge performance bug in v.unjoinNode
Fixed long-standing control-v bug on Linux
Fixed minor import bugs
Fixed problem with block comments
Fixed several problems revealed by French plugin
Fixed several problems with noweb mode
Fixed syntax coloring bugs
Full recolor after paste
Installer now creates plugins directory
Removed duplicate redraws when renaming nodes
Udated recent files menu when saving a new .leo file
Worked around bugs in Python 2.3 a1
3.10
Fixed bugs
Allowed abbreviated xml tags.
Changed shortcut to Find Previous so Alt - F4 closes Leo
Changed url of help file
Fixed @nsf bug reported by Travers A. Hough
Fixed a bug in Untangle
Fixed bug in Python importer
Fixed bug involving redrawing screen initially
Fixed bugs involving @nosentinelsfile
Fixed crashers in colorizeAnyLanguage
Fixed environment bug in Execute Script command
Fixed major memory leak
Fixed path problem in paths passed to tangle_done.py
Fixed problems with Open With code in customizeLeo.py
Fixed Recent Files command
Fixed reversion involving @comment & @language together
Fixed undo bug
Added features
New Mark Clones and Go To Next Clone commands.
New Export Headlines command
Control-dragging a node now clones it
New "Node Only checkbox in the Find/Change panel
@root options
Converted leoConfig.py to use @root-code
Added @file options
Added support for underlined menu items
Improved Leo's window icon
Added easy way of replacing any Leo code
Added convenience routines to redirect stderr and stdout
Added "event1" and "event2" hooks
Added contributed code to support @read-only nodes
Known bugs
Bugs in undoReplace logic
leo.py 3.9
Fixed bugs
Fixed bug involving @language
Correctly colors Pascal's "private" and "uses" keywords
Fixed a major bug in top()
Fixed bugs when importing Java files.
Convert All Blanks/Tabs commands honor @tabwidth directives
New documentation for leo.py 3.9
Major performance improvements
Incremental syntax coloring speeds redraws
Incremental undo reduces memory usages significantly
Major configuration improvements
Chapter 8: Customizing Leo
Using leoSettings.leo and @settings trees
Obsolete: Using leoConfig.leo and leoConfig.txt
Using plugins and hooks
Overview of plugins and hooks
New plugin architecture
About hooks
SECURITY WARNINGS
The danger of trusting code in shared .leo files
NEVER use this kind of code in a hook!!
Don't use rexec !!
<< change all instances of rexec to exec in v's body >>
<< delete thisNode >>
<< clear the undo stack >>
Convenience routines for plugins
Convenience functions to enable and disable the "idle" hook
Convenience methods to create, destroy and modify menus
createMenuItemsFromTable
createNewMenu
createOpenWithMenuFromTable
deleteMenu
deleteMenuItem
Example: how to create a menu
Translating menus into other languages
Support for unit testing
Extending the format of .leo files
Attaching temporary attributes to vnodes and tnodes
Recommended conventions for plugins
Script Find and Script Change
How it works
Using the initScriptFind script
Ideas for using scripts
How do I add a new menu item from a plugin?
@url http://www.pythonware.com/library/tkinter/introduction/index.htm
@url http://www.tcl.tk/man/tcl8.4/TkCmd/contents.htm
More flexible creation of non-existent directories
New commands & features
@url
Execute Script command
Go To Line Number command
More flexible creation of non-existent directories
Much better support for cweb
About cweb mode
Open With command
createOpenWithMenuFromTable
Optional Emacs-style auto-indent
Reformat Paragraph command
Appendix 1 to Chapter 4: Using @rawfile, @silentfile and @nosentinlefile trees
leo.py 3.8
Fixed bugs
Crashers
Fixed another crasher in scanAllDirectives
Bugs involving paths & derived files
Fixed @delims "round trip" bug
Fixed cweb sentinel bug
Fixed import to @root problems
Leo generates @@ sentinels only for real Leo directives
Minor syntax coloring bugs
Colorizer now recognizes comments after preprocessor directives
Syntax color perl's alarm function
Fixed block-comment bug in Java and HTML
Minor user interface bugs
Worked around Control-T bug
Fixed bug involving menu pastes in headlines
fixed Unicode bug in setBodyStringOrPane
New & changed features
New @rawfile & @silentfile trees
Appendix 1 to Chapter 4: Using @rawfile, @silentfile and @nosentinlefile trees
New @raw, @end_raw and @quiet directives
@raw and @end_raw directives delimit raw text
@verbose, @terse, @quiet and @silent directives control comments in @root trees
Much better support for CWEB
About cweb mode
Allow @comment and @language to coexist
Configuration settings and commands
Added stylesheet option to support <?xml-stylesheet...?> line
Added Configuration Commands to help menu
Added output_initial_comment option
Added output_newline option
Changed path_directive_creates_directories to create_nonexistent_directories
Minor changes
Added support for forth language comments
All export commands now use output_newline option
Changed names of commands in help menu and corresponding entries in leoConfig.leo
Created es_exception
Created reloadAll in leoGlobals.py
Forced focus to body pane after ending headline edit
Use // as single-line comment in Java
wrote "finished" after write @file nodes command
Coming soon: Leo 4.0, a major improvement
leo.py 3.7
Fixed Bugs
Language and syntax coloring bugs
Fixed @comment bug
Fixed colorizing for "while" in C
Fixed @language plain # bug
Fixed @language plain single-quote bug
Bugs in Edit body commands
Bugs relating to tangling and derived files
Fixed major bug in @file read code
Fixed minor read bug
Fixed @comment bug
Fixed a bug that affected wrapping in doc parts
Other bugs
Fixed reversion in Tangle/Untangle code
Fixed undo cloned headline bug
Fixed Find previous bug
Fixed tab problems
Leo now remembers insert point always
Removed setup.py from binary distribution
Improvements
Many new user options
General configuration options
path_directive_creates_directories
relative_path_base_directory
remove_sentinels_extension
write_clone_indices
Secondary pane ratios
User-configurable colors
User-configurable shortcuts for commands
Improved support for Unicode
End of cursed newlines
Code is now compatible with Python 2.1
Better file and path handling
Better support for Perl+pod
New End Edit Headline and Abort Edit Headline commands
Allow reads and writes of cloned @file nodes
Leo now closes an empty window when opening a recent file
Improved derived files
Improved enabling of menu items in popup menus
About Leo dialog is now non-modal
leo.py 3.6
Known bug: problems with Python window
Bug fixes
Fixed problems with opening and writing leoConfig.txt on Linux
Fixed problems renaming files on Linux
Fixed missing headline bug on startup
Improved call to os.path.join in leoApp.finishCreate
Improved how directories are handled in @root trees
Dave Hein: fixed Tk 8.4 problem in Prefs Panel
Dave Hein: added CheckVersion to leoUtils.py
Dave Hein: the Python window now works on Linux.
Steven P. Schaefer: Improved handling of directives in @root trees
Steven P. Schaefer: Fixed cursed newline bug for Linux
Improvements to existing features
Leo now remembers scrollbar position and insert point of previously visited nodes
Body pane now gets focus after Go Back/Next
Improved all commands in Help menu
Removed most error messages in atFile::read logic
Added shortcuts for Read/Write @file Nodes commands
Tomaz Ficko: Added support for MouseWheel (Linux only)
New features
Added Match Brackets command
Added PHP support
Added LaTex support
leo.py 3.5
Bug fixes
Called cf.flush in leoConfig.update
Fixed crasher in leoFileCommands.readOutlineOnly
Fixed crasher when leoConfig.txt did not exist
Fixed cursed newline bug in leoAtFile
Rewrote scanAllDirectives routines to handle relative paths
Suppressed erroneous tangle warning about relative paths
Improvements
Added configuration settings for horizontal scrollbars
Added commands to the help menu
Added logic to test for read-only files
Added importFiles script
leo.py 3.4
Configuration settings and leoConfig.leo
Added comments to leoConfig.txt about split direction and ratio
Added save_clears_undo_buffer config option
Corrected spelling of limit_directory_search_extenstion
Created leoConfig.leo
Fixed a major config bug. This fixes font problems
Improved Recent Files menu
Leo honors pane ratio stored in .leo files
Leo writes prefs if leoConfig.txt is read-only
Made leoConfig.txt be read/write by default
Toggle Split Direction now updates leoConfig.txt
Documentation for code in leo.py that may be of wider interest
Code hidden in leo.py
c2py.py
disStats.py
Tkinter utilities
Font dialog
Syntax coloring code
Tree code
Fixed bugs
Fixed another clone bug: created setAncestorsOfClonedNodesInTreeDirty
Fixed bugs that delayed writing of find and prefs panels
Fixed revert problems in font panel
Fixed several unicode bugs
Fixed wandering insertion point bug
Minor improvements
Syntax colorer now honors @comment
Added @ignore to "raw" imported files
Added log message for Remove Sentinels command
Improved highlighting of whitespace
Remove Sentinels command now uses .txt extension instead of .tmp
leo.py 3.3
Added support for Unicode
Improved the Import commands & fixed Javadoc problem
Fixed crasher when Tangling
Fixed problems with negative tab widths
Fixed numerous problems related to configuration settings
leo.py 3.2
Nested @others directives now valid
@file test.txt
class a
a::one
a:two
class b
b::one
b:two
Improved Import command
Reassigned shortcuts in the Outline-Move/Select menu
Fixed crasher in the Preferences Panel
Improved syntax coloring of continued C strings
Made many changes to Color Panel
Added email address & URL to About Leo dialog
added disStats.py
leo.py 3.1
Added compare panel
Added new settings to leoConfig.txt
Changed precedence scheme for preferences
Fixed @tabwidth, @pagewidth and @language directives
Flatten Outline now escapes only the first non-blank character of each line.
Open Python Window command adds path to IDLE automatically
Python 2.2 required dialog tells where to download Python 2.2 and Tk 8.3
leo.py 3.0
Optional new file format
New features (in approximate order of importance)
Added many settings to leoConfig.txt file
New windows now open using config params.
Added autoscrolling in the outline pane
Color panel
Font panel
Leo now opens windows at the position in which they were saved
Added Toggle Split Direction
Improved syntax coloring for @comment directives
Leo warns and aborts if not Python 2.2 or above
All panels now have labeled frames and grooved borders
Leo directives are now colored green by default
Print a traceback message for all serious exceptions
@comment supports comments starting with REM
Fixed bugs (one crasher)
Fixed crasher in atFile.scanAllDirectives
Fixed syntax coloring bug involving Leo directives
Windows now open without visual problems
Made Convert Tabs, Convert All Blanks and Convert All Tabs undoable
Made Prefs panel non-modal
4.0... New read logic eliminates read errors, eliminated child indices
4.0.1 through 4.0.4
4.0 final
4.0 beta 4
4.0 beta 3
Fixed bugs
Fixed bug that caused some clones not to be marked as clones
Corrected problems with setting icons on Linux
Fixed crasher in sentinelName
Reenabled orphans & ignored test in new write logic
New features
Added support for unknown tnode and vnode attributes
Added build number to signon
Added better error message in setDefaultIcon
4.0 beta 2
To-do for 4.0 final
Fixed Bugs
Added crucial defensive checks in v.headString() and v.bodySting()
Ensured newlines before all sentinels in @rawfile
Fixed bugs involving find params
Fixed Python Import bug
Fixed several more unicode bugs
Fixed crasher in Go To Outline command.
Fixed @rawfile write problem
Improved commands
Finished Import Derived File command and made it undoable
Moved Clear Recent Files menu item into Recent Files menu
Added better log message for Convert All Tabs/Blanks commands
Marked changed nodes & make the @file node and the outline dirty.
Rewrote icon code so it doesn't use PIL or tkIcon in Python 2.3
Created leoGui base class for tkinterGui class
New and improved settings
Added support for two new settings affecting drags
changed default for config.write_old_format_derived_files
4.0 beta 1
4.0 Theory of operation
New commands & options
New write_old_format_derived_files option
New Clear Recent Files command
New Import Derived File command
New Write 3.x/4.x Derived Files & autosave
New plugins
New read logic and greatly inproved error recovery
Added test for unvisited nodes in read logic
Error recovery is _much_ better than before
Improvements & bug fixes
Added horizontal scrollbar in body pane when @nowrap in effect
Added support for Python 2.3
Leo recycles window objects only if more than one window open
Removed "not undoable" message from Read @file Nodes command
Removed Open Python Window command
Simplified read and write code
4.1... gnx's
4.1 final
Added several new plugins
Added Toggle Angle Brackets command
Changed Undo/Redo messages
Fixed clone bug when pasting nodes
Investigated encoding problem: it's a Python 2.3 bug
4.1 rc4
New plugins in 4.1 rc4
mod_http.py plugin: Bernhard Mulder
newButtons.py plugin: Paul Paterson
nodenavigator.py plugin: Paul Paterson
rowcol.py: EKR
rst2.py plugin: Steve Zatz
searchbox.py plugin: Paul Paterson
status_line.py plugin: EKR
New features in 4.1 rc4
Leo no longer automatically draws the status area
Esc and enter key now work in the find panel
Improved message for orphan nodes
Eliminated marking nodes dirty unnecessarily
Execute Script command now ends all nodes with a newline
Added message when plugins are disabled
Created status_line.py plugin
Simplified operation of script-find/change & improved documentation
Script Find and Script Change
How it works
Using the initScriptFind script
Ideas for using scripts
Added done message to Mark Changed commands
Bugs fixed in 4.1 rc4
Fixed several bugs when writing derived files
Fixed several crashers
Fixed "bad leo file" when reading some 3.x .leo files
Fixed huge performance bug in cut/copy node commands
Leo now properly re-enables drawing after exceptions
Fixed major bug in tkFind.init
Fixed bug in Move Up command
Fixed bug in Import Derived File
Fixed bugs related to saving read-only files
Fixed bug in Import Python Window command when using Python 2.2
Fixed bugs in Convert All BlanksTabs commands
Fixed crashes in open_shell.py plugin
Fixed several bugs involving cut & paste
Fixed whitespace problem in leoTkinterGui.py
Fixed glitches when inserting node in hoisted outline
Fixed bugs in search command
Bug fixed in previous 4.1 releases
New code-level features
New configuration settings
New features
4.1 rc3
Bugs fixed in this release
Bug fixed in previous 4.1 releases
New code-level features
New configuration settings
New features
4.1 beta 5
Changes made in 4.1 beta 5
New and improved features
Honor outline/body pane ratio when opening files
Leo now adjusts newly opened windows so they fit on the screen
Tested support for Unicode file & directory names
Added code so @url nodes may open .leo files
Fixed problems with @lineending platform
Bugs fixed
Fixed crasher in Apply Settings command
Fixed crasher in Toggle Angle Brackets command
Fixed crasher when setting Icon in Linux)
Fixed Find panel bug on the Mac
Fixed Import backslash-newline bug
Fixed Linux import problem
Fixed Recent files crasher
Fixed Replace Blanks command
Fixed Serious Undo Change All bugs
Fixed several long-standing bugs related to Extract commands
Changes made in earlier 4.1 betas
Code-level features
Regression tests started
Code reorganized to support other guis
Made app.forceShutdown work in "idle" hook
Fixed bugs
Fixed bug involving 0x1a characters in body text.
Fixed first node-only find bug
Fixed bug in idle_body_key
Fixed LaTeX syntax coloring bug
Improved format of .leo files
Leo now ignores unknown prefs and find prefs
Leo now writes node_only find prefs
.leo files are now cvs-friendly
New & improved commands
Running Leo in batch mode
Executing Python scripts in body text
Added Check Outline command
Added Hoist/De-Hoist commands
Added script-based find/change commands
Script Find and Script Change
How it works
Using the initScriptFind script
Ideas for using scripts
Leo now does an auto-save only if files have actually been changed.
Shift commands now shift single line if no selection
New config settings
4.1 alpha 1
4.2... @file-thin, shared tnodes
4.2 final
4.2 rc1
Added new features
Added c.frame.openDirectory to sys.path when executing scripts
Added expanded_click_area option to disable left click logic in outline pane
Restored the "iconclick1/2" hooks
(Allow longer headlines for to support long url's)
Report
Fixed bugs
Disabled perfect import
Fixed bugs in Tangle/Untangle
Fixed Import Derived Files command
Fixed parsing of minimal <preferences> tag
Fixed problem with tabs on MacOs
Fixed read errors with @language html
Made sure a proper message is given with invalid versions of Python
Removed failed assert from colorizer
Removed spurious "Warning: updating changed text" messages
Shifted all Alt-shortcuts to Ctrl shortcuts on the Mac
4.2 beta 3
Bug fixes
Leo gives the user a chance to save read-only files
Fixed some unit-test bugs
Added 3 .cascading style sheets to the distribution list
Fixed some bugs in g.importFromPath
Fixed major bug in write logic
Fixed bug in p.isAncestorOf
Leo now writes only the currently selected tree when pasting to the clipboard
Fixed performance bug when reading .leo files
Leo now reports problems with bad directories more clearly
Leo reads collapsed xml tags properly in .leo files
Leo makes brings the confirm save box to the front
Improved how es_exception gets line number of errors
Fixed major bug: changing headline now marks subnodes dirty
Leo now gives update warning only once per derived file
Leo updates tnodeLists properly in all situations
Fixed several leaks of positions
Fixed all unit tests so they work with both Python 2.2 and Python 2.3
Features
@test and @suite greatly aid unit testing
New scripts in test.leo make it very easy to use the gc, profile and timeit modules
Import dialogs allow multiple selections
New Check menu and commands
Perfect Import feature automatically corrects imported files
Improved performance of outline pane
The Go To Line Number command ignores all @all nodes
4.2 beta 1 & beta 2
New coding conventions
Extending the format of .leo files
in 4.2 b2
Savedmarks and expantion state in <v> elements for @thin nodes
Marked all related @thin nodes dirty when a node changesd
Fixed bug when reading 4.1 files with topology errors
Leo passes all important pychecker tests
in 4.2 b1
Changed *nix install script
Fixed bugs
Made "end1" and "ilde"events work again
Put drawing hooks back in
Fixed syntax colouring Bug in html mode
Colorizing fixes
Fixed Select All bug
Fixed bugs in @tab_width: support backspace with negative tab width
Fixed bugs in Remove Sentinel command
Eliminated spurious error messages in Import Derived File command
Removed gnx in headlines when importing thin derived files
Fixed bugs reading 4.1 files
Fixed Open With bug
Fixed Go To Line Number command
Fixed crash when importing Borland wstring.cpp
Fixed bug in insertBodyTime
Fixed bug when pasting large text into headlines
Fixed bug in delete command
Fixed oops: nullGui setIdleTimeHook
Fixed problems with trailing newlines and spurious changed bit
Fixed headline key handling
Fixed Problems executing script
Fixed problem with PHP and @last
Fixed bug when writing unknownAttributes
Fixed bugs opening a second file
Fixed bug: @last silently failed when extra lines exist
Fixed hang when dragging from one clone copy to another
Fixed crash in Write Missing
Fixed bug in getScript
Fixed problems with @all
Fixed double print in Execute Script command
Fixed bug reading leo.nsi
Added new features
Allowed </leo_header> tag
Replaced the word "Leo" with Leo icon in Find/Compare/Prefs windows
Improved Import command slightly
Added 3 files to distribution lists
Supported @tabwidth in indent/dedent
Import now creates absolute path
Created @killcolor directive
Added Paste Retaining Clones command
Added readLineGenerator & readLineClass to leoGlobals
Much better error handling in executeScript
Recovered nodes when reading .leo files containing topology errors
Generalized write-to-string logic
Added case_sensitiveLanguage to colorizer
Write entire @thin tree on write errors
Handled inner @language and @comment properly
Better reporting of body text conflicts
Improved error handling for unknownAttributes
Read and write all t.unknownAttributes in top vnode of an @thin tree
4.2 a3
Bug fixes
Fixed copy/paste operations involving @thin trees
Fixed Change Headline command
Eliminated spurious "Not written x.tmp" message after write errors
Fixed problems saving unknownAttribute field
Fixed unicode problem in the Dump Outline command
New Features
Leo ignores all directives in @all trees
@+-middle sentinels allow sections to be defined in grandchildren
@clone sentinel allows siblings to be cloned
Created @thin, @nosent, @noref and @asis abbreviations
Appendix 1 to Chapter 4: Using @asis, @noref and @nosent trees
Made undo extensible
Started work on simple new undo scheme
Created new c, p, v iterators
Known bugs
4.2 a2
Implemented @file-thin
Fixed bugs
Fixed clone bug that caused parts of outlines to disappear
Fixed long-standing problem with the outline-only command
Made sure file indices are always assigned when writing files.
Fixed problems with missing tnodeList with @file-noref
Added t.writeBit
Dangers of @file-thin
4.3...@settings
4.3.3 final
Fixes made in 4.3.3
Rewrote documentation
Bug fixes...
Fixed various unicode bugs
Fixed bugs relating to recent files
Fixed minor crasher in colorizer
Protected several methods used by plugin manager
Added test files to distribution list and cvs
New and improved plugins
New rst3 plugin
Improved spellpyx plugin
Improved vim and openWith plugins
New & improved features...
Added g.es_print, g.es_trace function
Improved PrettyPrinting
4.3.2 final
Rewrote documentation
Bug fixes...
Fixed various unicode bugs
Fixed bugs relating to recent files
Fixed minor crasher in colorizer
Protected several methods used by plugin manager
Added test files to distribution list and cvs
New and improved plugins
New rst3 plugin
Improved spellpyx plugin
Improved vim and openWith plugins
New & improved features...
Added g.es_print, g.es_trace function
Improved PrettyPrinting
4.3.2 beta 1
4.3.1
Bug fixes...
Fixed bug in @ratio setting
Fixed crasher footprint plugin
Fixed invalid position bug)
Fixed undo problems in unit tests
Made sure same case is used in all recent files entries
Made sure all dialogs gets focus when they are run
Improved Resize To Screen command
Made sure comments are always visible in setting dialog even for non-@ nodes
Fixed problem with leading @ in body text
Fixed several crashers while undoing a move involving clones
Fixed Unicode encoding problem
Fixed problem with coloring @language plain
Fixed bug: Mark Clones command did not work
New features...
Created separate helpers for idle_body_key
Made all Mark commands undoable
Removed dependence on profile and pstats modules from leoTest.py
Added support for tk resource files
Added support for coloring the PL/SQL language
4.3-final
Fixed crasher when pie-menu plugin enabled
Fixed crasher in Extract Section Command
4.3-beta 2
Fixed bugs...
Fixed nodenavagator bug
Fixed LaTex Coloring bug
Error messages in scripts are now redirected properly.
Fixed 2 crashers in nav_buttons plugin
Fixed crasher in yoffsetTree
Fixed crasher in undo
Fixed several problems with Extract and Extract Section
Fixed bug with Delete in headlines
Fixed bugs re initial_splitter_orientation & @strings & @ints generally
Fixed bug with hoist + insert
Fixed problem with settings dialog position when panes split horizontally
Fixed problem changing shortcut & redid shortcuts widget
New Features...
Marking any node sets the outline changed
Allow quoted urls in @urls nodes
Moved executeFile into core
Rewrote g.getScript using at.writeFromString
Added define_name arg to c.executeScript
4.3-beta 1
Fixed bugs...
Made sure NameErrors are reported with tracebacks in scripts
Finally! fixed .leoID problem!
Investigated problem with LeoPluginsRef.leo
Fixed conflicts in menu shortcuts
Fixed bug in p.initStatus caught by pychecker
Fixed crasher in import logic (leoAtFile)
Put in protections against unbounded recursion in idle_scrollTo
New features...
Created stand-alone leoGlobals.py module
Leo now ignores problems opening settings file for chapters plugin
Improved write logic
Rewrote the undo code
Implemented undo/redo for Paste Retaining clones
Added support for 'str_' uA's
Removed unused params from leoAtFile.py
Leo saves recent files info in .leoRecentFiles.txt files
What I did
New plan
Finished all @settings coding
4.3-a4
Fixed bugs...
Fix colorizer bug for initial @nocolor in @root nodes
Fixed @wrap bug
Fixed change-all bug
New features...
Created Add Comments and Delete Comments commands
Deprecated new_c key in hooks, added c key
Added the 'before-create-leo-frame' hook
Added support for mod_labels plugin
Revised plugins for the 4.3 code base
4.3-a3
Bugs
Fixed crasher in Tangle
Applied patch to rst2 plugin
Revised searchbox plugin so it works with Leo 4.3
Fixed bugs in nav_buttons and nodenavigator plugins
Made sure Leo asks for leoID at most once
Fixed botch in g.pdb
Fixed crasher when executing a script if the script was selected text in a new window
New features
Added sets.py to distribution
Added color='suppress' hack to g.es
4.3-a2
To do: Improve how Leo handles recent files
Bugs fixed...
Fixed very old bug in Undo Insert Node
Made sure to remove duplicates from recent files
Fixed indentation problems in leoTkinterFind.py
Changed leoConfig.txt to leoSettings.leo in Help menu, etc.
Investigated recent files problems
Improved queuing of log messages
Fixed crasher in Change All command
Fixed crasher in script button
Fixed print problems on the Mac
leoTest.runTests now makes copies of all positions
Fixed problems with unit test file paths
Made local config settings work again
Fix problems searching for nothing but whitespace
Fixed problems with typing return in the Find panel
Buttons no longer work in toolbars when settings dialog is open
Fixed bug in delayed focus logic
Made sure Leo asks for leoID at most once
Leo now prints unicode characters properly in the log pane
Fixed various problems with opening files with Unicode filenames
Fixed bug reading encoding field in derived files
Allow indented code blocks to be run using Execute Script command
Fixed problems found by pychecker
New features...
Added undo granularity
Undoing operations
Added support for top-level init function in plugins
Changed name of Paste Retaining Clones to Paste Node As Clone
Added leoPlugins.leo to Help menu
Script buttons can request to be removed
Improved documentation in several nodes in leoSettings.leo
Predefined c,g & p in scripts, unit tests & test routines
Changed name of Preferences command to Settings
4.3-a1
Defining features of 4.3
Using @settings trees and leoSettings.leo
Using leoSettings.leo and @settings trees
Unfinished configuration features
Rewrote Leo's read/write logic
Added Plugins Manager plugin
You can install third-party extensions in Leo's extensions directory
Fixed bugs...
Major bugs: these bugs corrupted derived files!
Fixed double doc part bug
Fixed bug in how Leo writes thin derived files
Commands
Fixed problems with spawnv option of openWith
Fixed bug in Remove Sentinels command
Fixed bug re Paste Node As Clone
Fixed Pretty Print commands for Python 2.4
Fixed crasher in Import Derived Files command
Search commands are now restricted to hoisted area
Distribution
Fixed file association in leoDist.leo
Files
g.import wrappers return module if it is in sys.modules
Disabled changes to comment delims in @@language and @@comment sentinels
Made sure files that differ only in line ending get written if @lineending is in effect
Fixed bug: @nosent wrote sentinels!
Fixed bug in replaceTargetFileIfDifferent
Made sure that @ignore forces writing of inner @thin trees
Fixed crasher when attempting to write a derived file to an invalid path
Fixed Python 2.4 deprecation warning when saving .leo files
Fixed crasher in getOutputNewline
Always use os.rename in utils_rename
Fixed bugs handling @language & @comment in atFile.scanAllDirectives & g.scanDirectives)
Gui
Put the scrollWheel workaround in createTkTreeCanvas
Menus
Fixed problems with Control-E
Better handling of duplicate menu shortcuts
Nodes
Fixed crash after cutting an imported node
Removed invalid assert in lastVisible
Fixed bugs in tnodes_iter and unique_tnodes_iter
Plugins
Fixed two bugs in Plugins Manager plugin
Fixed bug re referencing destroyed ivars
Fixed bug in registerOneHandler
Fixed conflict between settings panel and chapters plugin
Pychecker
Scripting
Fixed unbounded recursion with --script and redirected output
Script buttons now execute the entire script
Fixed error reporting in executeScript when the error happens outside the script
Startup
Non-existent command-line file becomes name of new Leo wiindow
computeHomeDir now handles references to other vars
New or improved features...
Using @settings trees and leoSettings.leo
Using leoSettings.leo and @settings trees
Unfinished configuration features
Code
Rewrote Leo's read/write logic
Added g.cantImport
Added g.fileLikeObject.readline
Added support for g.app.debugSwitch in es_exception
Restored drawing/event hooks
Added p=p param to all hooks containing v=v
Implemented delayed focus scheme
Commands
Added 'Expand Or Go Right' and 'Contract or Go Left' commands
Added keyboard shortcuts to find panel
Find panels are now associated with individual Leo windows
Find panels are now inited from @settings nodes
Improved Go To Line Number and Execute Script commands
Improved support for relative path names
Implemented 'Undo Clear Recent Files'
Removed old-style write commands
Plugins & extensions
Added Plugins Manager plugin
You can install third-party extensions in Leo's extensions directory
Improved doHandlersForTag
Leo now associates modules with hook handlers
Syntax Coloring & languages
Added support for Ada
Added support for Forth
4.4 minibuffer, keys, autocompletion, multiple log panes
4.4 alpha 5
Fixed bugs
Made sure focus doesn't go to log during tab completion or after writes to log
Fixed problem with getScript in batch mode
Text box is now selected in goto-line-number command
Restored headkey & bodykey hooks
Fixed ancient bug in read error logic that hung Leo
Fixed many headline problems
Fixed problem in reformatParagraph
Installed LeoUsers patch
Improved Import Derived Files command.
Fixed crasher in backwardDeleteCharacter
Fixed recent bug: dialogs now get focus properly when first opened.
Made sure shortcuts are printed clearly by k.registerCommand
Suppressed crash undoing a clone followed by a drag
New features
created ut.leo, ut.py and ut.bat
Added modes/*.xml to distribution
Revised cursor movement commands and added selection-extension commands
Added classic key bindings in leoSettings.leo
Allow multiple key bindings to the same command
Settings command now opens leoSettings.leo
4.4 alpha 4
Quick Start
The 'key' features of 4.4
Leo's minibuffer works like the Emacs mini-buffer
@shortcuts nodes in leoSettings.leo allow per-pane bindings
The scripting plugin allows key bindings
EKR shortcuts
Leo now ignores key bindings in menu tables
Status of minibuffer commands
New in alpha 1...
New options
The @bool useMinibuffer option
The @bool useCmdMenu option
Options for selected body text
New mini-buffer commands
New code-level features
Dictionaries of keys and commands
Functions that return the present key bindings
The registerCommand helper
Bugs fixed (in 4.3 code base)
Leo protects c.endUpdate with a 'finally' clause
Added kludge to solve infamous control-v problems
Fixed bug in Leo's read logic
Fixed bug in goto-last-node.
Leo now reads @settings trees when opening a .leo file from another outline.
Improved g.removeExtraLws
New in alpha 2
The tabbed log
Programming the tabbed log
New minibuffer commands
Optional generation of closing brackets
New settings in leoSettings.leo
Improved and retired plugins
Improved the scripting plugin
Retired the TabbedLog plugin
Many code-level improvements
Fixed minor bugs
New in alpha 3
The New and Newer World Orders
Bugs fixed...
Fix crasher in Open logic
(Undo ends editing
Disabled minibuffer when not in use
Fixed bug in Find Backward
Improved Spell tab
New features
Created scripts.leo and unitTest.leo
c.executeMinibufferCommand executes a minibuffer command by name
Improved perl entries in language dicts
Code-level changes
Changed edit_text to edit_widget everywhere
Removed tree ivars
Removed frame.begin/endUpdate
New in alpha 4
Bugs fixed
Changed scripting plugin so files opened with buttons stay in front
Fixed undo/redo bugs
Fixed focus problem with tab completion
Fixed minor Save bug
Fixed long-standing problem with Plugins Manager plugin
Fixed 2 outline editing bugs
Fixed crasher in deleteNextChar
Fixed new headline bug
Fix problems applying settings
Fixed several bugs in rst3 plugin
Code changes
Removed later arg from c.frame.xWantsFocus
Created enableTclTraces
Eliminated w.update in g.app.gui.set_focus
New & improved features and files
Moved all scripts into scripts.leo
Improved how the New Tab and Rename Tab commands work in the log pane
Improved the appearance of the Spell tab
Added Clone-find checkbox to the Find tab
Improved find tab
Improved formatting of shortcuts in print-commands and print-bindings
Added settings for vim plugin
Put up a dialog if can't import Pmw
Bound <Return> to end-edit-headline
4.4 beta 1
Bugs fixed
Fixed minor headline problems
Fixed undo problems
Improved word-export plugin
Removed a bad use of g.app.log in the find panel
Fix crash: tab in minibuffer
Installed patch for headline width
Redraw screen properly after Move To Next Dirty
Fixed focus bug
Made sure to bring proper window on top in settings.leo button
Arrow keys now clear the text selection
Fixed several minor bugs
Fixed problems with plugins
Fixed old file handling bug
Use shutil.move in g.utils_rename
Simplified k.copyBindingsToWidget and eliminated k.onTextWidgetKey
Made sure that focus stays in body during tab completion
Leo now puts focus in body pane after deleting a window
Fixed many binding problems
Fixed extend-selection problems
Fixed per-pane bindings!
Always redraw the screen after editing a label
Code level changes
Removed g.top from Leo's core and all plugins
Created c.exists ivar and related logic
Call c.setLog in all entries into code
Generalized doCommand
New features
Installed many standard bindings to leoSettings.leo
Added Check Bindings script in leoSettings.leo
Scripts now maintain original focus
Added scroll-up/down-extend-selection commands
Improved cursor move/extend commands
Added support for @mode nodes
keyboard-quit restores default input mode
Added discusion to FAQ about when deleting a node is 'dangerous'
When is deleting a node dangerous?
4.4 beta 2
Bugs fixed
Fixed crasher in Save button
Fixed minor bugs & made minor improvements
Fixed two annoying headline glitches
Insert headline didn't redraw headline properly in vim mode
Improved printBindings, printCommands & modeHelp
Fixed crasher re BackSpace in log window
Fixed crashers in cut/copy/paste commands
Fixed crasher when clicking the close box during a long command
cloneFindAll now honor present find settings
Double-click didn't work in the body pane.
Improved body.makeInsertPointVisible
Fixed cut/copy/paste from menu
Fixed major blunder: tree.onHeadChanged sets focus only if there was a real change
Disabled plain-key bindings in insert/overwrite modes
Disabled auto-scrolling in outline pane on clicks
move-outline and find commands force a screen scroll
Fixed undo problem in headlines
Found the cause of 'sticking focus' problem
Fixed tree icon bug
Set remembered column properly in prev-line and next-line
Fixed focus problems in spell tab
Fixed problem with body_gmt_time setting
Made sure save updates the open directory
Fixed sort-lines problems
Fixed bug: paste outline lost headline editing
Code improvements
Removed code in c.begin/EndUpdate and c.endEditLabel that tried to save/restore focus
Improved tree allocation
Created c.masterFocusHandler
Added unit tests for key dicts
Special-cased commands for minibuffer
Made sure yield works with Python 2.2
Use os.getenv('User") if it exists to get initial cvs name
Improved commands
Minibuffer-oriented find commands
Leo remembers the previous open directory
Improved plugins
Fixed problem with view plugin
Installed cleo patch
New commands
Minibuffer-oriented find commands
New settings
User input modes
4.4 experimental 1
Fixed (maybe) problems with unicode characters & caps lock
Restored some legacy bindings
Fixed crasher in Go To Line command
Fixed menu problem on Linux
4.4 a6
Fixed urgent compatibility problems
Minor bugs fixed
New debugging options in leoSettings.leo
4.4 a7
Bugs Fixed
Fixed binding bug
Fixed bug in open-find-dialog
Ensure dialogs properly get focus
Disabled autocompleter in headlines
Removed horrible g.app.dialogs hack
Fix crasher in plugin
Autocompletion and calltips
4.4 b3
New features
Added scroll outline pane commands
Improved registerCommand
Suppressed autocompletion after numbers
Added colorizing support for Lua language
Added run-unit-test command
Bugs
Fixed problem with left & right arrows in outline mode
Fixed undo problem with clones
Investigated setting descendant @file nodes dirty when changing body text
Work around newline problems on the Mac
Got rid of settings messages
Clicks outside minibuffer no longer rip focus
Handled missing leoSettings.leo files more gracefully
Converted all shortcuts to unicode
Made Open With shortcuts work again
Made sure autocompleter and calltip text stick
Fixed a bug in c.openWith
Import/export commands now set directory for next open
Investigated colorizer problems: can not reproduce
Removed support @ifgui: it doesn't and can't work
Removed autocompletion for self
Rewrote g.importExtension to simplify startup logic
Removed calls to lstrip and rstrip for compatibility with Python 2.2.1
Fixed crash in string.startswith and string.endswith
Fixed Crash after undoing clearRecentFiles command
Fixed minor problems reported by Pychecker
Plugins
Changed path to stylesheet in the rst3 plugin
Fixed problems with chapters plugin
Improved groupoperations plugin
Fixed crasher in Word (and other) plugins
Fixed problem with labels plugin
4.4 b4
Bugs
Fixed rename-buffer command
Investigated problems with legacy bindings
Fixed bug when cutting text in headline
Report
Fixed crasher in open-find-dialog
Report
Traceback
Don't do typing completion for numbers
Fixed crash in undo
New features
Added script to update new copies of leoSettting.leo from previous copies
Added new commands
Made all edit command undoable
4.4 rc1
Bugs
Fixed rename-buffer command
Fixed bug when cutting text in headline
Fixed crasher in open-find-dialog
Suppressed typing completion for numbers
Fixed crash in undo
Fixed crash in datenodes plugin
New features
Added clear-selection command
Made all edit command undoable
Added new commands
Added filename completion
4.4 final
4.4.x
4.4.1...new colorizer, slideshow, multiple editors
4.4.1 final
Removed warning about changed nodes
Bugs fixed
Fixed serious bug in Paste Node as Clone
Report
What I did
Fixed minor .leoID.txt bug
Report
Improved speed of unmark-all and corresponding undo/redo
Report
4.4.1 b4
Bugs fixed
Added bindings to text panes for show-font command
Fixed kill-line, kill-word, kill-sentence, etc
Fixed minor scrolling problem
Fixed bug in backward-kill-word
Fixed unicode bug in forward-word and backward-word commands
Fixed problem setting body background color
Disabled incremental colorizing in new colorizer when there are multiple editors
Removed component classes
New features
Added scroll-outline-left/right commands
Generalized bracket flasher
Leo *already* supports Python decorators
Wrote script to convert g.es to g.et where appropriate
Created menu font settings
4.4.1 b1
Fixed bugs
The Open Python Window command runs Idle in a separate process
Fixed crasher in searchbox plugin
Fixed binding problems in leoSettings.leo reported by Check bindings script.
Fixed crasher in macros plugin
Fixed crasher in UNL plugin
Suppressed traceback in g.callers when the call stack isn't deep enough
Fixed long-standing bug involving @comment and @language
New features, commands & plugins
Support for multiple editors in the body pane
Improved searches
Added debug command
Added Debug button to scripting plugin
Added python-help command
Added toggle-invisibles and hide-invisibles commands
Added run-unit-test command
The help-for-command command now works for almost all commands
Added shortcut_button plugin
New and improved settings
Added @bool idle_redraw setting
Added autoindent_in_nocolor_mode setting
Added warnings about the expanded_click_area setting
Removed support for @shortcut (@shortcuts remains)
Minor improvements
Finished Cmds menu
Improved show-fonts command
Strip quotes from color, font settings.
Warn about invalid Enter and Leave key bindings
4.4.1 b2
Bugs fixed
Made sure calltip always adds '('
word matches now succeed if first character of the pattern is not in word-chars.
Dialogs now bring the Leo window back to the front
Fixed unit test: ensure that body gets focus after ending editing
Remember scrolling postion, insert point and selection range in multiple editors
Fix crasher in kill-region command
Fixed bug: cycle-editor hung Leo
Fixed crasher in init code
use g.stripBrackets instead of lstrip and rstrip
Restore cursor when changing focus in editors
Undo restores focus again
Updated row/col indicators when using arrow keys
Fixed show-invisibles crasher
Code level
Simplified gui bindings
Created g.makeScriptButton
New & improved features
Improved filename completion
Added support for --> command-name in @mode nodes
Better listings for print-commands and print-bindings & mode-help commands
Fixed find-character & find-word commands
Better printing of bindings (period -> .) etc
Added support for !command, !insert and !overwrite bindings
Improved check bindings script in leoSettings.leo
Improved isearch & added isearch-with-present-options command
Use last shortcut defined
selfInsertCommand sets the column used by up/down arrows
Added toggle-autocompleter and toggle-calltips commands
Script buttons now create press-xxx-button commands
print-bindings command now properly sorts bindings
Allow @shortcuts bindings to apply to press-xxx-commands
Added support for @abbrev nodes in leoSettings.leo
Created open-users-guide command
scroll-up/down commands now scroll the outline if focus is in outline pane
Cycle-focus command cycles through tabs and editors
Allow @mode outside of leoSettings.leo
Added section about upgrading settings
Documented how to turn @buttons into plugins
Plugins
Added doc-only option to rst3
Fixed bug in rst doc_only_mode
Support show_headlines options in doc-only mode in rst3 plugin
Fixed bug in UNL plugin
Improved image plugin
Fixed path problem with rst3 plugin
Fixed crashers in scheduler plugin
Settings
Added editor_orientation setting
4.4.1 b3
Bugs fixed
Fixed recent bug: Ctrl-g does not work in @mode nodes
Update column display when typing
Fixed long-standing problem reporting indentation errors
Fixed long-standing bug in Remove Sentinels command
Fixed long-standing bugs in import code
Overwrite mode now works in headllines
Fixed crasher in masterCommand
Improved view-lossage command
New features
Finished repeat-complex-command
Read leoSettings.leo from the directory containing the .leo file
Flash matching parens & corresponding settings
New settings
Added standard bindings for Ctrl-y (yank) and Ctrl-k (kill-line)
Added @bool warn_about_redefined_shortcuts setting
Added @bool trace_bind_key_exceptions setting
Added bracket flash settings
4.4.1.1 final
4.4.2... opml, zodb, sax, myLeoSettings, leoPymacs, autocontract, outline nav
4.4.2 beta 1
The 'big reorg': vnode, tnode and position classes are independent of the rest of Leo
New features
myLeoSettings.leo
Created simple support for ZODB databases
Scripting using zodb
Improved help-for-command
Improved quick-find commands
Improved how Leo works w/o the mousre
Increased speed of arrow keys
Find command now collapses nodes during searches
Added support -- comments in @url nodes
Added many new commands to Cmds menu
New plugins
4.4.2 beta 2
Bugs
Fixed rst3 problem
Fixed apparent bug in pmw
Fixed various unicode word-select problems
Installed installer patch
Use letter accellerators for recent files after 9
Made yank work in minibuffer
Mass change to edit commands: made sure w is a text widget
Do full recolor after cut/paste/yank
Fixed crash when pasting a node
Settings
Completed support for myLeoSettings.leo
Added settings for all mod_scripting switches
Added @bool collapse_nodes_during_finds
Added @bool outline_pane_has_initial_focus
Added @bool sparse_move_outline_left
Added bindings for Alt-Shift-Arrow keys to force an outline move
Added @bool use_sax_based_read
New commands
Added extend-to-line command
Improved print-bindings command
Created extend-to-sentence and extend-to-paragraph commands
Created runEditCommandTest
Features
Added chapters
Improved the mod_scripting plugin
rst3 plugin now registers the rst3-process-tree command
Made writing .leo files faster
Generalized navigation in outline pane to ignore @file, @thin, etc prefixes
Made outline navigation cumulative
added p.archivedPosition
(Integrated sax with read logic)
Leap 204. "New" positions allow Leo outlines to represent arbitrary directed graphs
4.4.2 beta 3
Bugs
Fixed crash when searching for headllines containing unicode chars
Fixed bugs in cycle-all-focus command
Fixed bug with Alt-n keys
Fix bug: closing a window after removing a script button can crash
The end-of-script message no longer yanks focus from tabs
Fixed warning if minibuffer command does not exist when making menus
Fixed new unicode bug
Made 'About Plugin' dialog scrollable
Removed unwanted key-state message
Made sure all kill commands do a full recolor
Fixed bug in new colorizer
Removed set-mark-command and all calls to removeRKeys
Fixed body editor problems
Moved @import to top of doc/default.css
Fixed focus problem when double-clicking @url nodes
Features
Added minibuffer and Settings menus
Toggling autocompleter and calltips now write to log (in red) instead of the statusLine
Finished collapse-on-move-left
Properly create Help menu on the Mac
'*command-name' in headline means convert '-' to blanks
Removed all references to commands from menu tables
Add Open scripts.leo to help menu
The spell tab now uses ctypes for Python 2.5
Simulated x-windows middle-button paste
Plugins
Fixed keyBindings plugin
The scripting plugin now creates a delete-x-script-button command for each script button
Fixed the nodenavigator plugin
Rewrote the multifile plugin for the 4.x code base.
Replaced __name__ with __plugin_name__ in four plugins
Improved the scripting plugin
Fixed bugs in multi-file plugin
Fix bug in shortcut_button plugin
Removed datenodes.ini from cvs
Fix bug in ops plugin
Fixed crasher on script button balloons
Settings
Made unlimited undo the default
Added @bool select_all_text_when_editing_headlines
Added bindings to toggle-autocompleter and toggle-calltips
Added 'Candidates for myLeoSettings.leo' to leoSettings.leo
Recent changes to settings
Added @bool insert_new_nodes_at_end
Removed .leoRecentFiles.txt from distribution and cvs
4.4.2 final and 4.4.2.1 final
Bugs
Changed leo_rst.css to pass the w3 validator
Fixed 'Run on string' message when typing
Fixed problem with c++ extensions
Move on if regexp matches an empty string
Fixed several bugs related to multiple body panes
Fixed multipath plugin so it works with new colorizier
Fixed bug in new colorizer
Fixed config bug
New features
Added forward-end-word/-extend-selection commands
Created leoPymacs.py for interaction with pymacs
4.4.3... winpdb, leoBridge, gui reorg, chapters
4.4.3 alpha 1
Bugs
Fixed an escape bug in new colorizer
Treat escaped characters in find patterns as a single character
Fixed undo problems with yank/kill
Fixed clone-drag problem
Made sure all ancestors expanded when select a body editor with multiple body editors
Fixed bug in CheckVersion
CheckVersion (EKR) & helper
CheckVersionToInt
test_CheckVersionToInt
Code reorg for wxGui plugin
Features
Added handleUrlInUrlNode helper for OnIconDoubleClick
Only do one message re writing recent files
Made escape in the minibuffer work like ctrl-g
Clear status line in repeat-complex-command
Added shortcuts for goto-first/last-sibling
Made copied nodes valid Leo files
Added support for chdir_to_relative_path setting
changeAll now works like findAll
Added Find & Spell tabs to log pane on startup
Created standard pluginsManager.txt only if it does not exist
Improved support for the winpdb debugger
Added \runAskOkCancelStringDialog
Plugins
The wxGui plugin is now functional
Changed bindings in UniversalScrolling pluing
Registered write-restructured-text command in rst3 plugin
Settings
Added @bool center_selected_tree_node
Added @bool invisible_outline_navigation = False
Added @bool show_full_tracebacks_in_scripts
4.4.3 alpha 2
Fixed Bugs
Fixed bugs in undo/redoNodeContents
Fixed minor xml problem
Fixed C++ import bug
Fixed recent bug in next-line command
Made standalone plugins manager work again
Fixed wiki markup bug
Fixed bugs in regular expressions
Fixed memory error in leoBridge
Fixed backspace in headline bug
Made sure alt-arrow keys honor focus settings
Fixed bug in nav button plugin
Fixed yet another cursor down bug
Improved special case in moveOutlineUp
Fixed crasher in rclicker plugin
Fixed recent problem with settings report
New Features
Added leoBridge module
Added support for @enabled-plugins in settings files
Added new search path for pluginsManager.txt
Made Leo's core gui-indenpendent
Warn on dubious section brackets
Plugins
4.4.3 beta 1
New features
Added support for chapters to Leo's core
Added @bool force_newlines_in_at_nosent_bodies setting
Added apropos-debugging-commands command
Added print-plugins & print-plugin-handlers commands
Added print-settings command
Added support for @openwith nodes in leoSettings.leo
Created clean-all-lines command
Support for compressed .leo files
Fixed bugs
Fixed bug: new-file doesn't allow edit of initial headline
Removed all returns from finally clauses
Fixed crashes when trying to import aspell
Fixed repeatComplexCommand weirdness
Fixed minor chapter hoist bug
Fixed crasher in plugins_menu.py
4.4.3 beta 2
Fixed bugs
Fixed noweb hangs
Alt-4 did not work in tree pane in unitTest.leo
Investigated problem with subprocess (works for me)
Fixed crashers in leoupate plugin
Fixed automatic directory creation
Fixed bug: shift-arrow keys not bound properly when node is clicked
Made sure the new outlines aren't marked dirty
Fix crasher in maximizeNewWindows
Don't change focus in the save command
downcase-region and upcase-region didn't color body text.
Fixed *major* demote bug
Features
Supported write_strips_blank_lines option
Completed chapters
Aspell now works on Linux, but only using Python 2.5
Improved dynamic abbreviations
Created the hoist-changed hook
Enabled more plugins by default
4.4.3 beta 3
Fixed bugs
Allow aspell on Linux provided that ctypes exists
Fixed a bug that disabled icon button colors on Linux
Switch chapters if new position isn't in current chapter
Improved goto-next/prev-node commands
Fixed failing bridge unit test
New features & settings
Added @bool contractVisitedNodes setting
Added goto-first-visible-node command
Changed binding of Alt-Home
Added @button dynamic-tests.
created g.unitTesting and g.getTestVars
Made alt menu keys work
4.4.3 final
4.4.3.1
Bugs
Fixed improper can not open myLeoSettings message
Fixed import problem in leoDynamicTest.py
Fixed cleo crasher
Fixed spell-check bug
Fixed several crashers in the group operations plugin
Fixed chapters bug
Fixed problems in groupOperations plugin
Fixed pychecker complaints
Fixed editor bug: deleting an editor did not always select the proper body pane
Features
g.es and g.es_print print only to console during unit tests
es_print & test
@test g.es_print
es
Run unit tests in a separate process
Move most unit tests into derived files
Send can not import aspell message only to the log
4.4.4 @auto, @menus, threading syntax colorer, the Great Graph Aha
4.4.4 b1
Added support for @mark-for-unit-tests node
Created threading_colorizer
Added support for @auto files
What @auto does
Perfect import checks
Commands related to @auto
Extending the code: adding new parsers
4.4.4 b2
Bug fixes
Fixed UNL bug1
Fixed how @auto handles paths
Fixed another path bug
fixed c parser so it handles non-ascii declaratsions
Fixed colorizing bug and moved calls to w.toGuiIndex out of some loops
Fixed unicode bug in http plugin
Fixed new @path problem
Fixed @auto path bug
Improved messages on @import failure
Fixed problem with space in path names in runLeoDynamicTest
Fixed bad drag & drop bug
Fixed bug 'node note selected' bug
Retain dirty bit after write @auto fails
Features
Read @auto nodes during saves if the node has not been read previously
New commands for resolving cvs conflicts
4.4.4 b3
Bugs fixed
Greatly improved speed of unmark-all
Made sure dirty bits get updated in xemacs plugin
Fixed backward find bug
Fixed cursor up/down problem
Fixed unicode bug in trace
Fixed chapter crasher
Installed patch to fix Fedora Tk.Text bug
Fixed bug in rst3 plugin
Allow unicode characters in Leo file names
Fixed bugs when running unit tests externally
New Features
The Great Graph Aha
Rewrote threading colorizer
Added support for @auto files
What @auto does
Perfect import checks
Commands related to @auto
Extending the code: adding new parsers
Added @buttons trees in @settings trees
Added @menus trees in @settings trees
New commands for resolving cvs conflicts
Added the graphed plugin
Added new convenience methods for scripts and plugins
Added button font settings
Leo's core is now compatible with jython
Added the insert-child command
@bool add_ws_to_kill_ring setting
Improved yank and yank-pop commands
Improved debug command
Added the @bool rst3 strip_at_file_prefixes setting
Added g.app.inBridge ivar
Improved the scripting and plugins chapters of Leo's Users Guide
4.4.4 b4
Fixed bugs
Fixed aspell problem
Fixed bug: utf-8 files now get imported properly
Replaced c.frame.body with c.frame.body.bodyCtrl
Fixed (maybe) multi-editor bug
Made sure proper node is visible when deleting a body editor
Fixed colorizer end-of-text bug
Added support for fastGotoNode plugin to leoKeyEvent classes
Fixed bug that disabled multiple occurances of the same user icon
Added features
Added @bool big_outline_pane setting
Can print *can* handle unicode
Improved the prototype of icon handling
4.4.4 Final
Fixed bugs
Fixed bug that caused rClick plugin to crash
Fixed scrolling problem with chapters
Fixed bug: select a chapter containing the initially selected node
Fixed Apple help menu reversion
Disabled the plugins manage plugin
Made sure plugins work if frame.iconFrame is None
Fixed @auto java bug
Fixed spell-check problem on Linux
Use the default spell tab
Fixed long-standing and important body editor bug
Non-ignored @auto trees do not get saved to the .leo file
Fixed bug that cause the import of PyParse.py to fail
Improved error reporting in rst3 plugins for code_block directive
4.4.5 bug fixes
Leo 4.4.5 b1
Fixed bugs
Removed all references to pluginsManager.txt
Fixed hung windows
Warn on resurrected (vampire) nodes
Fixed new @auto bug (python)
Fixed new @auto bug: c++
Fixed various @auto comparison problems
Retain relative paths in recent files menu
Fixed windows registry problem
Fixed paste node as clone crasher
Fixed hoist crasher
Ignore unpickling problems in getUa
New commaneds
toggle-collapse_nodes_during_finds
3 new sort-lines commands
Added Cmd:Icons menu and commands
New features
Leo now recognizes directives in headlines
Moved all unit tests to unitTest.leo
Added @rst-preformat
Installed small icon set from Tango library
New settings
@bool at_auto_warns_about_leading_whitespace
@bool diagnose-aspell-installation
@bool vim_plugin_opens_url_nodes
@bool warn_when_plugins_fail_to_load
Leo 4.4.5 b2
Fixed bugs
Improved error reporting for aspell on Linux
Fixed two crashers in the @noref logic
Fixed crasher in regularizeWhitespace
Fixed paste-node-as-clone
Fixed threading colorizer hang with perl
Fixed C++ importer crash
Reorganized leoImport.py
Fixed crasher when tangling @root
Fixed command lockout problem
Improved @auto code
Simplified perl colorizer and added progress checks
Fixed crasher in aspell logic
Fixed problem with decorators
Fixed @auto bug
Fixed focus problem with goto-next clone command
Leo 4.4.5 final
4.4.6 bug fixes
leo 4.4.6 b1
Bugs fixed
Fixed undo (dirty bit) problem)
Fixed cursesGui plugin
Fixed script_io_to_body plugin
Make Import to @file create @file nodes
Fixed bug: rst3 plugin now finds default.css file correctly
Fixed bug with clear-recent-files
Fixed bug: replace didn't always start in the correct place
fixed colorizer bug
Fixed clone focus bug
Removed call to printLine in change-all logic
Fixed crash when copying or cloning to non-exisitent chapter
Added text bindings to status area
Repaired damaged minusnode.gif icon
New features
Applied Terry Brown's config patch
Applied plumloco's patch to plugins_menu.py
Upgraded to Pmw 1.3
Added find-next-clone command
Added toggle-sparse-move command
Added support for @data nodes in @settings trees
Added @auto xml script
Added @import scanners for javascript and xml files
leo 4.4.6 b2
Fixed bugs
Fixed bug in nav_buttons plugin
Fixed problems with modes/rest.py
Replaced delete-all-icons command with a script in script.leo
Leo issues better messages if Image can not be imported
Added convenience methods for icons
Fixed undo bug
Don't mark nodes dirty if insert-icon is cancelled
leo 4.4.6 final
4.4.7 ipython plugin
leo 4.4.7 b1
Fixed bugs
Fixed perl syntax coloring bug
Removed warnings while typing @language directives
Fixed pascal import bug
write-outline-only command now prints a 'done' message
Worked around problems with winpdb
Fixed new problem with image.py
New features
All import commands now honor @path
Added ipython plugin
Added support for @bool open_with_save_on_update setting
Improved handling of unicode for @auto files
leo 4.4.7 final
Fixed bugs
Fixed perl syntax coloring bug
Removed warnings while typing @language directives
Fixed pascal import bug
write-outline-only command now prints a 'done' message
Worked around problems with winpdb
Fixed new problem with image.py
Leo's old colorizer now colorizes Leo directives properly
New features
All import commands now honor @path
Added ipython plugin
Added support for @bool open_with_save_on_update setting
Improved handling of unicode for @auto files
4.4.8 translating args to g.es and g.es_print
4.4.8 b1
Allow arguments to minibuffer commands
Added translation services
Translating Leo's menus and messages
4.4.8 b2
b1
Allow arguments to minibuffer commands
Added translation services
Translating Leo's menus and messages
b2
Bug fixes
Assigned g.fileIndex on the fly
Allow tkFrame to complete before killing it
Renamed self.fileIndex to readBufferIndex in file read logic
Made sure that all fileIndex fields get converted on read
Features
Compile regexp's once in findNextMatch
Created menus very late in the creation process
Improved marks/recent buttons plugin
Added support for @commands trees in settings files
4.4.8 b3
Fixed bugs
Corrected docs: unit tests are in test/unitTest.leo
Removed '.' from leoID
Fixed Open With menu
Fixed @lineending botch
Fixed undo problem with mutliple editors
Write dirty bit if write fails
Fixed bug involving default_target_language
Fixed plugins that create new menu items
Features
Added @bool collapse_nodes_while_spelling setting
Errors reading derived files give line numbers
Added @bool allow_middle_button_paste
Added support for @popup settings
4.4.8 rc1
Fixed delete-editor problem
Latest version
4.4.8 final
Open leoPluginsRef.leo in help menu if leoPlugins.leo does not exist
Fixed big performance bug in find/spell commands.
Fixed several unit testing bugs relating to doTests(all=True)
Leo 4.2 alpha 2 May 18, 2004

This is an important milestone in Leo's history; the two defining features of the 4.2 code base are complete:

1. This is the first stable version using the "shared nodes" code base.

Shared nodes dramatically improve the time needed to insert, delete, and move nodes. Moreover, the new code base is code compatible with the old. Indeed, much of Leo still uses the old code base. See Chapter 7 for full details of how to script Leo with the 4.2 code base.

2. This is the first version to use @file-thin for most derived files.

@file-thin makes it possible to use Leo effectively in a cvs environment. Indeed, cvs now contains only a "dummy" version of LeoPy.leo. The idea is that:

- LeoPyRef.leo hardly ever changes. Developers will download LeoPyRef.leo once from cvs, then rename LeoPyRef.leo to be LeoPy.leo. LeoPy.leo is private to each developer.

- Developers will commit and update to cvs only thin derived files. There is no longer any need to keep .leo files and the files derived from them "in synch".

- Similar remarks apply to LeoPlugins.leo. Cvs contains only LeoPluginsRef.leo, and contributors will need only to submit thin derived files.

I have been using the new code base without incident for weeks now, and I am fairly confident that it is safe to use. Nevertheless, I would suggest routine caution when dealing with this version until more people have tested it.

Known bugs

- Cutting and pasting an @file-thin node does not work properly. This will be easy to fix, I think.

- The present algorithm for reading thin derived files probably does not handle properly the situation in which a named node is some kind of grand child of the referencing node rather than being an immediate child of the referencing node. This is a rare situation, easily avoided, and it doesn't happen at all in LeoPy.leo. Nevertheless, something must be done.

Other improvements:

- Fixed a number of problems with using Leo on MacOS X. In particular, Leo now uses the clover key as is usual on the Mac. More Mac and *nix specific improvements are coming.

Still to do:

- Perfect import and @import. - Make the Go To Line Number command work with @file-thin files. - Fix minor bugs and add new features See the "To Do: 4.2" node in the leoToDo.txt node in LeoPy.leo.
- Moved call to assignFileIndices into write_Leo_file. - Called assignFileIndices in writeAtFileNodes, writeDirtyAtFileNodes, writeMissingAtFileNodes
What I did:

File format

Added -thin field to @+leo sentinel

Recognizers

- Added vnode recognizers for @file-thin option. - Added position proxies for vnode recognizers.

Directives & sentinels - Added support for @all.

Writing

- Added top-level atFile code to write @file-thin tree. - DO write @file-thin vnodes if there was an error writing the derived file. - No autosave for @file-thin. - Leo writes @file nodes first, so this is not a problem. - putVnode checks orphan bit, which gets set if there was an error. - Don't write vnodes (or related tnodes) for @file-thin trees. (fileCommands). - Do write empty nodes in @thin trees. - Don't generate close node sentinels until all children have been generated.

Reading

- Set at.thinFile when reading thin files. - Suppressed changed message and related items for thin files. - Modified scanText4 and allies to read thin derived files. - Don't look for tnodeList for thin files. - Initially, at.lastThinNode is at.root.v - readStartNode calls createThinChild - createThinChild makes a child of at.lastThinNode if needed and sets at.lastThinNode. - Updated fc.tnodesDict in at.createThinChild. Otherwise clones existing only in two thin files won't be linked properly.
After a match, the find-next command searched only in the suboutline where the first match occurred. To fix this, we call g.app.findFrame.handleUserClick in various Tk event handlers.
@nocolor

p.v.t.visitedBit was used for two purposes:

- To mark the nodes to be written. - To mark nodes that are not orphan.

What I did:

- Added t.is/set/clearWriteBit. - Call t.setWriteBit in putVnode unless we are in a thin node. - putTnodes tests for t.writeBit rather than t.visitedBit.
Leo did not handle moving a node to the root position of the outline correctly.
Using @ignore with @file-thin is asking for trouble. If you remove the @ignore and then save, you will lose data.

How to recover the data: - Read Outline. - Remove @ignore - Import derived file...
@language rest
A cloned node is a copy of a node that changes when the original changes. Not only are changes maintained across all the the clones of a node, changes to its offspring (children, grandchildren, etc). are simultaneously made to the corresponding offspring of all of those clones. A small red arrow in the icon box marks cloned nodes. There is no real distinction between the "original" node and any of its clones. This makes it possible to update any of the clones and the original node will change as well. A cloned nodes becomes a regular node again when its penultimate clone is deleted. Clones are useful for making alternate views of a program. See `Clones and views`_ for full details.
The ``Insert Node`` command inserts a new node into the outline. The ``Delete Node`` command deletes a node and all its children.
The ``Cut Outline``, ``Paste Outline``, ``Copy Outline`` and ``Delete Outline`` commands work on nodes rather than text. For example, to delete a node, select the node and choose the ``Cut Outline`` or ``Delete Outline`` command. The ``Cut Outline`` and ``Copy Outline`` commands copy a text representation of the outline to the clipboard. This representation is the same as Leo's .leo file format with some information deleted. You may copy this text representation into a body pane (or into any other text editor) using the ``Edit:Paste`` command.

**Warning**: In practice, it is almost always wiser to move clones rather than cutting or pasting them. Cutting and pasting outlines preserves clones, but the links between clones only exist within the part of the outline that was pasted. Therefore, if you are cutting and pasting an outline containing clones it is best to cut and paste the *entire* outline. Alternatively, you can paste part of an outline, then delete all clones.
You may drag an node (including all its descendants) from one place to another in an outline. To start a drag, press the main (left) mouse button while the cursor is over the icon for a node. The cursor will change to a hand icon. If you release the mouse button while the hand cursor is above the icon for another node, Leo will move the dragged node after that node. If you release the mouse button when the hand cursor is not over an icon, Leo will leave the outline pane as it is. Leo scrolls the outline pane as the result of mouse-moved events, so to continue scrolling you must keep moving the mouse.
Leo auto indents unless ``@nocolor`` is in effect. Typing a newline automatically inserts the same leading whitespace present on the previous line. If Python is the present language, Leo inserts an additional tab if the previous line ends with a colon.

The default features of Leo's body text derive from the Tk.Text widget, described at: http://www.tcl.tk/man/tcl8.3/TkCmd/text.htm Not all these features are found on all platforms. The following features are derived from the Tk Text widget. Some default behaviors have been changed because they conflict with other Leo features.

- Clicking mouse button 1 positions the insertion cursor just before the character underneath the mouse cursor, sets the input focus to this widget, and clears any selection in the widget. Dragging with mouse button 1 strokes out a selection between the insertion cursor and the character under the mouse.

- Double-clicking mouse button 1 selects the word under the mouse and positions the insertion cursor at the end of the word.

- The ends of the selection can be adjusted by dragging with mouse button 1 while the Shift key is down; this will adjust the end of the selection that was nearest to the mouse cursor when button 1 was pressed.

- Clicking mouse button 1 with the ``Control`` key down will reposition the insertion cursor without affecting the selection.

- Normal printing characters are inserted at the point of the insertion cursor.

- If the mouse is dragged out of the body pane while button 1 is pressed, the entry will automatically scroll to make more text visible.

- ``Left Arrow`` and ``Right Arrow`` move the cursor one character to the left or right and clear any selection in the text.

- ``Shift Left`` or ``Shift Right`` move the cursor and extend the selection.

- ``Control-Left`` and ``Control-Right`` move the insertion cursor by words, and ``Control-Shift-Left`` and ``Control-Shift-Right`` move the insertion cursor by words and also extend the selection.

- ``Up Arrow`` and ``Down Arrow`` move the insertion cursor one line up or down and clear any selection in the text.

- ``Shift Up`` and ``Shift Right`` move the cursor and extend the selection.

- ``Control-Up`` and ``Control-Down`` move the insertion cursor by paragraphs.

- ``Control-Shift-Up and ``Control-Shift-Down`` move the insertion cursor by paragraphs and extend the selection. ``Control-p`` and ``Control-n`` behave the same as ``Up`` and ``Down``, respectively. **Note**: by default, Leo binds ``Control-p`` and ``control-n`` to commands.

- ``Next`` (``Page Down``) and ``Prior`` (``Page Up``) keys move the insertion cursor one screen and clear any text selection.

- ``Shift Next`` and ``Shift Prior`` move the cursor one screen and extend the selection.

- Line movement is by text lines terminated by hard returns (newlines), not by displayed lines; if a text line is long and wraps across more than one display line, then the ``Up`` and ``Down`` movement will skip the extra wrapped display lines.

- ``Home`` moves the insertion cursor to the beginning of its line and clears any selection in the widget.

- ``Shift-Home`` moves the insertion cursor to the beginning of the line and extends the selection.

- ``End`` moves the insertion cursor to the end of the line and clear any selection in the widget.

- ``Shift-End moves`` the cursor to the end of the line and extends the selection.

- ``Control-Home`` moves the insertion cursor to the beginning of the text and clears any selection in the widget.

- ``Control-Shift-Home`` moves the insertion cursor to the beginning of the text and extends the selection.

- ``Control-End`` moves the insertion cursor to the end of the text and clears any selection.

- ``Control-Shift-End`` moves the cursor to the end of the text and extends the selection.

- ``Select`` and ``Control-Space`` set the selection anchor to the position of the insertion cursor. They don't affect the current selection.

- ``Shift-Select`` and ``Control-Shift-Space`` adjust the selection to the current position of the insertion cursor, selecting from the anchor to the insertion cursor if there was no previous selection.

- ``Control-/`` selects the entire contents of the widget.

- ``Control-\`` clears any selection in the widget.

- ``F16`` (``Copy`` on many Sun workstations) or ``Control-c`` copies the selection in the widget to the clipboard, if there is a selection.

- ``F20`` (``Cut`` on many Sun workstations) or ``Control-x`` copies the selection in the widget to the clipboard and deletes the selection. These keys have no effect if no text is selected.

- ``F18`` (``Paste`` on many Sun workstations) or ``Control-v`` inserts the contents of the clipboard at the position of the insertion cursor.

- ``Delete`` deletes the text selection, or the character to the right of the cursor if there is no text selection.

- ``Backspace`` deletes the selection, or character to the left of the cursor if there is no text selection.
You can expand or contract a node by clicking in the standard Windows Tree View icon to the left of the status icon. Expanding a node shows its immediate children; contracting a node hides all its children. The ``Expand All Subheads`` command expands all of a nodes offspring (children, grandchildren, etc.)
Leo auto indents body text following colons when ``@language Python`` is in effect. When the ``smart_auto_indent`` setting is True, Leo uses Emacs-style auto-indentation instead. This style of auto-indent aligns newly created lines with unmatched ``(`` ``[`` or ``{`` brackets in the previous line.
You can mark nodes in several ways:

- With the ``Mark`` commands.

- With the ``Find`` or ``Change`` commands.

- With the ``Untangle`` command.

The ``Go To Next Marked`` command selects the next marked node, if any. The ``Mark`` command unmarks the selected headline if it is already marked.
The ``Move Up``, ``Move Down``, ``Move Left`` and ``Move Right`` commands move the currently selected node. The ``Promote`` command makes all the children of a node siblings of the node. The ``Demote`` command makes all following siblings of a node children of the node.

You can cut and paste any part of a tree. If a node contains selected text, the cut, copy, clear or paste operation affects only the selected text. Otherwise, the cut, copy, clear or paste operations acts on the node and all nodes contained by it. For example, you can move a node by cutting it, selecting another location in the outline and pasting the node in the new location.

**Warning**: In practice, it is almost always wiser to move clones rather than cutting or pasting them. Cutting and pasting outlines preserves clones, but the links between clones only exist within the part of the outline that was pasted. Therefore, if you are cutting and pasting an outline containing clones it is best to cut and paste the _entire_ outline. Alternatively, you can paste part of an outline, then delete all clones.
Double-clicking the icon box of a node whose headline has the form::

@url <any url>

executes the url in your default web browser.

Leo checks that the url is valid before doing so. A valid url is:

- 3 or more lowercase alphas - followed by one ``:`` - followed by one or more of: - ``$%&'()*+,-./0-9:=?@A-Z_a-z{}~`` - followed by one of: ``$%&'()*+/0-9:=?@A-Z_a-z}~``

Url's should contain no spaces: use ``%20`` to indicate spaces. You may use any type of url that your browser supports: http, mailto, ftp, file, etc.
You can change the relative sizes of the outline and body panes by dragging the splitter bar. The ``Equal Sized Panes`` command resizes the panes so that each fills half of the main window.
Leo supports unlimited undo for all typing and all commands. The 'undo_granularity' setting controls the granularity of undo. There are four possible values:

``node`` Starts a new undo unit when typing moves to a new node.

``line`` (default) Starts a new undo unit when typing moves to new line.

``word`` Starts a new undo unit when typing starts a new word.

``char`` (not recommended) Starts a new undo unit for each character typed. This wastes lots of computer memory.

``setUndoTypingParams`` calls ``recognizeStartOfTypingWord`` to recognize the start of words. Plugins can modify ``recognizeStartOfTypingWord``. It should return ``True`` if the typing indicated by the params starts a new 'word' for the purposes of undo with 'word' granularity. ``setUndoTypingParams`` calls this method only when the typing could possibly continue a previous word. In other words, undo will work safely regardless of the value returned. See the actual code for ``recognizeStartOfTypingWord`` for more details.
An @asis tree is a tree whose root headline starts with @asis <filename>. Similarly, for @noref and @nosent trees.

New in 4.2: The following terms are equivalent. The first form is preferred in each case.

@asis, @file-asis, @silent @nosent, @file-nosent and @nosentinelsfile @noref, @file-noref and @rawfile

You can get any combination of sentinels/no sentinels and references/no references using @file, @nosent, @noref and @asis trees:

Derived files Sections and Type of tree contain sentinels? @others expanded? ------------ ------------------ ----------------- @asis no no @file yes yes @noref yes no @nosent no yes

Leo can not update the outline from changes made from derived files unless those files contain sentinels. The primary source for @nosent and @asis trees are the outlines from which those files were derived.

Leo creates files derived from @noref and @asis trees by writing the body text of all nodes of the tree in outline order. Leo writes the body text _as is_, without recognizing section definitions, without expanding section references, and without treating directives specially in any way. In particular, Leo copies all directives, including @space or @c directives, to the derived file as text. However, Leo recognizes the @ignore directive in the _ancestors_ of @noref or @asis nodes, so you may use the @ignore directive as usual to prevent Leo from writing @rawfile and @silentfile trees.

Notes:

1. When writing @noref trees, Leo writes only the @+leo, @-leo, @+node, @-node, @+body and @-body sentinels.

2. Within @asis trees only, if a headline starts with @@, Leo writes everything in the headline following the @@ just before the corresponding body text.

3. Files derived from @asis trees contain _nothing_ not contained in body text (or @@ headlines). In particular, if body text does not end in a newline, the first line from the next node will concatenated to the last line of the preceding node.
@language rest
- The ``New`` command creates a new Leo main window.

- The ``Open`` command opens an existing Leo file and shows it in a main window.

- The ``Close`` command closes the topmost Leo window, giving you an opportunity to save your work if you haven't yet done so.

- The ``Save``, ``Save As`` and ``Save To`` commands save the Leo window to a file. The ``Save As`` command changes the name of the outline being edited; the ``Save To`` command does not.

The ``Save File As Zipped`` command is the same as the ``Save As`` command except that the resulting .leo file is compressed with Python's zipfile module. Similarly, the ``Save File As Unzipped`` command is the same as the ``Save As`` command except that the resulting .leo file is not compressed. The ``Save``, ``Save As`` and ``Save To`` commands compress the file if it was originally compressed. **Note**: Leo writes files with .leo extension, regardless of whether the file is zipped or not. Zipped .leo files contain a single archive, whose name is the same as the .leo file itself. Outside of Leo you can change the extension to .leo.zip and use stuffit or other program to expand the .leo file contained within.

- The ``Revert`` command reloads a file, discarding any changes made to the file since it was last saved.

- The ``Recent Files`` command brings up a submenu containing a list of recently opened files. Choosing an item in this submenu opens the selected file or brings it to the front.

- The ``Clear Recent Files`` command deletes all entries in the Recent Files submenu except the most recent file. The files themselves are not affected, just the menu entries.

The following commands are located in the ``Read/Write`` menu, part of the ``File`` menu.

- The ``Read Outline Only`` command reads an outline using only the .leo file, not any files derived from ``@file`` nodes. This command is useful for reverting a project to a previously saved state.

- The ``Read @file Nodes`` command updates all ``@file`` nodes in an outline. This ensures that the state of an outline matches all files derived from ``@file`` nodes.

- The ``Write Outline Only`` command saves an outline without writing any ``@file`` trees. Useful for inserting an @file node into an outline without modifying a derived file with the same name.

- The ``Write @file Nodes`` command forces an update of all @file trees.

- The ``Write Dirty @file Nodes`` command writes all ``@file`` trees that have been changed.
The ``Open With`` command allows you to communicate with external editor. When you select this command Leo creates a temporary file and invokes an external program. Leo periodically checks whether this temporary file has changed; Leo changes the corresponding node in the outline if so. You must create the entries in the Open With submenu. This would typically be done in a hook routine, using the createOpenWithMenuFromTable routine described in the child of this node. The ``@file mod_open_with.py`` node in ``LeoPlugins.leo`` gives a complete example of handling the ``Open With`` menu.
The ``Tangle``, ``Tangle All`` and ``Tangle Marked`` commands create derived files from portions of an outline. These commands indent and format the derived files so that they are easy to read and so that it is clear what sections produced the code. The .c file in the Examples folder shows the code produced by the Tangle commands. The ``Tangle`` command tangles only the selected portion of the outline, the ``Tangle All`` command tangles the entire outline, and the ``Tangle Marked`` command tangles only marked headlines.

The ``Tangle`` commands create a derived file, call it F, from each ``@root`` node. This process is like macro expansion. The contents of F are simply the body text of the ``@root node``, with each section reference replaced by its definition. Substitution continues until all references to sections are replaced with their definitions. By default, ``Tangle`` commands look for section definitions only in the suboutline containing the ``@root`` directive being tangled. That is, all sections are assumed to be defined either in the body text of the headline, say h, containing the @root directive, or in the body texts of the descendants of h. The ``@unit`` directive changes the default scope of the tangle command, while the ``@ignore`` directive causes the tangle commands to ignore a subtree. For more details, see: `Tangling @root trees with the Tangle commands`_
The ``Untangle``, ``Untangle All`` and ``Untangle Marked`` commands are the reverse of the corresponding ``Tangle`` commands. They update an outline based on changes made to one or more derived files. These are exceptionally useful commands. For example, suppose you create a new part of the outline and ``Tangle`` it for the first time. When you compile the resulting derived files for the first time, you are likely to get many syntax errors. You could fix those errors in the outline and Tangle the outline again, but there is a much easier way: you fix the errors in the derived files using the compiler's editor, then run the untangle command on the part of the outline that created the derived file. The ``Untangle`` command updates the selected outline to match the changes in the derived files. It's as simple as that. The ``Untangle`` command marks all the nodes in the outline that it updates; you can examine all such nodes with the ``Go To Next Marked`` command in the Outline menu. You cannot use ``Untangle`` to update doc parts, or leading comments in code parts or "trivial" whitespace in code parts. This is a limitation of the ``Untangle`` command that cannot be fixed; ``Untangle`` has no way of knowing whether leading comments came from doc parts or are just leading comments.

``Untangle`` never changes the structure of an outline; it never inserts, deletes or moves nodes. Don't attempt to change the structure of an outline by modifying derived files; it won't work. Also, never delete, move or alter the sentinel lines in derived files written by the Tangle command. Such lines start with ``///`` followed by a section name. If you change the section name in a sentinel line ``Untangle`` will not update the code in the outline (with the old name) that generated the renamed section. Untangle now warns about sections that appear in a derived file but not in the outline. Untangle has no trouble with changed section references in derived files; it is only changed sentinel lines that cause problems. Cloned nodes that generate code in several files may cause problems for ``Untangle`` if not all the code is changed the same way in derived files. If ``Untangle`` is run separately on these derived files, Untangle will update all cloned nodes each time it is run, so only the code in the last ``Untangle`` run will take effect. Therefore, the only reliable way to update text in cloned nodes is to make the change in the .leo file rather than the derived files.
The ``Import`` commands do not attempt to do perfect translations; they merely automate the bulk of the drudgery:

- The ``Import to @file`` command creates an ``@file`` node from a file.

- The ``Import to @root`` command creates an ``@root node`` from a file.

- The ``Import CWEB Files`` command creates an @file node from a `CWEB`_ file.

- The ``Import noweb Files`` command creates an @file node from a `noweb`_ file.

- The Import Derived File command imports all the nodes in a derived file into the outline. Unlike the read commands, the command preserves no outline structure.

- The ``Import Flattened Outline`` command converts plain text written in ``MORE`` format to an outline.

The ``Import Flattened Outline`` command brings up a dialog which will accept at most one file. If that file contains MORE-format text it creates an outline corresponding to that text. ``MORE`` is a now-defunct outliner program. ``MORE`` represents outlines as follows. Headlines are denoted by a leading ``+`` or ``-`` character, preceding by zero or more tabs that denote the level of the headline. Body text follows its headline, with no indentation. The original ``MORE`` format did not escape lines in the body text that started with ``+`` or ``-``. Leo escapes such characters by preceding ``+``, ``-`` or backslash with a backslash.
- The ``Outline To CWEB`` command creates a `CWEB`_ file from the selected outline.

- The ``Outline TO noweb`` command creates a `noweb`_ file from the selected outline.

- The ``Flatten Outline`` command creates a text file in ``MORE`` format from the selected outline. See the previous section for a discussion of ``MORE`` format.

- The ``Remove Sentinels`` command removes all sentinel lines from a file derived from an ``@file`` node.

- The ``Weave`` Command formats the selected text and writes it to a file.
The ``Quit`` command causes Leo to exit. You may also exit Leo by closing the main window. You will be prompted to save any file that has been altered but not saved.
Leo supports unlimited undo and redo. Think of actions that may be undone or redone as a string of beads. A "bead pointer" points to the present bead. Performing an operation creates a new bead after the present bead and removes all following beads. Undoing an operation moves the bead pointer backwards; redoing an operation moves the bead pointer forwards. The ``Undo`` command is disabled when the bead pointer moves in front of the first bead; the ``Redo`` command is disabled when the bead pointer points to the last bead.
Leo supports the standard editing commands: ``Cut``, ``Copy``, ``Paste``, ``Clear`` and ``Select All``. These commands work with either headline or body text.
The ``Shift Left`` and ``Shift Right`` commands shift selected lines in the body text left or right one tab position. These commands shift the entire line if any characters in that line are selected.
The Extract, Extract Section and Extract Section Names commands create child nodes whose headline is the first line of the selected body text.

- The ``Extract command`` creates a new node whose headline is the first line of selected body text and whose body is all other lines of selected text. Previously selected text is deleted from the original body text.

- The ``Extract Section command`` creates a new node whose headline is the first line of selected text and whose body is ``@code`` followed by all the other lines of selected text. All selected text lines except the first line are deleted from the original body text. This command is enabled only if the first line contains nothing but section name.

- The ``Extract Section Names`` command creates one or more child nodes, one for each section name in the selected body text. The headline of each created node is the section name; the body text is ``@code`` followed by a newline.
- The Convert Tabs command converts leading tabs to blanks in a single node. - The Convert Blanks command converts blanks to tabs in a single node. - The Convert All Tabs converts leading tabs to blanks throughout the selected tree. - The Convert All Blanks command converts leading blanks to tabs throughout the selected tree.

All these commands convert between tabs and blanks using the tab width presently in effect.
The ``Execute Script`` command executes body text as a Python script. Leo execute the selected text, or the entire body text if no text is selected. The ``Execute Script`` command pre-defines the values ``c``, ``g`` and ``p`` as follows:

- ``c`` is the commander of the outline containing the script. - ``g`` is the leoGlobals modules. - ``p`` is ``c.currentPosition()``.

**Important**: Body text may contain Leo directives and section references. You can now use all of Leo's features to organize scripts that you execute interactively. Section definitions must appear in the node containing the script or in descendant nodes.

Leo preprocesses all scripts by simulating the writing of a derived file to a string. The ``Execute Script`` command sets ``app.scriptDict["script1"]`` to the value of the script before preprocessing, and sets ``app.scriptDict["script2"]`` to the value of the script after preprocessing. Scripts may examine and change app.scriptDict as they please.
The following check boxes options appear in the search dialog and control the operations of the find and change commands.

Clone Find All When checked, the the Find All command creates a new root node called ``Found:`` *<your search pattern>*. This node contains clones of the nodes found by the Find All command. It is your responsibility to navigate to this new node and to clean it up when it's no longer needed.

Ignore Case When checked, the ``Find and Change`` commands ignore the case of alphabetic characters when determining matches.

Mark Changes When checked, the ``Change`` command marks all headlines whose headline or body text are changed by the command.

Mark Matches When checked, the ``Find and Change`` commands mark all headlines in which a match is found with the pattern.

Pattern Match When checked, the ``Find and Change`` commands treat several characters specially in the find pattern.

- '*' matches any sequence of zero or more characters. - '.' matches any single character. - '^' matches a newline at the start of a pattern. - '$' matches a newline at the end of a pattern.

Examples::

"^abc$" matches lines that only contain "abc". "^a" matches any line starting with "A". "a$" matches any line ending with "a". "^*$" matches any line at all.

Reverse When checked, the ``Find and Change`` commands search backward through the file.

Search Body Text When checked, the ``Find and Change`` commands search body text.

Search Headline Text When checked, the ``Find and Change`` commands search headline text.

Show Context When checked, the ``Find All`` command shows additional context information when printing matches.

Suboutline Only When checked, the ``Find and Change`` commands search only the currently selected headline and its offspring.

Whole Word When checked, the find pattern must match an entire word. Words consist of an alphabetic character or underscore, followed by zero or more alphabetic characters, numbers or underscores.

Wrap Around When checked, the ``Find and Change`` commands continues at the top of the file when the command reaches the bottom of the file. For reverse searches, the find or change command continues at the bottom of the file when the command reaches the top of the file.
The ``Go To Line Number`` command selects the locations in your outlines corresponding to a line in a derived file.
The ``Insert Body Time/Date`` and ``Insert Headline Time/Date`` commands insert formatted time and date into body or headline text. You must be editing a headline to be able to insert the time/date into the headline. The `` body_time_format_string`` and ``headline_time_format_string`` settings specify the format of the inserted text. These settings are the format string passed to time.strftime. For a complete list of the format options see http://www.python.org/doc/current/lib/module-time.html If the format specified by either of these two settings is erroneous the ``"%m/%d/%Y %H:%M:%S"`` format is used by default, resulting in a time/date format like::

1/30/2003 8:31:55
The Reformat Paragraph command rearranges the words in a text paragraph to fill each line as full as possible, up to the ``@pagewidth`` setting. A paragraph is delimited by blank lines, Leo directives, and (of course) start and end of text in a node. The width of the line used by the reformatting operation is governed by ``@pagewidth`` and the indentation that would be applied to the node when tangled (as part of a ``@root``) or written (as part of a ``@file``).

The command operates on the paragraph containing the insert cursor. If the insert cursor is on a blank line or directive, nothing happens. If the cursor is on a line containing text, then the paragraph containing that text line is reformatted and the insert cursor is moved to the next paragraph.

**Note**: Hanging indentation is preserved. This is most useful for bulleted or numbered lists, such as::

1. This is the first paragraph, and it has a hanging indentation.

2. This is the second paragraph, and it too has a hanging indentation.
The ``Match Brackets`` command is enabled if the cursor is next to one of the following characters in the body pane:

( ) [ ] { } < >

This command looks for the matching character, searching backwards through the body text if the cursor is next to `)` `]` `}` or `>` and searching forward through the text otherwise. If the cursor is between two brackets the search is made for the bracket matching the leftmost bracket. If a match is found, the entire range of characters delimited by the brackets is highlighted and the cursor is placed just to the left of the matching characters. Thus, executing this command twice highlights the range of matched characters without changing the cursor.
Leo stores options in ``@settings`` trees, that is, outlines whose headline is ``@settings``. When opening a .leo file, Leo looks for ``@settings`` trees not only in the outline being opened but also in various leoSettings.leo files. The key design goal of ``@settings`` trees was that Leo's user options must be infinitely flexible. That goal has been accomplished. Indeed, users can create arbitrarily complex user options with ``@settings`` trees. Leo settings outlines are, in fact, much more flexible and powerful than any scheme based on flat text.

The ``myLeoSettings.leo`` file is a way of ensuring that your customized settings are not altered when updating Leo from cvs or while installing a new version of Leo. The myLeoSettings.leo acts much like Python's site-customize.py file. The ``myLeoSettings.leo`` file will never be part of any Leo distribution, and it will never exist in Leo's cvs repository. This solution is *much* better than trying to update leoSettings.leo with scripts.

The ``Settings`` command opens the file leoSettings.leo.

Leo stores options in ``@settings`` trees, that is, parts of Leo outlines whose root node has the headline ``@settings``. When opening a .leo file, Leo looks for ``@settings`` trees in the following places:

- The file ``leoSettings.leo`` in the leo/config directory. - The file ``leoSettings.leo`` in the user's home directory. - The file ``myLeoSettings.leo`` in the leo/config directory. - The file ``myLeoSettings.leo`` in the user's home directory. - The file being loaded.

Settings that appear later in the above list override settings found earlier. For example, any setting specified in an ``@settings`` tree in the file being loaded overrides any setting seen in any ``leoSettings.leo`` file.

The following sections describe the kinds of nodes in ``@settings`` trees.
- The ``Check Outline`` command checks the outline for consistency.

- The ``Check All Python Code`` and ``Check Python Code`` commands report any syntax errors or tabnanny errors. These commands mark erroneous nodes and ignore any nodes for which:

- ``@ignore`` is in effect or - ``@language python`` is in not effect.

- The ``Check Python Code`` and ``Pretty Print Python Code`` pretty print body text. You can customize this code by overriding the following methods of class ``prettyPrinter`` in ``leoCommands.py``::

putOperator: puts whitespace around operators. putNormalToken: puts whitespace around everything else.
- The ``Insert Headline`` command inserts a new headline after the presently selected headline, either as the next sibling or the first child of the presently selected headline if the presently selected headline has children and is expanded.

- The ``Clone Node`` creates a clone of the selected node. See `Clones and views`_ for full details about clones.
- The ``Cut Outline`` and ``Copy Outline`` commands copy a text representation of the outline to the clipboard. This representation is the same as the file format with some information deleted.

- The ``Paste`` command (in the ``Edit`` menu) copies this representation into the *body* pane.

- The ``Paste Node As Clone`` command pastes the node from the clipboard, retaining the identity of nodes. Thus, if the pasted node already exists in the outline the newly pasted node will become of a clone of the already-existing node.

- The ``Paste Outline`` command creates nodes with new identities (new gnx's).
- The ``Expand`` command expands the currently selected node so that all its children are visible. - The ``Expand All Subheads`` command expands the currently selected node so that all its offspring are visible. - The ``Expand All`` command expands all the nodes of the entire tree. - The ``Contract Parent`` contracts the selected node's parent and selects the parent node.
- The ``Hoist`` command redraws the screen so presently selected tree becomes the only visible part of the outline. Hoist commands may be nested.

- The De-hoist command restores the outline.
- The ``Mark Headline`` command marks a headline with a red marker near the leader characters. - The ``Unmark Headline`` command removes such a mark. - The ``Mark Subheads`` command marks all offspring of the currently selected node. - The ``Unmark All`` command removes the marks from the entire tree. - The ``Mark Changed Items`` command marks all headlines whose headline or body text has been changed since the file was last saved. - The ``Mark Changed Roots`` command marks all changed headlines whose body text contains the ``@root`` directive. This command is especially useful with the Tangle Marked command.
- The ``Move Up``, ``Move Down``, ``Move Left`` and ``Move Right`` commands move the currently selected node.

- The ``Promote command`` makes all the children of a node siblings of the node.

- The ``Demote`` command makes all the siblings that follow a node children of the node.

- The ``Sort Children`` command sorts all children of the present node in alphabetical order of their headlines.

- The ``Sort Siblings`` command sorts all siblings of the present node in alphabetical order.
- The ``Equal Sized Panes`` command adjusts the sizes of the outline and body panes so that they are the same height. - The ``Cascade`` command cleans up the screen by cascading all Leo windows. - The ``Minimize All`` command minimizes all Leo windows. - The ``Toggle Active Pane`` command toggles keyboard focus between the outline and body panes. - The ``Toggle Split Direction`` command switches between vertical and horizontal orientations of the Leo window. In the vertical orientation, the body pane appears below the pane containing the outline and log panes. In the horizontal orientation, the body pane appears to the left the pane containing the outline and log panes. By default, the ratio of pane outline pane to the body pane is 0.5 in the vertical orientation and 0.3 in the horizontal orientation. These two ratios may be changed using settings. - The ``Open Compare Window`` command opens a dialog that allows you to compare two files, one containing sentinels and one not.
- The ``About Leo`` command puts up a dialog box showing the version of Leo. - The ``Online Home Page`` command opens Leo's home page at http://webpages.charter.net/edreamleo/front.html. - The Open Online Tutorial command opens Joe Orr's excellent ScreenBook tutorial at http://www.evisa.com/e/sbooks/leo/sbframetoc_ie.htm. - The Open Offline Tutorial command opens the file sbooks.chm if it exists. Otherwise, you will be asked whether you want to download it from Leo's SourceForge web site. If you say yes, the page http://sourceforge.net/project/showfiles.php?group_id=3458 will open. You may then download sbooks.sbm to the folder containing leo.py. - The ``Open LeoDocs.leo`` command opens ``LeoDocs.leo``. - The ``Open LeoPlugins.leo`` command opens ``LeoPlugins.leo``. - The ``Open LeoSettings.leo`` command opens ``LeoSettings.leo``.

@language rest
The following paragraphs discuss the main benefits of traditional `literate programming`_. **Note**: none of these benefits depends on printed output.

**Design and coding happen at the highest possible level**. The names of sections_ are constrained only by one's design skill, not by any rules of language. You say what you mean, and that becomes both the design and the code. You never have to simulate a concept because concepts become `section names`_.

**The visual weight of code is separate from its actual length**. The visual weight of a section_ is simply the length and complexity of the `section name`_, regardless of how complex the actual definition of the section is. The results of this separation are spectacular. No longer is one reluctant to do extensive error handling (or any other kind of minutia) for fear that it would obscure the essence of the program. Donald Knuth stresses this aspect of literate programming and I fully agree.

**Sections show relations between snippets of code**. Sections_ can show and enforce relationships between apparently unrelated pieces of code. Comments, macros or functions are other ways to indicate such relationships, but often sections are ideal. Indeed, a natural progression is to create sections as a matter of course. I typically convert a section to a function only when it becomes apparent that a function's greater generality outweighs the inconvenience of having to declare and define the function.

**Complex section names invite improvements**. A `section name`_ is complex when it implies unwholesome dependencies between the caller (user) of the section and the section_ itself. Such section names tend to be conspicuous, so that the programmer is lead to revise both the section name and its purpose. Many times my attention has been drawn to a poorly conceived section because I didn't like what its name implied. I have always been able to revise the code to improve the design, either by splitting a section into parts or be simplifying its relation to colleagues.

**Sections create a place for extensive comments**. One of the most surprising thing about `literate programming`_ is how severely traditional programming tends to limit comments. In a conventional program the formatting of code must indicate structure, and comments obscure that formatting. Sections_ in literate programming provide a place for lengthy comments that do not clutter the code at the place the section is referenced_.

**Section names eliminate mundane comments**. The `section name`_ often says it all. The reference_ to the section says everything that the user needs to know, and the section name at the point of definition also eliminates the need for many comments.

**Sections create comments automatically**. A typical `@root node`_ starts out with something like::

<< includes for class x >> << private data for class x >> << private prototypes for class x >> << functions of class x >>

In the derived file there is a comment that looks like this::

/// << includes for class x >>

It would be silly to write this comment by hand, though often programmers do just that in order to have a place holder for a mark in the source file. With `literate programming`_ the situation is different: the comment indicates that the code came from a particular section_; that is, the comment servers a real purpose.

**Literate programming clarifies the shape of code**. These last several paragraphs have discussed comments in detail because the net effect of "putting comments where they belong" is that comments don't clutter the code. `Section references`_ hide irrelevant detail, so larger-scale patterns within functions (or declarations) become more apparent. Often just recasting code into web format has created Aha's about my own code, with no special attention to recoding or redesign! Recasting a function as a web raises the real and apparent level of abstraction.

**I spend less time formatting code**. Formatting no longer has to indicate overall design; sections do that. I am less obsessive about formatting code; it simply doesn't matter much whether different sections are formatted consistently because the format of one section has no effect on the look of other sections. Also, I don't worry about most line breaks within `documentation parts`, or about adding comment delimiters.

**Literate programming creates a new design dimension**. Sections_ add a new dimension to the design and coding process. Choices about what sections do, what they are named, what order they appear in, are choices in a design space different from "normal" programming. This an abstract concept, to be sure. However, the previous paragraphs are really a manifestation of working in this new design space.
Outlines_ add something brand new to traditional `literate programming`_, namely an explicit mechanism for expressing structure at any level of detail, from largest overall view to smallest detail. The following paragraphs elaborate on this theme.

**Outlines add context**. There are too many sections_ in conventional `literate programming`. It becomes difficult to understand the relationships between sections. Using an outline_ to express a literate programming instantly solves this problem. The programmer is always aware of how sections are related.

**Outlines provide scope for commands**. Outlines_ provide a convenient way of expressing the intended scope of commands. For example, the ``Tangle`` command operates only on the presently selected tree_. The ``Extract Section`` command creates a new section_ as the last child_ of the present node_.

**Clones create different views and focus attention**. Clones_ can create different views of the outline. An outline_ can contain many such views. `Clones & views`_ discusses the implications of clones in detail.

**Outlines increase flexibility**. `Organizer nodes`_ do not affect derived files in any way, but organizer nodes often convey the most information about the structure and design of a large system. Decoupling structure from content in this way is precisely what is needed for flexibility: one can reorganize at will without worrying about changing the meaning of the code.

**Outlines express hierarchy directly**. Hierarchy is often implicit in programming: for example, the grouping of functions into files, or the organization of a single file as a set of functions, etc. An outline_ directly expresses hierarchy. Many of Leo's commands_ operate on the presently selected node. It is natural to apply operations on selected node_ of the outline.

**reStructuredText is much easier to use than CWEB markup.** Leo's `rst3 plugin`_ makes it easy to use reStructuredText_ (rST) instead of CWEB_ markup. For most purposes, rST suffices, and rST is much easier to use and less intrusive than CWEB_.

**Outlines create new design dimensions**. There are many ways to express a program as a Leo outline. Such choices are important. They add clarity to the entire program. These are different *kind* of choices. They simply can not be expressed at all in other editors. In other words, such choices exist in a new design space.

**Leo improves tangling and adds untangling**. Tangling_ and untangling_ are fundamental operations of `literate programming`_. Leo tangles and untangles files derived from `@file trees`_ automatically. This is an important convenience.
Leo changes the theory and practice of literate programming as follows:

**Leo reduces the need for comments**. In particular, bridge or transition phrases are almost always unnecessary in a Leo outline_. One never needs to say something like, "having just finished with topic x, we turn now to topic y." Leo's outlines tend to be far less chatty than flat literate programs.

**Leo reduces the need for printed listings**. Experience with the ``Weave`` command shows that an outline can easily become unintelligible when printed, no matter how "beautiful" the typeset printout is. No printed listing can be as clear as Leo's outline view.

**Leo reduces the need for indices and tables of contents**. You could say the entire outline is a table of contents. Moreover, sections_ must always be defined in a descendant of the node_ containing the `section reference`_, so there is very little need for an index.

**Leo shows that outline structure is more powerful than narrative.** Indeed, narrative style creates severe maintenance problems. The narrative is soon forgotten, and when that happens it becomes difficult to find anything. The few times I have tried narrative organization I soon regretted it: things just weren't where I expected them to be.

**Leo shows that traditional literate programming encourages a too creative approach to programming.** A dictionary is a better model for programs than a novel. Leo's outlines provide a more regular organization, while providing space for the most lengthy discussions when those discussions are required.
@language rest
Naively using plugins can expose you and your .leo files to malicious attacks. The fundamental principles are::

Scripts and plugins must never blindly execute code from untrusted sources.

and::

.leo files obtained from other people may potentially contain hostile code.

Stephen Schaefer summarizes the danger this way::

I foresee a future in which the majority of leo projects come from marginally trusted sources...a world of leo documents sent hither and yon - resumes, project proposals, textbooks, magazines, contracts - and as a race of Pandora's, we cannot resist wanting to see "What's in the box?" And are we going to fire up a text editor to make a detailed examination of the ASCII XML? Never! We're going to double click on the cute leo file icon, and leo will fire up in all its raging glory. Just like Word (and its macros) or Excel (and its macros).

In other words::

When we share "our" .leo files we can NOT assume that we know what is in our "own" documents!

Not all environments are untrustworthy. Code in a commercial cvs repository is probably trustworthy: employees might be terminated for posting malicious code. Still, the potential for abuse exists anywhere.

In Python it is very easy to write a script that will blindly execute other scripts::

# Warning: extremely dangerous code

# Execute the body text of all nodes that start with `@script`. def onLoadFile(): for p in c.allNodes_iter(): h = p.headString().lower() if g.match_word(h,0,"@script"): s = p.bodyString() if s and len(s) > 0: try: # SECURITY BREACH: s may be malicious! exec(s + '\n') except: es_exception()

Executing this kind of code is typically an intolerable security risk. **Important**: rexec provides *no protection whatever*. Leo is a repository of source code, so any text operation is potentially malicious. For example, consider the following script, which is valid in rexec mode::

badNode = c.currentPosition() for p in c.allNodes_iter(): << change `rexec` to `exec` in p's body >> << delete badNode >> << clear the undo stack >>

This script will introduce a security hole the .leo file without doing anything prohibited by rexec, and without leaving any traces of the perpetrating script behind. The damage will become permanent *outside* this script when the user saves the .leo file.
The plugins test suite creates a new convention: if a plugin has a function at the outer (module) level called ``unitTest``, Leo will call that function when doing unit testing for plugins. So it would be good if writers of plugins would create such a ``unitTest function``. To indicate a failure the ``unitTest`` just throws an exception. Leo's plugins test suite takes care of the rest.
Leo reads and writes "foreign" attributes in ``<v>`` and ``<t>`` elements in .leo files as follows:

- When reading a .leo file, Leo will create ``t.unknownAttributes`` or ``v.unknownAttributes`` ivars for any ``tnode`` or ``vnode`` whose corresponding ``<v>`` or ``<t>`` element in the .leo file contains a foreign attribute.

- The ``unknownAttributes`` ivars are dictionaries whose keys are the attribute names and whose values are strings.

- When writing a file, Leo will write "foreign" attributes if a ``vnode`` or ``tnode`` contains an ``unknownAttributes`` ivar.

- The only native attribute of ``<t>`` elements is ``tx``.

- The native attributes of ``<v>`` elements are ``a``, ``t``, ``vtag`` and ``tnodeList``.

- The native attributes of ``<v>`` elements are ``marks``, ``expanded`` and ``descendentTnodeUnknownAttributes``.

- Non-native attributes are called **foreign** attributes.

- Leo performs the usual xml escapes on these strings when reading or writing the ``unknownAttributes`` ivars.

Plugins may cause Leo to write such foreign attributes simply by attaching unknownAttributes ivars to a vnode or tnode. Like this::

if hasattr(v,"unknownAttributes"): v.unknownAttributes ["vnodeIcon"] = pathToIcon else: v.unknownAttributes = {"vnodeIcon" : pathToIcon}

See the section called "Recommended conventions for plugins" for advice about how to avoid potential conflicts in naming new attributes.

All members of these dictionaries should be "pickleable". That is, Leo uses Python's Pickle module to encode all values in these dictionaries. Leo will discard any attributes that can not be pickled. This should not be a major problem to plugins. For example, instead of putting a tnode into these dictionaries, a plugin could put the tnode's gnx (a string) in the dictionary.

Leo writes only ``t.unknownAttributes`` when writing ``@thin`` trees to the .leo file. Leo puts (the encoding of) these elements into an attribute called ``descendentTnodeUnknownAttributes``. This attribute is part of the ``<v>`` element representing the ``@thin`` node. Leo does _not_ write ``v.unknownAttributes`` in ``@thin`` trees because *only tnodes have gnx's in thin derived files*. In effect, vnodes are anonymous. We could attempt to get around this by identifying vnodes by their corresponding tnodes, but that's not a general solution and it is, in effect, equivalent to writing only ``t.unknownAttributes``. So it seems pointless to "pretend" to be writing ``v.unknownAttributes``.

The effect of this is to make all vnodes identical, as far as using unknownAttributes is concerned. This won't work in all cases. For example, a plugin that creates an arbitrary directed graph between vnodes must distinguish between joined vnodes. In that case, the plugin should confine itself to @file trees, or just vnodes in .leo files, for that matter.
@language rest
In May of 1999 I began work on the Borland version of Leo for Windows. The Borland Delphi classes were a pleasure to use and free of bugs. I redesigned Leo's file format for the Windows version of Leo; the Yellow Box file format is a binary format that requires the Yellow Box runtime. Fortunately, I choose to use XML for Leo's file format. I have Marc-Antoine Parent to thank for this decision; he urged me to use XML and patiently explained how to use XML properly. However, there are two significant problems with the Borland version of Leo. First, it works only on Windows. Second, it can never be Open software, because it uses Borland's Delphi classes and a commercial syntax coloring component.

In October of 2001 I began work on the leo.py, an Open Software version of leo.py, a version of Leo written in Python and Tk. At last I have found the proper platform for Leo. leo.py naturally supports scripting in Python. The combination of Python and Tk is incredibly powerful, very easy to use, and truly cross platform. I rewrote Leo in Python in about two months! For the first time in my career I no longer am anxious while programming; it simply isn't possible to create bad bugs in Python.
The following sections give a pseudo-chronological list of the major Aha's involved in creating Leo2. These Aha's form the real design and theory of operation of Leo. See the "Diary", "Notes" and "Letters to Speed Ream" sections in LeoDocs.leo for a more accurate and less tidy history of Leo2.

I am writing these notes for several reasons. First, the initial design and coding of Leo2, spanning a period of about 8 weeks, was some of the most creative and rewarding work I have ever done. The result is elegant and simple. I'm proud of it. Second, much of the design work is not reflected in the code, because improved design often eliminated code entirely. The final code is so elegant that it obscures the hard work that created it. Third, you must understand this design in order to understand the implementation of @file trees and their derived files. Someday someone else may take charge of Leo. That person should know what really makes Leo2 work.
In the summer of 2001 I began work on a project that for a long time I had considered impossible. I had long considered that "private" file formats such as .leo files were the only way to represent an outline properly and safely. I'm not sure exactly what changed my mind, but I finally was willing to consider that information embedded in derived files might be useful. This meant accepting the possibility that sentinel lines might be corrupted. This was a crucial first step. If we can trust the user not to corrupt sentinel lines than we can embed almost any kind of information into a derived file.

There were several motivations for this work. I wanted to eliminate the need for explicit Tangle and Untangle commands. I thought of this as "Untangle on Read/Tangle on Write." If tangling and untangling could be made automatic it would save the user a lot of work. I also wanted to make derived files the primary sources files. .leo files might be made much smaller derived files contained the primary source information. This hope turned out to be false.

The result of this design work was something I originally called Leo2, though I now usually prefer to talk about @file trees. Initially most design issues were unresolved or unknown. I resolved to attempt a robust error-recovery scheme, not knowing in advance what that might involve. I also wanted to solve what I thought of as the "cross-file clone" problem: clones that point from a .leo outline into a derived file. With Leo1 cross-file clones do not exist; everything is in the same .leo file. It was clear that Leo2 would have to change some aspects of clones, but all details were fuzzy.
The next step was also crucial. I started to use Leo1 as a prototype to design what the new body pane would look like to the user. In retrospect, using Leo1 as a prototype for Leo2 was just as inspired as using MORE as a prototype for Leo1. Both prototypes marked the true beginning of their respective projects. The Leo2 prototype was a mockup in Python of the code for reading and writing derived files. The file LeoDocs.leo contain these first prototype nodes.

Writing the prototype got me thinking about improving noweb. With my experience with Leo1, I was able to create a new markup language that took advantage of outline structure. I called the new language "simplified noweb", though that terminology is obsolete. I created @file nodes to distinguish between the old and new ways of creating derived files. In Leo1, the @code directive is simply an abbreviation for a section definition line. Simplified noweb used @c as an abbreviation for @code. More importantly, simplified noweb used @c to separate doc parts from code parts without necessarily specifying a section name. It quickly became apparent that most nodes could be unnamed. All I needed was the @others directive to specify the location for all such unnamed nodes.

From the start, simplified noweb was a joy to use. Indeed, the @others directive could replace all section definition lines. Furthermore, I could make @doc directive optional if the body pane started in "code mode". But this meant that plain body text could become a "literate" program! This was an amazing discovery. These Aha's got me excited about Leo2. This was important, as it motivated me to do a lot of difficult design work.
In spite of this excitement, I was uneasy. After much "daydreaming" I realized that I was afraid that reading and writing derived files would be interrupted by a long series of alerts. I saw that designing the "user interaction" during reading and writing would be very important. The next Aha was that I could replace a long series of alerts with messages to the log window, followed by a single "summary" alert. Much later I saw how to eliminate alerts entirely.

At this time I thought there would be two kinds of "errors" while reading derived files. Warnings would alert the user that something non-serious had happened. True errors would alert the user that data might have been lost. Indeed, if Leo2 saves orphan and ignored nodes in a .leo file under an @file node, then read errors could endanger such nodes. Much later I saw that a robust error recovery scheme demands that @file nodes not contain orphan and @ignored nodes. (More on this subject later.) But if orphan and @ignored nodes are moved out of @file trees, there are no read errors that can cause data loss! So the distinction between warnings and errors finally went away.
I next turned my attention to writing @file nodes. A huge Aha: I realized that sentinel lines must contain both a leading and a trailing newline. The general principle is this: the write code must contain absolutely no "conditional" logic, because otherwise the read code could not figure out whether the condition should be true or false. So derived files contain blank lines between sentinel lines. These "extra" newlines are very useful, because the read (untangle) code can now easily determine exactly where every blank, tab and newline of the derived file came from. It would be hard to overstate how important this simplifying principle was in practice.

Much later, with urging from a customer, I realized that the write code could safely remove "extra" newlines between sentinels with a caching scheme in the low level atFile::os() routine. This scheme does not alter the body of the write code in any way: in effect, sentinels still contain leading and trailing "logical" newlines. The read code had to be modified to handle "missing" leading newlines, but this can always be done assuming that sentinels still contain logical leading and trailing newlines!

At about this time I designed a clever way of having the write code tell the read code which newlines were inserted in doc parts. (The whole point of doc parts is to have the write code format long comments by splitting long lines.) To quote from my diary:

"We can use the following convention to determine where putDocPart has inserted line breaks: A line in a doc part is followed by an inserted newline if and only if the newline is preceded by whitespace. This is a really elegant convention, and is essentially invisible to the user. Tangle outputs words until the line would become too long, and then it inserts a newline. To preserve all whitespace, tangle always includes the whitespace that terminates a word on the same line as the word itself. Therefore, split lines always end in whitespace. To make this convention work, tangle only has to delete the trailing whitespace of all lines that are followed by a 'real' newline."

After the write code was working I turned my attention to the read (untangle) code. Leo's Untangle command is the most complex and difficult code I have ever written. Imagine my surprise when I realized that the Leo2 read code is essentially trivial! Indeed, the Leo2 untangle code is like an assembler. The read code scans lines of a derived files looking for "opcodes", that is, sentinel lines, and executes some simple code for each separate opcode. The heart of this code is the scanText routine in atFile.cpp.

The read code was written and debugged in less than two days! It is the most elegant code I have ever written. While perfecting the read code I realized that sentinel lines should show the complete nesting structure found in the outline, even if this information seems redundant. For example, I was tempted to use a single sentinel to represent an @other directive, but finally abandoned this plan in favor of the @+other and @-other sentinels.

This redundancy greatly simplified the read code and made the structure of derived files absolutely clear. Moreover, it turned out that we need, in general, all the information created by the present sentinel lines. In short, sentinels are as simple as they can be, and no simpler.

The atFile::createNthChild method is a very important: it ensures that nodes will be correctly inserted into the outline. createNthChild must be bullet-proof if the Read code is to be robust. Note that the write code outputs @node sentinels, that is, section definitions, in the order in which sections are referenced in the outline, not the order in which sections appear in the outline. So createNthChild must insert the n'th node of parent p properly even if p contains fewer than n-1 children! The write code ensures that section references are properly nested: @node sentinels are enclosed in @node sentinels for all their ancestors in the @file tree. createNthChild creates dummy siblings as needed, then replaces the dummy siblings later when their actual definitions, that is, @node sentinels, are encountered.

At this point the fundamental read/write code was complete. I found three minor bugs in the code over the next week or so, but it was clear that the read/write code formed a rock-solid base from which to continue design and implementation. This was an entirely unexpected surprise.
At this point I could read and write derived files "by hand", using temporary Read and Write commands. The next step was to integrate the reading and writing of derived files with the loading and saving of .leo files. From time to time I made minor changes to the drivers for the read/write code to accommodate the Load and Save code, but at no time did I significantly alter the read or write code itself.

The user interaction of the Load and Save commands drove the design and implementation of the load/store code. The most important questions were: "what do we tell the user?", and "what does the user do with the information?" It turns out that the user can't make any complex decision during error recovery because the user doesn't have nearly enough information to make an informed choice. In turn, this means that certain kinds of error recovery schemes are out of the question...
I now turned my attention to "attributes" of nodes. Most attributes, like user marks, are non-essential. However, clone information is essential; we must never lose clone links. At this time I had a preliminary design for cross-file clones that involved a two part "pointer" consisting of a full path name and an immutable clone index within the derived file. Eventually such pointers completely disappeared, but the immutable clone indices remain.

My first thought was that it would be good to store all attributes in @node sentinels in the derived file, but experience showed that would be irritating. Indeed, one wants Leo2 to rewrite derived files only if something essential has changed. For example, one doesn't want to rewrite the derived file just because a different node as been selected.

At this point I had another Aha: we can use the .leo file to store all non-essential attributes. For example, this means that the .leo file, not the derived files, will change if we select a new node. In effect, the .leo file mirrors the derived file. The only reason to store nodes in the .leo file under an @file node is to carry these attributes, so Leo2 wrote dummy nodes that do not reference body text. Much later I saw that dummy nodes were dangerous and that .leo files should contain all information found in derived files.
The concept of mirroring created a huge breakthrough with cross-file clones: Here is an excerpt of an email i sent to my brother Speed:

"I realized this morning that since a .leo file contains dummy vnodes for all nodes in a derived file, those dummy nodes can carry clone info! I changed one line to make sure that the write code always writes clone info in dummy vnodes and voila! Cross-file clones worked!"

All of Leo1's clone code could be used completely unchanged. Everything "just works".
At first I thought we could make sure that the .leo file always correctly mirrors all derived file, but disastrous experience showed that is a completely false hope. Indeed, backup .leo files will almost never mirror derived file correctly. So it became urgent to find a completely fool-proof error recovery scheme.

I had known for quite a while that error recovery should work "as if" the mirroring nodes were deleted, then recreated afresh. Several failed attempts at an error recovery scheme convinced me that error recovery would actually have to delete all dummy nodes and then do a complete reread. This is what Leo2 does.

But erasing dummy nodes would destroy any orphan and ignored nodes--by definition such nodes appear nowhere in the derived file. Therefore, I had to enforce the rule that @file nodes should contain no such nodes. Here is an email I wrote to my brother, Speed Ream discussing what turned out to be the penultimate error recovery scheme:

"The error recovery saga continues. After much pondering and some trial coding I have changed my mind about orphans and @ignored nodes. They simply should never appear as descendants of @file nodes. Fortunately, this simplifies all aspects of Leo2. Leo2 will issue a warning (not an error) if an orphan or @ignored node appears as the descendant of an @file node when a .leo file is being saved. If any warnings occur while writing the derived file, Leo2 will write the "offending" @file tree to the .leo file instead of the derived file. This has several advantages:

1. The user gets warned about orphan nodes. These are useful warnings! Orphan nodes arise from missing @others directives or missing section references.

2. The user doesn't have to change anything immediately in order to save an outline. This is very important. Besides warnings about orphans, Leo2 will also warn about undefined or unreferenced sections. User's shouldn't have to fix these warnings to do a Save!

3. No errors or alerts will occur during Reading or Writing, so the user's anxiety level goes way down. At worst, some informational message will be sent to the log. The user will never have to make important decisions during Loads or Saves. [At last the dubious distinction between errors and warnings disappears.]

4. Error recovery can be bullet-proof. Simple code will guarantee that after any read operation the structure of an @file node will match the structure of the derived file. Also, sentinels in derived files will now account for all children of an @file node. There are no more "missing nodes" that must be filled in using the .leo file. Finally, error recovery will never change the @file tree in any way: no more "recovered nodes" nodes.

5. The present read code can be used almost unchanged. The only addition is the posting of a warning if the structure of the .leo file does not match the structure of the derived file. We need a warning because non-essential attribute of nodes (like user marks) may be altered."

This ends the original history of Leo2. In fact, it took quite a while before Leo recovered properly from all errors. I finally saw that .leo files should duplicate all information in derived files. This allows a .leo file to be used a single backup file and allows maximal error recovery in all situations. It took several months to stamp out several subtle bugs involving clones that caused spurious read errors. Such errors undermine confidence in Leo and can cause disastrous reversions. See my diary entries for January 2002 in leo.py for details.

The more I look at Tk, the more convinced I am that Python + Tk (aka Tkinter) is, by far, the best way to go with Leo. I now have Open Source code for tree widgets and splitter windows, and have intensely studied how to modify that code for use in Leo. It is clear, even at this early date, that this code will provide a very pleasant base on which to build Leo.

The tree code is based on code in ``IDLE``, the Python IDE. This code is simple, good and plenty fast enough. The tree code draws directly to a Tk canvas object. The look and feel matches Windows exactly. It would be trivial to use Mac triangle icons instead of the Windows plus and minus icons. It would also be trivial to modify the look and feel for Linux.

The tree widget code solves several intractable problems with ``wxTreeCtrl``. Moving nodes becomes trivial. Bugs in ``wxTreeCtrl`` involving editing and redrawing disappear. Using Python/Tk code simplifies the vnode class, and having access to the vnode class simplifies and speeds up the tree widget code. It will now be possible to bind keystrokes properly; this simply can not be done in ``wxWindows``. The tree widget code shows just how trivial the Windows native tree control is. The Tk canvas is a splendid example of higher-level code being superior, in every way, to lower level code.

Another big win comes from using the Tk text widget. This widget is extraordinarily powerful. The only text control that rivals it is the ``MacOS/Yellow Box`` text control. Indeed, the Tk text widget does everything that Leo could possibly want. One can even embed images in text.

In short, using Tk for Leo will be fast enough and will greatly increase what is possible in Leo while at the same time greatly simplifying Leo's code. I am about to convert Leo from wxPython to Python + Tk. Edward K. Ream, November 4, 2001
I've known for a while that Python was interesting; I attended a Python conference last year and added Python support to Leo. But last week I got that Python is something truly remarkable. I wanted to convert Leo from wxWindows to wxPython, so I began work on c2py, a Python script that would help convert from C++ syntax to Python. While doing so, I had an Aha experience. Python is more than an incremental improvement over Smalltalk or C++ or objective-C; it is "something completely different". The rest of this post tries to explain this difference.
@language rest
All versions of Leo are organized as a collection of classes. The general organization of Leo has remained remarkably stable throughout all versions of Leo, although the names of classes are different in different versions. Smalltalk's Model/View/Controller terminology is a good way think about Leo's classes. **Model classes** represent the fundamental data. The vnode and tnode classes are Leo's primary model classes.

**View classes** draw the screen. The main view classes are leoFrame.py and leoTree.py. The colorizer class in leoColor.py handles syntax coloring in the body pane. Leo's view classes know about data stored in the vnode class. Most events (keystrokes and mouse actions) in the outline and body pane are handled in the leoTree class. The leoFrame class also creates the Leo window, including menus, and dispatches the appropriate members of the controller classes in response to menu commands.

**Controller classes** (aka commanders) control the application. In Leo, controllers mostly handle menu commands. Commanders create subcommanders to handle complex commands. The atFile class reads and writes files derived from ``@file`` trees. The LeoFind class handles the Find and Change commands. The leoImportCommands class handles the Import and Export commands, the tangleCommands class handles the Tangle and Untangle commands and the undoer class handles the Undo command. Other classes could be considered controller classes.

Each Leo window has its own commander and subcommanders. Subcommanders are not subclasses of their commander. Instead, subcommanders know the commander that created them, and call that commander as needed. Commanders and subcommanders call the model and view classes as needed. For example, the Commands class handles outline commands. To move a headline, the commander for the window calls a vnode move routine to alter the data, then calls the view class to redraw the screen based on the new data.

A singleton instance of the **LeoApp** class represents the application itself. All code uses the app() global function to gain access to this singleton member. The ivars of the LeoApp object are the equivalent of Leo's global variables. leo.py uses no global Python variables, except the gApp variable returned by app(). leoGlobals.py defines all application constants. Naturally, most constants are local to the class that uses them.

Several classes combine aspects of model, view and controller. For example, the **LeoPrefs** class represents user preferences (model), the Preference Panel (view) and the Preferences menu command (controller). Similarly, the **LeoFind** class represents find settings, the Find/Change dialog, and the Find/Change commands.

We use the following convention throughout this documentation. Any variable named ``c`` is a commander, i.e., an instance of the Commands class in ``leoCommands.py``. Variables named ``v`` and ``t`` are vnodes and tnodes respectively. These classes are defined in ``leoNodes.py``.
The vnode and tnode classes represent most of the data contained in the outline. These classes are Leo's fundamental Model classes. A **vnode** (visual node) represents a headline at a particular location on the screen. When a headline is cloned, vnodes must be copied. vnodes persist even if they are not drawn on the screen. Commanders call vnode routines to insert, delete and move headlines.

The vnode contains data associated with a headline, except the body text data which is contained in tnodes. A vnode contains headline text, a link to its tnode and other information. Vnodes contain structure links: parent, firstChild, next and back ivars. To insert, delete, move or clone a vnode the vnode class just alters those links. The Commands class calls the **leoTree** class to redraw the outline pane whenever it changes. The leoTree class knows about these structure links; in effect, the leoTree and vnode classes work together.

A **tnode**, (text node) represents body text. All vnodes that are clones of each other share the same tnode. In other words, tnodes are the unit of sharing of body text. The tnode class is more private than the vnode class. Most commanders deal only with vnodes, though there are exceptions.

Because Leo has unlimited Undo commands, Leo deletes vnodes and tnodes only when a window closes. Leo deletes nodes indirectly using ``destroy`` methods. Several classes, including the vnode, tnode, leoFrame and leoTree classes, have ``destroy`` methods. ``destroy`` methods merely clear links so that Python's and Tkinter's reference counting mechanisms will eventually delete vnodes, tnodes and other data when a window closes.

Leo's XML file format uses **tnode indices** to indicate which tnodes (t elements) belong to which vnodes (v elements). Such indices are required. Even if we duplicated the body text of shared tnodes within the file, the file format would still need an unambiguous way to denote that tnodes are shared. Present versions of Leo use **gnx's** (global node indices) as node indices. These indices do not change once a node has created. This reduces cvs conflicts.
Leo must redraw the outline pane when commands are executed and as the result of mouse and keyboard events. The main challenges are eliminating flicker and handling events properly. These topics are interrelated.

**Eliminating flicker**. Leo must update the outline pane with minimum flicker. Various versions of Leo have approached this problem in different ways. The drawing code in leo.py is robust, flexible, relatively simple and should work in almost any conceivable environment. Leo assumes that all code that changes the outline pane will be enclosed in matching calls to the c.beginUpdate and c.endUpdate methods of the Commands class. c.beginUpdate() inhibits drawing until the matching c.endUpdate(). These calls may be nested; only the outermost call to c.endUpdate() calls c.redraw() to force a redraw of the outline pane.

Code may call ``c.endUpdate(flag)`` instead of ``c.endUpdate()``. Leo redraws the screen only if flag is true. This allows code to suppress redrawing entirely when needed. For example, here is how the idle_body_key event handler in leoTree.py conditionally redraws the outline pane::

redraw_flag = false c.beginUpdate() val = v.computeIcon() if val != v.iconVal: v.iconVal = val redraw_flag = true c.endUpdate(redraw_flag) # redraw only if necessary

The leoTree class redraws all icons automatically when ``c.redraw()`` is called. This is a major simplification compared to previous versions of Leo. The entire machinery of drawing icons in the vnode class has been eliminated. The ``v.computeIcon`` method tells what the icon should be. The ``v.iconVal`` ivar tells what the present icon is. The event handler simply compares these two values and sets ``redraw_flag`` if they don't match.

**Handling events.** Besides redrawing the screen, Leo must handle events or commands that change the text in the outline or body panes. It is surprisingly difficult to ensure that headline and body text corresponds to the vnode and tnode corresponding to presently selected outline, and vice versa. For example, when the user selects a new headline in the outline pane, we must ensure that 1) the vnode and tnode of the previously selected node have up-to-date information and 2) the body pane is loaded from the correct data in the corresponding tnode. Early versions of Leo attempted to satisfy these conditions when the user switched outline nodes. Such attempts never worked well; there were too many special cases. Later versions of Leo, including leo.py, use a much more direct approach. The event handlers make sure that the vnode and tnode corresponding to the presently selected node are always kept up-to-date. In particular, every keystroke in the body pane causes the presently selected tnode to be updated immediately. There is no longer any need for the ``c.synchVnode`` method, though that method still exists for compatibility with old scripts.

The leoTree class contains all the event handlers for the body and outline panes. The actual work is done in the ``idle_head_key`` and ``idle_body_key`` methods. These routines are surprisingly complex; they must handle all the tasks mentioned above, as well as others. The ``idle_head_key`` and ``idle_body_key`` methods should not be called outside the leoTree class. However, it often happens that code that handles user commands must simulate an event. That is, the code needs to indicate that headline or body text has changed so that the screen may be redrawn properly. The leoTree class defines the following simplified event handlers: ``onBodyChanged``, ``onBodyWillChange``, ``onBodyKey``, ``onHeadChanged`` and ``onHeadlineKey``. Commanders and subcommanders call these event handlers to indicate that a command has changed, or will change, the headline or body text. Calling event handlers rather than ``c.beginUpdate`` and ``c.endUpdate`` ensures that the outline pane is redrawn only when needed.
Since version 4.2, Leo represents clones by sharing tnodes. Cloned vnodes share the same tnode. This shared tnode represents the entire shared subtree of both clones. Thus, the ``_firstChild`` link must reside in *tnodes*, not *vnodes*.

Because vnodes may be visited many times during a complete traversal of a tree, a vnode does not represent unique location on the screen. As a result, the **position** class had to be invented. ``c.rootVnode`` and ``c.currentVnode`` now return *positions* instead of vnodes. The position class was designed to allow compatibility with old scripts. Old code can use positions just like they used to use vnodes.

Earlier versions of Leo duplicated all the descendants of vnode v when cloning v. This created many complications that no longer exist. In particular, in the new scheme a vnode v is cloned if and only if ``len(v.t.vnodeList) > 1``.
The find and change commands are tricky; there are many details that must be handled properly. The following principles govern the LeoFind class:

1. Find and Change commands initialize themselves using only the state of the present Leo window. In particular, the Find class must not save internal state information from one invocation to the next. This means that when the user changes the nodes, or selects new text in headline or body text, those changes will affect the next invocation of any Find or Change command. Failure to follow this principle caused all kinds of problems in the Borland and Macintosh codes. There is one exception to this rule: we must remember where interactive wrapped searches start. This principle simplifies the code because most ivars do not persist. However, each command must ensure that the Leo window is left in a state suitable for restarting the incremental (interactive) Find and Change commands. Details of initialization are discussed below.

2. The Find and Change commands must not change the state of the outline or body pane during execution. That would cause severe flashing and slow down the commands a great deal. In particular, the ``c.selectPosition`` and ``c.editPosition`` methods must not be called while looking for matches.

3. When incremental Find or Change commands succeed they must leave the Leo window in the proper state to execute another incremental command. We restore the Leo window as it was on entry whenever an incremental search fails and after any Find All and Change All command. Initialization involves setting the ``self.c``, ``self.v``, ``self.in_headline``, ``self.wrapping`` and ``self.s_text`` ivars.

Setting ``self.in_headline`` is tricky; we must be sure to retain the state of the outline pane until initialization is complete. Initializing the Find All and Change All commands is much easier because such initialization does not depend on the state of the Leo window. Using Tk.Text widgets for both headlines and body text results in a huge simplification of the code.

Indeed, the searching code does not know whether it is searching headline or body text. The search code knows only that ``self.s_text`` is a Tk.Text widget that contains the text to be searched or changed and the insert and sel Tk attributes of self.search_text indicate the range of text to be searched. Searching headline and body text simultaneously is complicated. The selectNextVnode() method handles the many details involved by setting ``self.s_text`` and its insert and sel attributes.
This section describes Leo's explicit ``Tangle`` and ``Untangle`` commands. Such commands operate only on ``@root`` and ``@unit`` trees. The previous chapter discusses the implicit Tangle on Write/Untangle on Read processes used to read and write ``@file`` trees.

The ``Tangle`` command translates the selected ``@root`` tree into one or more well-formatted C source files. The outline should contain directives, sections references and section definitions, as described in Chapter 4. The Untangle command is essentially the reverse of the ``Tangle`` command. The Tangle command creates a derived file from an ``@root`` tree; the Untangle command incorporates changes made to derived files back into the ``@root`` tree.

The ``Tangle`` command operates in two passes. The first pass discovers the complete definitions of all sections and places these definitions in a symbol table. The first pass also makes a list of root sections. Definitions can appear in any order, so we must scan the entire input file to know whether any particular definition has been completed.

This second pass creates one file for each ``@root`` node. ``Tangle`` rescans each section in the list of roots, copying the root text to the output and replacing each section reference by the section's definition. This is a recursive process because any definition may contain other references. We can not allow a section to be defined in terms of itself, either directly or indirectly. We check for such illegally recursive definitions in pass 2 using the section stack class. ``Tangle`` indicates where sections begin and end using comment lines called sentinel lines. The this part of the appendix discusses the format of the sentinels output by the ``Tangle`` command.

The key design principle of the ``Tangle`` command is this::

Tangle must output newlines in a context-free manner.

That is, ``Tangle`` must never output conditional newlines, either directly or indirectly. Without this rule ``Untangle`` could not determine whether to skip or copy newlines.

The ``Tangle`` command increases the indentation level of a section expansion the minimum necessary to align the section expansion with the surrounding code. In essence, this scheme aligns all section expansions with the line of code in which the reference to the section occurs. In some cases, several nested sections expansions will have the same indentation level. This can occur, for example, when a section reference in an outline occurs at the left margin of the outline.

This scheme is probably better than more obvious schemes that indent more "consistently." Such schemes would produce too much indentation for deeply nested outlines. The present scheme is clear enough and avoids indentation wherever possible, yet indents sections adequately. End sentinel lines make this scheme work by making clear where the expansion of one section ends and the expansion of a containing section resumes.

``Tangle`` increases indentation if the section reference does not start a line. Untangle is aware of this hack and adjusts accordingly. This extra indentation handles several common code idioms, which otherwise would create under-indented code. In short, ``Tangle`` produces highly readable output, given the necessity of preserving newlines for ``Untangle``.

``Untangle`` is inherently complex. It must do a perfect job of updating the outline, especially whitespace, from expansions of section definitions created by the Tangle command. Such expansions need not be identical because they may have been generated at different levels of indentation. The ``Untangle`` command can not assume that all expansions of a section will be identical in the derived file; within the derived file, the programmer may have made incompatible changes to two different expansions of the same section. ``Untangle`` must check to see that all expansions of a section are "equivalent". As an added complication, derived files do not contain all the information found in ``@root`` trees. ``@root`` trees may contain headlines that generate no code at all. Also, an outline may define a section in several ways: with an ``@c`` or ``@code`` directive or with a section definition line. To be useful, Untangle must handle all these complications flawlessly. The this part of the appendix discusses the various conventions used in the sentinels output by the ``Tangle`` command. These conventions allow the ``Untangle`` command to recreate whitespace correctly.

``Untangle`` operates in two passes. The first pass finds definitions in the derived file and enters them into the **Untangle Symbol Table**, or UST. Definitions often include references to other sections, so definitions often include nested definitions of referenced sections. The first pass uses a definition stack to keep track of nested definitions. The top of the stack represents the definition following the latest reference, except for the very first entry pushed on the stack, which represents the code in the outline that contains the ``@root`` directive. The stack never becomes empty because of the entry for the ``@root`` section. All definitions of a section should match--otherwise there is an inconsistent definition. This pass uses a forgiving compare routine that ignores differences that do not affect the meaning of a program.

The second pass of ``Untangle`` enters definitions from the outline into the **Tangle Symbol Table**, or TST. The second pass simultaneously updates all sections in the outline whose definition in the TST does not match the definition in the UST. The central coding insight of the Untangle command is this: **the second pass of Untangle is almost identical to the first pass of Tangle**. That is, ``Tangle`` and ``Untangle`` share key parts of code, namely the ``skip_body`` method and its allies. Just when ``skip_body`` enters a definition into the symbol table, all the information is present that ``Untangle`` needs to update that definition.
Leo uses unicode objects in vnodes and tnodes to denote headline and body text. Note that unicode strings have no encoding; only plain strings have encodings. This means that once an (encoded) plain string has been converted to a unicode string it doesn't matter how the unicode string was created. This is the key that makes Leo's new code robust: internally Leo never has to worry about encodings. Encoding matter only when encoded strings are converted to and from Unicode. This happens when Leo reads or writes files.

Python expressions that mix unicode strings u and plain strings s, like one of these::

u + s u == s u[5] == s[2:]

are promoted to unicode objects using the "system encoding". This encoding should never be changed, but we can't assume that we know what it is, so for safety we should assume the most restrictive encoding, namely "ascii". With this assumption, Leo's code can't throw an exception during these promotions provided that:

- All strings are converted to unicode when Leo reads files or gets text from Tk.Text widgets.

- All string literals in Leo's code have only ascii characters.
Unlimited undo is straightforward; it merely requires that all commands that affect the outline or body text must be undoable. In other words, everything that affects the outline or body text must be remembered. We may think of all the actions that may be Undone or Redone as a string of beads (undo nodes).

Undoing an operation moves backwards to the next bead; redoing an operation moves forwards to the next bead. A bead pointer points to the present bead. The bead pointer points in front of the first bead when Undo is disabled. The bead pointer points at the last bead when Redo is disabled. An undo node is a Python dictionary containing all information needed to undo or redo the operation. The Undo command uses the present bead to undo the action, then moves the bead pointer backwards.

The Redo command uses the bead after the present bead to redo the action, then moves the bead pointer forwards. All undoable operations call setUndoParams() to create a new bead. The list of beads does not branch; all undoable operations (except the Undo and Redo commands themselves) delete any beads following the newly created bead. I did not invent this model of unlimited undo. I first came across it in the documentation for Apple's Yellow Box classes.
@language rest
To convert an ``@root`` tree to an ``@file`` tree, choose the root of the tree to be converted, then do the following in the Python window::

import c2py c2py.leo1to2()

This script makes numerous changes throughout the tree. It does not, however, change ``@root`` to ``@file``, or insert the needed ``@others`` directives. You must do that by hand.

To convert ``@root`` trees to ``@file`` trees by hand:

1. Change the ``@root`` node to an ``@file`` node. That is, delete the ``@root <filename>`` from the body text and insert ``@file <filename>`` in the headline. Typically, the root node contains a reference like ``<<methods of class x>>`` as the last body text. Replace this reference with the ``@others`` directive. The expansion of @others is all text that is not part of a section definition.

2. Add ``@`` to the start of all doc parts. Leo starts syntax coloring in code mode rather than doc mode, so if a doc part starts body text it should start with ``@``

3. Replace all section definition lines (like ``<<name>>=``) by ``@c``. This results in the node being added to the expansion of ``@others``.

4. Remove all unused code from the ``@file`` tree. Leo does not write derived files whose ``@file`` trees contain orphan or ``@ignore`` nodes.

5. Make sure that all nodes defining a section have a headline that starts with ``<<section>>``. This will typically be true when converting ``@root`` trees that use the ``@code`` directive.

6. If a section is referenced in more than one node (a rare occurrence in my code), clone the defining node and move one clone under each referencing node.

7. If a node contains the definitions of several sections, place each different definition in a different node.
The following error messages may be generated by the ``Tangle`` commands.

``Can not re-open temp file`` A file error occurred while trying to reopen the temporary file used during tangling.

``Can not rename temporary file name`` A file error occurred while trying to change the name of the temporary file used during tangling.

``@code expects the header: [text of header] to contain a section name`` An @code directive appeared in body text whose header does not contain a section name.

``@directive not valid here`` An @directive was seen somewhere other than the start of a line.

``Halting Tangle: too many errors`` Tangle detected more than 20 errors.

``Invalid recursive reference of << section name >>`` A section was defined in terms of itself, either directly or indirectly. The trace shows the chain of section definitions that resulted in the illegal definition.

``This message is followed by a walkback of the section names that recursively reference the section.`` The walkback looks like this::

called from << section name >> called from << section name >> ...

``Multiple parts not allowed for << section name >>`` Sections can be defined in several parts in two ways:

1. Using ``<< section name >>=`` in several places with the same section name.

2. Using several ``@code`` directives within the same body text.

As a precaution against mistakenly defining a section in more than one place, it is invalid to use @code in different nodes to define multiple parts for the same section. In particular, this error may arise when using cloned nodes. This error may always be eliminated by using ``<< section name >>=`` instead of ``@code``.

``No file written because of errors`` Tangle did not write a file because errors were found.

``Run on comment`` A C-language comment was not properly terminated.

``Run on file name in @root directive`` The file name in an @root directive was not terminated with the proper delimiter.

``Run on section name`` A section name was not properly terminated before the end of the line in which it started.

``Run on string`` A C-language string or character constant was not properly terminated.

``Section definition not valid here.`` Something that looks like a section definition was seen in the middle of a line.

``Sections nested too deeply`` A section was defined using more than 100 levels of section definitions (!) You could easily create an outline containing every computer program ever written in less than 50 levels.

``The outline contains no roots`` The selected outline contained no @root directive.

``Undefined section: <<< section name >>>`` A reference to an undefined section was encountered.

``Unexpected @directive while putting code`` Tangle outputs 2-character WEB control code in a comment. This message is given if we find such comments in a code definition.

``Warning: possible duplicate definition of: <<< section name >>>`` (The text of the duplicate definition follows.) The section may have been defined in more than one place.

``Warning: <<< section name >>> has been defined but not used`` The indicated section appears in the outline but is never referenced.
The following error messages may be generated by the Untangle commands.

Incompatible definitions of <<< section name >>> Two expansions of ``<< section name >>`` were different in the derived file. This typically arises when the programmer changes one of the expansions but not the other.

Missing root part No end sentinel line was found for a part of the expansion of the code in the ``@root`` node. This is likely the result of adding, deleting or altering a sentinel line.

``Missing root section`` No end sentinel line was found for the expansion of the code in the ``@root`` node. This is likely the result of adding, deleting or altering a sentinel line.

``Missing sentinel line for <<< section name >>>`` The end sentinel name for ``<< section name >>`` was expected but not found. This is likely the result of adding, deleting or altering a sentinel line.

``Unterminated section: <<< section name >>>`` The end of the file was reached before encountering the end sentinel line for ``<< section name >>``. This is likely the result of adding, deleting or altering a sentinel line.
The following are all serious errors, meaning that the data in a derived file has been corrupted::

Bad @+leosentinel in <filename> Bad @delims Bad attribute field in @+node Bad child index in @+node File may have damaged sentinels! Ignoring <sentinel kind> sentinel. Expecting <sentinel kind> Ignoring unexpected @+leo sentinel Missing <sentinel kind> sentinel Missing @file in root @node sentinel Outline corrupted: different nodes have same clone index! Replacing body text of orphan <node name> Unexpected end of file. Expecting <sentinel kind> sentinel Unknown sentinel: <sentinel line>

You should restore the information from a backup .leo file using the ``Read Outline Only`` commands, followed by a ``Write @file Nodes`` command
Errors while writing ``@file`` nodes are harmless. No information is lost because all information is written to the .leo file rather than the derived file.

``bad @delims directive`` A node contains an ill-formed ``@delims`` directive.

``@ignore node <headline>`` The body text of *headline* contains an ``@ignore`` directive.

``orphan node: <headline>`` The node is referenced by no ancestor node, and no ``@others`` directive applies to it.

``@others already expanded in: <headline>`` The node contains more than one ``@others`` directive.

``Rename failed: no file created! (file may be read-only)`` Leo's ``Save`` command writes derived files to a temporary file, and replaces the derived file by the temporary files only if the two files are different. A problem with the file system prevented the temporary file from being renamed.

``Path does not exist: <filename>``

``undefined section: <section name> referenced from: <headline>`` The node given by *headline* contains a reference to *section name* but no section definition node for *section name* exists in the descendants of *headline*.
The following bugs can not be fixed:

1. The ``Untangle`` command has no way of updating a section whose name has been changed in the derived file.

Because of the ``@unit`` directive, there is not even a way to issue a meaningful warning.

2. The ``Tangle`` command treats ``@c`` like ``@code`` in ``CWEB`` mode.

I recommend changing ``@c`` to ``@< c @>=`` throughout your ``CWEB`` sources and adding a reference to ``@< c @>`` in all roots of ``CWEB`` files.
Leo uses unicode internally for all strings.

1. Leo converts headline and body text to unicode when reading .leo files and derived files. Both .leo files and derived files may specify their encoding. The default is ``utf-8``. If the encoding used in a derived file is not "utf-8" it is represented in the ``@+leo`` sentinel line. For example::

#@+leo-encoding=iso-8859-1.

The ``utf-8`` encoding is a "lossless" encoding (it can represent all unicode code points), so converting to and from utf-8 plain strings will never cause a problem. When reading or writing a character not in a "lossy" encoding, Leo converts such characters to '?' and issues a warning.

2. When writing .leo files and derived files Leo uses the same encoding used to read the file, again with ``utf-8`` used as a default.

3. leoSettings.leo contains the following Unicode settings, with the defaults as shown::

default_derived_file_encoding = UTF-8 new_leo_file_encoding = UTF-8

These control the default encodings used when writing derived files and .leo files. Changing the ``new_leo_file_encoding`` setting is not recommended. See the comments in leoSettings.leo. You may set ``default_derived_file_encoding`` to anything that makes sense for you.

4. The ``@encoding`` directive specifies the encoding used in a derived file. You can't mix encodings in a single derived file.
This technical information may be of use to those wanting to process Leo files with special-purpose filters. Leo's uses XML for its file format. The following sections describe this format in detail. **Important**: The actual read/write code in leoFileCommands.py is the authoritative guide. When in doubt about what Leo actually writes, look at an actual .leo file in another editor.

Here are the elements that may appear in Leo files. These elements must appear in this order.

``<?xml>`` Leo files start with the following line::

<?xml version="1.0" encoding="UTF-8"?>

``<?xml-stylesheet>`` An xml-stylesheet line is option. For example::

<?xml-stylesheet ekr_stylesheet?>

``<leo_file>`` The ``<leo_file>`` element opens an element that contains the entire file. ``</leo_file>`` ends the file.

``<leo_header>`` The ``<leo_header>`` element specifies version information and other information that affects how Leo parses the file. For example::

<leo_header file_format="2" tnodes="0" max_tnode_index="5725" clone_windows="0"/>

The ``file_format`` attribute gives the 'major' format number. It is '2' for all 4.x versions of Leo. The ``tnodes`` and ``clone_windows`` attributes are no longer used. The ``max_tnode_index`` attribute is the largest tnode index.

``<globals>`` The ``globals`` element specifies information relating to the entire file. For example::

<globals body_outline_ratio="0.50"> <global_window_position top="27" left="27" height="472" width="571"/> <global_log_window_position top="183" left="446" height="397" width="534"/> </globals>

- The ``body_outline_ratio attribute`` specifies the ratio of the height of the body pane to the total height of the Leo window. It initializes the position of the splitter separating the outline pane from the body pane.

- The ``global_window_position`` and ``global_log_window_position`` elements specify the position of the Leo window and Log window in global coordinates:

``<preferences>`` This element is vestigial. Leo ignores the ``<preferences>`` element when reading. Leo writes an empty ``<preferences>`` element.

``<find_panel_settings>`` This element is vestigial. Leo ignores the ``<find_panel_settings>`` element when reading. Leo writes an empty ``<find_panel_settings>`` element.

``<clone_windows>`` This element is vestigial. Leo ignores the ``<clone_windows>`` element when reading. Leo no longer writes ``<clone_windows>`` elements.

``<vnodes>`` A single ``<vnodes>`` element contains nested ``<v>`` elements. ``<v>`` elements correspond to vnodes. The nesting of ``<v>`` elements indicates outline structure in the obvious way.

``<v>`` The ``<v>`` element represents a single vnode and has the following form::

<v...><vh>sss</vh> (zero or more nested v elements) </v>

The ``<vh>`` element specifies the headline text. ``sss`` is the headline text encoded with the usual XML escapes. As shown above, a ``<v>`` element may contain nested ``<v>`` elements. This nesting indicates outline structure in the obvious way. Zero or more of the following attributes may appear in ``<v>`` elements::

t=name.timestamp.n a="xxx"

The ``t="Tnnn"`` attribute specifies the tnode associated with this vnode. The ``a="xxx"`` attribute specifies vnode attributes. The ``xxx`` denotes one or more upper-case letters whose meanings are as follows::

C The vnode is a clone. (Not used in 4.x) E The vnode is expanded so its children are visible. M The vnode is marked. T The vnode is the top visible node. V The vnode is the current vnode.

For example, ``a="EM"`` specifies that the vnode is expanded and is marked.

**New in 4.0**:

- ``<v>`` elements corresponding to ``@file`` nodes now contain ``tnodeList`` attributes. The ``tnodeList`` attribute allows Leo to recreate the order in which nodes should appear in the outline. The ``tnodeList`` attribute is a list of gnx's: global node indices. See ``Format of derived files (4.x)`` for the format of gnx's.

- Plugins and scripts may add attributes to ``<v>`` and ``<t>`` elements. See `Chapter 13: Writing plugins`_ for details.

``<tnodes>`` A single ``<tnodes>`` element contains a non-nested list of ``<t>`` elements.

``<t>`` The ``<t>`` element represents a single tnode and has this form::

<t tx="Tnnn"><tb>sss</tb></t>

The ``tx`` attribute is required. The ``t`` attribute of ``<v>`` elements refer to this ``tx`` attribute. The ``<tb>`` element specifies the body text. ``sss`` is the headline text encoded with the usual XML escapes.

**New in 4.0**: Plugins and scripts may add attributes to ``<v>`` and ``<t>`` elements. See `Chapter 13: Writing plugins`_ for details.
@language rest
Leo 4.2 alpha 3 June 1, 2004

This version fixes completes the essential features of version 4.2. All known incompletions and bugs involving shared nodes and Leo's new file format have been fixed. BTW, this version of Leo completes Leaps 201 and 202.

It should be safe to use this version for collaboration between Leo's developers. I hereby encourage people to start using cvs for collaboration. Only by doing so will we discover any possible problems.

The only item that must be completed before releasing 4.2 beta is fixing the Go To Line Number command so it supports thin derived files.

There are many known bugs in this version: most are minor bugs that have been around for a long time. All known bugs will be fixed by the first release candidate. See the to-do list in LeoPy.leo for the complete list.

The highlights of this version:

- All features of @file-thin are now complete and appear to be stable. - All .leo files in the distribution use @thin files where possible. - Leo ignores all directives within the range of the @all directive. - The @+middle and @-middle sentinels allow sections to be defined in any descendant node. - The @clone sentinel marks duplicate cloned siblings. - The beginnings of a new undo scheme are in place. - @thin, @nosent, @noref and @asis are abbreviations for @file-thin, @file-nosent, @file-noref and @file-asis. - Created new iterators that return lists of vnodes and tnodes, including iterators that remove all duplicates from those lists.
This happened after write errors such as orphan nodes.
Added u.registerUndoHandlers.

This will become largely unnecessary in the new undo scheme. It's good to have though.
When writing .leo files Leo now pickle's and hexlify's all data in the v.unknownAttribute and t.unknownAttribute dictionaries. When reading .leo files Leo does the reverse.

Leo ignores all elements in these dictionaries if some element can not be pickled.
I have fallen madly in love with generators. The following new iterators are defined with generators.

c.all_positions_iter c.all_tnodes_iter c.all_vnodes_iter c.all_unique_tnodes_iter c.all_unique_vnodes_iter

p.tnodes_iter p.vnodes_iter p.unique_tnodes_iter p.unique_vnodes_iter

v.self_and__subtree_iter v.self_and_unique_subtree_iter
If the copied node was an @thin or @file-thin node node only the root node was copied.
This bug exists in 4.1 final. Leo did not properly show the found text in headlines. The fix was in the code that redraws the screen, not in the find/change code itself.
The new scheme simply saves all information in one or more vnodes and their associated tnodes. This is a general scheme that can be used by almost any command.

At present only the u.saveTree method exists. Coming soon, u.saveNode, u.saveNodeAndChildren and u.saveListOfNodes.
See the to-do list in LeoPy.leo for a list of known bugs in this version.

None of these bugs is serious: I consider this version to be suitable for day-to-day work.
Leo 4.2 beta 2 July 5, 2004 Leo 4.2 beta 1 June 30, 2004

The highlights of 4.2 beta 2:

- Leo now writes the entire contents of @ignore'd @thin trees to the .leo file. This change ensures that users can create and remove @ignore directives without any chance of losing data inadvertently.

- Leo now saves and restores marks and the expansion state of nodes in @thin trees.

- Leo marks @thin nodes as dirty whenever they become "newly unignored", i.e., when an @thin node no longer falls in the range of an @ignore directive.

Beta 1 completes all fundamental work in the 4.2 code base. All essential code is complete. Dozens of bugs have been fixed since the Alpha 3 release about a month ago.

Known bugs in 4.2 beta 2:

- Not all plugins work correctly. - Some plugins leak memory very slightly.

The highlights of Leo 4.2:

- @thin trees make Leo much more friendly to cvs. Files derived from @thin can be committed to cvs and updated from cvs without having to commit or update the corresponding .leo file. There is no longer any need to keep .leo files and derived files in synch.

- Leo's data structures have been reorganized. As a result, all outline operations are much faster. To support this organization, scripts that traverse Leo's data structures must now use a positions rather than vnodes. Old scripts that appear to use vnodes will still work because methods like c.currentVnode that appear to return vnodes actually return positions.

Other features of 4.2:

- Leo is now much more friendly to using spaces instead of tabs. - The Execute Script command reports erroneous lines more clearly. - The usual assortment of bug features and minor features.

Coming soon in 4.2:

- Perfect Import will guarantee that Leo imports file perfectly. - @import will allow you to study files using Leo without changing those files.
@nocolor

- Leo calls g.enableIdleTimeHook at end of startup code. - This means that g.idleTimeHookHandler gets called periodically, even if no hooks have been defined. - g.enableIdleTime hook now calls g.app.gui.setIdleTimeHook at most once.

- app.forceShutdown now calls "end1" hook before calling app.finishQuit. - This ensures that the "end1" hook always gets called once. - app.finishQuit calls doHook("end1",...) only if it hasn't been called before. - This isn't necessary, but it makes traces in doHook less confusing.

- idleTimeHookHandler now calls the idle-time hook for all open windows. - So having multiple windows open should not affect idle-time hooks.

** Warning: new convention required to workaround apparent Tk problems. - "idle" hooks should return if g.app.killed is True.
@color

Added the following hooks:

tag argument keys in keywords (hook name) overrides when called dictionary argument --------- --------- ----------- -------------------

"draw-outline-box" yes start of drawBox tree,p,v,x,y (note 6) "draw-outline-icon" yes start of tree.drawIcon tree,p,v,x,y (note 6) "draw-outline-node" yes start of tree.drawNode tree,p,v,x,y (note 6) "draw-outline-text-box" yes start of tree.drawText tree,p,v,x,y (note 6) "draw-sub-outline" yes start of tree.drawTree tree,p,v,x,y,h,level,hoistFlag (note 6)
Added support for RapidQ, css, shell scripts and PHP.
http://sourceforge.net/forum/message.php?msg_id=2429098 By: nobody

The Leo icon can eliminate the need for the word Leo.

What I did:

- Eliminate Leo in name of Find panel. - Derived leoTkinterPrefs from leoTkinterDialog: creates icon. - Derived leoComparePanel from leoTkinterDialog: creates icon. - Eliminated the -t option when opening Idle: the idle window is now called "Python Shell"
- Added @language html when importing ".htm" and ".html" files. - Added @nocolor when importing ".txt" and ".text" files
When in headline, the Select All command selected the body text.
- idle_body_key must call g.scanDirectives in order to support @tab_width. - This must be done for tabs and newlines.

- Fixed bug in g.scanDirectives that was rejecting negative tabwidth values. - This bug did not exist in the other versions of scanDirectives.

- With a negative tabwidth, a backspace now computes what spaces are equivalent to a tab and delete all of those. This is easy to do!
doc\leoUsersGuide.txt doc\leoFAQ.txt doc\leoLeaps.txt
The old code used at c.tab_width. It should also look for @tabwidth directives.

This was not good when @tabwidth -4 was in effect.
atFile.scanHeader was not handling -encoding fields properly.
# namespace not handled very well.
I inserted "import time", and while I was at it I improved the error checking.
- By default, finishPaste command reassigns all indices in copied nodes. - Created pasteOutlineRetainingClones. - Added reassignIndices arg to pasteOutline, getLeoOutline and finishPaste. - Added << recreate tnodesDict >> in getLeoOutline. - Simplified getTnode slightly: the "if t" code is the same for both kinds of reads.
The code now limits what can be pasted to a maximum of one line or a about 250 characters.
@nocolor

- Leo now uses True and False everywhere instead of true and false.

- All of Leo's code uses spaces instead of tabs for indentation.
- Set removeTrailing to True unless ch is a newline.

This allows Alt-f to work properly.

- Return "break" after the "final" text has been computed if nothing has changed.

This suppresses spurious newlines.

A new idea: Make sure the text _does_ have a newline at all times. I'm not sure this will work...

- ALWAYS set the text in select. This prevents some weird problems with trailing newlines.
- The string passed to exec now includes sentinels.

goToLineNumber needs sentinels to work properly.

- es_exception now gets the error line number from the traceback.

- Added new keyword arguments to goToLineNumber.

- Created goToScriptLineNumber, which just calls goToLineNumber.
Hitting return in middle of a headline didn't work.
Changed getVnode so it checks for v = None after calling getExistingVnode. Creating the node seems to work in this case: I wouldn't bet my life that it works in all cases.
- Added toString to most write methods. - Retained scriptFile option for compatibility with plugins.
This only happened after previous write error.

The fix was to init self.errors in openWriteFile.

The whole atFile logic is pretty gruesome. It's got to be cleaned up.
- Allow indented @all. - Changed to g.is_special - Changed leoColor.doAtKeyword

- Fixed bug in is_special that broke p.isAtAllNode.
There was a small hole in the format of derived files. Leo assumed that comment delimiters do not change within any particular derived file. This assumption is not necessarily true in files like leoProjects.txt.

What I did:

- putDirective and readDirective now check for @langauge and @comment, and change comment delims appropriately.

This is slightly dubious: after all, an @langauge directive in the middle of most derived files will cause havoc. However, one could say that this is the users problem :-)

BTW, this doesn't really solve all problems in @all trees: Leo can still get mightily confused about comment delims if the user doesn't put proper @language directives in @all trees.
readEndNode uses the existing tempBodyString attribute to determine if the body text has changed. If so, we mark the tnode dirty. The code in

top_df.read.<< copy all tempBodyStrings to tnodes >>

propagates the dirty marks to all ancestor @file nodes. This can't be done in readEndNode because no positions are available at that time.
Leo now writes t.unknownAttributes to the .leo file when writing the <v> element corresponding to the root of an @thin tree. Leo will do this by writing a new xml attribute, descendentTnodeUnknownAttributes, in <v> element.

Leo will only write t.unknownAttributes, not v.unknownAttributes. This is because only tnodes have gnx's in thin derived files. In effect, vnodes are anonymous. We could attempt to get around this by identifying vnodes by their corresponding tnodes, but that's not a general solution and it is, in effect, equivalent to writing only t.unknownAttributes. This being so, it seems pointless to "pretend" to be writing v.unknownAttributes.

The effect of this is to make all vnodes identical, as far as using unknownAttributes is concerned. As I've stated in the past, this won't do if, for example, a plugin is trying create an arbitrary directed graph between vnodes. In that case, the plugin should confine itself to @file trees, or just vnodes in .leo files, for that matter.
The problem was setting endSentinelComment to None instead of "" in readDirective.

The code is pretty fragile; it should handle either None or "", but in fact it requires "".
@killcolor
gtkDialogs replaces Tk's file dialogs with Gtk file chooser dialogs.

The plugin is aimed mainly at Linux users with pyGtk installed on their systems, but it should work on on any system that support Gtk2 and pyGtk.

This plugin allows wxPython to be used as leo's gui instead of TK.

It is a prototype under development and so does not have all the features of Tk leo nor are there many plugins compatible with it yet.

It is mainly being developed for Linux at the moment, but attempts are being made to keep it working on Windows as well.

Work on this project has now halted in favor of a gtkLeo plugin.

@nocolor
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|back| |leo| |next|

########################################## Chapter 1: Installing Leo ##########################################

This chapter tells how to install and run_ Leo.

**Important**:

If you have *any* problems installing Leo, please ask for help on Leo's help forum:

.. contents::
Leo will work on any platform that supports Python 2.2.1 or later and Tk 8.4 or later.

- Download the latest version of Leo from `Leo's download page`_.

- Download Python from: http://python.org/

- Most installations of Python have Tk pre-installed. If your doesn't, you may download it from: http://tcl.activestate.com/software/tcltk/

**Warning**: When building Tcl on Linux, do **not** specify "--enable-threads". Only use Tcl with the default "threads not enabled" case.

- Leo uses `Pmw`_ (Python Mega Widgets). Leo's extensions folder contains a copy of Pmw for use if needed. Leo first tries to import Pmw normally. If that fails, Leo will use the version of Pmw in the extensions folder.
Download the latest version of Leo (a .zip file) from `Leo's download page`_.

Unzip the downloaded .zip file into a folder in your home directory. The folder will be called something like leo-4-4-3-final.

You now have two choices:

1. You can run Leo from your home directory. Just add ~/leo-4-4-3-final to your path.

2. You can install leo into /usr/local/lib and /usr/local/bin by running Leo's install script as follows::

cd ~/leo-4-4-3-final chmod u+x install sudo ./install

The install script will instruct you to add /usr/local/bin to your path.

Now you are ready to `run Leo`_.
Leo will open .leo files automatically provided that you associate leo.py with .leo files. Here is how to open Leo when double-clicking a .leo file on Windows 2K or XP:

- In Windows 2K or XP, go to ``Start->Settings->Control panel``, open the ``Folder Options`` tab. - Select the ``file types`` tab. Press the ``New`` button. - Enter ``Leo`` into the ``Create New File Extension`` field. Press OK. - With ``Leo`` still highlighted in the ``Registered File Types`` list box, press the ``Advanced`` button. - Change the default file type field to something like ``Leo Literate Outline``. - Press the ``Icon`` button and browse to the ``LeoDoc`` icon in Leo's ``Icons`` folder. - Click OK. This gets the icons right and registers the description of the .leo file.

You now have to tell windows what to do to open the file properly:

- Press the new button to open the ``New Action`` window. - In the ``Action`` field type ``Open``, then type **one** of the following lines::

[python install dir]\pythonw.exe [leo install dir]\leo.py %1 [python install dir]\python.exe -i [leo install dir]\leo.py %1

**Important**: The -i option is not valid when using pythonw.exe. Any call to pythonw -i will cause pythonw.exe to exit immediately.

The first line opens Leo files with no console window. The second line opens Leo files with a console window and leaves the window open after Leo exits. You should now be able to double click on a leo file in explorer with Leo.
For versions of Leo before 4.0 and for versions of Python before 2.3, Leo will draw a Leo icon in Leo windows only if you have installed Fredrik Lundh's PIL and tkIcon packages.

- Download PIL from http://www.pythonware.com/downloads/index.htm#pil

- Download tkIcon from http://www.effbot.org/downloads/#tkIcon
Leo 4.1 alpha 1 November 3, 2003

*** Alpha quality code: Please make full backups before playing with this code!

This release marks another significant milestone in Leo's history:

- Leo's 4.x file code is complete. At present I have no plans to change the format of .leo files or derived files. I am eating my own dog food: I do all my editing with the 4.1 code base.

- Leo uses immutable gnx's (id:timestamp:n) by default to associate tnodes with vnodes in .leo files. This makes Leo as cvs friendly as possible. From now on .leo files will be checked in to cvs with the -ko (text/keywords off) option.

- The use_gnx setting in leoConfig.txt determines whether uses gnx's (cvs friendly) or ints. No version of Leo before 4.1 can read .leo files containing gnx. Only gnx's are immutable. Leo recomputes all non-gnx indices from scratch whenever writing a .leo file. It is possible to convert between 3.x and 4.1 file formats by changing the use_gnx setting.

- The 4.1 code base has been reorganized to support gui's other than tkinter. Leo's src directory contains several new source files.

- The file test.leo in the test directory contains real regression tests for syntax coloring. Regression testing scripts create regression tests dynamically from data in Leo's outline. Very cool, very easy, very general. In particular, regression tests may use temporary nodes in test.leo rather than creating separate Tk windows for testing.

Known bugs:

- The Extract commands eat one character too much.

- The __wx_gui.py plugin is only partly functional.
Leo 4.0.4 October 29, 2003

- Fixed a problem with the titles in Font and Color panels. - Worked around a Unicode assert failure in the colorizer. - Fixed crasher in OnEndEditHeadline. - Fixed import problems in leoPlugins.leo. - @first and @last sentinels no longer contain corresponding text. This fixes a problem that affected PHP comment delimiters.

Leo 4.0.3 October 25, 2003

- Fixes several problems with the auto_save and plugin menu plugins. - Fixes a problem with the Go To Line Number command.

Note: This version does _not_ support Unicode file names or directory names.

Leo 4.0.2 October 23, 2003

- Fixes a crasher in reportBadChars when a .leo file contains a character that can not be represented in the encoding specified in the first line of the .leo file. - Leo now sends full tracebacks to the log window when Leo takes an unexpected exception. - Leo now issues a more informative message when the @comment directive inhibits the Untangle command.

Leo 4.0.1 October 22, 2003

- Fixes several crashers, one of which may prevent Leo from starting. - Fixes indentation for section references that are preceded by something other than whitespace. - Removes debugging traces when reading and writing unknown attributes. - Removes some improperly cloned nodes from LeoDocs.leo. - Adds the checkTopologyOfAllClones script. - Fixes some problems with plugins.
Leo 4.0 final October 17, 2003

More than a year in the making, Leo 4.0 is finally here.

Highlights of 4.0 final: -----------------------

** Improved and simplified format of derived files. - Eliminated child indices, extraneous blank lines and @body sentinels. - Eliminated @node sentinels that indicate outline structure. - New @nl and @nonl sentinels indicate where newlines are and aren't. - These changes will largely eliminate unwanted cvs conflicts.

** Greatly improved error handling. - Reading derived files _never_ alter outline structure or links. - Read errors leave the outline completely unchanged. - Broken clone links are gone forever. - As a result, 4.0 is much safer than all previous versions.

** Full compatibility will previous versions of Leo. - Leo 4.0 reads all derived files properly, regardless of version. - Leo writes new-format derived files by default, and this default may be changed. - New commands in the read/write menu allow you to explicitly specify the format of derived files.

* New commands: - Write 3.x Derived File and Write 4.x Derived File. - Import Derived File. - Clear Recent Files.

* Dozens of other improvements, including: - Better Unicode support. - New configuration settings. - Several new plugins.

See the notes for the various beta releases for full details.
Leo 4.0 beta 4 October 13, 2003

This is the third public release of Leo 4.0. There are no known serious bugs in this version of Leo. This will be the last beta release before 4.0 final.

Changes made in 4.0 beta 4 --------------------------

- Changed all instances of string.letters to string.ascii_letters. string.letters can cause crashes in some locales (Unicode environments). - Fixed several bugs that caused clone marks not to be set properly.
Leo 4.0 beta 3 October 9, 2003

This is the third public release of Leo 4.0. There are no known serious bugs in this version of Leo.

Highlights of 4.0 beta 3 ------------------------

- Fixed problems with setting Leo's window icons. - Plugins may now save their own information in <v> and <t> elements in .leo files. - The usual assortment of bug fixes and minor improvements.

See the children of this node for full details.
This was a long-standing bug. It's effect was cosmetic, and it was important to fix.
This could happen when the derived file was corrupted.
Leo can now read and write "foreign" attributes in <v> and <t> elements in .leo files:

- When reading a .leo file, Leo will create t.unknownAttributes or v.unknownAttributes ivars for any tnode and vnode object whose corresponding <v> or <t> element in the .leo file contains a foreign attribute.

- The unknownAttributes ivars are a dictionary whose keys are the attribute names and whose values are strings.

- When writing a file, Leo will write "foreign" attributes if a vnode or tnode contains an unknownAttributes ivar.

- The only "native" attributes that Leo expects to find are the "tx" attribute in <t> elements and the "a", "t", "vtag" and "tnodeList" attributes of <v> elements. Everything else is a foreign attribute.

- Leo performs the usual xml escapes on these strings when reading or writing the unknownAttributes ivars.

Plugins may cause Leo to write such foreign attributes simply by attaching unknownAttributes ivars to a vnode or tnode. For example:

v.unknownAttributes = {"vnodeIcon" : pathToIcon}

It would be best not to delete other foreign attributes, so the following would be preferred:

if hasattr(v,"unknownAttributes"): v.unknownAttributes["vnodeIcon"] = pathToIcon else: v.unknownAttributes = {"vnodeIcon" : pathToIcon}

Another way:

try: v.unknownAttributes["vnodeIcon"] = pathToIcon except AttributeError: v.unknownAttributes = {"vnodeIcon" : pathToIcon}
Leo now warns if it can't find either the Icons directory or the LeoApp16.ico icon in that directory.
Leo 4.0 beta 2 October 3, 2003

This is the second public release of Leo 4.0. There are no known serious bugs in this version of Leo. Version 4.0 is the culmination of over a year of collaborative design work and several months of actual implementation.

Highlights of 4.0 beta 2 ------------------------ * Fixed several bugs: - Fixed several problems with reading and writing 4.0 derived files. - Fixed several Unicode-related bugs. - Fixed a crasher in the Go To Line Number command. - Fixed a problem with Importing Python files. * Important improvements: - Added allow_clone_drags setting. N.B. Allows Leo to be used with Aqua. - When running Python 2.3 Leo can now create window icons without third-party packages. - The usual minor improvements and bug fixes.

See the children of this node for full details.

Highlights of 4.0 beta 1 ------------------------ * Improved and simplified format of derived files. * Greatly improved error handling. * Full compatibility will previous versions of Leo.
- Fix undo/redo bug for all commands that change body text in multiple nodes without changing outline structure. - This is a long-standing bug that came to light when trying to make Read @file Nodes undoable.

- Make Read @file Nodes command undoable.

- Fix small bugs in the Go To Line Number command.
The new code prints a warning if Leo's key internal strings are not Unicode.
There were bugs involving saving the "Pattern Match" and "Subroutine Only" find settings.
@nocolor

Class level-code after the method definitions was dropped. For example:

@color

class someclass: def __init__(self): pass

# this code is dropped class_var = None

def some_proc(): pass
The new code ensures that Leo creates and uses only Unicode strings internally.
Fixed Go To Outline command so it doesn't crash on 4.0 files. More work is needed.
Under certain conditions the no sentinels at all were written when writing @rawfile trees.
This is much more natural and less cluttered.
Leo will create the Leo icon in Leo windows automatically when using Python 2.3. The Python Imaging Library and the tkIcon package are only used when using previous versions of Python.
This is the foundation for "foreign" guis.
allow_clone_drags

This is a workaround so that Leo may be used on Aqua. When this setting is zero Leo always moves nodes when dragging. The default is to enable clone-drags.

enable_drag_messages

Allows the user to suppress the message telling whether dragging nodes will move them or clone them. The default is to enable those messages.
After the 4.0 beta 1 release I changed the default so that _new_ format derived files are written if leoConfig.txt does not exist.
leo.py 4.0 beta 1 September 26, 2003

This is the first public release of Leo 4.0. Version 4.0 is the culmination of over a year of collaborative design work and several months of actual implementation.

Please use caution when using this beta version of Leo. It appears very solid and it has been tested by only a few people.

Highlights of 4.0:

** Improved and simplified format of derived files. - Eliminated child indices, extraneous blank lines and @body sentinels. - Eliminated @node sentinels that indicate outline structure. - New @nl and @nonl sentinels indicate where newlines are and aren't. - These changes will largely eliminate unwanted cvs conflicts.

** Greatly improved error handling. - Reading derived files _never_ alter outline structure or links. - Read errors leave the outline completely unchanged. - Broken clone links are gone forever. - As a result, using 4.0 is much safer than all previous versions.

** Full compatibility will previous versions of Leo. - Leo reads all derived files properly, regardless of version. - Leo writes new-format derived files by default, and this default may be changed. - New commands in the read/write menu allow you to explicitly specify the format of derived files.

* New commands: - Write 3.x Derived File. - Write 4.x Derived File. - Import Derived File. - Clear Recent Files.

- Several new plugins. - Several minor bug fixes.

See the children of this node for full details.
The Synchronization Principle simplifies everything and at long last puts Leo on a firm theoretical foundation. This principle states that the "smallest unit of meaning" of any Leo outline is the entire outline itself. In particular, individual derived files have meaning only in the context of a particular outline.

The Synchronization Principle has the following happy consequences:

1. We may assume that all derived files are in synch with the outline that wrote them. This assumption allows Leo to use "hidden machinery" in the outline to associate nodes in the derived file with nodes in the outline. This "hidden" machinery consists of a list of tnodes associated with @file vnodes in the outline. When writing a derived file Leo creates a list of tnodes in the order they were written to the derived file. When reading the derived file, Leo uses this list to associate nodes in the derived file with nodes in the outline.

2. Derived files must get their structure from the .leo file that wrote them. As we have seen, this is done using the hidden machinery in the .leo file. Consequently, there is no further need to represent outline structure in derived files. There is no need any longer either for child indices or for sentinels to represent outline structure. As a result, we can eliminate @+body and @-body nodes entirely because all @+node sentinels are followed by body text.

3. All .leo files must contain full outline structure. Even "thin" outline will contain the full representation of the outline as vnodes.

4. Reading _never_ alters outline structure in the outline. No vnodes are ever created or destroyed and reading never alters clone links. This is true whether or not read errors occur. The read code sets a temporary attribute of tnodes while reading. These attributes are copied to the permanent t.bodyString attribute only if no read errors were encountered.

4. Error recovery is now trivial: Read errors indicate that the .leo files and one or more derived files are out-of-synch. No error recovery is attempted: the @file tree in which the error occurred reverts back to its original state.

5. The new Import Derived File command is the _only_ way to recover data from mismatched derived file.
The write_old_format_derived_files option in leoConfig.leo and leoConfig.txt determines which format of derived file Leo's Write and Save commands write by default. If this option is 0 (recommended) Leo writes 4.x format derived files. Otherwise Leo writes 3.x derived files.

Note that you can use the Write 3.x/4.x Derived Files commands in the File:Read/Write menu to write derived files in an explicitly specified format.
This command deletes all entries in the Recent Files submenu except the most recent file. The files themselves are not affected, just the menu entries.
The Import Derived File command imports all the nodes in a derived file into the outline. Unlike the read commands, no outline structure is preserved. This command can import either 3.x or 4.x derived files.

This command is necessary in version 4.0 because there is no other way to read derived files that are out-of-synch with a .leo file.
The Write 4.x Derived Files command and Write 3.x Derived Files command work just like the Write @file Nodes command, except that they write the indicated format off derived file. In contrast, the Write @file Nodes command writes 3.x format derived files if and only if the write_old_format_derived_files = 1 in leoConfig.txt.

All three of these commands automatically save the outline (the .leo file) if any derived file was actually written. This is necessary so that information in the .leo file always remains in synch with all derived files.
Paul Paterson contributed the following new plugins:

mod_autosave.py

Autosaves the Leo document every so often.

mod_timestamp.py

Timestamps all save operations to show when they occur.

word_export.py

Exports an outline to a word document. Clicking "plugins ... word export ... export" exports the selected outline to Word. Word should be running with an open (empty) document before executing this command.
Leo's read code now warns if any non-empty node is unvisited. This check, and the check that headlines match pretty much guarantees that out-of-synch outlines will generate errors. Thus, there is no need a gnx timestamp in @+leo sentinels!
Version 4.0 is a major advance in Leo's error handling. Using 4.0 is much safer than all previous versions. This new error handling applies to all derived files, both 3.x and 4.x format.

Leo's read code never alters the structure of an outline, regardless of whether read errors are encountered. This means that clone links, marks, and all other information in the outline except body text remains completely unchanged during reads. Broken clone links (the dreaded read errors) are gone forever. Also, the new read code makes no changes to any body text until it is known that no read errors have occurred. This ensures that absolutely no changes at all are made to the outline if there are read errors.

Leo's read code now writes a message to the log pane whenever it sees that the body text in the derived file does not match the body text in the outline. These messages do not indicate errors, only that the body text has been changed outside of Leo, say in an external editor or by cvs.
Added encoding comments to leoGlobals.py and French plugins

This removes a warning new in Python 2.3.
There is no need to recycle Python objects when the last outline window is being closed.
This is too annoying during testing. The Read @file Nodes command will in fact be made undoable for the 4.0 final release.
This has been changed in Python 2.3 and it probably wasn't ever a good idea...
The read code has much simplified using look-behind rather than look-ahead. Both the read and write code write the file line-by-line without recursion.
leo.py 3.12 Final July 17, 2003

Window sizes are now in pixels rather than grid units. You will need to resize existing outlines (.leo files). Don't panic!

Highlights of this version:

* Plugged a huge memory leak. * Fixed a major bug involving undo. * Added Icon & Status areas to Leo window for use by plugins. * Important new plugins: - The file leoPlugins.leo now contains all plugins. - add_directives.py allows plugins to define new directives. - color_markup.py supports wiki-styled markup. - mod_spelling.py checks spelling (requires aspell to be installed). - nav_buttons.py creates browser-style navigation plugins in the icon area. - plugins_menu.py creates a Plugins menu items for all loaded plugins. - scripts_menu.py creates a Scripts menu for all scripts in scripts folder. - spell - trace_gc traces all changes to memory at idle time. * Other enhancements: - Redesigned the Find panel. Non-functional options are dimmed. - Added @wrap and @nowrap directives. - Added Write Dirty @file Nodes command. - Added several new "stub hooks". - Hyperlinks are now enabled by default. - Leo now loads plugins in alphabetical order. - Leo now remembers the size and location of Leo windows. - Undo now restores the insert point or the selection range after most commands. - Added apply button to Font panel. - Improved the reporting of characters that do not exist in the present encoding. * The usual assortment of bug fixes and minor improvements. - There are no known bugs in this version of Leo.

See the children of this node for full details.
Undoing the following commands could corrupt outlines:

Convert All Blanks, Convert All Tabs, Extract, Extract Names, Extract Section.
v.nodeAfterTree was being called way too often when handling read errors.
- Leo wasn't properly recycling Tk widgets when redrawing the outline pane. This was a _huge_ leak.

- Leo now recycles all objects used by a window when that window closes.

The app.destroyAllWindowObjects() routine calls o.__dict__.clear for all objects o in a window.

- Leo now longer needs destroy() methods in each major class.
c:\prog\leoCVS\leo\src\leoNodes.py:1174: Parameter (encoding) not used

This may have been the cause of some "unicode" problems.
c:\prog\leoCVS\leo\src\leoFrame.py:976: No global (a) found

This may have been the cause of some problems with the log panel.
Leo didn't properly import .cxx files or files with upper case extensions.
The messages "reading: @file x" were not always showing up during Open commands.
Symptom: Sometimes the "reading" messages would not appear when reading an outline.

Cause: Several event handlers are called at unpredictable times during the load process. These may try to reset the log.

Solution: - create app.setLog, app.lockLog and app.unlocklog methods. - call app.lockLog before opening an outline.
The body_pane_wraps setting is now handled properly.
The body keystroke handler wasn't handling the delete character properly.
Methods with the same name confused this command.

The Go To Line Number command will be rewritten for 4.0.
The following was improperly indented in @nosentinel files. The expansion of << class shape declarations >> was indented twice.

class shape(object): << class shape declarations >> # after decls
- Added code to check for errors in the table passed to createOpenWithMenuFromTable.

- Revised code that checks to see whether a temp file has already been created. The old code didn't properly take into account of file extensions when checking for already opened temp files.
Leo now converts all tabs to blanks as you type, not just leading blanks.
- Moved the code into the app class.
This was due to a recent change in getTextSelection.
- Several parts of the code looped on lists that were altered in the loop. - Fixed several bugs in the code that handled shortcuts to Open With menu items.
- Leo's various sort commands did not work properly if two headlines were identical.

- Eliminated the unnecessary and buggy sortSequence routine.
Recent changes interfered with dragging nodes.
Here are the results from running checkClones2Links script on this file:

multipleTargetsInDerivedFiles: 8

(fixed) class nodeIndices (improperly duplicated in leoAtFile.py) (fixed) frame.OpenWithFileName (improperly duplicated in Recent Files submenu) (fixed) recentButtonCallback (improperly duplicated in Mark/Goto submenu)

-- Used several times in same derived file. Will this be valid in LeoN?

<< Append any unused text to the parent's body text >> (used several times in leoImport.py) << Check both parts for @ comment conventions >> (used several times in leoTangle.py) << Compare single characters >> (used several times in leoTangle.py) << Set the default directory >> (used several times in leoAtFile.py)

-- Used (properly) in two different derived files:

replacePatterns (used on purpose in setup.py and postSetup.py)

clonedAtFileNodes: 9

@file ../plugins/add_directives.py @file ../plugins/french_fm.py @file ../plugins/open_with.py @file ../plugins/vim.py @file ../plugins/xemacs.py @file c:\prog\test\multiple.txt @file-nosent nosentCloneTest.txt @silentfile ../doc/PKG-INFO.TXT @silentfile ../doc/README.TXT
Fractions cause problems in some locales. The height/width params weren't used anyway!
- createTopologyList creates a list containing a description of a tree. Used by several of the new scripts.

- importFromPath encapsulates a lot of details of custom importing, and makes it unnecessary to alter sys.path.

- funcToMethod allows users to add methods to any class. Such methods immediately become available to all objects, including existing objects!

- Added do-nothing flush method to redirect class. This routine was added to support LeoN.
- The checkForPossiblyBrokenLinks script does just what it says.

- The checkClones2Links script warns if nodes are used by several derived files.
The new code uses a common base class for all dialogs.
- The new code uses proper Python lists to represent join lists. This greatly clarifies the relevant sections of code, and may even provide a performance boost.

- tnodes now contain both headline and body text. This change creates an important invariant: vnodes with the same vnx's always point to tnodes with the same tnx's. This invariant is vital to resolving conflicts properly.

- rewrote joinList code and move joinLists to tnodes.
- There is now only a single entry point into Leo: the run() routine.

This routine uses an optional fileName arg.

- Created runMainLoop function in leo.py so the call to mainloop() is in a separate function.

This routine was added to support LeoN.
The body_pane_wraps setting is used if neither of these directives is in effect.
This make the Font panel a bit less intimidating to use.
- Added an "icon area" at the top of each Leo frame. Plugins may add buttons to the Icon area at the top of each Leo frame. See the nav_buttons.py plugin for an example of how to use this area.

- Added a "status area" at the bottom of each Leo frame. This area reports the line and column number of the cursor. Plugins may send status messages to this this area.

- Added convenience routines for the icon and status areas to the LeoFrame class. Plugins may use these convenience routines to create, update, manage and destroy fields in the icon and status areas.
These aren't quite ready for prime time.
Hypertext links now enabled by default. Control-click any section reference to go to its definition. I changed the colorer so that it does _not_ underline active hyperlinks in section reference. If a section reference is underlined, it means the definition does _not_ exist. Otherwise the section reference _does_ exist and control-clicking the reference takes you to the defining node in one of its descendants.
The new code is substantially more robust than the old.
Leo was not honoring the requested size of Leo windows.

As the result of this change Leo will open old .leo files much smaller than expected. Do not panic! Simply resize the Leo window and save it. The next time you open the window all will be well.
I have found this command to be highly annoying and unwanted.
This is very important for the spell-checking plugin, and is quite useful in all other situations.
- Added the following stub hooks:

"after-create-leo-frame" "close-frame" "create-optional-menus" "destroy-all-global-windows" "init-color-markup" "new" "redraw-entire-outline" "scan-directives"

See the section called "About hooks" for full details.

- Changed handleLeoHook to doHook. This simplifies the code a bit.
@nowrap

At startup time Leo looks all files of the form mod_*.py in the plugins directory. Leo assumes that these files are "plugins" containing Python modules that customizes Leo's operation. Leo attempts to import each file.

Each module should register routines that are called at various times during execution. Such times are identified by strings known as "tags". The code in in one or more plugins corresponding to each tag are known as the "hook" routines for that tag. Leo catches exceptions (including syntax errors) in hook routines, so it is safe to hack away on this code.

Leo passes two argument to all hook routines: the tag and a keywords dictionary containing additional information. For example, keywords["label"] indicates the kind of command for "command1" and "command2" hooks.

For some hooks, returning anything other than None "overrides" Leo's default action. Hooks have full access to all of Leo's source code. Just import the relevant file. For example, top() returns the commander for the topmost Leo window.

The following table summarizes the arguments passed to hooks: ( Overrides is "yes" if returning anything other than None overrides Leo's normal command or event processing.)

tag argument keys in keywords (hook name) overrides when called dictionary argument --------- --------- ----------- ------------------- "bodyclick1" yes before normal click in body c,v,event "bodyclick2" after normal click in body c,v,event "bodydclick1" yes before double click in body c,v,event "bodydclick2" after double click in body c,v,event "bodykey1" yes before body keystrokes c,v,ch,oldSel,undoType "bodykey2" after body keystrokes c,v,ch,oldSel,undoType "bodyrclick1" yes before right click in body c,v,event "bodyrclick2" after right click in body c,v,event "boxclick1" yes before click in +- box c,v,event "boxclick2" after click in +- box c,v,event "command1" yes before each command c,v,label (note 2) "command2" after each command c,v,label (note 2) "drag1" yes before start of drag c,v,event "drag2" after start of drag c,v,event "dragging1" yes before continuing to drag c,v,event "dragging2" after continuing to drag c,v,event "end1" start of app.quit() "enddrag1" yes before end of drag c,v,event "enddrag2" after end of drag c,v,event "headclick1" yes before normal click in headline c,v,event "headclick2" after normal click in headline c,v,event "headrclick1" yes before right click in headline c,v,event "headrclick2" after right click in headline c,v,event "headkey1" yes before headline keystrokes c,v,ch "headkey2" after headline keystrokes c,v,ch "hypercclick1" yes before control click in hyperlink c,v,event "hypercclick2" after control click in hyperlink c,v,event "hyperenter1" yes before entering hyperlink c,v,event "hyperenter2" after entering hyperlink c,v,event "hyperleave1" yes before leaving hyperlink c,v,event "hyperleave2" after leaving hyperlink c,v,event "iconclick1" yes before single click in icon box c,v,event "iconclick2" after single click in icon box c,v,event "iconrclick1" yes before right click in icon box c,v,event "iconrclick2" after right click in icon box c,v,event "icondclick1" yes before double click in icon box c,v,event "icondclick2" after double click in icon box c,v,event "idle" periodically (at idle time) c,v "menu1" yes before creating menus c,v (note 3) "menu2" yes before updating menus c,v "open1" yes before opening any file old_c,new_c,fileName (note 4) "open2" after opening any file old_c,new_c,fileName (note 4) "openwith1" yes before Open With command c,v,openType,arg,ext "openwith2" after Open With command c,v,openType,arg,ext "recentfiles1" yes before Recent Files command c,v,fileName,closeFlag "recentfiles2" after Recent Files command c,v,fileName,closeFlag "save1" yes before any Save command c,v,fileName "save2" after any Save command c,v,fileName "select1" yes before selecting a vnode c,new_v,new_v "select2" after selecting a vnode c,new_v,old_v "select3" after selecting a vnode c,new_v,old_v "set-mark" no when a mark is set c,v (new) "start1" no after app.finishCreate() "start2" after opening first Leo window c,v,fileName "unselect1" yes before unselecting a vnode c,new_v,old_v "unselect2" after unselecting a vnode c,old_v,old_v "@url1" yes before double-click @url node c,v (note 5) "@url2" after double-click @url node c,v (note 5)

Notes:

(1) "activate" and "deactivate" hooks: These have been removed because they do not work as expected.

(2) "commands" hooks: The label entry in the keywords dict contains the "canonicalized" form of the command, that is, the lowercase name of the command with all non-alphabetic characters removed.

Commands hooks now set the label for undo and redo commands "undo" and "redo" rather than "cantundo" and "cantredo".

(3) "menu1" hook: Setting app().realMenuNameDict in this hook is an easy way of translating menu names to other languages. Note: the "new" names created this way affect only the actual spelling of the menu items, they do _not_ affect how you specify shortcuts in leoConfig.txt, nor do they affect the "official" command names passed in app().commandName. For example, suppose you set app().realMenuNameDict["Open..."] = "Ouvre".

(4) "open1" and "open2" hooks: These are called with a keywords dict containing the following entries:

old_c: The commander of the previously open window. new_c: The commander of the newly opened window. fileName: The name of the file being opened.

You can use old_c.currentVnode() and new_c.currentVnode() to get the current vnode in the old and new windows.

Leo calls the "open1" and "open2" hooks only if the file is already open. Leo will also call the "open1" and "open2" hooks if: a) a file is opened using the Recent Files menu and b) the file is not already open.

(5) "@url1" and "@url2" hooks are only executed if "icondclick1" hook returns None.

New in version 3.12:

The following hooks are a new breed of hook, called "stub hooks". Conceptually, these hooks are like calls to stub routines that can be filled in by code in plugins.

tag argument keys in keywords (hook name) overrides when called dictionary argument --------- --------- ----------- ------------------- "after-create-leo-frame" no before calling f.finishCreate c "after-redraw-outline" no end of tree.redraw c (note 6) "before-create-leo-frame" no after calling f.finishCreate c "clear-mark" no when mark is set c,v "close-frame" no in app.closeLeoWindow c "color-optional-markup" yes * (note 7) colorer,v (note 7) "create-optional-menus" no (note 8) (note 8) "create-popup-menu-items" no in tree.OnPopup c,v,event (new) "destroy-all-global-windows" no (note 12) None "draw-outline-box" yes start of drawBox tree,p,v,x,y (note 6) "draw-outline-icon" yes start of tree.drawIcon tree,p,v,x,y (note 6) "draw-outline-node" yes start of tree.drawNode tree,p,v,x,y (note 6) "draw-outline-text-box" yes start of tree.drawText tree,p,v,x,y (note 6) "draw-sub-outline" yes start of tree.drawTree tree,p,v,x,y,h,level (note 6) "enable-popup-menu-items" no in tree.OnPopup c,v,event (new) "init-color-markup" no (note 7) colorer,v,s,i,j,colortag (note 7) "new" no start of New command old_c,new_c (note 9) "redraw-entire-outline" yes start of tree.redraw c (note 6) "scan-directives" no in scanDirectives c,v,s,old_dict,dict,pluginsList (note 10) "set-mark" no when mark is set c,v "show-popup-menu" no in tree.OnPopup c,v,event

Notes:

(6) These hooks are useful for testing.

(7) These stub hooks allow plugins to parse and handle markup withing doc parts, comments and Python """ strings. Note that these hooks are _not_ called in Python ''' strings. See the color_markup plugin for a complete example of how to use these hooks.

(8) The "create-optional-menus" stub hook is called when Leo is creating menus, at the place at which creating new menus is appropriate. Therefore, this hook need only create new menus in the correct order, without worrying about the placement of the menus in the menu bar. See the plugins_menu and scripts_menu plugins for examples of how to use this hook. Leo now executes hooks in alphabetical order, so that the Plugins menu will be created before the Scripts menu.

(9) The "new" stub hook is called at the beginning of the code that implements the New command. This provides a much easier way of recognizing when Leo is about to create a new Leo window.

(10) The "scan-directives" stub hooks is called inside the scanDirectives global function. The dictionary returned by scanDirectives now contains an item whose key is "pluginsList". The value of this item is a list of tuples (d,v,s,k) where:

- d is the spelling of the @directive, without the leading @. - v is the vnode containing the directive, _not_ the original vnode. - s[k:] is a string containing whatever follows the @directive. k has already been moved past any whitespace that follows the @directive.

See the add_directives plugins directive for a complete example of how to use the "scan-directives" stub hook.

(11) The "close-frame" stub hook is called in app.closeLeoWindow just before removing the window from app.windowList. The hook code may remove the window from app.windowList to prevent app.closeLeoWindow from destroying the window.

(12) Leo calls the "destroy-all-global-windows" hook in app.destroyAllGlobalWindows(). This hook gives plugins the chance to clean up after themselves when Leo shuts down.
Leo now supports two new stub hooks: "clear-mark" and "set-mark". Both fully update the marks window, so it is important that they not be called "too often", and they aren't.

As a side effect, it is no longer necessary to update the marks window after every command that affects marks, a nice simplification and generalization of the code.

While I was at it, I moved the two dialog classes used only by the nav_buttons plugin out of leoDialog.py and into nav_buttons.py where they belong.
Added the "create-popup-menu", "enable-popup-menu-items" and "show-popup-menu" hooks.
Added the "create-popup-menu", "enable-popup-menu-items" and "show-popup-menu" hooks.
This plugin allows users to create new directives.

As an example, this plugin creates a new @markup wiki directive.
This plugin supports coloring for markup in doc parts and Python triple-double-quoted strings.

At present, this plugin supports wiki-style markup, and it would be easy to change the style of markup.
This plugin adds 4 new buttons to the icon area at the top of each Leo window:

- Back and Forward arrows that work like a typical web browser. Clicking the back arrow button takes you to the last node in the tree you visited. Clicking the forward arrow button moves you forward. The forward arrow button is dimmed unless you have clicked the back arrow button recently.

- The Recent button opens a non-modal dialog showing all the nodes you have visited recently. This dialog is updated cleanly by the tree.select method. You will see this entries change dynamically. There are buttons in this dialog for clearing individual entries or clearing all entries. Double-clicking any entry in this dialog takes you to that node, as does clicking the Go button.

The entries in the Recent Nodes pane do _not_ correspond to the order implied by the Forward and Back arrows. Rather, the most recently visited node is on top, followed by the next most recently visited node, and so on, with the additional feature that nodes appear only once in the list.

- The Marks button opens a non-modal dialog showing all marked nodes in the tree. Marking or unmarking nodes in the tree adds or deletes entries from this dialog. Double-clicking any entry in this dialog takes you to that node, as does clicking the Go button.
This creates a plugins menu describing each loaded plugin.
The scripts_menu.py plugin creates a Scripts menu for all scripts in scripts folder.
- Leo now scans all .py files in the plugins folder when looking for plugins.

Filenames need not start with mod_, and Leo scans only the plugins folder.

- Leo loads plugins in alphabetical order.

- Leo now prints only a brief summary of the number of files loaded & examined to the log file.
1. Created config, doc, examples, plugins, scripts, src, test & tools folders.

2. Removed the following files:

- nsi.leo file. This was a duplicate of code in LeoPy.leo. - bdist.bat, go.bat, help.bat, sdist.bat. - leo.rc and leo.res. These were resource files used by the Delphi classes.
These were written by Frank Merenda.
leo.py 3.11.1 May 1, 2003

This version fixes two bugs:

- Version 3.11 had startup problems on some Linux systems.

- Creating clones by control dragging did not always work. This bug has existed in Leo for a long time.
leo.py requires Python 2.1 or above and tcl/tk 8.3 or above. leo.py will work on Linux, Windows and MacOs X Jaguar.

leo.py 3.11.1 May 1, 2003

This version fixes the following bugs:

- Leo would crash on startup on some Linux systems due to a problem with Leo's local copy of getpreferredencoding.

- Leo sometimes did not set clone bits properly after creating a clone by control-dragging a node. This bug has existed for about 6 months!

leo.py 3.11 April 27, 2003

This version of Leo contains many important improvements since 3.10, especially support for unicode and a new plugin architecture.

The Highlights of 3.11:

** Leo supports unicode. - New @encoding directives specifies encoding for derived files. - New settings specify default encodings for .leo and derived files. - Derived files specify encodings used to create them. ** A new plugin architecture for customizing Leo. (A major improvement.) - New commands: - Toggle Angle Brackets. - Insert Time/Date (in headline or body text). - Go To First/Last Node, Parent, Next/Previous Sibling. - Write Missing @file Nodes. - Expand/Contract Node. - Improved commands: - Fixed a huge performance bug that slowed moving nodes left. - Expand/Contract commands now operate on the selected tree. ( A major improvement) - Sort Siblings command can now sort top-level nodes. - Leo now allows multiple writes of cloned nodes. (Useful when different @path directives are in effect.) - Other improvements: - New @lineending directive specifies line endings. - Improved syntax coloring for html and xml. - Leo scrolls partially visible headlines into full view. - Added "Replace tabs with spaces" checkbox in Prefs panel. - New settings in leoConfig.leo/.txt. - Added "tk_encoding" setting and related logic. - Colors for Show Invisibles command and body_insertion_cursor - Settings affecting when control-drags start. - Defaults for unicode (see above). - Many other bug fixes and improvements.

See the children of this node for full details.
This ensures that the outline is redrawn properly after the Read @file Nodes command.
Browsing the comp.lang.python yesterday I found that there are serious problems with Python's getdefaultlocale() routine. Martin v. Löwis says "getdefaultlocale() is broken, and cannot be fixed", though he does suggest the following workaround:

leoGlobals.py uses locale.getpreferredencoding to define getpreferredencoding if locale.getpreferredencoding exists (it is new in Python 2.3alpha). Otherwise, Leo uses the code copied from the 2.3a2 version of Python to define getpreferredencoding. Either way, leoGlobals.py now defines getpreferredencoding and Leo uses getpreferredencoding rather than getdefaultlocale.
After opening the Python window the call to tkFont() threw a (caught) exception on every call to frame.setTabWidth. The fix was to add the optional root param.
skip_long was throwing an exception if there were no valid digits following a + or - sign.
- tangle.scanAllDirectives was not setting self.encoding when handling @encoding. - tangle.scanAllDirectives wasn't scanning the @encoding line properly. - fixed crashers in Tangle and Untangle logic.
Fixed bug in handleLinesFollowingSentinel: c:\prog\LeoCVS\leo\leoAtFile.py:482: No global (i) found Removed i arg from rfind.

Fixed bug in definition of BadLeoFile: c:\prog\LeoCVS\leo\leoFileCommands.py:27: Base class (exceptions.Exception) __init__() not called Added call to Exception.__init__(self,message)

Fixed bug in askYesNoCancel c:\prog\LeoCVS\leo\leoDialog.py:283: Variable (no) used before being set. Disabled defaultButton logic. New code would have to be thoroughly tested.

Removing unused routine: setDefaultLoc. c:\prog\LeoCVS\leo\leoNodes.py:2581: No class attribute (defaultLoc) found

Fixed bug in put: changed a to app() c:\prog\leoCvs\leo\leoFrame.py:4973: No global (a) found
I had completely misunderstood __del__ methods! __del__ methods disable the gc's ability to collect circular garbage (!!) and so __del__ methods will _never_ be called (!!)

BTW, when deleting an entire Leo window Leo calls various destroy methods to unlink items. This allows the garbage collector to collect all data structures. Because of unlimited undo only these destroy methods have the potential for creating "real" garbage.
This adds http:\\ to url's if needed.
New in version 3.11. The @lineending directive allows you to specify the line endings for individual derived files. This directive will override the output_newline setting in leoConfig.txt. Note that @lineending _never_ affects the line endings in .leo files themselves: we must have consistent line endings in .leo files! See below for more details.

The valid forms of the new @lineending directive are:

@lineending nl (the default, Linux) @lineending cr (Mac) @lineending crlf (Windows) @lineending lf (same as nl, not recommended) @lineending platform (same as platform value for output_newline setting in leoConfig.txt)
This will have no effect until version 4.0.
Leo now uses unicode internally for most strings. This solves a lot of problems. The children of this node discuss all the details...
This fixes several bugs.
In particular, the locale returned by locale.getdefaultlocale()[1] need not be a valid unicode encoding.
Leo now uses unicode internally for most strings. The highlights:

1. Leo converts headline and body text to unicode when reading .leo files and derived files. Both .leo files and derived files may specify their encoding, with "utf-8" being used by default. If the encoding used in a derived file is not "utf-8" it is represented in the @+leo sentinel line. For example:

#@+leo-encoding=iso-8859-1.

The "utf-8" encoding is a "lossless" encoding (it can represent all unicode code points), so encoding and decoding to and from utf-8 plain strings will never cause a problem. When reading or writing a character not in a "lossy" encoding, Leo converts such characters to '?' and issues a warning.

2. When writing .leo files and derived files Leo uses the same encoding used to read the file, again with "utf-8" used as a default.

3. leoConfig.py contains two settings used to specify the default encoding used for .leo and derived files:

default_derived_file_encoding = UTF-8 new_leo_file_encoding = UTF-8

I do not recommend changing new_leo_file_encoding (see the comments in leoConfig.leo) and you may set default_derived_file_encoding to anything that makes sense for you.

4. You may use the @encoding directive to specify the encoding used in a derived file. You can't mix encodings in a single derived file.

This is all should need to know to use extended character sets on Leo.
leoConfig.py now contains two new settings, with the defaults shown below:

default_derived_file_encoding = UTF-8 new_leo_file_encoding = UTF-8

These control the default encodings used when writing derived files and .leo files.

I do not recommend changing new_leo_file_encoding (see the comments in leoConfig.leo)

You may set default_derived_file_encoding to anything that makes sense for you.
The following paragraphs discuss code-level details. You should not need to read this section in order to use Leo.

1. Leo uses unicode objects in vnodes and tnodes to denote headline and body text. Note that unicode strings have no encoding; only plain strings have encodings. This means that once an (encoded) plain string has been converted to a unicode string it doesn't matter how the unicode string was created. This is the key that makes Leo's new code robust.

So internally Leo never has to worry about encodings. The only times encoding matter is when encoded strings are converted to and from unicode when Leo reads or writes files (or when the passing strings to and from Tk.Text widgets, but the idea is the same).

2. Python expressions that mix unicode strings u and plain strings s, like:

u + s or u == s or u[5] == s[2:]

are promoted to unicode objects using the "system encoding". This encoding should never be changed, but we can't assume that we know what it is, so for safety we should assume the most restrictive encoding, namely "ascii". With this assumption, Leo's code can't throw an exception during these promotions provided that:

- All strings are converted to unicode when Leo reads files or gets text from Tk.Text widgets. - All string literals in Leo's code have only ascii characters.
It is now much easier to customize Leo. The new scheme is based on plugins (files in the plugins directory) rather than modifying customizeLeo.py. Many thanks to Paul Paterson for suggesting this scheme and for doing the first implementation.
@nocolor

New in 3.11. Leo now looks in the plugins folder for files whose name matches mod_*.py. Leo tries to import all such files at startup ("start2") time.

The child of this node gives an example of the code that creates the Open With menu. The following code, appearing at the end of mod_open_with.py, registers two different hook functions. The on_idle function is the "idle" hook. The create_open_with_menu is the "start2","open2" and "command2" hooks. @color

if 1: # Register the handlers... registerHandler("idle", on_idle) registerHandler(("start2","open2","command2"), create_open_with_menu) es("...open with")

@nocolor Plugins may call registerHandler with a hook name like "idle" or a list of hook names like ("start2","open2","command2"). Also, you can use the "all" hook name to indicate that code will be called for all hooks. This is useful for tracing hooks. Plugins may also call registerExclusiveHandler for hooks that should not be redefined in other plugins.

mod_open_with.py also contains the on_idle and create_open_with functions that actually handle the hook. Such functions have two arguments: tag and keywords. You will find many examples of this in LeoPy.leo.

About distribution:

1. LeoPy.leo now contains all the plugins in @ignore'd @file nodes. This way Leo won't complain when you open LeoPy.leo.

2. Most plugins actually are disabled: the code that registers the hooks is contained in #if 0: blocks. So to create a plugin you have to remove the @ignore and you have to change #if 0: to #if 1.

3. Most mod_*.py will never be part of Leo distributions, and the single-click installer will create an plugins folder containing just mod_open_with.py.

4. There is no longer a need for a customizeLeo.py file.

About error checking:

At present Leo will disable all hooks if any hook throws an exception. In practice this isn't a big deal, but obviously something better could be done. I won't do anything until after 3.11b1 goes out.

How to send me your plugins:

It should now be _much_ easier to submit a plugin for inclusion in LeoPy.leo. Just send me a .leo file containing @file mod_your_plugin.py. Please have this @file node be @ignored: this is more convenient for me. Ideally, your .leo file should contain _only_ your plugin code.
Simplified and regularized hooks:

- replaced "event1" and "event2" hooks with 'regular' hooks. * Much easier to understand. - added "iconrclick" hooks. - added "bodyrclick" hooks. - added "save1" and "save2" hooks - added "dragging" hooks. * These are called when drag hook called while already dragging. - added "hyperenter" and "hyperleave" hooks. * These only fire if use_hyperlinks = 1 in leoConfig.txt. - removed "activate" and "deactivate" hooks. * These were not reliable. - almost all hooks now have c,v arguments. - "command" hooks now return "undo" and "redo" rather than "cantundo" and "cantredo"

Improved code:

- improved the tracing of hooks. - the tracing code also checks to make sure that most hooks have c,v keywords. - created es_event_exception(). - put all event handlers in try/except blocks that call es_event_exception on errors.
At startup time Leo looks all files of the form mod_*.py in the plugins directory. Leo assumes that these files are "plugins" containing Python modules that customizes Leo's operation. Leo attempts to import each file.

Each module should register routines that are called at various times during execution. Such times are identified by strings known as "tags". The code in in one or more plugins corresponding to each tag are known as the "hook" routines for that tag. Leo catches exceptions (including syntax errors) in hook routines, so it is safe to hack away on this code.

Leo passes two argument to all hook routines: the tag and a keywords dictionary containing additional information. For example, keywords["label"] indicates the kind of command for "command1" and "command2" hooks.

For some hooks, returning anything other than None "overrides" Leo's default action. Hooks have full access to all of Leo's source code. Just import the relevant file. For example, top() returns the commander for the topmost Leo window.

The following table summarizes the arguments passed to hooks: ( Overrides is "yes" if returning anything other than None overrides Leo's normal command or event processing.)

tag argument keys in keywords (hook name) overrides when called dictionary argument --------- --------- ----------- ------------------- "bodyclick1" yes before normal click in body c,v,event (new) "bodyclick2" after normal click in body c,v,event (new) "bodydclick1" yes before double click in body c,v,event (new) "bodydclick2" after double click in body c,v,event (new) "bodykey1" yes before body keystrokes c,v,ch,oldSel,undoType "bodykey2" after body keystrokes c,v,ch,oldSel,undoType "bodyrclick1" yes before right click in body c,v,event (new) "bodyrclick2" after right click in body c,v,event (new) "boxclick1" yes before click in +- box c,v,event (new) "boxclick2" after click in +- box c,v,event (new) "command1" yes before each command c,v,label (note 2) "command2" after each command c,v,label (note 2) "drag1" yes before start of drag c,v,event (new) "drag2" after start of drag c,v,event (new) "dragging1" yes before continuing to drag c,v,event (new) "dragging2" after continuing to drag c,v,event (new) "end1" start of app.quit() "enddrag1" yes before end of drag c,v,event (new) "enddrag2" after end of drag c,v,event (new) "headclick1" yes before normal click in headline c,v,event (new) "headclick2" after normal click in headline c,v,event (new) "headrclick1" yes before right click in headline c,v,event (new) "headrclick2" after right click in headline c,v,event (new) "headkey1" yes before headline keystrokes c,v,ch "headkey2" after headline keystrokes c,v,ch "hypercclick1" yes before control click in hyperlink c,v,event (new) "hypercclick2" after control click in hyperlink c,v,event (new) "hyperenter1" yes before entering hyperlink c,v,event (new) "hyperenter2" after entering hyperlink c,v,event (new) "hyperleave1" yes before leaving hyperlink c,v,event (new) "hyperleave2" after leaving hyperlink c,v,event (new) "iconclick1" yes before single click in icon box c,v,event (new) "iconclick2" after single click in icon box c,v,event (new) "iconrclick1" yes before right click in icon box c,v,event (new) "iconrclick2" after right click in icon box c,v,event (new) "icondclick1" yes before double click in icon box c,v,event (new) "icondclick2" after double click in icon box c,v,event (new) "idle" periodically (at idle time) c,v "menu1" yes before creating menus c,v (note 3) "menu2" yes before updating menus c,v "open1" yes before opening any file old_c,new_c,fileName (note 4) "open2" after opening any file old_c,new_c,fileName (note 4) "openwith1" yes before Open With command c,v,openType,arg,ext "openwith2" after Open With command c,v,openType,arg,ext "recentfiles1" yes before Recent Files command c,v,fileName,closeFlag "recentfiles2" after Recent Files command c,v,fileName,closeFlag "save1" yes before any Save command c,v,fileName "save2" after any Save command c,v,fileName "select1" yes before selecting a vnode c,new_v,new_v "select2" after selecting a vnode c,new_v,old_v "start1" no after app.finishCreate() "start2" after opening first Leo window c,v,fileName "unselect1" yes before unselecting a vnode c,new_v,old_v (new) "unselect2" after unselecting a vnode c,old_v,old_v (new) "@url1" yes before double-click @url node c,v (note 5) "@url2" after double-click @url node c,v (note 5)

Notes:

(1) "activate" and "deactivate" hooks: These have been removed because they do not work as expected.

(2) "commands" hooks: The label entry in the keywords dict contains the "canonicalized" form of the command, that is, the lowercase name of the command with all non-alphabetic characters removed.

Commands hooks now set the label for undo and redo commands "undo" and "redo" rather than "cantundo" and "cantredo".

(3) "menu1" hook: Setting app().realMenuNameDict in this hook is an easy way of translating menu names to other languages. Note: the "new" names created this way affect only the actual spelling of the menu items, they do _not_ affect how you specify shortcuts in leoConfig.txt, nor do they affect the "official" command names passed in app().commandName. For example, suppose you set app().realMenuNameDict["Open..."] = "Ouvre".

(4) "open1" and "open2" hooks: These are called with a keywords dict containing the following entries:

old_c: The commander of the previously open window. new_c: The commander of the newly opened window. fileName: The name of the file being opened.

You can use old_c.currentVnode() and new_c.currentVnode() to get the current vnode in the old and new windows.

Leo calls the "open1" and "open2" hooks only if the file is already open. Leo will also call the "open1" and "open2" hooks if: a) a file is opened using the Recent Files menu and b) the file is not already open.

(5) "@url1" and "@url2" hooks are only executed if "icondclick1" hook returns None.
See the Code:Customizing Leo:Plugins folder in LeoPy.leo for full details of all plugins.

- Added disabled support for @folder.

- Demoted up/down arrow stuff to a disabled plugin for now.
The idle-time hook now checks for dirty @file nodes that have been modified in an external editor since the last check. An alert is raised when such conflicting changes are found.

Improved sanitize_filename utility (in leoGlobals.py) so that it converts all characters used to denote filenames to underscores.
This allows output from registering hooks to appear in the log pane.
The following new plugins are now in LeoPy.leo.

- mod_script_io_to_body.py Redirect output from scripts to end of body pane.

- mod_vim.py Adds support for VIM editor.

- mod_french_fm.py Full translation of all Leo's menus into French.
Added support for the following options:

show_invisibles_space_background_color show_invisibles_tab_background_color
This option controls when the control key is considered to start a control-drag.

If look_for_control_drag_on_mouse_down = 1 the the control key must be down when dragging starts. Otherwise, the control key must be down when dragging ends.
This allows Leo to be used with a black background.
Two new settings in leoConfig.leo/.txt specify the format of the time/date strings inserted by the Insert Body Time/Date and Insert Headline Time/Date commands:

body_time_format_string headline_time_format_string

These settings are really the format string passed to time.strftime(format).

See http://www.python.org/doc/current/lib/module-time.html for a complete list of the format options. The "%m/%d/%Y %H:%M:%S" format is used by default, resulting in a time/date format such as: 1/30/2003 8:31:55

- if the headline is bracketed (named) then the << >> are removed. - if the headline is not bracketed (unnamed) then the << >> are inserted.
The Insert Body Time/Date and Insert Headline Time/Date commands are in the Edit Body and Edit Headline menus respectively. They insert the formatted time & date into the body or headline text. You must be editing a headline to be able to insert the time/date into the headline. If you aren't Leo will say: "Edit headline to append date/time"

Two new settings in leoConfig.leo/.txt specify the time/date format:

body_time_format_string headline_time_format_string

These settings are really the format string passed to time.strftime(format).

See http://www.python.org/doc/current/lib/module-time.html for a complete list of the format options. The "%m/%d/%Y %H:%M:%S" format is used by default, resulting in a time/date format such as: 1/30/2003 8:31:55
These commands select the first or last node of an outline and make that node visible.
This command selects the parent of the previously selected node and makes that node visible.
These commands select the previous or following sibling of a node and make the newly selected node visible.
This command writes any files (in the presently selected outline) that do not exist.
This allows time to be expressed as local time or gmttime.
The Expand To Level n commands now expand only the nodes in the presently selected outline. This makes these commands much more useful.

With these changes there is no longer any need for the Expand Subheads command.
This can be useful when clones are in the range of different @path directives.
1. Leo now longer warns when writing customizeLeo.py.

2. Inserted a lock that prevents customizeLeo.py from being written unless use_customize_leo_dot_py = 1 in leoConfig.txt. Leo writes a message to the log if customizeLeo.py is dirty but was not written because of the setting in leoConfig.txt.
This makes the file name easier to see in the Windows task bar.
This allows Leo to syntax color comments with @language plain. The @comment directive must follow the @langauge directive.
In other words, the Pressing the Enter key in the Find panel executes the Find Next command.
The syntax colorer now colors all element tags. See the example in the child of this node.
@language html @color @ignore <HTML> <!-- Author: Edward K. Ream, edream@tds.net --> <HEAD> <META NAME="GENERATOR" CONTENT="Microsoft FrontPage 4.0"> <TITLE> Leo's Home Page </TITLE> <META NAME="description" CONTENT="This page describes Leo. Leo adds powerful outlines to the noweb and CWEB literate programming languages."> <META NAME="keywords" CONTENT="LEO, LITERATE PROGRAMMING, OUTLINES, CWEB, NOWEB, OUTLINES, EDWARD K. REAM, DONALD E. KNUTH, SILVIO LEVY, OPEN SOFTWARE"> </HEAD> <!-- Last Modified: May 12, 2002 --> <BODY BGCOLOR="#fffbdc">

<H1 ALIGN=CENTER><a NAME="top"></a><IMG SRC="Blank.gif" width= "32" height="32" ALIGN="BOTTOM" NATURALSIZEFLAG="3"><IMG SRC="leo.gif" WIDTH="32" HEIGHT="32" ALIGN="BOTTOM" NATURALSIZEFLAG="3"><a href="leo_TOC.html#top"><IMG SRC= "arrow_rt.gif" WIDTH="32" HEIGHT="32" ALIGN="BOTTOM" NATURALSIZEFLAG="3"></a> &nbsp;</H1>

<H1 ALIGN=CENTER> Leo's Home Page</H1>

<p align="center"><a href="http://www.python.org/"><img border="0" src="PythonPowered.gif" width="110" height="44"> </a> <A HREF="http://sourceforge.net/"><IMG SRC="http://sourceforge.net/sflogo.php?group_id=3458&type=1" NATURALSIZEFLAG="0" ALT="SourceForge Logo"></A>&nbsp;&nbsp;&nbsp; <A HREF="http://sourceforge.net/project/?group_id=3458">Leo at SourceForge</A>&nbsp;&nbsp; <a href="icons.html"><img border="0" src="LeoCodeGray.gif" width="77" height="42"></a>&nbsp;&nbsp; <a href="icons.html"><img border="0" src="LeoProse.gif" width="81" height="42"></a>&nbsp;&nbsp;&nbsp;&nbsp;

<H3><A NAME="anchor127554"></A>Summary</H3>

<UL> <LI>Leo is a <i> programmer's editor</i> and a flexible <i>browser</i> for projects, programs, classes or data. Leo clarifies design, coding, debugging, testing and maintenance. <LI>Leo is an <i>outlining editor</i>. Outlines clarify the big picture while providing unlimited space for details. <LI>Leo is a <a HREF="http://www.literateprogramming.com/"><i>literate programming</i></a> tool, compatible with <A HREF="http://www.eecs.harvard.edu/~nr/noweb/">noweb</A> and <a HREF="http://www-cs-faculty.stanford.edu/~knuth/cweb.html">CWEB</a>. Leo enhances any text-based programming language, from assembly language and C to Java, Python and XML. <LI>Leo is also a <i>data organizer</i>. A single Leo outline can generate complex data spanning many different files.&nbsp; Leo has been used to manage web sites. <LI>Leo is a <i> project manager</i>. Leo provides multiple views of a project within a single outline. Leo naturally represents tasks that remain up-to-date. <LI>Leo is fully <i> scriptable</i> using <A HREF="http://www.python.org/">Python</A> and saves its files in <A HREF="http://www.w3.org/XML/">XML</A> format. <LI>Leo is <i>portable</i>.&nbsp; Leo.py is 100% pure Python and will run on any platform supporting <A HREF="http://www.python.org/">Python</A> and <a href="http://tcl.activestate.com/">Tk/tcl</a>, including Windows, Linux and MacOS X.&nbsp; Leo.exe runs on any Windows platform. <LI>Leo is <a href="http://www.opensource.org/"> <i> Open Software</i></a>, distributed under the <a href="http://www.python.org/doc/Copyright.html"> Python License</a>. </UL>

<H3>More Information and downloads</H3>

<ul> <LI>An excellent <a href="http://www.3dtree.com/ev/e/sbooks/leo/sbframetoc_ie.htm">online tutorial</a> and <A HREF="http://www.jserv.com/jk_orr/xml/leo.htm">Leo resource page</A>, both written by <a href="http://www.jserv.com/jk_orr">Joe Orr</a>. <LI>My brother's <a href="SpeedReam.html">slashdot article about Leo</a>, the best description about why Leo is special. <LI><A HREF="testimonials.html#anchor104391">What people are saying about Leo</A> <LI><A HREF="leo_TOC.html#anchor964914">Complete users guide</A> and <A HREF="intro.html#anchor887874">tutorial introduction</A> with screen shots. <li><a href="FAQ.html">FAQ</a> and <a href="http://sourceforge.net/forum/?group_id=3458">help and discussion forums</a>, preferable to <A HREF="mailto:edream@tds.net">email</A> so others may join in.</li> <li><a href="icons.html">Icons</a> for bragging about Leo.</li> </ul>

<a href="http://sourceforge.net/project/showfiles.php?group_id=3458">Download Leo</a> from <A HREF="http://sourceforge.net/project/?group_id=3458">Leo's SourceForge site</A>.

<P ALIGN=left>Leo's author is <A HREF="http://personalpages.tds.net/~edream/index.html">Edward K. Ream</A> email: <A HREF="mailto:edream@tds.net">edream@tds.net</A> voice: (608) 231-0766

<HR ALIGN=LEFT>

<p align="center">

<IMG SRC="Blank.gif" ALIGN="left" NATURALSIZEFLAG= "3" width="34" height="34"><IMG SRC="leo.gif" ALIGN="left" NATURALSIZEFLAG= "3" width="32" height="32"><a HREF="leo_TOC.html"><IMG SRC="arrow_rt.gif" WIDTH="32" HEIGHT="32" ALIGN="left" NATURALSIZEFLAG="3">

</BODY> </HTML>
- Added "Replace tabs with spaces" checkbox.

- The close button is equivalent to the "Cancel" button rather than the "Ok" button.
This was causing great confusion.
- There was a bug that prevented the command from working properly if the line number preceded the present line.

- The goto line number option only works on full path names in @file nodes. It does not work for relative paths or in combination with an @path directive.
This problem only arose with languages such as html that have no single-line comment delimiter.
Leo did not properly handle configuration settings containing the % character.
Double-clicking the icon box used to set the cursor to the hand.
Every call to v.unjoinNode was calling c.clearAllVistied.

Fixing this bug will allow me not to use inodes & locations for the foreseeable future.
In the unusual case that a language has no single-line comment delimiter, Leo will remove the block delimiters from the headline text in node sentinels. createNthChild must take this into account by doing a second comparison of headlines if the normal comparison fails. If the second comparison of headlines succeeds we assume that we should use the headline from the outline instead of the derived file. I believe some kind of kludge like this will also be required for 4.0.
- Translating the "Tangle..." label differently from the "Tangle" one was impossible without modifying leo's source code (same thing for "Untangle..." and "Untangle").

- Couldn't translate either "Show Invisibles" and "Hide Invisibles". First toggle is OK then an error occurs after the second...
- changed copyPart so it returns on @code as well as @c.

- changed convertVnodeToWeb so that it takes account of the "at_root_bodies_start_in_doc_mode" setting.

- For the most part, directives other than @c, @code, @space, @doc, @others get written to the file as @@directive. There are minor differences between how this is handled in @root and @file trees. This might be considered a bug, and I am not going to do anything unless someone complains loudly.
Enabling or disabling @language or @comment now recolors entire text.
I had forgotten to compile leo.nsi.
Python 2.3a1 contains a bug in the tkinter code. This bug has been fixed on Python's cvs site. Until this bug is fixed in an official Python release Leo must use:

true,false = 1,0

rather than:

true,false = True,False
leo.py 3.10 December 14, 2002

This version of Leo corrects bugs, improves Leo's documentation and adds many new features:

- Rewrote the Scripting Chapter in Leo's Users Guide. - Improved the Customization Chapter of the Users Guide. - Adds several customizations contributed by Leo's users. Among these: @read-only nodes. Reading empty .leo files. Redirecting stderr and stdout to Leo's log pane. - New Mark Clones and Go To Next Clone commands. - New Export Headlines command. - Control-dragging a node now clones it. - New "Node Only checkbox in the Find/Change panel. - @root-code trees start in code mode by default. This allows @root trees to work like @file trees. - @root-doc trees start in doc mode by default. - Converted leoConfig.py to use @root-code - New at_root_bodies_start_in_doc_mode option in leoConfig.py. Specifies whether @root trees work like @root-code or @root-doc. - New synonyms: @file-asis = @silentfile @file-nosent = @nosentinelsfile ; @file-noref = @rawfile. - Leo now supports navigation of menus using underlined menus. - Added an easy way to replace any Leo method by a function. The code in customizeLeo.py can now override any part of Leo's code! - Added routines to redirect stderr and stdout to Leo's log pane. These routines can be called from customizeLeo.py. - Added "event1" and "event2" hooks for customize event handling. - Improved Leo's window icon, and improved how that icon is loaded. - The usual assortment of bug fixes and minor improvements. Actually, this release fixes more than the usual number of bugs.

See the children of this node for full details.

The quote of the month:

I must say I am very impressed. I have been absolutely seduced by Leo over the past few days. I tell you, I can not put it down. I feel like a kid with a shiny new bike...I'm already bursting with new ways I'd like to use the tool in the future -- Lyn Adams Headley
The old code did not allow <tag /> in many cases. The new code reads minimal.leo without complaint. It is:

<?xml version="1.0" encoding="UTF-8"?> <leo_file> <leo_header file_format="2" /> <globals /> <preferences /> <find_panel_settings /> <vnodes /> <tnodes /> </leo_file>
Apparently the F4 shortcuts interferes with the Alt-F4 shortcut.
The content formerly on evisa.com, including the Leo tutorials is now on 3dtree.com.
Leo improperly added extra blank lines and tabs in @file-nosent trees.
Untangle was warning about a missing section if the section had only an @doc part.
Leo was not handling the class keyword properly.
When leo.py was launched from the command line specifying a non-existent file the message "file not found" was displayed but the outline pane was not drawn properly.
@nosentinelsfile nodes were not being marked dirty properly.

Also, the message in atFile.writeAll about "no @file node found" did not include these nodes. The message was generalized.
While scanning for the initial state we must make sure that i < old_len and i < new_len.

Leo was not handling Python ''' strings properly.
It is not correct to do:

exec s in __builtins__

because that pollutes the namespaces of the __builtin__ module. Correct is simply:

exec s in {}
Previous versions of Leo did not properly recycle bindings in the outline pane.

This was reported by David LeBlanc and fixed with major hints from Chad Netzer.
The lambda functions for callbacks were not working properly.
The fix was made to atFile.scanAllDirectives() and leoGlobals.scanDirectives() tangle.scanAllDirectives() was not affected.

# Reversion fix: 12/06/02: We must use elif here, not if. elif not old.has_key("language") and dict.has_key("language"):
This bug was created recently by the new underline/realMenuName logic. We must not set the undo/redoRealMenuName ivars in clearUndoState: that should only be done when actually setting the menu names.
Both command are enabled only if the presently selected node is a clone. Mark Clones marks all nodes that are clones of the present node. Go To Next Clone goes to the next node that is a clone of the present node. A little experimentation convinced me that this command should wrap. So this command endlessly cycles among the nodes. Trying to end the this endless cycling would not be easy, as my experience with the Find command shows.

These are straightforward (and surprisingly useful) commands. Please report any problems immediately.
This works just like the Flatten Outline command except it writes only headlines.
How did I ever live without this.

Also improved messages and fixed a major performance bug: tree.numberOfVisibleNodes was being called repeatedly!
The Node Only checkbox takes precedence over Suboutline Only if they are both checked.
New in Leo 3.10: Leo allows you to choose whether body text in @root trees will start in code mode or doc mode by default.

@root-doc filename and @root-code filename specify that body text is assumed to start in doc mode or code mode respectively. The options (-doc and -code) must follow @root immediately with no intervening whitespace. In effect, @root-code and @root-doc are two new directives.

These @root options override the new at_root_bodies_start_in_doc_mode option in leoConfig.py. This option affects only @root trees without options. Such "plain" @root trees are now deprecated, which only means that it is now better style to use either @root-code or @root-doc. The reason is simple: the meaning of plain @root trees will depend on the at_root_bodies_start_in_doc_mode option, and that isn't good.

By default, at_root_bodies_start_in_doc_mode = 1 for compatibility for old @root trees. I actually don't think this option is good for much; I created it before I created @root-doc and @root-code, and I decided it wouldn't hurt to leave it in. Anyway, you now have complete flexibility about how @root works, and in particular you can make @root work just like @file.
@file-asis is a synonym for @silentfile. @file-nosent is a synonym for @nosentinelsfile. @file-noref is a synonym for @norefsfile.
Completed a major revision of the menu handling code to handle underlined menus. As is typical on Windows, you specify the underlined character by preceding it with an ampersand character.
Created a new icon and improved the code that loads it.
This is the funcToMethod function in customizeLeo.py.
See the relevant section of customizeLeo.py
"event1" and "event2" are generated for many Leo events. keywords.get("kind") returns one of the following for "event1" and "event2" hooks:

"activate", activate window event (not uniform across window managers). "deactivate" deactivate window event (not uniform across window managers). "boxClick" The +- box has been clicked. "drag" Generated repeated while dragging nodes. "endDrag" mouseUp that ends a drag. "headClick" Left-click in a headline. "headPopup" Right-click in a headline. "headKey" A keypress in a headline. "hyperLinkControlClick" Control-click on a hyperlink. "hyperLinkEnter" Mouse moves over a hyperlink. Disabled at present. "hyperLinkLeave" Mouse moves away from a hyperlink. Disabled at present. "iconDoubleClick" The icon box has been double-clicked.
The present code properly handles undo/redo for operations that copy trees, but copying trees itself causes problems for further undoes. I've disabled further undos, as was done previously, but this is a pity.

To fix this, we may have to hack on the beads to indicated that a copy has been made. No doubt about it: copying trees is tricky.
leo.py 3.9 Nov 23, 2002

This is one of the most interesting versions of Leo ever released:

* Major performance improvements: - Incremental syntax coloring speeds response when typing. - Incremental undo drastically reduces memory used.

* Major improvements in customizing Leo: - Leo looks in the file customizeLeo.py for user-specific customizations. - Leo calls "hook routines" in customizeLeo.py for all commands and events. These hook routines can modify or replace any command or event. - New convenience routines simplify creating and modifying menus. - Easy translation of menus to other languages using customizeLeo.py.

* Better integration with other tools: - The Open With command allows you to communicate back and forth to other editors. - The Go To Line Number command converts lines numbers in derived files to locations in the outline. - Double-clicking the icon of a @url node launches any url in your web browser. - The Execute Script command executes Python code in any body pane. This is much more convenient than opening Leo's Idle window. - Much better support for cweb. At last, Leo has a power user of cweb. By default, @space, @* and @** sections are colored as latex text. Leo properly generates @q..@> sentinels. - @nosentinelfile is like @file except Leo writes no sentinel lines.

* Other improvements: - Optional Emacs-style auto-indent. - Reformat Paragraph command. - Leo will optionally create nonexistent directories specified in @file, @root or @path, including all nonexistent parent directories. - Leo will place its own icon in Leo windows provided that you have installed Fredrik Lundh's PIL and tkIcon packages. - The usual assortment of bug fixes.

See the children of this node for full details.

P.S. Here is what Travers A. Hough recently said about Leo:

"When first I opened Leo, it was out of curiosity. But having used it...I'LL NEVER GO BACK. THEY'LL HAVE TO PRY LEO OUT OF MY COLD, DEAD FINGERS! Seriously, it should be renamed "Crack Cocaine" because it's that addictive. I'm ready to start a 12-Step group."
The cweb prefs panel setting was overriding @language python (!)
@language pascal @color

private uses
app().log is now set correctly when there are multiple windows. Previously, app().log depended on activate events, and was not reliable. The following routines now set app().log:

- frame.doCommand - frame.OnMenuClick

Thus, top() will be reliable after any command is executed. Creating a new window and opening a .leo file also set app().log correctly, so it appears that all holes have now been plugged.

Note: The value of top() may change during a new or open command, which may change the routine used to execute the "command1" and "command2" hooks. This is not a bug, and hook routines must be aware of this fact.
Leo no longer massages comments when importing Java files.

There was a bug in massageBody that prevented text from being indented properly. There was a bug in find_line_start (!!) that caused the start of the previous line to be found if s[i] was a newline. It's amazing that these bugs were undiscovered for so long.

Treat interface like class.
Version 3.9 contains many new features and commands. The children of this node document them.
Undo now uses incremental syntax coloring. This speed up undo tremendously.
Previous versions of Leo stored the complete body text whenever any change was made to the body text. The present version of undo stores only enough information to undo or redo the typing: typically two lines of text. This results in about a 90% reduction in the memory used by undo.
These are discussed in the child of this node.
@nocolor

You may customize Leo in several ways:

I. Using leoSettings.leo

The following information discusses how Leo 4.3 and all later versions handle user configuration settings. For all previous versions, see the node called 'Obsolete: Using leoConfig.leo and leoConfig.txt'

Leo stores options in @settings trees, that is, parts of Leo outlines whose root node has the headline @settings. When opening a .leo file, Leo looks for @settings trees in the following places:

- The file called leoSettings.leo in the leo/config directory. - The file called leoSettings.leo in the users home directory. - The file being loaded.

Settings that later in the above list override settings found earlier. For example, any setting specified in an @settings tree in the file being loaded overrides any setting seen in any leoSettings.leo file.

II. Using plugins and hooks

During startup, Leo looks for plugins, i.e., .py files in the plugins directory. These plugins register functions called "hooks" to be called a various times during execution. Full details are provided below.

Plugins provide the following advantages:

- Any time you see a nice hook handler that someone has written you can just copy it to a plugin file and it runs next time you start Leo. - You don't have to keep updating a large and growing customizeLeo.py file. - You can disable and enable hooks by renaming the relevant plugin file. (or by enabling or disabling the code in the plugin that registers hook functions). - You don't have to merge code from hooks pertaining to the same Leo event.

When executing any command or handling any event, Leo calls hook routines registered from the plugin files. The arguments to hooks are:

- "tag", a string telling the kind of command or event about to be executed, and - "keywords", a Python dictionary whose keys depend on the specific command or event.

This is a very simple, powerful and general mechanism for customizing Leo as you see fit. There are dozens of kinds of hooks, including the "command1" and "command2" hooks that are called before and after each of Leo's menu commands. Leo will allow you to override most commands and event handling. In many cases, if a hook returns any value except None Leo will assume that the hook has completely handled the command or event and will take no further action. The details will be explained in full below.

Leo catches all exceptions raised in hook code, so you can modify hooks without worry.

SECURITY WARNINGS: Using hooks naively can create the potential for virus-like behavior. Please read the section called SECURITY WARNINGS for full details.

III. Using convenience routines called from hooks.

Hook routines can import any file in Leo's source code and execute routines in that file. Leo's contains a number of convenience routines designed to make common customization tasks easier. Hooks can use these routines to create your own menus, to translate menus into other languages, and to create entries in the Open With menu. These convenience routines are discussed in detail below.

IV. Setting app().realMenuNameDict inside hooks to translate menus into other languages.

This is discussed below.
@nocolor

Leo will override settings in .leo files if it finds a file called leoConfig.txt in the config subdirectory. Leo works just as before if it does not find a leoConfig.txt file.

You should make changes to leoConfig.txt by changing leoConfig.leo and then executing the Tangle All command. There are two advantages to changing leoConfig.txt in this manner. First, it is just easier to change leoConfig.leo. Second, all comments are lost in leoConfig.txt when Leo updates it, so using leoConfig.leo as the primary data file means you will always have the comments available.

Leo looks for leoConfig.txt first in the directory specified by the Python variable sys.leo_config_directory. You would typically set this variable in Python's sitecustomize.py file. If this variable does not exist, Leo looks in the directory from which Leo was loaded.

The child of this node contains an example of leoConfig.txt that shows all the options that may be set.

Settings in leoConfig.txt overrides preferences in .leo files, but only for those items actually in leoConfig.txt, so you can choose which settings you want to override. Also, a Leo ignores any setting in leoConfig.txt whose value is "ignore" (without the quotes). For example:

[prefs panel options] tab_width = ignore

If a setting is overridden, it is _not_ written to the .leo file when the outline is saved. Note that this does not change the file format: all previous versions of Leo will be able to read such .leo files.

The preceding is probably all you need to know to use leoConfig.txt. The following discuss some minor details:

1. When reading a .leo file, if a setting is found neither in leoConfig.txt nor in the .leo file, Leo uses a default, hard-coded value. In leo.py 3.0 and later these default settings are found in tables that appear in the section called:

<< define default tables for settings >>

in the file leoConfig.py. So it is now convenient to change settings in leo.py itself as well as in leoConfig.txt.

2. Leo will update leoConfig.txt unless the read_only option is on in leoConfig.txt.

WARNING: there are problems when Leo does write leoConfig.txt: all comments are lost and options and sections are written in a random order. This is due to problems in Python's ConfigParser module and will not be changed any time soon.

3. Provided the read_only option is off, Leo updates leoConfig.txt whenever it saves a .leo file or whenever the Preferences panel is closed without being canceled. When updating leoConfig.txt, Leo will write only existing settings whose value is not "ignore".

4. When Leo saves a .leo file, Leo will write a Preferences setting to the .leo file only if the setting will not be written when updating leoConfig.txt. In particular, changes made in the Preferences Panel will become permanent immediately if Leo the read_only option is off. Otherwise the change will become permanent when any .leo file is saved.
Beginning with version 3.11, you may use plugins to customize how Leo works. You can

- override or modify any command - add or customize menus or - translate menus into any language.

Plugins have full access to all of Leo's source code. In particular, several convenience methods have been added to make customizing menus and commands easier.

Plugins are permanent: they will not go away when Leo is updated. You can take advantage of the latest CVS updates _without_ having to throw away your modifications.

Important warning: plugins must avoid blindly executing scripts in .leo files. Doing so could expose all parts of your computer to malicious Python code. The section called "Security warnings and precautions" discusses how to customize Leo safely and how to avoid several pitfalls.
What is a plugin?

A plugin is a .py file that appears in Leo's plugin subdirectory. Leo tries to import all such files while starting up. This is done at "start1" time, that is, in the call to doHook("start1") in the run function in leo.py. Plugins exist to define "hook code".

New in 3.11: Leo looks in the plugins folder for .py files. Leo tries to import all such files at startup ("start2") time.

New in 4.1: Leo enables only plugins whose name appears in pluginsManager.txt. Leo loads plugins in the order in which they appear in pluginsManager.txt. Leo loads no plugins if pluginsManager.txt does not exist in the plugins directory.

What is hook code?

Leo automatically calls hook code at various times during Leo's execution. Typical hooks are:

- "start2", called at the end of Leo's startup process, - "command1", called before executing any of Leo's commands - "idle", called at Tk's idle time, when nothing else is happening,

See the documentation for hooks in this file for full details.

N.B. Plugins can use "start2" hooks to override any of Leo's classes. See "Overriding functions, methods & classes" in leoPlugins.leo for several examples of how to do this.

How do plugins work?

Plugins register themselves when Leo imports them using the following code, which should appear as the outer level of the .py file:

@color

"""A description of this plugin"""

registerHandler("xxx", onXXX) __version__ = "1.2" plugin_signon(__name__)

@nocolor

Line by line:

1) """A description of this plugin"""

This is a Python doc string describing the plugin. This string becomes the value of the __name__ attribute for the module (.py file).

2) registerHandler("xxx", onXXX)

This line registers a handler called onXXX for the hook called "xxx". See the documentation for hooks for a complete list of hook names that you can use instead of "xxx". onXXX is the name of a function or method, presumably defined in the plugin file, that Leo will call at "xxx" time. For example:

registerHandler("idle",onIdle)

will cause Leo to call the onIdle function at "idle" time.

You can pass a list of hook names as the first argument to registerHandler. For example:

registerHandler(("bodykey1","bodykey2","headkey1","headkey2"), onKey)

3) __version__ = "1.2"

This assigns a version attribute to module. At present this attribute is used by the plugin code that creates Leo's Plugins menu.

4) plugin_signon(__name__)

This line increases the count of loaded modules. The present code for plugin_signon does not actually print separate signons--it seems to verbose.

About hook handlers

See the "About hooks" section of leoPlugins.leo for full documentation about how to write hook handler routines, like onXXX or onKey in the examples above. Basically, each hook should have this pattern:

@color

def onXXX (tag,keywords): c = keywords.get("c") otherKeyword = keywords.get("otherKeyword") << do something with c and otherKeyword, etc. >>

@nocolor

In other words, keywords is a Python dictionary containing the keyword arguments passed to the hook handler. See the See the "About hooks" section of leoPlugins.leo for a list of the keywords passed to each hook handler.

The tag is the name of the hook. For example, tag would one of "bodykey1","bodykey2","headkey1","headkey2", for the onKey hook handler in the example above.

What's next?

It's one thing to know how to create a plugin. It's another to know how to actually change Leo. Obviously, some study is needed. The place to start your study is LeoPy.leo. In particular, study very carefully the section called "Overview of code". Leo is a highly modular program, and Python is ideally suited to this style of programming.
@nocolor

New in 3.11: Leo looks in the plugins folder for .py files. Leo tries to import all such files at startup ("start2") time.

New in 4.1: Leo enables only plugins whose name appears in pluginsManager.txt. Leo loads no plugins if pluginsManager.txt does not exist in the plugins directory.

The child of this node gives an example of the code that creates the Open With menu. The following code, appearing at the end of mod_open_with.py, registers two different hook functions. The on_idle function is the "idle" hook. The create_open_with_menu is the "start2","open2" and "command2" hooks.

@color

# Register the handlers... registerHandler("idle", on_idle) registerHandler(("start2","open2","command2"), create_open_with_menu) es("...open with")

@nocolor Plugins may call registerHandler with a hook name like "idle" or a list of hook names like ("start2","open2","command2"). Also, you can use the "all" hook name to indicate that code will be called for all hooks. This is useful for tracing hooks. Plugins may also call registerExclusiveHandler for hooks that should not be redefined in other plugins.

mod_open_with.py also contains the on_idle and create_open_with functions that actually handle the hook. Such functions have two arguments: tag and keywords. You will find many examples of this in LeoPy.leo.

About error checking:

At present Leo will disable all hooks if any hook throws an exception. In practice this isn't a big deal, but something better could be done.

How to send me your plugins:

It should now be _much_ easier to submit a plugin for inclusion in LeoPy.leo. Just send me a .leo file containing @file mod_your_plugin.py. Please have this @file node be @ignored: this is more convenient for me. Ideally, your .leo file should contain _only_ your plugin code.
Naively using hooks can expose you and your .leo files to malicious attacks. You will be safe as long as you follow these basic principles:

1. Hooks should _never_ blindly execute Python scripts in .leo files. Blindly executing scripts in .leo files runs the extreme risk of executing malicious code if you ever share any .leo file with someone else. Moreover, using rexec instead of exec WILL NOT PROTECT YOU. See the children of this node for further discussion of this important topic.

2. Hooks can execute any code safely _provided_ that all code is contained entirely within the plugin file. If you have a nifty customization that you want to do on a particular .leo file, put that code into a plugin.

3. Use only authentic copies of Leo that come from Leo's SourceForge site.
I'd like to thank Stephen Schaefer for gently insisting that we must guard against malicious code in shared .leo files. Here is a little story Stephen told on Leo's SourceForge site that makes clear what the danger is:

"I foresee a future in which the majority of leo projects come from marginally trusted sources...I see a world of leo documents sent hither and yon - resumes, project proposals, textbooks, magazines, contracts - and as a race of Pandora's, we cannot resist wanting to see "What's in the box?" And are we going to fire up a text editor to make a detailed examination of the ASCII XML? Never! We're going to double click on the cute leo file icon, and leo will fire up in all its raging glory. Just like Word (and its macros) or Excel (and its macros)."

This succinctly illustrates the fundamental problem: when we share "our" .leo files we can _not_ assume that we know what is our "own" documents. So hooks that naively searches through .leo files looking for scripts to execute is looking for big trouble.

The following node contains an example of the kind of code that is extremely dangerous.
@color @ WARNING ***** Using the following routine exposes you to malicious code in .leo files! *****

Do not EVER use code that blindly executes code in .leo files! Someone could send you malicious code embedded in the .leo file.

WARNING 1: Changing "@onloadpythonscript" to something else will NOT protect you if you EVER share either your files with anyone else.

WARNING 2: Replacing exec by rexec below provides NO additional protection! A malicious rexec script could trash your .leo file in subtle ways. @c if 0: # WRONG: This blindly execute scripts found in an .leo file! NEVER DO THIS! def onLoadFile(): v = top().rootVnode() while v: h = v.headString().lower() if match_word(h,0,"@onloadpythonscript"): s = v.bodyString() if s and len(s) > 0: try: # SECURITY BREACH: s may be malicious! exec(s + '\n',__builtins__,__builtins__) except: es_exception() v = v.threadNext()
@color @ It would be most foolish to expect rexec to protect you against malicious code contained in .leo files. Remember that Leo is a repository of source code, so any text operation is potentially malicious.

For example, consider the following script. This script is valid in rexec mode: @c

c = top() thisNode = c.currentVnode() v = c.rootVnode() while v: << change all instances of rexec to exec in v's body >> v = v.threadNext() << delete thisNode >> << clear the undo stack >>

@ This script will introduce a security hole the .leo file without doing anything prohibited by rexec, and without leaving any traces of the perpetrating script behind. The damage will become permanent _outside_ this script when the user saves the .leo file.
pass
pass
pass
Hooks have full access to all of Leo's source code simply by importing it.

Moreover, several convenience methods have been added to make customizing menus and commands easier. The following paragraphs discuss these routines and how to use them.

The following routines enable and disable "idle" hooks. They are defined in leoGlobals.py.

enableIdleTimeHook(idleTimeDelay=100)

Enables the "idle" hook. After this routine is called Leo will call the "idle" hook approximately every idleTimeDelay milliseconds. Leo will continue to call the "idle" hook periodically until disableIdleTimeHook() is called.

disableIdleTimeHook()

Disables the "idle" hook.
The following convenience routines make creating menus easier.

These are methods of the leoFrame class. Use top().frame to get the frame object for the presently active Leo window.

The plugins node in LeoPy.leo gives examples of how to use these routines to create custom menus and to add items to the Open With menu.

These convenience methods all do complete error checking and write messages to the log pane and to the console if errors are encountered.
@nocolor createMenuItemsFromTable (self,menuName,table,openWith=0)

This method adds items to the menu whose name is menuName. The table argument describes the entries to be created. This table is a sequence of items of the form (name,shortcut,command).

- name is the command name - shortcut is the shortcut, or None to indicate no shortcut. - command is the routine to execute when the menu item is selected.

An entry of the form ("-",None,None) indicates a separator line between menu items.

For example: @color table = ("Toggle Active Pane","Ctrl-T",self.OnToggleActivePane), ("-",None,None), ("Toggle Split Direction",None,self.OnToggleSplitDirection))

top().frame.createMenuItemsFromTable("Window",table) @nocolor

If the openWith keyword argument is 1 the items are added to a submenu of the Open With menu. However, it will be more convenient to use the createOpenWithMenuFromTable method to create the Open With menu.
createNewMenu (self,menuName,parentName="top")

This method creates a new menu:

- menuName is the name of the menu to be created. - parentName is the name of the parent menu, or "top" if the menu is to created in the menu bar.

This method returns the menu object that was created, or None if there was a problem. Your code need not remember the value returned by this method. Instead, your code will refer to menus by name.
createOpenWithMenuFromTable (self,table)

This method adds items to submenu of the Open With menu item in the File menu.

The table argument describes the entries to be created. This table is a sequence of items of the form (name,shortcut,data).

- name is the command name - shortcut is the shortcut, or None to indicate no shortcut. - data is a tuple of the form (command,arg,ext) - command is one of "os.system", "os.startfile", "os.spawnl", "os.spawnv" or "exec". - arg is an argument to be passed to the given command. - ext is a file extension or None.

When the user selects the Open With item corresponding to the table item Leo executes command(arg). If ext is not None, the temp file has the given extension. Otherwise, Leo computes an extension based on what @language directive is in effect.

For example:

table = ( ("Idle", "Alt+Shift+I",("os.system",idle_arg,".py")), ("Word", "Alt+Shift+W",("os.startfile",None,".doc")), ("Wordpad","Alt+Shift+T",("os.startfile",None,".txt")))

top().frame.createOpenWithMenuFromTable(table)
deleteMenu (self,menuName)

Deletes the menu whose name is given, including all entries in the menu.
deleteMenuItem (self,itemName,menuName="top")

Deletes the item whose name is itemName from the menu whose name is menuName. To delete a menu in the menubar, specify menuName="top".
@nocolor The leoFrame class creates the Window menu as follows: @color

windowMenu = self.createNewMenu("&Window")

table = ( ("&Equal Sized Panes","Ctrl-E",self.OnEqualSizedPanes), ("Toggle &Active Pane","Ctrl-T",self.OnToggleActivePane), ("Toggle &Split Direction",None,self.OnToggleSplitDirection), ("-",None,None), ("Casca&de",None,self.OnCascade), ("&Minimize All",None,self.OnMinimizeAll), ("-",None,None), ("Open &Compare Window",None,self.OnOpenCompareWindow), ("Open &Python Window","Alt+P",self.OnOpenPythonWindow))

self.createMenuEntries(windowMenu,table)
@nocolor

It is easy for hooks to translate menus into another language. For example, code similar to the following code would typically be found in the "start2" hook:

@color

table = ( ("Open...","&Ouvre"), ("OpenWith","O&uvre Avec..."), ("close","&Ferme"), ("Undo Typing","French &Undo Typing"), # Shows you how much French I know ;-) ("Redo Typing","French &Redo Typing"), ("Can't Undo", "French Can't Undo"), ("Can't Redo", "French Can't Redo")) # Call the convenience routine to do the work. app().setRealMenuNamesFromTable(table)
New in 4.0: Leo can now read and write "foreign" attributes in <v> and <t> elements in .leo files:

- When reading a .leo file, Leo will create t.unknownAttributes or v.unknownAttributes ivars for any tnode and vnode object whose corresponding <v> or <t> element in the .leo file contains a foreign attribute.

- The unknownAttributes ivars are a dictionary whose keys are the attribute names and whose values are strings.

- When writing a file, Leo will write "foreign" attributes if a vnode or tnode contains an unknownAttributes ivar.

- The only "native" attributes that Leo expects to find are the "tx" attribute in <t> elements and the "a", "t", "vtag" and "tnodeList" attributes of <v> elements. Everything else is a foreign attribute.

- Leo performs the usual xml escapes on these strings when reading or writing the unknownAttributes ivars.

Plugins may cause Leo to write such foreign attributes simply by attaching unknownAttributes ivars to a vnode or tnode. For example:

v.unknownAttributes = {"vnodeIcon" : pathToIcon}

It would be best not to delete other foreign attributes, so the following would be preferred:

if hasattr(v,"unknownAttributes"): v.unknownAttributes["vnodeIcon"] = pathToIcon else: v.unknownAttributes = {"vnodeIcon" : pathToIcon}

Another way:

try: v.unknownAttributes["vnodeIcon"] = pathToIcon except AttributeError: v.unknownAttributes = {"vnodeIcon" : pathToIcon}

See the section called "Recommended conventions for plugins" for advice about how to avoid potential conflicts in naming new attributes.
Leo creates nonexistent directories only if create_nonexistent_directories = 1 in leoConfig.txt.

Previous versions of Leo created a new directory only if its parent directory already existed. Now, Leo will create all non-existing directories as required.

For example. Suppose neither dir1 nor dir2 exists. Leo will create both dir1 and dir1 when it writes the following @file \root\dir1\dir2\spam.py.
Double-clicking the icon box of a node whose headline has the form:

@url <any url>

executes the url in your default web browser.

Leo checks that the url is valid before doing so. A valid url is:

-- 3 or more lowercase alphas, -- followed by one ':', -- followed by one or more of: $%&'()*+,-./0-9:=?@A-Z_a-z{}~ -- followed by one of: $%&'()*+/0-9:=?@A-Z_a-z}~

Url's should contain no spaces: use %20 to indicate spaces.

You may use any type of url that your browser supports: http,mailto,ftp,file,etc.
The present version should be quite usable for its main purpose: tracking down lines corresponding to error messages. In particular, except for possible pathological cases, Leo should always put the cursor in the node containing the referenced line. Possible pathologies involve asking Leo to "go to" a sentinel line. It won't always be clear what node contains the sentinel.

I am well aware that Leo may not put the cursor on the proper line within the vnode, but human beings being the excellent pattern matchers that we are, we should be easily be able to find a line within a node.

Notes in LeoPy.leo, in the node called (Go to line number), discuss a variety of issues that may cause the cursor not to go to the "proper" line. It also discusses a better way to position the cursor.

Internally, there are two main versions of this command: one for @silentfile trees, and one for @rawfile and @file trees. In the first case, there are no sentinels in the derived file, so Leo just steps through the outline. This is the easy case, and should work well. In the second case (@rawfile and @file trees), the derived file contains sentinels, and Leo uses those sentinels to determine in what vnode the given line occurs.

In this second case, Leo can almost always position the cursor within the proper node, because Leo just scans back in the derived file looking for the proper @+node sentinel. However, in order to "count" lines in the derived file (to place the cursor properly _within_ the body text) Leo must recreate exactly the logic used by the atFile.read logic, and that isn't easy. Moreover, there is _no_ guarantee that the derived file is unchanged from when it was written; after all, if you get syntax errors you tend to want to fix them ;-)

Please do not report bugs in this command, unless the bug involves a crash, which would be reported both in Leo's log pane and in the console window. This command will probably be improved in 3.10.
At last Leo has a power user of cweb. Cweb mode is now fully tested and fully functional. The following improvements have been made to cweb mode:

1. Corrected sentinels used in cweb mode.

Leo must double _all_ @ signs following the @q@. For example, an @@color sentinel gets turned into @q@@@@@color@>.

2. Leo colors cweb doc parts and C comments in LaTex mode by default.

In cweb mode Leo colors @space, @* and @** sections using LaTeX coloring by default. The color_cweb_doc_parts_with_latex option in leoConfig.py/.txt affects this default.

Similarly, Leo colors C comments in cweb mode using LaTeX coloring by default. The color_cweb_comments_with_latex option in leoConfig.py/.txt affects this default.

3. Cweb mode works similarly in @file and @root trees.

See the child of this node for full details about cweb mode.
Cweb mode refers to how Leo tangles an outline when @language cweb is in effect or the cweb option in the Settings Panel is in effect.

Leo treats _all_ cweb code in cweb mode as unevaluated text. That is, Leo treats cweb control codes, including @<...@>, @<...@>=, @c, @space, @* and @** as "raw" text within cweb mode. Leo does _not_ expand _cweb_ section references when writing derived files in cweb mode. However, Leo _does_ expand _noweb_ section references, so you may use noweb sections to organize cweb files! You can create _noweb_ code and doc sections using the @code and @doc directives in place of @c and @space directives.

By default, cweb colors @space, @* and @** sections using the same syntax coloring as for LaTeX. In addition, cweb colors C // and /*..*/ comments using LaTeX coloring by default. You may change these defaults using the color_cweb_doc_parts_with_latex and color_cweb_comments_with_latex options in leoConfig.py.
The Open With command allows you to communicate with external editor. When you select this command Leo creates a temporary file and invokes an external program. Leo periodically checks whether this temporary file has changed; Leo changes the corresponding node in the outline if so.

You must create the entries in the Open With submenu. This would typically be done in a hook routine, using the createOpenWithMenuFromTable routine described in the child of this node.

The @file mod_open_with.py node in LeoPy.leo gives a complete example of handling the Open With menu.
Leo now supports optional Emacs-style auto-indent. This style of auto-indent aligns newly created lines with unmatched ( [ or { brackets in the previous line. This feature is enabled only if smart_auto_indent = 1 in leoConfig.txt.

This code was contributed by David McNab, david@rebirthing.co.nz.
New in leo.py v3.9

Whether importing text from an outside source, typing in text, or modifying text, eventually you end up with a block of text in which some lines are too long and some are too short. The Reformat Paragraph command will rearrange the words in a text paragraph to fill each line as full as possible, up to the @pagewidth setting.

A paragraph is delimited by blank lines, Leo directives, and (of course) start and end of text in a node. The width of the line used by the reformatting operation is governed by @pagewidth and the indentation that would be applied to the node when tangled (as part of a @root) or written (as part of a @file).

The command operates on the paragraph containing the insert cursor. If the insert cursor is on a blank line or directive, nothing happens. If the cursor is on a line containing text, then the paragraph containing that text line is reformatted and the insert cursor is moved to the next paragraph.

Be careful that you don't do this on source code! Of course, if you do reformat something that should have been left alone, then just Undo.

NOTE: Lines with hanging indentation are handled so that the hanging indentation is preserved. This is most useful for bulleted or numbered lists, such as:

1. This is the first paragraph, and it has a hanging indentation.

2. This is the second paragraph, and it too has a hanging indentation.
An @rawfile tree is a tree whose root headline starts with @rawfile <filename>. Similarly, for @silentfile and @nosentinelsfile trees.

Leo creates files derived from @file and @nosentinelsfile trees in exactly the same way. The _only_ difference is that files derived from @file trees contain sentinels, while files derived from @nosentinelsfile trees do not. Therefore, Leo can not update outlines from changed made from files derived from @nosentinelfile trees.

Leo creates files derived from @rawfile and @silentfile trees by writing the body text of all nodes of the tree in outline order. Leo writes the body text _as is_, without recognizing section definitions, without expanding section references, and without treating directives specially in any way. In particular, Leo copies all directives, including @space or @c directives, to the derived file as text. However, Leo recognizes the @ignore directive in the _ancestors_ of @rawfile or @silentfile nodes, so you may use the @ignore directive as usual to prevent Leo from writing @rawfile and @silentfile trees.

There are several difference between @rawfile and @silentfile trees:

1. Leo writes no sentinel lines when writing @silentfile trees. When writing @rawfile trees, Leo writes only the @+leo, @-leo, @+node, @-node, @+body and @-body sentinels. Therefore, Leo can update @rawfile trees, but _not_ @silentfile trees from changes made in derived files. Unlike @file and @rawfile trees, the primary source of information for an @silentfile tree is the outline containing it.

2. Within @silentfile trees only, if a headline starts with @@, Leo writes everything in the headline following the @@ just before the corresponding body text.

3. Files derived from @silentfile trees contain _nothing_ not contained in body text (or @@ headlines). In particular, if body text does not end in a newline, the first line from the next node will concatenated to the last line of the preceding node.

In short, you can get any combination of sentinels/no sentinels and references/no references using @file, @nosentinelsfile, @rawfile and @silentfile trees. This is shown in the following table:

Derived files Sections and Type of tree contain sentinels? @others expanded? ------------ ------------------ ----------------- @file yes yes @nosentinelsfile no yes @rawfile yes no @silentfile no no

New in Leo 3.10:

@file-asis is a synonym for @silentfile. @file-nosent is a synonym for @nosentinelsfile. @file-noref is a synonym for @rawfile.
leo.py 3.8 October 29, 2002

Many major improvements have been made to Leo, all made as the result of user requests:

- New @rawfile and @silentfile trees complement @file trees. @rawfile and @silentfile trees create derived files without using sections. @rawfile files contain only those sentinels needed to automatically untangle them. @silentfile trees contain no sentinels at all. - New @raw and @end_raw directives allow unformatted code within @file trees. - Much better support for CWEB. You may organize .w files using noweb! - The @comment and @language directives may now apply simultaneously. - Leo can now read, remember and write <?xml-stylesheet...?> lines, under control of the new stylesheet option. - The new output_newline option specifies the line endings used when writing files. - The new output_initial_comment option specifies the text to appear in an @comment sentinel at the start of each derived file. - New commands in the help menu make it much easier to change configuration options. - Dozens of minor improvements and bug fixes.

This month Dave Hein and I discovered how to uniquely and permanently identify nodes, regardless of where those nodes are located and regardless of how many people are working simultaneously on them. This discovery will greatly improve Leo, and will simplify how people use Leo with CVS. Leo 4.0, due out in a month or two, will be the first version of Leo to use this breakthrough.

See the children of this node for full details.
The warning for "unknown language" had an unbound var.
Leo now properly handles @delims directives in @file trees.
Leo now properly recognizes all sentinel lines when @language cweb is in effect.
Fixed a bug that caused Leo to say "methods" rather than "functions" when importing C code.

Leo now adds @root <filename> statement when importing to @root nodes.
Previously, Java only had block comments, and the ending delim wasn't being removed from doc parts.
The present code explicitly eliminates control-T processing in headlines, which means that control-T does not switch panes when editing headline text. Control-T _does_ switch panes in all other cases.

This appears to be another Tk bug.
Only shortcut pastes worked before.
Leo 3.7 significantly offers you several new ways to create derived files.
@rawfile and @silentfile trees are important new additions to Leo. They work like @file trees, but are simpler to use. See the child of this node for full details.
The @raw and @end_raw directives delimit a region of "raw" text. No section references are recognized within "raw" text, and no additional leading whitespace is generated within "raw" text when writing the derived file.

The @quiet directive is valid only within @root trees. It suppresses all sentinels except the @+node sentinels used to mark headlines.

See the children of this node for full details.
The @raw and @end_raw directives are valid only within @file trees. The @raw directive starts a section of "raw" text. The @end_raw directive ends such a section, as does the end of body text. No section references are recognized within "raw" text, and no additional leading whitespace is generated within "raw" text when writing the derived file.
The @verbose, @terse, @quiet and @silent directives determine how the Tangle command outputs comments in @root trees. Comments written by the user in code sections are always output: these directives control only: a) the comments containing doc sections and b) sentinel comments that delimit the beginning and end of code sections.

When @verbose is in effect Tangle outputs all comments. When @terse is in effect, Tangle outputs only those comments necessary for Untangle to work. When @silent is in effect Tangle adds no additional comments. The @quiet directive is like @silent except that it does output leading sentinels as comments. Like @silent, @quiet inhibits untangling.

@verbose is the default. If more than one of these directives appear in the same body text the "most verbose" of these options will be in effect.
It is now possible to create CWEB (.w) files from @file trees. When @language cweb is in effect the following happen:

1. Leo does not recognize @space and @c directives.

2. The colorizer now recognizes both cweb and noweb section definitions and references.

3. Leo uses @q@ and @> for comment delimiters in files derived from @file or @rawfile trees, and Leo replaces @ by @@ within such comments.

4. Leo now properly warns about orphan nodes when @langauge cweb was in effect.

See the child of this node for the new documentation that applies to cweb mode.
It is now possible to have both the @comment and @language directives to be in effect at the same time. To do this, both directives must appear in the same node, and the @comment directive must follow the @language directive.
Leo preserves the <?xml-stylesheet...?> line if it is already present in the .leo file.

Otherwise, Leo writes a <?xml-stylesheet...?> line only if the stylesheet option is present in the configuration file. The stylesheet option specifies s in <?xml-stylesheet s?>
The Open LeoConfig.leo command opens the configuration file. The apply setting command applies any changes to settings made as the result of changing leoConfig.leo.
This option allows a comment to be inserted in derived files just after the initial @+leo line. The comment will appear in an @comment sentinel. See leoConfig.leo for full details.
This option allows you to specify the line endings to be used when writing derived files and when exporting files. See leoConfig.leo for full details.
Changed the path_directive_creates_directories option in leoConfig.leo to create_nonexistent_directories.

The old name was too misleading. Indeed, this option applies not just to @path directives, but to all situations in which the path name specified in @path directives or @root, @file, @rawfile or @silentfile nodes does not exist.

The new names are less cluttered than the old.
Leo now prints a summary of any exception taken to the log window, and a full traceback to the console window.
This is taken from Python Cookbook.

This may be of use to people developing Leo, though it's not clear how useful this is with Tk programs.
A small convenience that is actually quite nice to have.
Sentinel lines in Java files now start with //@.
It wasn't always completely clear when the command was complete.
Recently I have discovered a way of creating true, immutable global identifiers (called global tnode indices or gti's for short). Version 4.0, due late this year or early next, will be the first version of Leo to take full advantage of the opportunities created by gti's.

Gti's will be a way of permanently and uniquely identifying every node (headline and body text) ever created by Leo, even when many people are working on the same .leo and derived files. For the first time, Leo will be able reliably to associate nodes in .leo files with nodes in derived files.

No previous version of Leo, including 3.7, has this ability, although that may not be so apparent to the casual user. As a work around in all previous versions of Leo, .leo files contain copies of all information in derived files. This "mirroring scheme" is needed so that clones in .leo files can be associated with their cloned counterparts in derived files.

While the mirroring scheme usually works well, it has some significant problems:

1. .leo files are much larger than they need to be.

2. Read errors occur if the derived files get out-of-synch with the information in the .leo file. All clone links get broken when read errors occur, which basically ruins the resulting .leo file. The only real way to recover is to use the Read Outline Only command.

3. Because out-of-synch conditions are so serious, it becomes a dicey proposition to save .leo files as backups; to create a reliable backup one must save the leo file along with all derived files.

Gti's solve all these problems:

1. .leo files no longer need to save a copy of all information in all derived files. Leo will write only the root node of @file trees to the outline, secure in the knowledge that it can reliably recreate the outline from the derived file.

2. The dreaded read errors will be impossible because there is no longer any data in the .leo file that can become out-of-synch with data in the derived files.

3. Because .leo files can never become out-of-synch with derived files, we can, for the first time, safely backup a project by creating a "fat" .leo file that contains all information in all derived files. Most .leo files will be "thin." Saving "fat" .leo files will only happen as the result of a new Save Backup command.

I am excited about Leo 4.0. It promises to revolutionize how people use Leo.
leo.py 3.7 October 9, 2002

Many improvements have been made to Leo. The highlights:

- Now works with Python 2.1. Previous versions required Python 2.2. - Many new user options, including user-definable shortcuts for all commands and colors for all parts of Leo's windows. As a result, it is now possible to use arrow keys as you desire. - Minimal support for Unicode Latin-1 (iso-8859-1) encoding. Better support is coming. - Improved handling of relative path names. - The @first directive allows lines to precede the opening @+leo sentinel line. - The @last directive allows lines to follow the closing @-leo sentinel line. - Better support for Perl+pod. - Leo now ends all lines with '\n' regardless of platform. - Leo is now compatible with Python 2.1. - Simplified sentinels reduce spurious CVS diffs. - Many other minor improvements and bug fixes.

Warning: Leo expects that all characters in derived files and .leo files are contained in the encoding specified by the xml_version_string option in leoConfig.txt. Characters will be garbled if this restriction is not followed. This restriction will be removed in the next release.

See the children of this node for full details.
The old code did not handle @comment /* */ in C mode because the */ given in the comment improperly terminated the scanning.

Changed find to rfind when scanning @@ sentinels.
Under certain circumstances # was not properly colored when coloring plain text.
single quote colorized text in plain text mode. This was due to missing parentheses.
The old code did not properly set the text selection in all cases.

This bug affected the Indent, Unindent, Extract and Extract Section.
Body text was being cleared in a node in an @file tree if the node contained a reference to a section defined in a grandchild. This was the first serious bug ever reported in the @file read logic.

The problem: Body text was being updated as the result of @+node sentinels rather than @+body sentinels. This was wrong, as extra @+node sentinels are often generated when no body text is generated. The result is that the body text was being cleared.

The fix: I simply moved the code that creates body text from the @+node logic to the @+body logic in scanText.
The new code resets the error count when reading each derived file, so errors in one file do not cascade to following derived files.
st_enter was not returning part numbers, which would have affected the Untangle command.
The old code undid the changes to only one headline of a group of cloned nodes. This was a serious bug because it would destroy the assumed equality between all cloned headlines.
The Find Previous command would get stuck once it found a match.
The original bug report:

"If you set the @tabwidth to something other than the Preference value, you'll see the body displayed appropriately. However, if you do a Ctrl-s to save the leo file, the body is redisplayed using the Preferences setting--of course, clicking on another node and then back to the original node displays with the correct tab setting again."
The old code remembered the insertion point only if it were set as the result of a keystroke.
This was too confusing to users. setup.py is intended only to create official distributions.
These improvements are listed in the approximate order of importance.
path_directive_creates_directories

Specifies whether to create a directory mentioned in an @file, @root node or @path directive if it does not exist.
relative_path_base_directory

The directory to be used as a prefix for <filename> in @path <filename> and @file <filename> and @root <filename> when <filename> is a relative path.

Valid values for this option:

"!" means relative to the location leo.py (the default). "." means relative to the location of the .leo file in the top window. An absolute path (in platform-dependent format).

Relative paths are not allowed: such paths would be dangerous because their meaning would depend on the changing value of the current working directory.
remove_sentinels_extension

Sets the string to be appended to file names resulting from the Remove Sentinels command. If the value starts with . the extension is appended to the original file name. Otherwise, the extension is appended before the file extension.

Example 1: File name x.y remove_sentinels_extension = _ns Result: x_ns.y

Example 2: File name x.y remove_sentinels_extension = .txt Result: x.y.txt
write_clone_indices

Indicates whether derived files will contain clone indices.

Please specify no clone indices if you are going to submit files to Leo's CVS site.
The following options now exist in the << Options for newly opened windows >> section of LeoConfig.leo.

initial_horizontal_secondary_ratio

Sets the ratio of outline pane size to log pane size when splitting the primary panes horizontally. The primary panes are the body pane and the secondary pane.

initial_vertical_secondary_ratio

Sets the ratio of tree pane size to body pane size when splitting the primary panes vertically. The primary panes are the body pane and the secondary pane.

The following options now exist in the << Window options >> section of LeoConfig.leo.

body_text_foreground_color body_text_background_color

The foreground and background colors of body text.

body_cursor_foreground_color body_cursor_background_color

The foreground and background colors for the cursor in body text.

headline_text_unselected_foreground_color headline_text_unselected_background_color

The foreground and background colors of unselected headline text. Both must be specified for either to take effect.

headline_text_selected_foreground_color headline_text_selected_background_color

The foreground and background colors of selected headline text that is not being edited. Both must be specified for either to take effect.

headline_text_editing_foreground_color headline_text_editing_background_color

The foreground and background colors of unselected headline text in a headline that is being edited. Both must be specified for either to take effect.

headline_text_editing_selection_foreground_color headline_text_editing_selection_background_color

The foreground and background colors of selected text headline text in a headline that is being edited. Both must be specified for either to take effect.

outline_pane_background_color

The background color of outline pane itself.

log_text_foreground_color log_text_background_color

The foreground and background colors of log text.
The << Keyboard shortcuts settings >> section of leoConfig.leo allows the user to specify keyboard shortcuts for all commands.

Notes:

1. There is one option for every command in Leo's menus; they won't be listed separately here.

2. For full documentation, see the

<< Keyboard shortcuts settings >> and << About keyboard shortcuts >>

sections of leoConfig.leo. The gist of this documentation is that you must use names known to Tk, and Leo also provides a few other names.

3. At most one shortcut may be associated with a command. If one really wanted to have two shortcuts, one would have to use two different command names. In particular, there is now only one shortcut for the Find Next command.
Leo checks all characters that are entered (via typing or via paste) into headline and body text to see whether they can be represented in the encoding specified by the xml_version_string setting in leoConfig.txt. Leo issues a message and disallows the entry of the character if it can't be represented in that encoding.

This draconian behavior shouldn't be too much of a nuisance, at least temporarily. Note that _all_ characters are valid in the UTF-8 encoding, so the present version of Leo will allow you to specify all characters if you must. But the Latin-1 (iso-8859-1) encoding, being a one-byte encoding, limits you to at most 256 separate characters.

In 3.8 I plan to allow you to use all Unicode characters, regardless of encoding, by using character references. This will require some reorganization of the present code, and I don't want to delay 3.7 to handle them.

Warning: The present code does not handle well files (.leo or derived files) that contain characters outside the specified encoding. At present, your best bet is to remove such characters for now. Hopefully 3.8 will do a much better job handling characters "foreign" to the specified encoding.
Leo now writes only \n (Linux newlines) in derived files and .leo files. This was done simply by opening derived files and .leo files in "wb" mode.
1. Leo now supports relative_path_base_directory and path_directive_creates_directories user options. See the discussion of those options in this document.

2. Leo now retains file modes when tangling and writing derived files.
Blank lines now precede and follow =pod and =cut.

Improvements made to @first and @last directives.
These were added so to resolve the debate about what the Esc key should do. The user can now bind Esc to either of these commands.
Leo no longer gives an error message when reading or writing cloned @file nodes.
Leo writes derived files a bit differently than before. These changes are compatible with the Borland version of Leo, provided that xml_version_string = UTF-8 in leoConfig.txt.

The changes:

1. Eliminated writing clone indices in derived files. This reduces the number of spurious changes reported by CVS. Leo now relies solely on information in .leo files to recreate clone indices. This is safe because read errors clear clone indices anyway. You can force clone indices to be written using the write_clone_indices user option in leoConfig.txt.

2. Removed extra newline following @+leo directive. This is part of an unfinished plan to eliminate all extra blank lines in derived files. It's not clear whether this plan will ever succeed.
Leo enables the Tangle and Untangle items in popup menus if any descendant of the selected node contains an @root node. Similarly, Leo enables the Read @file nodes and Write @file nodes items in popup menus if any descendant of the selected node contains an @file node.
leo.py 3.6 September 11, 2002

Highlights:

- Fixed a large number of bugs, especially bugs that appear only on Linux. - Leo now remembers the previous insertion point and location of the scrollbar when switching between nodes. - Added Match Brackets command. - Added support for MouseWheel (Linux only). - Added support for LaTex and PHP. - Improved all aspects of the Help menu. - Discovered a minor bug involving the Python (Idle) window and documented a workaround.

See the children of this node for full details.
The following minor bug can not easily be fixed because it involves an interaction between Leo and Idle.

After opening Idle with the Open Python Window command, opening another Leo window shows both the Leo window and a blank, square window. Closing either of the new windows may cause exceptions, either immediately or later.

The best workaround is simply not to open any new Leo windows after using the Open Python Window command.
os.rename can fail on some Linux systems.
When starting Leo with no arguments the 'NewHeadline' node was not displayed.
Changed:

bitmap_name = os.path.join(self.loadDir,"Icons\LeoApp.ico")

to:

bitmap_name = os.path.join(self.loadDir,"Icons","LeoApp.ico")
There were problems handling relative path names in @root and @path directives.
With Tk/Tcl 8.4, the Preferences window is empty (no buttons, fields, labels).

Tcl 8.4 complains about using "col" in the grid() calls.
This routine does a better job of checking the Tk version than the old code in leoApp.py
Only the last directive was in effect in @root trees. The new code allows node-by-node control.
This involved calling readlineForceUnixNewline instead of readline in the atFile:read logic.
How did I ever live without this?
The cursor now changes to an arrow when it moves over a link in the About Leo dialog.

The About Leo dialog now includes a build revision number.

Fixed problems with the Leo icon in the About Leo dialog.

Improved download dialog in Tutorial command.
CVS conflict files produce so many error messages that these errors are useless.
The Match Brackets command is enabled if the cursor is next to one of the following characters in the body pane:

( ) [ ] { } < >

This command looks for the matching character, searching backwards through the body text if the cursor is next to ) ] } or > and searching forward through the text otherwise. If the cursor is between two brackets the search is made for the bracket matching the leftmost bracket.

If a match is found, the entire range of characters delimited by the brackets is highlighted and the cursor is placed just to the left of the matching characters. Thus, executing this command twice highlights the range of matched characters without changing the cursor.
This code is due to Dave Hein.

Leo understands the following PHP keywords:

<?php, ?>, __CLASS__, __FILE__, __FUNCTION__, __LINE__, and, as, break, case, cfunction, class, const, continue, declare, default, do, else, elseif, enddeclare, endfor, endforeach, endif, endswitch, endwhile, eval, extends, for, foreach, function, global, if, new, old_function, or, static, switch, unset(), use, var, while, xor,

Leo does not yet color the following keywords containing():

array(), die(), echo(), empty(), exit(), include(), include_once(), isset(), list(), print(), require(), require_once(), return()
This code is due to Marcus A. Martin.

Leo understands the following LaTex keywords: capitalization is significant. For example, \vert produces a single vertical line and \Vert produces a double vertical line.

\@, \(, \), \{, \},

\acute, \addcontentsline, \addtocontents, \addtocounter, \address, \addtolength, \addvspace, \AE, \ae, \aleph, \alph, \angle, \appendix, \approx,\arabic, \arccos, \arcsin, \arctan, \ast, \author,

\b, \backmatter, \backslash, \bar, \baselineskip, \baselinestretch, \begin, \beta, \bezier, \bf, \bfseries, \bibitem, \bigcap, \bigcup, \bigodot, \bigoplus, \bigotimes, \bigskip, \biguplus, \bigvee, \bigwedge,\bmod, \boldmath, \Box, \breve, \bullet,

\c, \cal, \caption, \cdot, \cdots, \centering, \chapter, \check, \chi, \circ, \circle, \cite, \cleardoublepage, \clearpage, \cline,\closing, \clubsuit, \coprod, \copywright, \cos, \cosh, \cot, \coth,csc,

\d, \dag, \dashbox, \date, \ddag, \ddot, \ddots, \decl, \deg, \Delta, \delta, \depthits, \det, \DH, \dh, \Diamond, \diamondsuit, \dim, \div, \DJ, \dj, \documentclass, \documentstyle, \dot, \dotfil, \downarrow,

\ell, \em, \emph, \end, \enlargethispage, \ensuremath, \enumi, \enuii, \enumiii, \enuiv, \epsilon, \equation, \equiv, \eta, \example, \exists, \exp,

\fbox, \figure, \flat, \flushbottom, \fnsymbol, \footnote, \footnotemark, \fotenotesize, \footnotetext, \forall, \frac, \frame, \framebox, \frenchspacing, \frontmatter,

\Gamma, \gamma, \gcd, \geq, \gg, \grave, \guillemotleft, \guillemotright,\guilsinglleft, \guilsinglright,

\H, \hat, \hbar, \heartsuit, \heightits, \hfill, \hline, \hom, \hrulefill,\hspace, \huge,\Huge,\hyphenation

\Im, \imath, \include, includeonly, indent, \index, \inf, \infty, \input, \int, \iota,\it, \item, \itshape,

\jmath, \Join,

\k, \kappa, \ker, \kill,

\label, \Lambda, \lambda, \langle, \large, \Large, \LARGE, \LaTeX, \LaTeXe, \ldots, \leadsto, \left, \Leftarrow, \leftarrow, \lefteqn, \leq, \lg, \lhd, \lim, \liminf, \limsup, \line, \linebreak, \linethickness, \linewidth,\listfiles, \ll, \ln, \location, \log, \Longleftarrow, \longleftarrow, \Longrightarrow,longrightarrow,

\mainmatter, \makebox, \makeglossary, \makeindex,\maketitle, \markboth, \markright, \mathbf, \mathcal, \mathit, \mathnormal, \mathop, \mathrm, \mathsf, \mathtt, \max, \mbox, \mdseries, \medskip, \mho, \min, \mp, \mpfootnote, \mu, \multicolumn, \multiput,

\nabla, \natural, \nearrow, \neq, \newcommand, \newcounter, \newenvironment, \newfont, \newlength,\newline, \newpage, \newsavebox, \newtheorem, \NG, \ng, \nocite, \noindent, \nolinbreak, \nopagebreak, \normalsize, \not, \nu, nwarrow,

\Omega, \omega, \onecolumn, \oint, \opening, \oval, \overbrace, \overline,

\P, \page, \pagebreak, \pagenumbering, \pageref, \pagestyle, \par, \parbox,\paragraph, \parindent, \parskip, \part, \partial, \per, \Phi, \phi,\Pi, \pi, \pm, \pmod, \pounds, \prime, \printindex, \prod, \propto, \protext, \providecomamnd, \Psi,\psi, \put,

\qbezier, \quoteblbase, \quotesinglbase,

\r, \raggedbottom, \raggedleft, \raggedright, \raisebox, \rangle, \Re, \ref, \renewcommand, \renewenvironment, \rhd, \rho, \right, \Rightarrow,\rightarrow, \rm, \rmfamily, \Roman, \roman, \rule,

\s, \samepage, \savebox, \sbox, \sc, \scriptsize, \scshape, \searrow, \sec, \section, \setcounter, \setlength, \settowidth, \settodepth, \settoheight, \settowidth, \sf, \sffamily, \sharp, \shortstack, \Sigma, \sigma, \signature, \sim, \simeq, \sin, \sinh, \sl, \SLiTeX, \slshape, \small, \smallskip, \spadesuit, \sqrt, \sqsubset, \sqsupset, \SS, \stackrel, \star, \subsection, \subset, \subsubsection, \sum, \sup, \supressfloats, \surd, \swarrow,

\t, \table, \tableofcontents, \tabularnewline, \tan, \tanh, \tau, \telephone,\TeX, \textbf, \textbullet, \textcircled, \textcompworkmark,\textemdash, \textendash, \textexclamdown, \textheight, \textquestiondown, \textquoteblleft, \textquoteblright, \textquoteleft, \textperiod, \textquotebl, \textquoteright, \textmd, \textit, \textrm, \textsc, \textsl, \textsf, \textsuperscript, \texttt, \textup, \textvisiblespace, \textwidth, \TH, \th, \thanks, \thebibligraphy, \Theta, theta, \tilde, \thinlines, \thispagestyle, \times, \tiny, \title,\today, \totalheightits, \triangle, \tt, \ttfamily, \twocoloumn, \typeout, \typein,

\u, \underbrace, \underline, \unitlength, \unlhd, \unrhd, \Uparrow, \uparrow,\updownarrow, \upshape, \Upsilon, \upsilon, \usebox, \usecounter, \usepackage,

\v, \value, \varepsilon, \varphi, \varpi, \varrho, \varsigma, \vartheta, \vdots, \vec, \vector, \verb, \Vert, \vert, \vfill, \vline, \vphantom, \vspace,

\widehat, \widetilde, \widthits, \wp,

\Xi, \xi,

\zeta
leo.py 3.5 August 14, 2002

Highlights:

- Added new entries in the help menu. (Including a link to Joe Orr's excellent ScreenBook tutorial). - Added the importFiles script in leoImport.py. - Added configuration options for horizontal scrollbars. - Added better warnings for read-only files. - Removed all '\r' when reading derived files. - Fixed crasher in Read Outline Only command. - Fixed crasher when leoConfig.txt did not exist. - Many small improvements and bug fixes.
This may be the cause of truncated leoConfig.txt files on Linux.
Removed '\r' characters when reading. The write logic is unchanged.
Relative paths should not set the global default paths. Instead, the relative path is concatenated to the global default path when the file is opened.
Added log_pane_wraps and outline_pane_scrolls_horizontally configuration settings.
Note: b4 contains a fix to b3 in this area: for writing, we must first test whether the file exists. Otherwise we may get a false indication that the (non-existent) file is read-only.
Added the importFiles script in leoImport.py. Use this script as follows:

- Select the node under which you want the imported files to appear. - Open the Python window within Leo. - Type the following in the Python window:

import leoImport dir = "c:/prog/test" # or some other directory type = ".py" # Type of files you want to import. leoImport.importFiles(dir,type)

If you want to import all files in a directory, replace the last line with:

leoImport.importFiles(dir)
leo.py 3.4 August 11, 2002

This release contains many small improvements and bug fixes. The highlights:

- Fixed several crashers involving Unicode. - The Show Invisibles command now makes blanks and tabs look much better. - Created leoConfig.leo, from which leoConfig.txt is now derived. - Added save_clears_undo_buffer configuration option. - Fixed a large number of problems with the configuration code. - The usual minor improvements and bug fixes.

See the children of this node for full details.
The problem is that the ratio is saved in the .leo file and the split direction is not. So if leoConfig.txt is read-only you the Toggle Split Direction command will permanently change the body-outline ratio _without_ permanently changing the split direction itself.

This basically sucks, and here are my reasons:

1. I do not want to be adding more options to .leo files; the whole idea of leoConfig.txt is to move in the opposite direction.

2. You can make everything work more like you would expect by making leoConfig.txt read-write.

3. Especially in the case of the split direction, I expect people to have strong preferences one way or the other, so even if leoConfig.txt is read-only it shouldn't be too odious to pick a split direction and live with it.
The undo buffer creates a lot of strings. On some system this may be a problem. If save_clears_undo_buffer = 1 the Save command (and only the Save command) will clear the undo buffer.
The new spelling is to limit_directory_search_extension. Note that this affects the valid entries in leoConfig.txt.
This allows us to create leoConfig.txt more easily, and provides a safe place to permanently store comments when read-write mode is on.
If a setting was missing or "ignore" it could never be set! This no doubt could have caused a wide variety of symptoms. In particular, in the distributed leoConfig.txt file it meant that settings for "default" fonts and sizes were never updated!
The new code properly deletes previous entries regardless of case or path separators.
There were a couple of bugs here.

Note that the ratio (whichever the direction) is stored in the .leo file. The initial_splitter_orientation setting in leoConfig.txt applies to _all_ files. The initial_vertical_ratio and the corresponding initial_horizontal_ratio apply only to new files, so are essentially useless.

Yes, this is pretty stupid; it's the result of not wanting to add more stuff to Leo's file format.
leo.py 3.1 contains Python code that may be of interest to some Python programmers. All Python files are derived from LeoPy.leo.

See the children of this node for details.
This script does much of the grunt work of converting from C/C++ syntax to Python syntax. It was surprisingly effective in converting Leo from C++ to Python. These scripts don't need to be perfect to save a _lot_ of work. And of course you can always add your own improvements...

As written, the script converts an entire Leo tree. It would be easy to write an entry that would convert plain text files, but it's probably best to import the files to be converted into Leo first. That way the slow algorithms in c2py.py will work on smaller pieces of text.
This code gathers and prints static statistics about Python bytecode.
The file leoUtils.py contains some small Tkinter utilities:

w,h,x,y = get_window_info(top) returns the width, height, x and y positions of the Tkinter window top.

center_dialog(top) centers the Tkinter window top on the screen.

w,f = create_labeled_frame(parent...) creates a labeled Tkinter window as a child of parent. The caller packs widgets into f to create the frame.

leoUtils.py contains many other routines including an Python version of the Sherlock tracing package.
leoFontPanel.py puts up a Font dialog. This dialog dispenses with the typical "sample" pane and instead changes text immediately directly on the screen. Comes with Ok, Cancel and Revert buttons. IMO, this dialog is much better than the sample Tk/Tkinter font dialogs available on the web.
leoColor.py contains code to syntax color Tk.Text widgets for a variety of languages. Supporting a new language here is mostly a matter of adding another table of keywords.
Leo supports powerful outlining features, including clones. Clones are challenging to implement, to say the least. The vnode and tnode classes, defined in leoNodes.py, represent the underlying data. vnodes represent nodes on the screen. vnodes may share text, the tnode class is the "unit of sharing" of such text. The leoTree class draws the tree and handles events, including dragging nodes around the screen. The Commands class calls the vnode, tnode and leoTree classes to handle menu commands. In Smalltalk's model/view/controller terminology, the vnode and tnode classes are model class, the leoTree class is a view class, and the Commands class is a controller class.
Now at last it is clear why Leo hasn't been writing derived files affected by clones. It's not enough to mark v dirty. We must mark all the cloned nodes of v's tree dirty as well.

However, we only need do this when a node is deleted, and we definitely do _not_ want to do this otherwise, for that would mark far too many nodes dirty. To get around this, we leave v.setDirty() as it was, and use the new code only in v.setDirtyDeleted.

Note that the undo and redo cases handle this automatically because they call c.doDelete.

So now we can state a rule that should not ever be broken: after doing a Save command, a Write @file Nodes command should always report "unchanged" for all files.
Added setRevertVars to update revert settings. This is called from __init__ and onOk.
Changed idle_body_key and idle_head_key, leoTangle::os and tnode::setTnodeText.

We must remove backticks from messages that might contain unicode characters so they will print properly. There were only a few instances, and they are all error messages that hardly ever get executed, so I hope I was careful putting them in. I should be able to find them all by looking for '"'.
Repeated double-clicking (without intervening single-click) caused the selection to move to the left.
This is consistent with what the Import commands do for the other file types. It's also much safer.
This makes selected text look much better and makes Show Invisibles look much better as well.

This was not easy to do. Apparently tag settings interfere with the Tk.Text settings. I have not found a way to specify the selectbackground color for tags. The only way I could get things to work is define whitespace tags only when in showInvisibles mode.
.tmp files disappear On Windows XP after Leo exits!
leo.py 3.3 August 3, 2002

This version of Leo:

- Added support for Unicode. - Improved the Import commands. - Fixed numerous bugs related to configuration settings. - Fixed the "Javadoc" bug and several latent bugs related to it.

See the children of this node for details.

Edward K. Ream
It is now possible to use non-Ascii characters in Leo!

Leo uses the xml_version_string setting to encode Unicode characters in .leo files. This will be UTF-8 by default. I've also very briefly tested ISO-8859-1.

I am a complete Unicode ignoramus. It seemed trivial to add Unicode support to Leo, and if there are any fine points that should have been considered I no doubt did not consider them...
The Import command now does a better job of removing excess leading whitespace.

When importing .java files, Leo now preserves newlines in leading block comments. This makes the typical weird Java comments look better. For example,

/** This is a typical, * brain-dead, * Java comment. */

Now gets rendered as

@ * This is a typical * brain-dead, * Java comment. @c

The comment will be reconstituted properly when rewritten.
This never happened before because all languages had either 1 or 3 delims. But Java now has only 2 delims to force block comments.
Leo should now handle negative tab widths properly.
- Negative tab widths are now honored properly.

- Made 'additional_body_text_border' setting functional.

- Made 'body_pane_wraps' setting functional.

- There was a bug that made the following non-functional.

"read_only" "xml_version_string" "limit_count" "body_pane_wraps"

That is, only the default settings in leoConfig.py were used, not the settings in leoConfig.txt.

- The old code did not use the "page_width" and "tab_width" settings from leoConfig.txt.
leo.py 3.2 July 30, 2002

This version generalizes the @others directive, improves the Import command and fixes several bugs. See the children of this node for full details.

The highlights:

- Nested @others directives are now valid, an important improvement. This simplifies files that define more than one class. - Improved the Import command and squashed several bugs lurking there. - Made the various Go commands in the Outline-Move/Select menu functional by reassigning keyboard shorts - Fixed a crasher in the Prefs Panel. - Fixed numerous bugs in the Set Colors command. - Fixed syntax coloring of C strings that span multiple lines. - The usual minor improvements and bug fixes.

Edward K. Ream
Nested @others directives are now valid, even when no named node intervenes. This is a significant enhancement to Leo because it is now easier to define multiple classes in a single file. The leoNode.py file also uses nested @others directives.

The outline shown in the child of this node shows the general idea.

The Import command uses nested @others to great effect in Python files containing many classes. For example, try importing the file Python/Lib/Compiler/ast.py.
@color @ignore

# This is the "outer" @others @others
class a: # This is an "inner" @others. No named node intervenes. @others
def one(): pass
def two(): pass
class b: # This is an "inner" @others. No named node intervenes. @others
def one(): pass
def two(): pass
The Import command creates nested @others directives when parsing Python classes.

Fixed two bugs in the Import command:

1. The Import command now properly places the first @others directive of Python files. Previously the @others directive was placed before section references, so code could be rearranged.

2. The Import command now properly handles all C preprocessor directives. Previously there were problems handling the #ifndef directive which could ruin imports.

Two other minor improvements:

1. This is reasonable: we don't wan't people generating files from imported files unless they take some positive action.

2. The Import command now checks that different branches of #if, #else, #endif directives have the same net number of braces, and warns if they do not. This logic was inserted while trying to fix bug #2 above.
It's too confusing to have arrow keys mean different things in different panes.

For one thing, we want to leave the focus in the body pane after the first click in the outline pane, but that means that the arrow keys must still be functional in the body pane!

Alas, all the various combinations of key bindings of arrow keys appear to do something; there are none left to use for moving around in the outline pane. So we are stuck with poor shortcuts.
Leo could sometimes crash when the user selected Cancel in the Preferences panel.
There were too many problems in the old color panel.

- Completely revised the Revert logic in the main Color panel. - The color name picker now reverts properly. - Color names and color swatches are now properly updated in all cases, so there is no need to write color values to the log window. - Eliminate quotation marks around color names and values. - The color picker now shows the value of the present color, not the revert color. - Increased the width of name buttons to handle long color names.
Thanks to Thomas Guettler for suggesting this.
This script uses the dis module to print static statistics about Python bytecode. Of no use to anyone but me.
leo.py 3.1 July 20, 2002

This version fixes a blunder that affects only leo.py 3.0. I recommend that all users of 3.0 upgrade to this version.

With this release Leo's to-do list is now empty! I shall fix bugs as they are reported. I'll add new features only if convinced that they contribute significantly to Leo.

The highlights:

- Fixed a blunder: Leo 3.0 did nothing when it was opened directly from leo.py. (Opening leo using openLeo.py did work.) - Created a compare panel to control scripts in leoCompare.py. - Added many new settings in leoConfig.txt to initialize the compare panel. - The FAQ tells how to add support for new languages. (These instructions also appear in the "Notes/How To" section in LeoPy.leo) - The usual minor improvements and bug fixes.

Edward K. Ream
The file comparison window helps people verify that imported files are, in fact, precisely equivalent to the original files.
Here are the new settings in leoCompare.txt:

# Initial settings of the Compare panel. # These correspond to the keyword parameters of the leoCompare constructor. # Exception: there are no keywords for compare file names in the constructor.

[compare options]

# ----- Options specifying files for the Compare panel.

compare_file_1 = c:/prog/test/compareTest1/file1.txt # Path to the first file or directory to be compared. # Directory compares ignore a filename part of the path, if present. # E.g., c:/directory1/spam.py is valid for directory compares.

compare_file_2 = c:/prog/test/compareTest2/file2.txt # Path to the second file or directory to be compared. # Directory compares ignore a filename part of the path, if present. # E.g., c:/directory2/spam.py is valid for directory compares

output_file = c:/prog/test/compareResults.txt # Path to the output file. # Leo will silently write to this file, regardless of whether it already exists. # Leo will write to the log pane if this path is empty or invalid.

append_output_to_output_file = 0 # 0: Replace output file with results of compare. # 1: Append output to output file.

# ----- Options related to directory compares. # These options has no effect when comparing files.

limit_directory_search_extenstion = .py # Limit directory searches to files with the given file extension. # Examples: # None Compare all files when comparing directories. # .py Compare .py files when comparing directories.

# ----- Options related to file compares. # These options have no effect when comparing directories.

ignore_blank_lines = 1 # 1: Ignore blanks lines when comparing files.

ignore_first_line_of_file_1 = 0 # 1: Ignore the first line of compare_file_1 when comparing files.

ignore_first_line_of_file_2 = 0 # 1: Ignore the first line of compare_file_2 when comparing files.

ignore_interior_whitespace = 0 # 1: Ignore whitespace after the leading whitespace of a line when comparing files.

ignore_leading_whitespace = 0 # 1: Ignore leading whitespace of each line when comparing files. # Not recommended when comparing .py files.

ignore_sentinel_lines = 0 # 1: Ignore sentinel lines when comparing files. # Leo sets sentinel comment delimiters from the first line of each file. # This option has no effect if the first line is not a @+leo line.

# ----- Options affecting how Leo shows the results of file compares. # (Leo gathers statistics regardless of these options.)

limit_count = 9 # 0: Show lines regardless of the number of mismatches. # n: Stop showing lines after n mismatches.

make_whitespace_visible = 0 # 1: Show blanks as [ ] and tabs as [t]

print_both_lines_for_matches = 0 # 0: Print only the line of compare_file_1 when showing matching lines. # 1: Print lines of both files when showing matching lines.

print_matching_lines = 0 # 1: Print lines that match using the print_both_lines_for_matches option.

print_mismatching_lines = 1 # 1: Print lines that do not compare equal to each other.

print_trailing_lines = 1 # 1: Print lines all lines in one file after an end-of-file is seen on the other file.
The new rules allow leo.py 3.1 to read and write .leo files more like leo.py 2.x when there is no leoConfig.txt file. The scheme used in leo.py 3.0 meant that preferences were _never_ written to .leo files. It's advantage was that all defaults were specified in:

leoConfig.<< define default tables for settings >>

I think the present scheme is more natural, but we shall see...

In effect, Leo sets and gets various options in the following order of precedence:

1. Use explicit settings in leoConfig.txt if they exist.

2. Use defaults for leoConfig.txt, but only if leoConfig.txt exists. These defaults are found in:

leoConfig.<< define default tables for settings >>

3. Use settings in .leo files if leoConfig.txt does not exist.

4. If leoConfig.txt does not exist, and the .leo file does not specify a setting, use hard-coded settings in the various classes, just as leo.py 2.x did.
The @pagewidth, @tabwidth and @language directives could not have worked while tangling. Apparently nobody has every used these directives in @root trees!
The Flatten Outline command must use an escape convention so that it can distinguish between the "+" and "-" characters that denote a headline and any "+" and "-" characters that start a line of body text.

The old version of Flatten Outline inserted a backspace before _all_ "+", "-" and backspace characters. The new version of Flatten Outline inserts a backspace before such characters only if they are the first non-whitespace character of a line.

This change affects the "file format" used by the Import Flattened Outline command. If you import a file flattened with the old version of Flatten Outline, the new Import Flattened Outline will remove the inserted backspace only if it is the first non-whitespace character of the line. In practice, this is unlikely to be a problem: you could just manually convert "\\", "\+" and "\-" to "\", "+" and "-" throughout the imported file.
The Open Python Window command now attempts to add IDLE's location to sys.path if import idle fails.

Bernhard Mulder contributed the code that made this improvement possible.

leo.py 3.0 July 16, 2002

This version is called 3.0 because it can optionally produce files that can NOT be read by the leo.py 2.x or the Borland version of Leo. However, by default, leo.py 3.0 DOES produce files that all previous versions of Leo can read.

See the children of this node for full details. The highlights:

- Support for many user options stored in leoConfig.txt, including, among others, fonts in all panes, colors for syntax coloring and default window size and position. - Support for .leo files with XML types like "ISO-8859-1", controlled by a user option. Note: by default, Leo writes files compatible with previous versions of Leo. - Powerful new Color and Font pickers, fully connected to user options. - Added Toggle Split Direction command, under control of user options. - Added autoscrolling in the outline pane. - Windows open at the position in which they were saved. - The size and position of new windows can be controlled with user options. - Eliminated drawing problems while opening files. - Improved syntax coloring for @comment plain. - The Convert All Blanks and Convert All Tabs commands are now undoable. - Leo warns and aborts if Python 2.2 or above is not running. - The usual bug fixes.

At least one more version of leo.py is planned.
You now have a choice: you can configure Leo to please previous versions of Leo or to please XML parsers:

Leo now uses the xml_version_string configuration setting, if present, to override the UTF-8 setting used in all previous versions of Leo. The default value of this setting is UTF-8, so by default leo.py will write files that may be read by any previous version of leo.py or the Borland version of Leo.

However, xml_version_string = ISO-8859-1 will produce .leo files that are more acceptable to XML parsers when those .leo files contain Unicode characters that are not found in the UTF-8 (Ascii) character set. In any event, the choice of whether to please previous versions of Leo or XML parser is completely up to you.

If the setting does not exist, whatever value is present in the .leo file will be written when the .leo file is written. For new files, a value of UTF-8 will be used when this setting is not present.

Notice that this also affects what is written to the clipboard.
This version supports many more options than before. See leoConfig.txt for the full list.

Leo looks for leoConfig.txt in the same places as in leo.py 2.5. If Leo does not find leoConfig.txt, This version will use defaults specified in tables defined in the section << define default tables for settings >> in leoConfig.py. So it is now convenient to change settings in leo.py itself as well as in leoConfig.txt.
Including the split direction and split ration.

Leo now uses all configuration settings from leoConfig.txt.
If you drag a headline above or below the outline pane the outline pane will scroll automatically. As before, Leo will cancel the drag if you release a headline anywhere but over another headline's icon.
You can specify colors for each syntax coloring construct using a color wheel or by choosing one of the standard Tk color names. When a color becomes active Leo writes its value or color name to the log pane for your reference. This is useful when setting coloring options in leoConfig.txt.
Using this panel should be self-explanatory (what you see is what you get) with the following exceptions:

1. When a font becomes "active", the new font appears in the panes whose check boxes are selected. A font becomes active when you double-click its name, or check or uncheck any checkbox.

It would be much better to have a font become active if you just select its name. Alas, that is not possible due to a well-known gap in the Tk.Listbox class.

2. Font sizes must be greater than 0 and less than 100 for them to become in effect.

3. Choosing very _small_ values for font sizes may cause Leo's window to _expand_ its width.

4. When you choose OK or Cancel Leo writes the fonts presently active in each pane to the log pane for your reference. This is useful when setting font options in leoConfig.txt.
This was a supremely irritating bug.
This command switches between vertical and horizontal orientations of the Leo window. In the vertical orientation, the body pane appears below the pane containing the outline and log panes. In the horizontal orientation, the body pane appears to the left the pane containing the outline and log panes.

leoConfig.txt specifies the default direction. If leoConfig.txt does not exist, or does not specify the direction, the "vertical" orientation is used, just as in previous versions.

By default, the ratio of pane outline pane to the body pane is 0.5 in the vertical orientation and 0.3 in the horizontal orientation. These two ratios may be changed using leoConfig.txt.
The @comment directive no longer suppresses syntax coloring. Leo directives (but not doc parts) are colored when @language plain is in effect. The user can, as always, suppress all coloring by using @nocolor. The new rules are much more natural than the old, and much less confusing.
The old colorer colored all Leo directives blue, the same color as keywords in whatever language is current. I think the distinction between Leo directives and language keywords is useful. Of course, you can control syntax coloring yourself by altering leoConfig.txt.
This message is printed to the console, not the log pane. On windows, this may not always be visible.
Leo will convert underscores in the @comment directives to significant spaces. For example,

@comment REM_

causes the comment delimiter to be "REM " (Note the trailing space).
This happened sometimes when using @comment.
Leo directives were mostly being colored using the colors for keywords. This didn't show up because both were colored blue.
Only one window now appears when opening a .leo file, and the window is completely drawn before anything gets written to the log pane.
Added new code for Convert All Blanks and Convert All Tabs.

Fixed a bug that resulted in Convert Tabs being undoable.
This makes the panel much more convenient to use.
leo.py version 2.5.1 July 7, 2002

2.5.1 This version corrects crashers that affect undo/redo move commands. Version 2.5 has been withdrawn. Anyone using 2.5 should use 2.5.1 instead.

This is a major step forward to completing leo.py. It adds significant new features and corrects many bugs. Full details are found in the children of this node. Here are the highlights, in approximate order of importance:

1. Leo supports tab widths properly, and negative tab widths cause Leo to convert tabs to blanks as you type. Three new commands appear in the Edit Body menu: Convert Tabs, Convert All Tabs and Convert All Blanks. Convert All Tabs and Convert All Spaces convert the entire selected tree.

2. Leo now allows you to override selected preferences using a configuration file called leoConfig.txt. Leo acts as before if this file does not exist. An option in leoConfig.txt specifies whether leoConfig.txt is read-only.

3. The Preferences panel is now a modal dialog containing Ok, Cancel and Revert buttons. This makes it clear what preferences are being set.

4. At long last, cut and paste work properly in all situations. You can cut and paste between Leo and other applications, or between two different copies of Leo.

5. Added the Recent Files submenu to the File menu. Very nice to have.

6. Fixed a number of bugs, including several crashers. Fixed several bugs in the Import commands. Leo will no longer abort reading if it detects an invalid directory name in the Default Tangle Directory in the Preferences panel.

leo.py is almost complete. The only remaining tasks on my list are:

1. Make the Set Font... and Set Colors... commands functional. This will be easy now that leoConfig.txt exists. 2. Fix the Javadoc bug.
The following are listed in the approximate order of their importance. The marked nodes are particularly important.
Gary Herron suggested this changes.
These commands convert an entire tree.
This command converts leading tabs to blanks in a single node.
Previous versions of Leo ignored the tab width field! This field is now fully functional.
Leo converts tabs to blanks as you type when a negative tab width is specified.
The Preferences panel is now a modal dialog. This solves a number of problems, both for the implementation and for the user. It is now completely clear which preferences are being set, viz., the preferences for the window on top. In addition, the Prefs panel now shows the name of the window whose preferences are to be set.

The Prefs panel now contains OK, Cancel and Revert buttons. These are useful, and they are possible only because we have a modal dialog.
You may now cut and paste between Leo and other apps, or between two different copies of Leo.
The elements of this submenu are saved in leoConfig.txt, if present.

Leo adds files to this submenu even if leoConfig.txt is missing or read-only, but those additions will not be remembered unless leoConfig.txt is present and writable.
1. Importing the following script

class C: def __init__(self): pass

created an outline with class C appearing in two nodes.

2. Importing the following file created orphan nodes for declaration.

import sys # This line becomes an orphaned node class C: xyz = 'xyz' # This line becomes an orphaned node def __init__(self): pass

3. Importing a Python file containing classes without methods resulted in nested classes. There is still a minor problem: The following

class A: pass

puts the "pass" in a section called << class A declarations >>. This is not easy to fix: you will have to correct it by hand.

4. Improved the Import to @root command. Added @root <filename> to the body text of the root of tree and eliminated @language and @others directives.
This is important, because it means that invalid entries in, say, the Default Tangle Directory preference will no longer abort an attempted read.
This would happen if the Default Tangle Directory did not exist in the Prefs panel.
This command always crashed, perhaps due to a reversion.
The crash happened if the Import command was executed in a new, unsaved file.

The fix was to the directory logic in import.scanAllDirectives.
The bug involves only the clone mark itself: nodes have always been properly joined.
Gary Herron reported this bug and told me how to fix it. This change is to the default file extension field of file dialogs. It seems to have no effect on Windows. Apparently this makes a difference in Linux...
These commands no longer change the file name associated with a window if the user cancels the Save or Save As dialog.
This involved changing the documentation for the Demote, Insert Headline, Extract Headline, Syntax Coloring... and Font... commands. Removed documentation for the Open/Close Log Window command.
leo.py version 2.4 June 20, 2002

This version fixes some annoying bugs and adds some nice features. The children of this node contain full details.

1. Leo now properly highlights the headline of a newly created node. Similarly, the Edit Headline command (control-H) now works. Double-clicking in a headline now does what you would expect: it selects the word under the cursor. Similarly, triple-clicking now selects the entire headline. Also fixes several other minor bugs.

2. Drag and drop. You can now reorganize outlines by dragging nodes around. You must drag from a node's headline and release on another node's headline. See a child of this node for complete details.

3. You can now open .leo files in leo.py by double clicking on .leo files. You must associate leo.py with .leo files. See a child of this node for detailed instructions about how to do this.

4. Improves error recovery when there are errors writing .leo files.

5. Updates this file to match the documentation of Leo's web site. At long last, Leo's documentation is complete.
1. Fixed a bug in app.finishCreate that caused Leo to take an exception on MacOS X.

2. Leo now properly highlights the headline of a newly created node. Similarly, the Edit Headline command (control-H) now works properly.

3. Removed a useless assert in st_enter_root_name that could fail under unusual circumstances.
When writing a .leo file, say f.leo, Leo now attempts to create a backup file called f.leo.back. If there is an error while writing f.leo, Leo will restore f.leo from f.leo.back. Note that Leo will write derived files correctly even when there is an error writing the .leo file.
New in leo.py v2.4: You may drag an node (including all its descendants) from one place to another in an outline. To start a drag, press the main (left) mouse button while the cursor is over the icon for a node. The cursor will change to a hand icon. If you release the mouse button while the hand cursor is above the icon for another node, Leo will move the dragged node after that node. If you release the mouse button when the hand cursor is not over an icon, Leo will print "not moved" and leave the outline pane as it is. This can result in the dragged node not being visible on the screen, but it seems less alarming not to force the current node to become visible as that would undo any scrolling that has just been done.

New in leo.py 3.0: If you drag outside the outline pane, the outline pane will scroll automatically.

Leo scrolls the outline pane as the result of mouse-moved events, so to continue scrolling you must keep moving the mouse. I experimented with scrolling the outline pane whenever the cursor is dragged outside it, but the results were not good. There was a noticeable delay between releasing the cursors and halting the scrolling. The present code is simpler and more likely to work on all platforms.

Leo only allows dragging from one icon to another. In particular, you can't move a node to the first child of another node unless that node is already expanded. I experimented with automatically open nodes when the cursor moves over an unexpanded node with children. However, this was confusing and alarming. It seems best to expand and contract nodes explicitly.
leo.py version 2.3 June 5, 2002

This version fixes a minor problem with Leo.

1. The code that reads and writes @file nodes now uses the directory containing the .leo file as a default when the Default Tangle Directory setting is empty in the Preferences panel. This is a reasonable default because derived files are most often created in the same directory as the .leo file. BTW, the Tangle and Untangle commands have used this convention for a long time.

Note: This default allows us to distribute LeoPy.leo without specifying a directory in the Preferences Panel.
leo.py version 2.2 June 1, 2002

The version fixes two bugs that happen rarely and can cause loss of data when they do happen.

1. In certain circumstances leo.py v2.1 would delete most of an outline when a node was moved in front of the previous root node!

2. All previous versions of leo.py will crash when saving body text containing unicode characters. This could occur as the result of cutting and pasting text from another application into the body pane. Leo.py now writes body text containing unicode characters using Python's u-prefixed notation. That is, the body text is written as: u'escaped_text' where escaped text replaces unicode characters not in the ascii character set by escape sequences of the form \uxxxx. The result contains nothing but ascii characters, so leo.py will have no problem reading it. Naturally, compilers and other tools may not understand Python's notation, so you may have to convert escaped text to something that your tools can understand.

3. This file, LeoDocs.leo, now more closely matches the documentation on Leo's web site.
leo.py version 2.1 May 16, 2002

This version of Leo adds Import and Export commands and fixes several bugs:

1. All Import and Export commands now work. Several of these commands are found only in Leo.py. Some of these commands may be of beta quality.

I use Import commands mainly for studying other people's code. Be wary of generating source files from trees generated by the Import commands.

2. Fixed a bug that caused Leo to crash when a node was moved up in front of the previous root node.

3. Fixed several bugs in the syntax colorer. One of these bugs caused Leo to crash when handling CWEB.

4. Leo now colors strings green.
I use Import commands mainly for studying other people's code. Be wary of generating source files from trees generated by the Import commands.

The Remove Sentinels command can "clean" files for publication or walkthroughs. You can also use the Remove Sentinels command to prepare files for comparisons. For example, one could study a file, say f.py, as follows:

1. Use the Import Files command to create an @file tree, say @file f2.py, for study. Changing the name to f2.py ensures that saving the .leo file won't destroy the original file.

2. Use the Remove Sentinels command to create a file f3.py. Use a file comparison program to ensure that f1.py is identical to f3.py.
Fixed several bugs that caused Leo to hang when moving an outline up before the previous root node.
Fixed a bug that caused Leo to hang when syntax coloring noweb code with the CWEB syntax colorer.

The syntax colorizer now handles Python triple strings and C preprocessor directives properly.

Leo now colors strings with the same green used by IDLE. I think this color looks very good.

Improved the syntax coloring for CWEB.
leo.py version 2.0 March 4, 2002

leo.py v2.0 and Borland Leo v2.6 are being released simultaneously. I urge all users of Leo to upgrade to one or both of these versions. Note: the Untangle commands of both v2.0 and v2.6 should be considered beta quality. Please report any problems with Untangle ASAP.

This is an important milestone in Leo's history, for several reasons:

1. For the first time, leo.py (v2.0) and the Borland Leo (v2.6) are functionally identical. In particular, their respective Tangle commands produce identical output.

2. All "mission critical" aspects of leo.py are now complete: only the Import commands remain unfinished. leo.py v2.0 adds unlimited Undo/Redo, Untangle and full syntax coloring. Unlimited Undo/Redo are reason enough to upgrade to v2.0.

3. leo.py v2.0 and Borland Leo v2.6 introduce an optimized format for derived files: both versions remove blank lines from between sentinel lines. This is an upward compatible change in the format of derived files: leo.py v2.0 and Borland Leo v2.6 can read derived files from all previous versions of Leo, but previous versions of Leo can not read derived files without blanks lines between sentinels.

See the children of this node for full details.
leo.py v2.0 optionally can remove blanks from between sentinel lines in derived files. This is an upward compatible change in the format of derived files: leo.py v2.0 can read derived files from all previous versions of Leo, but previous versions of Leo can not read derived files without blanks lines.

Removing blank lines requires a new kind of sentinel, the "verbatimAfterRef" sentinel. This allows Leo to handle comments following section references that would otherwise be treated as sentinels themselves. For example:

<< section >> #+others

Leo removes blanks lines between sentinels by default. To cause Leo not to remove blank lines do the following. In the section called << initialize atFile ivars >> in leoAtFile.py, change:

self.suppress_newlines = true to self.suppress_newlines = false

Note: leo.py v2.0 can read derived files without blank lines between sentinels regardless of the setting of self.suppress_newlines.
leo.py supports unlimited Undo and Redo. All outline operations and all typing operations may be undone and redone. Undo state persists even after Saves. Even the Change All command is undoable. Only the "Read @file Nodes" command is undoable; it clears the entire undo state. This command raises a dialog to allow the user to cancel.

Think of the actions that may be Undone or Redone as a string of beads. A "bead pointer" points to the present bead. Performing an operation creates a new bead after the present bead and removes all following beads. Undoing an operation moves the bead pointer backwards; redoing an operation moves the bead pointer forwards. The Undo command is disabled when the bead pointer moves in front of the first bead; the Redo command is disabled when the bead pointer points to the last bead.

leo.py syntax colors all languages mentioned in the Preferences Panel.
1. Show Invisibles command works in @nocolor mode.

2. @unit, @root, @nocolor and @color now terminate doc parts.

3. Three characters were colored blue at the start of a section def in:

<<name>>=

This didn't show up if there is a space after the <<.
Leo adds extra space at the end of headlines so that headlines now have enough room to show all text. This works around an apparent Tk bug.
The Untangle command is beta quality. Please make backups before untangling.
leo.py v2.0 fixes two bugs present in Borland v2.5 and fixed in Borland v2.6:

1. Untangle did not work properly for languages like Perl and Python that do not have block comments.

2. Untangle did not recognize @ on a line by itself as the start of a doc part.
@c now works the same as @code. This makes the syntax colorers agree with what the Tangle commands actually do. Previously, the syntax colorers indicated that everything following an @c was code, while the Tangle commands placed everything following an @c in the doc part!
Previous versions of untangle silently trimmed trailing lines from all nodes, which seems rude.
The font size for code text is now 12 on Linux.

Changed code so that the path to the Icons folder is computed correctly on all platforms.
leo.py version 1.0 February 10, 2002

Version 1.0 adds many new features and fixes several bugs. I recommend that all users of leo.py upgrade to this version. This version deserves the number 1.0; it has no known bugs.

Here are the highlights of this release. See the children of this node for details.

1. Fixed bugs: the Tangle All and Tangle Marked commands didn't work at all. Fixed several bugs in the Find and Change commands. The "Suboutline Only" option now applies to the Search All and Change All commands. Settings in the Preferences Panel now "stick" properly to the currently selected window. Fixed many minor bugs.

2. leo.py now re-marks @file trees as dirty if errors are found while writing those trees. This makes it difficult to write derived files that will be out-of-synch when read again.

3. New commands and features: Added the Revert, Select All, Delete, Sort Children, Sort Siblings, Contract Parent (very useful!) and Toggle Active Pane commands, and all commands in the Edit Body menu, and all the Go To commands in the Move/Select menu. The Show Invisibles commands is ugly, and useful nonetheless.

The Edit Body commands work much more reliably than the similar commands in the Borland version of Leo. You may now specify Python scripts rather than .bat files in the Preferences panel. Added a way, albeit clumsy, to cut and paste nodes between Borland Leo and leo.py. When syntax coloring Python text, leo.py increments the auto-indentation by one tab after a trailing colon. This provides a subtle reminder to add such colons.

4. leo.py handles events and shortcuts properly. The shortcut for the Insert Node command is now Control-I, as it is in the Borland version of Leo. Worked around a TK bug that prevented double-clicks from properly selecting words. leo.py enables and disables all menu items properly.
Removed the Print and Page setup commands because Tk provides no support for printing. This is not significant: we can use the export commands to create text files. These text files can then be formatted and printed as desired.

The following commands remain unfinished. They will be finished in this order:

1. Untangle commands.

2. Import/Export commands.

3. Unlimited Undo and Redo.

4. Toggle Split Direction, Cascade and Recent Windows commands.

5. Font Panel and Syntax Coloring commands.
It should be possible to cut a node or tree in Borland Leo and paste it using the Copy Node command in leo.py. At present, cutting and pasting trees between applications can only be done indirectly. Do this:

1. Copy the tree in Borland Leo using the Copy Node or Cut Node command. 2. Paste the tree into empty body text of leo.py using the Paste command from the Edit menu, _not_ the Paste Node command from the Outline menu. 3. Select all the body text and choose Copy or Cut from the Edit menu. 4. Move to the tree view, and choose Paste Node.

I hope to make this unpleasantness go away soon.
1. Fixed the Tangle All and Tangle Marked commands. They always crashed.

2. The Change command did not work in headlines because of a reversion in how headline text is selected.

3. All event handlers now return "break". This prevents further event handling and allows leo.py to handle events properly. This cleared up the last major mystery in leo.py.

4. Settings in the Prefs Panel now "stick" to windows. That is, they change when the user selects a new Leo window. In particular, the Default Tangle Directory is restored properly. This is important, as otherwise the Tangle commands might write files to the wrong place.

5. Removed calls to trace during shutdown. In general, it is not possible to call app() during shutdown because the app object may no longer exist.

6. @others was not syntax colored properly if it was indented.
1. Adding trailing whitespace to a line in body text does not set the file-dirty mark. This can never cause a derived file to become "out-of-synch" because the read code does not compare body text.

Apparently there is no way to fix this bug because of holes in Tk's event mechanism. Specifically, tree.idle_body_key has no way to tell directly what keystroke caused it to be entered.

2. Cutting and pasting between applications can only be done indirectly. See the node called "How to copy an outline from Borland Leo to Leo.py".
leo.py version 0.08 February 3, 2002

Version 0.08 adds important new features and fixes several bugs. All users of version 0.07 should upgrade to this version. This code seems solid, and significant bugs may remain. Note: this code has been tested only on Windows XP. Please report any problems with Linux or Macintosh.

This is the first version of Leo to feel as smooth as the Borland v2.5. leo.py is now less buggy than v2.5; the Borland version will soon be upgraded to match leo.py.

Here is a summary of new features. See the children of this node for full details.

1. The Find and Change commands are fully functional. These commands support Tk's "advanced regular expressions" when the "pattern match" option is checked. Tk's regular expressions are documented at:

http://tcl.activestate.com/man/tcl8.4/TclCmd/regexp.htm

2. The Tangle commands work; leo.py now supports @root trees. The next release will support the Untangle commands. Converting the Untangle code to Python is almost complete.

3. Leo now ensures that the currently selected headline is always visible, scrolling the outline pane as needed.

4. Improved Leo's memory management and eliminated several serious bugs. One bug caused errors while reading @file trees. Eliminating this is a huge step forward. This bug exists in the Borland version of Leo and will be fixed soon.

5. Leo now underlines undefined section references. Added support for hyperlinking, but disabled hyperlinking because it is not very useful without browser navigation buttons.
leo.py handles Find and Change commands much more smoothly than does the Borland version of Leo. Indeed, I plan to rewrite the Borland code to match the code in leo.py.

In general, leo.py handles the Find and Change commands more smoothly than does the Borland version of Leo. Note: the node that "anchors" wrapped searches is the current node when any change is made to the Find panel. The anchor is recomputed after a wrapped search fails.

Changed the meaning of a Find panel setting from "batch" to "context". This will be changed in a future Borland version. In the meantime, setting the "context" option in leo.py will set the "batch" option in the Borland version.

The "context" option affects only the "Find All" and "Change All" commands. When this option is in effect, more context information is printed when matches are found.

The "reverse" option affects all Searches and Changes, both those initiated from the Find Panel itself, and those initiated from menu commands. In particular, F3 will find the previous search if the "reverse" option is in effect.
The Tangle command has passed significant tests, and bugs may remain. Be warned.

leo.py's Tangle command produces output that is slightly different from Leo v2.5. The differences are insignificant; here is the complete list:

1. The header line, i.e., the first comment line of the tangled file: leo.py produces forward slashes in the path name, Leo v2.5 produces back slashes.

2. Leading whitespace: leo.py produces "optimized" leading whitespace. leo.py removes blanks if they do not affect the visual appearance of whitespace; this depends on the tab width specified in the Preferences Panel. Leo v2.5 copies leading whitespace exactly. The leo.py way is preferable; it will produce output acceptable to Python's tabnanny regardless of tab width used while running Python.

3. Trailing blanks lines in body text: leo.py removes all trailing whitespace. Leo v2.5 does not. Conceivably, leo.py might have to change to make the Untangle command work properly. More likely the leo.py way is just better.
Underlining "live" links clutters the screen too much, and hyperlinks from section references to section definitions isn't very useful without the standard "back" and "forward" buttons typically found in web browsers. For these reasons, I have disabled hyperlinking.

To enable hyperlinking, just set:

self.use_hyperlinks = true

in color.__init__ in the @file leoColor.py tree.
1. Fixed several bugs involving cloned headlines. One bug caused cloned headlines not to be updated in synch. Another bug caused @file trees not to be marked as dirty under certain conditions.

Both bugs could have caused read errors while reading @file trees, so fixing these bugs is a big step forward. I have experienced no read errors since fixing these bugs. A huge step forward. This bug exists in the Borland versions of Leo and should be fixed ASAP.

2. There was a big performance bug lurking in the tree code that became apparent during testing of the Find and Change commands. Closing a window could take almost a minute if the tree had been redrawn many times. Old widgets were never deleted until the window was closed. This may be a problem with tkinter, and the workaround was straightforward.

3. Fixed a bug in the "Save To" command. After doing a Save To, a following Save command used the Save To file name! This explains why some saves "didn't take".

4. Fixed a bug in the Save commands. Canceling a Save dialog did not work: instead it wrote a file called ".leo". I am not sure whether this bug occurred in previous releases.

5. All Save commands now always recompute file indices. This old logic accomplished very little, and introduced needless differences between the various kinds of Save commands.

6. Made file and path name processing more portable. Removed all calls to os.chdir().

7. Fixed a bug that caused a control-d to delete a character in the body pane when the Move Down command didn't do anything, i.e., when the presently selected node was the bottom node on the screen.
1. Used Tk.Text widgets in headlines rather than Tk.Entry widgets. This allows the Find/Change commands to search headlines. Control-k no longer deletes text following the cursor in headlines.

2. Improved the performance of screen updates and markedly reduced flicker in the body pane.

3. Found a way to handle keystrokes without knowing the status of the control and alt keys. The idle event handlers now ignore the actual keystrokes in most cases, and take action solely based on whether the headline or body text has actually changed as the result of those keystrokes. If not, we can assume that a command has been entered and we do not set the dirty or changed bits.

4. Replaced es_newline global with app().log.es_newline, i.e., frame.es_newline. This is better than before because each log stream now has its own newline count.

5. Reduced width of the log pane to give more space to the tree pane.

6. The LeoPy folder now contains a dummy file called __init__.py. This file marks the LeoPy folder as a potential package.

7. Added several new functions to the file leo.py. These are useful for invoking leo.py from a Python interpreter. See the section "How to Install & Run Leo" for details.
Previous version of leo.py did not release memory when windows close. This version does.

Memory management is remarkably easy in Python/Tk. Added __del__ routines and corresponding destroy routines to the frame, vnode and tree classes. The destroy routines eliminate circular references between objects. The __del__ routines do nothing except print debugging traces; we know that all references to an object have been removed when its __del__ routine is called.

Added app.deleteOnClose ivar to control memory management. When true, Leo deletes all frame objects when a frame closes. This is always true at present.

Fixed a memory botch: previously a dummy vnode was allocated for every vnode created while reading files.
Starting with this release, you will see trace statements throughout the code. The trace function is defined in leoUtils.py; trace implements much of the functionality of my Sherlock tracing package. Traces are more convenient than print statements for two reasons: 1) you don't need explicit trace names and 2) you can disable them without recompiling.

In the following examples, suppose that the call to trace appears in function f.

trace(string) prints string if tracing for f has been enabled. For example, the following statement prints from s[i] to the end of the line if tracing for f has been enabled.

j = skip_line(s,i) ; trace(s[i:j])

trace(function) executes the function if tracing for f has been enabled. For example,

trace(self.f2)

You enable and disable tracing by calling init_trace(args). Examples:

init_trace("+*") # enable all traces init_trace("+a","+b") # enable traces for a and b init_trace(("+a","+b")) # enable traces for a and b init_trace("-a") # disable tracing for a traces = init_trace("?") # return the list of enabled traces

If two arguments are supplied to trace, the first argument is the "tracepoint name" and the second argument is the "tracepoint action" as shown in the examples above. If tracing for the tracepoint name is enabled, the tracepoint action is printed (if it is a string) or executed (if it is a function name).

"*" will not match an explicit tracepoint name that starts with a minus sign. For example,

trace("-nocolor", self.disable_color)
Rewrote the code that computes file names. This should have two beneficial effects:

Note: This code has only been tested on Windows XP.

1. The code should be more portable. I've used os.path.join throughout to concatenate parts of filenames, and this should handle differences involving path separators on different platforms.

2. The code no longer calls os.chdir(). The "current application directory" changes only as the result of completing file open and save dialogs. In particular, @path, @root and @file do not change the current application directory.

3. Used leo.__file__ to get the directory from which leo.py was loaded. This seems to be reliable, though it has only been tested on Windows XP.
The following features of leo.py will be incorporated into the Borland version 2.6 of Leo:

1. Improve leading whitespace handling in Tangle.

2. Fix clone bugs (rewrite vnode::setDirty). These bugs can cause errors while reading @file nodes.

3. Improve Find/Change commands. Change "batch" to "context". This will make the Preferences Panel work identically in both programs.

4. Always recompute file indices and compute file indices. This will make derived files produced by v2.6 identical to the files produced by leo.py.

5. Make sure all file names end in .leo.
I urge anyone using leo.py upgrade to this version. This is the first version of leo.py that has been thoroughly tested.

See the children of this node details about this release. Here are the highlights:

1. Fixed many bugs, including a bug that can cause body text to be lost when creating a new headline.

2. The Python window now works. You can now run Python scripts from within leo.py!

3. Added a script to convert Leo files from Leo 1 to Leo 2 format.

4. @nocolor and @color are now inherited properly from ancestor nodes.

5. Added Leo Documentation to Help menu. This command opens LeoDocs.leo.

6. Added auto indent to body pane.

For even more details, see the diary entries for January 6-9 in LeoPy.leo.

See the To Do lists in LeoPy.leo for a list of unfinished features. The primary unfinished features are the Find/Change commands, preferences settings and the Tangle/Untangle commands.
This is the first version of leo.py that has been heavily tested. About 70 percent of my work on leo.py has been done using leo.py itself. I know of no remaining bugs that can cause data to be lost.
I have concentrated on removing all significant irritations encountered while using leo.py. Far fewer still remain than before. Among the remaining irritations:

1. Syntax coloring happens at "idle time", that is, after all events have been handled. This means that characters are initially colored black, then changed to another couple after an obvious delay. The obvious event-handling code does not work. Perhaps using a "virtual event" may work.

2. Keystrokes that should initiate commands _also_ get passed to widgets. I am hoping to find a way around this, and it may take a bit of work. The two biggest offender: Control-k while editing a headline deletes from the cursor to the end of the headline (in addition to creating a new node!) Control-i gets passed to the body pane as a tab.

3. The border around the tree pane gets over-written by headlines. I'm not sure how to fix this: it is certainly a Tk bug.
Fixed a bug that can cause body text to be lost when creating a new node.
Choosing Open Python Window brings up IDLE, the standard Python IDE, from which scripts may be run and debugged.

Note: The path to idle.py must exist in sys.paths. For Python2.1 on windows, this path will typically be \Python21\Tools\idle If this path does not exist, a message will be sent to the log pane. The usual way to add a path to sys.paths is to modify the sitecustomize.py file.

Changed names of several vnode and commands methods to make them compatible with the scripting documentation on Leo's web site. You may now run any script that runs on Borland Leo on leo.py.

When running scripts from leo.py, you may refer to any method or instance variable (attribute) in the code for leo.py. If you want to run those scripts on Borland Leo you should restrict yourself to the methods documented in the Scripting chapter of Leo's online documentation.
To convert an @root tree to an @file tree, choose the root of the tree to be converted, then do the following in the Python window:

import c2py c2py.leo1to2()

This script makes numerous changes throughout the tree. It does not, however, change @root to @file, or insert the needed @others directives. You must do that by hand.
At long last it is possible to open this file, LeoDocs.leo, from the help menu.

This command will work only if LeoDocs.leo is located in the directory in which leo.py exists.
The body pane now has auto-indent on at all times.
leo.py version 0.06 (alpha) December 20, 2001

This version fixes several minor problems that prevented leo.py from running on Linux. There is no need to upgrade to this version if leo.py works on your system. This version is neither more nor less stable than version 0.05. This file, LeoDocs.leo, has also been improved substantially.

There still may be problems running leo.py on Linux. You may be able to fix those problems yourself after reading this file... I'll be on vacation until about January 8. I may be able to answer questions on Leo's SourceForge site, and I'll make no code changes until then.

Problems fixed:

1. Removed call to print_stack() in es() logic. If there are problems during initialization this logic printed "Null log" and then printed a stack dump. This dump was more confusing than helpful.

2. Changed "darkblue" to "DarkBlue". The standard colors known to Tk are listed at http://tcl.activestate.com/man/tcl8.4/TkCmd/colors.htm

If you have more problems with unknown colors, please use a color listed above.

3. Eliminated some accelerators (Linux only). You may take an exception in createAccelerators() in leoFrame.py if Linux does not support the accelerators defined in one of the following sections:

<< control key bindings >> << alt key bindings >>

Just comment out the relevant entry. Please let me know which accelerators don't work. I can add platform-specific code to deal with them.

4. Added loaddir code to leo.py. Leo tries to guess where leo.py was loaded from. If this doesn't work leo may take an exception in leo.py.

As a temporary hack, please set loaddir correctly in the following code at the start of leo.py:

# loaddir should be the directory that contains leo.py if sys.platform=="win32": loaddir = "c:\\prog\\LeoPy\\" else: loaddir = "LeoPy"

5. Removed bullet 0x95 characters from this file. They don't show up well on Linux.

6. In leoTree.py, changed the filenames from x.gif to x.GIF. Linux is more picky about case in filenames than Windows.

Edward K. Ream December 20, 2001
leo.py version 0.05 (alpha) December 17, 2001

This version of Leo marks a major milestone in Leo's history. leo.py is the first functional version of Leo written completely in Python and Tkinter, Python's interface to the tcl/Tk system.

leo.py is quite usable. leo.py should work on any machine with recent Python and tcl/Tk interpreters. This version of Leo was created using Windows XP, Python 2.1 and tcl/Tk 8.3.

Warning: This version is alpha quality. Use extreme caution: please save your work often and make full backups of all .leo files and derived files.

Please read this node's children before sending bug reports or feature requests. Send all bug reports to Leo's SourceForge web site at: http://sourceforge.net/projects/leo/

Edward K. Ream
I have been happily using leo.py to develop itself for the last three days without serious problems. leo.py reads and writes all its source files exactly as does the Borland version. This is an important test, and significant errors may remain.

Performance on a 1.2 Ghz Pentium is good to excellent. Drawing the screen happens quickly, smoothly and without flicker. Expanding and contracting nodes is usually excellent, and slows when a many nodes have been expanded. Syntax coloring appears instantaneous, even with an unsophisticated algorithm. Loading LeoPy.leo files takes about 3 seconds. This could be improved by using Python's XML classes.
You must have recent versions of Python and tcl/Tk installed on your machine. Download Python from http://python.org/ Download tcl/Tk from http://tcl.activestate.com/software/tcltk/

After installing Python and Tk, run Leo double clicking the file leo.py in the LeoPy folder. On Windows this will bring up a Leo window and a black Python interpreter window.

The LeoPy folder contains all files in this distribution. leo.py is the main source file; run Leo by double clicking leo.py. The Python interpreter will create corresponding .pyc files as .py files are imported by leo.py.

LeoPy.leo is the master source code file; all .py files were derived from LeoPy.leo. c2py.py and leoCompare.py are tools that should be run from a Python interpreter.
Functional Commands and Features

Open, Save, Save As, Save To commands. Read @file Nodes command. Read Outline Only command. Write Outline Only command. Warning: this has not been tested thoroughly. Insert Node, Delete Node and Clone commands. Move Node Right/Left/Up/Down commands. Cut Node, Copy Node, Paste Node commands. Syntax coloring for Python only. The @color and @nocolor directives, but these are not inherited yet.
Unfinished Commands and Features:

Revert. All Tangle and Untangle commands. All Import commands. All Find and Change commands. Sort Children command. Toggle Split Direction, Toggle Active Pane and Cascade commands. Auto indent in the body pane. The Preferences panel is semi-functional: see note one below. The Find panel is non-functional. The Python scripting window is non-functional. Syntax Coloring Options and Font Options windows are not ready yet. @color and @nocolor directives are not inherited yet.

Notes:

1. The Preferences panel is partly functional. The default target language option has no effect: syntax coloring is for Python only. Tab width can not be changed; tabs are 8 characters wide.

2. Menu items are not yet dynamically dimmed and undimmed. Some non-functional commands have undimmed menus. Keyboard accelerators work even for dimmed menus.

3. Scripting Leo is not possible yet. You can't control Leo from the Python interpreter because control passes to the Tk event loop.

4. Leo's Save commands do not yet save the information about which node was visible at the top of the tree.

5. The Save/SaveAs/SaveTo dialogs don't handle shortcuts to folders properly; they try to replace the shortcut with the .leo file.

6. Initialization code in leo.py computes the directory from which Leo was loaded using argv[0]. I am not sure this is proper, though I have had no problems recently. Tree icons will not load properly if argv[0] does not specify this directory. If the path is invalid Leo will print: os.chdir failed: `dir`

7. The tree class does not automatically ensure that the current node is visible after an outline operation.

8. The font used in the body pane is not great. I hope to improve it.

9. Headline text is sometimes obscured.
leo.py already feels less buggy than the wxWindows versions of Leo. Rewriting Leo in Python and Tkinter has greatly improved the code. Further improvements are possible. BTW, work began in earnest on this version of Leo in late October, 2001. It's been a great month.

The following problems have resisted my initial attempts at solving them. Any help from Tk experts would be appreciated:

1. Window icons are the Tk icon, not the nifty Leo icon. Really, there _must_ be a way to do this!

2. Can variable-width tabs can be done in Tk? If not, Leo may have to convert tabs to blanks as specified by the preferences panel.

3. Cut, copy and paste work in the log and body panes using Control-X, Control-C and Control-V keys. However, there are no Cut, Copy or Paste menu items in the Edit menu. Is it possible to send simulated keystrokes to a text widget?

4. Some menu accelerators do not seem to be available in Tk. In particular, many of the items in the submenus of the Outline menu have no accelerators yet. These commands are useful only if they can be chosen from the keyboard rather than the menu.

5. The border of the tree control is gray. It can be overwritten by large headlines. This appears to be a Tk or Tkinter bug; I haven't found any way to eliminate the border or color it white.

6. There doesn't seem to be a way to select all the headline text when editing starts. The click that starts editing always clears the selection.

7. Changing the type of leo.py to .pyw doesn't seem to work.

8. A message flash briefly on the screen when leo.py exits, too fast to read. These messages do not appear when invoking leo.py from the Python interpreter. They probably would be visible in a Linux window.
It will be much easier to make such improvements to leo.py than to previous versions of Leo. Here is my list of new things to do:

1. Create "hyperlinks" from section references to section definitions. This will happen in the next release.

2. Add automatic "tab nanny" checking and full syntax checking of Python body text.

3. Build a file/directory comparison window using code in leoCompare.py.

4. Build a Python debugger into Leo. Python provides excellent hooks for debugging and tracing. Python's stand-alone IDLE debugger doesn't seem to work well with the Tk command loop.

5. Expand Leo's file format to take advantage of the power of Tk text widgets.
Leo Borland version 2.6 May 15, 2002

This version fixes a bug that can cause errors while reading derived files. Earlier versions do not ensure that clone indices in derived files are distinct.

I recommend that all users of the Windows version of Leo upgrade to this version.
Leo Borland version 2.6 March 4, 2002

leo.py v2.0 and Borland Leo v2.6 are being released simultaneously. I urge all users of Leo to upgrade to one or both of these versions. This is an important milestone in Leo's history, For the first time, leo.py (v2.0) and the Borland Leo (v2.6) are functionally identical. In particular, their respective Tangle commands produce identical output.

Borland version 2.6 fixes major problems and contains numerous changes to make it fully compatible with leo.py v2.0. Highlights of Borland v2.6:

1. Fixes bugs that caused spurious errors while reading @file trees. Such errors can destroy clone links.

2. Supports an improved format for derived files. This format is used by leo.py 2.0. This is an upward compatible change: previous versions of Leo can not read the new format, and this version of Leo can read all previous derived files.

3. Fixes two long-standing bugs in the Untangle command.

4. As mentioned above, the Tangle commands are byte-for-byte compatible with leo.py v2.0. Also, @c is now equivalent to @code.

5. Adds two very useful commands: Sort Siblings and Contract Parent.

See the Children of this node for full details.
This version of Leo removes blanks from between sentinel lines in derived files. This version of Leo is fully compatible with leo.py v2.0 in this regard.

This is an upward compatible change in the format of derived files: Borland Leo v2.6 can read derived files from all previous versions of Leo, but previous versions of Leo can not read derived files without blanks lines.

Removing blank lines requires a new kind of sentinel, the "verbatimAfterRef" sentinel. This allows Leo to handle comments following section references that would otherwise be treated as sentinels themselves. For example:

<< section >> #+others
Whenever a node changes, Leo now ensures that all nodes cloned to it, and all ancestor @file nodes are marked dirty. This is the cause of spurious read errors.

As a side effect, nodes now become dirty when they move.

This change was made in leo.py v0.8.

It is also vital that @file nodes remain dirty until they are written without errors. Otherwise, a Save command will succeed without warning, and a later read may cause the dreaded "clones have been cleared" message.

This change was made in leo.py v1.0.
@c now works the same as @code. This makes the syntax colorers agree with what the Tangle commands actually do. Previously, the syntax colorers indicated that everything following an @c was code, while the Tangle commands placed everything following an @c in the doc part!
This version fixes two long-standing bugs:

1. Untangle did not work properly for languages like Perl and Python that do not have block comments.

2. Untangle did not recognize @ on a line by itself as the start of a doc part.
The Tangle commands are now byte-for-byte compatible with leo.py 2.0. Tangle outputs "optimized" leading whitespace just as leo.py does. This can be important in Python programs.

All the Save commands now recompute clone indices just as in leo.py 2.0.
The "Show Context" checkbox in the Find Panel is presently non-functional. (In leo.py it affects the messages produced by the Find All and Change All commands.)
Unlike leo.py, the Borland version of Leo can not ensure that saved outlines have .leo extensions.

There are two problems:

1. The ensureExtension routine is called after the dialog closes. If this routine changes the file name we could overwrite an existing file!

2. There appears to be problems with the Borland DefaultExt field. Setting this field causes crashes.
This version fixes several serious bugs. All users of Leo2 should upgrade to version 2.5 immediately.

1. Eliminated the ill-fated automatic updating feature. This turns out to be very dangerous and disconcerting. If one makes changes to the .leo file and does not save those changes, a later update could erase those unsaved changes!

2. Removing automatic updating also fixed another bug: The current outline node was not being selected properly when a .leo file was read, so that in some cases the body text did not correspond to the selected outline node. This never caused loss of data, and was disconcerting.

3. Fixed a bug that caused Find/Change settings to be saved to a file only if a find or change command was actually executed.

4. Restored several parts of Leo2(cb).leo that were inadvertently erased due to earlier bugs. In particular, the outlines for xbuf.c and xbuf.h have now been restored.

One bug remains. On Windows XP, the cursor is obscured in the Find/Change dialog when it is at the far left of the Find or Change text areas. This may be a botch in the XP text control itself. The solution would be to create a border in the text areas, and there is no obvious way to do this using the Borland classes.
Version 2.4 is a major improvement in Leo2. I urge all users of Leo2 to upgrade to this version. See the children of this node for full details.

The "old" Leo2 tried to save space by not writing all information in @file trees. This was a serious mistake. The "new" Leo2 saves all information in an outline to the .leo file, including all information in @file trees. Once again you may back up a project merely by backing up the project's .leo file. There is no Archive command, and no need for one. All .leo files are now safe archives.

As the result of the change in file formats, Leo 2.4 may clear clone links when loading derived files created with previous versions of Leo. Leo 2.4 will issue detailed messages when that happens.

The new Leo2 is much safer and more convenient to use than the old Leo2. Error messages and error recovery have been improved.

Leo2 updates @file trees automatically when Leo2 is activated. For example, suppose you change a derived file in another editor, say in an IDE. Leo2 will update the @file tree when you switch to Leo, provided that you have saved the file in the IDE. Warning: due to several apparent bugs in the Delphi code, this feature only works if the main Leo window is at least partially visible on the screen (!)
Version 2.4 fixes several bugs involving clones.

1. Version 2.4 rewrites clone indices when writing derived filed, so node sentinels accurately reflect the clone status of the node. The node sentinel for the root node no longer contains the maximum clone index. Leo2 clears the root's clone index on reading and writing so that the root node is not mistakenly joined so another node!

2. Version 2.4 takes more care to recreate clone links properly when reading derived files. A derived file can be read into a .leo file different from the .leo that wrote the derived file, so Leo2 makes sure that clone links are proper in the .leo file being opened. A minor drawback: .leo files now are "big", so reading them is a little slower.

Note: Clone links into @file trees work only if the .leo file is "in synch" with the files derived from the @file trees. Clone links will break if the .leo file and derived files are not in synch. Typically "backup" .leo files will be out-of-synch with present derived files, so it's best to use "backup" .leo files only in emergencies, for example to revert a project to a previous state.
The "old" Leo2 tried to save space by not writing all information in @file trees. This was a serious mistake. The "new" Leo2 saves all information in an outline to the .leo file, including all information in @file trees. It is once again possible to back up a project merely by backing up the project's .leo file.
The archive command was a backup disaster waiting to happen. It has been replaced by the following four file commands are located in the File:Read/Write submenu.

Read Outline Only: reads an outline using only the .leo file, not any files derived from @file nodes. This command is useful for reverting a project to a previously saved state.

Read @file Nodes: updates all @file nodes in an outline. This ensures that the state of an outline matches all files derived from @file nodes. Included for completeness. This happens automatically when a .leo file is first read, and it also happens automatically when Leo2 is reactivated.

Write Outline Only: saves an outline without writing any @file trees. Useful for inserting an @file node into an outline without modifying a derived file with the same name.

Write @file Nodes: forces an update of all @file trees. Surprisingly useful.
Leo2 updates @file trees automatically when Leo2 is activated. For example, suppose you change a derived file in another editor, say in an IDE. Leo2 will update the @file tree when you switch to Leo, provided that you have saved the file in the IDE.

Warning: due to several apparent bugs in the Delphi code, this feature only works if the main Leo window is at least partially visible on the screen (!)
Revised for version 2.4

Loading and saving .leo files usually keeps the .leo file and derived files "in synch". However, if you create backup .leo files, it can easily happen that the structure of @file nodes in the backup .leo files no longer matches that structure in the derive files. Leo2 will detect this condition the next time you next open the old .leo file. When that happens, Leo2 discards the entire out-of-synch @file tree, and recreates it solely using the derived file. In the process all marks and clone links from outside the file are lost. Leo2 issues the messages:

Error reading @file <filename> -- Rereading file. Clone links into this file will be lost.

to remind you that the .leo file you are using is out-of-date. Saving the .leo file will bring it up to date.

If one or more sentinel lines in a derived file have been corrupted in some way, by inserting, deleting, altering or moving a sentinel, Leo issues these messages:

Error reading @file <filename> <An error message about a bad sentinel> -- Rereading file. Clone links into this file will be lost. <An error message about a bad sentinel> (again) ----- File may have damaged sentinels!

Data may not actually be lost, and the outline structure will be seriously damaged. The most sensible thing to do is to restore the derived file from a .leo file using the Read Outline Only command.

No error recovery is attempted when automatically updating @file trees. If an error is found the update is canceled (leaving the outline unchanged) and the following message is given:

-- Update canceled due to structure errors

We don't attempt error recovery because error recovery would clear clone links. For example, suppose we are editing a .leo file, and for some reason we also edit a derived file _without_ saving the .leo file. Now the files could be out of synch! So it is best not to press on with an automatic update.
Revised for version 2.4

If Leo2 detects orphan or ignored nodes while writing an @file node it saves all information in the @file tree in the outline (.leo) file. No information is lost. When the .leo file is read again Leo2 will load the information in the @file tree from the .leo file, not the derived file.

As a reminder, Leo2 marks the erroneous @file node as dirty so that saving the .leo file will attempt to rewrite the @file node. Version 2.4 no longer marks the @file node as "stuck on dirty". If you save the .leo file the dirty mark will be cleared. However, the @file node will be dirty every time the file is read until all errors are corrected.
@file trees are less flexible than @root trees:

1. You can not use section definitions in more than one file. For example, you can't define declarations in one file to be used in another file. If you need all the features of noweb you must use @root trees.

2. @file trees use no escape conventions whatever. A code part in an @file tree contains a section reference if << precedes >> on the line, regardless of whether << or >> are contained in strings or comments. In practice, such "false references" occur infrequently, and the workaround is simply to split the offending line. Moreover, noweb's escape conventions (@<< and @>>) cause problems in @root trees, so this "drawback" is very minor.

3. Clone links into @file trees work only if the .leo file is "in synch" with the files derived from the @file trees. In particular, backup .leo files will usually be out of synch with derived files. Clone links will break otherwise. To recover from such errors, simply use the "Read Outline Only" command.
Note: 10/19/01: I recommend that all users upgrade to version 2.4. There are some serious problems with version 2.3.

This version of Leo contains some significant improvements. See the children of this node for details:

1. The new @first directive allows you to place lines at the very start of files derived from @file nodes. For example, @first #!/usr/bin/env python

2. The log window is now part of the Leo window. Very handy.

3. Fixed several bugs involving the Find command.

4. A new Archive command saves an entire outline (including all @file trees) to a .leo file. Use this command with caution. Loading and then saving a .leo file created with the Archive command will revert an entire project to the state it had when the archived .leo file was created.
The @first directive allows you to place lines at the very start of files derived from @file nodes. For example, the body text of @file spam.py might be:

@first #! /usr/bin/env python

The body text of @file foo.perl might be:

@first #/usr/bin/perl

@first directives are recognized only at the start of the body text of @file nodes. No text may precede @first directives. More than one @first directive may exist, like this:

@first #! /usr/bin/env python @first # more comments.
The Archive command writes all nodes of an outline to a .leo file, including all parts of @file trees. All @file trees are marked in such a way that when the archived .leo file is read 1) all @file trees will be restored from the archived outline rather from derived files and 2) all @file trees will be marked dirty so that when the archived .leo file is written all @file nodes will be updated.

Use the Archive command (and the files written by it) with caution: loading and then saving an archived .leo file will back up an entire project to its state when the archive was originally written!
Added support for @c in syntax colorers for Python, Pascal, Perl, Java and HTML.
Fixed a bug in the Change, Then Find command. The Change, Then Find command would rescan the newly changed text if the "change text" contained the "find text" preceded by other text of length greater or equal to the length of the original "find text".

For example, changing "blah" to "const blah" would result in rescanning the newly inserted "blah". This would cause the "Change All" command to hang.

The old code advanced the search point by the length of the "find text." The new code advances the insertion point by the length of the "change text".

Fixed the Find/Change panel: some captions were cut off.
@file nodes are now marked dirty whenever any change is made in the @file tree, including changes made as the result of changing cloned nodes outside the @file tree.
Made the log window part of the Leo window. Having the log be part of the leo window is very convenient.
Leo2 readme file Borland version 2.2, 9/16/01

This version fixes several bugs in Leo2:

1. Fixed a bug that causes all data in an @file tree to be lost under the following conditions:

A. The @file tree was erroneous, i.e., it contained orphan or ignored nodes. B. The .leo file containing the erroneous tree was saved twice.

Leo2 now marks an erroneous @file node as "stuck on dirty" until the tree is fixed. Recall that dirty nodes have icons with a black border rather than a gray border. Whenever a file Save operation occurs, Leo2 will attempt to write all dirty @file trees, thereby reminding you that errors remain. However, the .leo file itself is not "stuck on unsaved", so you won't be prompted to save the .leo file endlessly.

While fixing this bug I also improved error and warning messages relating to reading and writing @file nodes. This should make it clear that a) data in erroneous @file trees is saved to the .leo file and b) data is recovered from the .leo file when reading erroneous @file nodes.

2. Fixed a bug relating to clones that could cause loss of data. Leo2 now marks all clones dirty when any clone changes, and makes sure to mark @file nodes dirty that contain changed clones.

3. Changed the code that writes @file trees to end lines with "\r\n" rather than "\n". I hope this will improve matters, though I have my doubts. Please report any problems with the new scheme immediately.

4. Added Write @file Nodes command. The command writes all @file nodes in the selected tree, regardless of whether they have been changed.

5. Made the commands in the Main Leo2 window functional.
Version 2.1 is the first public release of Leo2. This version appears stable, and should be used with caution.

The major feature of Leo2 is that tangling and untangling happen automatically for all code derived from @file nodes.

Remember to back up all files derived from @file nodes; such files are original source files! It is no longer possible to back up an entire project by backing up a single .leo file.
Version 1.15 can read @file trees. Leo warns when reading @file files, and changing @file trees in Leo v1.15 is not recommended.
This version corrects a problem with double-clicking Leo icons under Windows Me. You may now launch Leo by double-click the icon for any .leo file and you may open any .leo file by double-clicking on it.
This version of Leo corrects a problem with how whitespace was handled in @silent mode.
Barring serious bugs, version 1.12 is likely to be the last Borland/Windows version of Leo for a while. The wxWindows versions of Leo are usable enough to justify putting all further work into them.

There are several important improvements in version 1.12:

1. Added the Sort command to the Outline menu. This command sorts all the children of a node into alphabetical order.

2. A major improvement to Tangle. In @silent mode, Tangle now outputs derived files with "verbatim" whitespace, that is, without any extra blanks, tabs and newlines. This makes Tangle much more useful for Python, and in other applications. For example, it is now possible to do the following in Python:

if <<condition1>> && <<condition2>>: print <<list of vars>>

In the derived file, expansions of the sections will be placed on the lines in which the reference appears. This works in Python as long as the expansions themselves appear on a single logical line.

This "verbatim" expansion only happens in @silent mode, so these kinds of derived files can not be Untangled.

3. Tangle now reports errors more fully and less redundantly. Errors involving missing or erroneous path names (specified in @root directives, @path directives or the Preferences Panel) are more specific. These errors are reported only once per Tangle command, and these errors terminate the Tangle command immediately. This is wise; we don't want to write files to the wrong directory! Finally, Tangle no longer prints the actual text of a section when giving the "possibly duplicate section definition" error. This should be helpful: no longer are huge error messages generated. It should be easy enough to find the relevant section definitions using Leo's find command.
This version corrects a problem that can cause the Import CWEB Files command to hang in an endless loop.

This file also contains improved documentation (see the children of this node) in two sections:

1. Added an explanation of the following error message given by the Tangle command: "Multiple parts not allowed for << section name >>"

2. Added a warning about using Untangle to update cloned nodes. (See the last paragraph of the node.)
Sections can be defined in several parts in two ways:

1. Using << section name >>= in several places with the same section name.

2. Using several @code directives within the _same_ body text.

As a precaution against mistakenly defining a section in more than one place, it is invalid to use @code in different nodes to define multiple parts for the same section. In particular, this error may arise when using cloned nodes.

This error may always be eliminated by using << section name >>= instead of @code.

The Untangle, Untangle All and Untangle Marked commands are the reverse of the corresponding Tangle commands. They update an outline based on changes made to one or more derived files. These are exceptionally useful commands.

For example, suppose you create a new part of the outline and Tangle it for the first time. When you compile the resulting derived files for the first time, you are likely to get many syntax errors. You could fix those errors in the outline and Tangle the outline again, but there is a much easier way: you fix the errors in the derived files using the compiler's editor, then run the untangle command on the part of the outline that created the derived file. The Untangle command updates the selected outline to match the changes in the derived files. It's as simple as that. By the way, the Untangle command marks all the nodes in the outline that it updates, and you can examine all such nodes with the Go To Next Marked command in the Outline menu.

You cannot use Untangle to update doc parts, or leading comments in code parts or "trivial" whitespace in code parts. This is a limitation of the Untangle command that cannot be fixed; Untangle has no way of knowing whether leading comments came from doc parts or are just leading comments.

Untangle never changes the structure of an outline; it never inserts, deletes or moves nodes. Don't attempt to change the structure of an outline by modifying derived files; it won't work. Also, never delete, move or alter the sentinel lines in derived files written by the Tangle command. Such lines start with /// followed by a section name.

If you change the section name in a sentinel line Untangle will not update the code in the outline (with the old name) that generated the renamed section. Untangle now warns about sections that appear in a derived file but not in the outline. Untangle has no trouble with changed section references in derived files; it is only changed sentinel lines that cause problems.

Cloned nodes that generate code in several files may cause problems for Untangle if not all the code is changed the same way in derived files. If Untangle is run separately on these derived files, Untangle will update all cloned nodes each time it is run, so only the code in the last Untangle run will take effect. Therefore, the only reliable way to update text in cloned nodes is to make the change in the .leo file rather than the derived files.
Version 1.10 incorporates the following changes:

1. The Untangle command no longer updates @doc chunks under any circumstances. This makes Untangle safe to use when the "Tangle outputs doc chunks" preferences is not selected. In previous versions the Untangle command would delete all @doc chunks in the outline when a derived file had been Tangled without "Tangle outputs doc chunks".

The new version of Untangle is experimental; only one line of code has been added. I welcome any comments about this change. This change also fixes (or rather bypasses) a crasher reported in Untangle.

2. The shortcut for the Execute Script command has been changed from Alt-E to Shift-Alt-E to avoid conflicting with the shortcut that brings up the edit menu.

Version 1.9 contains several improvements that make Leo more Python-friendly:

1. The Execute Script command (Alt-E) in the Edit menu allows you to execute Python scripts directly from body text.

2. Several small changes make the Python window significantly easier to use.

Also, considerable reference (study-only) code has been removed from leo(CB).leo.
It is now possible to execute any Python script directly from any body text. Just select the script in the body text (including a trailing newline) and use the Execute Script (Alt-E) command from the edit menu. The script is copied to the Python window and executed as usual.
Several small changes make the Python window significantly easier to use:

1. The paste command now works in the Python window whenever the Python window is visible. This fixes a bug that required a mouse click in either pane before paste would work.

2. It is now possible to execute scripts multi-line scripts pasted into the input pane. Other changes make it easier (or possible) to terminate continued code.
Fixed a crasher that makes it impossible to tangle outlines containing doc parts in languages like HTML that have no single-line comment delimiter.
Leo v 1.7 accepts a slightly more general file format so that it can read XML generated from external XML tools. Leo v 1.7 can read all previous .leo files. Leo's Save commands remain unchanged.

Leo still only understands Leo files. However, Leo now understands a slightly generalized form of Leo files. Specifically:

1. Attributes may now appear in any order. (Leo writes attributes in a fixed order, but some XSLT tools rewrite Leo files with attributes in a different order.)

2. Leo will now accept <tag/> instead of <tag>stuff</tag> when "stuff" is empty.
This version corrects a small bug: the wrong text is selected when the syntax colorer changes. This is a cosmetic bug only; the selected text will not be replaced when further typing occurs.

Unless major bugs are found, this will be the last version of Leo for several months. I want to freeze the code so that I can work on the wxWindows version.
This version is a major milestone in Leo's code. Improvements were made throughout Leo's code in an attempt to correct an extremely hard-to-find bug that can cause data in body panes to be lost. Only time will tell if the bug has, in fact, finally been eradicated.

This version also corrects a minor bug; icons in a newly cloned tree were not always drawn properly. Also, the currently selected headline no longer changes if you click on the + or - icons that expand and contract headlines. This new behavior is a result of simplifying the event handlers; I won't consider changing this behavior until it is clear that the data loss bug has finally been fixed.

Use this version of Leo with caution until the new code has been thoroughly tested. New asserts will guard against silent data loss and other unexpected events. I don't expect these asserts to fail, but then one never does...

The following lists the changes that were made the code. You don't need to read the following details; they are provided only for completeness.

1. Greatly simplified the event handlers. This should have been done long ago.

The event handlers now handle _all_ aspects of switching tree nodes and updating data structures when the body pane changes. In particular, this guarantees that tnodes are "synched" when the body pane changes. This is a major simplification and a major improvement: it should no longer be possible to lose data once it appears in the body pane.

The reverse is not true: the code must still take care that the body pane is updated if tnodes are changed "by hand." (This is typically done when new nodes are being created. Such nodes are never the current node and so are not shown in the body pane.) I re-checked all code to make sure this constraint is satisfied.

Removed synchVnodes and updateBodyPane methods. These have always been the most error-prone methods in Leo. Removing them was made possible because the global constraint that tnodes are up-to-date is now guaranteed by the event handlers.

Created a new updateSyntaxColorer routine, which is called when moving a node or changing its text might affect syntax coloring. This routine can never affect tnodes.

2. Removed reference counting from tnodes. The new code deletes tnodes only during the read process. After that, tnodes are never deleted. This could be called a memory leak, but it ensures that tnodes can never be deleted out from under a vnode. I don't this was ever the problem with losing data, and the new code makes sure that it can't be.

3. Improved how icons are redrawn. Event handlers now set the dirty bit when text changes, which simplifies matters.

4. Added asserts to guard against silent data loss, unexpected calls to event handlers, and mismatches between vnodes and their commanders.

6. Added the mCommands data member to vnodes. This member ensures that the correct commander is returned by vnode::commands(). The old code got the commander by looking for the current window. Conceivably this could have caused the wrong commander to be used in some cases.
This version adds the following features:

1. Outline to noweb command. 2. Python scripts for finding and changing text in Leo outlines. 3. A Python method of the vnode class returning the commander corresponding to a vnode. 4. Documentation for Leo's import/export commands.

This may be the last version of Leo for a while; I am about to start work on a cross-platform wxWindows version of Leo. However, bug reports and requests for new features are always welcome.

Edward K. Ream September 19, 2000
The "Outline To Noweb" command converts the selected outline to a flat file containing noweb text. The name of the root section is taken from the @root directive. <<*>> is used if the @root directive is not followed by any file name.
Leo's Python scripting does not support Leo's Find and Replace commands directly because these commands are interactive. Calling these commands from a Python script would be clumsy.

Instead you can use the new find and change scripts to search and replace text. These scripts use Python's powerful re module.
The commands() method has been added to the Python vnode class.

c=v.commands()

This method returns the commander for the window containing v. This method can be used to avoid passing commanders as arguments to vnode methods. For example, given just v, we can call either of the following:

v.commands().synchNode() v.commands().Repaint()
This version corrects a problem with the Save As command; it worked only once! That is, after the Save As command was executed the window's title would change, but a later Save command would change the file specified before the Save As command was executed.
This version of Leo introduces Python scripting. This is a major new addition to Leo. See the new Chapter 7 of this documentation. Python support still has rough edges; the next release will be cleaner. Any suggestions for improvements to Leo's support for Python would be appreciated.

Alt-V now toggles the "View All Characters" option. This is especially useful when editing Python code.

Besides Python support, a number of minor bug fixes have been made:

Added syntax coloring for try and catch to the C parsers.

Control-K, I now indents blocks of text uniformly, regardless of the language being syntax colored, and regardless of @nocolor and @color directives. Similarly, Control-K, U now undents blocks of text. The old keys, control-[ and control-] only worked when the current language was C and syntax coloring was enabled.

Removed the menu items that had the enter key as a shortcut. The only way to create a new node now is with Control-I. Using the enter key for a shortcut is not a good idea: it causes problems throughout the code.

Fixed a bug in forgiving compare. The code that was calling compare_comments wasn't handling mismatched whitespace properly.

Got the Import command for Python working. I found a bug in Tangle: in @silent mode we must always output a newline in the place of the function name. Otherwise the Python indentation will be wrong.

The Untangle is now disabled when in @silent mode. Nothing good can happen in that case!

Fixed a minor problem with the @path directive: ff a _new_ file has not been saved we issue a warning, not an error if no path has been specified. We can't really test the @root command for a path because the @root command may be found much later. Fortunately, this warning will happen very rarely. It's important, however, to warn that the file may be written to the standard directory if no path is specified in the @root command. Otherwise, Leo's behavior would be quite confusing.
This version corrects an oversight in the Flatten Outline command. In order to recreate the outline structure it is not enough to know whether each node has children; you must also know how many children each node has.

The new version of the Flatten Outline command represents the outline the same way the Export MORE Text does: a child headline is indented one tab more than its parent headline.
The Tangle commands now examine all nodes, including cloned nodes that have previously been visited. Previously, such nodes were skipped during tangling. The new logic allows clones to represent code common to more than one unit. You can always insert an @ignore directive in an ancestor of a cloned node to prevent the node from being processed during tangling.
Version 0.19 fixes some bugs and eliminates some problematic features of Leo. Also, the role of CWEB mode has been documented more thoroughly.

The PC version of PC is feature complete. I will release version 1.0 after people have played with this version for a while.

As always, I'll be happy to fix bugs or add urgently needed features.
Fixed a bug that could result in Tangle outputting derived files in the wrong directory.

Tangle and Untangle now set the current directory using @path directive if it exists, otherwise the directory specified in the Preferences panel if it exists, otherwise the directory set by the Load or Save commands if it exists. (The Save As and Save To never alter this directory.) Finally, a check to see if the @root directive specifies a full path. If so, the current directory is not changed.

If none of these directories exists an error is raised so that no Tangling or Untangling is done. This error can only occur if Tangling or Untangling a file that has just been created by the New command and never saved with the Save command.
Added the @language html, @language perl and @language perlpod directives, and added HTML, Perl and Perl + POD items in the Preferences panel.

The HTML script is rudimentary at present. Suggestions for improvement are welcome.
The @cweb and @noweb commands are no longer functional. The new @language cweb directive replaces @cweb, and the other @language directives effectively replace @noweb. There is an new CWEB option in the Preference panel.
Leo now parses the @language directive as you type, so if you change the language specified by the @language directive you will see the effect immediately.

There is no longer a limit of 6 languages that can be syntax colored. Let me know if you would like Leo to support another language.
The Print command is now much more flexible and convenient: it will print any node and all its descendants, whether or not the node contains @unit, @root or @ignore directives.
Modified massage_block_comment so that it converts the first of a series of newlines to a blank and deletes the rest; Untangle no longer mangles modified @doc sections.

A more complete solution would be for Tangle to insert a flag for inserted newlines ( say backslash newline) so that Untangle could know which newlines to remove. I'd like to wait until all Tangle/Untangle code is converted to C++ before doing a more thorough job.
Leo no longer supports clone _windows_. Cloned outlines, however, will remain with Leo forever.

Clone windows were never very useful and were buggy. Eliminating clone windows has made it possible to handle events more smoothly and powerfully.
The Extended Noweb Syntax option in the Preferences panel is gone. This option has always been deprecated.
Version 0.18 changes the file format in an upward compatible way. That is, version 0.18 can read all previous versions of Leo files, but you must have version 0.18 of Leo to read files written by version 0.18.
Fixed a bug that caused @doc section not to be output properly for those languages like Fortran and Perl that do not have block comments.
The @noheader directive suppresses the header line normal written by Tangle at the start of each derived file. The @noheader directive is especially useful in Perl. Also added the corresponding "Tangle outputs header line" checkbox in the preferences panel. This checkbox sets the default which may be over-ridden by the @header or @noheader directives.
@language fortran specifies that comments start with C. @language fortran90 specifies that comments start with !.
@language perlpod specifies the Perl language with block comments being delimited by =pod and =cut
Version 0.17 fixes some bugs and puts some finishing touches on Leo.

The Borland C++ Builder version of Leo is now feature complete; there are no further items on the to-do list. Yes, I'll be happy to fix bugs or add urgently needed features.
Tangle and Untangle now treat <<*>>= as a synonym for @root filename if the _headline_ starts with text of the form @root filename. This convention allows full compatibility with noweb.
The @path, @tabwidth and @pagewidth directives are new.

These directives allow the user to override the defaults specified in the Prefs panel on a file-by-file basis. For the first time, every option in the Preferences panel may be overridden by a directive.
I fixed several severe bugs involving CWEB mode. It is now possible to tangle and untangle files when in CWEB mode, though CWEB mode has still not been tested thoroughly.
Reduced the default size of Leo windows so that they can be more easily resized on a small screen.
Version 0.16 is a significant new release of Leo. All users of the PC version of Leo should upgrade to version 0.16.

Significant changes have been made to Tangle and Untangle: these commands should now be able to handle code in almost any language. The new @language directive specifies the comment and string conventions used when Tangling and Untangling.

The @verbose, @terse and @silent directives are new: they control how Tangle outputs comments.

The Import Files command now handles Pascal, Python and Java files in addition to C and C++ files.

Besides the major changes a number of bug fixes and other minor features have been added.

Acknowledgments: Thanks to Zak Greant for numerous suggestions and bug fixes, and to Garold Johnson for improving this file.
Version 0.16 fixes all bugs mentioned on the SourceForge site as of April 27, 2000. These bugs involved problems with

@comment <empty> @comment 2 delims Not inheriting @comment properly non-delimited filenames in @root directives Crashes while Tangling Problems with Untangle with languages other than C.

Later sections discuss some of these in more detail.
Version 0.16 fixes a crasher related to changing windows.

This _may_ have been the source of crashes when cutting and pasting outlines, but don't count on it! Make sure you back up files _before_ cutting and pasting outlines!
The @language directive is new. The @language directive actually specifies the comment delimiters and string types used by the Tangle and Untangle.

The form of this directive is

@language x

where x is one of the following: c,c++,html,java,objective-c,pascal,perl,python and shell. Shell files have comments that start with #. Case is ignored in the language specifiers, but not in the @language itself. Thus, the following are equivalent:

@language html @language HTML @language hTmL

but the following is invalid:

@LANGUAGE html

The @comment directive is now officially deprecated: you should use the @language directive whenever possible. At present Untangle will not process an @root or @unit node if an @comment directive is in effect. Why? Because Untangle can't be sure of properly parsing a derived file if the language of the derived file isn't known. It might be possible to assume some defaults in this case, but that is not done at present and is not a high priority.
Scanning for @directives is now much faster. As a result, the @language and @comment directives will be recognized anywhere in an outline. This means

1) child nodes will "inherit" @language or @comment directives from ancestors unless over-ridden in the child node and

2) @language and @comment directives need not be placed in @unit or @root nodes. This is a much more intuitive and powerful way of handling these directives.
Key parts of the untangle logic have been generalized so that they can handle essentially any computer language. The following routines no longer have any C-specific code and have essentially been completely rewritten:

scan_derived_file (formerly scan_c_file) forgiving_compare (formerly c_compare)

Tangle now will properly output comments using the present comment delimiters as specified by either the @language directive or the @comment directive. As mentioned before, you should use @language instead of @comment wherever possible.
As a side effect of the Untangle command, Leo now removes trailing blank lines from the body text of all nodes being untangled. This finally crushes a long-standing bug. If the body text ends with one or more blank lines, the altered body text contains exactly one trailing newline.

Nodes that are altered in this way are not marked, nor is the file-changed mark set. This seems to be the most appropriate action to take: it would be confusing to prompt the user to save a changed file if the only changes involve trailing whitespace.
The @verbose, @terse and @silent directives determine how Tangle outputs comments. When @verbose is in effect Tangle outputs all comments. When @terse is in effect, Tangle outputs only those comments necessary for Untangle to work. When @silent is in effect Tangle no additional comments. Note: comments written by the user in code sections are always output: these directives control only:

1. The comments containing doc chunks and 2. Sentinel comments that delimit the beginning and end of code chunks.

@verbose is the default. If more than one of these directives appear in the same body text the "most verbose" of these options will be in effect.
At long last Leo has a useful notion of default directory. By default, the default directory is the directory containing the .leo file. This may be over-ridden using the "Tangle Default Directory" option in the Preferences panel.

The default directory is used whenever a file name in an @root directive contains no path component.
The Import Files command looks at the file extension to see how it should handle files.

Extension Language .c C .cpp C++ .java Java .pas Pascal .py Python

If the extension is not one of the above the Import files commands merely puts the entire file into the body text of a single node.

The Import Files command probably needs quite a bit of work.
Control-T now changes the pane that is currently active. If the outline pane was active, the body pane becomes active, and vice versa. This command makes it possible to switch between panes without using the mouse.
In previous versions of leo.leo I used slash instead of backslash as path delimiters. This should never have worked, but somehow it did. The present code uses the correct backslash in all @root directives.
Many improvements were made to the code. See the diary section of leo.leo if you are interested. In particular, I created args.h and args.c to define arguments. This cleans up the code quite a bit.
Changed Tangle and Untangle so that empty section names like << >> and << >>= are treated as ordinary characters. No warning is issued, which is debatable.
As mentioned in the main documentation, you must not change sentinel lines in derived files in any way. In particular, if you change the section name in a sentinel line Untangle will not update the code in the outline (with the old name) that generated the renamed section. Untangle now warns about sections that appear in a derived file but not in the outline. Untangle has no trouble with changed section references in derived files; it is only changed sentinel lines that cause problems.
Leo is being used to develop HTML files for web sites. In this context it is natural to define sections that are shared between files. Don't expect Untangle to update such sections if you make changes to them in derived files. The natural place to change sections shared by several roots is in the outline, not in the files derived from the outline.

If you do change code in a derived file that appears in several derived files, and try to use Untangle to update the code in the outline one of two things will happen:

1) You untangle an @root node. Untangle will never compare examine the common section of code for changes, as the common section appear under a @unit node, not the @root node. Untangle will complain about an orphan node.

2) You untangle an @unit node. Untangle will examine each @root node under the @unit node. Unless the change is made in the last root examined, Untangle will propagate the change when it first sees it, then go right ahead and undo the change when it sees the next expansion of the node in a derived file.

Untangle tests for inconsistent expansions of a section only within a single derived file. Such tests are not done between different derived files because we do not want disallow sections with the same names in different roots.
Known bugs and limitations in all versions of Leo.

1. Untangle has no way of updating a section(chunk) whose name has been changed in the derived file. Because of the @unit directive, there is not even a way to issue a meaningful warning.

2. Tangle treats @c like @code when in CWEB mode. I recommend changing @c to @< c @>= throughout your CWEB sources and adding a reference to @< c @> in all roots of CWEB files.

Known bugs and limitations of the PC version of Leo.

Syntax coloring options are not saved to the file.

The Log window has a limited capacity. This mainly affects debugging traces but could affect the output from the Tangle or Untangle commands if you tangled or untangled a large number of files.
The Execute Script command executes body text as a Python script. Leo execute the selected text, or the entire body text if no text is selected.

Scripts are executed in a "pristine" environment, that is, with __builtins__ as both the local and global environments.

New in version 4.1: Body text may now contain @directives and section references. This is a major step forward: you can now use all of Leo's features to organize scripts that you execute interactively.

Section definitions must appear in the node containing the script or in descendant nodes. Leo "preprocesses" all scripts by simulating the writing of a derived file to a string.

The Execute Script command sets app.scriptDict["script1"] to the value of the script before preprocessing, and sets app.scriptDict["script2"] to the value of the script after preprocessing. Scripts may examine and change app.scriptDict as they please.
Leo does an auto-save only if something has actually been changed.
The config_encoding setting controls the encoding of non-ascii characters in leoConfig.txt.

The use_gnx setting in leoConfig.txt determines whether uses gnx's (cvs friendly) or ints. No version of Leo before 4.1 can read .leo files containing gnx. Only gnx's are immutable. Leo recomputes all non-gnx indices from scratch whenever writing a .leo file. It is possible to convert between 3.x and 4.1 file formats by changing the use_gnx setting.
Leo 4.1 beta 5 December 5, 2003

This is the fifth release of the reorganized 4.1 code base.

For the first time in months there are no serious bugs outstanding.

Warning: By default Leo 4.1 creates .leo files that can not be read by older versions of Leo.

Warning: Use the __wx_gui.py plugin with extreme caution until further notice: bugs in this plugin could cause body text to be cleared improperly when changing nodes.

Beta 5: * Leo runs in batch mode when invoked with --script aScriptFile.py - Created "null gui" classes that do not use any gui code. * Leo supports Unicode characters (e.g. Chinese) in path and file names. * Fixed several long-standing bugs: - Fixed several minor problems with the Extract Section and Import commands. - Fixed problem that prevent the Find panel from working on the Mac. - Improved @url handling so that @url file:\\path\x.leo works properly. - Improved support for @lineending platform. - Leo honors outline/body pane ratio when opening .leo files. - Leo now ensures that newly-opened windows fit entirely on the screen. - Fixed a crasher when Undoing a Change All command when searching headlines. - Fixed other bugs resulting from the 4.1 reorg: - Fixed problem loading plugins on Linux. - Fixed crashers in the Extract Section and Extract commands. - Fixed a crasher when writing a file containing an undefined section. - Removed duplicate bindings in popup menus. - Made sure to show Leo's windows in wx gui plugin.

Beta 4: - Fixed several "reorg" bugs, some of which affected plugins. - Allow @directives and section references when executing scripts! - More than one section reference may now appear on the same line. - Use "utf-8" encoding for filenames under MacOS (Darwin) - Allow command or cmnd prefix for menu shortcuts under Darwin.

Beta 3: - Completed the reorg, making many changes to the code base. - Fixed a LaTeX coloring bug

Beta 2: - Fixed a startup problem on Linux: the "mbcs" text encoding is not valid on Linux.

Beta 1: * Script-based find/change commands. - Hoist & DeHoist commands for viewing parts of an outline. - Check Outline command finds user clone mistakes. * New configuration settings: - use_gnx specifies whether .leo files use integers as indices: use_gnx = 0 makes .leo files compatible with previous versions of Leo. use_gnx = 1 makes .leo files cvs-friendly - config_encoding specifies the encoding of leoConfig.txt. * Several significant code-level changes: - The 4.1 code base has been reorganized to support gui plugins. - An example wx_gui plugin is partly functional. - Created a flexible framework for creating & running regression tests. - app.forceShutdown now works when called from plugins.
Leo 4.1 uses immutable gnx's (id:timestamp:n) by default to associate tnodes with vnodes in .leo files. This makes Leo as cvs friendly as possible. From now on .leo files will be checked in to cvs with the -ko (text/keywords off) option.
The file test.leo in the test directory contains real regression tests for syntax coloring. Regression testing scripts create regression tests dynamically from data in Leo's outline. Very cool, very easy, very general. In particular, regression tests may use temporary nodes in test.leo rather than creating separate Tk windows for testing.
The 4.1 code base has been reorganized to support gui's other than tkinter. Leo's src directory contains several new source files.

This reorg affects almost all plugins. Considerably more work and testing will be done before 4.1 final.

The __wx_gui.py plugin is uses the newly reorganized code. It is functional except for gui-dependent commands like Toggle-Split Direction. WARNING: treat the this plugin with extreme caution until further notice. The possibility exists that bugs in the code could cause body text to be cleared improperly when changing nodes.
This involved fixing a bug in idle_body_key so that the oldText param is honored if present.
@nocolor

New in 4.1: Leo now supports scripts in Leo's Find/Change dialog.

Leo's find panel now contains the Script Search radio button and the Script Change checkbox. When the Script Search radio button is selected Leo treats the contents of the Search Text as a script to execute whenever any kind of Find command is executed. Similarly, when the Script Change checkbox is selected Leo treats the context of the Change Text as a script to execute whenever any kind of Change command is executed. See below for just how this works.

Script-based find-change is extremely powerful. In effect, Leo's Find/Change panel becomes a new platform for running scripts interactively. Leo now has all the find/change capability of pattern matching languages like Snobol and Icon, just by using the capabilities of the plain Python language. Moreover, Leo can deliver these capabilities interactively or not depending which buttons you push in Leo's Find/Change panel.

Script-based find/change frees the user from having to control script-based searches interactively. Rather than forcing find/change scripts to implement their own interactive controls, it is much easier to use what Leo already has.
Undoing Change All cleared the body pane or the headline pane.

The fix was simple: call setUndoParams instead of setUndoTypingParams in batchChange.
The node-only option wasn't working due to a bug in createFrame.

There still may be a problem with the interaction between Node-only,Change All and Undo.
The fix was to open files with 'rb' instead of 'r'. This probably should be done in more places.
This command checks for unused tnodeLists and checks the topology of all clones.
The Hoist command redraws the screen so presently selected tree becomes the only visible part of the outline. Leo prevents the you from moving nodes outside the hoisted outline. The De-hoist command restores the outline. Hoist commands may be nested.
Leo dedicates a Python dictionary called app.searchDict for communication between Leo and the search and change scripts. The search and change scripts may also use app.searchDict for communication between themselves. Leo sets app.searchDict["type"] to "find", "change", "findAll" or "changeAll" to indicate the kind of command being executed. Scripts may use all other entries in app.searchDict as they please.

Leo executes the find script once when you press the Find button (or the Change then Find button) in Leo's Find/Change dialog. Typically, the find script would traversing the tree and highlight the found text or otherwise indicate to the user that the find operation has succeeded. However, the script can do anything it pleases.

Leo executes the the find script repeatedly when you press the Find All button. Leo keeps executing the find script until app.searchDict["continue"] evaluates to false. Initially there is no entry for app.searchDict["continue"], so the find script must set app.searchDict["continue"] = true if it wants Leo to keep executing it.

Leo executes the change script once when you press the Change button. Typically, the change script would change the selected text. Usually the change script will compute the new value of body text and call c.setBodyString(p,newText) to make that change permanent.

The change script also may handle undo, typically by calling c.frame.onBodyChanged(v,"Change",oldText=oldText). Leo does not handle undo automatically. Indeed, Leo makes no assumptions whatever about what the change script really does.

Leo executes the the change script repeatedly when you press the Change All button. Just as with the Find All command, Leo keeps executing the change script until app.searchDict["continue"] evaluates to false.

Most find and change scripts will ignore settings in the Find Panel like "whole word", "pattern match", and "reverse". However, these settings are available to the scripts via ivars such as c.whole_word_flag, etc. if desired.
@nocolor

Some ideas for using scripts:

Either the find and change scripts may use Python's re module. For example, the find script could set app.searchDict["m"] to the match object returned by re's match method. The change script would then compute the result, change the text and set the undo info as usual.

There is no reason to confine find/change scripts to operate on data only within a Leo outline. These scripts could as easily traverse your file system as the Leo outline. But notice: scripts could pull data from the file system into the outline so that you can see the effects of changes as the scripts operate. Again, this can all happen interactively if you like.
@color @ New in version 4.1: On startup, Leo looks for two arguments of the form --script scriptFile. If found, Leo enters batch mode.

In batch mode Leo does not show any windows. Leo assumes the scriptFile contains a Python script and executes the contents of that file using Leo's Execute Script command. By default, Leo sends all output to Leo's log pane to the console window. Scripts in the scriptFile may disable or enable this output by calling app.log.disable() or app.log.enable()

Scripts in the scriptFile may execute any of Leo's commands except the Edit Body and Edit Headline commands. Those commands require interaction with the user.

For example, the following batch script reads a Leo file and prints all the headlines in that file. @c

import leoGlobals as g

path = r"c:\prog\leoCVS\leo\test\test.leo"

g.app.log.disable() # disable reading messages while opening the file flag,newFrame = g.openWithFileName(path,None) g.app.log.enable() # re-enable the log.

for p in newFrame.c.allNodes_iter(): g.es(g.toEncodedString(p.headString(),"utf-8"))
Another 4.1 reorg bug.
This was due to a missing activate event.
Continuation lines caused the import command to terminate functions, methods and classes prematurely.
This was causing Leo not to load plugins properly on Linux. The problem was that the imp module does not handle Unicode file names properly.
This was a reorg bug.
Another bug caused by the 4.1 reorg.
- Leo now properly enables and disables the Extract Section menu item. - Leo no longer removes leading forward slashes in section names in headlines. - Corrected the documentation for the Extract Section command.
Another 4.1 reorg bug.
This bug has been around for a long time.
The new code attempts to use bitmap files only on Windows.
Leo makes sure that opened files or newly-created outlines fit entirely on the screen. The Cascade commands leaves the sizes of windows unchanged: it merely ensures that the top left corner of a window is visible on the screen.
@ A problem: the new window gets put behind the old. This is probably because Tk thinks that the mouse-down event should select then new window...
Plugins may create (or add to) v.tempAttributes (for vnodes) or t.tempAttributes (for tnodes). These will work just like the corresponding unknownAttributes dicts except that Leo will _not_ read or write these dictionaries when reading or writing files. Note: nothing needs to change in Leo to support this convention.
@nocolor

We wish to avoid the possibility that two plugins might unwittingly choose the same name for attributes in the unknownAttributes or tempAttributes dictionaries. The following convention eliminates that possibility.

Each plugin should create its own dictionary _inside_ any tempAttributes or unknownAttributes dictionaries that it intends to create or modify. Something like this:

@color

# Create the tempAttributes dict for this vnode. if not v.hasattr("tempAttributes"): v.tempAttributes = {}

# Create a subdictionary for the private use of my plugin. d = v.tempAttributes.get("myPluginName") if d is None: v.tempAttributes["myPluginName"] = d = {}

@nocolor

Now the plugin can set and get fields in d. Similar code would be used for the t.tempAttributes, v.unknownAttributes and t.unknownAttributes dictionaries.
Leo 4.1 Release Candidate 3 December 19, 2003

This release fixes a serious bug in the logic that reads old-style derived files.

There are no known bugs in this version of Leo.

The highlights of this release:

- Leo runs in batch mode when invoked with --script aScriptFile.py - Leo supports Unicode characters (e.g. Chinese) in path and file names. - @directives and section references are now valid when executing scripts. - @ignored and orphan nodes now valid in @file-nosent trees. - Script-based find/change commands. - Check Outline command. - Hoist & DeHoist commands. - A new gui-agnostic architecture: useful for batch mode and unit tests. - Several new configuration settings. - Many new unit tests. - A host of bug fixes.
See previous release notes for more details:

- Fixed several minor problems with the Extract Section and Import commands. - Fixed problem that prevent the Find panel from working on the Mac. - Improved @url handling so that @url file:\\path\x.leo works properly. - Improved support for @lineending platform. - Leo honors outline/body pane ratio when opening .leo files. - Leo now ensures that newly-opened windows fit entirely on the screen. - Fixed a crasher when Undoing a Change All command when searching headlines. - Fixed other bugs resulting from the 4.1 reorg: - Fixed problem loading plugins on Linux. - Fixed crashers in the Extract Section and Extract commands. - Fixed a crasher when writing a file containing an undefined section. - Removed duplicate bindings in popup menus. - Made sure to show Leo's windows in wx gui plugin. - More than one section reference may now appear on the same line. - Use "utf-8" encoding for filenames under MacOS (Darwin) - Allow command or cmnd prefix for menu shortcuts under Darwin. - Fixed a LaTeX coloring bug
- The 4.1 code base has been reorganized to support gui plugins. - Created a flexible framework for creating & running regression tests. - app.forceShutdown now works when called from plugins. - Created app.unitTestDict for communication between tests and between tests and code.

- An example wx_gui plugin is partly functional.

Warning: Use the __wx_gui.py plugin with extreme caution until further notice: bugs in this plugin could cause body text to be cleared improperly when changing nodes.
- use_gnx specifies whether .leo files use integers as indices:

use_gnx = 0 makes .leo files compatible with previous versions of Leo. use_gnx = 1 makes .leo files cvs-friendly

- config_encoding specifies the encoding of leoConfig.txt.
- Import Derived File command now uses a file dialog.

This is much more natural than using @file nodes.

- Leo now loads all plugins listed in pluginsManager.text.

It is no longer necessary to edit plugin files to enable or disable plugins.
New in 4.1: The plugins test suite creates a new convention: if a plugin has a function at the outer (module) level called unitTest, Leo will call that function when doing unit testing for plugins. So it would be good if writers of plugins would create such a unitTest function. The unitTest function should run some tests. All unitTest needs to do to indicate failure is throw an exception or cause an assert to fail. Leo's plugins test suite takes care of the rest.
- Corrected counts when replacing tabs/blanks. - Don't write tnodeList when executing scripts. - Fixed long-standing clone-drag bug. - Fixed inconsistency between how 4.x and 3.x handle @others. The code now works as it did in all 3.x versions, namely @others does not terminate doc parts. - Leo now properly sets clone marks when when cutting and pasting nodes. - Only double-quotes delimit strings in html files. This bug prevented Leo from untangling some valid html/xml files. - Leo now puts class docstrings in class nodes when importing .py files. - Fixed several reorg bugs.
Leo 4.1 Release Candidate 4 February 3, 2004

This release fixes numerous bugs reported since 4.1 rc3 and makes several other minor improvements, including several nifty new plugins.

The highlights of Leo 4.1:

- Leo runs in batch mode when invoked with --script aScriptFile.py - Leo supports Unicode characters (e.g. Chinese) in path and file names. - @directives and section references are now valid when executing scripts. - @ignored and orphan nodes now valid in @file-nosent trees. - Script-based find/change commands. - Check Outline command. - Hoist & DeHoist commands. - A new gui-agnostic architecture: useful for batch mode and unit tests. - Several new configuration settings. - Many new unit tests. - Excellent new plugins. - A host of bug fixes.
See previous release notes for more details:

4.1 rc3:

- Corrected counts when replacing tabs/blanks. - Don't write tnodeList when executing scripts. - Fixed long-standing clone-drag bug. - Fixed inconsistency between how 4.x and 3.x handle @others. The code now works as it did in all 3.x versions, namely @others does not terminate doc parts. - Leo now properly sets clone marks when when cutting and pasting nodes. - Only double-quotes delimit strings in html files. This bug prevented Leo from untangling some valid html/xml files. - Leo now puts class docstrings in class nodes when importing .py files. - Fixed several reorg bugs.

4.1 rc2, rc1, betas, alphas:

- Fixed several minor problems with the Extract Section and Import commands. - Fixed problem that prevent the Find panel from working on the Mac. - Improved @url handling so that @url file:\\path\x.leo works properly. - Improved support for @lineending platform. - Leo honors outline/body pane ratio when opening .leo files. - Leo now ensures that newly-opened windows fit entirely on the screen. - Fixed a crasher when Undoing a Change All command when searching headlines. - Fixed other bugs resulting from the 4.1 reorg: - Fixed problem loading plugins on Linux. - Fixed crashers in the Extract Section and Extract commands. - Fixed a crasher when writing a file containing an undefined section. - Removed duplicate bindings in popup menus. - Made sure to show Leo's windows in wx gui plugin. - More than one section reference may now appear on the same line. - Use "utf-8" encoding for filenames under MacOS (Darwin) - Allow command or cmnd prefix for menu shortcuts under Darwin. - Fixed a LaTeX coloring bug
- The 4.1 code base has been reorganized to support gui plugins. - Created a flexible framework for creating & running regression tests. - app.forceShutdown now works when called from plugins. - Created app.unitTestDict for communication between tests and between tests and code.

- An example wx_gui plugin is partly functional.

Warning: Use the __wx_gui.py plugin with extreme caution until further notice: bugs in this plugin could cause body text to be cleared improperly when changing nodes.
- use_gnx specifies whether .leo files use integers as indices:

use_gnx = 0 makes .leo files compatible with previous versions of Leo. use_gnx = 1 makes .leo files cvs-friendly

- config_encoding specifies the encoding of leoConfig.txt.
- Import Derived File command now uses a file dialog.

This is much more natural than using @file nodes.

- Leo now loads all plugins listed in pluginsManager.text.

It is no longer necessary to edit plugin files to enable or disable plugins.
This allows plugins to draw the status area in the icon area.
The old code was concatenating strings; the new code uses list.append.
- ESC closes the Find panel.

- Hitting the Return key is now equivalent to hitting the Find button.
Leo now reports the parent of the orphan node.
This bug happened when a move up command would cause a node to become the sibling of (a clone of) itself. In such cases, Leo simply selects the other cloned copy of the moved node.
The bug was causing Leo not to remember the comment delimiters in the @+leo sentinel. As a result, Leo was recognizing no sentinels and the command complained about missing @-leo sentinels.
- Leo now does a better job of checking and reporting read-only violations.

- Leo now clears the file-dirty mark only if the file was successfully saved.

Leo sets only ancestor @file nodes dirty (not nodes themselves) when altering outline structure, i.e., when moving, inserting, deleting, cloning and sorting nodes.
That is, when preprocessing the script (expanding section references, etc.) Leo now ensures that child nodes effectively end in a newline. This prevents unintended concatenation of lines.
A contained a space before a tab in the leading whitespace of the line.
- These commands did not properly count the number of changed nodes. - These commands now mark only changed nodes as dirty.
Fixed crashers in:

- Insert Headline Time/Date commands. - Change headline command. - Write Dirty/Missing @file Nodes commands. - Batch mode.
- Fixed a bug that caused cut and paste operations in headlines to revert when those commands were chosen from the Edit menu.

- Extended control-v bug fix to "darwin","freebsd4","freebsd5"

- Cut and paste are now always enabled when not editing the body pane. This isn't perfect, and is an improvement.
1. Fixed a bug that caused improper indentation of sections.

The bug happened in some cases when a section reference occurred following non-whitespace.

2. Leo ensures that leading whitespace is not added when writing empty lines.

This might fix the "Zope Sprint" bug: "blank" lines in the expansion of @others got leading whitespace.
Previously, if you hoist a node with no children and then insert a node (CTRL-I) then the child is created as a sibling of the hoisted node and consequently is not displayed.

Leo now creates the new node as the first child of the hoisted node.

Also, Leo disables the Clone command when the presently selected node is the root of a hoist.
This creates a status area at the bottom of the Leo Window. Plugins may write to this area using the status area convenience routines in leoTkinterFrame.py.
@nocolor

The Scripts node in LeoPy.leo contains a script called initScriptFind. This script makes it easy to set up script based searches as follows:

1. Put the following code in the root of a tree that will contain your script search:

@color # Initialize Leo's find panel using the named children of this node. from leoGlobals import * initScriptFind("Find script","Change script") # Second argument is optional. # Start searching at the top. top().selectVnode(c.rootVnode()) @nocolor

2. Put the search script in a child node called "Find script" (no quotes).

3. (Optional) Put the change script in a child node called "Change script"

4. Execute the code above. Leo does the following:

- Puts the body of the "Find script" into the find text of Leo's Find/Change dialog. - Puts the body of the "Change script" into the change text of Leo's Find/Change dialog. - Selects the Script Find radio button. - Selects the Script Change checkbox if the change script exists. - Selects the root of the entire outline.

Presto! Leo is ready for a script search.
This plugin uses Leo and docutils to mix program code and reST documentation.

The Python docutils package must be installed.http://docutils.sourceforge.net

If SilverCity is installed (http://silvercity.sourceforge.net) the plugin produces HTML output that is syntax colored.

The basic approach is that any Leo node that contains program code that needs documentation (in an ideal world it would be every node) has an associated child node whose headline is simply '@rst', that contains reST-style documentation. While this means that a typical program may have dozens (if not hundreds) of these @rst nodes, it produces documentation that I think is as close as I have ever seen to useful, easy-to-read documentation that is easy to create at the same time as an application is being coded.

There are several interrelated aspects to this work:

- The reST plugin (renamed rst2) was hacked to manage Leo outlines that were a combination of normal code nodes and reSt nodes.

- The plugin now recognizes a @rst directive (that has no associated file name) in the headline of a node.

- When it encounters such a @rst Headline node, it writes the contents of the body of the @rst node's *parent* (which generally contains program code) to the reST output file (HTML) and then adds the reST content that is contained in the body of the @rst documentation node to the output HTML file,

- These @rst nodes are used in @file-nosent trees and the @rst nodes have an @ignore directive (plus @nocolor directive and @wrap directives) so that when the @file is updated the application code does not contain the reST-style documentation contained in the body of the @rst nodes. (This was the reason I had asked you in the Leo Forum to allow @file-nosent trees to work appropriately with @ignore nodes - Thank you for doing this right away.) There is no reason that the reST content couldn't be written to the @file as documentation other than I personally believe in a volume of documentation (including musings, failed ideas, questions, etc.) that is probably best kept separate from the actual *.py files.

- When you double-click on a plain rst node (no associated filename) Leo opens both the @rst documentation node and the parent node containing code in an external editor *simultaneously*. I happen to use Textpad and so the code is opened with python syntax coloring in one Textpad window and right next to it is the reST documentation. This makes it much much easier to code and do documentation at the same time. (Note that the plugin assumes that the python extension is '.tp' since that is what I use with TextPad.)

So why is this a big deal?

For the first time in my experience the documentation process:

1) is completely in sync with the process of code development.

2) allows the programmer to write as much documentation as he/she wants without the programming code becoming unreadable because of what would be considered excessive or intrusive documentation. (This applies whether documentation is intended for external consumption or just so a solo programmer can remember what he/she was thinking...)

My conclusion is that Leo + reST/docutils provides the perfect platform for optimal documentation. I have never completely understood what is meant by Literate Programming but in my mind this is practical Literate Programming.

Frankly, I think this is all a minor miracle but maybe I've lost perspective.

Steve Zatz
Adds a quick search to the toolbar in Leo.

A search box which behaves like a web site search is added, along with a "GO" button to do quick searches right from the main Leo window. All the current search options are retained except that "search body text" is explicitly set - mainly because this is by far the most common use case.

Pressing <CR> while editing the text automatically does a search. Repeated searches can be done by clicking the "GO" button.

The combo box also stores a list of previous searches, which can be selected to quickly repeat a search. When activating a previous search the original search mode is used.

Still to do:

- incremental search - reverse search - persist recent searches across Leo sessions - use INI file to set options for list size, etc.
Adds a node navigator to the toolbar. The navigator allows quick access to marked nodes. You can either go to the marked node or hoist the marked node.
Adds row/column indicators to the toolbar at the top of Leo Windows.
A minimal http plugin for LEO, based on AsyncHttpServer.py.

Use this plugin is as follows:

1. Start Leo with the plugin enabled. You will see a purple message that says something like: "http serving enabled on port 8080, version 0.9"

2. Start a web browser, and enter the following url: http://localhost:8080/ You will see a a "top" level page containing one link for every open .leo file. Start clicking :-)

You can use the browser's refresh button to update the top-level view in the browser after you have opened or closed files.
Automatically add nodes for common tasks. This can be used to generate boiler plate code to quickly build an outline.
This bug happened when executing the initScriptFind script. This bug could cause Leo not to be able to save files.
Adds a status line to the bottom of Leo windows.
The Change All command was looping when the find pattern was '\n'.
Leo 4.1 Final February 20, 2004

Leo 4.1 Final is the culmination of four months of work. No significant bugs have been reported since 4.1 rc4. Several people have contributed nifty plugins recently. See leoPlugins.leo for full details.

The highlights of Leo 4.1:

- Leo runs in batch mode when invoked with --script aScriptFile.py - Leo supports Unicode characters (e.g. Chinese) in path and file names. - @directives and section references are now valid when executing scripts. - @ignored and orphan nodes now valid in @file-nosent trees. - Script-based find/change commands. - Check Outline command. - Hoist & DeHoist commands. - A new gui-agnostic architecture: useful for batch mode and unit tests. - Several new configuration settings. - Many new unit tests. - Excellent new plugins. - A host of bug fixes.
Changed Undo/Redo messages:

- Insert Outline to Insert Node. - Delete Outline to Delete Node. - Clone to Clone Node.

This is a real code change: it affects the undo/redo logic.
Clone bits could be improperly set in some cases. This bug would not have caused serious long-term problems.

Steps to reproduce:

1. Create a parent node (named 'cloned'). 2. Create two children nodes (one named 'dummy' and another named 'bottom') under the parent node 'cloned'. 3. Move the 'bottom' node below the 'dummy' node. 4. Clone node 'cloned'. 5. Copy node 'dummy'. 6. Paste node 'dummy' in between 'dummy' and 'bottom'. 7. After pasting you'll see that 'bottom' is now marked as a cloned node.
See leoPlugins.leo for full details.
Here is the bug report I submitted to Python:

The documentation for encoding lines at

C:\Python23\Doc\Python-Docs-2.3.1\whatsnew\section-encodings.html

states:

"Encodings are declared by including a specially formatted comment in the first or second line of the source file."

In fact, contrary to the implication, the Python 2.3 parser does not look for lines of the form:

# -*- coding: <encoding> -*-

For example, Python improperly scans the following line for an encoding

#@+leo-ver=4-encoding=iso-8859-1.

and reports that iso-8859-1. (note trailing dot) is an invalid encoding!

The workaround for my app is to precede this line with the following line:

# -*- coding: iso-8859-1 -*-

This makes Python 2.3 happy.

To make myself perfectly clear: Python has absolutely no right to complain about comment lines that do not have the form:

# -*- coding: <encoding> -*-
@ @rst-options code_mode=False generate_rst=True http_server_support = False .. .. A very cool option: doc parts will be rendered properly, .. but will be ignored by the Execute script command. .. show_doc_parts_as_paragraphs = True show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|back| |leo| |next|

#################################### Chapter 7: Scripting Leo with Python ####################################

This chapter is a tutorial describing how to write Python scripts that get and modify data contained in Leo outlines. Scripts use Leo's, **vnode**, **tnode** and **position** classes to access data in Leo outlines. The combination of a vnode v and its tnode v.t represents a node's data. Leo needs both vnodes and tnodes to represent clones efficiently. Indeed, a tnode represents all data shared by cloned nodes. When Leo clones a vnode v, Leo creates a new, independent vnode v2 and sets v2.t == v.t. Thus, cloning a node does not duplicate any information in descendant trees, but descendants of a cloned node appear more than once on the screen (when all nodes are expanded). Positions represent a node at a particular place on the screen. Equivalently, a position indicates a particular place in a tree traversal. Iterators of the position class define various kinds of tree traversals.

Leo's execute-script command predefines several symbols. This makes it easy to access the data in Leo outlines and the Leo's own source code. g is predefined to the leoGlobals module. Scripts commonly use utility functions such as g.es, g.trace, etc. The g.app object represents Leo itself. The instance vars (ivars) of g.app are Leo's global variables and constants. The execute-script command predefines c to be the commander (see below) of the Leo outline in which the script is contained. Whenever possible, scripts should use the high-level methods of the commander to insert, delete or clone nodes. Finally, the execute-script commands predefines p to be the presently selected position.

This chapter describes only some of Leo's functions, classes and methods. However, your scripts have complete access to all of Leo's source code, that is, all the code in ``LeoPy.leo``. You are not limited by what you see in this chapter.

.. contents::
The g.es method prints its arguments to the Log tab of the log pane::

g.es("Hello world")

g.es converts non-string arguments using repr::

g.es(c)

g.es prints multiple arguments separated by commas::

g.es("Hello","world")

To create a tab named 'Test' or make it visible if it already exists::

c.frame.log.selectTab('Test')

When first created, a tab contains a Tk.Text widget. To write to this widget, add the tabName argument to g.es::

g.es('Test',color='blue',tabName='Test')
``leoGlobals.py`` defines 6 convenience methods for redirecting stdout and stderr::

g.redirectStderr() # Redirect stderr to the current log pane. g.redirectStdout() # Redirect stdout to the current log pane. g.restoreStderr() # Restores stderr so it prints to the console window. g.restoreStdout() # Restores stdout so it prints to the console window. g.stdErrIsRedirected() # Returns True if the stderr stream is redirected to the log pane. g.stdOutIsRedirected() # Returns True if the stdout stream is redirected to the log pane.

Calls need *not* be paired. Redundant calls are ignored and the last call made controls where output for each stream goes. **Note**: you must execute Leo in a console window to see non-redirected output from the print statement::

print "stdout isRedirected:", g.stdOutIsRedirected() print "stderr isRedirected:", g.stdErrIsRedirected()

g.redirectStderr() print "stdout isRedirected:", g.stdOutIsRedirected() print "stderr isRedirected:", g.stdErrIsRedirected()

g.redirectStdout() print "stdout isRedirected:", g.stdOutIsRedirected() print "stderr isRedirected:", g.stdErrIsRedirected()

g.restoreStderr() print "stdout isRedirected:", g.stdOutIsRedirected() print "stderr isRedirected:", g.stdErrIsRedirected()

g.restoreStdout() print "stdout isRedirected:", g.stdOutIsRedirected() print "stderr isRedirected:", g.stdErrIsRedirected()
Here is how to access the data of a Leo window::

g.es(p) # p is already defined. p = c.currentPosition() # get the current position. g.es(p) g.es("head:",p.headString()) g.es("body:",p.bodyString())

Here is how to access data at position ``p``. **Note**: these methods work whether or not ``p`` is the current position::

body = p.bodyString() head = p.headString() c.setBodyString(p,body) # set body text of p to body. c.setHeadString(p,head) # set headline text of p to head.
The proper way to traverse an outline is with an iterator. Iterators are defined only by the position class; vnodes can not have iterators because vnodes may appear in multiple places in an outline.
The ``c.allNodes_iter`` iterator returns a list of all positions in the outline. This script makes a list of all the nodes in an outline::

nodes = [p for p in c.allNodes_iter()] g.es("This outline contains %d nodes" % len(nodes))

Here is one way to count the nodes of an outline::

count = 0 for p in c.allNodes_iter(): count += 1 g.es("This outline contains %d nodes" % count)

Here is a way to count the *distinct* vnodes of an outline::

positions = 0 ; tnodes = {} for p in c.allNodes_iter(): positions += 1 if not tnodes.get(p.v.t): tnodes[p.v.t] = p.v.t g.es("%8s positions" % positions) g.es("%8s vnodes" % len(tnodes.keys()))
The ``p.children_iter`` iterator returns a list of all children of position ``p``::

parent = p.parent() g.es("children of %s" % parent.headString(),color="purple") for p in parent.children_iter(): g.es(p.headString())
The ``p.parents_iter`` iterator returns a list of all parents of position ``p``, excluding ``p``::

current = p.copy() g.es("inclusive parents of %s" % current.headString(),color="purple") for p in current.self_and_parents_iter(): g.es(p.headString())

The ``p.self_and_parents_iter`` iterator returns a list of all parents of position ``p``, including ``p``::

current = p.copy() g.es("exclusive of %s" % current.headString(),color="purple") for p in current.parents_iter(): g.es(p.headString())
The ``p.siblings_iter`` iterator returns a list of all siblings of position ``p``::

current = c.currentPosition() g.es("all siblings of %s" % current.headString(),color="purple") for p in current.self_and_siblings_iter(): g.es(p.headString())

The ``p.following_siblings_iter`` iterator returns a list of all siblings that follow position ``p``::

current = c.currentPosition() g.es("following siblings of %s" % current.headString(),color="purple") for p in current.following_siblings_iter(): g.es(p.headString())
The p.subtree_iter iterator returns a list of all positions in ``p``'s subtree, excluding ``p``::

parent = p.parent() g.es("exclusive subtree of %s" % parent.headString(),color="purple") for p in parent.subtree_iter(): g.es(p.headString())

The p.self_and_subtree_iter iterator returns a list of all positions in ``p``'s subtree, including ``p``::

parent = p.parent() g.es("inclusive subtree of %s" % parent.headString(),color="purple") for p in parent.self_and_subtree_iter(): g.es(p.headString())
You can use ``c.redraw_now`` to redraw the entire screen immediately::

c.redraw_now()

However, Leo's code redraws the screen using the following pattern::

c.beginUpdate() try: << whatever >> finally: c.endUpdate()

This suppresses redraws inside <<whatever>> that would otherwise be caused by ``c.endUpdate``. ``c.endUpdate`` takes an optional argument::

c.endUpdate(flag)

redraws the screen only if flag is True. This is an important pattern. Leo uses ``c.beginUpdate`` and ``c.endUpdate`` almost everywhere to redraw the screen, so provided that << whatever >> contains no calls to ``c.redraw_now`` this pattern insures that at most one redraw occurs.
Leo dispatches commands using c.doCommand, which calls the "command1" and "command2" hook routines for the given label. c.doCommand catches all exceptions thrown by the command::

c.doCommand(c.markHeadline,label="markheadline")

You can also call command handlers directly so that hooks will not be called::

c.markHeadline()

You can invoke minibuffer commands by name. For example::

c.executeMinibufferCommand('open-outline')

c.keyHandler.funcReturn contains the value returned from the command. In many cases, as above, this value is simply 'break'.
Each commander maintains its own preferences. Your scripts can get the following ivars::

ivars = ( 'output_doc_flag', 'page_width', 'page_width', 'tab_width', 'tangle_batch_flag', 'tangle_directory', 'target_language', 'untangle_batch_flag', 'use_header_flag', )

g.es("Prefs ivars...\n",color="purple") for ivar in ivars: g.es(getattr(c,ivar))

If your script sets ``c.tab_width`` your script may call ``f.setTabWidth`` to redraw the screen::

c.tab_width = -4 # Change this and see what happens. c.frame.setTabWidth(c.tab_width)
The file ``leoFindScript.py`` contains functions for finding and changing text from within scripts. See ``leoFindScript.py`` in ``LeoPy.leo`` for full details.

The findall function returns a list of tuples ``(v,pos)`` describing matches in ``c``'s entire tree::

import leoFindScript

pattern="import leoGlobals as g" result = leoFindScript.findAll(c,pattern,bodyFlag=1)

g.es("%-3d instances of: '%s'...\n" % (len(result),pattern),color="purple")

for v,pos in result: body = v.bodyString() g.es('\n%-4d %s' % (pos,v.headString())) g.es(g.get_line_after(body,pos))

The ``reFindall`` function returns a list of tuples ``(v,mo,pos)``, where ``mo`` is a ``MatchObject``. The ``reFlags`` argument are flags to ``re.search``::

import leoFindScript

pattern="from .* import" result = leoFindScript.reFindAll(c,pattern,bodyFlag=1,reFlags=None)

g.es("%-3d instances of: '%s'...\n" % (len(result),pattern),color="purple") for v,mo,pos in result: body = v.bodyString() g.es('\n%-4d %s' % (pos,v.headString())) g.es(g.get_line_after(body,pos))
On startup, Leo looks for two arguments of the form::

--script scriptFile

If found, Leo enters batch mode. In batch mode Leo does not show any windows. Leo assumes the scriptFile contains a Python script and executes the contents of that file using Leo's ``Execute Script`` command. By default, Leo sends all output to the console window. Scripts in the scriptFile may disable or enable this output by calling ``app.log.disable`` or ``app.log.enable``

Scripts in the scriptFile may execute any of Leo's commands except the ``Edit Body`` and ``Edit Headline`` commands. Those commands require interaction with the user. For example, the following batch script reads a Leo file and prints all the headlines in that file::

path = r"c:\prog\leoCVS\leo\test\test.leo"

g.app.log.disable() # disable reading messages while opening the file flag,newFrame = g.openWithFileName(path,None) g.app.log.enable() # re-enable the log.

for p in newFrame.c.allNodes_iter(): g.es(g.toEncodedString(p.headString(),"utf-8"))
``leoGlobals.py`` contains many utility functions and constants. The following script prints all the names defined in ``leoGlobals.py``::

g.es("Names defined in leoGlobals.py",color="purple") names = g.__dict__.keys() names.sort() for name in names: g.es(name)
Most scripts will use methods of the position class to access information in an outline. The following sections summarizes the most useful methods that your scripts can use. For a complete list, see the ``leoNodes.py`` in of ``LeoPy.leo``.
Here are the most useful getters of the ``vnode`` and ``position`` classes.

Returning strings::

p.bodyString() # the body string of p. p.headString() # the headline string of p.

Returning ints::

p.childIndex() p.numberOfChildren() p.level()

Returning bools representing property bits::

p.hasChildren() p.isAncestorOf(v2) # True if v2 is a child, grandchild, etc. of p. p.isCloned() p.isDirty() p.isExpanded() p.isMarked() p.isVisible() p.isVisited()
Here are the most useful setters of the ``Commands`` and ``position`` classes. The following setters of the ``position`` class regardless of whether ``p`` is the presently selected position::

c.setBodyString(p,s) # Sets the body text of p. c.setHeadString(p,s) # Sets the headline text of p.

Moving nodes::

p.moveAfter(v2) # move p after v2 p.moveToNthChildOf(v2,n) # move p to the n'th child of v2 p.moveToRoot(oldRoot) # make p the root position. # oldRoot must be the old root position if it exists.

The "visited" bit may be used by commands or scripts for any purpose. Many commands use this bits for tree traversal, so these bits do not persist::

c.clearAllVisited() # Clears all visited bits in c's tree. p.clearVisited() p.setVisited()
The windowlist attribute of the application instance contains the list of the frames of all open windows. The commands ivar of the frame gives the commander for that frame::

windows = g.app.windowList # get the list of all open frames. g.es("windows...") for f in windows: c = f.c # c is f's commander g.es(f) g.es(f.shortFileName()) g.es(c) g.es(c.rootPosition())
Leo's source code is a collection of classes, along with utility functions in ``leoGlobals.py``. Here are the classes and objects that scripts will commonly use:

**g.app** The **application object** representing the entire Leo application. The ivars (instance variables) of ``g.app`` represent Leo's global variables.

**g.app.gui** This is a wrapper class that shields Leo's core code from gui-dependent details. As described below, scripts can invoke dialogs using g.app.gui convenience methods.

**commander** An instance of the ``Commands`` class in ``leoCommands.py``. Commanders represent commands for a *particular* window. Each open Leo window has its own commander. By convention, any variable named ``c`` is a commander.

**frame** An instance of the base ``leoFrame`` class in ``leoFrame.py``. Frames contains all the internal data needed to manage a Leo window. Given a commander ``c``, ``c.frame`` is commanders frame. Given a frame ``f``, ``f.c`` is the frame's commander.

**position** An instance of the ``position`` class in ``leoNodes.py``. A position object represents the location of a particular node *in a tree traversal*. By convention, variables named ``p``, ``p1`` or ``p2`` are positions. For any ``position`` ``p``, ``p.v`` is the vnode at that position and ``p.v.t`` is the tnode at that position. **Positions are the primary way to access data.** ``c.currentPosition`` and ``c.rootPosition`` return positions. From those starting point, it is possible to access the data in any node.

**Important**: Positions can become *invalid* when the structure of the outline changes. As discussed below, plugins and scripts that store positions for use at a later time should make sure the position p is still valid by calling c.positionExists(p)

**Important**: For compatibility with old (pre-4.2) scripts, ``c.currentVnode`` and ``c.rootVnode`` methods return *positions* not vnodes. Old scripts appear to be using vnodes; in fact they are using positions. I call such scripts **confused** scripts. Confused scripts work because the ``position`` class is designed to make them work. We'll see how this works in detail in `About copying positions`_. This section is **supremely important**.

**vnode** An instance of the ``vnode`` class in ``leoNodes.py``. vnodes represent one or more outline nodes on the screen. Normally, scripts access vnodes via the ``position`` class described below. By convention, variables named ``v``, ``v1`` or ``v2`` refer to vnodes. **Important**: scripts normally should use positions, not vnodes.

**tnode** An instance of the ``tnode`` class in ``leoNodes.py``. tnodes represent the actual data in a vnode, including headline and body text. For any vnode ``v``, ``v.t`` is v's tnode. Cloned vnodes v1 and v2 share the same tnode. That is ``v1.t == v2``. **Important**: If ``p`` is a ``position``, ``p.v.t`` is the tnode associated with that position. Many positions may share the same tnode.

**Important**: With the exception of the p.v and v.t ivars, scripts should be careful to use only the methods of the position, vnode and tnode classes rather than the internal ivars of these classes. Doing so will ensure that the script is as simple as possible and that the script will continue to work regardless of future changes to the internals of these classes.
Iterators exist only in the position class::

c.allNodes_iter # returns all positions in c's outline. p.children_iter # returns all children of p. p.parents_iter # returns all parents of p. p.self_and_parents_iter # returns p and all parents of p. p.siblings_iter # returns all siblings of p, including p. p.following_siblings_iter # returns all siblings following p. p.subtree_iter # returns all positions in p's subtree, excluding p. p.self_and_subtree_iter # returns all positions in p's subtree, including p.
@language rest

These are the sources for the html version of Leo's users guide, as well as the documentation for the rst3 plugin used to create the actual html files.

These sources contain reStructuredText_ (rST) markup that is easy to read. See http://docutils.sourceforge.net/docs/user/rst/quickstart.html for an introduction to rST.

To create the html files, choose one of the @rst nodes and run the rst3 plugin by clicking on the blue 'rst' button in the icon area.

**Important**: The following @ignore is needed so that discussions of @file, @root, etc. do not create derived files!

@ignore @tabwidth -4
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. August 28, 2005

|blank| |leo| |next|

################### Leo's Users Guide ###################

**Important**: LeoDocs.leo (included in all Leo distributions) contains the full source code for all parts of Leo's Users Guide.
`Front Matter`_

`Preface`_

`What people are saying about Leo`_

`FAQ`_

`Chapter 1: Installing Leo`_

`Chapter 2: A Tutorial Introduction to Leo`_

`Chapter 3: Using Leo's Outlines`_

`Chapter 4: Writing Programs in Leo`_

`Chapter 5: Using Leo's Commands`_

`Chapter 6: Leo and Literate Programming`_

`Chapter 7: Scripting Leo with Python`_

`Chapter 8: Customizing Leo`_

`Chapter 9: History of Leo`_

`Chapter 10: Theory of Operation`_

`Chapter 11: White Papers`_

`Chapter 12: Plugins`_

`Chapter 13: Writing Plugins`_

`Chapter 14: Using the Rst3 Plugin`_

`Chapter 15: Controlling Syntax Coloring`_

`Chapter 16: Debugging with Leo`_

`Chapter 17: Using ZODB with Leo`_

`Chapter 18: Leo and Emacs`_

`Chapter 19: Embedding Leo with the leoBridge Module`_

`Chapter 20: Unit testing with Leo`_

`Chapter 21: ILeo - the IPython bridge`_

Appendices_

Glossary_

`What's new in Leo 4.4.7 and 4.4.8`_

`What's new in Leo 4.4.6`_

`What's new in Leo 4.4.5`_

`What's new in Leo 4.4.4`_

`What's new in Leo 4.4.3`_

`What's new in Leo 4.4.2`_

`What's new in Leo 4.4.1`_

`What's new in Leo 4.4`_
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|prev| |leo| |next|

############ Front Matter ############

.. contents::

Leo_ has thousands of users_. Like me, many of them would never willingly be without Leo again. Here are Leo's essential features:

1. Leo outlines_ show you the big picture at all times, while providing unlimited space for details.

2. Leo outlines_ can organize any kind of data: computer programs, web sites, documentation, pictures, whatever.

3. Clones_ allow multiple views of the data within a *single* outline_. You don't have to choose the 'correct' view; you can see data in many ways.

4. Plugins_ allow Leo's users to add new features to Leo. Many of Leo's most successful features started life this way.

5. Leo is a superb scripting_ environment for Python. Scripts contained in a Leo outline_ have easy access to all the outline's data. It is natural to organize Leo outlines to make life easier for scripts.

6. Leo is `Open Software`_, written in 100% pure Python_. Leo runs wherever Python does.

Leo has a strong and active community of users on `SourceForge`_. Working with this community has been a constant source of joy and inspiration. Suggestions and plugins from users continue to drive Leo in excellent new directions. Who knows what the next plugin will bring? -- Edward K. Ream, September, 2005
Leo owes much of its visual design to ``MORE``, possibly the most elegant computer program ever written. Leo's clone nodes are inspired by ``MORE``.

The following people have made generous donations to the Leo project: Robert Low, Nic Cave-Lynch.

The following people reported bugs, answered questions, and made suggestions for improving Leo: Alex Abacus, Shakeeb Alireze, Steve Allen, Bruce Arnold, Chris Barker, Dennis Benzinger, David Boddie, Jason Breti, Eric Brown, Terry Brown, Darius Clarke, Martin Clifford, Jason Cunliffe, Josef Dalcolmo, Gil Dev, Bill Drissel, Wenshan Du, Allen Edwards, Chris Elliot, Dethe Elza, Mark Engleberg, Roger Erens, Stephen Ferg, Tom Fetherston, Tomaz Ficko, Niklas Frykholm, Fred Gansevles, Jonathan M. Gilligan, Zak Greant, Thomas Guettler, Romain Guy, Dave Hein, Tiago Castro Henriques, Gary Herron, Steve Holden, Klass Holwerda, Matthias Huening, Robert Hustead, John Jacob, Paul Jaros, Christopher P. Jobling, Eric S. Johansson, Garold Johnson, James Kerwin, Nicola Larosa, David LeBlanc, Chris Liechti, Steve Litt, Martin v. Loewis, Robert Low, Fredrik Lundh, Michael Manti, Alex Martelli, Marcus A. Martin, Gidion May, David McNab, Frank Merenda, Martin Montcrieffe, Will Munslow, Chad Netzer, Derick van Niekerk, Jeff Nowland, Naud Olivier, Joe Orr, Marc-Antoine Parent, Paul Paterson, Sean Shaleh Perry, Tim Peters, David Priest, Gary Poster, Scott Powell, Bruce Rafnel, Walter H. Rauser, Olivier Ravard, David Speed Ream, Rich Ries, Aharon Robbins, Guido van Rossum, David Rowe, Davide Salomoni, Steven Schaefer,Johannes Schöön, Wolfram Schwenzer, Casey Wong Kam Shun, Gil Shwartz, Jim Sizelove, Paul Snively, Jurjen Stellingwerff, Phil Straus, David Szent-Györgyi, Kent Tenney, Jeffrey Thompson, Gabriel Valiente, Jim Vickroy, Tony Vignaux, Tom van Vleck, Kevin Walzer, Ying-Chao Wang, Cliff Wells, Dan Wharton, John Wiegley, Wim Wijnders, Dan Winkler, Vadim Zeitlin.

The following have contributed plugins to Leo:

Rodrigo Benenson, Pierre Bidon, Felix Breuer, Terry Brown, Mike Crowe, Josef Dalcolmo, Michael Dawson, e, Roger Erens, Andrea Galimberti, Engelbert Gruber, Timo Honkasalo, Jaakko Kourula, Maxim Krikun, Zhang Le, LeoUser, Frédéric Momméja, Bernhard Mulder, Mark Ng, Alexis Gendron Paquette, Paul Paterson, Dan Rahmel, Davide Salomoni, Ed Taekema, Kent Tenney, Brian Theado, Ville M. Vainio, Steve Zatz.
All parts of Leo are distributed under the following copyright. This is intended to be the same as the Python license, namely that Leo is absolutely free, even for commercial use, including resale. There is no GNU-like "copyleft" restriction. This license is compatible with the GPL.

Copyright 1997-2006 by Edward K. Ream. All Rights Reserved. Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appears in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the names of Edward K. Ream or Leo may not be used in advertising or publicity pertaining to distribution of the software without specific, prior written permission from Edward K. Ream.
**EDWARD K. REAM (REAM) SPECIFICALLY DISCLAIMS ALL WARRANTIES, EXPRESSED OR IMPLIED, WITH RESPECT TO THIS COMPUTER SOFTWARE, INCLUDING BUT NOT LIMITED TO IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL REAM BE LIABLE FOR ANY LOSS OF PROFIT OR ANY COMMERCIAL DAMAGE, INCLUDING BUT NOT LIMITED TO SPECIAL, INCIDENTAL, CONSEQUENTIAL OR OTHER DAMAGES.**
The following deserve special mention: David Brock wrote TSyntaxMemo. The late Bob Fitzwater kept me focused on design. Donald Knuth invented literate programming and the CWEB language. Jonathan M. Gilligan showed how to put the Leo icon in Leo's windows. Joe Orr created XSLT stylesheets for Leo; see http://www.jserv.com/jk_orr/xml/leo.htm. Joe Orr also created an outstanding set of tutorials for Leo; see http://www.evisa.com/e/sb.htm. LeoUser (B.H.) contributed numerous plugins and was the inspiration for Leo's minibuffer. LeoUser also wrote jyLeo: Leo for Jython. Bernhard Mulder proposed a new way of untangling derived files. John K. Ousterhout created tcl/Tk. Neal Norwitz wrote PyChecker. Marc-Antoine Parent urged me to use XML for Leo's file format and helped improve it. Paul Paterson suggested the plugin architecture, suggested an approach to spell checking and has contributed many excellent plugins. François Pinard wrote pymacs. Norman Ramsey created noweb and gave permission to quote from the noweb web documentation. Rich Ries has contributed a huge number of suggestions. Steven P. Schaefer pointed out major security problems lurking in hooks. Gil Shwartz helped with unicode support. Phil Straus has been a great friend and constant support. Guido van Rossum created Python, Tkinter and the Python License. Dave Winer created ``MORE``. Ville M. Vainio created ILeo. Dan Winkler helped support Leo on the Mac.

Special thanks to my family. My brother, David Speed Ream, tested Leo and made many useful suggestions. Rebecca, James and Linda make it all worthwhile. It was during a conversation with Rebecca that I realized that ``MORE`` could be used as a prototype for Leo. That was a crucial first step.
Leo will write only t.unknownAttributes to the .leo file when writing the <v> element corresponding to the root of an @thin tree. Leo will do this by writing a new xml attribute, say descendentTnodeUnknownAttributes, in <v> element.

The reason that Leo will only write t.unknownAttributes and not v.unknownAttributes is that only tnodes have gnx's in thin derived files. In effect, vnodes are anonymous. We could attempt to get around this by identifying vnodes by their corresponding tnodes, but that's not a general solution and it is, in effect, equivalent to writing only t.unknownAttributes. This being so, it seems pointless to "pretend" to be writing v.unknownAttributes.

The effect of this is to make all vnodes identical, as far as using unknownAttributes is concerned. As I've stated in the past, this won't do if, for example, a plugin is trying create an arbitrary directed graph between vnodes. In that case, the plugin should confine itself to @file trees, or just vnodes in .leo files, for that matter.

7/1/04:

- Leo now writes "marks" and "expanded" attributes in the root <v> element for @thin trees.

- VERY IMPORTANT. Leo now writes entire tree of @ignored @thin nodes. This fixes a major bug.
Leo marks as dirty all @file nodes when they become "newly unignored".
Leo now generates no warnings with all significant tests enabled. Some tests have been disabled in bases classes, and in a few cases pychecker gives erroneous warnings that have been suppressed directly in the source code using the __pychecker__ = arg syntax.
Leo 4.2 beta 3 August 10, 2004

This version of Leo is feature complete. Leo's core code has been stable for several months.

To do: most plugins work with the new code base, but other plugins need some more work.

The highlights of Leo 4.2:

- @thin trees make Leo much more friendly to cvs. Files derived from @thin can be committed to cvs and updated from cvs without having to commit or update the corresponding .leo file. There is no longer any need to keep .leo files and derived files in synch.

- Leo's data structures have been reorganized. As a result, all outline operations are much faster. To support this organization, scripts that traverse Leo's data structures must now use a positions rather than vnodes. Old scripts that appear to use vnodes will still work because methods like c.currentVnode that appear to return vnodes actually return positions.

- A new mod_scripting plugin is a big advance in scripting and testing. test.leo now uses @test and @script nodes to define unit tests without explicitly creating subclasses of unittest.TestCase. Converting scripts to unit tests now takes a few seconds!

- A much faster and more robust spell checker plugin. (requires Python 2.3)

- Leo is now much more friendly to using spaces instead of tabs.

- The Execute Script command reports erroneous lines more clearly.

- The Perfect Import feature guarantee that Leo imports file exactly.
Leo now vetoes the shutdown logic if saving a dirty file fails.

Leo prints in red the warning about not being able save the read-only file. The user can use the Save To command to save the file. The Save To command does not clear the file's dirty bit, so Leo will prompt again to save the file. The user will have to ignore this prompt in order to exit. This is correct: the _original_ file has not been saved.
- g.getScript implicitly assumed that p == c.currentPosition. I removed that assumption.

- The scriptButton callback in the scripting.py plugin no longer calls c.executeScript. It's simpler and easier to call exec directly.

- Improved c.checkOutline: - Added full keyword arg. - Print more if verbose is on.
Spurious entries in a tnodeList for @thin trees wiped out all the headlines in the @thin tree.
# The new code only writes tnodes for the current tree when pasting to the clipboard.
There was a big performance bug in the nodenavigator plugin.
@nocolor

As a result, the minimal .leo file is:

@color @language html

<?xml version="1.0" encoding="UTF-8"?> <leo_file> <leo_header/> <globals/> <preferences/> <find_panel_settings/> <vnodes/> <tnodes/> </leo_file>

@nocolor

The empty_leo_file plugin now uses this code. The minimal .leo file that Leo might actually write is more like this:

@color

<?xml version="1.0" encoding="UTF-8"?> <leo_file> <leo_header/> <globals/> <preferences/> <find_panel_settings> <find_string/> <change_string/> </find_panel_settings> <vnodes/> <tnodes/> </leo_file>
This is required to make @thin work properly.
This makes the command more useful.
A major change: putVnode doesn't put tnodeLists for @thin nodes.

Instead it issues an informational message and deletes the tnodeList.
Leo used to allocate more positions than necessary. This unnecessarily stressed the garbage collector.
Leo now allows you to select multiple files in the dialogs for all Import commands. This fixes a major annoyance. However, you must be running Python 2.3 or above to get this feature.
Added the Check submenu of the Outline menu. This contains the Check Outline and Dump Outline commands, as well as four new commands:

The Check All Python Code and Check Python Code commands report any syntax errors or tabnanny errors. These commands mark erroneous nodes. These commands work on the selected Node and its descendants. These commands ignore any nodes for which a) @ignore is in effect or b) @language python is in not effect.

The Check Python Code and Pretty Print Python Code commands replace nodes with their pretty-printed alternative. No doubt everyone will have their own favorite style. You could implement alternate pretty printers in a plugin merely by overriding the following methods of class prettyPrinter in leoCommands.py:

---- putOperator: puts whitespace around operators. ---- putNormalToken: puts whitespace around everything else.
Leo now reuses all widgets used to draw the outline pane. This improves performance and ends leaks of bindings and widgets.
@thin bad-directory caused excessive and confusing tracebacks.
The tests::

if p: # Right if not p: # Right

are the **only** correct ways to test whether a position ``p`` is valid. In particular, the following **will not work**::

if p is None: # Wrong if p is not None: # Wrong
Leo 4.2 release candidate 1 September 14, 2004

This version fixes a number of minor bugs reported since the last release. See the children of this node for details.

The highlights of Leo 4.2:

- @thin trees make Leo much more friendly to cvs. Files derived from @thin can be committed to cvs and updated from cvs without having to commit or update the corresponding .leo file. There is no longer any need to keep .leo files and derived files in synch.

- Leo's data structures have been reorganized. As a result, all outline operations are much faster. To support this organization, scripts that traverse Leo's data structures must now use a positions rather than vnodes. Old scripts that appear to use vnodes will still work because methods like c.currentVnode that appear to return vnodes actually return positions.

- A new mod_scripting plugin is a big advance in scripting and testing. test.leo now uses @test and @script nodes to define unit tests without explicitly creating subclasses of unittest.TestCase. Converting scripts to unit tests now takes a few seconds!

- A much faster and more robust spell checker plugin. (requires Python 2.3)

- Leo is now much more friendly to using spaces instead of tabs.

- The Execute Script command reports erroneous lines more clearly.

- The Perfect Import feature guarantee that Leo imports file exactly.
With TclTkAqua on the Mac (but *not* with tcltk installed via Fink), the tab problem doesn't exist there), the tab, return, and backspace keys did not generate ASCII codes, i.e. event.char is an empty string. So when I press the tab key, Tk inserts a tab character and Leo isn't even aware of it.
If only one file was specified Leo gave an error for every character of the file name!
@killcolor

From Dan Winkler:

On a couple of occasions, I tried to paste in a long @url node and got this message:

Truncating headline to 250 characters

I wonder if the 250 character limit on headline length should be rethought in light of the @url directive and long web addresses.
There were too many problems with this feature. In the future Leo will have a Check Import command.
Leo wasn't always traversing the outline correctly when looking for @root nodes.
http://sourceforge.net/forum/message.php?msg_id=2742238 By: hinsen

The shortcut definitions in Leo are quite inconvenient on the Mac, as those using the Alt key don't work. Alt is used for entry of additional characters. On the other hand, ctrl is available for shortcuts but not used in Leo, since the ctrl-based shortcuts are shifted to the command key (following standard Mac practice).

The patch at the end of this message simply shifts all Alt-shortcuts to Ctrl on the Mac.

That leaves one minor clash: Command-` is used for CloneNode in Leo, although it canonical MacOS function (switching between the windows of an application) would be very useful in Leo as well. Removing the CloneNode binding is easy enough, but it seems that I must implement a window switching function myself. Not today :-)

Konrad.
Leo 4.2 Final September 20, 2004

The highlights of Leo 4.2:

- @thin trees make Leo much more friendly to cvs. Files derived from @thin can be committed to cvs and updated from cvs without having to commit or update the corresponding .leo file. There is no longer any need to keep .leo files and derived files in synch.

- Leo's data structures have been reorganized. As a result, all outline operations are much faster. To support this organization, scripts that traverse Leo's data structures must now use a positions rather than vnodes. Old scripts that appear to use vnodes will still work because methods like c.currentVnode that appear to return vnodes actually return positions.

- A new mod_scripting plugin is a big advance in scripting and testing. test.leo now uses @test and @script nodes to define unit tests without explicitly creating subclasses of unittest.TestCase. Converting scripts to unit tests now takes a few seconds!

- A much faster and more robust spell checker plugin. (requires Python 2.3)

- Leo is now much more friendly to using spaces instead of tabs.

- The Execute Script command reports erroneous lines more clearly.
c.spellCommands.openSpellTab()
Leo stores options in @settings trees, that is, parts of Leo outlines whose root node has the headline @settings. When opening a .leo file, Leo looks for @settings trees in the following places:

- The file called leoSettings.leo in the leo/config directory. - The file called leoSettings.leo in the users home directory. - The file being loaded.

Settings that later in the above list override settings found earlier. For example, any setting specified in an @settings tree in the file being loaded overrides any setting seen in any leoSettings.leo file.

The Settings command temporarily replaces the outline pane with an outline showing all the @settings trees in effect. The Settings command also replaces the body pane with a "settings dialog" pane. This settings dialog pane allows you to change the settings selected in the outline pane using standard gui widgets.

The format of nodes in @settings trees are as follows:

1. "Simple settings nodes" have headlines of the form:

@<type> name = val

set the value of name to val, with the indicated type.

<type> may be one of the following, with valid values shown:

<type> Valid values ----- ------------ \@bool True, False, 0, 1 \@color A Tk color name or value, such as 'red' or 'xf2fddff' (without the quotes)

For a list of Tk color specifiers see:

- http://www.tcl.tk/man/tcl8.4/TkCmd/colors.htm - http://www.tcl.tk/man/tcl8.4/TkLib/GetColor.htm

\@directory A path to a directory \@float A floating point number of the form nn.ff. \@int An integer \@ints[list] An integer (must be one of the ints in the list). Example: @ints meaningOfLife[0,42,666]=42 \@path A path to a directory or file \@ratio A floating point number between 0.0 and 1.0, inclusive. \@string A string \@strings[list] A string (must be one of the strings in the list). Example: @strings tk_relief['flat','groove','raised']='groove'

2. "Complex settings nodes" have headlines of the form:

\@<type> description

The actual settings are specified in the body text. At present, there are two such kinds of complex settings nodes:

- @font

The body text contains a list of settings for a font. For example:

body_text_font_family = Courier New body_text_font_size = None body_text_font_slant = None body_text_font_weight = None

- @recentFiles

The body text contains a list of paths of recently opened files, one path per line.

Warning: The following features of @recentfiles nodes are confusing and probably will be changed:

- Leo does not save recent file information unless the open .leo file has an @settings tree and an @recentfiles node within the @settings tree. That is, Leo does not save recent files information in leoSettings.leo files.

- Changing the @rencentfiles node doesn't mark the Leo file as dirty, so if you don't save the .leo file the recent files information will not be updated.

3. All other nodes are "Organizer" nodes. Such nodes have no effect on the settings shown in the dialog. You may use them as you please to organize settings.

Notes:

A. At present, you can not change @settings trees while executing the Settings command. You can, however, change any @settings tree normally when not executing the Settings command.

B. Other kinds of settings nodes are planned for future releases.
Leo 4.3 alpha 1 January 24, 2005

Leo 4.3 is the culmination of more than four months of work.

The defining features of Leo 4.3:

1. Leo now stores options in @settings trees, that is, outlines whose headline is '@settings'. When opening a .leo file, Leo looks for @settings trees not only in the outline being opened but also in various leoSettings.leo files.

The key design goal of @settings trees was that Leo's user options must be infinitely flexible. That goal has been accomplished. Indeed, users can create arbitrarily complex user options with @settings trees. Leo settings outlines are, in fact, infinitely more flexible and powerful than any scheme based on flat text. Readers of Python's configParser shootout take note!

2. The Settings command temporarily replaces the outline pane with an outline showing all the @settings trees in effect. The Settings command also replaces the body pane with a "settings pane". This settings pane allows you to change the settings selected in the outline pane using standard gui widgets. The settings pane is dynamically created from nodes in the settings tree; it is as extensible as the @settings tree itself.

3. Leo's read/write code in leoAtFile.py has been rewritten to support user- defined tangling and untangling. This is a major cleanup of Leo's core.

4. Leo now boasts a wonderful new Plugins Manager plugin. This plugin enables and disables plugins automatically. You never have to mess with pluginsManager.txt again! This plugin also tells you everything you need to know about each plugin. Finally, this plugin also lets you download plugins from Leo's cvs site! Many thanks to Paul Patterson for this excellent work.

5. You can install third-party extensions in Leo's extensions directory. Leo will attempt to import such extensions from the extensions directory if normal imports fail.
The essential features of @settings trees and the settings dialog appear to be stable. However, many improvements can be imagined, including the following:

- Allow searching for nodes while in the settings dialog.

- Allow adding, deleting, rearranging nodes while in the settings dialog.

- Allow adding, deleting, rearranging recent files while in the settings dialog.

These will be added as time permits and people request.
The Open With logic in createOpenWithMenuFromTable for the 'spawnv' case now actually calls os.spawnv (rather than spawnl) and it allows a variable length list of parameters.
The old code wasn't handling single file selections properly. The new code works around an apparent bug in Tk.askopenfilename.
The new code forbids Paste Node As Clone if the paste would result in a node being a clone of itself.
The '@' sign is an operator in Python 2.4, not an error token.
What I did:

- Created a new top-level method: scanHeaderForThin.

This sets self.encoding temporarily. The actual value of self.encoding does not really matter: no errors will be given by readLine and its helpers even if there are unicode encoding errors.

- We must _not_ set self.encoding in scanHeader: that would interfere with normal initialization.
- Restored non Pmw code in resizePanesToRatio. This code got deleted by mistake. The Equal Sized Panes works again.

- Added many do-nothing methods to nullMenu class.

This should prevent the startup logic from messing with shortcuts in any way. It's also the right thing to do.

- Added an entry for EqualSizedPanes to leoSettings.leo. This overrides the default (Ctrl-E) and thereby prevents the default from overriding the entry for ExecuteScript!

- Re-enabled code in createMenuEntries that warns when shortcuts have been redefined. Not sure if this is a wise idea, or indeed if it actually does anything :-)

I am tempted to remove all the default entries entirely. This would simplify error reporting, but then Leo would hardly work at all if leoSettings.leo were not present.
p.moveToParent now just returns if p is a null position.
# Leo looped after this assert failed.
he readDirective method was changing the comment delimiters as the result of seeing the sentinels corresponding to @language or @comment directives. But in general this makes no sense! Comment delimiters should be set once and for all in the @+leo sentinel: there is no compiler in the world that tolerates mixed comment delimiters.

BTW, the way to set javascript "inner" comments is to use @delims, not @comment. N.B. The @language and @comment delimiters _will_ have an effect, and that effect is in the _write_ logic, not the read logic. The effect is to set the comment delims in the @+leo sentinel.

The quick fix is to comment out code in readDirective.
The old code did not honor the @lineending directive if the two files would otherwise be identical.

What I did:

- Added self.explicitLineEnding to remember whether an explicit @lineending directive is in effect.

- Make sure the user knows why an otherwise identical file was written.

- Changed name of compareFilesIgnoringNewlines to compareFiles.

- Added ignoreLineEndings arg to compareFiles.
The fix was to add nosentinels=nosentinels in the call to initWriteIvars in atFile.write.
This method now does nothing if at.toString is True.
Leo did not correctly write adjacent @doc parts in @file trees. Leo could not read the resulting derived files!

The bug happened if any node in an @file tree contains adjacent @doc parts, like this:

@ first doc part ... @ second doc part ...

Leo failed to write the closing #@-at sentinel that would finish the first @doc part.
The new code uses protocol=1 instead of the deprecated bin argument to Pickler.
The problem was that nullLog.write calls print, and if print is redirected the code ends up calling nullLog.write again.

What I did:

- g.redirectClass.redirect does nothing if g.app.batchMode is True. - added g.rawPrint. - Changed self.old.write(s) to self.old.write(s+'\n') throughout.
It makes no sense to use only the selected text.
The old code assumed that the error is always in the script itself. Not true! The error could happen in methods called by the script.

This code works with Python 2.3.4 and Python 2.4. It may be version dependent.
Leo now sets the name of the frame to the requested file name on the command line even if the file name does not exist.
The code now clears previous shortcut, and tells what the previous entry was.
Changed the open command associated with .leo files on Windows from:

pythonw.exe "<leodir>\src\leo.py" %1

to:

"pythonw.exe" "<leodir>\src\leo.py" "%1"

The difference is in quotes. Especially quotes around "%1" seem to matter.
This is an important difference. imp.load_module is equivalent to a reload, so we must not call this if the module already exists!
Leo did not properly write derived files that contained section references to grand-children.

For example:

<< current level>> reference to << 3. level>> << 1.level>> << 2.level >> << 3.level>>

The fix was simply to reverse the order in which putRefAt puts +middle and -middle sentinels.
In some cases g.app.config.output_newline was None. The new code sets the default to '', and then assigns a valid default to ''.
This binds scroll-wheel events to Button-4 and Button-5
chapters.py requires that the canvas have a name ivar.

Added treeCanvas.name = '1' in:

<< replace tree pane with settings tree >>
Leo can still read such files, but old-style file formats are now deprecated
The new code greatly simplifies the class structure. The intention is to allow plugins to override methods of this file more easily.

The highlights:

- Plugins may now override methods in this file much more easily. - All code is now in a single class. - Resolved the few name conflicts by renaming x to x3 or x4. - The new code generally uses methods instead of sections. - Initialization is now simple and sane, and is done in dedicated methods. - All constants are class constants: no more module-level constants.

- All top-level methods support toString or fromString arguments.
Fixed shadow warnings. The following are all Python global functions:

cmp -> compare dict -> theDict dir -> theDir file -> theFile id -> theId type -> theType input (suppressed the warning) iter -> theIter
Apparently distutils.file_util is not present in all Python distributions!

New approaches: - Fall back on code in distutils.file_util if import fails. - Make sure the src and dst volumes are the same (so Linux os.rename will always work) - Simplify replaceTargetFileIfDifferent by creating new routines.

What I did: - Rewrote replaceTargetFileIfDifferent in terms of atFile.rename, atFile.remove, etc. - Rewrote update_file_if_changed in terms of g.utils_rename, g.utils_remove, etc.
Leo's code now contains an important simplification to Leo's gui code. This arose because of a problem in the UNL plugin. The window that opened when double clicking an @url UNL node wasn't staying on top.

It turns out that this was essentially impossible to fix with the old code. The proximate cause of the original problem button-1 was bound to OnActivateTree, which called g.app.gui.set_focus after the new window was visible, thereby bringing the old tree to the front.

Further investigation revealed other problems. For example, the idle-time code in the status line logic was also messing with the focus. It turns out that repeatedly calling g.app.gui.set_focus is a very bad idea, for lots of reasons which I won't go into in detail here.

The old code called g.app.gui.set_focus explicitly whenever it wanted focus to change. But there is a much better way, namely to have routines that _indicate_ where they want the focus to be "after the dust settles", that is, when all gui calls have been completed. I call this a "delayed focus" scheme.

So I rewrote all the code that sets the focus. The new code replaces direct calls to g.app.gui.set_focus with calls to the following methods in leoTkinterFrame class: bodyWantsFocus, statusLineWantsFocus, treeWantsFocus and logWantsFocus. Actually, these xWantsFocus methods all do the same thing, but using different methods improves traces.

This is an excellent pattern. Again, rather than setting the focus directly, these xWantsFocus methods merely signal their intension to set the focus. This allows very complex logic to be hidden in leoTkinterFrame.set_focus.

leoTkinterFrame.set_focus is indeed complex. It took me several hours this morning to get it just right. It queues up a 'one-shot' callback. That is, at most one copy of the callback is ever waiting to be executed. Furthermore, the callback is only queued for execution at the result of a call to xWantsFocus; it is never run automatically at idle time. Finally, even when executed, the callback does nothing if the last requested commander (in the new ivar, g.app.wantedFocus) does not match the commander to which the callback was bound.

These checks allow the UNL plugin to open a window properly and keep it topmost.

This is a big step forward for Leo, for the following reasons:

- Delayed focus ensures that the body pane always has focus unless the code has a specific, positive reason for the focus to be elsewhere. This was difficult (or rather impossible) to do with the old code: there are _many_ Tk calls that can affect the focus.

- Delayed focus minimizes calls to g.app.gui.set_focus. Unlike the old code, many seconds may elapse between calls. The stress on Tk is much less, and I believe this may cure some flakiness in how focus changes, especially in headlines.

- There are some cases where focus must change immediately. The xWantsFocus methods all support a 'later' keyword argument. By default it is True, but when it is False leoTkinterFrame.set_focus calls g.app.gui.set_focus immediately.

- The xWantsFocus methods all support a 'tag' keyword argument that tells what routine the method is called from. It is a big help in making sense of traces. BTW, extensive traces are the _only_ possible way of tracking down focus/selection problems.
These commands work as do the similar commands in Windows Explorer. How did we ever live without them?
This supports the fromString option in read commands.
Thanks to Bernhard Mulder for the new code.
- Tab toggles between the Search to the Replace areas.

- Control-Tab inserts a tab.

- Added hot keys for all settings. Use Alt-x to activate hot key x. The Enter key activates the Find button.

- As usual, Alt-F4 dismisses the Find panel.
It's not clear that this support is so useful for debugging scripts.

If g.app.debugSwitch is True es_exception gives a full traceback.
Thanks to David McNab <david@freenet.org.nz> for this work.
- Go To Line Number command now assumes the presently selected node is a script if there is no ancestor @file node.

- Execute Script command uses this new logic to select the proper node and line in a script if there is an error.

How did we ever live without these features?
Restored the following hooks:

"boxclick1" before click in +- box c,p,v,event "boxclick2" after click in +- box c,p,v,event "drag1" before start of drag c,p,v,event "drag2" after start of drag c,p,v,event "dragging1" before continuing to drag c,p,v,event "dragging2" after continuing to drag c,p,v,event "enddrag1" before end of drag c,p,v,event "enddrag2" after end of drag c,p,v,event

The following already existed. I added v=p keyword params:

"iconclick1" before single click in icon box c,p,v,event "iconclick2" after single click in icon box c,p,v,event "iconrclick1" before right click in icon box c,p,v,event "iconrclick2" after right click in icon box c,p,v,event "icondclick1" before double click in icon box c,p,v,event "icondclick2" after double click in icon box c,p,v,event
Changed these hooks:

"bodyclick1", "bodyclick2", "bodydclick1", "bodydclick2", "bodyrclick1", "bodyrclick2", "bodykey1", "bodykey2", "command1", "command2", "headclick1", "headclick2", "headrclick1", "headrclick2", "headkey1", "headkey2", "hyperclick1", "hyperclick2", "hyperenter1", "hyperenter2", "hyperleave1", "hyperleave2", "openwith1", "openwith2", "menu1", "menu2", "recentfiles1", "recentfiles2", "save1", "save2", "select1", "select2", "select3", "start2", "unselect1", "unselect2", "url1", "url2",

"clear-mark", "set-mark", "color-optional-markup", "create-popup-menu", "draw-outline-icon", "draw-outline-node", "draw-outline-text-box", "draw-sub-outline", "init-color-markup", "scan-directives", "draw-outline-box", "enable-popup-menu-items", "show-popup-menu",
Leo no loner has any global windows!

- Each commander has its own find window. - It's title tells to what commander it applies.
computeHomeDir() now test the first retrieval of the %HOME% var and grab it's results if it is in fact another environment variable.
Actually, support already existed for them in getBaseDirectly!

What I did.

- Added a c keyword to getBaseDirectory. - Added similar logic to os_path_join.

- Changed some stupid code in g.openWithFileName (called by @url logic): changed: fileName = g.os_path_join(os.getcwd(),fileName) to: fileName = g.os_path_abspath(fileName)

MAYBE g.os_path_abspath should force '.' to mean c.openDir, but I kinda doubt it. This could be asking for trouble.

OTOH, the various flavors of scanAllDirectives already do this. Hmmmmmm.
- This plugin now handles both kinds of triple-quotes correctly so that both kinds of docstrings are recognized.

- This plugin now is controlled by the first reference to a plugin in pluginsManager.txt. All other references are ignored.
Created callTagHandler. This checks 'idle' hooks to make sure that any commander referenced by the 'c','new_c' or 'old_c' keywords still exists.
leoPlugins.registerOneHandler wasn't working properly at all. In effect, only the last registered hook was ever being remembered!
tnodes_iter and unique_tnodes_iter were returning vnodes, not tnodes!
- Leo now ignores all find settings in .leo files. Instead, Leo inits find settings from @settings entries.

- Removed all c ivars corresponding to leoFind ivars. - This eliminates the ugliest code in Leo. - Inits all leoFind ivars from @settings in init, a helper of the ctor. - Updates all the leoFind ivars in update_ivars, called just before doing any find.

- Removed the _flag suffix from leoFind ivars. - Another major mess cleaned up.

- Renamed find/change_text to find/change_ctrl to avoid name conflict.
Leo now stores options in @settings trees, that is, outlines whose headline is '@settings'. When opening a .leo file, Leo looks for @settings trees not only in the outline being opened but also in various leoSettings.leo files.

The key design goal of @settings trees was that Leo's user options must be infinitely flexible. That goal has been accomplished. Indeed, users can create arbitrarily complex user options with @settings trees. Leo settings outlines are, in fact, infinitely more flexible and powerful than any scheme based on flat text.

The Settings command temporarily replaces the outline pane with an outline showing all the @settings trees in effect. The Settings command also replaces the body pane with a "settings pane". This settings pane allows you to change the settings selected in the outline pane using standard gui widgets. The settings pane is dynamically created from nodes in the settings tree; it is as extensible as the @settings tree itself.

For full details, see the children of this node.
- leoPlugins.doHandlersForTag now executes the list of hook handlers for a particular tag (hook name) until one of the handlers returns a non-None result. doHandersForTag no longer tries to "sort" handlers, so the order that the handlers are executed is the order in which they were registered.

I finally understand the concerns people have raised several times about hooks interfering with each other. If two handlers try to return a non-None result only one of them will ever execute. doHandlersForTag can't do much about this: a better solution would require more conceptual framework. Not now...
Leo now boasts a wonderful new Plugins Manager plugin. This plugin enables and disables plugins automatically. You never have to mess with pluginsManager.txt again! This plugin also tells you everything you need to know about each plugin. Finally, this plugin also lets you download plugins from Leo's cvs site! Many thanks to Paul Patterson for this excellent work.

Note. The Plugins Manager plugin requires Pmw. You can install Pmw in Leo's extensions directory if you like.
You can can import any extension to Leo by putting the extension in the 'extensions' directory and using g.importExtension to import it.

- created the 'extensions' directory and g.app.extensionsDir

- created g.importModule and g.importExtension
Changed scanDirectives and atFile.scanDirectives so they work like tangle.scanAllDirectives. Also added a few clarifying words in LeoDocs.leo.

This should have worked, but didn't:

+ Code @language python + @file sql_create.sql @comment --

So I rearranged the outline (probably more logical anyway) to +Code + Python ... + SQL ...
Leo 4.3 alpha 2 February 14, 2005

Leo 4.3 is the culmination of more than four months of work. This alpha 2 release corrects various bugs and distribution problems.

a2 also adds several new features:

- Adds 'word', 'line' and 'node' undo granularities. - Predefines 'c','g', and 'p' in scripts and unit tests. - Added support for top-level init functions in plugins. - Buttons can remove themselves when their scripts fail.

The defining features of Leo 4.3:

1. Leo now stores options in @settings trees, that is, outlines whose headline is '@settings'. When opening a .leo file, Leo looks for @settings trees not only in the outline being opened but also in various leoSettings.leo files.

The key design goal of @settings trees was that Leo's user options must be infinitely flexible. That goal has been accomplished. Indeed, users can create arbitrarily complex user options with @settings trees. Leo settings outlines are, in fact, infinitely more flexible and powerful than any scheme based on flat text. Readers of Python's configParser shootout take note!

2. The Settings command temporarily replaces the outline pane with an outline showing all the @settings trees in effect. The Settings command also replaces the body pane with a "settings pane". This settings pane allows you to change the settings selected in the outline pane using standard gui widgets. The settings pane is dynamically created from nodes in the settings tree; it is as extensible as the @settings tree itself.

3. Leo's read/write code in leoAtFile.py has been rewritten to support user- defined tangling and untangling. This is a major cleanup of Leo's core.

4. Leo now boasts a wonderful new Plugins Manager plugin. This plugin enables and disables plugins automatically. You never have to mess with pluginsManager.txt again! This plugin also tells you everything you need to know about each plugin. Finally, this plugin also lets you download plugins from Leo's cvs site! Many thanks to Paul Patterson for this excellent work.

5. You can install third-party extensions in Leo's extensions directory. Leo will attempt to import such extensions from the extensions directory if normal imports fail. Leo is distributed with Pmw (Python Mega Widgets) in this directory.
Warning: The following features of @recentfiles nodes are confusing and probably will be changed:

- Leo does not save recent file information unless the open .leo file has an @settings tree and an @recentfiles node within the @settings tree. That is, Leo does not save recent files information in leoSettings.leo files.

- Changing the @rencentfiles node doesn't mark the Leo file as dirty, so if you don't save the .leo file the recent files information will not be updated.
http://sourceforge.net/forum/message.php?msg_id=2795653

1. Select a node in the tree 2. Hit CTRL-I to insert a node 3. Hit CTRL-Z to undo the insert 4. There is no longer a node selected in the tree so keyboard tree navigation etc commands don't work until you click on something with the mouse

-----

http://sourceforge.net/forum/message.php?msg_id=2795656

1. Select a node in the tree 2. Hit CTRL-I to insert a node 3. Hit CTRL-Z to undo the insert 4. Hit Hoist before clicking on anything

Now you are hoisted on the recently removed node! The node is dead but his memory lives on ...
http://sourceforge.net/forum/message.php?msg_id=2966541

---- Report:

"Recent Files" is not remembering files after one closes all open leo sessions.

But it does update the "Recent Files" list while leo is open in the same session. If one opens more files it adds them to the list. But close all files and Leo forgets them all.

---- Added to @recentfile documentation:

Warning: The following features of @recentfiles nodes are confusing and probably will be changed:

- Leo does not save recent file information unless the open .leo file has an @settings tree and an @recentfiles node within the @settings tree. That is, Leo does not save recent files information in leoSettings.leo files.

- Changing the @rencentfiles node doesn't mark the Leo file as dirty, so if you don't save the .leo file the recent files information will not be updated.
http://sourceforge.net/forum/message.php?msg_id=2960328

Symptom

Can not import messages were not being sent to the console, even though there is a call to es in g.cantImport.

What I did

- The code in g.es now checks for nullLog as well as log == None when deciding when to queue messages.

- g.openWithFileName now calls g.app.writeWaitingLog immediately after enabling the new log.

This writes the queued log messages in the proper order: a major advance in clarity.

- Added silent param to two methods.

This allows the 'reading settings from' message to be sent to the log instead of the default 'reading' message.
The new code no longer requires that the present node have a tnodeList.

File "/Users/edream/leoCVS/leo/src/leoAtFile.py", line 3830, in putOpenNodeSentinel at.root.v.t.tnodeList.append(p.v.t)

AttributeError: 'tnode' object has no attribute 'tnodeList'
The message 'command for widget 5' was a message from Tk saying in effect that no command was bound to the button.

Indeed, this was so: a recent botch in a change in mod_scripting.py prevented the binding.

Moreover, there were some extra print statements in the g.es logic for the Mac.
This makes the test more robust in case of failure.
Changed the setup code for the import/export test cases so that it uses os.path.sep when it sees \\ in the test nodes.

With this change all unit tests pass on the Mac as well as on XP.
*None* of the local settings were working(!!)

The old init code in the configSettings class had no chance of working. We must use the full g.app.config.get logic.

Added some very simple unit tests to make sure the basics will never break again so easily.
There were problems searching for whitespace.

Note: it just ran slowly & silently.
http://sourceforge.net/forum/message.php?msg_id=2958470

I opened a new .leo file, and the cursor was flashing in the text box. I started typing "@language", and found that the first character is in the text box, and the rest is in the headline!

What I did:

This was the result of a race condition in the new scheme for setting focus. I rewrote set_focus so the delayed callback always sets the last requested focus. The new code also takes care to clear the last request after fulfilling it.
http://sourceforge.net/forum/message.php?msg_id=2958470

All changes were to g.app.leoID():

- Fixed bug: set g.app.leoID in << put up a dialog requiring a valid id >>. - Improved signon message. - Better error handling and reporting.
This now works: g.es('ﺻﺱ',color='red')

g.es must send the original unicode string to the log pane widget, NOT an encoded string.
http://sourceforge.net/forum/message.php?msg_id=2983923

- Replaced string.+ with string.% in numerous places. - Simplified g.openWithFileName and corrected problems in error-reporting logic.
When loading plugins, the Leo checks to see if the plugin has an init function at the top level (the module level). If so, Leo calls the init function. This function should return True (or equivalent) if the module loaded correctly.

If the top-level init function does not exist, Leo assumes the module loaded correctly.
A script in an @button node or script node can now request to be removed by setting g.app.scriptDict['removeMe'] = True. Leo checks this value after executing the script in the button.
@nocolor

Added define_p keyword arg in executeScript. When True (the default), the script or unit test is run in an environment in which ``c``, ``p`` and ``g`` are all defined. ``c`` is the commander for the outline in which the script appears. ``p`` is the same as ``c.currentPosition`` and ``g`` is the leoGlobals module.

Therefore, the following lines need never appear in scripts or unit tests!

@color

import leoGlobals as g p = c.currentPosition()
Typing return now correctly invokes the Find button, without adding a newline in the find string.
@nocolor http://sourceforge.net/forum/message.php?msg_id=2990951 Milan Melena

I think, I found two bugs:

1) leoAtFile.py: << read optional encoding param >> changed first instance of i = j + 1 to i = j + 2

2) leoGlobals.py g.getScript now returns with

if at.output_newline == 'crlf': return script.replace("\r\n","\n") else: return script
At present, such indented blocks may not contain Leo directives or section references. This will be fixed in 4.3a3.
1. (fixed) C:\prog\leoCVS\leo\src\leoCommands.py:4539: No global (loadDir) found # Would cause leoSettings.leo in Window menu to crash.

2. (fixed) C:\prog\leoCVS\leo\src\leoGlobals.py:3426: No global (local) found

# Local --> locale # Might cause getpreferredencoding to fail on *nix.

3. (fixed) C:\prog\leoCVS\leo\src\leoGlobals.py:4152: No global (testing) found # Should be self.testing.

4. (fixed) mu problems: - Changed x to self.x: - C:\prog\leoCVS\leo\src\leoGlobals.py:3795: No global (removeSentinelsFromLines) found - C:\prog\leoCVS\leo\src\leoGlobals.py:3838: No global (getSentinelsFromLines) found - Changed self.x to g.x: C:\prog\leoCVS\leo\src\leoGlobals.py:3854: No class attribute (comment_delims_from_extension) found - pull_source has been renamed, I don not know to what. C:\prog\leoCVS\leo\src\leoGlobals.py:4170: Object (mu) has no attribute (pull_source) (commented out the code that contains this)

5. (removed code) from << create a node p for kind & root2 >> - last_p is None at first, so last_p.insertAfter does not make sense.
@nocolor

c.frame.menu.createMenuItemsFromTable will append items to the end of an existing menu. For example, the following script will add a new item at the end of the 'File' menu. @color

def callback(*args,**keys): g.trace()

table = (("Test1",None,callback),)

c.frame.menu.createMenuItemsFromTable('File',table)

@nocolor Plugins can do anything that can be done with Tk using the menu returned by c.frame.menu.getMenu. For example, here is a script that adds a Test menu item after the 'Open With' menu item in the File menu. @color

def callback(*args,**keys): g.trace()

fileMenu = c.frame.menu.getMenu('File')

# 3 is the position in the menu. Other kinds of indices are possible. fileMenu.insert(3,'command',label='Test2',command=callback)
The authoritative source for information.
Leo 4.3 alpha 3 February 24, 2005

Leo 4.3 is the culmination of more than five months of work. This alpha 3 release corrects various bugs in Leo's core and in plugins. This is the first release that include an installer for MacOSX.

The defining features of Leo 4.3:

1. Leo now stores options in @settings trees, that is, outlines whose headline is '@settings'. When opening a .leo file, Leo looks for @settings trees not only in the outline being opened but also in various leoSettings.leo files.

The key design goal of @settings trees was that Leo's user options must be infinitely flexible. That goal has been accomplished. Indeed, users can create arbitrarily complex user options with @settings trees. Leo settings outlines are, in fact, infinitely more flexible and powerful than any scheme based on flat text. Readers of Python's configParser shootout take note!

2. The Settings command temporarily replaces the outline pane with an outline showing all the @settings trees in effect. The Settings command also replaces the body pane with a "settings pane". This settings pane allows you to change the settings selected in the outline pane using standard gui widgets. The settings pane is dynamically created from nodes in the settings tree; it is as extensible as the @settings tree itself.

3. Leo's read/write code in leoAtFile.py has been rewritten to support user- defined tangling and untangling. This is a major cleanup of Leo's core.

4. Leo now boasts a wonderful new Plugins Manager plugin. This plugin enables and disables plugins automatically. You never have to mess with pluginsManager.txt again! This plugin also tells you everything you need to know about each plugin. Finally, this plugin also lets you download plugins from Leo's cvs site! Many thanks to Paul Patterson for this excellent work.

5. You can install third-party extensions in Leo's extensions directory. Leo will attempt to import such extensions from the extensions directory if normal imports fail. Leo is distributed with Pmw (Python Mega Widgets), path.py and sets.py in this directory.
http://sourceforge.net/forum/message.php?msg_id=2998446 By: djsg

g.create_temp_name() calls tempfile.mktemp or mkstemp(), but these return different values!

mktemp returns the filename(a string); mkstemp returns a tuple (handle,filename)

What I did:

- Changed g.create_temp_name to g.create_temp_file. - Removed the file open logic in tangle.put_all_roots (now done in g.create_temp_file) - Rewrote g.create_temp_file so it works in both cases. - Create test routine for g.create_temp_file - Created very simple unit tests in test.leo for tangle and untangle.
http://sourceforge.net/forum/message.php?msg_id=2999651

I was pleasantly surprised to discover the reST2 plug-in working under 4.3a2 (this is one the first thing I try as I'd like to use Leo as an editor for that).

As mentioned in early threads, it still needs @rst for each node to be included in the reST rendering process. So I put @rst test.html and then a child with @rst and some reST code and it worked !!

Then I tried to to get a simple rst file using @rst test but the plugin complained:

[snip]

File "C:\dn_apps\Leo\plugins\rst2.py", line 164, in onIconDoubleClick writeTreeAsRst(rstFile,fname,p,c) TypeError: writeTreeAsRst() takes exactly 5 arguments (4 given)

So I looked at the rst2.py and found a way to get it working but I would need someone to verify it :

line 164, replaced writeTreeAsRst(rstFile,fname,p,c) by

syntax = False writeTreeAsRst(rstFile,fname,p,c,syntax)

And it worked!
http://sourceforge.net/forum/message.php?msg_id=3005140 By: ktenney

- perform a search which marks a number of nodes - select "Outline -> Mark/Unmark -> Unmark All" - Several marks are still listed in in the nodenavigator "Marks" list. (They are not marked in the outline.)

What I did:

- The p.set/clearMark methods now call the hook _after_ changing the marked status. This fixes the apparent bug in nodenavigator.py. - Rewrote nav_buttons.py. The old code was a mess; the new code is clean. - Changed the vnodeList ivar in leoTkinterDialog to positionList. - Rewrote c.unmarkAll to make clear that it is using positions. - Added test_c_unmark_all test routine.
http://sourceforge.net/forum/message.php?msg_id=2958470 From: Rich

Leo 4.3 alpha 1, build 1.208 , January 24, 2005 Python 2.3.4, Tk 8.4.3, win32

Opened a new .leo file. It asked for an ID, and said it saved it. Closed the new leo file & tried opening "Leo\config\leoSettings.leo". _It_ is asking for a leoID!

What I did

All changes were to g.app.leoID(): - Fixed bug: set g.app.leoID in << put up a dialog requiring a valid id >>. - Improved signon message. - Better error handling and reporting.
g.pdb wasn't working because pdb wasn't imported inside the function.
This allows plugins such as plugin_manager.py to work on Python 2.2.x.
g.es does nothing if color=='suppress'. This can be useful in unit tests.
http://sourceforge.net/forum/message.php?msg_id=3008045

Leo crashed when executing a script if the script was selected text in a new window.

What I did:

- g.getScript now calls g.getOutputNewline(c=c) rather than look at atFile.output_newline.

atFile.output_newline may not exist if a) the file is new and b) g.getScript doesn't call atfile.write.

- Set scripting=scriptWrite in call to atFile.scanAllDirectives in atFile.write.

This suppresses the following irrelevant message when executing scripts:

"No absolute directory specified anywhere."
This documents how I used Platypus 3.0 to create MacLeo, the MacOS X launcher for Leo. You don't need Platypus to _use_ MacLeo, but you do need Platypus to *create* MacLeo. You may download Platypus 3.0 from http://sveinbjorn.vefsyn.is/platypus Platypus creates something called an "application bundle," essentially a wrapper for the shell script called openLeoScript.sh.

At present this script contains just::

#!/bin/sh # $2 only works if .leo is one of the extensions. /usr/bin/pythonw ~/leo/src/leo.py $2

In detail, here is how I created MacLeo:

1. Open Platypus.

2. Set the Platypus settings::

- Name: MacLeo - Script type: shell - Icon: Python Icon - Using the standard Leo outline doesn't work, but one could be created… - Script Path: /Users/edream/dist/Platypus 3.0/openLeoScript.sh - Is droppable checkbox (checked) - Edit Types: .leo only, not *, not folders. - N.B. There MUST be a period in front of .leo! Otherwise $2 will be empty in the script. - Output: None (progress bar and text window appear to be essentially useless)

3. Hit the create button to create MacLeo.
This tells how I created ``leo-4-3-a3.pkg`` using ``PackageMaker``.

``PackageMaker`` is included in the ``Xtools`` disk that comes with MacOS X. Installing ``PackageMaker`` was easy, but I don't remember the details.

1. Make sure ``~/dist/make-leo-dist`` contains a folder called ``leo-(version)``. The ``~/dist/make-leo-dist/leo-(version)`` folder should contain a *folder* called just ``leo``. This is the folder that should have the files to be distributed. I got this folder by downloading ``leo-4-3-a3.zip``, the official a3 distribution.

2. Open ``PackageMaker`` by double-clicking the file ``~/dist/LeoPackage.pmsp`` I originally created this .pmsp file in ``PackageMaker``. It will be included in the next official release. I'll also add it to cvs. ``LeoPackage.pmsp`` contains most of the information needed to create the .pkg file, but even without the .pmsp file using ``PackageMaker`` is pretty self-explanatory

3. Update the description in the ``PackageMaker`` dialog. This should be similar to the readme file.

4. Browse to ``~/dist/make-leo-dist/leo-(version)`` in the ``Files`` tab in the ``PackageMaker`` dialog.

5. Choose ``Make Package`` from the ``PackageMaker File`` menu. If necessary, set the file name to ``Leo.pkg``. This will create ``Leo.pkg``.

6. Quit ``PackageMaker``. Choose 'yes' when prompted to save ``LeoPackage.pmsp``.
Leo's .leo file format is extensible. The basis for extending .leo files are the ``t.unknownAttributes`` and ``v.unknownAttributes`` ivars of tnodes and vnodes, or uA's for short. Leo translates between uA's and xml attributes in the corresponding ``<v>`` and ``<t>`` elements in .leo files. Plugins may also use ``v.tempAttributes`` or ``t.tempAttributes`` ivars to hold temporary information that will *not* be written to the .leo file.

Collectively, these four kinds of ivars are called **attribute ivars**. Attribute ivars must be Python dictionaries, whose keys are names of plugins and whose values are *other* dictionaries, called **inner dictionaries**, for exclusive use of each plugin. For example, a plugin named 'xyzzy' would set ``t.unknownAttributes`` as follows::

# Create the uA if necessary. if not hasattr(p.v.t,'unknownAttributes'): p.v.t.unknownAttributes = {}

# Get the inner dictionary for the 'xyzzy' plugin, creating it if necessary. d = p.v.t.unknownAttributes.get('xyzzy',{})

# Set some values. These values must be picklable. d ['duration'] = 5 d ['notes'] = "This is a note."

# Update the uA. p.v.t.unknownAttributes ['xyzzy'] = d

if hasattr(p.v.t,"unknownAttributes"): d = p.v.t.unknownAttributes.get("xyzzy",{}) g.es(d['duration']) g.es(d['notes'])

Plugins would use similar code to create ``v.unknownAttributes``, ``t.tempAttributes``, and ``v.tempAttributes`` ivars.

**Important**: All members of inner dictionaries should be picklable: Leo uses Python's Pickle module to encode all values in these dictionaries. Leo will discard any attributes that can not be pickled. This should not be a major problem to plugins. For example, instead of putting a tnode into these dictionaries, a plugin could put the tnode's gnx (a string) in the dictionary.

**Note**: Leo does *not* pickle members of inner dictionaries whose name (key) starts with ``str_``. The values of such members should be a Python string. This convention allows strings to appear in .leo files in a more readable format.

**Important**: Plugins must *not* use ``v.unknownAttributes`` inside ``@thin`` trees. Indeed Leo uses **hidden machinery** to write ``t.unknownAttributes``. Leo does *not* write ``t.unknownAttributes`` to thin derived files. Instead Leo writes a representation of all ``t.unknownAttributes`` contained in the ``@thin`` tree to a special xml attribute called ``descendentTnodeUnknownAttributes`` in the ``<v>`` element corresponding to the ``@thin`` node. Yes, this is complicated, but it works. Leo can *not* write ``v.unknownAttributes`` in ``@thin`` trees because **only tnodes have gnx's in thin derived files**. In effect, vnodes are anonymous.

Plugins that must associate attributes with vnodes should support only ``@file`` trees. A completely different alternative would be for the plugin to extend how Leo reads and writes ``<v>`` elements in .leo files, but that would be much more complicated than using ``t.unknownAttributes``

Here are the details about how Leo associates uA's with ``<v>`` and ``<t>`` elements in .leo files:

- **Native xml attributes** are the attributes of ``<v>`` and ``<t>`` elements that are known (treated specially) by Leo's read/write code. The only native attribute of ``<t>`` elements is ``tx``. The native attributes of ``<v>`` elements are ``a``, ``t``, ``vtag``, ``tnodeList``, ``marks``, ``expanded`` and ``descendentTnodeUnknownAttributes``. All other attributes of ``<v>`` and ``<t>`` elements are **foreign xml attributes**.

- When reading a .leo file, Leo will create ``t.unknownAttributes`` or ``v.unknownAttributes`` ivars for any ``tnode`` or ``vnode`` whose corresponding ``<v>`` or ``<t>`` element contains a foreign xml attribute.

- When writing a file, Leo will write foreign xml attributes in ``<v>`` or ``<t>`` elements if the corresponding vnode or tnode contains an ``unknownAttributes`` ivar.

- Leo performs the usual xml escapes on these strings when reading or writing the ``unknownAttributes`` ivars.
Leo 4.3 alpha 4 March 15, 2005

Leo 4.3 is the culmination of more than five months of work. This alpha 4 focuses on plugins: all known plugins are now in leoPlugins.leo. Most plugins now work with the 4.3 code base. Warning: not all plugins have been tested thoroughly.

This alpha 4 release also adds the frequently-requested Add Comments and Delete Comments commands to Leo's Edit Body menu.

The defining features of Leo 4.3:

1. Leo now stores options in @settings trees, that is, outlines whose headline is '@settings'. When opening a .leo file, Leo looks for @settings trees not only in the outline being opened but also in various leoSettings.leo files.

The key design goal of @settings trees was that Leo's user options must be infinitely flexible. That goal has been accomplished. Indeed, users can create arbitrarily complex user options with @settings trees. Leo settings outlines are, in fact, infinitely more flexible and powerful than any scheme based on flat text. Readers of Python's configParser shootout take note!

2. The Settings command temporarily replaces the outline pane with an outline showing all the @settings trees in effect. The Settings command also replaces the body pane with a "settings pane". This settings pane allows you to change the settings selected in the outline pane using standard gui widgets. The settings pane is dynamically created from nodes in the settings tree; it is as extensible as the @settings tree itself.

3. Leo's read/write code in leoAtFile.py has been rewritten to support user- defined tangling and untangling. This is a major cleanup of Leo's core.

4. Leo now boasts a wonderful new Plugins Manager plugin. This plugin enables and disables plugins automatically. You never have to mess with pluginsManager.txt again! This plugin also tells you everything you need to know about each plugin. Finally, this plugin also lets you download plugins from Leo's cvs site! Many thanks to Paul Patterson for this excellent work.

5. You can install third-party extensions in Leo's extensions directory. Leo will attempt to import such extensions from the extensions directory if normal imports fail. Leo is distributed with Pmw (Python Mega Widgets), path.py and sets.py in this directory.
Nodes containing the @root directive did not honor @nocolor directives.
http://sourceforge.net/forum/message.php?msg_id=3035471

Leo was not inserting a visible horizontal scrollbar when @nowrap was in effect.
http://sourceforge.net/forum/message.php?msg_id=3042593

Leo now properly redraws the screen after a Change All command.
Several hooks use the 'new_c' key in the keywords dictionary. Plugin writers had to remember whether to get the commander using keywords.get('c') or keywords.get('new_c') or both. This was needlessly confusing.

All hooks that use the 'new_c' key now use also include the 'c' key. The 'new_c' key is deprecated; plugins should use the 'c' key instead.

None of the plugins presently in leoPlugins.leo use the 'new_c' key, but the 'new_c' key still exists for compatibility.

The following plugins were affected by this change:

ConceptualSort.py URLloader.py UASearch.py arrows.py autocompleter.py base64Packager.py cleo.py dyna_menu.py macros.py mod_read_dir_outline.py mod_scripting.py multifile.py nodebar.py nodenavigator.py open_with.py scheduler.py read_only_nodes.py templates.py
The Add Comments command puts comments around a block of code. This command uses single-line comments if the language in effect for the node supports single-line comments.

The Delete Comments command deletes the comments specified by the Add Comments command.
Fixed problems in the following plugins. See the << version history >> section in each plugin for details.

autocompleter.py cleo.py mod_scripting.py mod_tempfname.py templates.py vim.py xemacs.py

Replaced the 'new_c' key by the 'c' key in the following plugins:

ConceptualSort.py URLloader.py UASearch.py arrows.py autocompleter.py base64Packager.py cleo.py dyna_menu.py macros.py mod_read_dir_outline.py mod_scripting.py multifile.py nodebar.py nodenavigator.py open_with.py scheduler.py read_only_nodes.py templates.py

Replaced the 'start2' hook by the 'new' hook in the following plugins: (This was made possible now that 'new' is called when opening a new window if the 'open1/2' hooks are not called.

URLloader.py UASearch.py at_produce.py autocompleter.py color_markup.py fastGotoNode.py groupOperations.py import_cisco_config.py multifile.py nodebar.py open_with.py read_only_nodes.py scheduler.py table.py usetemacs.py xsltWithNodes.py
atFile.copyAllTempBodyStringsToTnodes calls:

c.mod_label_controller.add_label(p,"before change:",old_body)
- The ``Add Comments`` command puts comments around a block of code. This command uses single-line comments if possible.

- The ``Delete Comments`` command deletes the comments specified by the ``Add Comments`` command.
Leo calls the 'before-create-leo-frame' hook just before calling frame.onCreate. Similarly, Leo calls the 'after-create-leo-frame' just after calling frame.onCreate.
Plugins and scripts should call ``u.beforeX`` and ``u.afterX`` methods ato describe the operation that is being performed. **Note**: ``u`` is shorthand for ``c.undoer``. Most ``u.beforeX`` methods return ``undoData`` that the client code merely passes to the corresponding ``u.afterX`` method. This data contains the 'before' snapshot. The ``u.afterX`` methods then create a bead containing both the 'before' and 'after' snapshots.

``u.beforeChangeGroup`` and ``u.afterChangeGroup`` allow multiple calls to ``u.beforeX`` and ``u.afterX`` methods to be treated as a single undoable entry. See the code for the ``Change All``, ``Sort``, ``Promote`` and ``Demote`` commands for examples. The ``u.beforeChangeGroup`` and ``u.afterChangeGroup`` methods substantially reduce the number of ``u.beforeX`` and ``afterX`` methods needed.

Plugins and scripts may define their own ``u.beforeX`` and ``afterX`` methods. Indeed, ``u.afterX`` merely needs to set the ``bunch.undoHelper`` and ``bunch.redoHelper`` ivars to the methods used to undo and redo the operation. See the code for the various ``u.beforeX`` and ``afterX`` methods for guidance.

``p.setDirty`` and ``p.setAllAncestorAtFileNodesDirty`` now return a ``dirtyVnodeList`` that all vnodes that became dirty as the result of an operation. More than one list may be generated: client code is responsible for merging lists using the pattern ``dirtyVnodeList.extend(dirtyVnodeList2)``

See the section ``<< How Leo implements unlimited undo >>`` in ``leoUndo.py`` for more details. In general, the best way to see how to implement undo is to see how Leo's core calls the ``u.beforeX`` and ``afterX`` methods.
Leo 4.3 beta 1 April 30, 2005

Leo 4.3 beta 1 completes all major features of Leo 4.3. There are no known significant bugs remaining.

The defining features of Leo 4.3: --------------------------------- 1. Leo now stores options in @settings trees, that is, outlines whose headline is '@settings'. When opening a .leo file, Leo looks for @settings trees not only in the outline being opened but also in various leoSettings.leo files.

The key design goal of @settings trees was that Leo's user options must be infinitely flexible. That goal has been accomplished. Indeed, users can create arbitrarily complex user options with @settings trees. Leo settings outlines are, in fact, infinitely more flexible and powerful than any scheme based on flat text. Readers of Python's configParser shootout take note!

2. The Settings command temporarily replaces the outline pane with an outline showing all the @settings trees in effect. The Settings command also replaces the body pane with a "settings pane". This settings pane allows you to change the settings selected in the outline pane using standard gui widgets. The settings pane is dynamically created from nodes in the settings tree; it is as extensible as the @settings tree itself.

3. Leo now stores recent files information in .leoRecentFiles.txt files.

4. Leo's read/write code in leoAtFile.py has been rewritten to support user- defined tangling and untangling. This is a major cleanup of Leo's core.

5. Leo now boasts a wonderful new Plugins Manager plugin. This plugin enables and disables plugins automatically. You never have to mess with pluginsManager.txt again! This plugin also tells you everything you need to know about each plugin. Finally, this plugin also lets you download plugins from Leo's cvs site! Many thanks to Paul Patterson for this excellent work.

6. You can install third-party extensions in Leo's extensions directory. Leo will attempt to import such extensions from the extensions directory if normal imports fail. Leo is distributed with Pmw (Python Mega Widgets), path.py and sets.py in this directory.
The initial bug report:

http://sourceforge.net/forum/message.php?msg_id=3048149

The problem arose from a misguided attempt to eliminate non-useful information from traces. Alas, the baby got thrown out with the bath water.

Here are the changes I made:

- c.executeScript now calls g.es_exception(full=True) to ensure that a full stack trace always gets produced. This is especially important when the exception happens in a module (file) called by the script.

- c.executeScript now always executes the section < < dump the lines near the error > >, regardless of context. The lines are printed (in black) in the log. This is useful information in almost all cases.

- After much experimentation, g.es_exception is basically unchanged. Note: If the error occurs in your script itself (as contrasted with an exception thrown from a file called by your script) Leo always has properly put the cursor on the offending line. I made no changes in this logic.

BTW, calling pdb.set_trace() in your scripts may cause more problems than it is worth. Indeed.pdb.set_trace() uses only the information on the stack, and that may not be enough information to be useful. I usually use g.trace to find out what is happening. This works well.
Initial bug report:

http://sourceforge.net/forum/message.php?msg_id=3053699

There were three similar bugs, all arising from the fact that g.os_path_abs and g.os_path_join return the _working_ directory if the initial path is None!

I removed my HOME directory for testing. This was essential.

- Compute home directory must return None, rather than the working directory if the HOME variable is None.

- app.setLeoId must be careful (in two sections) to do nothing if any of (homeDir,globalConfigDir,loadDir) is None.
The problem is that newButtons must use @nosent, so any changes to newButtons must be accompanied by a change to LeoPluginsRef.py. There is nothing more that needs to be done.
The De-hoist command conflicted with the Expand/Contract submenu.

The Paste Node As Clone conflicted with the Mark submenu.
The status bits weren't being passed to v.initStatus!
Traceback (most recent call last): File "c:\prog\leoCVS\leo\src\leoCommands.py", line 174, in doCommand command() File "c:\prog\leoCVS\leo\src\leoCommands.py", line 863, in importDerivedFile c.importCommands.importDerivedFiles(v,names) File "C:\prog\leoCVS\leo\src\leoImport.py", line 137, in importDerivedFiles isThin = at.scanHeaderForThin(theFile,fileName) File "C:\prog\leoCVS\leo\src\leoAtFile.py", line 570, in scanHeaderForThin junk,junk,isThin = at.scanHeader(theFile,fileName) File "C:\prog\leoCVS\leo\src\leoAtFile.py", line 2616, in scanHeader at.error("Bad @+leo sentinel in: %s" % fileName) File "C:\prog\leoCVS\leo\src\leoAtFile.py", line 4500, in error self.printError(message) File "C:\prog\leoCVS\leo\src\leoAtFile.py", line 4509, in printError if self.errors == 0: AttributeError: atFile instance has no attribute 'errors'
Traceback (most recent call last): File "C:\prog\leoCVS\leo\src\leoTkinterTree.py", line 1409, in idle_scrollTo h1 = self.yoffset(p) File "C:\prog\leoCVS\leo\src\leoTkinterTree.py", line 1488, in yoffset h, flag = self.yoffsetTree(root,v1) File "C:\prog\leoCVS\leo\src\leoTkinterTree.py", line 1506, in yoffsetTree h2, flag = self.yoffsetTree(child,p1)

# Maximum recursion depth exceeded.

It is still not completely clear why this happened.
- Moved computeGlobalConfigDir, computeHomeDir, computeLoadDir and startupEncoding from leo.py to leoGlobals.py.

- Created g.computeStandardDirectories and used it in leo.py.

- Created g.createStandAloneApp using the above functions. This function was based on the 'Standalone Operation' classed in the plugin_manager plugin. g.createStandAloneApp doesn't actually use any of these classes because the nullGui class is basically a clumsier version of the BlackHole class.

- Added a do-nothing attachLeoIcon method to nullGui class to suppress a warning. As I said, the nullGui class is not as elegant as Paul's BlackHole class.

- Added <<importLeoGlobals>> button to newButtons plugin. This creates a node named << define importLeoGlobals >> whose body text defines an importLeoGlobals function.

The idea is that importing leoGlobals from a stand-alone plugin is a bit tricky. The importLeoGlobals handles these details. Note that we don't want to define importLeoGlobals in a node included by @others, because this function must be available to the code in the << imports >> section. So we use a named section and reference it in before referencing the << imports >> section. See the plugin_manager plugin for an example.

- Changed the plugin_manager plugin as follows: - Used the newButtons plugin to add an << define importLeoGlobals >> section. - Simplified the import logic using importLeoGlobals function. - Commented out the Standalone Operation classes. - Called g.createStandAloneApp in the '__name__ == "__main__"' code.
- config.openSettingsFile returns None if there is a read error.

- leoFileCommand.open gives no BadLeoFile message if silent is True.
- Simplified write_Leo_file using new leoFileCommand.deleteFileWithMessage and g.utils_rename.

- Eliminated outputList var. - The code that writes to a clipboard sets self.outputFile to g.fileLikeObject.

- Sped up put routine: it always writes to self.outputFile.

- self.outputFile is now a cStringIo object. However, the heart of the put routine is:

s = g.toEncodedString(s,self.leo_file_encoding,reportErrors=True) self.outputFile.write(s)

and it appears that the call to g.toEncodedString is the limiting factor.
- Use g.Bunch to simplify code. - Added 'before' & 'after' methods - Added entries to optionalIvars dynamically in bead methods. - Eliminated 'case-itis' by making it unnecessary ever to add more cases. - Removed 'v' key in undoer: replaced it with 'p'. - Replaced u.v by u.p and v by p in find code (It's too confusing). - p.setDirty and p.setAllAncestorAtFileNodesDirty return list of nodes that were marked dirty. - Create new top-level before/after methods & helpers: - Changed setUndoTypingParams to use new dispatch method. - Removed makeBeadDict. - Removed updateSetChangedFlag. - Added new methods to nullUndoer class. - Moved undo methods from leoNodes.py to leoUndo.py - Added dirtyVnodeList param to afterChangeNodeContents.
The only changes concern how Leo encodes and decodes items in t.unknownAttributes and v.unknownAttributes.

Without changing the file format, the only way to tell Leo how to write attributes is to use naming conventions. When writing attributes, Leo now does the following:

- Do nothing except apply xml escapes if the attribute name (in t.unknownAttributes or v.unknownAttributes) starts with str_ and the attribute is, in fact, a string. If the string is a Unicode string Leo converts the Unicode string to an encoded string.

- Use the present pickling/hexlifying scheming otherwise. In particular, issue a warning and ignore the attribute if the attribute can not be pickled. BTW, there is no need for separate base64 support: hexlifying guarantees that the result is valid in any xml environment.

Leo now does the reverse when reading.

BTW, plugins could add their own naming conventions in an emergency. Indeed, the conventions will be confined to code in atFile.putUa and atFile.getUa, so a plugin would only need to override these two methods.
Removed inAtOthers param from putOpen/CloseNodeSentinel. Removed inAtAll param from putCloseNodeSentinel. Removed putCloseSentinel param from putAtAllBody Removed putCloseSentinel param from putBody

Removed toString param from openFileForWritingHelper Removed toString param from v.putUnknownAttributes

Note: most(all?) top-level atFile.write methods pass toString to initWriteIvars.
Leo stores recent files information as follows.

1. Leo stores recent files info in files called .leoRecentFiles.txt. These will be a plain text files with one line per recent files entry. An Easter egg: if the file starts with read-only, read_only, readonly, etc. Leo will never update the file and will not remember changes to the Recent Files menu.

2. On startup, Leo searches for the .leoRecentFiles.txt files in the user's home directory, if it exists. Leo looks in Leo's config directory next, but only if the home directory does not exist, or does not contain a .leoRecentFiles.txt file. In other words, Leo will use at most one .leoRecentFiles.txt file on startup.

3. When opening a .leo file, Leo looks for .leoRecentFiles.txt in the directory containing the file.

4. At no time after installation does Leo create any .leoRecentFiles.txt file. This will allow users (or their managers) to set policy regarding where to store this information (if anywhere).

5. Leo writes at most one .leoRecentFiles.txt file when saving a .leo file, namely the file read in item 3 if it exists, or the file read in item 2 otherwise.

This is a flexible scheme that should meet most needs without having to resolve thorny questions about exactly where recent files info belongs.
@killcolor

- Properly implemented undo/redo Clear Recent Files.

- readSettingsFiles now reads @recentfiles nodes from all settings files.

- Created @settings nodes and @recent-files nodes if they do not exist.
@killcolor

You all have convinced me that storing recent files data in .leo files is a dubious idea. My new plan is as follows:

1. Leo will store recent files info in files called .leoRecentFiles.txt. These will be a plain text files with one line per recent files entry. These will be local files, so problems concerning directory structure and path specifications should go away.

2. On startup, Leo will search for the .leoRecentFiles.txt files in the user's home directory, if it exists. Leo will look in Leo's config directory next, but only if the home directory does not exist, or does not contain a .leoRecentFiles.txt file. In other words, Leo will use at most one .leoRecentFiles.txt file on startup.

3. When opening a .leo file, Leo will look for .leoRecentFiles.txt in the directory containing the file.

4. At no time after installation will Leo create any .leoRecentFiles.txt file. This will allow users (or their managers) to set policy regarding where to store this information (if anywhere).

5. Leo will write at most one .leoRecentFiles.txt file when saving a .leo file, namely the file read in item 3 if it exists, or the file read in item 2 otherwise.

6. Leo will have settings to tell which .leoRecentFiles.txt files may be written.

7. Leo will never create @settings nodes or @recent-files nodes automatically. Moreover, I shall remove the @recent-files panel from the settings dialog and the corresponding @recent-files code from the config classes.

I believe this will address everyone's concerns without the need for resolving thorny questions about exactly where recent files info belongs.

- Saved expansion state of @settings trees when the user hits the OK button.

- Added support for UNL's in the status line when the settings dialog is active.

- Debugged @if-platform, @if-gui, @ints & @strings.

- Reloaded settings files when opening the settings dialog.

- Removed support for @recent-files nodes. This is now handled by .leoRecentFiles.txt files.
Leo 4.3 beta 2 May 15, 2005

Leo 4.3 beta 2 completes all major features of Leo 4.3 and fixes all bugs reported since the beta 1 release.

The defining features of Leo 4.3: --------------------------------- 1. Leo now stores options in @settings trees, that is, outlines whose headline is '@settings'. When opening a .leo file, Leo looks for @settings trees not only in the outline being opened but also in various leoSettings.leo files.

The key design goal of @settings trees was that Leo's user options must be infinitely flexible. That goal has been accomplished. Indeed, users can create arbitrarily complex user options with @settings trees. Leo settings outlines are, in fact, infinitely more flexible and powerful than any scheme based on flat text. Readers of Python's configParser shootout take note!

2. The Settings command temporarily replaces the outline pane with an outline showing all the @settings trees in effect. The Settings command also replaces the body pane with a "settings pane". This settings pane allows you to change the settings selected in the outline pane using standard gui widgets. The settings pane is dynamically created from nodes in the settings tree; it is as extensible as the @settings tree itself.

3. Leo now stores recent files information in .leoRecentFiles.txt files.

4. Leo's read/write code in leoAtFile.py has been rewritten to support user- defined tangling and untangling. This is a major cleanup of Leo's core.

5. Leo now boasts a wonderful new Plugins Manager plugin. This plugin enables and disables plugins automatically. You never have to mess with pluginsManager.txt again! This plugin also tells you everything you need to know about each plugin. Finally, this plugin also lets you download plugins from Leo's cvs site! Many thanks to Paul Patterson for this excellent work.

6. You can install third-party extensions in Leo's extensions directory. Leo will attempt to import such extensions from the extensions directory if normal imports fail. Leo is distributed with Pmw (Python Mega Widgets), path.py and sets.py in this directory.
http://sourceforge.net/forum/message.php?msg_id=3133917

'Recent' and 'Marked' button now appear in new windows.
http://sourceforge.net/forum/message.php?msg_id=3133915

The colorizer now correctly handles the following:

\@, \(, \), \{, \}

And also constructs like \documentclass{report}.
http://sourceforge.net/forum/message.php?msg_id=3051870
http://sourceforge.net/forum/message.php?msg_id=3138608

The nav_buttons plugin was using self.c rather than keywords.get('c') in a hook handler. The general rule is that hook handlers should do nothing if self.c !- keywords.get('c'). This was an old bug, arising from the rewrite of the plugin.

I added a warning to that effect in the plugin template.

It would perhaps be better to specify an optional commander in registerHandler and only call the handler if the commander matches. However, this isn't so easy or clean to do.I

http://sourceforge.net/forum/forum.php?thread_id=1282631&forum_id=10226

The plugin was failing to set the positionList ivar (in the base tkinterListBoxDialog class). This was a fairly recent blunder: I saw that positionList wasn't used in the plugin directly, so I 'improved' the code by using a local var instead of self.positionList. This illustrates a hazard of using subclassing.
This happened when creating a new chapter with chapters.py enabled.
http://sourceforge.net/forum/forum.php?thread_id=1281868&forum_id=10226

The fix was to recompute newSel in << handle backspace with negative tab_width >> in idle_body_key.
- The section name lost its indentation. - The created section had extra indentation. - Undoing did not remove the inserted section node.

The unit tests now properly test indentation.
http://sourceforge.net/forum/message.php?msg_id=3143895

The Edit->Delete command did nothing when the selected text was in a headline.
The following methods changed:

- markAllAtFileNodesDirty - markAtFileNodesDirty - markClones - markHeadline - markSubheads

I also rewrote the code using explicit positions.
http://sourceforge.net/forum/forum.php?thread_id=1281868&forum_id=10226

doStrings now accepts either:

@strings[values]name=value @strings name[values]=value

Similarly, doInts accepts:

@ints[values]name=value @ints name[values]=value
http://sourceforge.net/forum/message.php?msg_id=3149604

Changed c.hoistStack[-1].current to c.hoistStack[-1].p in c.insertHeadline.
http://sourceforge.net/forum/forum.php?thread_id=1281868&forum_id=10226

The code now calls frame.resizePanesToRatio in createFrame in Leo.

Not only does this fix this bug, it honors the following settings:

- initial_horizontal_ratio - initial_horizontal_secondary_ratio - initial_vertical_ratio - initial_vertical_secondary_ratio
http://sourceforge.net/forum/message.php?msg_id=3138608

Replaced individual shortcuts widget with a single text widget. This allows the user to add or delete shortcuts.
http://sourceforge.net/forum/message.php?msg_id=3135170
For a test of this, see the script in test.leo at:

Scripts-->Script to execute @test, @suite or file

Read the documentation in that node before running the script.
g.getScript now fully processes all scripts, regardless of where they came from.

- Changed g.getScript: - p arg is now required. - Removed unused script arg. - Added forcePythonSentinels arg (default is True). - g.getScript no longer temporarily alters any body text. - atFile.writeFromString gets the initial text using the fromString arg. - g.getScript now always calls atFile.writeFromString to handle all Leo directives.

- Added forcePythonSentinels to atFile.initWriteIvars and atFile.scanAllDirectives. - Default is None, in which case the code sets forcePythonSentinels to the scriptWrite arg.

- Added forcePythonSentinels to atFile.scanAllDirectives. - Default is False.

- Created atFile.putAtFirstLines and atFile.putAtLastLines. - These replace the corresponding sections in writeOpenFile. - It was not actually necessary to define these, but it cleans up the code.

- Created atFile.writeFromString. - This handles all the details of simulating a write _from_ a string _to_ a string.

- atFile.initWriteIvars and atFile.openFileForWriting now allow root to be None. - This is not used at present: root is always defined.

- Added fromString arg to atFile.writeOpenFile and atFile.putBody.
http://sourceforge.net/forum/forum.php?thread_id=1281640&forum_id=10228

The default is ''. It define_name exists c.executeScript executes the script in an environment containing __name__ = define_name.
Leo 4.3 final May 23, 2005

Leo 4.3 is here after almost five months of work.

The defining features of Leo 4.3: --------------------------------- 1. Leo now stores options in @settings trees, that is, outlines whose headline is '@settings'. When opening a .leo file, Leo looks for @settings trees not only in the outline being opened but also in various leoSettings.leo files.

The key design goal of @settings trees was that Leo's user options must be infinitely flexible. That goal has been accomplished. Indeed, users can create arbitrarily complex user options with @settings trees. Leo settings outlines are, in fact, infinitely more flexible and powerful than any scheme based on flat text. Readers of Python's configParser shootout take note!

2. The Settings command temporarily replaces the outline pane with an outline showing all the @settings trees in effect. The Settings command also replaces the body pane with a "settings pane". This settings pane allows you to change the settings selected in the outline pane using standard gui widgets. The settings pane is dynamically created from nodes in the settings tree; it is as extensible as the @settings tree itself.

3. Leo now stores recent files information in .leoRecentFiles.txt files.

4. Leo's read/write code in leoAtFile.py has been rewritten to support user- defined tangling and untangling. This is a major cleanup of Leo's core.

5. Leo now boasts a wonderful new Plugins Manager plugin. This plugin enables and disables plugins automatically. You never have to mess with pluginsManager.txt again! This plugin also tells you everything you need to know about each plugin. Finally, this plugin also lets you download plugins from Leo's cvs site! Many thanks to Paul Patterson for this excellent work.

6. You can install third-party extensions in Leo's extensions directory. Leo will attempt to import such extensions from the extensions directory if normal imports fail. Leo is distributed with Pmw (Python Mega Widgets), path.py and sets.py in this directory.
http://sourceforge.net/forum/message.php?msg_id=3155657

Enabling the Pie Menu plug-in caused Leo to quit when opening .leo files.
This fixed a recent bug. The crash happened if not section text was specified. Added new checks and new error messages.
Leo 4.3.1 June 20, 2005

- Added support for Tk resource files. - Added support for coloring the PL/SQL language. - All Mark commands are now undoable. - Improved Resize To Screen command. - The usual assortment of minor bug fixes.
http://sourceforge.net/forum/message.php?msg_id=3166883 By: rogererens

I swear I didn't wait for the release to be the first to report a bug! I just didn't try this in the alpha/beta versions:

Leo 4.3 final, build 1.262 , May 23, 2005 Python 2.4.1, Tk 8.4.7, win32

Changing Global settings: C:\Leo\config\leoSettings.leo-->Window options-->@page Options for new windows-->@ratio initial_horizontal_ratio = 0.3 or any of the other ratios, does not save them to leoSettings.leo. So after restarting I still have the old settings in use.
http://sourceforge.net/forum/message.php?msg_id=3167166

The fix was to add the following line to the init function:

global click_registry, coloured_nodes
Modifying outlines can invalidate existing positions! This rarely happens. At present it affects the atFile.read logic when reading an outline whose initial current position is a clone outside an @thin tree with another clone inside the @thin tree. So the read logic computes the expected current position before reading all derived files, and this expected current position becomes invalid.

What I did:

1. Moved << set current and top positions >> from getVnodes to end of getLeoFile. This ensures that the outline won't change after computing the position.

2. Unit tests will have to be revised to make sure that only valid positions get used.
- Fixed bugs in convertAllBlanks and convertAllTabs.

These must always call afterChangeGroup to match beforeChangeGroup, even if nothing has changed.

- Added u.getMark and u.rollbackToMark.

These allow unit tests to cut the undo stack back to an initial position in the tearDown method. This should be done for all tests that use u.undo and u.redo methods. The bug was probably the result of changing the outline in the tearDown method.

Both the Reformat Paragraph and Edit Body unit tests now roll back the undo stack.

- Added traces for unexpected conditions in u.undo, u.redo and tree.select.

- Call u.setUndoTypes() in u.setUndoTypingParams when returning early.

- Corrected Edit Body unit tests.

These tests should not call undo/redo when nothing is expected to change. Doing so may trigger the new 'cant undo' traces in u.undo.

- doTest in leoTest.py now makes copies of both p and p1.

It's not clear that this is needed, it can't hurt, and it may have been important.
The problem was that leo.__file__ returns a randomly upper or lower cased drive letter.
# The About Leo dialog was not getting focus.
http://sourceforge.net/forum/message.php?msg_id=3176499

5) am I missing text in the Settings panels? the outline shows that certain nodes have text (e.g., "About keyboard shortcuts" has the blue rectangle), yet the body pane is empty; heck, even the title suggests that something should be there...
http://sourceforge.net/forum/message.php?msg_id=3190593

As luck would have it, I need to put an @ character at the beginning of a line in source code (windows registry file format) and can't figure out how to do it.
http://sourceforge.net/forum/message.php?msg_id=3186385

I just tried 4.3-final, and it seems it does not work with Chinese LC_CTYPE:
http://sourceforge.net/forum/message.php?msg_id=3175553

When I set default_target_language to plain in 4.2., no words in any body text is colored. This behavior seems to have changed in 4.3. Is it right, that I now have to write @nocolor on top of *every* body text to get rid of randomly colored words?

What I did:

- Added entries for target_language to ivarsDic and defaultsDict in leoConfig.py. - Added @language target_language = Python to leoSettings.leo. - Convert c.target_language to lowercase in several places.
idle_body_key now calls doAutoIndent and convertBlanksToTabs. The idea is that plugins could override these methods if desired.
# I also fixed a bug: the Mark Clones command did not work!
Some non-standard distributions don't include the profile and pstats modules.
Leo will now look for a file called .leo_xresources in the users home directory. If found, Leo will pass that file to Tk's option_readfile method for the top widget. This allows users to set Tk options.
Leo looks for a file called ``.leo_xresources`` in the users home directory. If found, Leo will pass that file to Tk's ``option_readfile`` method for the top widget. This allows users to set Tk options.
import leoPlugins

rst3 = leoPlugins.getPluginModule('rst3')

if rst3: controller = rst3.controllers.get(c) if controller: controller.processTopTree(p) else: rst3 = leoPlugins.loadOnePlugin('rst3',verbose=True) if rst3: g.es('rst3 loaded') rst3.onCreate('tag',{'c':c}) else: # Ask to be removed. g.app.scriptDict['removeMe'] = True
Deletes p.v.rst2_http_attributename from all nodes after writing.

Deletes p.v.unknownAttributes if it then becomes empty.
@nocolor

If False, add_node_marker and http_support_main do nothing. Otherwise add_node_marker does the following:

1. add_node_marker writes a string using generate_node_marker.

Generates 'http-node-marker-'+str(number), where number is config.node_counter (incremented each time add_node_marker is called.

2. Enables the following code in : @color

if config.tag == 'open2': http_map = self.http_map else: http_map = {} config.anchormap = {} # maps v nodes to markers. config.node_counter = 0 # [snip] code to write the tree if config.rst2_http_server_support: self.http_map = http_map
True: call body_filter to massage text.

Removes @ignore, @nocolor, @wrap directives.
Used differently. See rst2_pure_document.
----------------

|prev| |leo| |next|
.. External links...

.. .. _`CWEB`: http://www-cs-faculty.stanford.edu/~knuth/cweb.html .. _`Open Software`: http://www.opensource.org/ .. _Python: http://www.python.org/ .. _`SourceForge`: http://sourceforge.net/projects/leo/

.. Relative links...

.. _clones: intro.html#clones-views .. _leo: front.html .. _outline: intro.html#introduction .. _outlines: intro.html#introduction .. _plugins: intro.html#plugins-settings .. _scripting: intro.html#scripting-leo .. _users: http://sourceforge.net/projects/leo/

.. WARNING: image targets may not have upper case letters!

.. |leo| image:: leo.gif :target: front.html

.. |prev| image:: arrow_lt.gif :target: leo_TOC.html

.. |next| image:: arrow_rt.gif :target: preface.html
.. Links used in this document.

.. _front: front.html .. _chapter6: design.html .. _chapter8: customizing.html

.. _`rst3 plugin`: rstplugin3.html

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: design.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: customizing.html
------------

|leo| |next|
########################### |leo| Using the rst3 plugin ###########################

.. August 14, 2005

@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = True verbose=True @c

.. contents::
.. Links used in this document...

.. _LaTeX: http://www.latex-project.org/ .. _reStructuredText: http://docutils.sourceforge.net/rst.html .. _docutils: http://docutils.sourceforge.net .. _ListManagerDocs.html: http://webpages.charter.net/edreamleo/ListManagerDocs.html .. _wxListManager.leo: http://webpages.charter.net/edreamleo/wxListManager.leo .. _SilverCity: http://silvercity.sourceforge.net .. _front: http://webpages.charter.net/edreamleo/front.html .. _home: http://webpages.charter.net/edreamleo/front.html

.. |blank| image:: blank.gif .. |leo| image:: leo.gif :target: http://webpages.charter.net/edreamleo/front.html
The rst3 plugin creates output files from Leo outlines containing reStructuredText_ (rST) ReStructuredText is a simple and powerful text formatting markup language. Outlines are a natural way to organize rST (or any text).

.. The line @rst <xyzzy> causes problems.

This plugin adds the Write Restructured Text command to Leo's Edit menu. The Write Restructured Text command searches the selected outline looking for **rst root nodes** whose headline have the form @rst xyzzy. The plugin then creates the named file in various ways depending which rst3 options are in effect.

By default, the rst3 plugin creates rST headings automatically from outlines, so the higher-level nodes in the outline correspond to higher-level sections in the output. Creating rST headings automatically relieves you from one of the most tedious chores in creating rST markup.

.. .. [1] See footnote 1.

.. .. [2] See footnote 2.

To use this plugin effectively, Python's docutils_ module must be installed. The rst3 plugin will use the SilverCity_ syntax coloring package if it installed.

This plugin sends .htm, .html or .tex files to the docutils module for further processing. Docutils generates HTML files or LaTeX files depending on the file's extension. HTML files generated by docutils refer to three .css (cascading style sheet) files that should exist in the same directory as the generated HTML file. You can control the formatting of the HTML file by altering these .css files. .. .. See `Required cascading style sheets`_ for more details. See Required cascading style sheets for more details.
The rst3 plugin provides several important benefits compared to previous rst plugins:

1. This plugin allows much more flexible control over its operations using **rst3 options**. You can set options in @settings trees, in headlines and in body text. Nodes inherit most rst3 options from ancestor nodes much like nodes inherit Leo directives. See `Options`_.

The most important option is the code_mode option. This option specifies whether to process the body text of a node as rst markup (rst mode) or source code that is to be converted to rST markup (code mode). Unlike previous versions of this plugin, any node can be processed in any mode.

2. Headlines can set any option. This turns out to be very convenient. See `Headline commands`_ for details. Nodes whose headlines start with @rst-options are treated specially. The body text of such **rst options nodes** should contain nothing but lines of the form::

<option>=<value>

3. You can set any rst3 options in the *body text* of any node using doc parts of the form::

@ @rst-options list of rst3 options, one per line @c

Such **option doc parts** allows you to specify rst3 options even with source code files.

4. You can embed rST markup in the body text of any node using doc parts of the form::

@ @rst-markup any rST markup @c

Such **markup doc parts** allow you to fine-tune the formatting of your source files. See `Using doc parts`_ for full details.

All these features create a wonderful environment for using rST. There is complete integration of Leo outlines with rST markup. You can embed both rst3 options and rST markup in any node, even node in derived files.
You can set any option in any node, so you have complete control over how this plugin processes each node. The following is a list of options that control how the rst3 plugin formats each particular node.

code_mode True: process nodes in code mode. False: process nodes in rst mode. In code mode, the rst3 plugin automatically creates rST markup to display the body text as an rst code-block. In rst mode the rst3 simply copies the body text of the node to the output. That is, the plugin assumes that body text is already valid rST markup.

default_path The path to be prepended to filenames given in root nodes. The default is an empty string.

generate_rst A master switch. True: generate rST markup for rST sections and rST code-blocks. False: don't generate rST markup and ignore @ @rst-markup doc parts.

number_code_lines Controls whether to number code lines in code mode. This option has no effect in rst mode.

show_doc_parts_as_paragraphs True: Move doc parts outside of the code-block directive in code mode. This option has no effect in rst mode.

**Cool**: Any rST markup in doc parts included as the result of this option will be rendered properly.

show_headlines True: automatically generate rST sections from headlines. Applies to both code mode and rst mode.

The level of the node in the outline determines the level of the section underling in the rST markup. Higher-level headlines in the outline correspond to higher-level section headings; lower-level headlines in the outline correspond to lower-level section headings.

show_leo_directives True: include Leo directives in code mode. This option has no effect in rst mode.

show_markup_doc_parts True: include markup doc parts in code mode. This option has no effect in rst mode.

show_options_doc_parts True: include options doc parts in code mode. This option has no effect in rst mode.

show_options_nodes True: show @rst-options nodes.

show_organizer_nodes True: generate rST sections for nodes that do not contain body text. This option has no effect unless the rST section would otherwise be written.

stylesheet_name The name of the stylesheet passed to docutils. The default is 'default.css'

stylesheet_path The directory containing the stylesheet passed to docutils. The default is an empty string.

underline_characters The underlining characters to be used to specify rST sections. The default value is \'\'\'#=+*^~"'\`-:><\_\'\'\'. The first character is reserved so you can specify the top-level section explicitly.

verbose True: write informational messages.

write_intermediate_file True: writes intermediate files before sending them to docutils. This option only applies to .htm, .html and .tex files. The name of the intermediate file has the name of the output file with .txt appended. This option has effect only if the generate_rst option is True.
It is often convenient to set options in headlines. This is done with the following **headline commands**:

.. changed <text> to TEXT to avoid problems.

@rst TEXT Enter rst mode. Create a section called TEXT provided the show_headlines option is set.

@rst-code TEXT Enter code mode. Create a section called TEXT provided the show_headlines option is set.

@rst-ignore-node TEXT Suppress all output from a single node. TEXT is ignored. Has *no* effect on descendant nodes and does **not** change any rst3 option.

@rst-ignore-tree TEXT Suppress all output from the node and its descendants. TEXT is ignored. Does **not** change any rst3 formatting option.

@rst-no-head TEXT Suppress the generation of an rST section for this node only. Does not affect descendant nodes. Has *no* effect on descendant nodes and does **not** change any rst3 option.

@rst-no-headlines TEXT Set the show_headlines option to False. As a result, TEXT is ignored.

@rst-option OPTION = VALUE Set a single option to the given value. The default value is True.

@rst-options TEXT Set zero or more options from the body text of the node. TEXT is ignored. The entire body text is treated as if it were in an @ @rst-options doc part.

**Notes**:

- Several of these commands affect only the node in which they appear. Such commands set internal settings variables only: they have no effect on the visible rst3 options.

- If a headline generates an rST section, the section name does not include the headline command. Furthermore, no rST section is generated if the TEXT is empty.
Recall that in Leo a doc part starts with the '@' directive and continues until the end of body text or until the '@c' directive is seen. For example::

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

Leo converts doc parts into comments using whatever comment delimiters are in effect.

**Option doc parts** are doc parts that start with @ @rst-options. All other lines of such doc parts should be of the form name=value. (rST comments lines starting with '..' are allowed). For example::

@ @rst-options .. This comment line is ignored. show_headlines=False show_leo_directives=False verbose=True @c

The rst3 plugin sets options from option doc parts, even in code mode.

**Markup doc parts** are doc parts that start with @ @rst-markup. For example::

@ @rst-markup .. contents::

The rst3 plugin replaces markup doc parts by the markup they contain, even in code mode.

Option and markup doc parts are especially useful in code mode. They allow you to specify options or insert rST markup directly from with derived files. This makes your source files self contained: there is no need to add other nodes to make the rst3 plugin happy.

A cool feature: In code mode, rST markup in *ordinary* doc parts will be rendered properly when the show_doc_parts_as_paragraphs option is in effect. *Important*: Regardless of the show_doc_parts_as_paragraphs option, doc parts have no special significance in rst mode. That is, the entire `doc part` from the opening '@' to the closing '@c and everything in between are treated normal rST markup.
You can set the defaults for any rst3 option in several ways:

\1. By setting options in the root node using @ @rst-options doc parts. For example, the root of the file that generated this documentation contains::

@ @rst-options code_mode=False generate_rst=True show_organizer_nodes=True show_headlines=True show_leo_directives=True verbose=True @c

\2. By setting options in @settings trees. To do this, you must prefix the option name shown in this documentation with the prefix 'rst3\_'. For example::

@settings @bool rst3_write_intermediate_file = True
This plugin defines a code-block rST directive. The primary purpose of this directive is to show formatted source code.

In rst mode you can insert the code-block directive like any other rST markup. The rst3 plugin generates code-block directives when handling nodes in code mode.

This directive takes one argument, a language name. Like this::

.. code-block:: Python

import leoPlugins import leoGlobals as g

This directive syntax colors the code in the indented code block that follows the directive. The result looks like this if the SilverCity syntax coloring module has been installed.

.. code-block:: Python

import leoPlugins import leoGlobals as g

Otherwise, the output looks like this::

import leoPlugins import leoGlobals as g

See the tree called "Scripting chapter using the rst plugin" in LeoDocs.leo for many examples of how to use code-blocks.
HTML files generated by the rst3 plugin assume that three .css (cascading style sheet) files exist in the same directory. For the HTML output to look good the following .css files should exist:

- default.css is the default style sheet that docutils expects to exist.

- leo_rst.css contains some style improvements based on Gunnar Schwant's DocFactory.

- silver_city.css is the style sheet that controls the syntax highlighting generated by SilverCity.

The latter two style sheets are imported at the end of the default.css.

**Important:** You can use cascading style sheets to do things that otherwise wouldn't be possible with "plain" rST. For instance, the background color of this page was specified in a body style.
The plugin reserves the '#' character for your own use so that you can specify an rST headline explicitly. For example,::

##### Title #####

You would typically put such a title in the rst root node. Otherwise, you should let the rst3 plugin automatically generate rST sections from headlines.

To create a table of contents (TOC) put::

.. contents:: Table of Contents

on its own line wherever you want the TOC to appear. This line can appear in body text in rst mode, or in an @ @rst-markup doc part in code mode.
The file ListManagerDocs.html_ is an impressive example of the kind of output that can be generated relatively easily using this plugin.

The source for ListManagerDocs.html is wxListManager.leo_. **Important**: wxListManager.leo was written for the rst2 plugin; it could be greatly simplified if adapted for the rst3 plugin.

The files in LeoDocs.leo under the node 'Leo's HTML Users Guide' contain examples of using the rst3 plugin.

This documentation was created using the rst3 plugin. The source code for this documentation is in LeoDocs.leo. The source code for all the rst plugins is in LeoPlugins.leo.
Josef Dalcolmo wrote the initial rst plugin. Timo Honkasalo, Bernhard Mulder, Paul Paterson, Kent Tenney and Steve Zatz made contributions to the rst and rst2 plugins. Edward K. Ream designed and wrote the rst3 plugin.
-------------

|leo|
The following options are for the use of Bernhard Mulder's http plugin. The http plugin creates an http server running on a local port, typically 8080. When the http plugin is running you will see a purple message in the log window that looks something like this::

http serving enabled on port 8080, version 0.91

To use the http plugin, start a web browser and enter this url::

http://localhost:8080/

You will see a a top level page containing one link for every open .leo file. Clicking on link will cause the http server to pass a new page to the browser. You can use the browser's refresh button to update the top-level view in the browser after you have opened or closed files.

**Important**: See the docstring for the http plugin for information on configuring the plugin. Some of the following rst3 settings must match values of settings for the http plugin. Here are the rst3 options that support the http plugin:

http_server_support A master switch: none of the following options have any effect unless this option is True. If True, the rst3 plugin does the following:

- Writes **node markers** in the rst output for use by the http plugin. Node markers are rst named hyperlink targets. By default they look like::

.. _http-node-marker-N

where N is a unique node number.

- Adds additional information to all nodes of the tree being formatted using Leo's unknownAttributes mechanism.

http_attributename The name of the attribute name written to the unknownAttributes attribute of each each outline node in the rst root tree. The default is 'rst_http_attribute'; it should match the following setting of the *http* plugin::

@string rst_http_attributename = 'rst_http_attribute'

This option has no effect unless the http_server_support option is True.

clear_http_attributes If True the rst3 plugin initially clears the fields specified by `http_attributename`. This option has no effect unless the http_server_support option is True.

node_begin_marker The string used for node markers. The default is 'http-node-marker-'. This option has no effect unless the http_server_support option is True.
The code for the rst3 plugin is more complex than usual. Fortunately, the overall organization is straightforward.

defaultOptionsDict This dictionary represents each rst3 option. To add another option, just add another entry to this dictionary. Keys are the option name, including the `rst3_` prefix. Values are the default value of the option. The hard values in the dictionary may be changed as the result of @settings entries.

processTree processTree is the top-level code that handles one rst root node. It calls preprocessTree to create the **tnodeOptionDict** ivar. processTree then calls either writeNormalTree or writeSpecialTree depending on whether text will be sent to docutils for further processing. These two methods handle mundane details of opening an closing files. Both writeNormalTree and writeSpecialTree call **writeTree** to do the actual work.

tnodeOptionDict The entries in this dictionary represents the options that are set in one particular node. The keys of tnodeOptionDict are tnodes, the values are anonymous dictionaries. These anonymous inner dictionaries contain the options that are explicitly set at each tnode (and thus each position). Preprocessing the tree this way ensures that each node (headline and body text) is parsed exactly once.

writeTree writeTree first calls **scanAllOptions**, which has the effect of initializing all options. writeTree then calls **writeNode** for each node that will be processed by the rst3 plugin. Options may cause the plugin to skip a node or an entire subtree.

writeNode writeNode first calls **scanAllOptions** to compute the options that are in effect for that *single* node. Once options have computed, processing the node is straightforward. writeNode calls writeBody and writeHeadline to do the real work. These methods generate or skip text based on various options.

scanAllOptions scanAllOptions recreates the optionsDict ivar to represent *all* the options in effect for *for the particular node being processed by writeNode*. Client code gets these options by calling the getOption method.

scanAllOptions first inits all options from settings, then updates those options using the anonymous dictionaries contained in the tnodeOptionsDict. scanAllOptions works like g.scanAllDirectives, but the code is much simpler.
The following options specify the 'spelling' of headline commands. The option_prefix and option_prefixes command also define the spelling of special doc parts.

You can change these to make them shorter or to avoid conflicts with headlines in your Leo files. The list below merely gives the default value for each setting.

.. escape the '@' signs so they don't become email addresses.

`code_prefix`: '\@rst-code'

`ignore_headline_prefix`: '\@rst-no-head'

`ignore_headlines_prefix`: '\@rst-no-headlines'

`ignore_node_prefix`: '\@rst-ignore-node'

`ignore_tree_prefix`: '\@rst-ignore-tree'

`option_prefix`: '\@rst-option'

`options_prefix`: '\@rst-options'

`rst_prefix`: '\@rst'

`show_headline_prefix`: '\@rst-head'
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

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

.. contents::
**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|
.. Links used in this document...

.. ----- External references.

.. _`Leo's help forum`: http://sourceforge.net/forum/forum.php?forum_id=10227 .. _`Literate Programming`: http://www.literateprogramming.com/ .. _`noweb`: http://www.eecs.harvard.edu/~nr/noweb/

.. ----- Relative links....

.. _directive: `Leo directives`_ .. _directives: `Leo directives`_ .. _`derived file`: `Derived files`_ .. _glossary: glossary.html .. _`Good style and bad`: `Good style and bad: sections vs. @others`_ .. _outline: `Leo's main window`_ .. _outlines: `Leo's main window`_ .. _plugin: `Plugins & settings`_ .. _plugins: `Plugins & settings`_ .. _quickstart: `Quick start for programmers`_ .. _scripts: `Scripting Leo`_ .. _settings: `Plugins & settings`_

.. ----- References to other chapters.

.. _`@auto trees`: directives.html#auto-trees .. _command: commands.html .. _commands: commands.html .. _`editing commands`: commands.html#the-edit-menu .. _front: front.html .. _`install Leo`: install.html .. _`launch Leo`: install.html#running-leo .. _`Leo's Users Guide`: leo_TOC.html .. _`Chapter 4: Writing Programs in Leo`: directives.html .. _`Chapter 6: Leo and Literate Programming`: design.html .. _`Chapter 7: Scripting Leo with Python`: scripting.html .. _`Chapter 8: Customizing Leo`: customizing.html

.. ----- References to the glossary

.. _`@auto`: glossary.html#auto .. _`@file`: glossary.html#file .. _`@nosent`: glossary.html#nosent .. _`@others`: glossary.html#others .. _`@thin`: glossary.html#thin .. _`@thin trees`: glossary.html#thin-trees .. _`body text`: glossary.html#body-text .. _ancestor: glossary.html#ancestor .. _children: glossary.html#child .. _clone: glossary.html#clone .. _cloned: glossary.html#cloned .. _cloning: glossary.html#clone .. _clones: glossary.html#clones .. _`code part`: glossary.html#code-part .. _`doc part`: glossary.html#doc-part .. _descendant: glossary.html#descendant .. _descendants: glossary.html#descendants .. _`doc part`: glossary.html#doc-part .. _grandchildren: glossary.html#grandchildren .. _headline: glossary.html#headline .. _headlines: glossary.html#headlines .. _`organizer node`: glossary.html#organizer-node .. _`organizer nodes`: glossary.html#organizer-nodes .. _`outline order`: glossary.html#outline-order .. _node: glossary.html#node .. _nodes: glossary.html#nodes .. _reference: glossary.html#reference .. _references: glossary.html#references .. _root: glossary.html#root .. _`root node`: glossary.html#root .. _section: glossary.html#section .. _sections: glossary.html#section .. _`section definition`: glossary.html#section-definition .. _`section definitions`: glossary.html#section-definitions .. _`section definition nodes`: glossary.html#section-definition-nodes .. _`section name`: glossary.html#section-name .. _`section names`: glossary.html#section-names .. _`section reference`: glossary.html#section-reference .. _`section references`: glossary.html#section-references .. _siblings: glossary.html#siblings

.. WARNING: image targets may not have upper case letters!

.. |leoMainWinow| image:: PCWindow.gif

.. |back| image:: arrow_lt.gif :target: install.html

.. |next| image:: arrow_rt.gif :target: outlines.html

.. |leo| image:: leo.gif :target: front.html
-------------

|back| |leo| |next|
.. June 8, 2006

@ @rst-options code_mode=False doc_only_mode=False default_path = generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. publish_argv_for_missing_stylesheets = --language=de,--documentclass=report,--use-latex-toc

|back| |leo| |next|

#################################### Chapter 14: Using the rst3 plugin ####################################

.. contents::
.. rST links used in this document...

.. External links...

.. _docutils: http://docutils.sourceforge.net .. _LaTeX: http://www.latex-project.org/ .. _reStructuredText: http://docutils.sourceforge.net/rst.html .. _SilverCity: http://silvercity.sourceforge.net

.. Hard links to Leo's web site...

.. _ListManagerDocs.html: http://webpages.charter.net/edreamleo/ListManagerDocs.html .. _wxListManager.leo: http://webpages.charter.net/edreamleo/wxListManager.leo

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: writingPlugins.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: coloring.html
The rst3 plugin creates output files from Leo outlines containing reStructuredText_ (rST) ReStructuredText is a simple and powerful text formatting markup language. Outlines are a natural way to organize rST (or any text).

This plugin adds the Write Restructured Text command to Leo's Edit menu. The Write Restructured Text command searches the selected outline looking for **rst root nodes** whose headline have the form @rst <filename>. The plugin then creates the named file in various ways depending which rst3 options are in effect.

By default, the rst3 plugin creates rST headings automatically from outlines, so the higher-level nodes in the outline correspond to higher-level sections in the output. Creating rST headings automatically relieves you from one of the most tedious chores in creating rST markup.

To use this plugin effectively, Python's docutils_ module must be installed. The rst3 plugin will use the SilverCity_ syntax coloring package if it installed.

This plugin sends .htm, .html or .tex files to the docutils module for further processing. Docutils generates HTML files or LaTeX files depending on the file's extension. HTML files generated by docutils refer to three .css (cascading style sheet) files that should exist in the same directory as the generated HTML file. You can control the formatting of the HTML file by altering these .css files. See `Required cascading style sheets`_ for more details.
The rst3 plugin provides several important benefits compared to previous rst plugins:

1. This plugin allows much more flexible control over its operations using **rst3 options**. You can set options in @settings trees, in headlines and in body text. Nodes inherit most rst3 options from ancestor nodes much like nodes inherit Leo directives. See `Options`_.

The most important option is the code_mode option. This option specifies whether to process the body text of a node as rst markup (rst mode) or source code that is to be converted to rST markup (code mode). Unlike previous versions of this plugin, any node can be processed in any mode.

2. Headlines can set any option. This turns out to be very convenient. See `Headline commands`_ for details. Nodes whose headlines start with @rst-options are treated specially. The body text of such **rst options nodes** should contain nothing but lines of the form::

<option>=<value>

3. You can set any rst3 options in the *body text* of any node using doc parts of the form::

@ @rst-options list of rst3 options, one per line @c

Such **option doc parts** allows you to specify rst3 options even with source code files.

4. You can embed rST markup in the body text of any node using doc parts of the form::

@ @rst-markup any rST markup @c

Such **markup doc parts** allow you to fine-tune the formatting of your source files. See `Using doc parts`_ for full details.

All these features create a wonderful environment for using rST. There is complete integration of Leo outlines with rST markup. You can embed both rst3 options and rST markup in any node, even node in derived files.
You can set any option in any node, so you have complete control over how this plugin processes each node. The following is a list of options that control how the rst3 plugin formats each particular node.

code_mode (default: False) True: process nodes in code mode. False: process nodes in rst mode. In code mode, the rst3 plugin automatically creates rST markup to display the body text as an rst code-block. In rst mode the rst3 simply copies the body text of the node to the output. That is, the plugin assumes that body text is already valid rST markup.

doc_only_mode (default: False) True: process nodes in doc_only mode. False: process nodes in rst mode or code_mode, depending on options. In doc_only mode, the rst3 plugin outputs only regular doc parts and @ @rst-markup doc parts. Headlines create section in doc_only mode only if a\) the node contains a doc part or b\) the show_organizer_nodes option is in effect. As always can use @ @rst-options for per-node control of the process, especially node-by-node control of the show_organizer_nodes option.

default_path (default: '') The path to be prepended to filenames given in root nodes.

generate_rst (default: True) A master switch. True: generate rST markup for rST sections and rST code-blocks. False: don't generate rST markup and ignore @ @rst-markup doc parts.

number_code_lines (default: True) Controls whether to number code lines in code mode. This option has no effect in rst mode.

show_doc_parts_as_paragraphs (default: False) True: Move doc parts outside of the code-block directive in code mode. This option has no effect in rst mode. **Cool**: Any rST markup in doc parts included as the result of this option will be rendered properly.

show_headlines (default: True) True: automatically generate rST sections from headlines. Applies to both code mode and rst mode. The level of the node in the outline determines the level of the section underling in the rST markup. Higher-level headlines in the outline correspond to higher-level section headings; lower-level headlines in the outline correspond to lower-level section headings.

show_leo_directives (default: True) True: include Leo directives in code mode. This option has no effect in rst mode.

show_markup_doc_parts (default: False) True: include markup doc parts in code mode. This option has no effect in rst mode.

show_options_doc_parts (default: False) True: include options doc parts in code mode. This option has no effect in rst mode.

show_options_nodes (default: False) True: show @rst-options nodes.

show_organizer_nodes (default: True) True: generate rST sections for nodes that do not contain body text. This option has no effect unless the rST section would otherwise be written.

strip_at_file_prefixes (default: True) True: remove @auto, @file, @nosent and @thin from the start of headlines.

stylesheet_name (default: 'default.css') The name of the stylesheet passed to docutils.

stylesheet_path (default: '') The directory containing the stylesheet passed to docutils.

underline_characters (default: \'\'\'#=+*^~"'\`-:><\_\'\'\') The underlining characters to be used to specify rST sections. The first character is reserved so you can specify the top-level section explicitly.

verbose (default: True) True: write informational messages.

write_intermediate_file (default: False) True: writes intermediate files before sending them to docutils. This option only applies to .htm, .html and .tex files. The name of the intermediate file has the name of the output file with .txt appended. This option has effect only if the generate_rst option is True.

publish-argv-for-missing-stylesheets (Default: '') The arguments to be passed to docutils.core.Publisher().publish() when no stylesheet is in effect. This is a string that represents a comma-separated list of strings: For example, the option::

publish-argv-for-missing-stylesheets=--language=de,--documentclass=report,--use-latex-toc

results in the call::

publish(['--language=de','--documentclass=report','--use-latex-toc'])
The following options are for the use of Bernhard Mulder's http plugin. The http plugin creates an http server running on a local port, typically 8080. When the http plugin is running you will see a purple message in the log window that looks something like this::

http serving enabled on port 8080, version 0.91

To use the http plugin, start a web browser and enter this url::

http://localhost:8080/

You will see a a top level page containing one link for every open .leo file. Clicking on link will cause the http server to pass a new page to the browser. You can use the browser's refresh button to update the top-level view in the browser after you have opened or closed files.

**Important**: See the docstring for the http plugin for information on configuring the plugin. Some of the following rst3 settings must match values of settings for the http plugin. Here are the rst3 options that support the http plugin:

http_server_support (default: False) A master switch: none of the following options have any effect unless this option is True. If True, the rst3 plugin does the following:

- Writes **node markers** in the rst output for use by the http plugin. Node markers are rst named hyperlink targets. By default they look like::

.. _http-node-marker-N

where N is a unique node number.

- Adds additional information to all nodes of the tree being formatted using Leo's unknownAttributes mechanism.

http_attributename (default: 'rst_http_attribute') The name of the attribute name written to the unknownAttributes attribute of each each outline node in the rst root tree. The default is 'rst_http_attribute'; it should match the following setting of the *http* plugin::

@string rst_http_attributename = 'rst_http_attribute'

This option has no effect unless the http_server_support option is True.

clear_http_attributes (default: False) If True the rst3 plugin initially clears the fields specified by `http_attributename`. This option has no effect unless the http_server_support option is True.

node_begin_marker (default: 'http-node-marker-') The string used for node markers. This option has no effect unless the http_server_support option is True.
The following options specify the 'spelling' of headline commands. The option_prefix and option_prefixes command also define the spelling of special doc parts.

You can change these to make them shorter or to avoid conflicts with headlines in your Leo files. The list below merely gives the default value for each setting.

`code_prefix`: '\@rst-code'

`ignore_headline_prefix`: '\@rst-no-head'

`ignore_headlines_prefix`: '\@rst-no-headlines'

`ignore_prefix_tree`: '\@rst-ignore'

`ignore_node_prefix`: '\@rst-ignore-node'

`ignore_tree_prefix`: '\@rst-ignore-tree'

`option_prefix`: '\@rst-option'

`options_prefix`: '\@rst-options'

`preformat_prefix`: '\@rst-preformat'

`rst_prefix`: '\@rst'

`show_headline_prefix`: '\@rst-head'
It is often convenient to set options in headlines. This is done with the following **headline commands**:

@rst TEXT Enter rst mode. Create a section called TEXT provided the show_headlines option is set.

@rst-code TEXT Enter code mode. Create a section called TEXT provided the show_headlines option is set.

@rst-ignore-node TEXT Suppress all output from a single node. TEXT is ignored. Has *no* effect on descendant nodes and does **not** change any rst3 option.

@rst-ignore-tree TEXT and @rst-ignore TEXT Suppress all output from the node and its descendants. TEXT is ignored. Does **not** change any rst3 formatting option.

@rst-no-head TEXT Suppress the generation of an rST section for this node only. Does not affect descendant nodes. Has *no* effect on descendant nodes and does **not** change any rst3 option.

@rst-no-headlines TEXT Set the show_headlines option to False. As a result, TEXT is ignored.

@rst-option <option> = <value> Set a single option to the given value. The default value is True.

@rst-options TEXT Set zero or more options from the body text of the node. TEXT is ignored. The entire body text is treated as if it were in an @ @rst-options doc part.

@rst-preformat TEXT Format the entire body text of the node as if the entire text preformatted. TEXT is ignored. In effect, a line containing '::' is added to the start of the text, and all following lines of the text are indented. This option has no effect on descendant nodes.

**Notes**:

- Several of these commands affect only the node in which they appear. Such commands set internal settings variables only: they have no effect on the visible rst3 options.

- If a headline generates an rST section, the section name does not include the headline command. Furthermore, no rST section is generated if the TEXT is empty.
Recall that in Leo a doc part starts with the '@' directive and continues until the end of body text or until the '@c' directive is seen. For example::

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

Leo converts doc parts into comments using whatever comment delimiters are in effect.

**Option doc parts** are doc parts that start with @ @rst-options. All other lines of such doc parts should be of the form name=value. (rST comments lines starting with '..' are allowed). For example::

@ @rst-options .. This comment line is ignored. show_headlines=False show_leo_directives=False verbose=True @c

The rst3 plugin sets options from option doc parts, even in code mode.

**Markup doc parts** are doc parts that start with @ @rst-markup. For example::

@ @rst-markup .. contents::

The rst3 plugin replaces markup doc parts by the markup they contain, even in code mode.

Option and markup doc parts are especially useful in code mode. They allow you to specify options or insert rST markup directly from with derived files. This makes your source files self contained: there is no need to add other nodes to make the rst3 plugin happy.

A cool feature: In code mode, rST markup in *ordinary* doc parts will be rendered properly when the show_doc_parts_as_paragraphs option is in effect. *Important*: Regardless of the show_doc_parts_as_paragraphs option, doc parts have no special significance in rst mode. That is, the entire `doc part` from the opening '@' to the closing '@c and everything in between are treated normal rST markup.
You can set the defaults for any rst3 option in several ways:

\1. By setting options in the root node using @ @rst-options doc parts. For example, the root of the file that generated this documentation contains::

@ @rst-options code_mode=False doc_mode_only=False generate_rst=True show_organizer_nodes=True show_headlines=True show_leo_directives=True verbose=True @c

\2. By setting options in @settings trees. To do this, you must prefix the option name shown in this documentation with the prefix 'rst3\_'. For example::

@settings @bool rst3_write_intermediate_file = True
This plugin defines a code-block rST directive. The primary purpose of this directive is to show formatted source code.

In rst mode you can insert the code-block directive like any other rST markup. The rst3 plugin generates code-block directives when handling nodes in code mode.

This directive takes one argument, a language name. Like this::

.. code-block:: Python

import leoPlugins import leoGlobals as g

This directive syntax colors the code in the indented code block that follows the directive. The result looks like this if the SilverCity syntax coloring module has been installed.

.. code-block:: Python

import leoPlugins import leoGlobals as g

Otherwise, the output looks like this::

import leoPlugins import leoGlobals as g

See the tree called "Scripting chapter using the rst plugin" in LeoDocs.leo for many examples of how to use code-blocks.
HTML files generated by the rst3 plugin assume that three .css (cascading style sheet) files exist in the same directory. For the HTML output to look good the following .css files should exist:

- default.css is the default style sheet that docutils expects to exist.

- leo_rst.css contains some style improvements based on Gunnar Schwant's DocFactory.

- silver_city.css is the style sheet that controls the syntax highlighting generated by SilverCity.

The latter two style sheets are imported at the end of the default.css.

**Important:** You can use cascading style sheets to do things that otherwise wouldn't be possible with "plain" rST. For instance, the background color of this page was specified in a body style.
The plugin reserves the '#' character for your own use so that you can specify an rST headline explicitly. For example,::

##### Title #####

You would typically put such a title in the rst root node. Otherwise, you should let the rst3 plugin automatically generate rST sections from headlines.

To create a table of contents (TOC) put::

.. contents:: Table of Contents

on its own line wherever you want the TOC to appear. This line can appear in body text in rst mode, or in an @ @rst-markup doc part in code mode.
The file ListManagerDocs.html_ is an impressive example of the kind of output that can be generated relatively easily using this plugin.

The source for ListManagerDocs.html is wxListManager.leo_. **Important**: wxListManager.leo was written for the rst2 plugin; it could be greatly simplified if adapted for the rst3 plugin.

The files in LeoDocs.leo under the node 'Leo's HTML Users Guide' contain examples of using the rst3 plugin.

This documentation was created using the rst3 plugin. The source code for this documentation is in LeoDocs.leo. The source code for all the rst plugins is in LeoPlugins.leo.
The code for the rst3 plugin is more complex than usual. Fortunately, the overall organization is straightforward.

defaultOptionsDict This dictionary represents each rst3 option. To add another option, just add another entry to this dictionary. Keys are the option name, including the `rst3_` prefix. Values are the default value of the option. The hard values in the dictionary may be changed as the result of @settings entries.

processTree processTree is the top-level code that handles one rst root node. It calls preprocessTree to create the **tnodeOptionDict** ivar. processTree then calls either writeNormalTree or writeSpecialTree depending on whether text will be sent to docutils for further processing. These two methods handle mundane details of opening an closing files. Both writeNormalTree and writeSpecialTree call **writeTree** to do the actual work.

tnodeOptionDict The entries in this dictionary represents the options that are set in one particular node. The keys of tnodeOptionDict are tnodes, the values are anonymous dictionaries. These anonymous inner dictionaries contain the options that are explicitly set at each tnode (and thus each position). Preprocessing the tree this way ensures that each node (headline and body text) is parsed exactly once.

writeTree writeTree first calls **scanAllOptions**, which has the effect of initializing all options. writeTree then calls **writeNode** for each node that will be processed by the rst3 plugin. Options may cause the plugin to skip a node or an entire subtree.

writeNode writeNode first calls **scanAllOptions** to compute the options that are in effect for that *single* node. Once options have computed, processing the node is straightforward. writeNode calls writeBody and writeHeadline to do the real work. These methods generate or skip text based on various options.

scanAllOptions scanAllOptions recreates the optionsDict ivar to represent *all* the options in effect for *for the particular node being processed by writeNode*. Client code gets these options by calling the getOption method.

scanAllOptions first inits all options from settings, then updates those options using the anonymous dictionaries contained in the tnodeOptionsDict. scanAllOptions works like g.scanAllDirectives, but the code is much simpler.
Josef Dalcolmo wrote the initial rst plugin. Timo Honkasalo, Bernhard Mulder, Paul Paterson, Kent Tenney and Steve Zatz made contributions to the rst and rst2 plugins. Edward K. Ream designed and wrote the rst3 plugin.
-----------------------

|back| |leo| |next|
.. This was used only for testing.

[1]_ Footnote 1.

[2]_ Footnote 2.
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.
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.
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.
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. 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 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** 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`_.
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.
So far we have discussed features that Leo shares with other editors and outliners. The following sections explain what makes Leo unique.
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.
**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.
`@thin trees`_ (parts of the outline whose *headline* starts with @thin) 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**:

- `Section definition nodes`_ must be descendants_ of the node_ containing the `section reference`_. Leo's syntax colorer underlines undefined `section references`_.

- `Section definitions`_ may contain references to other sections_.

- The **@others** directive_ is a special kind of `section reference`_. Leo replaces the ``@others`` directive by the body text of all descendant_ nodes_ *except* `section definition nodes`_. That's how ``@others`` got its name. For example, the `root node`_ of Python `derived files`_ typically is something like this::

<< docstring >> << imports >> @others

The `derived file`_ will contain the docstring, followed by the imports, followed by the the body text of all other nodes in the ``@file`` tree, in `outline order`_.

- A `derived file`_ may contain multiple ``@others`` directives_: Each ``@others`` directive expands to the body text of all descendant_ nodes_, excluding any nodes (and *their* descendants) that contain other ``@others`` directives_. In practice, using ``@others`` is easy.

- You may precede `section references`_ (including the ``@others`` directive_) with whitespace. When expanding the section references, Leo inserts the preceding whitespace before every expanded line. For example, the following will work properly in Python::

if path: << create or recreate temp file as needed >>

*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 derived files that do not contain sentinels. Leo imports such derived files every time Leo reads the .leo file.
``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`_.
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."
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.
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.
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.
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. August 28, 2005

|back| |leo| |next|

##################################### Chapter 4: Writing Programs in Leo #####################################
This chapter is a *reference guide* to computer programming with Leo. This chapter does *not* teach you how to use Leo: for that you should read `Leo's tutorial`_. This chapter assumes you are thoroughly familiar with the terminology introduced in the tutorial. **Note**: Are you *sure* you want to read this chapter? It contains many details that are no interest to the average user of Leo. I recommend using Leo for two weeks, or longer, before attempting this chapter.

.. contents::
The following sections give full details about each directive. The directives listed here may appear in headlines or body text.
The ``@all`` directive is valid only in ``@thin`` trees. The ``@all`` directive is similar to ``@others``, but it is less restrictive: it dumps *all* nodes to the derived file, including ``@ignore`` nodes and nodes that in an ``@others`` tree would be considered to be orphan nodes.

The ``@all`` directive is required for files such as ``@thin leoProjects.txt`` in ``LeoPy.leo``. ``leoProjects.txt`` contains so-called project nodes. It doesn't have any meaning as a program file: it is simply a collection of unrelated data. ``@others`` would not work at all: it would complain about lots of orphan nodes.
Syntax coloring is on by default in all body text. Leo formats comments and documentation parts in red, directives and C keywords in blue, strings and character constants in gray and all other text in code parts in black. The ``@nocolor`` directive disables syntax coloring for the body text in which it appears. No syntax coloring is done until an ``@color`` directive re-enables syntax coloring.

If a node contains neither the ``@color`` nor the ``@nocolor`` directive it may inherit the syntax coloring attribute from an ancestor. The nearest ancestor that contains exactly one of the ``@color`` or ``@nocolor`` directives will control the syntax coloring. **Ambiguous nodes**, nodes containing both the ``@color`` and ``@nocolor`` directives, never affect the coloring of their offspring.

The ``@killcolor`` directive completely disables the colorizer for that node. The result much faster syntax coloring of large body text. As usual ``@killcolor`` may itself be overridden in descendant nodes. The differences between ``@killcolor`` and ``@nocolor``:

- ``@nocolor`` suppresses coloring only until the next ``@color`` directive.

- ``@killcolor`` overrides ``@nocolor`` and ``@color`` directives. Any node containing @killcolor is unambiguously a ``@killcolor`` node regardless of whether that node also contains ``@color`` or ``@nocolor`` directives.

**Note**: the ``@color``, ``@nocolor`` and ``@killcolor`` directives do not affect the ``Tangle`` commands in any way. In particular, the ``Tangle`` commands will recognize section definitions as usual even after an ``@nocolor`` directive is seen.
**Note**: the ``@comment`` directive is deprecated: you should use the ``@language`` directive whenever possible. However, sometimes using both ``@language`` and ``@comment`` is useful. For this to be effective the ``@comment`` directive should appear after the ``@language`` directive (in outline order).

The ``Untangle`` command will not process an ``@root`` or ``@unit`` node if an ``@comment`` directive is in effect because ``Untangle`` can't be sure of properly parsing a derived file if the language of the derived file isn't known. It might be possible to assume some defaults in this case, but that is not done at present and is not a high priority. By default, the ``Tangle`` commands produces C-language comments. Single-line comments generated during tangling start with ``///``, while documentation parts are surrounded by ``/*`` and ``*/``. The ``@comment`` directive allows you to use ``Tangle`` to produce shell and make files, as well as source code for other programming languages.

The ``@comment`` directive may be followed by zero to three delimiters, separated by whitespace. This directive sets the single-line comment delimiter and the opening and closing block comment delimiters as follows:

====================== ===================================================================== \@comment no args\: restores the defaults to ///, /\* and \*/ ---------------------- --------------------------------------------------------------------- \@comment /// \1 arg\: sets the single-line comment and clears the other delims. ---------------------- --------------------------------------------------------------------- \@comment /\* \*/ \2 args\: sets the block comment delims; clears the single-line delim. ---------------------- --------------------------------------------------------------------- \@comment /// /\* \*/ \3 args\: sets all three delimiters. ====================== =====================================================================

If only one delimiter is given, Leo does not write any documentation parts while tangling. If two delimiters are given, block-style comments are used instead of single-line comments. For example, the ``@comment { }`` directive could be used to tangle Pascal files.

The ``@comment`` directive is only recognized in ``@root``, ``@unit`` or ``@file`` nodes, and the ``@comment`` directive must precede the first section name or ``@code`` directive. An ``@comment`` directive in the body text of an ``@unit`` directive specifies the current global defaults. An ``@comment`` directive in the body text of an ``@root`` directive affects comments generated for one root only. Comments in all other roots are governed by the global defaults.

Leo will convert underscores in the ``@comment`` directives to significant spaces. For example::

@comment REM_

causes the comment delimiter to be "REM " (Note the trailing space).
The ``@delims`` directive changes the comment strings used to mark sentinel lines. This directive is often used to place Javascript text inside XML or HTML files. The ``delims`` directive is not valid in ``@root`` or ``@unit`` trees.

The ``@delims`` directive contains one or two delimiters, separated by whitespace. If only one delim is present it delimits single-line comments. If two delims are present they delimit block comments. The ``@delims`` directive can not be used to change the comment strings at the start of the derived file, that is, the comment strings for the ``@+leo`` sentinel and the initial ``@+body`` and ``@+node`` sentinels.

The ``@delims`` directive inserts ``@@delims`` sentinels into the derived file. The new delimiter strings continue in effect until the next ``@@delims`` sentinel in the derived file or the end of the derived file.

**Note**: Leo can not revert to previous delimiters automatically; you must change back to previous delimiters using another ``@delims`` directive. For example::

@delims /* */ Javascript stuff @delims <-- --> HTML stuff

Adding, deleting or changing ``@@delims`` sentinels will destroy Leo's ability to read the derived file. Mistakes using the ``@delims`` directive have no effect on Leo, though such mistakes will thoroughly mess up a derived file as far as compilers, HTML renderers, etc. are concerned.
You may use the ``@encoding`` directive to specify the encoding used in a derived file. You can't mix encodings in a single derived file. For example::

@encoding iso-8859-1

If the encoding used in a derived file is not "utf-8" it is represented in the @+leo sentinel line, like this::

#@+leo-encoding=iso-8859-1.

The ``utf-8`` encoding is used by default. The ``utf-8`` encoding is a "lossless" encoding (it can represent all unicode code points), so encoding and decoding to and from ``utf-8`` plain strings will never cause a problem. When reading or writing a character not in a "lossy" encoding (such as ``iso-8859-1``), Leo converts such characters to ``'?'`` and issues a warning.
The ``@first`` directive allows you to place lines at the very start of files derived from ``@file`` nodes. For example, the body text of ``@file spam.py`` might be::

@first #! /usr/bin/env python

The body text of ``@file foo.perl`` might be::

@first #/usr/bin/perl

``@first`` directives are recognized only at the start of the body text of ``@file`` nodes. No text may precede ``@first`` directives. More than one ``@first`` directive may exist, like this::

@first #! /usr/bin/env python @first # more comments.

The ``@first`` directive is not valid in ``@root`` or ``@unit`` trees.
The ``@language`` directive specifies the comment delimiters and string types used by the ``Tangle`` and ``Untangle`` commands. This directive over-rides the default specified in the settings dialog.

When the threading_colorizer plugin is enabled, the valid @language directives are::

@language x

where the leo/modes folder contains the file x.py. When the threading_colorizier plugin is not enabled, the 'old' colorizer is used and the valid ``@language`` directives are::

@language actionscript @language c @language c++ @language cweb @language elisp @language html @language java @language latex @language objective-c @language pascal @language perl @language perlpod @language plain @language python @language rebol @language shell @language tcltk

Shell files have comments that start with `#`. Case is ignored in the language specifiers, but not in the ``@language`` itself. Thus, the following are equivalent::

@language html @language HTML @language hTmL

but the following is invalid::

@LANGUAGE html
The ``@lineending`` directive sets the line endings for individual derived files. This directive will override the ``output_newline`` setting. The ``@lineending`` *never* affects the line endings in .leo files themselves: .leo files must have consistent line endings!

The valid forms of the ``@lineending`` directive are:

======================= ====================================================== \@lineending nl The default, Linux. ----------------------- ------------------------------------------------------ \@lineending cr Mac ----------------------- ------------------------------------------------------ \@lineending crlf Windows ----------------------- ------------------------------------------------------ \@lineending lf Same as 'nl', not recommended ----------------------- ------------------------------------------------------ \@lineending platform Same as platform value for ``output_newline`` setting. ======================= ======================================================
The ``@path`` directives override the deprecated ``default_tangle_directory`` setting.

The form of the @path directive is ``@path`` *filename*, where *filename* is taken to be everything following @path to the end of the line.

If *filename* is an absolute filename the location of the derived file is specified only by the filename. Otherwise, if *filename* is a relative filename, the location of the derived file is relative to:

1. the directory specified the applicable ``@path`` directive, or 2. the "Default Tangle Directory" in the Settings dialog if no ``@path`` directive is in effect, or 3. the directory in which the .leo file resides if the .leo file has ever been saved.

An error occurs if no absolute path can be computed according to these rules, or if *filename* does not exist.
The ``@raw`` and ``@end_raw`` directives are valid only within ``@file`` trees. The ``@raw`` directive starts a section of "raw" text. The ``@end_raw`` directive ends such a section, as does the end of body text. No section references are recognized within raw text, and no additional leading whitespace is generated within raw text when writing the derived file.
Leo allows you to choose whether body text in ``@root`` trees will start in code mode or doc mode by default. ``@root-doc`` *filename* and ``@root-code`` *filename* directives specify that body text is assumed to start in doc mode or code mode respectively. The options (``-doc`` and ``-code``) must follow ``@root`` immediately with no intervening whitespace. In effect, ``@root-code`` and ``@root-doc`` are two new directives.

These ``@root`` options override the ``at_root_bodies_start_in_doc_mode`` setting. This setting affects only @root trees without options. Such "plain" ``@root`` trees are now deprecated, which only means that it is better style to use either ``@root-code`` or ``@root-doc``. The reason is simple: the meaning of plain ``@root`` trees will depend on the ``at_root_bodies_start_in_doc_mode`` setting. It's better to be explicit. By default, ``at_root_bodies_start_in_doc_mode = 1`` for compatibility for old ``@root`` trees. I actually don't think this option is good for much; I created it before I created ``@root-doc`` and ``@root-code`` settings, and I decided it wouldn't hurt to leave it in. Anyway, you now have complete flexibility about how ``@root`` works, and in particular you can make ``@root`` work just like ``@file``.
By default, the ``body_pane_wraps`` setting controls whether body text wraps. You may override this setting for a particular tree using the ``@wrap`` and ``@nowrap`` directives. Only the first ``@wrap`` or ``@nowrap`` directive in a node has any effect.
See `CWEB`_ for a discussion of the CWEB language. CWEB mode refers to how Leo tangles an outline when ``@language cweb`` is in effect or the ``cweb`` setting is in effect. Leo treats *all* cweb code in cweb mode as unevaluated text. That is, Leo treats cweb control codes, including ``@<...@>``, ``@<..@>=``, ``@c``, ``@``, ``@*`` and ``@**`` as "raw" text within cweb mode. Leo does *not* expand *cweb* section references when writing derived files in cweb mode. However, Leo *does* expand *noweb* section references, so you may use noweb sections to organize cweb files! You can create *noweb* code and doc sections using the ``@code`` and ``@doc`` directives in place of ``@c`` and ``@`` directives.

By default, cweb colors ``@``, ``@*`` and ``@**`` sections using the same syntax coloring as for ``LaTeX``. In addition, cweb colors ``C`` ``//`` and ``/*..*/`` comments using ``LaTeX`` coloring by default. You may change these defaults using the ``color_cweb_doc_parts_with_latex`` and ``color_cweb_comments_with_latex`` settings.
This section discusses all aspects of ``@root`` trees. You should carefully consider whether the extra flexibility afforded by ``@root`` trees is worth the extra bother. Indeed, ``@file`` trees are much easier to use than ``@root`` trees:

- ``@file`` trees use less markup than ``@root`` trees. In particular, the @others directive is valid only within ``@file`` trees.

- You must explicitly tangle and untangle ``@root`` trees using the ``Tangle`` and ``Untangle`` commands.

However, ``@root`` trees are more flexible than ``@file`` trees:

- Sections may be defined anywhere within ``@root`` trees. Moreover, the ``@unit`` directive expands the scope of section definitions in ``@root`` trees so that a section may be referenced in several ``@root`` trees.

- The meaning of section definitions in ``@root`` trees are independent of their position within the tree.
Just as with ``@file`` trees, ``@root`` trees may contain code parts and doc parts. Code parts start with section definition lines (see below) or the ``@c`` directive. Doc parts start with ``@`` directive. Doc parts continue until the end of body text or until the next ``@c`` or ``@`` directive.

Body text in ``@root`` trees contain zero or more code and doc parts in any order. The ``@c`` directive starts a named code section if the node's headline starts with ``<<section name>>``. Otherwise, the ``@c`` directive is invalid.

**Section definition lines** are lines of the form::

<< section name>>=

(note the equal sign). Such lines also start named code parts. Named code parts in ``@root`` trees may be defined in several places. The definition of a named code part is the concatenation of all code parts with the same name. Body text that defines no code part is ignored. At least one non-blank line must follow the section definition line; empty sections are not allowed.

As in ``@file`` trees, paired ``<<`` and ``>>`` characters on the same line always denote a section name, even within comments and strings. Thus, ``<<`` and ``>>`` characters that do not delimit a section name must be placed on separate lines. If ``<<`` and ``>>`` are not paired on a line, they are treated as ordinary ``<<`` and ``>>`` characters.

Here is a typical example of body text within an @root tree::

@ This method puts an open node sentinel for node v. <<atFile methods>>= def putOpenNodeSentinel(self,v): if v.isAtFileNode() and v != self.root: << issue an error message >> else: s = self.nodeSentinelText(v) self.putSentinel("@+node:" + s)

Provided that the node's headline starts with <<atFile methods>>, the example above is equivalent to::

@ This method puts an open node sentinel for node v. @c def putOpenNodeSentinel(self,v): if v.isAtFileNode() and v != self.root: << issue an error message >> else: s = self.nodeSentinelText(v) self.putSentinel("@+node:" + s)

We may not eliminate @c directives in @root trees. If we convert the doc part to a comment we are left with::

@c # This method puts an open node sentinel for node v. def putOpenNodeSentinel(self,v): if v.isAtFileNode() and v != self.root: << issue an error message >> else: s = self.nodeSentinelText(v) self.putSentinel("@+node:" + s)

The following escape convention applies only in ``@root`` trees. Within a code part ``@@`` in the first column (and only in the first column) stands for a single ``@`` sign.
Each ``@root`` tree represents a single derived file. **Tangling** is the process of creating derived files from ``@file`` or ``@root`` trees. Leo tangles ``@file`` trees automatically whenever an outline is saved. The user must tangle ``@root`` trees explicitly using one of the ``Tangle`` commands.

Leo creates derived files by expanding all section references in an ``@root`` node. Leo expands a section reference by substituting the code section itself for the section reference. This is a recursive process: the substituted code section may contain other code references which are themselves expanded, and so on.

The outline provides a natural way of organizing an sections as follows::

Place the definition of a section S in a child of the node containing the reference to S.

If a section is referenced in more than one node, I usually place its definition in a node containing all the nodes that refer to it. Using this rule of thumb creates an outline whose structure mirrors the intrinsic organization of a program.

The ``Tangle`` command creates derived files from ``@root`` node. The ``@root`` directive indicates which sections constitute an output file. The text following a @root directive forms the entire content of the file, that is, after section references are expanded. An outline can contain arbitrarily many ``@root`` directives: Leo's ``Tangle`` commands will create one output file for each. The process of creating derived files is called "tangling" because the code from the outline is rearranged to create the derived files.

For example, the following ``@root`` section shows a typical way of specifying a header file ``xx.h``::

@root xx.h #ifndef xx_defined #define xx_defined << declarations of public constants of the xx class >> << declarations of public types of the xx class >> << declarations of public variables of the xx class >> << public prototypes of the xx class >> #endif

The ``Tangle`` commands will create the file ``xx.h`` from this body text by expanding all the section references. Incidentally, the introductory documentation will be included in the header file: any text preceding the ``@root`` directive is treated just like the doc part of a section definition.

As another example, the following shows a typical way of specifying the corresponding ``xx.c`` file::

@root xx.c << public variables of the xx class >> << private types of the xx class >> << private variables of the xx class >> << private function prototypes of the xx class >> << methods of the xx class >>

There are three menu commands that tangle an outline: ``Tangle``, ``Tangle All`` and ``Tangle Marked``. These commands are identical except for how much of the outline is tangled. The ``Tangle`` command tangles only the selected portion of the outline, the ``Tangle All`` command tangles the entire outline, and the ``Tangle Marked`` command tangles only marked headlines.

The ``@root`` directive has three forms. All three forms mean exactly the same thing::

@root filename @root "filename" @root <filename>

If *filename* is an absolute filename the location of the derived file is specified only by the filename. Otherwise, if the ``@root`` node contains a relative filename, the location of the derived file is relative to:

1. the directory specified by an ``@path`` directive, or

2. the ``default_tangle_directory`` setting if no ``@path`` directive is in effect, or

3. the directory in which the .leo resides if the .leo file has ever been saved.

An error occurs if no absolute path can be computed according to these rules, or if the filename or directory does not exist.

The scope of a definition is the tree in which the definition is known. By default, ``Tangle`` commands look for section definitions only in the suboutline of the ``@root`` node being tangled. That is, all sections are assumed to be defined either in the body text of the headline, say h, containing the ``@root`` directive, or in the body texts of the descendants of h. The ``@unit`` directive explicitly indicates the scope of section definitions. When a ``Tangle`` command encounters the ``@unit`` directive it treats the suboutline containing the ``@unit`` command as the scope for all enclosed roots. This ensures that the group of roots in the subtree use the same section definitions.

For example, suppose we have a tree organized as follows::

+ @unit + @root A sections in A + @root B sections in B

The ``@unit`` directive insures that only sections defined in the unit can affect files A and B and that all sections definitions in A and B are compatible with each other.

The ``Tangle`` commands ignore any tree containing an ``@ignore`` directive. This ensures that trees that contain cloned nodes or other subsidiary information do not cause the tangle commands to issue spurious error messages. It also ensures that a tree can never contribute a section definition to another part of the outline by mistake.
The ``Untangle``, ``Untangle All`` and ``Untangle Marked`` commands are the reverse of the corresponding ``Tangle`` commands. They update one or more ``@root`` nodes based on changes made to the corresponding derived files.

For example, suppose you create a new part of the outline and tangle it for the first time. When you compile derived files for the first you are likely to get many syntax errors. You could fix those errors in the outline and tangle the outline again, but there is a much easier way: you fix the errors in the derived files using the compiler's editor, then run the untangle command on the part of the outline that created the derived file. The ``Untangle`` command updates the selected outline to match the changes in the derived files. It's as simple as that. By the way, the ``Untangle`` command marks all the nodes in the outline that it updates, and you can examine all such nodes with the ``Go To Next Marked`` command in the ``Outline`` menu.

You cannot use ``Untangle`` to update doc parts, or leading comments in code parts or "trivial" whitespace in code parts. This is a limitation of the ``Untangle`` command that cannot be fixed; ``Untangle`` has no way of knowing whether leading comments came from doc parts or are just leading comments.

``Untangle`` never changes the structure of an outline; it never inserts, deletes or moves nodes. Don't attempt to change the structure of an outline by modifying derived files; it won't work. Also, never delete, move or alter the sentinel lines in derived files written by the ``Tangle`` command. Such lines start with the comment delimiter followed by a section name.

If you change the section name in a sentinel line ``Untangle`` will not update the code in the outline (with the old name) that generated the renamed section. ``Untangle`` warns about sections that appear in a derived file but not in the outline. ``Untangle`` has no trouble with changed section references in derived files; it is only changed sentinel lines that cause problems.

Cloned nodes that generate code in several files may cause problems for ``Untangle``. If ``Untangle`` is run separately on these derived files, ``Untangle`` will update all cloned nodes each time it is run, so only the code in the last Untangle run will take effect. Therefore, the safe way to update text in cloned nodes is to make the change in the .leo file rather than the derived files.
The ``@verbose``, ``@terse``, ``@quiet`` and ``@silent`` directives determine how the ``Tangle`` command outputs comments in ``@root`` trees. Comments written by the user in code sections are always output. These directives control only: a) the comments containing doc sections and b) sentinel comments that delimit the beginning and end of code sections.

When ``@verbose`` is in effect ``Tangle`` outputs all comments. When ``@terse`` is in effect, ``Tangle`` outputs only those comments necessary for ``Untangle`` to work. When ``@silent`` is in effect Tangle adds no additional comments. The ``@quiet`` directive is like @silent except that it does output leading sentinels as comments. Like ``@silent``, ``@quiet`` inhibits untangling. ``@verbose`` is the default. If more than one of these directives appear in the same body text the "most verbose" of these options will be in effect.
In most respects ``@thin`` works just like ``@file``. In fact, you can convert from ``@file`` to ``@thin`` simply by opening an outline, changing ``@file`` to ``@thin``, and saving the outline.

Here are the differences between ``@file`` and ``@thin``:

- Leo does not save the information contained in the ``@thin`` tree in the .leo file.

- Files derived from ``@thin`` ("thin" derived files) contain all information needed to recreate the ``@thin`` tree in the outline. In particular, ``@+node`` and ``@-node`` sentinels use timestamps to uniquely identify nodes.

- The ``@all`` directive is valid only in ``@thin`` trees.

- Thin derived files are much more friendly to cvs than files derived from ``@file`` trees. Developers only need to commit thin derived files to cvs.

The cvs repository contains **reference** .leo files. These reference files should containing nothing but ``@thin`` nodes. Reference files will change only when new derived files get added to the project.

Developers will use local copies of reference files for their own work. For example, instead of using LeoPyRef.leo directly, I use a copy called ``LeoPy.leo``. My local copy can contain nodes other than ``@thin`` nodes.
In the following table all terms in each row are equivalent. The spelling in the first column is preferred:

=========== =============== ================= \@asis \@file-asis \@silent ----------- --------------- ----------------- \@nosent \@file-nosent \@nosentinelsfile ----------- --------------- ----------------- \@noref \@file-noref \@rawfile =========== =============== =================

You can get any combination of sentinels/no sentinels and references/no references using ``@auto``, ``@file``, ``@thin``, ``@nosent``, ``@noref`` and ``@asis`` trees:

+---------+------------+-------------------+ | | | Sections and | | Type | Sentinels? | @others expanded? | +---------+------------+-------------------+ | @asis | no | no | +---------+------------+-------------------+ | @auto | no | no | +---------+------------+-------------------+ | @file | yes | yes | +---------+------------+-------------------+ | @noref | yes | no | +---------+------------+-------------------+ | @nosent | no | yes | +---------+------------+-------------------+ | @root | yes | yes | +---------+------------+-------------------+ | @thin | yes | yes | +---------+------------+-------------------+

Leo can not update the outline from changes made from derived files unless those files contain sentinels. The primary source for ``@nosent`` and ``@asis`` trees are the outlines from which those files were derived.
The ``@others`` directive refers to the body text of all nodes *except* section definition nodes. The ``@others`` directive places the body text of section definition nodes in the derived file in outline order.

An ``@file`` tree may contain more than one ``@others`` directive. ``@others`` directives that descend from other ``@others`` directives refer only to unnamed nodes that descend from them. The ``@others`` directive that occurs highest in the ``@file`` tree refers to all other unnamed nodes.

**Notes**:

- No node may contain more than one ``@others`` directive.

- No section definition node may intervene between an non-section definition node containing body text and an ``@others`` node. In practice this is never a problem.

- The ``@others`` directive is not valid in ``@root`` or ``@unit`` trees.
The ``@ignore`` directive is valid *only* in the root node of ``@file`` trees. The ``@ignore`` directive has several uses:

- In the root node of an ``@file`` tree, ``@ignore`` prevents Leo from writing the derived file.

- In ``@root`` trees, ``@ignore`` excludes the ``@ignore`` tree from the derived file.

- Outside of ``@file`` and ``@root`` trees, ``@ignore`` can be used by scripts.
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`_.
.. _`Front Matter`: frontMatter.html .. _`Preface`: preface.html .. _`What people are saying about Leo`: testimonials.html .. _`FAQ`: FAQ.html .. _`Chapter 1\: Installing Leo`: install.html .. _`Chapter 2\: A Tutorial Introduction to Leo`: intro.html .. _`Chapter 3\: Using Leo's Outlines`: outlines.html .. _`Chapter 4\: Writing Programs in Leo`: directives.html .. _`Chapter 5\: Using Leo's Commands`: commands.html .. _`Chapter 6\: Leo and Literate Programming`: design.html .. _`Chapter 7\: Scripting Leo with Python`: scripting.html .. _`Chapter 8\: Customizing Leo`: customizing.html .. _`Chapter 9\: History of Leo`: history.html .. _`Chapter 10\: Theory of Operation`: theory.html .. _`Chapter 11\: White Papers`: whitepapers.html .. _`Chapter 12\: Plugins`: plugins.html .. _`Chapter 13\: Writing Plugins`: writingPlugins.html .. _`Chapter 14\: Using the Rst3 Plugin`: rstplugin3.html .. _`Chapter 15\: Controlling Syntax Coloring`: coloring.html .. _`Chapter 16\: Debugging with Leo`: debuggers.html .. _`Chapter 17\: Using ZODB with Leo`: zodb.html .. _`Chapter 18\: Leo and Emacs`: emacs.html .. _`Chapter 19\: Embedding Leo with the leoBridge Module`: leoBridge.html .. _`Chapter 20\: Unit testing with Leo`: unitTesting.html .. _`Chapter 21\: ILeo - the IPython bridge`: IPythonBridge.html .. _`Appendices`: appendices.html .. _`Glossary`: glossary.html .. _`What's new in Leo 4.4.7 and 4.4.8`: new-4-4-8.html .. _`What's new in Leo 4.4.6`: new-4-4-6.html .. _`What's new in Leo 4.4.5`: new-4-4-5.html .. _`What's new in Leo 4.4.4`: new-4-4-4.html .. _`What's new in Leo 4.4.3`: new-4-4-3.html .. _`What's new in Leo 4.4.2`: new-4-4-2.html .. _`What's new in Leo 4.4.1`: new-4-4-1.html .. _`What's new in Leo 4.4`: new-4-4.html

.. WARNING: image targets may not have upper case letters!

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: frontMatter.html

.. |blank| image:: Blank.gif
------------------

|back| |leo| |next|
.. External links...

.. _`CWEB`: http://www-cs-faculty.stanford.edu/~knuth/cweb.html .. _`noweb`: http://www.eecs.harvard.edu/~nr/noweb/

.. Relative links...

.. _front: front.html .. _`Leo's tutorial`: intro.html

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: outlines.html

.. |next| image:: arrow_rt.gif :target: commands.html

.. |blank| image:: blank.gif

.. |leo| image:: leo.gif :target: front.html
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.

You can create derived files using seven kinds of directives. Unlike most directives, these directives may only appear in headlines.

The first five, ``@auto``, ``@file-thin``, ``@file``, ``@file-nosent``, ``@file-noref``, ``@file-asis``, are collectively known as ``@file`` trees. The abbreviated forms are most common: ``@thin``, ``@file``, ``@nosent``, ``@noref`` and ``@asis``. There is also a sixth directive: ``@root``.

**Important**: You create the ``@file`` trees by putting ``@thin``, ``@file``, ``@nosent``, ``@noref`` or ``@asis`` (or the long forms) in a *headline*. In contrast, you create ``@root`` trees by putting the ``root`` directive in *body text*. The term 'directive' usually refers to a construct in Leo's body text. In this chapter *I'll stretch the term* to include all 10 ``@file`` forms, as well as the true ``@root`` directive. Here are the six ways of creating derived files:

\@auto Import the derived file when Leo reads an outline. See `@auto`_ for full details.

\@thin Use this unless you have a good reason not to. It is the 'state-of-the-art' in derived files. This form is easy to use and is cvs friendly. Using ``@thin`` reduces the size of .leo files, and saves all essential information in the derived file. ``@all`` directives are valid only in ``@thin`` trees.

\@file This was the old 'state-of-the-art' directive. There is not much reason to use it now, except that its sentinels are more readable than ``@thin`` sentinels. However, ``@file`` is not nearly as cvs friendly as ``@thin``; avoid ``@file`` in cooperative environments.

\@nosent Use this directive only if you absolutely can not tolerate any sentinels in derived files. Without sentinels, Leo can not update ``@nosent`` trees from changes made to the derived files. *Consider using @thin even if you must produce derived files without sentinels*. You can use ``@thin`` for most work, then change ``@thin`` to ``@nosent`` when showing your derived files to the world.

The @bool force_newlines_in_at_nosent_bodies setting controls whether Leo writes a trailing newline if non-empty body text does not end in a newline. The default is True. In effect, the default value of this setting was False in previous versions of Leo.

\@noref This directive produces derived files with minimal sentinels. Section references are not allowed. This is the least often used way of producing derived files. Don't use this unless you are sure you must.

\@asis This directive copies body text verbatim, without even ensuring that newlines terminate each node. Use this directive only when you must have complete control over every character of the derived file.

\@root This directive is the most flexible, and the most difficult to use. **Note**: ``@root`` is a true directive: you put ``@root`` in body text. Historically, this was the first directive that created derived files. It comes closest in spirit to traditional literate programming tools. However, it is seldom necessary to suffer the drawbacks of using ``@root``. It is certainly never necessary when programming in Python. My advice is to avoid using ``@root`` unless you have a compelling reason.

To complicate matters further, you can use `CWEB`_ markup instead of `noweb`_ markup. See the section called `CWEB mode`_ for the details. The choice between CWEB and noweb is independent of the directive is used to create derived files.
The ``@`` directive starts a doc part. Doc parts 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`` is a synonym for ``@``, but ``@`` is preferred.
The ``@c`` directive ends a doc part and begins a code part. ``@code`` is a synonym for ``@c``, but ``@c`` is preferred.

In ``@root`` and ``@unit`` trees, the headline must contain a valid section name.
Leo writes ``@nosent`` trees just as for ``@thin`` trees, but Leo writes no sentinels at all.

The @bool force_newlines_in_at_nosent_bodies setting controls whether Leo writes a trailing newline if non-empty body text does not end in a newline. The default is True. In effect, the default value of this setting was False in previous versions of Leo.
The only difference between ``@asis`` and ``@noref`` trees is that files derived from ``@noref`` contain sentinels while files derived from ``@asis`` do not.

Leo creates files derived from ``@noref`` and ``@asis`` trees by writing the body text of all nodes of the tree in outline order. Leo writes the body text *as is*, without recognizing section definitions, without expanding section references, and without treating directives specially in any way. In particular, Leo copies all directives, including ``@`` or ``@c`` directives, to the derived file as text.

Leo does recognize the ``@ignore`` directive in the *ancestors* of ``@noref`` or ``@asis`` nodes, so you may use the ``@ignore`` directive as usual to prevent Leo from writing ``@noref`` or ``@asis`` trees.

**Notes**:

- When writing ``@noref`` trees, Leo writes only the ``@+leo``, ``@-leo``, ``@+node``, ``@-node``, ``@+body`` and ``@-body`` sentinels.

- Within ``@asis`` trees only, if a headline starts with ``@@``, Leo writes everything in the headline following the ``@@`` just before the corresponding body text.

- Files derived from ``@asis`` trees contain *nothing* not contained in body text (or ``@@`` headlines). In particular, if body text does not end in a newline, the first line from the next node will concatenated to the last line of the preceding node.
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.

**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.
The ``@last`` directive allows you to place lines at the very end of files derived from ``@file`` nodes. The ``@last`` directive is recognized only at the end of body text of ``@file`` nodes. No text may follow ``@last`` directives. More than one ``@last`` directive may exist. For example, here is how a PHP file might be set up::

@first <?php ... @last ?>
The ``@pagewidth`` directive overrides the ``page_width`` setting. The form of the ``@pagewidth`` directive is ``@pagewidth`` *n*, where n is a positive integer that indicates the width of tangled pages in columns. For example::

@pagewidth 100

This setting only affects how Leo reformats doc parts, and how the ``Tangle`` command outputs block comments.

The ``@tabwidth`` directive overrides the ``tab_width`` setting. The form of the ``@tabwidth`` directive is ``@tabwidth`` *n*, where n is a positive integer that indicates the width of tabs in spaces. For example::

@tabwidth -4

Negative values cause Leo to convert tabs to blanks.
Here is a brief summary of each directive:

- **\@** Starts a doc part. ``@doc`` is a deprecated synonym.

- **\@all** Copies *all* descendant nodes to the derived file. Not valid in ``@root`` trees.

- **\@auto** Imports the derived file every time Leo reads the outline. The read-at-auto-nodes and write-at-auto-nodes commands can be used to read and write and @auto nodes.

- **\@c** Starts a code part. ``@code`` is a deprecated synonym.

- **\@color**, **\@nocolor** and **\@killcolor** Control syntax coloring.

- **\@comment** Sets comment delimiters in ``@root`` and ``@unit`` trees.

- **\@delims** Sets comment delimiters in ``@file`` trees.

- **\@encoding** Sets the Unicode encoding used in derived files.

- **\@first** Forces lines to appear before the first sentinel of a derived file.

- **\@ignore** Causes Leo to ignore all or part of a derived file. Works differently in ``@file`` and ``@root`` trees.

- **\@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** Sets 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** Set the path to be appended to filenames.

- **\@raw** and **\@end_raw** Delimit a section of 'raw' text. Not valid in ``@root`` or ``@unit`` trees.

- **\@root**, **\@root-code** and **\@root-code** Start an ``@root`` tree. The last two forms set the starting mode for body text.

- **\@tabwidth** Sets the width of tabs. Negative tab widths cause Leo to convert tabs to spaces.

- **@verbose**, **@terse**, **@quiet** and **@silent** Set the verbosity of sentinels in files derived from ``@root``.

- **\@wrap** and **\@nowrap** Enable or disable line wrapping the Leo's body pane.
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.
Here is a brief summary of each directive:

\@ Starts a doc part. ``@doc`` is a deprecated synonym.

\@all Copies *all* descendant nodes to the derived file. Not valid in ``@root`` trees.

\@c Starts a code part. ``@code`` is a deprecated synonym.

\@color, \@nocolor and \@killcolor Control syntax coloring.

\@comment Sets comment delimiters in ``@root`` and ``@unit`` trees.

\@delims Sets comment delimiters in ``@file`` trees.

\@encoding Sets the Unicode encoding used in derived files.

\@first Forces lines to appear before the first sentinel of a derived file.

\@ignore Causes Leo to ignore all or part of a derived file. In ``@file`` trees, only valid in the actual ``@file`` node itself. May appear anywhere in ``@root`` trees.

\@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 Sets 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 Set the path to be appended to filenames in descendant ``@file`` nodes.

\@raw and \@end_raw Delimits a section of 'raw' text. Not valid in ``@root`` or ``@unit`` trees.

\@root, \@root-code and \@root-code Start an ``@root`` tree. ``@root-code`` and ``root-doc`` specify whether body text starts in code or doc mode by default.

\@tabwidth Sets the width of tabs. Negative tab widths cause Leo to convert tabs to spaces.

\@wrap and \@nowrap Enable or disable line wrapping the Leo's body pane. Only the first ``@wrap`` or ``@nowrap`` directive in a node has any effect.
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = True verbose=True @c

.. August 28, 2005

|back| |leo| |next|

##################################### Chapter 4: Writing Programs in Leo #####################################
.. _front: http://webpages.charter.net/edreamleo/front.html .. _home: http://webpages.charter.net/edreamleo/front.html .. _back: http://webpages.charter.net/edreamleo/outlines.html .. _next: http://webpages.charter.net/edreamleo/commands.html

.. _`CWEB`: http://www-cs-faculty.stanford.edu/~knuth/cweb.html .. _`noweb`: http://www.eecs.harvard.edu/~nr/noweb/

.. |back| image:: arrow_lt.gif :target: back_

.. |next| image:: arrow_rt.gif :target: next_

.. |blank| image:: blank.gif

.. |leo| image:: leo.gif :target: front.html

.. _`Leo's tutorial`: http://webpages.charter.net/edreamleo/intro.html
** Use active verbs!

* Spell check.
This chapter is a *reference guide* to computer programming with Leo. This chapter does *not* teach you how to use Leo: for that you should read `Leo's tutorial`_. This chapter assumes you are thoroughly familiar with the terminology introduced in the tutorial. **Note**: Are you *sure* you want to read this chapter? It contains many details that are no interest to the average user of Leo. I recommend using Leo for two weeks, or longer, before attempting this chapter.

.. contents::
You can create derived files using six kinds of directives. The first five, ``@file-thin``, ``@file``, ``@file-nosent``, ``@file-noref``, ``@file-asis``, are collectively known as ``@file`` trees. The abbreviated forms are most common: ``@thin``, ``@file``, ``@nosent``, ``@noref`` and ``@asis``. There is also a sixth directive: ``@root``.

**Important**: You create the ``@file`` trees by putting ``@thin``, ``@file``, ``@nosent``, ``@noref`` or ``@asis`` (or the long forms) in a *headline*. In contrast, you create ``@root`` trees by putting the ``root`` directive in *body text*. The term 'directive' usually refers to a construct in Leo's body text. In this chapter *I'll stretch the term* to include all 10 ``@file`` forms, as well as the true ``@root`` directive. Here are the six ways of creating derived files:

\@thin Use this unless you have a good reason not to. It is the 'state-of-the-art' in derived files. This form is easy to use and is cvs friendly. Using ``@thin`` reduces the size of .leo files, and saves all essential information in the derived file. ``@all`` directives are valid only in ``@thin`` trees.

\@file This was the old 'state-of-the-art' directive. There is not much reason to use it now, except that its sentinels are more readable than ``@thin`` sentinels. However, ``@file`` is not nearly as cvs friendly as ``@thin``; avoid ``@file`` in cooperative environments.

\@nosent Use this directive only if you absolutely can not tolerate any sentinels in derived files. Without sentinels, Leo can not update ``@nosent`` trees from changes made to the derived files. *Consider using @thin even if you must produce derived files without sentinels*. You can use ``@thin`` for most work, then change ``@thin`` to ``@nosent`` when showing your derived files to the world.

\@noref This directive produces derived files with minimal sentinels. Section references are not allowed. This is the least often used way of producing derived files. Don't use this unless you are sure you must.

\@asis This directive copies body text verbatim, without even ensuring that newlines terminate each node. Use this directive only when you must have complete control over every character of the derived file.

\@root This directive is the most flexible, and the most difficult to use. **Note**: ``@root`` is a true directive: you put ``@root`` in body text. Historically, this was the first directive that created derived files. It comes closest in spirit to traditional literate programming tools. However, it is seldom necessary to suffer the drawbacks of using ``@root``. It is certainly never necessary when programming in Python. My advice is to avoid using ``@root`` unless you have a compelling reason.

To complicate matters further, you can use `CWEB`_ markup instead of `noweb`_ markup. See the section called `CWEB mode`_ for the details. The choice between CWEB and noweb is independent of the directive is used to create derived files.
Here is a brief summary of each directive:

- **\@** Starts a doc part. ``@doc`` is a deprecated synonym.

- **\@all** Copies *all* descendant nodes to the derived file. Not valid in ``@root`` trees.

- **\@c** Starts a code part. ``@code`` is a deprecated synonym.

- **\@color**, **\@nocolor** and **\@killcolor** Control syntax coloring.

- **\@comment** Sets comment delimiters in ``@root`` and ``@unit`` trees.

- **\@delims** Sets comment delimiters in ``@file`` trees.

- **\@encoding** Sets the Unicode encoding used in derived files.

- **\@first** Forces lines to appear before the first sentinel of a derived file.

- **\@ignore** Causes Leo to ignore all or part of a derived file. Works differently in ``@file`` and ``@root`` trees.

- **\@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** Sets 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** Set the path to be appended to filenames.

- **\@raw** and **\@end_raw** Delimit a section of 'raw' text. Not valid in ``@root`` or ``@unit`` trees.

- **\@root**, **\@root-code** and **\@root-code** Start an ``@root`` tree. The last two forms set the starting mode for body text.

- **\@tabwidth** Sets the width of tabs. Negative tab widths cause Leo to convert tabs to spaces.

- **@verbose**, **@terse**, **@quiet** and **@silent** Set the verbosity of sentinels in files derived from ``@root``.

- **\@wrap** and **\@nowrap** Enable or disable line wrapping the Leo's body pane.
Here is a brief summary of each directive:

\@ Starts a doc part. ``@doc`` is a deprecated synonym.

\@all Copies *all* descendant nodes to the derived file. Not valid in ``@root`` trees.

\@c Starts a code part. ``@code`` is a deprecated synonym.

\@color, \@nocolor and \@killcolor Control syntax coloring.

\@comment Sets comment delimiters in ``@root`` and ``@unit`` trees.

\@delims Sets comment delimiters in ``@file`` trees.

\@encoding Sets the Unicode encoding used in derived files.

\@first Forces lines to appear before the first sentinel of a derived file.

\@ignore Causes Leo to ignore all or part of a derived file. In ``@file`` trees, only valid in the actual ``@file`` node itself. May appear anywhere in ``@root`` trees.

\@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 Sets 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 Set the path to be appended to filenames in descendant ``@file`` nodes.

\@raw and \@end_raw Delimits a section of 'raw' text. Not valid in ``@root`` or ``@unit`` trees.

\@root, \@root-code and \@root-code Start an ``@root`` tree. ``@root-code`` and ``root-doc`` specify whether body text starts in code or doc mode by default.

\@tabwidth Sets the width of tabs. Negative tab widths cause Leo to convert tabs to spaces.

\@wrap and \@nowrap Enable or disable line wrapping the Leo's body pane. Only the first ``@wrap`` or ``@nowrap`` directive in a node has any effect.
The following sections give full details about each directive.
The ``@`` directive starts a doc part. Doc parts 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`` is a synonym for ``@``, but ``@`` is preferred.
The ``@all`` directive is valid only in ``@thin`` trees. The ``@all`` directive is similar to ``@others``, but it is less restrictive: it dumps *all* nodes to the derived file, including ``@ignore`` nodes and nodes that in an ``@others`` tree would be considered to be orphan nodes.

The ``@all`` directive is required for files such as ``@thin leoProjects.txt`` in ``LeoPy.leo``. ``leoProjects.txt`` contains so-called project nodes. It doesn't have any meaning as a program file: it is simply a collection of unrelated data. ``@others`` would not work at all: it would complain about lots of orphan nodes.
The ``@c`` directive ends a doc part and begins a code part. ``@code`` is a synonym for ``@c``, but ``@c`` is preferred.
Syntax coloring is on by default in all body text. Leo formats comments and documentation parts in red, directives and C keywords in blue, strings and character constants in gray and all other text in code parts in black. The ``@nocolor`` directive disables syntax coloring for the body text in which it appears. No syntax coloring is done until an ``@color`` directive re-enables syntax coloring.

If a node contains neither the ``@color`` nor the ``@nocolor`` directive it may inherit the syntax coloring attribute from an ancestor. The nearest ancestor that contains exactly one of the ``@color`` or ``@nocolor`` directives will control the syntax coloring. **Ambiguous nodes**, nodes containing both the ``@color`` and ``@nocolor`` directives, never affect the coloring of their offspring.

The ``@killcolor`` directive completely disables the colorizer for that node. The result much faster syntax coloring of large body text. As usual ``@killcolor`` may itself be overridden in descendant nodes. The differences between ``@killcolor`` and ``@nocolor``:

- ``@nocolor`` suppresses coloring only until the next ``@color`` directive.

- ``@killcolor`` overrides ``@nocolor`` and ``@color`` directives. Any node containing @killcolor is unambiguously a ``@killcolor`` node regardless of whether that node also contains ``@color`` or ``@nocolor`` directives.

**Note**: the ``@color``, ``@nocolor`` and ``@killcolor`` directives do not affect the ``Tangle`` commands in any way. In particular, the ``Tangle`` commands will recognize section definitions as usual even after an ``@nocolor`` directive is seen.
**Note**: the ``@comment`` directive is deprecated: you should use the ``@language`` directive whenever possible. However, sometimes using both ``@language`` and ``@comment`` is useful. For this to be effective the ``@comment`` directive should appear after the ``@language`` directive (in outline order).

The ``Untangle`` command will not process an ``@root`` or ``@unit`` node if an ``@comment`` directive is in effect because ``Untangle`` can't be sure of properly parsing a derived file if the language of the derived file isn't known. It might be possible to assume some defaults in this case, but that is not done at present and is not a high priority. By default, the ``Tangle`` commands produces C-language comments. Single-line comments generated during tangling start with ``///``, while documentation parts are surrounded by ``/*`` and ``*/``. The ``@comment`` directive allows you to use ``Tangle`` to produce shell and make files, as well as source code for other programming languages.

The ``@comment`` directive may be followed by zero to three delimiters, separated by whitespace. This directive sets the single-line comment delimiter and the opening and closing block comment delimiters as follows:

====================== ===================================================================== \@comment no args\: restores the defaults to ///, /\* and \*/ ---------------------- --------------------------------------------------------------------- \@comment /// \1 arg\: sets the single-line comment and clears the other delims. ---------------------- --------------------------------------------------------------------- \@comment /\* \*/ \2 args\: sets the block comment delims; clears the single-line delim. ---------------------- --------------------------------------------------------------------- \@comment /// /\* \*/ \3 args\: sets all three delimiters. ====================== =====================================================================

If only one delimiter is given, Leo does not write any documentation parts while tangling. If two delimiters are given, block-style comments are used instead of single-line comments. For example, the ``@comment { }`` directive could be used to tangle Pascal files.

The ``@comment`` directive is only recognized in ``@root``, ``@unit`` or ``@file`` nodes, and the ``@comment`` directive must precede the first section name or ``@code`` directive. An ``@comment`` directive in the body text of an ``@unit`` directive specifies the current global defaults. An ``@comment`` directive in the body text of an ``@root`` directive affects comments generated for one root only. Comments in all other roots are governed by the global defaults.

Leo will convert underscores in the ``@comment`` directives to significant spaces. For example::

@comment REM_

causes the comment delimiter to be "REM " (Note the trailing space).
The ``@delims`` directive changes the comment strings used to mark sentinel lines. This directive is often used to place Javascript text inside XML or HTML files.

The ``@delims`` directive contains one or two delimiters, separated by whitespace. If only one delim is present it delimits single-line comments. If two delims are present they delimit block comments. The ``@delims`` directive can not be used to change the comment strings at the start of the derived file, that is, the comment strings for the ``@+leo`` sentinel and the initial ``@+body`` and ``@+node`` sentinels.

The ``@delims`` directive inserts ``@@delims`` sentinels into the derived file. The new delimiter strings continue in effect until the next ``@@delims`` sentinel in the derived file or the end of the derived file.

**Note**: Leo can not revert to previous delimiters automatically; you must change back to previous delimiters using another ``@delims`` directive. For example::

@delims /* */ Javascript stuff @delims <-- --> HTML stuff

Adding, deleting or changing ``@@delims`` sentinels will destroy Leo's ability to read the derived file. Mistakes using the ``@delims`` directive have no effect on Leo, though such mistakes will thoroughly mess up a derived file as far as compilers, HTML renderers, etc. are concerned.
You may use the ``@encoding`` directive to specify the encoding used in a derived file. You can't mix encodings in a single derived file. For example::

@encoding iso-8859-1

If the encoding used in a derived file is not "utf-8" it is represented in the @+leo sentinel line, like this::

#@+leo-encoding=iso-8859-1.

The ``utf-8`` encoding is used by default. The ``utf-8`` encoding is a "lossless" encoding (it can represent all unicode code points), so encoding and decoding to and from ``utf-8`` plain strings will never cause a problem. When reading or writing a character not in a "lossy" encoding (such as ``iso-8859-1``), Leo converts such characters to ``'?'`` and issues a warning.
The ``@first`` directive allows you to place lines at the very start of files derived from ``@file`` nodes. For example, the body text of ``@file spam.py`` might be::

@first #! /usr/bin/env python

The body text of ``@file foo.perl`` might be::

@first #/usr/bin/perl

``@first`` directives are recognized only at the start of the body text of ``@file`` nodes. No text may precede ``@first`` directives. More than one ``@first`` directive may exist, like this::

@first #! /usr/bin/env python @first # more comments.
The ``@ignore`` directive is valid *only* in the root node of ``@file`` trees. The ``@ignore`` directive has several uses:

- In the root node of an ``@file`` tree, ``@ignore`` prevents Leo from writing the derived file.

- In ``@root`` trees, ``@ignore`` excludes the ``@ignore`` tree from the derived file.

- Outside of ``@file`` and ``@root`` trees, ``@ignore`` can be used by scripts.
The ``@language`` directive specifies the comment delimiters and string types used by the ``Tangle`` and ``Untangle`` commands. This directive over-rides the default specified in the settings dialog. Here are the valid ``@language`` directives::

@language actionscript @language c @language c++ @language cweb @language elisp @language html @language java @language latex @language objective-c @language pascal @language perl @language perlpod @language plain @language python @language rebol @language shell @language tcltk

Shell files have comments that start with `#`. Case is ignored in the language specifiers, but not in the ``@language`` itself. Thus, the following are equivalent::

@language html @language HTML @language hTmL

but the following is invalid::

@LANGUAGE html
The ``@last`` directive allows you to place lines at the very end of files derived from ``@file`` nodes. The ``@last`` directive is recognized only at the end of body text of ``@file`` nodes. No text may follow ``@last`` directives. More than one ``@last`` directive may exist. For example, here is how a PHP file might be set up::

@first <?php ... @last ?>
The ``@lineending`` directive sets the line endings for individual derived files. This directive will override the ``output_newline`` setting. The ``@lineending`` *never* affects the line endings in .leo files themselves: .leo files must have consistent line endings!

The valid forms of the ``@lineending`` directive are:

======================= ====================================================== \@lineending nl The default, Linux. ----------------------- ------------------------------------------------------ \@lineending cr Mac ----------------------- ------------------------------------------------------ \@lineending crlf Windows ----------------------- ------------------------------------------------------ \@lineending lf Same as 'nl', not recommended ----------------------- ------------------------------------------------------ \@lineending platform Same as platform value for ``output_newline`` setting. ======================= ======================================================
The ``@others`` directive refers to the body text of all nodes *except* section definition nodes. The ``@others`` directive places the body text of section definition nodes in the derived file in outline order.

An ``@file`` tree may contain more than one ``@others`` directive. ``@others`` directives that descend from other ``@others`` directives refer only to unnamed nodes that descend from them. The ``@others`` directive that occurs highest in the ``@file`` tree refers to all other unnamed nodes.

**Notes**:

- No node may contain more than one ``@others`` directive.

- No section definition node may intervene between an non-section definition node containing body text and an ``@others`` node. In practice this is never a problem.
The ``@path`` directives override the deprecated ``default_tangle_directory`` setting.

The form of the @path directive is ``@path`` *filename*, where *filename* is taken to be everything following @path to the end of the line.

If *filename* is an absolute filename the location of the derived file is specified only by the filename. Otherwise, if *filename* is a relative filename, the location of the derived file is relative to:

1. the directory specified the applicable ``@path`` directive, or 2. the "Default Tangle Directory" in the Settings dialog if no ``@path`` directive is in effect, or 3. the directory in which the .leo resides if the .leo file has ever been saved.

An error occurs if no absolute path can be computed according to these rules, or if *filename* does not exist.
The ``@pagewidth`` directive overrides the ``page_width`` setting. The form of the ``@pagewidth`` directive is ``@pagewidth`` *n*, where n is a positive integer that indicates the width of tangled pages in columns. For example::

@pagewidth 100

This setting only affects how Leo reformats doc parts, and how the ``Tangle`` command outputs block comments.

The ``@tabwidth`` directive overrides the ``tab_width`` setting. The form of the ``@tabwidth`` directive is ``@tabwidth`` *n*, where n is a positive integer that indicates the width of tabs in spaces. For example::

@tabwidth -4

Negative values cause Leo to convert tabs to blanks.
The ``@raw`` and ``@end_raw`` directives are valid only within ``@file`` trees. The ``@raw`` directive starts a section of "raw" text. The ``@end_raw`` directive ends such a section, as does the end of body text. No section references are recognized within raw text, and no additional leading whitespace is generated within raw text when writing the derived file.
Leo allows you to choose whether body text in ``@root`` trees will start in code mode or doc mode by default. ``@root-doc`` *filename* and ``@root-code`` *filename* directives specify that body text is assumed to start in doc mode or code mode respectively. The options (``-doc`` and ``-code``) must follow ``@root`` immediately with no intervening whitespace. In effect, ``@root-code`` and ``@root-doc`` are two new directives.

These ``@root`` options override the ``at_root_bodies_start_in_doc_mode`` setting. This setting affects only @root trees without options. Such "plain" ``@root`` trees are now deprecated, which only means that it is better style to use either ``@root-code`` or ``@root-doc``. The reason is simple: the meaning of plain ``@root`` trees will depend on the ``at_root_bodies_start_in_doc_mode`` setting. It's better to be explicit. By default, ``at_root_bodies_start_in_doc_mode = 1`` for compatibility for old ``@root`` trees. I actually don't think this option is good for much; I created it before I created ``@root-doc`` and ``@root-code`` settings, and I decided it wouldn't hurt to leave it in. Anyway, you now have complete flexibility about how ``@root`` works, and in particular you can make ``@root`` work just like ``@file``.
The ``@verbose``, ``@terse``, ``@quiet`` and ``@silent`` directives determine how the ``Tangle`` command outputs comments in ``@root`` trees. Comments written by the user in code sections are always output. These directives control only: a) the comments containing doc sections and b) sentinel comments that delimit the beginning and end of code sections.

When ``@verbose`` is in effect ``Tangle`` outputs all comments. When ``@terse`` is in effect, ``Tangle`` outputs only those comments necessary for ``Untangle`` to work. When ``@silent`` is in effect Tangle adds no additional comments. The ``@quiet`` directive is like @silent except that it does output leading sentinels as comments. Like ``@silent``, ``@quiet`` inhibits untangling. ``@verbose`` is the default. If more than one of these directives appear in the same body text the "most verbose" of these options will be in effect.
By default, the ``body_pane_wraps`` setting controls whether body text wraps. You may override this setting for a particular tree using the ``@wrap`` and ``@nowrap`` directives. Only the first ``@wrap`` or ``@nowrap`` directive in a node has any effect.
In the following table all terms in each row are equivalent. The spelling in the first column is preferred:

=========== =============== ================= \@asis \@file-asis \@silent ----------- --------------- ----------------- \@nosent \@file-nosent \@nosentinelsfile ----------- --------------- ----------------- \@noref \@file-noref \@rawfile =========== =============== =================

You can get any combination of sentinels/no sentinels and references/no references using ``@file``, ``@nosent``, ``@noref`` and ``@asis`` trees:

+---------+------------+-------------------+ | | | Sections and | | Type | Sentinels? | @others expanded? | +---------+------------+-------------------+ | @asis | no | no | +---------+------------+-------------------+ | @file | yes | yes | +---------+------------+-------------------+ | @noref | yes | no | +---------+------------+-------------------+ | @nosent | no | yes | +---------+------------+-------------------+

Leo can not update the outline from changes made from derived files unless those files contain sentinels. The primary source for ``@nosent`` and ``@asis`` trees are the outlines from which those files were derived.
In most respects ``@thin`` works just like ``@file``. In fact, you can convert from ``@file`` to ``@thin`` simply by opening an outline, changing ``@file`` to ``@thin``, and saving the outline.

Here are the differences between ``@file`` and ``@thin``:

- Leo does not save the information contained in the ``@thin`` tree in the .leo file.

- Files derived from ``@thin`` ("thin" derived files) contain all information needed to recreate the ``@thin`` tree in the outline. In particular, ``@+node`` and ``@-node`` sentinels use timestamps to uniquely identify nodes.

- The ``@all`` directive is valid only in ``@thin`` trees.

- Thin derived files are much more friendly to cvs than files derived from ``@file`` trees. Developers only need to commit thin derived files to cvs.

The cvs repository contains **reference** .leo files. These reference files should containing nothing but ``@thin`` nodes. Reference files will change only when new derived files get added to the project.

Developers will use local copies of reference files for their own work. For example, instead of using LeoPyRef.leo directly, I use a copy called ``LeoPy.leo``. My local copy can contain nodes other than ``@thin`` nodes.
Leo writes ``@nosent`` trees just as for ``@thin`` trees, but Leo writes no sentinels at all.
The only difference between ``@asis`` and ``@noref`` trees is that files derived from ``@noref`` contain sentinels while files derived from ``@asis`` do not.

Leo creates files derived from ``@noref`` and ``@asis`` trees by writing the body text of all nodes of the tree in outline order. Leo writes the body text *as is*, without recognizing section definitions, without expanding section references, and without treating directives specially in any way. In particular, Leo copies all directives, including ``@`` or ``@c`` directives, to the derived file as text.

Leo does recognize the ``@ignore`` directive in the *ancestors* of ``@noref`` or ``@asis`` nodes, so you may use the ``@ignore`` directive as usual to prevent Leo from writing ``@noref`` or ``@asis`` trees.

**Notes**:

- When writing ``@noref`` trees, Leo writes only the ``@+leo``, ``@-leo``, ``@+node``, ``@-node``, ``@+body`` and ``@-body`` sentinels.

- Within ``@asis`` trees only, if a headline starts with ``@@``, Leo writes everything in the headline following the ``@@`` just before the corresponding body text.

- Files derived from ``@asis`` trees contain *nothing* not contained in body text (or ``@@`` headlines). In particular, if body text does not end in a newline, the first line from the next node will concatenated to the last line of the preceding node.
This section discusses all aspects of ``@root`` trees. You should carefully consider whether the extra flexibility afforded by ``@root`` trees is worth the extra bother. Indeed, ``@file`` trees are much easier to use than ``@root`` trees:

- ``@file`` trees use less markup than ``@root`` trees. In particular, the @others directive is valid only within ``@file`` trees.

- You must explicitly tangle and untangle ``@root`` trees using the ``Tangle`` and ``Untangle`` commands.

However, ``@root`` trees are more flexible than ``@file`` trees:

- Sections may be defined anywhere within ``@root`` trees. Moreover, the ``@unit`` directive expands the scope of section definitions in ``@root`` trees so that a section may be referenced in several ``@root`` trees.

- The meaning of section definitions in ``@root`` trees are independent of their position within the tree.
Just as with ``@file`` trees, ``@root`` trees may contain code parts and doc parts. Code parts start with section definition lines (see below) or the ``@c`` directive. Doc parts start with ``@`` directive. Doc parts continue until the end of body text or until the next ``@c`` or ``@`` directive.

Body text in ``@root`` trees contain zero or more code and doc parts in any order. The ``@c`` directive starts a named code section if the node's headline starts with::

<< section name >>

Otherwise, the ``@c`` directive is invalid.

**Section definition lines** are lines of the form::

<< section name >>=

(note the equal sign). Such lines also start named code parts. Named code parts in ``@root`` trees may be defined in several places. The definition of a named code part is the concatenation of all code parts with the same name. Body text that defines no code part is ignored. At least one non-blank line must follow the section definition line; empty sections are not allowed.

**Note for pdf version**: due to a bug in docutils the phrase 'double-angle-bracket characters' below stands for::

<< and >>

As in ``@file`` trees, paired double-angle-bracket characters on the same line always denote a section name, even within comments are strings. Thus,double-angle-bracket characters that do not delimit a section name must be placed on separate lines. If double-angle-bracket are not paired on a line, they are treated as ordinary double-angle-bracket characters.

Here is a typical example of body text within an @root tree::

@ This method puts an open node sentinel for node v. <<atFile methods>>= def putOpenNodeSentinel(self,v): if v.isAtFileNode() and v != self.root: << issue an error message >> else: s = self.nodeSentinelText(v) self.putSentinel("@+node:" + s)

Provided that the node's headline starts with::

<< atFile methods >>

the example above is equivalent to::

@ This method puts an open node sentinel for node v. @c def putOpenNodeSentinel(self,v): if v.isAtFileNode() and v != self.root: << issue an error message >> else: s = self.nodeSentinelText(v) self.putSentinel("@+node:" + s)

We may not eliminate @c directives in @root trees. If we convert the doc part to a comment we are left with::

@c # This method puts an open node sentinel for node v. def putOpenNodeSentinel(self,v): if v.isAtFileNode() and v != self.root: << issue an error message >> else: s = self.nodeSentinelText(v) self.putSentinel("@+node:" + s)

The following escape convention applies only in ``@root`` trees. Within a code parts ``@@`` in the first column (and only in the first column) stands for a single ``@`` sign.
Each ``@root`` tree represents a single derived file. **Tangling** is the process of creating derived files from ``@file`` or ``@root`` trees. Leo tangles ``@file`` trees automatically whenever an outline is saved. The user must tangle ``@root`` trees explicitly using one of the ``Tangle`` commands.

Leo creates derived files by expanding all section references in an ``@root`` node. Leo expands a section reference by substituting the code section itself for the section reference. This is a recursive process: the substituted code section may contain other code references which are themselves expanded, and so on.

It is unusual and bad style for the meaning of an ``@root`` tree to depend on the position of nodes within it. The meaning of a section definition in an ``@root`` tree usually does not depend on is position, and we may place sections wherever we want. The outline provides a natural way of organizing an sections as follows::

Place the definition of a section S in a child of the node containing the reference to S.

If a section is referenced in more than one node, I usually place its definition in a node containing all the nodes that refer to it. Using this rule of thumb creates an outline whose structure mirrors the intrinsic organization of a program.

The ``Tangle`` command creates derived files from ``@root`` node. The ``@root`` directive indicates which sections constitute an output file. The text following a @root directive forms the entire content of the file, that is, after section references are expanded. An outline can contain arbitrarily many ``@root`` directives: Leo's ``Tangle`` commands will create one output file for each. The process of creating derived files is called "tangling" because the code from the outline is rearrange to create the derived files.

For example, the following ``@root`` section shows a typical way of specifying a header file ``xx.h``::

@root xx.h #ifndef xx_defined #define xx_defined << declarations of public constants of the xx class >> << declarations of public types of the xx class >> << declarations of public variables of the xx class >> << public prototypes of the xx class >> #endif

The ``Tangle`` commands will create the file ``xx.h`` from this body text by expanding all the section references. Incidentally, the introductory documentation will be included in the header file: any text preceding the ``@root`` directive is treated just like the documentation part of an section definition.

As another example, the following shows a typical way of specifying the corresponding ``xx.c`` file::

@root xx.c << public variables of the xx class >> << private types of the xx class >> << private variables of the xx class >> << private function prototypes of the xx class >> << methods of the xx class >>

There are three menu commands that tangle an outline: ``Tangle``, ``Tangle All`` and ``Tangle Marked``. These commands are identical except for how much of the outline is tangled. The ``Tangle`` command tangles only the selected portion of the outline, the ``Tangle All`` command tangles the entire outline, and the ``Tangle Marked`` command tangles only marked headlines.

The ``@root`` directive has three forms. All three forms mean exactly the same thing::

@root filename @root "filename" @root <filename>

If *filename* is an absolute filename the location of the derived file is specified only by the filename. Otherwise, if the ``@root`` node contains a relative filename, the location of the derived file is relative to:

1. the directory specified by an ``@path`` directive, or

2. the ``default_tangle_directory`` setting if no ``@path`` directive is in effect, or

3. the directory in which the .leo resides if the .leo file has ever been saved.

An error occurs if no absolute path can be computed according to these rules, or if the filename or directory does not exist.

The scope of a definition is the tree in which the definition is known. By default, ``Tangle`` commands look for section definitions only in the suboutline of the ``@root`` node being tangled. That is, all sections are assumed to be defined either in the body text of the headline, say h, containing the ``@root`` directive, or in the body texts of the descendants of h. The ``@unit`` directive explicitly indicates the scope of section definitions. When a ``Tangle`` command encounters the ``@unit`` directive it treats the suboutline containing the ``@unit`` command as the scope for all enclosed roots. This ensures that the group of roots in the subtree use the same section definitions.

For example, suppose we have a tree organized as follows::

+ @unit + @root A sections in A + @root B sections in B

The ``@unit`` directive insures that only sections defined in the unit can effect files A and B and that all sections definitions in A and B are compatible with each other.

The ``Tangle`` commands ignore any tree containing an ``@ignore`` directive. This ensures that trees that contain cloned nodes or other subsidiary information do not cause the tangle commands to issue spurious error messages. It also ensures that a tree can never contribute a section definition to another part of the outline by mistake.
The ``Untangle``, ``Untangle All`` and ``Untangle Marked`` commands are the reverse of the corresponding ``Tangle`` commands. They update one or more ``@root`` nodes based on changes made to the corresponding derived files.

For example, suppose you create a new part of the outline and tangle it for the first time. When you compile derived files for the first you are likely to get many syntax errors. You could fix those errors in the outline and tangle the outline again, but there is a much easier way: you fix the errors in the derived files using the compiler's editor, then run the untangle command on the part of the outline that created the derived file. The ``Untangle`` command updates the selected outline to match the changes in the derived files. It's as simple as that. By the way, the ``Untangle`` command marks all the nodes in the outline that it updates, and you can examine all such nodes with the ``Go To Next Marked`` command in the ``Outline`` menu.

You cannot use ``Untangle`` to update doc parts, or leading comments in code parts or "trivial" whitespace in code parts. This is a limitation of the ``Untangle`` command that cannot be fixed; ``Untangle`` has no way of knowing whether leading comments came from doc parts or are just leading comments.

``Untangle`` never changes the structure of an outline; it never inserts, deletes or moves nodes. Don't attempt to change the structure of an outline by modifying derived files; it won't work. Also, never delete, move or alter the sentinel lines in derived files written by the ``Tangle`` command. Such lines start with the comment delimiter followed by a section name.

If you change the section name in a sentinel line ``Untangle`` will not update the code in the outline (with the old name) that generated the renamed section. ``Untangle`` warns about sections that appear in a derived file but not in the outline. ``Untangle`` has no trouble with changed section references in derived files; it is only changed sentinel lines that cause problems.

Cloned nodes that generate code in several files may cause problems for ``Untangle``. If ``Untangle`` is run separately on these derived files, ``Untangle`` will update all cloned nodes each time it is run, so only the code in the last Untangle run will take effect. Therefore, the safe way to update text in cloned nodes is to make the change in the .leo file rather than the derived files.
Cweb mode refers to how Leo tangles an outline when ``@language cweb`` is in effect or the ``cweb`` setting is in effect. Leo treats *all* cweb code in cweb mode as unevaluated text. That is, Leo treats cweb control codes, including::

@<...@> @<..@>= @c @ @* @

as "raw" text within cweb mode.

Leo does *not* expand *cweb* section references when writing derived files in cweb mode. However, Leo *does* expand *noweb* section references, so you may use noweb sections to organize cweb files! You can create *noweb* code and doc sections using the ``@code`` and ``@doc`` directives in place of ``@c`` and ``@`` directives.

By default, cweb colors ``@``, ``@*`` and ``@**`` sections using the same syntax coloring as for ``LaTeX``. In addition, cweb colors ``C`` ``//`` and ``/*..*/`` comments using ``LaTeX`` coloring by default. You may change these defaults using the ``color_cweb_doc_parts_with_latex`` and ``color_cweb_comments_with_latex`` settings.
------------------

|back| |leo| |next|
Cweb mode refers to how Leo tangles an outline when ``@language cweb`` is in effect or the ``cweb`` setting is in effect. Leo treats *all* cweb code in cweb mode as unevaluated text. That is, Leo treats cweb control codes, including: ``@<...@>``, ``@<..@>=``, ``@c``, ``@``, ``@*`` and ``@**`` as "raw" text within cweb mode. Leo does *not* expand *cweb* section references when writing derived files in cweb mode. However, Leo *does* expand *noweb* section references, so you may use noweb sections to organize cweb files! You can create *noweb* code and doc sections using the ``@code`` and ``@doc`` directives in place of ``@c`` and ``@`` directives.

By default, cweb colors ``@``, ``@*`` and ``@**`` sections using the same syntax coloring as for ``LaTeX``. In addition, cweb colors ``C`` ``//`` and ``/*..*/`` comments using ``LaTeX`` coloring by default. You may change these defaults using the ``color_cweb_doc_parts_with_latex`` and ``color_cweb_comments_with_latex`` settings.
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|prev| |leo| |next|

################################### What People Are Saying About Leo ###################################

.. contents::
"I am using Leo since a few weeks and I brim over with enthusiasm for it. I think it is the most amazing software since the invention of the spreadsheet."

"We who use Leo know that it is a breakthrough tool and a whole new way of writing code." -- Joe Orr

"I am a huge fan of Leo. I think it's quite possibly the most revolutionary programming tool I have ever used and it (along with the Python language) has utterly changed my view of programming (indeed of writing) forever." -- Shakeeb Alireza

"Thank you very much for Leo. I think my way of working with data will change forever... I am certain [Leo] will be a revolution. The revolution is as important as the change from sequential linear organization of a book into a web-like hyperlinked pages. The main concept that impress me is that the source listing isn't the main focus any more. You focus on the non-linear, hierarchical, collapsible outline of the source code." -- Korakot Chaovavanich

"Leo is a quantum leap for me in terms of how many projects I can manage and how much information I can find and organize and store in a useful way." -- Dan Winkler

"Wow, wow, and wow...I finally understand how to use clones and I realized that this is exactly how I want to organize my information. Multiple views on my data, fully interlinkable just like my thoughts." -- Anon

"Edward... you've come up with perhaps the most powerful new concept in code manipulation since VI and Emacs. -- David McNab

"Leo is...a revolutionary step in the right direction for programming." -- Brian Takita
"Thanks for a wonderful program – everybody should be using it! It blows the socks off that Java Mind mapping software that won project of the month a while back on sourceforge!" -- Derick van Niekerk.

"A few years back I would have said Zope was #1 Python showcase, but I agree 100% that Leo is tops now." -- Jason Cunliffe

"Leo is the most interesting Python project I know of...I see lots of stuff posted on the Daily Python page, but I usually yawn and come over to this forum to see what's cooking." -- Anon

"Leo is the best Tkinter application ever written. It convinces me that Tkinter can really *do something*, and do [it] well." - Anon

"What an original synthesis of different ideas, why can't other Open Source projects change the way I think?" -- Anon
"When first I opened Leo, it was out of curiosity. But having used it...I'll never go back. They'll have to pry Leo out of my cold, dead fingers! Seriously, it should be renamed 'Crack Cocaine' because it's that addictive. I'm ready to start a 12-Step group." -- Travers A. Hough

"I feel addicted to programming again...in fact [Leo] has resurrected a dead project of mine :) The Outline has proven most liberating in terms of testing ideas out." -- Anon

"I have been absolutely seduced by Leo over the past few days. I tell you, I can not put it down. I feel like a kid with a shiny new bike...I'm already bursting with new ways I'd like to use the tool in the future." -- Lyn Adams Headley

Thanks for the great work--I love Leo!!! -- Josef Dalcolmo

Leo has simplified updating and creating new scripts and .bats keeping similar information in the same place. there is almost an addictive withdrawal effect when I can complete an operation in so much less time with Leo & python than I had become used to. -- Anon
"[Leo] should either replace or greatly augment the development tools that I use." -- Zak Greant

"Leo is a marriage of outlining and literate programming. Pure genius. The main reason I am impressed with this tool is that it doesn't affect your choice of tools. You can use whatever IDE for whatever language and switch back and forth between Leo and it." -- Austin King

"Leo is the best IDE that I have had the pleasure to use. I have been using it now for about 2--3 months. It has totally changed not only the way that I program, but also the way that I store and organize all of the information that I need for the job that I do." -- Ian Mulvany

"I only have one week of Leo experience but I already know it will be my default IDE/project manager...people complain about the lack of a project manager for the free/standard Python IDE's like Idle. Leo clearly solves that problem and in a way that commercial tools can't touch." -- Marshall Parsons

"I have been using Leo for about 3 weeks and I hardly use my other programming editor anymore...I find it easy and enjoyable to use. I plan to adopt it as my presentation tool for code reviews." -- Jim Vickroy

"I'm absolutely astounded by the power of such a simple idea! It works great and I can immediately see the benefits of using Leo in place of the standard flat file editor." -- Tom Lee

I think you're really showing what open source can do and your current trajectory puts you on track to kick Emacs into the dustbin of computing history. -- Dan Winkler
"Word outlines are very useful. But Leo makes Word look like a clunky toy." --Joe Orr

"Leo is an interactive editor for organizing text fragments hierarchically and sequentially into one or more files and hierarchical folders, without arbitrary limits on the number and size of text fragments and the depth of the hierarchy...Tangle is a tool for combining hierarchically and sequentially organized text fragments into text files, hierarchically grouped into folders, with hierarchical or sequential organization of text within the files, and without arbitrary limits on the size and number of files and the depth of the hierarchy of folders and text nesting within the files." -- Alex Abacus

"Leo reminds me a great deal of things I loved when I used Userland's Frontier (an outlining cms with a native oodb) - but Frontier wasn't hackable enough for me, and it wasn't oriented towards coding and literate programming, and you couldn't round-trip rendered pages (big Leo win). This is really a super tool - in a matter of days I've started to use it on all my projects and I still haven't figured out how I lived without it." -- John Sequeira

"Leo is EXACTLY the kind of outliner I was looking for--fantastic job!" -- Steve Allen

"If you are like me, you have a kind of knowledge base with infos gathered over time. And you have projects, where you use some of those infos. Now, with conventional outliners you begin to double these infos, because you want to have the infos needed for the project with your project. With Leo you can do this too, but if you change text in one place IT IS UPDATED IN THE OTHER PLACE TOO! This is a feature I did not see with any other outliner (and I tried a few). Amazing! Leo directly supports the way I work!" -- F. Geiger
"Another day, another breakthrough using Leo--now I realize Leo is the best URL bookmark manager there is. No more bookmarks menus or favorites lists inside the browser for me. With the @url directive I can just double click on the URL to open it in my browser. Leo lets me arrange the URLs in a hierarchy (or multiple hierarchies), attach notes to them, save clippings of things I read on the sites. It's sooo much better than anything the browsers have built in and it lets me easily use different browsers on different platforms and different machines (try that with the browsers' built-in bookmark managers)." -- Dan Winkler

"I am an amateur photographer. I use plain old 35mm. film for my pictures. Over the weekend, I used Leo to organize my lists of pictures. It is quite helpful--I can have separate nodes for pictures I have enlarged, as well as pictures I have submitted to our local camera club. Thanks!" -- Rich Reis

"Cloning is pure genius!... Leo's cloning facility, allows me to create several views on the CFA course material. My main view follows the prescribed study guide. Another view is organized like the textbooks. Yet another gives me a glossary of terms. And when I'm done, I'll have some nice libraries...I can re-use later in other projects." -- Michael Manti
"I've tried Literate Programming tools off and on for more than 10 years, mainly because the promise was so great. I've abandoned them every time because working with the various Cweb-like tools was so awkward. Leo changes all that. The most important benefits promised by Literate Programming are realized by using Leo, without the awkwardness of the other tools." -- Dave Hein

"[Leo] has enabled me to use Literate Programming in production for the first time. When I figured out I could do it in plain text and export to DocBook for automated typesetting, I was on my way. Because I only do business and utility software, I don't need the sophistication of LaTeX markup. Writing the documentation and the code in the same outline at the same time improves the whole product. Being able to automatically export both with just two key presses (tangle and export-to-DocBook) is a real luxury." -- Michael Dawson

I wanted to thank you for the effort you've put into Leo. It looks fantastic. I've always though that Literate Programming was a good idea, but the tools were completely un-workable. -- Bob Hustead
"I've written documentation in WordPerfert, Ventura, Word, PageMaker, and FrameMaker and even though they create wonderfully looking and useful documents, they've never been able to do what I've been looking for. HTML, compiled help files, and later PDF came closer, but still not there...I think I've found it in LEO, a way to make a "living" document. A document built out of discrete parts that can be re-organized on the fly to meet the needs of a varying audience...I've already started converting the IT Procedures manual from Open Office to LEO because I know it's going to be much more useful to me and anyone else...just the possibility of keeping system maintenance scripts in the IT manual is mind boggling." -- David Nichols

"With the help of the rst2 plugin, [Leo is] the best outliner I have yet encountered for writing the early stages of academic papers."

"A Leo file is an ideal documentation tool, collecting the assorted readme.txt files, the comments from the source files...as well as the config files themselves." -- Kent Tenney
"Just as structured programming reveals and disciplines the flow control of a program, [Leo] allows the designer to reveal and discipline structure at many layers simultaneously: data structures, object structure, entity-relationship structure, client-server structure, design pattern structure, temporal structure, project management structure, and any other structure relevant to the system." -- Steven P. Schaefer

"A funny observation with Leo is that when I 'Leo-ise' other people's code, Leo makes the code's structure so transparent that design faults become very quickly apparent. For example, maintenance pain caused by lack of factorization." -- David McNab

"Leo is a powerful tool for organizing text into tree structures, and for just generally attacking a number of problems from a tree-based perspective." -- Joe Orr

"I found this blog entry by someone (a talented former coworker of mine actually) complaining about some poorly written code she had to maintain: http://snippy.ceejbot.com/wiki/show/start/2003/01/29/001 She said: 'You'd need a bulldozer to start refactoring it.' That was my cue to write a long message explaining that there is indeed such a bulldozer and it's called Leo. (You can see my message there as a reply to her original posting.) I gave her my recipe for how to get someone else's messy, scary code into Leo and how to break it down into manageable chunks." -- Dan Winkler

"Ed, you continue to push the envelope. The amazing thing is that the footprint isn't doubling every few months like it would be in another designer's hands. Adding features by removing constraints, hot refactoring while adding unit tests. Forget the book. I would pay to see the movie."
"I am extremely impressed at how stable and useful Leo appears to be." -- Marcus A. Martin

"Leo is amazingly stable. Docs are often weak with Open Source Software. Not so Leo: Leo is unusually well documented." -- F. Geiger

"Leo is unimaginably useful and I always find new things it already knows(!) how to do. Indeed I am amazed by the never-ending resources and patience Edward is putting into it and its users community. Excellent." -- Gil Shwartz

"I feel strongly that Ed Ream, our ever-patient, ever-productive Leo architect deserves a nomination [ for the ActiveState OpenSource Award] Among other reasons, for:

- Delivering the first usable visual literate programming tool. - Adding a vast abundance of new features. - Making possible a previously unimaginable amount of leverage in code editing. - Eliminating vast amounts of menial programming labour. - Tirelessly and patiently supporting users, and catering to a wide range of feature requests." -- David McNab
September 3, 2002

Hello, my full name is David Speed Ream. I am known as Speed to friends and enemies alike, but I gladly answer to David or most any other handle. I am an unabashed and biased fan of Leo, the fact that it was written by my brother Edward only slightly coloring my already colored glasses. I have been testing and using Leo in software production for over 4 years. My company currently has over 50,000 lines of code in over 100 source files that are written using Leo.

My comments are from two points of view, the first being software project manager for a complicated, multi-module software product, and the second being as a production line coder. For me, Leo’s greatest and only real drawback is the learning curve. This learning curve can be shallow is if all that is required is that someone code using Leo. However, in our company we allocate 40 to 80 hours *on top* of the normal coding load for someone to come up to speed on Leo. The ROI (return on investment) is calculated by me to be on the order of 3 months. So if I hire a consultant for less than 3 months, I don’t teach him Leo, even though all source code in our company must reside in Leo files for the reasons I won’t go into now.

I consider that my coders are 15 to 30 percent more efficient in their daily operations than my competition’s people. This indefensible claim of mine is based on the changes in my productivity as Leo grew from a test document production tool to the primary production method for all our assembly, c and cpp source code.

Personally, I hate to deal with documentation when I write code, except:

1) When I am first sitting down to solve a new problem. Then the documentation becomes quite long-winded and pontificatory, as if I were the only one on earth smart enough to solve the problem - or 2) When I come back to code I or someone else has written and find the documentation insufficient to understand the code without study (seems to be most of the time).

So I do not require my engineers or myself to do a great job of documentation, nor do I use Leo for that purpose. Rather, it is Leo’s outlining and organizing ability, and Leo’s ability to create source files from within the outline that give me what I think is a tremendous competitive advantage. Each of my company’s products run on all versions of windows from Win 3.1 to XP. In our flagship software piece, there are ten main modules, and each module is maintained by one single Leo file. In the CODEC module, one Leo file named compress.leo organizes and creates seven .asm files, forty-four .c files, twenty .h files, two .def files, four .mak files, etc. etc. etc. This one file can be checked out from source code control and given to an engineer for the addition of a new feature.

In it are contained all the known issues for the CODEC, each issue arranged in its own clone section. One clone section groups together every routine, variable or type definition that must change between different versions of Windows. These sections could be from six different c source files, two assembly files, and eight .h files. Another clone section groups together those sections relating to memory problems, which change according to the memory configuration and TSR configuration (or lack thereof) on the target machine. Another clone section groups sections that fail (or don’t fail) if the routine in question was accidentally run during the dreaded ‘interrupt time’. Another clone section is a section containing clones, each of which is named after the major bug that was fixed when the engineer who fixed the bug grouped a bunch of routines, definitions, etc. together to fix the bug.

None of the above clone sections was ‘designed’ into the document. Just the opposite happens. When the codec was first written, there was just a single Leo file with a bunch of sections for each c routine or assembly module. As the product grew and was tested on various platforms, each failure of the module was organized into clones each time a failure was fixed. This is what I call “SELF DOCUMENTING CODE”. This has nothing to do with me sitting and documenting anything. Its just that the STRUCTURE of a bug fix (or product enhancement) lives on long after the coding is done, as long as no one is foolish enough to delete the cloned sections that ‘DOCUMENT’ what happened.

In actual practice, this organizational ‘history’ is so powerful that I can’t begin to describe it. A ‘REVERSE LEARNING CURVE’ happens when an engineer gets a Leo file that already has the ‘interrupt time sensitive’ routines grouped together by the last unfortunate soul who had to work on them. There may not be any more written documentation, but the knowledge contained in the structure can be breathtaking. It is certainly time saving. I find this particularly true in my own case. Often I’ll look at some code that seems totally unfamiliar and think ‘what idiot wrote this crap’. Then I’ll look at the version control comments and realize that I wrote the crap. Then for sure I know the documentation is non-existent, but the clones I used to develop it are still there, and they always serve to refresh my memory in an indescribable way.

Enough of this commentary, I just looked at the clock. Best wishes to anyone willing to try Leo for a week. I hope you will be glad you did.
The Word outlines are very useful. But Leo makes Word look like a clunky toy.

#1 Reason would probably be clone nodes. One node can point to another. Another way of putting this is is that a leaf can be on more than one tree. For example, suppose you have a list of recipes. You simultaneously put a single recipe under multiple categories or even multiple hierarchies. You could put "3 bean enchilada" simultaneously under Recipes-Mexican and Food-Gas. Another example would be, if you are a biologist trying to decide under which genus to put a new species, you could put the species under two simultaneously. In effect, you can build a 3-D tree. For a further illustration see http://www.3dtree.com/ev/e/sbooks/leo/sbframetoc_ie.htm

#2 Reason would probably be that Leo outlines can be embedded in external text files. So, a Leo outline is more than an outline, it is a meta-structure that can be added to another text without changing that text, but rather providing an external road map to the text. Microsoft Word has a text (xml) version with a commenting convention, so Leo can even be used to add outlines into Word docs, although it isn't set up to do that now. For example, see http://www.3dtree.com/ev/e/sbooks/leo/sbframetoc_ie.htm In this case, the upper window of Leo is the meta-structure, and the bottom window is the file to which the meta-structure is being applied, viewed one node at a time.

I may not have made #2 very clear, but it is actually a very useful feature. It takes some getting used to before one sees all of the possibilities tho. One way to think of it is that Leo allows you to throw external documents into your outline, and yet the external document remains independent and can still be edited separately.

Some other cool things about Leo which Word doesn't feature: 1. Pure xml output that is easy to transform into other formats (next version of Word will have true XML format, but not as easy to work with). One consequence of this is that Leo files can be transformed pretty easily to web pages with their outlining capability intact. 2. Easy to add features since is programmed in Tk and open source. Maybe your average user can't start hacking on it, but a surprising amount can be tacked on by flipping through the Tk manual. 3. Free, opensource, multi-platform 4. Leo is scriptable with Python. It should be possible to build a Tickler into Leo using Python scripting, for example.
First of all, kudos to you for the excellent progress you've been making with Leo. I upgraded today after about three months of using and older version and I was thrilled to see all the great improvements that have happened so fast. I especially love the ability to go to next clone. I think you're really showing what open source can do and your current trajectory puts you on track to kick Emacs into the dustbin of computing history.

So today I copied all my data (personal information manager and project management stuff) out of my old outliner (ThoughtManager, which syncs with and runs on the Palm) and put it into Leo. It took me hours to do it and then to rearrange it the way I really wanted it. But having the ability to make clones and have different ways to view my data is, as you know, fabulous. In my case, for personal information and project management things, I used the flexibility of clones to allow me to see my data in several different views: 1) by project, the logical hierarchical breakdown by topic, 2) by person, so whenever I'm talking to someone I can easily see all the pending items related to them which may be spread over multiple projects, 3) by priority, so I can see what needs to get done sooner and what can wait for later and, 4) a special case of priority called "Today" for the things I'm going to focus on in the coming hours.

Now here's why I don't miss the ability of my old outliner to synch the entire outline with the Palm. It turns out the main thing I really want in the Palm is the top category "Today" so all I have to do is have Leo flatten that one heading into a text file (and it kindly remembers the name and directory of the file I used last time) and then I'm done because I've told the Palm Hotsync manager that that file should be sent to Palm memo pad every time I synch. The Palm Hotsync manager does a nice job of sending a text file to the Palm memo pad and even breaks the file up into multiple memo records if it's too big to fit in just one. So that gives me enough to be able to browse (or full text search) the small amount of data that I really want right inside my Palm (which is also my cell phone). Quick and dirty but it works.

For times when I want my whole outline with me, Leo wins again because thanks to its cross platform nature I can take my whole outline with me on my Mac iBook, even though I usually edit it on a Windows PC (which is the only kind of machine my old outliner would run on). Quite frankly, although my old outliner was able to shoehorn the whole thing into my palm/cellphone, it was a pain to access it on the small screen and slow processor. Now when I anticipate I'll need the whole thing, for example when I'm going to a meeting, I can put it on my Mac iBook (under X and Fink for now until Python can do it native under Aqua) and have real, full access to it all.

I think now in addition to being great for programming Leo is also a great PIM. Being able to flatten a strategically chosen portion of the outline into a known file name that the Palm synch manager has been told to send to the Palm on every synch does the trick for me. I wonder if you would consider something like an @flatten directive so I can have that done automatically for me every time I save my outline? For now it's up to me to flatten the node I want manually, although once I've done that the transfer to the Palm is automatic.

You're my hero! Thank you so much.
Another day, another breakthrough using Leo -- now I realize Leo is the best URL bookmark manager there is. No more bookmarks menus or favorites lists inside the browser for me. With the @url directive I can just double click on the URL to open it in my browser. Leo lets me arrange the URLs in a hierarchy (or multiple hierarchies), attach notes to them, save clippings of things I read on the sites. It's sooo much better than anything the browsers have built in and it lets me easily use different browsers on different platforms and different machines (try that with the browsers' built-in bookmark managers).

When using Leo as a project manager and personal information manager as I do I can heavily annotate every task and project with helpful and relevant URLs. And since URLs can be of the ``file://`` form, they're not just for web pages or HTML documents; I can link to any file on my disk of any type to be opened by any program.

Leo is a quantum leap for me in terms of how many projects I can manage and how much information I can find and organize and store in a useful way. I'm a data-mining army of one now and the web is my playground. Every time I find a web page that has interesting links to others, those links get stored in my Leo outline too, right where I can find them and make practical use of them. I can easily accept dozens of valuable links every day and integrate them into what I'm doing in a way that I'm confidant they won't get lost or forgotten. Before I always used to get bogged down by the difficulty of managing bookmarks inside the browser. But now I'm no longer the victim of information overload buried in the knowledge landslide of the Internet; instead I'm the professional strip miner with the world's biggest bulldozer. I eagerly plunge into mountains of data and emerge with all the valuable information nuggets neatly stored and organized. And my storehouse of knowledge is a flexible thing where I can reorganize and prioritize and massage the data to my heart's content as I learn more about it and decide to use it in different ways for different purposes. It's the difference between the pick axe and the steam shovel for me.
This year my accountant is getting a beautiful printout generated by LaTeX and Leo. I have a complicated tax situation this year, but I got it all laid out and organized in Leo. Then I had each of the nodes that had something my accountant needs to see write the data out to a file in the form a LaTeX table.

Sometimes a row of a table would have a result that was calculated by adding up a list of numbers. For that I used the modern day equivalent of an adding machine paper tape -- I stored a lisp s-expression in a Leo comment. I like s-expressions for this because once I put the opening "(+" on one line and the closing ")" on another line, I can fill in additional numbers just by typing them and can even annotate them with comments. So in the middle of generating a LaTeX file I might have something like this::

@ (+ 1165.26 1823.70 ; May 2002 123.38 ; June 2002 13.50 ; July 2002 13.21 ; October 2002 55.25 ; November 2002 ) @c

That's an annotated record of how I arrived at the number the accountant will actually see. I can just paste it into any lisp or scheme interpreter and get the total. Adding additional numbers is easy.

For next year, I think I might take this a step further. What I did this year is good for adding up numbers to get a total for one row of a LaTeX table. But it turns out I'd also like some more processing done on those tables (which I had to do by hand this time) -- I'd like the rows sorted in reverse order by magnitude (so that the big numbers jump out at you from the start of the tables) and I'd like a total of all the rows in the table. So I think next year, instead of having an s-expression that computes the total of one row for me, I think I'll use s-expressions that generate whole tables, formatted for LaTex, from the underlying data. So I'm thinking next year my s-expressions might look more like this::

@ (table "Widget Related Expenses" ("widget insurance" (+ 1165.26 1823.70 ; May 2002 123.38 ; June 2002 13.50 ; July 2002 13.21 ; October 2002 55.25 ; November 2002 )) ("widget shipping" (+ 472.15 651.94 ; May 2002 54 ; June 2002 )) ("widget cleaning" (+ 165.26 183.70 ; May 2002 123.38 ; June 2002 13.50 ; July 2002 13.21 ; October 2002 55.25 ; November 2002 )) ) @c

The job of that "table" function would be to return the LaTeX code needed to display a table with the category names and values, sorted descending by magnitude, with the total displayed. It's sort of a poor man's way of doing a spreadsheet inside Leo and then making it look great using LaTeX. The idea would be as I wanted to add more data, I'd add it to the s-expression and then reevaluate the whole thing by pasting it into a lisp interpreter and then copying the result back into the same Leo node for LaTeX to process.

-- Dan
.. Relative links...

.. _quotes: testimonials.html .. _toc: leo_TOC.html

.. WARNING: image targets may not have upper case letters!

.. |leo| image:: leo.gif :target: preface.html

.. |prev| image:: arrow_lt.gif :target: preface.html

.. |next| image:: arrow_rt.gif :target: FAQ.html
--------------------

|prev| |leo| |next|
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. August 30, 2005

|back| |leo| |next|

#### FAQ ####

This is Leo's Frequently Asked Questions document.

.. contents::
First, read the tutorial_. This will be enough to get you started if you just want to use Leo as an outliner_. If you intend to use Leo for programming, read the `Quick start for programmers`_, then look at Leo's source code in the file ``LeoPy.leo``. Spend 5 or 10 minutes browsing through the outline. Don't worry about details; just look for the following common usage patterns:

- The (Projects) tree shows how to use clones to represent tasks.

- Study ``@file leoNodes.py``. It shows how to define more than one class in single file.

- Most other files show how to use a single ``@others`` directive to define one class.

- Most methods are defined using ``@others``, *not* section definition nodes.
.. _`Clones & views`: intro.html#clones-views

You will lose much of Leo's power if you don't use clones. See `Clones & views`_ for full details.
Use `@file`_ trees (including ``@thin`` trees) unless you are *sure* you must have the extra flexibility of `@root`_ trees. Indeed, `@file`_ trees are much easier to use than `@root`_ trees:

- `@file`_ trees use less markup than `@root`_ trees. In particular, the `@others directive`_ is valid only within `@file`_ trees.

- You must explicitly tangle_ and untangle_ `@root`_ trees using the `Tangle and Untangle`_ commands.

However, `@root`_ trees are more flexible than `@file`_ trees:

- Sections_ may be defined anywhere within `@root`_ trees. Moreover, the `@unit`_ directive_ expands the scope of section definitions in `@root`_ trees so that a section may be referenced in several `@root`_ trees.

- The meaning of section definitions in `@root`_ trees are independent of their position within the tree.
Use methods for any code that is used (called or referenced) more than once.

Sections_ are convenient in the following circumstances:

- When you want to refer to snippets of code the can not be turned into methods. For example, many plugins start with the code like this::

<< docstring >> << imports >> << version history >> << globals >>

None of these sections could be replaced by methods.

- When you want to refer to a snippet of code that shares local variables with the enclosing code. This is surprisingly easy and safe to do, *provided* the section is used only in one place. `Section names`_ in such contexts can be clearer than method names. For example::

<< init ivars for writing >>

In short, I create sections when convenient, and convert them to functions or methods if they need to be used in several places.
Internally, Leo represents all strings as unicode. Leo translates from a particular encoding to Unicode_ when reading .leo files or `derived files`_. Leo translates from Unicode_ to a particular encoding when writing `derived files`_. You may see strange looking characters if your text editor is expecting a different encoding. The encoding used in any `derived file`_ is shown in the ``#@+leo`` `sentinel line`_ like this::

#@+leo-encoding=iso-8859-1.

**Exception**: the encoding is ``UTF-8`` if no ``-encoding=`` field exists. You can also use the ``@encoding`` directive_ to set the encoding for individual `derived files`_. If no ``@encoding`` directive_ is in effect, Leo uses the following settings_ to translate to and from unicode:

default_derived_file_encoding The encoding used for derived files if no ``@encoding`` directive_ is in effect. This setting also controls the encoding of files created by the ``Tangle`` commands. The default is ``UTF-8`` (case not important).

new_leo_file_encoding The encoding specified in the following line of new .leo files::

<?xml version="1.0" encoding="UTF-8">

The default is ``UTF-8`` (upper case for compatibility for old versions of Leo). **Important**: once a .leo file is created the ``<?xml...">`` line can only be changed by hand. This may cause unicode errors the next time the .leo file is loaded, so you should change the ``<?xml...">`` line by hand only when first creating a .leo file.

tk_encoding The encoding that Leo uses to communicate with Tk text widgets. You would typically use this setting only in an emergency. The section called::

<< set app.tkEncoding >>

in app.finishCreate sets this encoding as follows:

a) using the ``tk_encoding`` setting if it exists, b) using ``locale.getpreferredencoding`` if it exists, or the equivalent code in pre-python 2.3 versions, c) using ``sys.getdefaultencoding`` d) defaulting to ``"utf-8"``

Neither b nor c are guaranteed to give a valid encoding in all systems, and Leo will ignore invalid encodings returned from b or c. Therefore, setting the ``tk_encoding`` setting may be needed.
The encoding used in the file being imported doesn't match the encoding in effect for Leo. You have two options:

- Use the ``@encoding`` directive_ in an ancestor of the node_ selected when doing the ``Import`` command_ to specify the encoding of file to be imported.

- Set the ``tk_encoding`` setting_ (see the previous answer) to the encoding you normally use.
Using `@thin`_ trees can eliminate most problems with using Leo in cvs environments:

- Developers should use `@thin`_ trees to create derived files in any kind of cooperative environment.

- The cvs repository contains "reference" .leo files. These reference files should containing nothing but ``@thin`` nodes. Reference files will change only when new derived files get added to the project.

**Important**: Leo's `cvs repository`_ contains the *reference* versions of the following .leo files: ``LeoPyRef.leo`` and ``LeoPluginsRef.leo``. However, Leo's distributions contain the *non-reference* versions of those files: ``LeoPy.leo`` and ``LeoPlugins.leo``. These two files have many ``@thin`` nodes. There is no reference file for ``test.leo`` even though it contains ``@thin leoTest.py``. It would be clumsy to use testRef.leo, and there is less need to do so.

- Developers will use local copies of reference files for their own work. For example, instead of using ``LeoPyRef.leo`` directly, I use a copy called ``LeoPy.leo``. My local copy can contain nodes other than ``@thin`` nodes.
You have two options, depending on whether you want to be able to use sections or not.

- Use `@nosent`_ trees. Files derived from ``@nosent`` trees contain no sentinels_. However, Leo create the `derived file`_ just as in `@file`_ trees. In particular, Leo expands section references and understands the ``@others`` directive.

- Use `@asis`_ trees. Files derived from ``@asis`` trees contain no sentinels_. Moreover, Leo does not expand section references in ``asis`` trees. In other words, Leo creates the `derived file` simply by writing all body text in outline order. Leo can't update the outline unless the derived file contains sentinels, so Leo does not update ``@nosent`` trees or ``@asis`` trees automatically when you change the derived file in an external editor.
You have two options, depending on whether you want sentinel lines in your derived file or not.

- Use `@noref`_ trees. Leo creates files derived from ``@noref`` trees by writing all the nodes of the tree to the derived file in outline order. The derived file *does* contain some sentinels, so you *can* update ``@noref`` trees from changes made to derived files.

- Use `@asis`_ trees. Files derived from ``@asis`` trees contain no sentinels. Leo creates the derived file simply by writing all body text in outline order. Leo can't update the outline unless the derived file contains sentinels, so Leo does not update ``@asis`` trees automatically when you change the derived file in an external editor.
The import commands insert ``@ignore`` directives_ in the top-level node_. Leo does this so that you won't accidentally overwrite your files after importing them. Change the filename following ``@file`` or ``@root`` as desired, then remove the ``@ignore`` directive_. Saving the outline will then create the `derived file`_.
**Question**: I'm writing a Windows Script Component, which is an XML file with a CData section containing javascript. I can get the XML as I want it by using ``@language html``, but how can I get the tangling comments inside the CData section to be java-style comments rather than html ones?

**Answer**: In `@file`_ trees you use the ``@delims`` directive_ to change comment delimiters. For example::

@delims /* */ Javascript stuff @delims <-- --> HTML stuff

**Important**: Leo can not revert to previous delimiters automatically; you must change back to previous delimiters using another ``@delims`` directive_.

In `@root`_ trees you can work around this problem using the ``@silent`` directive_.
By Zvi Boshernitzan: I was having trouble disabling ``<?php`` with comments (and couldn't override the comment character for the start of the page). Finally, I found a solution that worked, using php's heredoc string syntax::

@first <?php @first $comment = <<<EOD EOD;

// php code goes here. echo "boogie";

$comment2 = <<<EOD @last EOD; @last ?>

or::

@first <?php @first /* */

echo "hi";

@delims /* */ @last ?>
Here is a posting which might be helpful: http://sourceforge.net/forum/message.php?msg_id=2300457 The ``@first`` directive_ is the key to output usable code in unsupported languages. For example, to use Leo with the Basic language, use the following::

@first $IFDEF LEOHEADER @delims ' @c $ENDIF

So this would enable a basic compiler to "jump" over the "true" LEO-header-lines. Like this::

$IFDEF LEOHEADER <-conditional compilation directive #@+leo-ver=4 <-these lines not compiled #@+node:@file QParser005.INC #@@first #@delims ' '@@c $ENDIF <-... Until here! <rest of derived code file ... >

This changes the comment symbol the apostrophe, making comments parseable by a BASIC (or other language.)
Use the @first directive_ in `@file`_ trees or `@nosent`_ trees. Use the @silent directive in `@root`_ trees.

The ``@first`` directive puts lines at the very start of files derived from ``@file``. For example, the body text of ``@file spam.py`` might be::

@first #! /usr/bin/env python

The body text of ``@file foo.perl`` might be::

@first #/usr/bin/perl

Leo recognizes the ``@first`` directive_ only at the start of the body text of `@file`_ nodes. No text may precede ``@first`` directives_. More than one ``@first`` directive may exist, like this::

@first #! /usr/bin/env python @first # more comments.
Leo has good support for `CWEB`_. `@file`_ trees can organize any part of CWEB code using *noweb* sections. You can also use `@asis`_, `@noref`_ or `@nosent`_ trees to create cweb files. See `CWEB mode`_ for full details.
No. Everything in an `@file`_ trees must be part of the derived file: orphan and ``@ignore`` nodes are invalid in ``@file`` trees. This restriction should not be troublesome. For example, you can organize your outline like this::

+ myClass ..+ ignored stuff ..+ @file myClass

(As usual, + denotes a headline.) So you simply create a new node_, called myClass, that holds your `@file`_ trees and stuff you don't want in the `@file`_ trees.
By Rich Ries. Some older C compilers don't understand the "//" comment symbol, so using ``@language C`` won't work. Moreover, the following does not always work either::

@comment /* */

This generates the following sentinel line::

/*@@comment /* */*/"

in the output file, and not all C compilers allow nested comments, so the last ``*\/`` generates an error. The solution is to use::

#if 0 @comment /* */ #endif

Leo is happy: it recognizes the ``@comment`` directive_. The C compiler is happy: the C preprocessor strips out the offending line before the C compiler gets it.
See the instructions are in ``LeoPy.leo`` in::

``Notes:How To:How to add support for a new language section.

This section contains clones of all relevant parts of Leo that you will change. Coming in Leo 4.4: Leo will use ``JEdit``'s language description files to drive the syntax colorer. To add support for a new language, just add another such description file.
You have two options:

- Get cvs write access, and add the `@thin`_ file to the plugins directory.

- Just send the `@thin`_ file to me at edreamleo@charter.net. That's all you need to do. In particular that there is no need to change ``leoPlugins.leo``.
The Import Files dialog allows you to select multiple files provided you are running Python 2.3 or above. There is also an importFiles script in ``LeoPy.leo``. You can use that script as follows::

import leoImport leoImport.importFiles(aDirectory, ".py")

This will import all .py files from aDirectory, which should be a full path to a particular directory. You could use ".c" to import all .c files, etc.
From: http://sourceforge.net/forum/message.php?msg_id=1685399

When building Tcl on Linux, do not specify "--enable-threads" Only use Tcl with the default "threads not enabled" case.

Here is how to build Tk without thread support:

- Go to www.tcl.tk, and download the sources for Tcl and Tk. - Build those two pack's as is told in the "How to Compile Tcl Source Releases" - Go to www.python.org and download your favorite Python (2.3.5 for me). - Build it as is told on the download page. - Enjoy using Leo on Linux.
Just run Leo in a console window. At the point you want to drop into the debugger, execute this line::

g.pdb()

All output from pdb goes to stdout, which is the console window. It would be good to create a subclass of pdb.Pdb that uses Leo's log pane rather than a console window, but I haven't done that. It could be done easily enough in a plugin...

**Important**: I recommend using g.trace instead of pdb. For example::

g.trace(x)

prints the name of the function or method containing the trace, and the value of x. g.callers is often useful in combination with g.trace. g.callers(5) returns the last 5 entries of the call stack. For example::

g.trace(x,g.callers(5))

Used this way, g.trace shows you patterns that will be invisible using pdb.
**Question**: It would be nice if Leo could open empty files. I tend to be "document oriented" rather than "application oriented" in my thinking and prefer "create empty file at location -> open it with program" to "start program -> create new file -> save it at location".

**Answer** by Paul Paterson: If you are on Windows 98/2000/XP then the procedure is as follows...

1. Start Leo 2. Click New 3. Click Save as... 4. Save the file as "c:\windows\shellnew\leofile.leo" (or c:\winnt for 2000/XP) 5. Open regedit "start...run...regedit" 6. Open HKEY_CLASSES_ROOT and find the ".leo" extension type 7. Go New ... Key from the context menu 8. Call the new key ShellNew 9. Select the new key, right-click, choose New...String Value from the context menu 10. Call it FileName 11. Double-click on the string, and modify it to be the filename of the leofile.leo file you created, including the extension 12. Exit the registry editor and restart Windows Explorer (you may need to reboot on Windows 98)

Now you should have a New:Leo File option in Explorer. This creates a duplicate of the file you saved. This can be useful because you could make a template Leo file containing some standard nodes_ that you always have and then save this.
By Dave Hein: The cause of the keymapping problem is a issue with the X11 keyboard mapping, not with Tk. If you have this problem on your system, issue the command::

xmodmap -pke

and look in the results for the line for keycode 22. I'll bet it shows something like::

keycode 22 = BackSpace Terminate_Server

That second token ("Terminate_Server") is what is supposed to be mapped to Shift-Backspace. You want this second token to be either not present or to be BackSpace. To fix this, create a file (e.g. .Xmodmap) and give it the content::

keycode 22 = BackSpace

then run the command::

xmodmap .Xmodmap

This fixes the problem. On my system this also disables the ability to terminate the X server using Ctrl-Alt-BackSpace. This is because of some conflict with xdb (xdb is the newer keyboard mapping facility in XFree86; xmodmap is the old original X11 keyboard mapping facility). I'm still working on that. I'm also not able to get xmodmap to make this change during X11 startup (again because of conflicts with xdb). But I'm working on that as well.
For the most part, docutils_ does a good job of reporting errors. docutils_ prints a message to the console and inserts an unmistakable error message in the generated .html file. **Important**: On Windows it is helpful to `Run Leo from a console window`_.

However, in some cases, docutils_ crashes instead of properly reporting the problem. There are several workarounds:

1. The crashes I have seen arise from the following bug in docutils. **Hyperlinks in image:: markup must be lower case**. This will work::

.. |back| image:: arrow_lt.gif :target: faq_

This will **crash**::

.. |back| image:: arrow_lt.gif :target: FAQ_

So avoid this crash by making sure to use lower case targets in ``:target:`` markup.

2. You can change the docutils_ source slightly so that it prints a traceback when it crashes. (The rst3 plugin should be able to do this, but I haven't figured out how yet.) It's easy enough to do this:

- Find the file ``core.py`` in top-level ``docutils`` folder. Typically this folder will be in Python's ``site-packages`` folder.

- Open ``core.py`` in some editor other than Leo.

- Find the method called ``report_Exceptions``.

- Insert the following lines at the very start of this method::

print 'EKR: added traceback' import traceback ; traceback.print_exc()

This will cause a traceback whenever docutils_ crashes. I have found that such tracebacks are generally enough to locate the general area of the problem. **Note**: These tracebacks go to the console window, so you should `Run Leo from a console window`_.

3. As a last resort, you can isolate syntax errors by reducing your input files until they work again, then adding sections until you get a crash. This is easy enough to do (when using the `rst3 plugin`_) by change a headline ``x`` to ``@rst-ignore-tree x``.
From: http://sourceforge.net/forum/message.php?msg_id=3240374 Using Leo's ``File-Export-Flatten Outline`` commands creates a ``MORE`` style outline which places all Leo body sections on the left margin. The headlines_ are indented with tabs which Excel will read as a tab delimited format. Once inside Excel there are benefits.

1. The most obvious benefit inside Excel is that the body sections (Excel first column) can be selected easily and highlighted with a different font color. This makes the ``MORE`` format very readable. Save a copy of your sheet as HTML and now you have a web page with the body sections highlighted.

2. It is possible to hide columns in Excel. Hiding the first column leaves just the headlines showing.

3. Formulas based on searching for a string can do calculations in Excel. For example if a heading ``"Current Assets"`` appears on level 4 then the body formula::

=INDEX(A:A,MATCH("Current Assets",D:D,0)+1)

will retrieve it. The +1 after match looks down one row below the matched headline. The trick is to place all your headlines in quotes because Excel will see ``+ "Current Assets"`` from the ``MORE`` outline. When Excel tries without the quotes it thinks it is a range name and displays a ``#N/A`` error instead of the headline. Also you must place a child node_ below to get the + sign instead of a - sign which would give a ``MORE`` headline of ``-"Current assets"`` , also is an error.

I think there is some interesting possibility here because of the enforcement of Leo `body text`_ being always in the first column. The Leo outline provides additional reference to organizing the problem not typical of spreadsheet models. Beyond scripting in Python, Excel is good at doing interrelated calculations and detecting problems like circular references. In Excel Tools-Options-General is a setting for r1c1 format which then shows numbers instead of letters for column references. Using this would allow entries like this in the leo body::

1000 3500 =R[-1]C+R[-2]C

In Excel you would see 4500 below those two numbers. This is completely independent of where the block of three cells exists on the sheet.
Python's decorator_ syntax is ill-conceived. This syntax file hack works well enough anyway to work with Leo ``@`` markup::

syn region leoComment start="^@\s*" end="^@c\s*$" syn match pythonDecorator "@\S\S+" display nextgroup=pythonFunction skipwhite
By Rich Ries. I often rework C code that's already been "Leo-ized"--the first pass was quick and dirty to get it going. When I do subsequent passes, I wind up with subnodes that are out of order with the sequence found in the main node_. It's not a big deal, but I like 'em ordered. With just one editor pane, clicking on the node_ to move would switch focus to that node_. I'd then need to re-focus on the main node_. A minor nuisance, but it does slow you down.

My solution is to open a second editor with its focus on the main node_. Switch to the other editor, and, referring to the first editor pane, move the nodes as you like. The second editor's pane will change focus to the node_ you're moving, but the first editor will stay focused on the main node_. It's a lot easier to do than to describe!
One way is to link directly to the media file from a Leo node_ (with ``@url``) and write a scriptbutton to wrap all URL-nodes under the current node_ in a single HTML page (using the HTML browser trick at http://sourceforge.net/forum/forum.php?thread_id=1201579&forum_id=10226).

Then, you can view your media in two ways:

- Individually. You can directly click on the ``@url`` link to display the media in the browser (assuming you have your MIME/filetype associations set up correctly for your browser).

- In a group. You can click on a script button (you have to code this yourself, very simple) which should collect all ``@url`` nodes_ under the current node_ and dynamically generate a HTML page displaying either links to or embedded versions of the media (using the HTML trick described above to invoke the browser). This way, you can create collections of ``@url`` nodes under a single node_ (like a bookmark folder), and press a single button to view the ``@url`` collection as a single entity in the browser (with all browser capabilities like displaying the media).

You could probably generalize this idea of "collect all ``@url`` nodes under current node_ and display as HTML in browser" into a general-purpose plugin. However, the plugin would have to be somewhat smart in mapping a link to its corresponding HTML code (e.g. an image link gets mapped to an <img> HTML tag, a link to a Flash file gets mapped to an <embed> tag, etc).
.. Links used in this document...

.. ----- External links.

.. _`cvs repository`: http://sourceforge.net/cvs/?group_id=3458 .. _decorator: http://www.python.org/peps/pep-0318.html .. _docutils: http://docutils.sourceforge.net/ .. _unicode: http://www.unicode.org/

.. ----- Relative links into Leo's documentation.

.. _`Associating Leo with .leo Files`: install.html#how-to-associate-leo-with-leo-files-on-windows .. _`How to install Leo on Windows`: install.html#how-to-install-leo-on-windows

.. _`CWEB mode`: directives.html#cweb-mode .. _command: commands.html .. _commands: commands.html .. _`quick start for programmers`: intro.html#quick-start-for-programmers .. _`rst3 plugin`: rstplugin3.html .. _`Run Leo from a console window`: `How can I run Leo from a console window?`_ .. _`Tangle and Untangle`: commands.html#tangling-an-outline-producing-derived-files .. _tutorial: intro.html .. _`Leo 4.0: Eliminating error 'recovery'`: history.html#leo-4-0-eliminating-error-recovery .. _`Chapter 9: History of Leo`: history.html

.. ----- References to the glossary: the glossary now contains references to the tutorial. .. _`@asis`: glossary.html#asis-trees .. _`@file`: glossary.html#file-trees .. _`@others directive`: glossary.html#others .. _`@noref`: glossary.html#noref .. _`@nosent`: glossary.html#nosent .. _`@root`: glossary.html#root .. _`@thin`: glossary.html#thin-trees .. _`@unit`: glossary.html#unit .. _`body text`: glossary.html#body-text .. _cweb: glossary.html#cweb .. _directive: glossary.html#directive .. _directives: glossary.html#directives .. _`derived file`: glossary.html#derived-file .. _`derived files`: glossary.html#derived-files .. _headline: glossary.html#headline .. _headlines: glossary.html#headlines .. _node: glossary.html#node .. _nodes: glossary.html#nodes .. _outliner: glossary.html#outliner .. _sections: glossary.html#sections .. _`section names`: glossary.html#section-names .. _sentinels: glossary.html#sentinels .. _`sentinel line`: glossary.html#sentinel .. _`sentinel lines`: glossary.html#sentinel .. _setting: glossary.html#setting .. _settings: glossary.html#settings .. _tangle: glossary.html#tangle .. _untangle: glossary.html#untangle

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: testimonials.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: install.html
``c.frame.menu.createMenuItemsFromTable`` will append items to the end of an existing menu. For example, the following script will add a new item at the end of the 'File' menu::

def callback(*args,**keys): g.trace()

table = (("Test1",None,callback),)

c.frame.menu.createMenuItemsFromTable('File',table)

Plugins can do anything that can be done with ``Tk`` using the menu returned by ``c.frame.menu.getMenu``. For example, here is a script that adds a Test menu item after the 'Open With' menu item in the File menu::

def callback(*args,**keys): g.trace()

fileMenu = c.frame.menu.getMenu('File')

# 3 is the position in the menu. Other kinds of indices are possible. fileMenu.insert(3,'command',label='Test2',command=callback)
The trick is to create a workflow that separates editing from testing. Putting test code in ``LeoPy.leo`` would waste a lot of time. To run tests you would have to exit Leo and reload ``LeoPy.leo``. A much quicker way is to put all test code in a ``test.leo`` file. So to change and test code, do the following:

1. Save ``LeoPy.leo`` but do **not** exit Leo.

2. Quit the copy of Leo running test.leo, then reload test.leo.

3. Run test scripts from test.leo.

That's all. Python will recompile any changed .py files in the new copy of Leo. **Note**: I create a batch file called t.bat that runs test.leo, so to the "edit-reload-test" cycle is just:

1. Control-S (in ``LeoPy.leo``: saves the .leo file) 2. t (in a console window: runs test.leo, compiling all changed .py files as a side effect) 3. Control-E (in test.leo: runs the test script)

The benefits of the new workflow:

- test.leo loads _much_ more quickly than ``LeoPy.leo`` does. This new approach can increase the speed of the edit-reload-test cycle by more than a factor of 10. Hitting Control-S, t, Control-E takes about 5 seconds.

- ``LeoPy.leo`` runs with the *old* code, so it is much easier to fix syntax errors or exceptions in the *new* code: just fix the problem and save ``LeoPy.leo`` *without* closing ``LeoPy.leo``, then restart test.leo. You run your tests on the new code, but you edit the new code with the old, stable code.

- test.leo is the perfect place to develop test. I can create and organize those tests and when I am done, ''test.leo'' is a log of my work.
@language rest
@language rest
@language rest
@language rest
@language rest
@language rest
@language rest
@language rest
@language rest
@nocolor

For instruction about installing Leo see: http://webpages.charter.net/edreamleo/install.html

For everything a beginner needs to know about Leo see: http://webpages.charter.net/edreamleo/intro.html

For help, please ask questions at: http://sourceforge.net/forum/?group_id=3458
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. August 30, 2005

|back| |leo| |next|

############ Appendices ############

.. contents::
.. Relative links.

.. _`Chapter 13: Writing plugins`: writingPlugins.html

.. References to the glossary.

.. _`sentinel lines`: glossary.html#sentinel-lines

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: IPythonBridge.html

.. |next| image:: arrow_rt.gif :target: glossary.html

.. |leo| image:: leo.gif :target: front.html
c.save()
@color # Script to promote headlines and body text

root = p.copy() body = [root.bodyString()+'\n'] for p in root.subtree_iter(): body.append(p.headString()) body.append(p.bodyString().rstrip()+'\n')

body = '\n'.join(body) root.setBodyString(body)
@color

# Converts text selection to def list.

@others

createDefList(c,p)
def createDefList(c,p):

undoType = 'Create Def List' head,lines,tail,oldSel,oldYview = c.getBodyLines() if not lines: return

result = ['``%s``\n' % lines[0].strip()]

for line in lines[1:]: result.append(' %s' % line.lstrip()+'\n') lines = ''.join(result).rstrip()

c.updateBodyPane(head,lines,tail,undoType,oldSel,oldYview)
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. August 30, 2005

|prev| |leo| |next|

############ Glossary ############
.. Links used in this document.

.. ----- External links.

.. _`CWEB language`: http://www-cs-faculty.stanford.edu/~knuth/cweb.html .. _`literate programming web page`: http://www.literateprogramming.com/ .. _`noweb language`: http://www.eecs.harvard.edu/~nr/noweb/ .. _`rST primer`: http://docutils.sourceforge.net/docs/user/rst/quickstart.html

.. ----- Relative links.

.. _`Chapter 8: Customizing Leo`: customizing.html .. _`Writing plugins and hooks`: writingPlugins.html

.. _`programming reference`: directives.html .. _`@asis`: directives.html#asis-and-noref .. _`@auto`: directives.html#auto .. _`@file`: directives.html#file-and-thin .. _`@noref`: directives.html#asis-and-noref .. _`@nosent`: directives.html#nosent .. _`@root`: directives.html#root .. _`@thin`: directives.html#file-and-thin .. _`@unit documentation`: directives.html#root .. _`tangling @root trees`: directives.html#tangling-root-trees-with-the-tangle-commands .. _`untangling @root trees`: directives.html#untangling-root-trees-with-the-untangle-commands

.. ----- References to the tutorial. .. _`clones & views`: intro.html#clones-views .. _`leo's tutorial`: intro.html .. _`derived files section`: intro.html#derived-files .. _`directives for programming`: intro.html#directives-for-programming .. _`leo directives`: intro.html#leo-directives .. _`quick start for programmers`: intro.html#quick-start-for-programmers .. _`sentinels lines`: intro.html#sentinel-lines

.. WARNING: image targets may not have upper case letters!

.. |prev| image:: arrow_lt.gif :target: appendices.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: new-4-4-8.html

----------------------

|back| |leo| |next|
**Important**: We often refer to outline_ nodes_ by the directives_ they contain. For example, an `@root node`_ is a node containing an @root directive_, etc. **Exception**: An `@file node`_ is a node whose *headline* starts with ``@file``.

.. _`@auto node`: .. _`@file node`: .. _`@thin node`: .. _`@root node`: .. _`@file nodes`: .. _`@thin nodes`: .. _`@root nodes`:

``@file node`` An ``@file`` node_ is a node whose *headline* starts with ``@file``. **Important**: Headlines_ that start with ``@file-asis``, ``@file-noref``, ``@file-nosent`` (and their abbreviations ``@asis``, ``@noref``, ``@nosent``) are collectively called ``@file`` nodes.

.. _`@auto tree`: .. _`@file tree`: .. _`@thin tree`: .. _`@root tree`: .. _`@file trees`: .. _`@thin trees`: .. _`@root trees`:

``@file tree, @others tree, @root tree, etc.`` An @file tree_ is a tree whose root_ is an @file node, etc.

``@asis, @auto, @file, @noref, @nosent, @thin`` Headlines_ that start with one of these create (correspond to) `derived files`_. The following synonyms exist::

@asis, @file-asis @noref, @file-noref @nosent, @file-nosent

For more information, see the documentation for `@asis`_, `@auto`_, `@file`_, `@noref`_, `@nosent`_ and `@thin`_ in Leo's `programming reference`_ chapter.

\@auto trees allow you to edit derived files that contain no sentinels. Leo will import the @auto files when reading .leo files. Be careful when first creating the @auto node. *Before* saving the .leo file containing the new @auto node, use the read-at-auto-nodes command to do the initial import.

.. _`@all`: .. _`@all directive`:

``@all`` A directive_ that copies the `body text`_ of all nodes_ in an `@thin` tree to the corresponding `derived file`_. For more information, see `directives for programming`_ in `Leo's tutorial`_.

.. _`@others`: .. _`@others directive`:

``@others`` A directive_ that copies the `body text`_ of all nodes_ *except* `section definition nodes`_ in an `@thin` tree to the corresponding `derived file`_. For more information, see `directives for programming`_ in `Leo's tutorial`_.

.. _`@unit`: .. _`@unit directive`:

``@unit`` A directive_ that expands the scope_ of definitions in `@root` trees. For more information, see the `@unit documentation` in Leo's `programming reference`_.

.. _`body pane`:

``Body pane`` The pane containing the `body text`_ of the currently selected headline_ in the `outline pane`_.

.. _`body text`:

``Body text`` The text in the `body pane`_. Body text is always associated with a particular node_.

.. _`body text box`:

``Body text box`` A small blue box in the `icon box`_ indicating that the node_ contains `body text`_.

.. _`child`: .. _`children`:

``Child`` A node_ directly contained by a node.

.. _`chunk`: .. _`chunks`:

``Chunk`` A section_ (noweb_ terminology).

.. _`clone`: .. _`clones`: .. _`cloned`:

``Clone`` A copy of a tree_ that changes whenever the original changes. The original and all clones are treated equally: no special status is given to the "original" node_.

.. _`clone arrow`: .. _`clone arrows`:

``Clone Arrow`` A small red arrow in the `icon box`_ indicating that the node_ is a clone_.

.. _`code part`: .. _`code parts`:

``Code part`` A part of a `section definition`_ that contains code. Code parts start with ``@c`` or ``@code`` directives_ and continue until the next `doc part`_

.. _contract: .. _contracts: .. _contracted:

``Contract``: To hide all descendants_ of a node_.

.. _`cweb`:

``CWEB`` A `literate programming`_ language invented by Donald Knuth and Silvio Levy. The `CWEB language`_ produces derived files for the C language.

.. _`demote`:

``Demote`` To move all siblings_ that follow a node_ so that they become children_ of the node.

.. _`derived file`: .. _`derived files`:

``Derived file`` The file created as the result of tangling_ a node containing an ``@root`` directive_. The file consists of the expansion of the text following the ``@root`` directive_. For more information, see the `derived files section`_ of `Leo's tutorial`_.

.. _`descendant`: .. _`descendants`:

``Descendant`` An offspring_ of a node_. That is, a child_, grandchild_, etc. of a node.

.. _`directive`: .. _`directives`:

``Directive`` A keyword, preceded by an '@' sign, in `body text`_ that controls Leo's operation. The keyword is empty for the ``@`` directive. For more information, set the `Leo directives`_ section of `Leo's tutorial`_.

.. _`doc part`: .. _`doc parts`:

``Doc part, @doc part, document part, etc.`` A part_ of a `section definition`_ that contains comments. Doc parts start with ``@`` and continue until the ``@c`` directive_ or the end of the `body text`_. In `@root trees`_, doc parts are associated with the immediately following `code part`_, if any.

.. _`escape convention`: .. _`escape conventions`:

``Escape convention`` A convention for representing sequences of characters that would otherwise have special meaning. Leo has only one such convention: in `@root trees`_, ``@@`` in the leftmost column of a `code part`_ stands for a single ``@`` character. **Important**: Leo does not support `noweb's`_ ``@<<`` and ``@>>`` escape conventions. Any line containing matched ``<<`` and ``>>`` is a `section reference`_, regardless of context. To use ``<<`` and ``>>`` as ordinary characters, place them on separate lines.

.. _expand: .. _expands: .. _expanded:

``expand`` To make the children_ of a node_ visible.

.. _`grandchild`: .. _`grandchildren`:

``Grandchild`` The child_ of a child of a node_.

.. _`headline`: .. _`headlines`: .. _`headline text`:

``Headline`` The headline text of a node_. The part of the node visible in the `outline pane`_

.. _`hoist`: .. _`hoisted`: .. _`dehoist`:

``Hoist & dehoist`` Hoisting a node_ redraws the screen that node and its descendants_ becomes the only visible part of the outline_. Leo prevents the you from moving nodes outside the hoisted outline. Dehoisting a node restores the outline. Multiple hoists may be in effect: each dehoist undoes the effect of the immediately preceding hoist.

.. _`icon box`: .. _`icon boxes`:

.. _`LaTex`:

``LaTex`` A markup language often used in `literate programming` environments. See: http://www.latex-project.org/

``Icon box`` An icon just to the left of `headline text`_ of a node_ indicating whether the node is cloned, marked or dirty, and indicating whether the node contains `body text`_.

.. _`Leo1`: .. _`Leo2`:

``Leo1 and Leo2`` **Leo1** denotes all versions of Leo that write version 1 .leo files, that is, all Windows version of Leo prior to version 2.0. The last version of Leo1, version 1.15, understands enough about Leo2 to issue a warning when opening version 2 files.

**Leo2** denotes all versions of Leo that write version 2 .leo files, that is, all versions of leo.py and all Windows versions with version number 2.0 and above. Only Leo2 can generate `derived files`_ from `@file trees`_.

.. _`literate programming`:

``Literate programming`` A style of programming that aims at producing the highest quality program listings. Literate programming languages apply two fundamental operations to text: weaving_ and tangling_. Leo supports two literate programming languages, `CWEB`_ and `noweb`_. For more links see the `literate programming web page`_.

.. _`mark`: .. _`marks`:

``Mark`` A red vertical line in the `icon box`_ of a node_.

.. _node: .. _nodes:

``Node`` The organizational unit of an outline_. The combination of `headline text`_ and `body text`_. Sometimes used as a synonym for tree_.

.. _`noweb`: .. _`noweb's`:

``noweb`` A literate programming language invented by Norman Ramsey. The `noweb language`_ can produce `derived files`_ for any text-based programming language.

.. _`offspring`:

``Offspring`` The children_, grandchildren_, etc. of a node_.

.. _`organizing node`: .. _`organizing nodes`: .. _`organizer node`: .. _`organizer nodes`:

``Organizing node``, ``organizer node`` A node_ containing no `body text`_. Organizing nodes may appear anywhere in an `@file tree`_; they do not affect the derived file in any way. In particular, organizing nodes do not affect indentation in `derived files`_.

.. _`orphan`: .. _`orphan node`: .. _`orphan nodes`:

``Orphan node`` A node_ that would not be copied to a `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`_. No information is lost; Leo saves the information in the `@thin tree`_ in the .leo file. Leo will load the `@thin tree`_ from the .leo file the next time Leo opens the .leo file.

.. _`outline`: .. _`outliner`: .. _`outlines`:

``Outline`` - A node_ and its descendants_. - A tree_ - All the nodes_ of a .leo file.

.. _`outline order`:

``Outline Order`` The order that nodes_ appear on the screen when all nodes_ are expanded.

.. _`outline pane`:

``Outline pane`` The pane containing a visual representation of the entire outline_, or a part of the outline_ if the outline is hoisted_.

.. _parent: .. _parents:

``Parent`` The node_ that directly contains a node.

.. _`part`: .. _`parts`:

``Part`` A synonym for section_. See also `code part`_ and `doc part`_.

.. _`pdf file`: .. _`.pdf file`:

``pdf file`` A file that can be read by Adobe Acrobat.

.. _`plugin`: .. _`plugins`:

``Plugin`` - A Python file in Leo's ``plugins`` folder. - A way to modify and extend Leo without changing Leo's core code. ``leoPlugins.leo`` contains all of Leo's official plugins.

See `Writing plugins and hooks`.

.. _`promote`:

``Promote`` To move all children_ of a node_ in an outline so that they become siblings_ of the node.

.. _reStructuredText: .. _rST:

``reStructuredText (rST)`` A simple, yet powerful markup language for creating .html, or LaTeX output files. See the `rST primer`_.

.. _`root`: .. _`root node`:

``Root`` - The first node_ of a .leo file. - The first node of an `@root`_ tree or `@file`_ tree.

.. _`rst3 plugin`:

``rST plugin`` A plugin_ that supports reStructuredText_. Unlike previous rst plugins, the rst3 plugin supports per-node options.

.. _`scope`:

``Scope`` The portion of the outline_ in which a `section definition`_ is known.

.. _`section`: .. _`sections`:

``Section`` A fragment of text that can be incorporated into `derived files`_. See the `Quick start for programmers`_ in `Leo's tutorial`_ for more details.

.. _`section definition`: .. _`section definitions`:

``Section definition``: The `body text`_ of a `section definition node`_. See the `Quick start for programmers`_ in `Leo's tutorial`_ for more details.

.. _`section definition node`: .. _`section definition nodes`:

``Section definition node`` A node_ whose headline_ starts with a `section name`_ and whose body text defines a section_. See the `Quick start for programmers`_ in `Leo's tutorial`_ for more details.

.. _`section name`: .. _`section names`:

``Section name`` A name enclosed in ``<<`` and ``>>``. Section names may contain any characters except newlines and ">>". See the `Quick start for programmers`_ in `Leo's tutorial`_ for more details.

.. _`section reference`: .. _`section references`: .. _`reference`: .. _`references`: .. _`referenced`:

``Section reference`` A `section name`_ appearing in a `code part`_. Tangling_ replaces all references by their definitions. See the `Quick start for programmers`_ in `Leo's tutorial`_ for more details.

.. _`sentinel`: .. _`sentinels`: .. _`sentinel lines`:

``Sentinels, sentinel lines`` Comment lines in files derived from `@file nodes`_. Such lines start with an ``@`` following the opening comment delimiter. Sentinels embed outline structure into `derived files`_. **Do not alter sentinel lines**. Doing so can corrupt the outline structure. For more information see `Sentinel lines`_ in `Leo's tutorial`_.

.. _`@settings`: .. _`setting`: .. _`settings`:

``Setting``: 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`_.

.. _`sibling`: .. _`siblings`:

``Sibling`` Two nodes_ are siblings if they have the same parent_. Siblings of the root_ have no parent.

.. _`tangle`: .. _`tangles`: .. _`tangling`:

``Tangling`` The process of creating `derived files`_ from `@root trees`_ or `@file trees`_. Leo tangles `@file trees`_ automatically when writing a .leo file. You must explicitly tangle_ `@root trees`_ using the ``Tangle`` command. Tangling expands all `section references` in an `@root node`_ or `@file node`_. For more information, see `Tangling @root trees`_ in Leo's `programming reference`_.

.. _`target language`:

``Target language`` The language used to syntax color text. This determines the default comment delimiters used during tangling_ and untangling_.

.. _`tree`: .. _`trees`:

``Tree`` An outline_. A node_ and its descendants_.

.. _`untangle`: .. _`untangles`: .. _`untangling`:

``Untangling`` Updating an outline_ based on changes to `derived files`_. Untangling allows changes to be propagated from derived files back to the outline. Especially useful when fixing syntax errors outside Leo. For more information, see `Untangling @root trees`_ in Leo's `programming reference`_.

.. _`weave`: .. _`weaves`: .. _`weaving`:

.. _`view node`: .. _`view nodes`:

``View node`` A `node`_ that represents a view of an `outline`_. View nodes are typically ordinary, non-`cloned`_ nodes that contain cloned `descendant`_ nodes. The cloned descendant nodes comprise most of the data of the view. Other non-cloned nodes may add additional information to the view. See `clones & views`_ in the `Leo's tutorial`_ for more information.

``Weaving`` The process of creating typeset documentation from a noweb_ or CWEB_ source file. Weaving creates documentation. Tangling_ creates `derived files`_. Leo does not support weaving directly. To weave a file you can create noweb_ or CWEB_ files using Leo's ``Export`` commands, then use the noweb_ or CWEB_ systems to weave those files.
-----------------------

|prev| |leo| |next|
@language rest
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. February, 2006

|back| |leo| |next|

########################## Chapter 11: White Papers ##########################

I wrote the first two white papers soon after discovering Python. The conclusions in these papers have remained largely unchanged. I wrote the third in November 2004, and rewrote it in February 2006.

.. contents::
.. External links...

.. _pychecker: http://pychecker.sourceforge.net/ .. _`region inference`: http://en.wikipedia.org/wiki/Region_inference

.. Relative links...

.. _chapter10: theory.html .. _appendices: appendices.html .. _`Rst3 plugin`: rstplugin3.html .. _`Scripting plugin`: plugins.html#mod-scripting .. _`test buttons`: scripting.html#test-and-suite-nodes

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: theory.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: plugins.html
What struck me first as I converted C++ code to Python is how much less blah, blah, blah there is in Python. No braces, no stupid semicolons and most importantly, *no declarations*. No more pointless distinctions between ``const``, ``char *``, ``char const *``, ``char *`` and ``wxString``. No more wondering whether a variable should be ``signed``, ``unsigned``, ``short`` or ``long``.

Declarations add clutter, declarations are never obviously right and declarations don't prevent memory allocation tragedies. Declarations also hinder prototyping. In C++, if I change the type of something I must change all related declarations; this can be a huge and dangerous task. With Python, I can change the type of an object without changing the code at all! It's no accident that Leo's new log pane was created first in Python.

Functions returning tuples are a "minor" feature with a huge impact on code clarity. No more passing pointers to data, no more defining (and allocating and deallocating) temporary structs to hold multiple values.

Python can't check declarations because there aren't any. However, there is a really nifty tool called Pychecker that does many of the checks typically done by compilers. See `pychecker`_ for details.
Python is much more powerful than C++, not because Python has more features, but because Python needs *less* features. Some examples:

- Python does everything that the C++ Standard Template Library (STL) does, without any of the blah, blah, blah needed by STL. No fuss, no muss, no code bloat.

- Python's slicing mechanism is very powerful and applies to any sequence (string, list or tuple). Python's string library does more with far less functions because slices replace many functions typically found in other string libraries.

- Writing dict = {} creates a dictionary (hash table). Hash tables can contain anything, including lists and other hash tables.

- Python's special functions, ``__init__``, ``__del__``, ``__repr__``, ``__cmp__``, etc. are an elegant way to handle any special need that might arise.
Before using Python I never fully realized how difficult and dangerous memory allocation is in C++. Try doing::

aList[i:j] = list(aString)

in C. You will write about 20 lines of C code. Any error in this code will create a memory allocation crash or leak.

Python is fundamentally safe. C++ is fundamentally unsafe. When I am using Python I am free from worry and anxiety. When I am using C++ I must be constantly "on guard." A momentary lapse can create a hard-to-find pointer bug. With Python, almost nothing serious can ever go wrong, so I can work late at night, or after a beer. The Python debugger is always available. If an exception occurs, the debugger/interpreter tells me just what went wrong. I don't have to plan a debugging strategy! Finally, Python recovers from exceptions, so Leo can keep right on going even after a crash!
Python has almost all the speed of C. Other interpretive environments such as icon and Smalltalk have clarity, power and safety similar to Python. What makes Python unique is its seamless way of making C code look like Python code. Python executes at essentially the speed of C code because most Python modules are written in C. The overhead in calling such modules is negligible. Moreover, if code is too slow, one can always create a C module to do the job.

In fact, Python encourages optimization by moving to higher levels of expression. For example, Leo's Open command reads an XML file. If this command is too slow I can use Python's XML parser module. This will speed up Leo while at the same time raising the level of the code.
Little of Python is completely new. What stands out is the superb engineering judgment evident in Python's design. Python is extremely powerful, yet small, simple and elegant. Python allows me to express my intentions clearly and at the highest possible level.

The only hope of making Leo all it can be is to use the best possible tools. I believe Python (possibly with Tkinter) will allow me to add, at long last, the new features that Leo should have.

Edward K. Ream, October 25, 2001. P.S., September, 2005:

Four years of experience have only added to my admiration for Python. Leo could not possibly be what it is today without Python.
-----------------------

|back| |leo| |next|
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|back| |leo| |next|

########################################## Chapter 3: Using Outlines ##########################################

This chapter tells how to use Leo's outlines.

.. contents::
.. _`Chapter 2\: A Tutorial Introduction to Leo`: intro.html .. _`Chapter 4\: Writing Programs in Leo`: directives.html .. _`Clones and views`: intro.html#clones-views

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: intro.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: directives.html

@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|back| |leo| |next|

########################################## Chapter 5: Using Leo's Commands ##########################################

This chapter discusses all of Leo's menu commands. It starts with a discussion of the Emacs-like minibuffer, then continues with a discussion of commands in each of Leo's menus.

.. contents::
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|back| |leo| |next|

########################################## Chapter 6: Leo and Literate Programming ##########################################

This chapter discusses Leo's relationship with traditional `literate programming`_.

.. contents::
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|back| |leo| |next|

############################################# Chapter 8: Customizing Leo #############################################

This chapter discusses how to customize Leo using the plugins and other means. See `Specifying settings`_ for a description of how to change Leo's settings.

.. contents::
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|back| |leo| |next|

########################################## Chapter 9: History of Leo ##########################################

This chapter discusses the history of Leo and tells the essential features of each version. Here are the most important dates in Leo's history:

.. contents::
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|back| |leo| |next|

########################################## Chapter 10: Theory of Operation ##########################################

This chapter discusses how Leo's code works, paying particular attention to topics that have caused difficulties in design or implementation. This chapter will be of use primarily to those wanting to change Leo's code.

.. contents::
.. External links...

.. _CWEB: http://www-cs-faculty.stanford.edu/~knuth/cweb.html .. _noweb: http://www.eecs.harvard.edu/~nr/noweb/

.. Relative links...

.. _`Chapter 4\: Writing Programs in Leo`: directives.html .. _`Chapter 6\: Leo and Literate Programming`: design.html .. _`Chapter 8: Customizing Leo`: customizing.html

.. _`Clones and views`: intro.html#clones-views .. _`Creating script buttons`: scripting.html#creating-script-buttons .. _`Tangling @root trees with the Tangle commands`: directives.html#tangling-root-trees-with-the-tangle-commands

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: directives.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: design.html
.. Relative links...

.. _`Chapter 5\: Using Leo's Commands`: commands.html .. _`Chapter 7\: Scripting Leo with Python`: scripting.html .. _`Clones & views`: intro.html#clones-views .. _`Organizer nodes`: intro.html#good-style-and-bad-sections-vs-others

.. _`@file trees`: glossary.html#file-trees .. _`@root node`: glossary.html#root-node .. _child: glossary.html#child .. _clones: glossary.html#clones .. _commands: `Chapter 5\: Using Leo's Commands`_ .. _cweb: glossary.html#cweb .. _`literate programming`: glossary.html#literate-programming .. _node: glossary.html#node .. _outline: glossary.html#outline .. _outlines: glossary.html#outlines .. _`reference`: glossary.html#reference .. _`referenced`: glossary.html#referenced .. _reStructuredText: glossary.html#restructuredtext .. _`rst3 plugin`: glossary.html#rst3-plugin .. _section: glossary.html#section .. _sections: glossary.html#sections .. _`section name`: glossary.html#section-name .. _`section names`: glossary.html#section-names .. _`section reference`: glossary.html#section-reference .. _`section references`: glossary.html#section-references .. _tangling: glossary.html#tangling .. _tree: glossary.html#tree .. _untangling: glossary.html#untangling

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: commands.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: scripting.html
.. _`Chapter 7\: Scripting Leo with Python`: scripting.html .. _`Chapter 9\: History of Leo`: history.html .. _`rst3 plugin`: glossary.html#rst3-plugin .. _`Specifying settings`: commands.html#specifying-settings

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: scripting.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: history.html
.. Relative links...

.. _`Chapter 7\: Scripting Leo with Python`: scripting.html .. _`Chapter 8\: Customizing Leo`: customizing.html .. _`Chapter 10\: Theory of Operation`: theory.html

.. _`Chapter 15\: Controlling Syntax Coloring`: coloring.html .. _`Chapter 16\: Debugging with Leo`: debuggers.html .. _`Chapter 17\: Using ZODB with Leo`: zodb.html .. _`Chapter 18\: Leo and Emacs`: emacs.html .. _`Chapter 19\: Embedding Leo with the leoBridge Module`: leoBridge.html .. _`Chapter 20\: Unit testing with Leo`: unitTesting.html .. _`Chapter 21\: ILeo - the IPython bridge`: IPythonBridge.html .. Absolute links..

.. _OPML: http://en.wikipedia.org/wiki/OPML

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: customizing.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: theory.html
.. _`Chapter 9\: History of Leo`: history.html .. _`Chapter 11\: White Papers`: whitepapers.html

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: history.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: whitepapers.html
-------------

|back| |leo| |next|
-------------

|back| |leo| |next|
-------------

|back| |leo| |next|
-------------

|back| |leo| |next|
-------------

|back| |leo| |next|
-------------

|back| |leo| |next|
-------------

|back| |leo| |next|
.. Links used in this document...

.. _`Pmw`: http://pmw.sourceforge.net/ .. _run: `Running Leo`_ .. _`run Leo`: `Running Leo`_ .. _`Leo's download page`: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

.. _`associated .leo files with Leo`: `How to associate Leo with .leo files on Windows`_

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: FAQ.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: intro.html
@color

# Puts each sentence on a separate line # Not as useful as I had hoped. The Reformat Paragraph command is better.

@others

splitSentences(c,p)
def splitSentences(c,p):

undoType = 'Split Sentences' head,lines,tail,oldSel,oldYview = c.getBodyLines() s = p.bodyString() if not s.strip(): return

i = 0 ; line = [] ; result = [] ; nl = False while i < len(s): ch = s[i] ; i += 1 ; ch2 = '.' if i < len(s): ch2 = s[i] if ch in ('.',';') and ch2 in (' ','\t','\n'): line.append(ch) r = ''.join(line)+'\n' if nl and ch == '.': r = r + '\n' result.append(r) line = [] ; nl = False while i < len(s): ch2 = s[i] if ch2 == '\n' and ch == '.': nl = True if ch2 in (' ','\t','\n'): i += 1 else: break else: line.append(ch)

result.append(''.join(line)+'\n') # Add the last line. result = ''.join(result) c.updateBodyPane('',result,'',undoType,oldSel,oldYview)
You can run Leo from a Python interpreter as follows::

import leo leo.run() # runs Leo, opening a new outline. leo.go() # runs Leo after reloading all modules. leo.leoOpen(fileName) # runs Leo, reloads all modules, and opens fileName.

Here are some tips that may make running Leo easier:

**Linux** The following shell script will allow you to open foo.leo files by typing leo foo::

#!/bin/sh python <leopath>/leo.py $1

where <leopath> is replaced with the path to the leo directory.

**Windows** If you have `associated .leo files with Leo`_ you may run Leo by double-clicking any .leo file. You can also use a batch file. Put the following .bat file in c:\\Windows::

cd c:\prog\LeoCVS\leo c:\python22\python c:\prog\LeoCVS\leo\leo.py %1

This opens the file specified by the first argument (%1).

The first time you start Leo, a dialog will ask you for a unique identifier. If you are using cvs, use your cvs login name. Otherwise your initials will do. Leo stores this identifier in the file ``.leoID.txt``. Leo attempts to create ``leoID.txt`` in your home directory, then in Leo's config directory, and finally in Leo's src directory. You can change this identifier at any time by editing ``.leoID.txt``.
You can execute all the code in this file. Just select the code you want to execute and run the Execute Script command.

**Important**: Python is finicky about indentation, so you must be careful to select the leading whitespace of the first line.
Understanding this section is *essential*. By default, all iterators discussed below use a *single* position to move through the outline. This is a vital optimization; otherwise Leo would generate one or more position object for each node of a tree traversal. However, it means that it is *useless* to try to capture a position with::

p2 = p # Wrong. p2 will change after this assignment.

Instead, scripts and plugins should use ``p.copy()`` to 'capture' the value of a position::

p2 = p.copy() # Correct: p2 will not change when p changes later.

Another way to solve this problem is to set ``copy=True`` when using an iterator::

d = {} for p in c.allNodes_iter(copy=True): d[p.v.t] = p

This creates a dictionary of (unchanging!) positions, indexed via tnode. **Warning** The positions in this dictionary will become invalid when the outline's structure changes. It would be wrong to save a dictionary like this for use between commands.

Setting the ``copy=True`` argument to iterators is an acceptable strategy for infrequently used scripts; it is not acceptable for heavily used code in Leo's core: it would create huge numbers of positions that would immediately be candidates for garbage collection.

**Important**: 'Confused' scripts work because the ``position`` methods that simulate the old ``vnode`` methods automatically create copies of positions when 'moving' through an outline. Thus, confused scripts generate many more positions than would the equivalent script that uses ``position`` iterators. Such is the price of compatibility.
# Start at the top. b = c.frame.body.bodyCtrl b.mark_set('insert','1.0') b.tag_remove('sel','1.0','end') b.tag_add('sel','1.0','1.0') b.update_idletasks()

# Format until the end. count = 0 # Guard against loops. while count < 100: count += 1 s = p.bodyString() if not s.strip(): break c.reformatParagraph() s2 = p.bodyString()

index = b.index('insert') if b.compare(index,'>=','end-1c'): break
This following information may be of interest to historians. It is not of general enough interest to put in Leo's Users Guide on the web. I am including this mass of detail here to indicate the complexities that were involved in designing Leo's simple-looking mechanisms.
Leo grew out of my efforts to use Donald Knuth's "CWEB system of Structured documentation." I had known of literate programming since the mid 1980's, but I never understood how to make it work for me. In November 1995 I started thinking about literate programming in earnest. Over the holidays I mused about making literate programs more understandable. In January 1996 the fog of confusion suddenly cleared. I summarized my thinking with the phrase, **web are outlines in disguise**. I suspected that outline views were the key to literate programming, but many details remained obscure.
March 5, 1996, is the most important date in Leo's history. While returning from a day of skiing, I discussed my thoughts with Rebecca. During that conversation I realized that I could use the ``MORE`` outliner as a prototype for a "literate outliner." I immediately started work on my first literate outline. It quickly became apparent that outlines work: all my old problems with literate programming vanished. The ``@others`` directive dates from this day. I realized that ``MORE``'s outlines could form the basis for Leo's screen design. Rather than opening body text within the outline, as ``MORE`` does, I decided to use a separate body pane.

I hacked a translator called ``M2C`` which allowed me to use ``MORE`` to write real code. I would write code in ``MORE``, copy the text to the clipboard in ``MORE`` format, then run ``M2C``, which would tangle the outline into C code. This process was useful, if clumsy. I called the language used in the outline ``SWEB``, for simplified ``CWEB``. Much later Leo started supporting the noweb language.
Throughout 1996 I created a version of Leo on the Macintosh in plain C and the native Mac Toolbox. This was a poor choice; I wasted a huge amount of time programming with these primitive tools. However, this effort convinced me that Leo was a great way to program.

Late in 1997 I wrote a ``Print`` command to typeset an outline. Printing (Weaving) is supposedly a key feature of literate programming. Imagine my surprise when I realized that such a "beautiful" program listing was almost unintelligible; all the structure inherent in the outline was lost! I saw clearly that typesetting, no matter how well done, is no substitute for explicit structure.

In 1998 I created a version of Leo using Apple's YellowBox environment. Alas, Apple broke its promises to Apple developers. I had to start again.
I rewrote Leo for Borland C++ starting in May 1999. Borland C++ was much better than CodeWarrior C, but it was still C++. This version of Leo was the first version to use xml as the format of .leo files. The last version of Borland Leo, 3.12 Final went out the door July 17, 2003.
I attended the Python conference in early 2001. In May of 2000 I began work on an wxWindows version of Leo. This did not work out, but something good did come from this effort. I spent a lot of time adding Python scripting to the wxWindows code and I became familiar with Python and its internals.

I really started to 'get' Python in September 2001. I wrote the white papers at about this time. Python solved *all* my programming problems. I rewrote Leo in Python in about two months! For the first time in my career I was no longer anxious while programming; it simply isn't possible to create bad bugs in Python. The Python version of Leo was the first officially OpenSoftware version of Leo. The first functional version of Leo in Python was 0.05 alpha, December 17, 2001.
I registered the Leo project on SourceForge on March 10, 2003. It is certainly no accident that Leo started a new life shortly thereafter. Prior to SourceForge my interest in Leo had been waning.
In the summer of 2001 I began to consider using sentinel lines in derived files. Previously I had thought that outline structure must be 'protected' by remaining inside .leo files. Accepting the possibility that sentinels might be corrupted opened vast new design possibilities. In retrospect, problems with sentinel almost never happen, but that wasn't obvious at the time! The result of this design was known at first as ``Leo2``. That terminology is extinct. I think of this version as the first version to support ``@file`` and automatic tangling and untangling.
The biggest surprise in Leo's history was the realization it is **much** easier to untangle files derived from ``@file``. Indeed, ``@root`` creates all sorts of problems that just disappear when using ``@file``. The new Python version of Leo became fully operational in early 2002. It was probably about this time that I chose noweb as Leo's preferred markup language. My decision not to support noweb's escape sequences made Leo's read code much more robust.
I spent 2002 taking advantages of Python's tremendous power and safety. Many improvements were at last easy enough to do:

- Nested ``@others`` directives appeared in 3.2. - Unicode support started in 3.3. - @first and @last appeared in 3.7 - @asis and @nosent appeared in 3.8. - Incremental syntax coloring and incremental undo appeared in 3.9. - Paul Paterson created Leo's plugin architecture sometime during this period. Plugins have been a driving force in Leo's development because people can change how Leo works without altering Leo's core. - 3.12 fixed a huge memory leak. - 3.12 Final, the last 3.x version, appeared July 17, 2003.
In late 2002 and throughout 2003 I worked on an entirely new file format. 4.0 final went out the door October 17, 2003 after almost a year intense design work trying to improve error recovery scheme used while reading derived files. In the summer of 2003 I realized that orphan and ``@ignore``'d nodes must be prohibited in ``@file`` trees. With this restriction, Leo could finally recreate ``@file`` trees in outlines using **only** the information in derived files. This made the read code much more robust, and eliminated all the previous unworkable error recovery schemes. At last Leo was on a completely firm foundation.
Leo first used gnx's (global node indices) as a foolproof way of associating nodes in .leo files with nodes in derived files. At the time, there was still intense discussions about protecting the logical consistency of outlines. ``@thin`` was later to solve all those problems, but nobody knew that then.
Leo 4.2 Final went out the door September 20, 2004. This surely is one of the most significant dates in Leo's history:

- This marked the end worries about consistency of outlines and derived files: Leo recreates all essential information from thin derived files, so *there is nothing left in the .leo file to get out of synch*.

- Thin derived files use gnx's extensively. This simplifies the file format and makes thin derived files more cvs friendly.

- A sensational scripting plugin showed how to create script buttons. This has lead to improvements in the Execute Script command and other significant improvements in Unit testing.

- As if this were not enough, 4.2 marked the 'great divide' in Leo's internal data structures. Before 4.2, Leo every node in the outline had its own ``vnode``. This was a big performance problem: clone operations had to traverse the entire outline! 4.2 represents clones by sharing subtrees. Changing Leo's fundamental data structures while retaining compatibility with old scripts was engineering work of which the entire Leo community can be proud. `Chapter 7: Scripting Leo with Python`_ tells how the position class makes this happen. This was a cooperative effort. Kent Tenney and Bernhard Mulder made absolutely crucial contributions. Kent pointed out that it is a ``tnode``, not a ``vnode`` that must form the root of the shared data. Bernhard showed that iterators are the way to avoid creating huge numbers of positions.

Leo 4.2 marked so many significant changes. I often find it hard to remember what life with Leo was like before it.
Leo 4.3 corrected many problems with ``leoConfig.txt``. Instead, Leo gets settings from one or more ``leoSettings.leo files``. This version also introduced a way to changed settings using a settings dialog. However, the settings dialog proved not to be useful (worse, it inhibited design) and the settings dialog was retired in Leo 4.4.
**Important**: Script buttons are easier to use than the script-oriented find/change commands described next. I recommend using script buttons whenever possible. See `Creating script buttons`_. You are not likely to need all the firepower that script-orient find/change commands, but it could save you lots of time for complex jobs.

Leo's find panel contains the ``Script Search`` radio button and the ``Script Change`` checkbox. When the ``Script Search`` radio button is selected Leo treats the contents of the ``Search Text`` as a script to execute whenever any kind of Find command is executed. Similarly, when the ``Script Change`` checkbox is selected Leo treats the context of the ``Change Text`` as a script to execute whenever any kind of Change command is executed.

Script-based find-change turns Leo's Find/Change panel into a platform for running scripts interactively. The script writer need not write code to control interactive searches.

Here's how it works. Leo dedicates ``g.app.searchDict`` for communication between Leo and the search and change scripts. The search and change scripts may also use ``g.app.searchDict`` for communication between themselves. Leo sets ``g.app.searchDict["type"]`` to "find", "change", "findAll" or "changeAll" to indicate the kind of command being executed. Scripts may use all other entries in ``g.app.searchDict`` as they please.

Here is what Leo does when the user presses buttons with ``Script Search`` enable:

``Find and Change, then Find`` buttons Leo executes the find script once. Typically, the find script would traverse the tree and highlight the found text or otherwise indicate to the user that the find operation has succeeded. However, the script can do anything it pleases.

``Find All`` button Leo executes the find script repeatedly until ``g.app.searchDict["continue"]`` evaluates to ``False``. Initially there is no entry for ``g.app.searchDict["continue"]``, so the find script must set ``g.app.searchDict["continue"] = True`` if it wants Leo call it again.

``Change`` button Leo executes the change script once. Typically, the change script would change the selected text. Usually the change script will compute the new value of body text and call ``c.setBodyString(p,newText)`` to make that change permanent. To handle undo, the change script can call ``c.frame.onBodyChanged(v,"Change",oldText=oldText)``.

``Change All`` button Leo executes the change script repeatedly until g.app.searchDict["continue"] evaluates to false.

Most find and change scripts will ignore settings in the Find Panel like "whole word", "pattern match", and "reverse". However, these settings are available to the scripts via ivars such as ``c.whole_word_flag``, etc. if desired.

The ``initScriptFind`` script in ``LeoPy.leo`` makes it easy to set up script based searches:

1. Put the following code in the root of a tree that will contain your script search::

# Initialize Leo's find panel using the named children of this node. import leoGlobals as g. g.initScriptFind("Find script","Change script") # Second argument is optional. # Start searching at the top. c.selectPosition(c.rootPosition())

2. Put the search script in a child node called "Find script" (no quotes).

3. (Optional) Put the change script in a child node called "Change script"

4. Execute the code above. Leo does the following:

- Puts the body of the "Find script" into the find text of Leo's Find/Change dialog. - Puts the body of the "Change script" into the change text of Leo's Find/Change dialog. - Selects the Script Find radio button. - Selects the Script Change checkbox if the change script exists. - Selects the root of the entire outline.

Presto! Leo is ready for a script search. **Note**: you could also consider creating a script button to set up complex find/change scripts.

Here are some ideas for using script find/change.

- Find and change scripts may use Python's re module. For example, the find script could set ``g.app.searchDict["m"]`` to the match object returned by re's match method. The change script would then compute the result, change the text and set the undo info as usual.

- Find and change scripts may operate on data outside any Leo outline. For example, script-find scripts could traverse your file system. Scripts could even pull data from the file system into the outline so that you can see the effects of changes as the scripts operate.
Plugins and other scripts can register event handlers (also known as hooks) with code such as::

leoPlugins.registerHandler("after-create-leo-frame",onCreate) leoPlugins.registerHandler("idle", on_idle) leoPlugins.registerHandler(("start2","open2","command2"), create_open_with_menu)

As shown above, a plugin may register one or more event handlers with a single call to ``leoPlugins.registerHandler``. Once a hook is registered, Leo will call the registered function' at the named **hook time**. For example::

leoPlugins.registerHandler("idle", on_idle)

causes Leo to call ``on_idle`` at "idle" time.

Event handlers must have the following signature::

def myHook (tag, keywords): whatever

- ``tag`` is the name of the hook (a string). - ``keywords`` is a Python dictionary containing additional information. The following section describes the contents of the ``keywords`` dictionary in detail.

**Important**: hooks should get the proper commander this way::

c = keywords.get('c')
The following table tells about each event handler: its name, when it is called, and the additional arguments passed to the hook in the ``keywords`` dictionary. For some kind of hooks, Leo will skip its own normal processing if the hook returns anything *other* than None. The table indicates such hooks with 'yes' in the 'Stop?' column.

**Important**: Ever since Leo 4.2, the ``v``, ``old_v`` and ``new_v`` keys in the keyword dictionary contain *positions*, not vnodes. These keys are deprecated. The ``new_c`` key is also deprecated. Plugins should use the ``c`` key instead.

============================= ======== =================================== ============================= Event name (tag argument) Stop? When called Keys in keywords dict ============================= ======== =================================== ============================= 'after-create-leo-frame' after creating any frame c 'after-redraw-outline' end of tree.redraw c (note 6) 'before-create-leo-frame' before frame.finishCreate c 'bodyclick1' yes before normal click in body c,p,v,event 'bodyclick2' after normal click in body c,p,v,event 'bodydclick1' yes before double click in body c,p,v,event 'bodydclick2' after double click in body c,p,v,event 'bodykey1' yes before body keystrokes c,p,v,ch,oldSel,undoType 'bodykey2' after body keystrokes c,p,v,ch,oldSel,undoType 'bodyrclick1' yes before right click in body c,p,v,event 'bodyrclick2' after right click in body c,p,v,event 'boxclick1' yes before click in +- box c,p,v,event 'boxclick2' after click in +- box c,p,v,event 'clear-all-marks' after clear-all-marks command c,p,v 'clear-mark' when mark is set c,p,v 'close-frame' in app.closeLeoWindow c 'color-optional-markup' yes * (note 7) colorer,p,v,s,i,j,colortag (note 7) 'command1' yes before each command c,p,v,label (note 2) 'command2' after each command c,p,v,label (note 2) 'create-optional-menus' (note 8) c (note 8) 'create-popup-menu-items' in tree.OnPopup c,p,v,event (new) 'destroy-all-global-windows' (note 12) None 'draw-outline-box' yes when drawing +- box tree,p,v,x,y 'draw-outline-icon' yes when drawing icon tree,p,v,x,y 'draw-outline-node' yes when drawing node tree,p,v,x,y 'draw-outline-text-box' yes when drawing headline tree,p,v,x,y 'drag1' yes before start of drag c,p,v,event 'drag2' after start of drag c,p,v,event 'dragging1' yes before continuing to drag c,p,v,event 'dragging2' after continuing to drag c,p,v,event 'enable-popup-menu-items' in tree.OnPopup c,p,v,event 'end1' start of app.quit() None 'enddrag1' yes before end of drag c,p,v,event 'enddrag2' after end of drag c,p,v,event 'headclick1' yes before normal click in headline c,p,v,event 'headclick2' after normal click in headline c,p,v,event 'headrclick1' yes before right click in headline c,p,v,event 'headrclick2' after right click in headline c,p,v,event 'headkey1' yes before headline keystrokes c,p,v,ch (note 13) 'headkey2' after headline keystrokes c,p,v,ch (note 13) 'hoist-changed' whenever the hoist stack changes c 'hypercclick1' yes before control click in hyperlink c,p,v,event 'hypercclick2' after control click in hyperlink c,p,v,event 'hyperenter1' yes before entering hyperlink c,p,v,event 'hyperenter2' after entering hyperlink c,p,v,event 'hyperleave1' yes before leaving hyperlink c,p,v,event 'hyperleave2' after leaving hyperlink c,p,v,event 'iconclick1' yes before single click in icon box c,p,v,event 'iconclick2' after single click in icon box c,p,v,event 'iconrclick1' yes before right click in icon box c,p,v,event 'iconrclick2' after right click in icon box c,p,v,event 'icondclick1' yes before double click in icon box c,p,v,event 'icondclick2' after double click in icon box c,p,v,event 'idle' periodically (at idle time) c 'init-color-markup' (note 7) colorer,p,v (note 7) 'menu1' yes before creating menus c,p,v (note 3) 'menu2' yes during creating menus c,p,v (note 3) 'menu-update' yes before updating menus c,p,v 'new' start of New command c,old_c,new_c (note 9) 'open1' yes before opening any file c,old_c,new_c,fileName (note 4) 'open2' after opening any file c,old_c,new_c,fileName (note 4) 'openwith1' yes before Open With command c,p,v,openType,arg,ext 'openwith2' after Open With command c,p,v,openType,arg,ext 'recentfiles1' yes before Recent Files command c,p,v,fileName,closeFlag 'recentfiles2' after Recent Files command c,p,v,fileName,closeFlag 'redraw-entire-outline' yes start of tree.redraw c (note 6) 'save1' yes before any Save command c,p,v,fileName 'save2' after any Save command c,p,v,fileName 'scan-directives' in scanDirectives c,p,v,s,old_dict,dict,pluginsList (note 10) 'select1' yes before selecting a position c,new_p,old_p,new_v,new_v 'select2' after selecting a position c,new_p,old_p,new_v,old_v 'select3' after selecting a position c,new_p,old_p,new_v,old_v 'set-mark' when a mark is set c,p,v 'show-popup-menu' in tree.OnPopup c,p,v,event 'start1' after app.finishCreate() None 'start2' after opening first Leo window c,p,v,fileName 'unselect1' yes before unselecting a vnode c,new_p,old_p,new_v,old_v 'unselect2' after unselecting a vnode c,new_p,old_p,old_v,old_v '\@url1' yes before double-click @url node c,p,v,url (note 5) '\@url2' after double-click @url node c,p,v(note 5) ============================= ======== =================================== =============================

**Notes**:

1. 'activate' and 'deactivate' hooks have been removed because they do not work as expected.

2. 'commands' hooks: The label entry in the keywords dict contains the 'canonicalized' form of the command, that is, the lowercase name of the command with all non-alphabetic characters removed. Commands hooks now set the label for undo and redo commands 'undo' and 'redo' rather than 'cantundo' and 'cantredo'.

3. 'menu1' hook: Setting ``g.app.realMenuNameDict`` in this hook is an easy way of translating menu names to other languages. **Note**: the 'new' names created this way affect only the actual spelling of the menu items, they do *not* affect how you specify shortcuts settings, nor do they affect the 'official' command names passed in ``g.app.commandName``. For example::

app().realMenuNameDict['Open...'] = 'Ouvre'.

4. 'open1' and 'open2' hooks: These are called with a keywords dict containing the following entries:

- c: The commander of the newly opened window. - old_c: The commander of the previously open window. - new_c: (deprecated: use 'c' instead) The commander of the newly opened window. - fileName: The name of the file being opened.

You can use ``old_c.currentPosition()`` and ``c.currentPosition()`` to get the current position in the old and new windows. Leo calls the 'open1' and 'open2' hooks only if the file is not already open. Leo will also call the 'open1' and 'open2' hooks if: a) a file is opened using the Recent Files menu and b) the file is not already open.

5. '\@url1' and '\@url2' hooks are only executed if the 'icondclick1' hook returns None.

6. These hooks are useful for testing.

7. These hooks allow plugins to parse and handle markup within doc parts, comments and Python ``'''`` strings. Note that these hooks are *not* called in Python ``'''`` strings. See the color_markup plugin for a complete example of how to use these hooks.

8. Leo calls the 'create-optional-menus' hook when creating menus. This hook need only create new menus in the correct order, without worrying about the placement of the menus in the menu bar. See the plugins_menu and scripts_menu plugins for examples of how to use this hook.

9. The ``New`` command calls 'new'. The 'new_c' key is deprecated. Use the 'c' key instead.

10. ``g.scanDirectives`` calls 'scan-directives' hook. ``g.scanDirectives`` returns a dictionary, say d. d.get('pluginsList') is an a list of tuples ``(d,v,s,k)`` where:

- d is the spelling of the @directive, without the leading @. - v is the vnode containing the directive, _not_ the original vnode. - s[k:] is a string containing whatever follows the @directive. k has already been moved past any whitespace that follows the @directive.

See the add_directives plugins directive for a complete example of how to use the 'scan-directives' hook.

11. ``g.app.closeLeoWindow`` calls the 'close-frame' hook just before removing the window from ``g.app.windowList``. The hook code may remove the window from ``app.windowList`` to prevent ``g.app.closeLeoWindow`` from destroying the window.

12. ``g.app.destroyAllGlobalWindows`` calls the 'destroy-all-global-windows' hook. This hook gives plugins the chance to clean up after themselves when Leo shuts down.

13. New in Leo 4.4: Leo calls the 'headkey1' and 'headkey2' hooks only when the user completes the editing of a headline, and ch is always '\r', regardless of platform.
A **plugin** is a Python file that appears in Leo's plugin directory. Plugins modify how Leo works. With plugins you can give Leo new commands, modify how existing commands work, or change any other aspect of Leo's look and feel. ``leoPlugins.leo`` contains all of Leo's official plugins. Studying this file is a good way to learn how to write plugins.

You **enable** plugins using @enabled-plugins nodes in leoSettings.leo or myLeoSettings.leo. For more details, see the @enabled-plugins node in leoSettings.leo. Leo imports all enabled plugins at startup time. Plugins become **active** if importing the plugin was successful.

Writing plugins is quite similar to writing any other Leo script. See `Chapter 7\: Scripting Leo with Python`_. In particular:

1. Plugins can use any of Leo's source code simply by importing any module defined in leoPy.leo.

2. Plugins can register event handlers just like any other Leo script. For full details, see the section called `event handlers`_ in Leo's scripting chapter.

The rest of this chapters discusses topics related specifically to plugins.
Creating a script button should be your first thought whenever you want to automate any task. The scripting plugin, ``mod_scripting.py``, puts two buttons in the icon menu, a pink ``Run Script`` button and a yellow ``Script Button`` button. The ``Run Script`` button does the same thing as the ``Execute Script`` command. The ``Script Button`` button is the interesting one. It creates a button, confusingly called a **script button** in the icon area. A script button executes a script when you push it.

Suppose node N is selected. When you press the ``Script Button`` button a new (pink) script button is created. The name of the new button is N's headline text. The script associated with the new button is N's body text. Now whenever you press the new button, N's script is executed on the **presently** selected node. Script buttons are extraordinarily useful. In effect, each script button defines an instant command! For example, sometimes my fingers get tired of saving a file. I simply put ``Save`` in a node's headline and ``c.save()`` in the body text. I hit the ``Script Button`` button and I get a new button called ``Save`` that will save the outline when I press it.

Here's a more interesting example. The following script searches the present node and its ancestors looking for an ``@rst`` node. When such a node is found the script calls the `rst3 plugin`_ to format it. I don't have to select the actual ``@rst`` node; I can select any of its children::

import leoPlugins rst3 = leoPlugins.getPluginModule('rst3') if rst3: # already loaded. controller = rst3.controllers.get(c) if controller: for p in p.self_and_parents_iter(): if p.headString().startswith('@rst '): controller.processTree(p) break else: # Just load the plugin. rst3 = leoPlugins.loadOnePlugin('rst3',verbose=True) if rst3: g.es('rst3 loaded') rst3.onCreate('tag',{'c':c}) else: # Ask to be removed. g.app.scriptDict['removeMe'] = True

**Notes**:

- The scripting plugin pre-defines the ``c``, ``g`` and ``p`` symbols just as the ``Execute Script`` command does.

- By default a script button executes the **present** body text of the node that original created the script button. This is very handy: you can modify a script button's script at any time without having to recreate the script button.

- You can delete any script button by right-clicking on it.

- On startup, the scripting plugin scans the entire .leo file and creates a script button for every node whose headline starts with ``@button scriptName``. **Warning**: this is indeed a security risk of the kind discussed later. This feature can be disabled by setting ``atButtonNodes = True`` at the start of ``mod_scripting.py``.
There are many problems with pdf at present.

@ignore
Leo (and other programs) often send more detailed error messages to ``stderr``, the output stream that goes to the console window. In Linux and MacOS environments, python programs normally execute with the console window visible. On Windows, can run Leo with the console window visible by associating .leo files with ``python.exe`` *not* ``pythonw.exe``. For full instructions about how to do this, see `Associating Leo with .leo Files`_.
Leo 4.3.2 beta 1 September 10, 2005

To learn about Leo, see: http://webpages.charter.net/edreamleo/intro.html

The highlights of 4.3.2: -----------------------

- Improved Leo's documentation: - A tutorial introduction to Leo: http://webpages.charter.net/edreamleo/intro.html - A 5-minute guide to programming with Leo: http://webpages.charter.net/edreamleo/intro.html#quick-start-for-programmers

- The new rst3 plugin creates .html and .tex files from reStructuredText embedded in Leo files. Any node of the source outline may contain options for the rst3 plugin, which makes this plugin much more useful and flexible than the previous rst plugins. All of Leo's documentation was created using this plugin from sources in LeoDocs.leo. For full documentation for rst3 see: http://webpages.charter.net/edreamleo/rstplugin3.html.

- The spellpyx (spell checking) plugin is now much easier to use.

- The vim and openWith plugins now use Python's subprocess module if it is present.

- Improved the Pretty Printing command.

- The usual assortment of bug fixes.
Here is a summary of the changes:

- General: All chapters created with rst3 plugin. This ensures a uniform look. The source is in LeoDocs.leo. Removed all references to older versions of Leo, except when discussing old file formats in the Appendices. Corrected all text so it discusses present version.

- rst3 plugin itself: Correct bug that caused chapters to be formatted differently when processing multiple @rst trees.

- rst3 button in LeoDocs.leo: The script first looks *up* the tree, looking for an @rst node. If found, it processes just that tree. If not found, it processes all @rst nodes *below* the originally selected node. The button is now much more convenient to use.

- Preface: Shorter, no history. No longer a dead end.

- What People are Saying About Leo: No longer a dead end.

- FAQ: Reorganized, simplified, revised. Added entries for running Leo in a console window and debugging docutils. Improved entry for using cvs.

- Chapter 1: Installation: Now the first chapter. Revised.

- Chapter 2: Tutorial: Completely rewritten. Like Python's tutorial, this chapter contains everything a beginner needs to understand and use Leo. The `Quickstart for programmers` section is the heart of this chapter. All terms used have links either to their definition in the tutorial or in the Glossary. Newbies should be able to digest this chapter easily. This chapter should make Leo comprehensible to many more people.

- Chapter 3: Using Outlines: Revised per general remarks above.

- Chapter 4: Writing Programs in Leo. Completely rewritten. The old chapter was an embarrassment. The new chapter is a reference guide, properly organized as such. The introduction warns newbies away.

- Chapter 5: Using Leo's Commands. 'Minor' revisions and corrections create a substantially better result.

- Chapter 6: Leo and literate programming: Reformatting helps. New words about rST markup and other improvements over traditional LP.

- Chapter 7: Scripting Leo with Python: Rewritten, simplified, updated and corrected. The sources in LeoDocs.leo are directly executable. rST sources use literal blocks instead of code-blocks so that the sources are simplified. (Important when executing examples). Properly discusses positions, including 'supremely important' section on copying positions.

- Chapter 8: Customizing Leo. Heavily revised. Discusses leoSettings.leo, not leoConfig.txt. Security warnings are more reasonable. Section on script buttons. Rewrote section on uA's (Adding extensible attributes to nodes and .leo files).

- Chapter 9: History of Leo. Rewritten. Much shorter and more useful. Discusses the major milestones, concentrating on explaining the major differences between versions. Gone are details of how discoveries came to be. They are in LeoPostings.leo, which will be included in the distribution.

- Chapter 10: Theory of Operation. Largely rewritten. Discusses positions properly. Omits discussion of how clones were implemented before 4.2.

- Chapter 11: White Papers. A new chapter. This is a slightly-edited version of writing that had been buried in the appendices.

- Appendices. Heavily revised and reformatted. Rewrote sections on file formats.

- Glossary: A separate chapter. All terms have links to their definition. All definitions are rST targets so other chapters may refer to them. Added several new entries.
http://sourceforge.net/forum/message.php?msg_id=3218558
The fix was to add an entry of 'unknown' state to state_dict. This fixes the crash by brute force, but may not be strictly correct. However, this is pretty much moot: we shall soon be moving to the new colorizer.
The code gets c = keywords.get('c') in several places. The protection is to return if c is None. This affects the following files: plugins_menu.py, pluginsTest.py, plugin_manager.py
http://sourceforge.net/forum/message.php?msg_id=3231597

test.leo had some non-@ignore'd @thin nodes for files not in the distribution.

- Only files used by unit tests should be on cvs and the distribution. - test\unittest\batchTest.py and test\unittest\errorTest.py were already on cvs. - Added these files to the distribution.

- Other test files should be distributed in @ignore nodes.

- Leo's distribution checklist now has an item to check that the distributed test.leo can be opened without errors.
Calling print directly is dangerous: it will fail for unicode characters.
The new Pretty Print code has the following improvements:

- Strip trailing blanks in get. - Many improvement to doOp. - Improved DoMultiline: - Added special case logic to ensure '#' is preceded by space except at start of line. - Added blank after multi-line string if needed. - Added lastName token for special-case handling depending on previous token. - No change to put, putArray or doName.
-------------

|back| |leo| |next|
-------------

|back| |leo| |next|
Any .leo file may contain an ``@settings`` tree, so settings may be different for each commander. Plugins and other scripts can get the value of settings as follows::

format_headlines = c.config.getBool('rst3_format_headlines') g.es('format_headlines',format_headlines)

The ``c.config`` class has the following getters. See the ``configSettings`` in ``leoCommands.py`` for details::

c.config.getBool(settingName,default=None) c.config.getColor(settingName) c.config.getDirectory(settingName) c.config.getFloat(settingName) c.config.getInt(settingName) c.config.getLanguage(settingName) c.config.getRatio(settingName) c.config.getShortcut(settingName) c.config.getString(settingName)

These methods return None if no setting exists. The getBool 'default' argument to getBool gives the value to be returned if the setting does not exist.

You can set any *existing* item in an ``@settings`` tree with ``c.config.set(p,setting,val)``. For example::

for val in (False,True): c.config.set(p,'rst3_format_headlines',val) format_headlines = c.config.getBool('rst3_format_headlines') g.es('format_headlines',format_headlines)

``c.config.set`` does not change the ``@settings`` tree; it simply changes the values returned by the getters.
This is a known bug in Tk that prevents this on Windows. The obvious Tk code causes a hard crash in the Python dll: it's the only time Leo has taken such a hard crash. The ``UniversalScrolling`` plugin is an attempt at a workaround.

Scrolling with the mouse wheel may be possible on Linux. See the code in createTkTreeCanvas in leoTkinterFrame.py
See http://webpages.charter.net/edreamleo/rstplugin3.html for full documentation of this plugin.

The rst3 plugin creates output files from Leo outlines containing reStructuredText (rST) ReStructuredText is a simple and powerful text formatting markup language. Outlines are a natural way to organize rST (or any text).

This plugin adds the Write Restructured Text command to Leo's Edit menu. The Write Restructured Text command searches the selected outline looking for rst root nodes whose headline have the form @rst <filename>. The plugin then creates the named file in various ways depending which rst3 options are in effect.

By default, the rst3 plugin creates rST headings automatically from outlines, so the higher-level nodes in the outline correspond to higher-level sections in the output. Creating rST headings automatically relieves you from one of the most tedious chores in creating rST markup.

To use this plugin effectively, Python's docutils module must be installed. The rst3 plugin will use the SilverCity syntax coloring package if it installed.

This plugin sends .htm, .html or .tex files to the docutils module for further processing. Docutils generates HTML files or LaTeX files depending on the file's extension. HTML files generated by docutils refer to three .css (cascading style sheet) files that should exist in the same directory as the generated HTML file. You can control the formatting of the HTML file by altering these .css files.
This plugin now allows quotes within words, but strips quotes and other cruft from the beginning and end of words. As a result, using the spellpyx spell checker is much easier than before.

Leo's extensions folder now contains aspell23.pyd and aspell24.pyd. These are Python dll's compiled for Python 2.3 and 2.4 respectively. You must rename one of these files to be aspell.pyd and move aspell.pyd to the aspell folder. For more details, see the installation nodes in the docstring for the spellpyx plugin.
- Fixed bug with non-unicode characters in file name

http://sourceforge.net/forum/message.php?msg_id=3224635

Leo crashed try to read .leo files whose name contained non-ascii characters.

- Fixed bug with non-unicode characters in settings value

http://sourceforge.net/forum/message.php?msg_id=3222750

Leo crashed try to write settings whose values contained non-ascii characters.

- Fixed bug tangling sections with non-unicode characters.

http://sourceforge.net/forum/message.php?msg_id=3307318
These plugins now use Python's subprocess module if it is present. The subprocess module comes standard with Python 2.4. For Linux systems, Leo will use subprocess.py in Leo's extensions folder if necessary.

For Windows systems you can install Python's subprocess module in Python 2.2 or 2.3 as follows:

- Go to http://www.effbot.org/downloads/#subprocess

- Download and execute one of the following installers, depending on your version of Python: subprocess-0.1-20041012.win32-py2.3.exe subprocess-0.1-20041012.win32-py2.2.exe

This installer installs the subprocess sources and also _subprocess.pyd in Python's site-packages folder.
@language rest
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. August 30, 2005

|back| |leo| |next|

########################## Chapter 12: Plugins ##########################

This chapter discusses the plugins contained in leoPlugins.leo. These plugins are part of Leo's official distribution. `Chapter 13: Writing Plugins`_ tells how to write plugins.

The scripting plugin (``mod_scripting.py``) deserves special mention. This plugin lets you create **script buttons** in a matter of seconds. See `Creating script buttons`_. Script buttons are extraordinarily useful. Try them, you'll be instantly hooked.

.. contents::
.. External links...

.. _docutils: http://docutils.sourceforge.net .. _LaTeX: http://www.latex-project.org/ .. _reStructuredText: http://docutils.sourceforge.net/rst.html .. _SilverCity: http://silvercity.sourceforge.net

.. Relative links...

.. _`Specifying settings`: customizer.html#specifying-settings .. _`Chapter 8\: Customizing Leo`: customizing.html .. _`Chapter 13\: Writing Plugins`: writingPlugins.html .. _`Creating script buttons`: scripting.html#creating-script-buttons

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: whitepapers.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: writingPlugins.html
This plugin adds a menu item under the File->Import menu to import Cisco configuration files. The plugin will:

1) Create a new node, under the current node, where the configuration will be written. This node will typically have references to several sections (see below).

2) Create sections (child nodes) for the indented blocks present in the original config file. These child nodes will have sub-nodes grouping similar blocks (e.g. there will be an 'interface' child node, with as many sub-nodes as there are real interfaces in the configuration file).

3) Create sections for the custom keywords specified in the customBlocks[] list in importCiscoConfig(). You can modify this list to specify different keywords. DO NOT put keywords that are followed by indented blocks (these are taken care of by point 2 above). The negated form of the keywords (for example, if the keyword is 'service', the negated form is 'no service') is also included in the sections.

4) Not display consecutive empty comment lines (lines with only a '!').

All created sections are alphabetically ordered.
Supports new Leo directives.
This plugin manages BibTeX files with Leo. Create a bibliographic database by putting ``@bibtex filename`` in a headline. Entries are added as nodes, with ``@entrytype key`` as the headline, and the contents of the entry in body text. The plugin will automatically insert a template for the entry in the body pane when a new entry is created (hooked to pressing enter when typing the headline text). The templates are defined in dictionary ``templates`` in the \<\<globals\>\> section, by default containing all required fields for every entry.

The file is written by double-clicking the node. Thus the following outline::

-@bibtex biblio.bib +@book key author = {A. Uthor}, year = 1999

will be written in the file 'biblio.bib' as::

@book{key, author = {A. Uthor}, year= 1999}

Strings are defined in ``@string`` nodes and they can contain multiple entries. All ``@string`` nodes are written at the start of the file. Thus the following outline::

-@bibtext biblio.bib +@string j1 = {Journal} +@article AUj1 author = {A. Uthor}, journal = j1 +@string j2 = {Journal2} j3 = {Journal3}

Will be written as::

@string{j1 = {Journal1}} @string{j2 = {Journal2}} @string{j3 = {Journal3}}

@article{AUj1, author = {A. Uthor}, journal = j1}

No error checking is made on the syntax. The entries can be organized under nodes--if the headline doesn't start with '@', the headline and body text are ignored, but the child nodes are parsed as usual. BibTeX files can be imported by creating an empty node with ``@bibtex filename`` in the headline. Double-clicking it will read the file ``filename`` and parse it into a ``@bibtex`` tree. No syntax checking is made, ``filename`` is expected to be a valid BibTeX file.
This plugin is enhances the EditAttributes.py plugin. It puts a command in Outline called ConceptualSort. This will prompt you for a concept to sort by. This gives the user some more flexibility in how they want to arrange their nodes. Nodes without the attribute in question go to the bottom of the sort. The user can:

- Select which attribute he wants to sort on by clicking on the Attribute box.

- Select the type of sort he wants by clicking on the radio buttons:

- Normal. - Reversed. Like normal but the results are reversed. - Used defined. For advanced users. The text box is where a user can type in their own python code to sort the nodes-attributes. There is no need for a def. That gets appended to the beginning of the code. It prototype looks like::

def( a, b, att ):

where a and b are nodes and att is dictionary of the nodes and the respective value of the selected attribute. There is no need to indent on the first level since indentation is added at compile time.
Leo plugin that permits the definition of actions for double-clicking on file nodes. Double-clicking in a ``@file`` node writes out the file if changes have been made since the last save, and then runs a script on it, which is retrieved from the outline. Scripts are located in a node whose headline is FileActions. This node can be anywhere in the outline. If there is more than one such node, the first one in outline order is used. The children of that node are expected to contain a file pattern in the headline and the script to be executed in the body. The file name is matched against the patterns (which are Unix-style shell patterns), and the first matching node is selected. If the filename is a path, only the last item is matched. Execution of the scripts is similar to the ``Execute Script`` command in Leo. The main difference is that the namespace in which the scripts are run contains two elements:

- ``filename``, which contains the filename from the ``@file`` directive.

- ``shellScriptInWindow``, a utility function that runs a shell script in an external windows, thus permitting programs to be called that require user interaction

File actions are implemented for ``@file`` nodes and all its variants (``@file-nosent``, ``@thin``, etc.). There is also a new node type ``@file-ref`` for referring to files purely for the purpose of file actions, Leo does not do anything with or to such files.
A Leo Plugin that adds Group commands functionality. Restrictions currently apply to using Leo with a Tk front end. There are several commands in this plugin:

- Mark Node: marks a node for further operations such as copying, cloning and moving.

- Mark Spot: marks a node as the place where group operations are to target.

- Operate On Marked: moves lassoed nodes to the spot where the roundup node is placed. Clones are maintained.

- Clear Marked: unmarks all marked nodes and removes the roundup node.

- Transfer Lassoed Nodes: this is a menu for inter-window communication. The windows must all be spawned from the same Leo instance. It allows the user to move all node marked for copying and moving from another window to this one.
Creates new nodes containing parameterized section references.
This plugin allows Leo to read a complete directory's outline into a Leo's Outline. Directories are converted into headlines and files names are listed into the bodies.
Timestamp all save operations to show when they occur.
Modify the way exported outlines are displayed.
A plugin that helps customize pretty printing. It creates a do-nothing subclass of the default pretty printer. To customize, simply override in this file the methods of the base prettyPrinter class in leoCommands.py. You would typically want to override putNormalToken or its allies. Templates for these methods have been provided. You may, however, override any methods you like. You could even define your own class entirely, provided you implement the prettyPrintNode method.
A plugin to schedule commands for later execution. It's provides the ability to issue commands at a future time and to write messages that will be displayed at a later time. To record commands You goto Schedule and choose begin recording. Then you jump to the nodes and select the commands you want issued on them. This process is ended with the end recording option. A dialog pops up. You can then click on the individual commands and set the time for execution. To set the execution time for all, enter a value and hit set_all. All times must be in the form hh:mm. For example I want to issue a save command for 5:00 PM. I would do so by using the value 17:00. The Schedule Message is simple. There is a Text box to enter the message and a Entry to place the time. View Queue will summon a view of The Queue. This dialog will show the commands that have been enqueued. There is also the option to Cancel out any scheduled commands/messages.
This plugin lets you add customizable templates to an outline. Templates are like any other node except that the plugin replaces %s in the body text by values that you specify when using template. Templates may have section references; this plugin uses Leo's ``@nosent`` write machinery to create one string out of possibly many nodes. This plugin requires the simplified atFile write code that is new in 4.2.1.

This plugin creates two buttons in Leo's icon area:

- The '%s' button marks or unmarks a node as a template. A %s symbol will appear to the left of the node when it is marked as a template.

- The '----> %s' button brings up a dialog that shows you the template text and asks you to specify the value for all %s instances. Dismissing this dialog inserts the template as the first child of the node, and creates a section reference in the node that references the template.

If a template does not have a '%s' in it, then the templates plugin just adds the text as a node. Templates once marked are stored across sessions. Do not put a template in a thin file, as your template mark will be erased between sessions.

This plugin adds **date nodes** (nodes with dates as their headlines) to the current outline. Date nodes may be added one at a time, a month's-worth at a time, or a year's-worth at a time. The format of the headlines is configurable in the ini file.
A plugin to store Leo trees in anydbm files. Note: there isn't such a thing as an anydbm file: it's whatever the anydbm module uses. Under Outline, there is an option called ``Library``. This will open a dialog with a list of the trees that you have saved. You can insert trees stored in the library, remove them and add trees to the library. Be aware of unicode, any characters outside of the ascii set gets turned into a ?. I found this problem in storing some trees from Edward's Leo outline. Id like it to be able to store unicode, but that may require a more specific db background, than anydbm. Also note, that your library files may not be OS independent. If your python distribution does not have the backing db on another machine, it will not be able to open your library. This should help people develop templates that they want to reuse between Leo projects. For example, Id like a template of many Java interfaces to be easily accessible.
Autosave the Leo document every so often. The time between saves is given in seconds in autosave.ini.
This plugin puts the View Table command in the Outline menu. This command checks the current node using the csv (comma separated values) mods Sniffer. It tries to determine the format that is in the nodes data. If you had excel data in it, it should be able to determine its excel data. It then creates a dialog with the data presented as in a table for the user to see it. Requires Pmw and the tktable widget at http://sourceforge.net/projects/tktable.
A plugin to test import problems.
Dump Python globals at startup.
Enable debugging and tracing for Python's garbage collector.
Trace changes to Leo's objects at idle time.
Trace keystrokes in the outline and body panes.
Trace the most common hooks, but not key, drag or idle hooks.
The dyna_menu plugin is a remarkable body of work by 'e'. This plugin creates a dyna_menu menu from which you can execute commands. You may download the latest version at: http://rclick.netfirms.com/dyna_menu.py.html
Synchronizes ``@folder`` nodes with folders. If a node is named ``@folder path_to_folder``, the content (filenames) of the folder and the children of that node will be sync. Whenever a new file is put there, a new node will appear on top of the children list (with mark). So that I can put my description (i.e., annotation) as the content of that node. In this way, I can find any files much easier from leo. Moreover, I add another feature to allow you to group files(in leo) into children of another group. This will help when there are many files in that folder. You can logically group it in leo (or even clone it to many groups), while keep every files in a flat/single directory on your computer.
Executes commands in nodes whose body text starts with ``@produce``. To use, put in the body text of a node::

@produce javac -verbose Test.java

To execute, you goto Outline and look at Produce. Choose Execute All Produce or Execute Tree Produce. The Tree does the current Tree, All does the whole Outline. Executing will fire javac, or whatever your using. ``@produce`` functions as a directive. After executing, a log file/node is created at the top of the Outline. Any output, even error messages, should be there. It executes in a hierarchal manner. Nodes that come before that contain ``@produce`` go first. I'm hoping that this orthogonal to ``@run`` nodes and anything like that. Its not intended as a replacement for make or Ant, but as a simple substitute when that machinery is overkill. **Warning**: trying to execute a non-existent command will hang Leo.
A plugin that supports ``@clip``, ``@view`` and ``@strip`` nodes.

- Selecting a headline containing ``@clip`` appends the contents of the clipboard to the end of the body pane.

- Double clicking the icon box of a node whose headline contains ``@view <path-to-file>`` places the contents of the file in the body pane.

- Double clicking the icon box of a node whose headline contains ``@strip <path-to-file>`` places the contents of the file in the body pane, with all sentinels removed.

This plugin also accumulates the effect of all ``@path`` nodes.
This plugin allows the user to import binary data and store it in Leo as a base64 string. This plugin adds ``Import base64`` and ``Export base64`` commands to the Import menu and adds the 'View base64' command to the outline menu. The Import base64 command creates a new node with the headline::

@base64 <filename>

The body of this node will kill the colorizer, add some info on the original file and create a section reference to the payload node, which contains the data. The Export base64 command asks for a location to place the file. The plugin checks that the structure of the base64 node is what it expected, basically what an import operation creates. If Ok, it will write the file to the selected directory. The View base64 command brings up a Pmw Dialog that displays the data as a PhotoImage. This currently only supports formats recognized by the PhotoImage class. This would be the .gif format. This functionality may be enhanced in the future by PIL to support more image types. Depending on the size of the image, you may have to scroll around to see it. For example, a leo clone icon will require scrolling to find. Id like to change this in the future.
A Leo plugin that adds quick utility commands through a pop-up menu. To summon Menu, type control-space. To unsummon, Right Click.

1. Movement. If a node has ancestors,siblings or children a menu option will appear offering the user the ability to jump to the node from the current node. This is an improvement over moving one node at a time with the keyboard commands.

2. Inserting text. These menus offer the current language keywords, the directives the body recognizes and any ``@file`` type headline directives. It offers the new user easy access to the different directives and ways to write a file.

3. Moving Nodes(experimental). You can quickly move a node to its parent's parent or after a sibling, if they exist.
This plugin allows you to associate information with nodes. This information is organized around "labels", which is are just strings and freely chosen by the user. The plugin allows you to create such a label quickly for each marked node, and to mark all nodes which have a certain label. Labels can be converted to subnodes, and vice versa. This facility allows you to add additional information for each label. You can create clones for each node which has a label. These clones are created as children of the current node. This last facility can be used to create clones for each node which has been found or changed by the standard search/replace dialog:

- Delete all marks. - Do a "find all" / "change all". - Convert the marks to a label. - Run the "Clone label subnodes" command.

Finally, if you read a derived file, and the content of a node changes, the previous content is available under the label "before change:"
A plugin to create and update ``@read-only`` nodes. I wanted to have the ability to import files in "read-only" mode, that is, in a mode where files could only be read by leo (not tangled), and also kept in sync with the content on the drive. The reason for this is for example that I have external programs that generate resource files. I want these files to be part of a leo outline, but I don't want leo to tangle or in any way modify them. At the same time, I want them to be up-to-date in the leo outline. This plugin has the following characteristics:

- It reads the specified file and puts it into the node content.

- If the ``@read-only`` directive was in the leo outline already, and the file content on disk has changed from what is stored in the outline, it marks the node as changed and prints a "changed" message to the log window; if, on the other hand, the file content has *not* changed, the file is simply read and the node is not marked as changed.

- When you write a ``@read-only`` directive, the file content is added to the node immediately, i.e. as soon as you press Enter (no need to call a menu entry to import the content).

- If you want to refresh/update the content of the file, just edit the headline and press Enter. The file is reloaded, and if in the meantime it has changed, a "change" message is sent to the log window.

- The body text of a ``@read-only`` file cannot be modified in leo.

The syntax to access files in ``@read-only`` via ftp/http is the following::

@read-only http://www.ietf.org/rfc/rfc0791.txt @read-only ftp://ftp.someserver.org/filepath

If FTP authentication (username/password) is required, it can be specified as follows::

@read-only ftp://username:password@ftp.someserver.org/filepath
Runs a program and interface Leo through its input/output/error streams. Double clicking the icon box whose headlines are ``@run 'cmd args'`` will execute the command. There are several other features, including ``@arg`` and ``@input`` nodes.

The run_nodes.py plugin introduce two new nodes that transform leo into a terminal. It was mostly intended to run compilers and debuggers while having the possibility to send messages to the program.

- Double clicking on the icon of an node whose headline is::

@run <command> <args>

will launch <command> with the given arguments. It will also mark the node. # Terminates the argument list. ``@run # <comment>`` is also valid.

- ``@in`` nodes are used to send input to the running process. Double clicking on the icon of an ``@in <message>`` node will append a "\n" to <message> and write it to the program, no matter where the node is placed. If no ``@run`` node is active, nothing happens.

- The body text of every child, in which the headlines do not begin with ``@run`` or ``@in``, will be appended to <command>, allowing you to add an infinite number of arguments to <command>.

- The output of the program is written in the log pane (Error outputted in red). When the program exit the node is set unmarked and the return value is displayed...When the enter key is pressed in the body pane of an active ``@run`` node the content of it body pane is written to the program and then emptied ready for another line of input. If the node have ``@run`` nodes in its descendants, they will be launched successively (unless one returned an exit code other than 0, then it will stop there).
Launches (starts) a file given by a headline when double-clicking the icon. Ignores headlines starting with an '@'. Uses the ``@folder`` path if the headline is under an ``@folder`` headline. Otherwise the path is relative to the Leo file.
The AutoTrees plugin is a helper plugin designed to make it very easy to write "handler" plugins to manage dynamic content in Leo outlines. AutoTrees provides:

- Convenient handler base classes which can be specialized for particular uses. - A manager to turn handlers on and off. - A set of example handlers to show the kinds of things that are possible.

AutoTrees doesn't do anything that you cannot do in other ways, but it does provide a consistent way of adding dynamic content. This means that individual plugin writers don't have to rewrite all the same kinds of code each time and also makes it easier to maintain Leo, since it standardizes the way that certain classes of plugin interact with the Leo core. Why use this? I'm a plugin writer and I want to write a plugin to display dynamic content, i.e., content not directly contained in the .leo or derived files, e.g.,

- email messages - news feeds - news groups - documentation - remote files - statistics - file system data - data base records

You can do this as a standard plugin, but as an AutoTrees handler you,

- don't need to write code that interacts with the tree (this is done for you) - get centralized management - can still do everything else you could as a normal plugin
Rebinds up/down arrow keys.
Handles images in body text. Based on work by Gil Shwartz. Brent Burley provided many important insights. See: http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52264
Create a context menu when right-clicking in the body pane.
Autocompletion and calltips plugin.

- ``.`` summons the autocompletion. - ``(`` summons the calltips - ``Escape`` closes either box. - ``Ctrl`` selects an item. - ``alt-up_arrow``, ``alt-down_arrow`` move up or down in the list. The mouse will work for this as well.

This plugin scans the complete outline at startup. You many enable or disable features in autocompleter.ini. This file contains two options under the [ autocompleter ] section::

useauto usecalltips

Setting either to 1 will turn on the feature. 0 means off. If there is a section called [ newlanguages ] it will read each option as a new language for autocompleter to recognize, and compile its value as a regex pattern for the autocompleter system to recognize as a calltip. This has relevance for the .ato system described below. Languages that currently have patterns::

python, java, c++, c, perl

Autocompleter looks in the plugin directory for a directory called autocompleter. If it doesn't find one it will attempt to create this directory. This directory should contain what are called .ato files ( pronounced auto ). Autocompleter will scan each .ato file that has a first part that matches a languages name. For example: python.ato autocompleter recognizes python, and will scan this file. The contents are read with the same mechanism that reads the information in the nodes, so calltip and autocompleter information is added to autocompleter's runtime database. If a new language has been added in the autocompleter.ini file then an .ato file that starts with the new languages name will be recognized and read in. Note, this language needs to be recognizable to Leo. Used correctly an .ato file is a mechanism by which a user can carry autocompletion and calltip information between .leo files/sessions.
Handle coloring for markup in doc parts and Python triple-double-quoted strings.

**Important**:

- This plugin requires that the ``add_directives`` plugin is enabled.

- To color a text with wiki markup the text must be in the range of an ``@markup wiki`` directive.

The currently supported markups are::

''text'' # write text in italics __text__ # write text in bold ~~<color>:text~~ # write text in the color specified by <color> (e.g. blue, grey, etc) {picture file=<filename>} # load the picture indicated by <filename> http://url # URL support: double clicking on the url will open it in the default browser. https://url # URL support: double clicking on the url will open it in the default browser.

- Note 1: italics and bold markups can be nested, e.g.,::

''__text__'' # write text in italics and bold

Just remember to terminate the tags in the order they were opened.

- Note 2: URLs must be terminated by a space.

By default, once the text has been markup up, the actual tags (e.g. ``__`` for bold) are not displayed anymore. You can choose to display them selecting "Show Invisibles" from the Edit menu.
Send output from the Execute Script command to the end of the body pane.
Adds navigation buttons to icon bar.
Automatically add nodes for common tasks.
Add Hoist/De-Hoist buttons to the toolbar.
Adds "Recent" and "Marks" pulldown buttons to the toolbar.
Adds a quick search to Leo's toolbar, along with a "GO" button to do quick searches right from the main Leo window. All the current search options are retained except that "search body text" is explicitly set - mainly because this is by far the most common use case. Pressing <CR> while editing the text automatically does a search. Repeated searches can be done by clicking the "GO" button. The combo box also stores a list of previous searches, which can be selected to quickly repeat a search. When activating a previous search the original search mode is used.
This plugin supports Uniform Node Locators (UNL's). UNL's specify nodes within Leo files. UNL's are not limited to nodes within the present Leo file; you can use them to create cross-Leo-file links. This plugin consists of two parts:

1) Selecting a node shows the UNL in the status line at the bottom of the Leo window. You can copy from the status line and paste it into headlines, emails, whatever.

2) Double-clicking ``@url`` nodes containing UNL's select the node specified in the UNL. If the UNL species in another Leo file, the other file will be opened.

UNL's referring to nodes within the present outline have the form::

headline1-->headline2-->...-->headlineN

where headline1 is the headline of a top-level node, and each successive headline is the headline of a child node. UNL's of the form::

file:<path>#headline1-->...-->headlineN

refer to a node specified in <path> For example, double clicking the following headline will take you to Chapter 8 of Leo's Users Guide::

@url file:c:/prog/leoCvs/leo/doc/leoDocs.leo#Users Guide-->Chapter 8: Customizing Leo

For example, suppose you want to email someone with comments about a Leo file. Create a comments.leo file containing ``@url UNL`` nodes. That is, headlines are ``@url`` followed by a UNL. The body text contains your comments about the nodes in the _other_ Leo file! Send the comments.leo to your friend, who can use the comments.leo file to quickly navigate to the various nodes you are talking about. As another example, you can copy UNL's into emails. The recipient can navigate to the nodes 'by hand' by following the arrows in the UNL.

**Notes**:

- At present, UNL's refer to nodes by their position in the outline. Moving a node will break the link.

- Don't refer to nodes that contain UNL's in the headline. Instead, refer to the parent or child of such nodes.

- You don't have to replace spaces in URL's or UNL's by '%20'.
Cleo allows you to annotate or colour leo outlines based on priority, code archetype, node types or some arbitrary criteria. The annotations and colour coding can play a similar role like that of syntax highlighting. Right-click on the icon area to popup its menu to play with it.
A plugin to leave footprints! This colors the Leo nodes so that the ones you have visited most and most recently will stand out.
A plugin that lets the user to associate text with a specific node. Summon it by pressing button-2 or button-3 on an icon Box in the outline. This will create an attribute editor where the user can add, remove and edit attributes. Since attributes use the underlying tnode, clones will share the attributes of one another.
Maximizes all new windows.
The nodebar plugin adds buttons at the bottom of the tree canvas. The buttons correspond to commands found in the Outline commands. It is intended to speed up a new users ability to use the outline. Experienced users may find value in being able to quickly execute commands they do not use very often.
Send all output to the log pane.
Turns the log into a tabbed component. Other plugins may add tabs. To get a new tab in TabbedLog::

import TabbedLog pane = TabbedLog.getPane(name,c)

- ``pane`` is the pane returned for you to work with. - ``name`` is the name of the tab you want for the pane. - ``c`` is the commander for the leoFrame.
A plugin for searching unknownAttributes (uA's).
A plugin that enables the user to scroll down with a left mouse click and hold, and to scroll up with a right mouse click and hold. Scrolling continues until the user releases the mouse. Originally designed as a workaround for various bugs in Tkinter scrolling, this may actually be superior to wheel scrolling, in that there is little work a user has to do to scroll except to press a button.
This plugin uses Python's urllib module to download files and import them into Leo. It requires the TabbedLog plugin.
Replaces ``Commands.openWithTempFilePath`` so Leo opens temporary files with a filename that begins with the headline text, and located in a ``username_Leo`` subdirectory of the temporary directory. The ``LeoTemp`` prefix is omitted. This makes it easier to see which temporary file is related to which outline node.
Creates an 'extensions' menu with commands to open either an xterm on Linux or a cmd windows/explorer window on win32 in the directory of the current ``@file`` node. This allows quick navigation to facilitate testing and navigating large systems with complex directories.
This plugin creates menu items in the File:Open With menu.

@openwith nodes in @settings trees create menu items. The openWith plugin must be active for these settings to have any effect.

The headline of an @openwith node has the form::

@openwith name = shortcut

name is name of the menu item. shortcut specifies the shortcut used to invoke the menu item. shortcut may be None.

The body text @openwith nodes should contain a single line contain a tuple of the form::

command,arg,ext

For example::

'subprocess.Popen',['pythonw','C:/Python24/Lib/idlelib/idle.pyw'],'.py'

When the user selects this menu item Leo executes command(arg+path) where path is the full path to the temp file. The ext argument specifies the extension of the temp file.

Notes:

- command is a string. Valid values are::

'subprocess.Popen' 'os.system' 'os.startfile' 'os.spawnl' 'os.spawnv' 'exec'

- arg is either a single string or a list of strings.

- ext is a string or None. If None, Leo computes a file extension base on what @language directive is in effect.

- If the .leo file being loaded contains @openwith nodes, the File:Open With menu contains only the items created by those nodes. Similarly, @openwith nodes in myLeoSettings.leo override entries in leoSettings.leo.

- If no @openwith nodes are found anywhere the openWith plugin uses hard-coded tables in the plugin itself.

This plugin will use Python's new subprocess module if it is present. This module comes standard with Python 2.4. For Linux systems, Leo will use subprocess.py in Leo's extensions folder if necessary.

For Windows systems you can install Python's subprocess module in Python 2.2 or 2.3 as follows:

- Go to http://www.effbot.org/downloads/#subprocess

- Download and execute one of the following installers, depending on your version of Python::

subprocess-0.1-20041012.win32-py2.3.exe subprocess-0.1-20041012.win32-py2.2.exe

This installer installs the subprocess sources and also _subprocess.pyd in Python's site-packages folder.
A plugin that communicates with VIM:

- Double clicking on a node's icon opens that node in VIM. You can open nodes in VIM with a single-click if you set useDoubleClick = False. However, that interferes with Leo's dragging logic.

- Leo will update the node in the outline when you save the file in VIM.
This plugin allows you to edit nodes in emacs/xemacs. Depending on your preference, selecting or double-clicking a node will pass the body text of that node to emacs. You may edit the node in the emacs buffer and changes will appear in Leo.
Use commands in the ``Plugins:Word Export:Export`` menu to formats and export the selected outline to a Word document, starting Word if necessary.
Opens any empty file as a minimal .leo file.
Adds #line directives in perl and perlpod programs. Currently supports only perl and perlpod.
Multipath enables the ability to write a file to multiple locations. It acts as a post-write mechanism, a file must be written to the file system for it to work. At this point it is not a replacement for ``@path`` or an absolute path, it works in tandem with them. To use, place ``@multipath`` at the start of a line in the root node or an ancestor of the node. The format is (On Unix systems)::

@multipath /machine/unit/:/machine/robot/:/machine/

It will place a copy of the written file in each of these directories.

There is an additional directive that simplifies common paths, it is called ``@multiprefix``. By typing ``@multiprefix`` with a path following it, before a ``@multipath`` directive you set the beginning of the paths in the ``@multipath`` directive. For example::

@multiprefix /leo #@multipath /plugins

or::

@multiprefix /leo/ @multipath plugins: fungus : drain

copies a file to /leo/plugins /leo/fungus /leo/drain.

The ``@multiprefix`` stays in effect for the entire tree until reset with another ``@multiprefix`` directive. ``@multipath`` is cumulative, in that for each ``@multipath`` in an ancestor a copy of the file is created. These directives must at the beginning of the line and by themselves.
Preprocess ``@file-nosent`` nodes: make sure each subnode ends with exactly one newline, replace all tabs with spaces, and add a newline before class and functions in the derived file.
LeoN is Leo over the Network. LeoN is Collaborative Leo. This is an important project for Leo's long-term development. See leo/doc/LeoN for important research papers that form the basis of this project.
Translate a few menu items into Simplified Chinese 本插件将部分Leo菜单翻译成简体中文 By Zhang Le <ejoy@xinhuanet.com>
Traduit les menus en Français.
Adds pie menus. See http://www.piemenus.com/
Create a Plugins menu and adds an item to the plugin menu for each active plugin. Selecting this menu item will bring up a short About dialog with the details of the plugin. Plugins can create additional menu items by defining functions named ``cmd_XZY``. These will appear in a submenu. If the plugin requires an INI file then a configure menu item will be created which will show an INI file editor. The plugin can define an ``applyConfiguration`` function, which will be called when the configuration changes. Plugins can also define a top level function to be called instead of the default "About" dialog by defining a "topLevelMenu" function in the plugin. This function will be called when the user clicks on the plugin name in the plugins menu, but only if the plugin was loaded properly and registered with ``g.plugin_signon``.

Plugins can define their name by setting the ``__plugin_name__`` property. Plugins can also attempt to select the order they will appear in the menu by defining a ``__plugin_prioriy__``. The menu will be created with the highest priority items first. This behavior is not guaranteed since other plugins can define any priority. This priority does not affect the order of calling handlers. To change the order select a number outside the range 0-200 since this range is used internally for sorting alphabetically.
A plugin to manage Leo's Plugins:

- Enables and disables plugins. - Shows plugin details. - Checks for conflicting hook handlers. - Checks for and updates plugins from the web.
A plugin to automatically update Leo from the current CVS version of the code stored on the SourceForge site. You can view individual files and update your entire Leo installation directly without needing a CVS client.
A plugin to create script buttons and ``@button``, ``@plugin`` and ``@script`` nodes. This plugin puts two buttons in the icon area: a button called ``run Script`` and a button called ``script Button``. The ``run Script`` button is simply another way of doing the Execute Script command: it executes the selected text of the presently selected node, or the entire text if no text is selected. The 'script Button' button creates another button in the icon area every time you push it. The name of the button is the headline of the presently selected node. Hitting this _new_ button executes the button's script.

For example, to run a script on any part of an outline do the following:

1. Select the node containing the script. 2. Press the scriptButton button. This will create a new button, call it X. 3. Select the node on which you want to run the script. 4. Push button X.

That's all. You can delete a script button by right-clicking on it. This plugin optionally scans for ``@button`` nodes, ``@plugin`` nodes and ``@script`` nodes whenever a .leo file is opened.

- ``@button`` nodes create script buttons. - ``@plugin`` nodes cause plugins to be loaded. - ``@script`` nodes cause a script to be executed when opening a .leo file.

Such nodes may be security risks. This plugin scans for such nodes only if the corresponding atButtonNodes, atPluginNodes, and atScriptNodes constants are set to True in this plugin.
A minimal http plugin for LEO, based on AsyncHttpServer.py. Use this plugin is as follows:

1. Start Leo with the plugin enabled. You will see a purple message that says something like::

http serving enabled on port 8080, version 0.91

2. Start a web browser, and enter the following url: http://localhost:8080/ You will see a a "top" level page containing one link for every open .leo file. Start clicking :-)

You can use the browser's refresh button to update the top-level view in the browser after you have opened or closed files.

To enable this plugin put this into your file::

@settings @bool http_active = True @int port = 8080 @string rst_http_attributename = 'rst_http_attribute'
aspell.pyx: Leo's new spell checking plugin that uses aspell.exe. It is much faster than the old mod_spelling plugin, but requires Python 2.3 or above and a recent version of Aspell. When properly installed and enabled, this plugin adds a Check Spelling command to Leo's Edit menu. This command brings up a spell checking dialog. You can set options by changing entries in spellpyx.ini in Leo's plugins menu. One of these settings is the name of the dictionary, spellpyx.txt by default. **Warning**: do not create spellpyx.txt with an ``@asis`` tree in leoPlugins.leo: only the plugin code should typically change spellpyx.txt. You **can** edit ``spellpyx.txt`` yourself in an external editor: just make sure that Leo isn't running when you do this. You can bring up the spell checker without enabling the spellpyx plugin by using an ``@button Check Spelling...`` script button. LeoDocs.leo contains such a script button.
``temacs`` is a binding module for the Tkinter Text widget. ``usetemacs`` is a Leo plugin that patches the temacs modules Emacs emulation into the standard Leo Tkinter Text editor.
Adds XSLT-Node Command submenu item to the Outline menu. This menu contains the following items:

``Set StyleSheet Node`` Selects the current node as the xsl stylesheet the plugin will use.

``Process Node with Stylesheet Node`` Processes the current node as an xml document, resolving section references and Leo directives, and creates a sibling containing the results.

Requires 4Suite 1.0a3 or better, downloadable from http://4Suite.org.
Leo2AsciiDoc is a small Python program which has been built to be used as a plugin module for the Leo outlining editor. For more information see: http://www.marshallresearch.com/michael-dawson/os/leo.html I am still using Leo version 4.1 (rc3, build 1.62), as I've been unable to keep up with the speed of Edward's Leo development. He has made such significant changes to Leo since 4.1 that I doubt that Leo2AsciiDoc will work with any version later than 4.1. I do intend to rewrite Leo2AsciiDoc for the new Leo, but there is no schedule set.

Leo2AscDoc enables the contents of plain text Leo outlines to be published to HTML or PDF via the AsciiDoc program and the DocBook set of publishing tools. Plain text from the Leo outline can be transformed into a final result that has typeset body text, in which bulleted and numbered lists, variable lists, page numbers, URLs, index terms,and bold and italic text are automatically recognized. typeset Headings a Table of Contents an Index containing any items marked by the user, and any Python classes or functions. To produce HTML and PDF, you'll need to have the AsciiDoc program installed (a trivial task) and a DocBook tool chain installed, which is not a trivial task. And, of course, Python and Leo. In sum, this little program is an easy install for people who are already using Leo and DocBook. As noted later, Leo2AsciiDoc has only been tested on Linux
The rst3 plugin creates output files from Leo outlines containing rST (reStructuredText_) markup. rst3 options control most aspects of this plugin's operations. You can set options in ``@settings`` trees, in headlines and in body text. There are too many options to describe here. See: http://webpages.charter.net/edreamleo/rstplugin3.html for full documentation. To use this plugin effectively, Python's docutils_ module must be installed. The rst3 plugin will use the SilverCity_ syntax coloring package if it installed.

The rst3 plugin adds the ``Write Restructured Text`` command to Leo's Edit menu. This command searches the selected outline looking for **rst root nodes** whose headline have the form::

@rst <filename>

The plugin then creates the named file in various ways depending which rst3 options are in effect. By default, the rst3 plugin creates rST headings automatically from outlines, so the higher-level nodes in the outline correspond to higher-level sections in the output. Creating rST headings automatically eliminates one of the most tedious chores associated with rST markup. This plugin sends .htm, .html or .tex files to the docutils module for further processing. Docutils generates HTML files or LaTeX files depending on the file's extension. HTML files generated by docutils refer to three .css (cascading style sheet) files that should exist in the same directory as the generated HTML file. You can control the formatting of the HTML file by altering these .css files.

For full details on this plugin, see http://webpages.charter.net/edreamleo/rstplugin3.html

A new method has been added to the rst3 plugin to make it more easily to drive the plugin from scripts::

def writeNodeToString (self,p=None,ext=None)

writeNodeToString scans p's tree (p defaults to presently selected node) looking for @rst nodes. When the first @rst node is found, writeNodeToString processes the node as usual, with the following changes:

- @rst need not be followed by a filename; any filename and its extension are *ignored*.

- Only the ``ext`` argument to writeNodeToString determines the type of output produced. The valid values for the ``ext`` argument are None (for rst output), '.html', '.pdf', and '.tex'.

- Instead of writing the result to a file, writeNodeToString returns the tuple (p,s), where p is the node whose tree produced the output, and s is the output itself.

- writeNodeToString returns after processing at most one @rst node.

Scripts can easily use writeNodeToString to convert @rst trees into various kinds of output. For example, here is the body of @button rst->html in LeoDocs.leo::

import leoPlugins rst3 = leoPlugins.getPluginModule('rst3') if rst3: controller = rst3.controllers.get(c) if controller: p,s = controller.writeNodeToString(ext='.html') print '*' * 40,p print s

Notes:

- This script scans the presently selected tree for @rst nodes, just like the @button rst script does. In particular, if the presently selected tree does not contain an @rst node the search continues in parent trees. When an @rst node is found, it converts the node (and descendants) to html and returns p, the found @rst node and s, the html itself.

- The script shown above merely prints the output, but many other actions could be taken. In particular, because writeNodeToString returns p it would be possible to write a script that would scan multiple @rst nodes.

- None and '.tex' are also valid values for the ext argument to writeNodeToString. None converts the @rst tree to a single reStructuredText string, as shown in @button rst->rst.

- There is some support for ext='.pdf', but this is experimental code. Expect crashes.
-----------------------

|back| |leo| |next|
Leo 4.3.2 final September 16, 2005

To learn about Leo, see: http://webpages.charter.net/edreamleo/intro.html

The highlights of 4.3.2: -----------------------

- Improved Leo's documentation: - A tutorial introduction to Leo: http://webpages.charter.net/edreamleo/intro.html - A 5-minute guide to programming with Leo: http://webpages.charter.net/edreamleo/intro.html#quick-start-for-programmers

- The new rst3 plugin creates .html and .tex files from reStructuredText embedded in Leo files. Any node of the source outline may contain options for the rst3 plugin, which makes this plugin much more useful and flexible than the previous rst plugins. All of Leo's documentation was created using this plugin from sources in LeoDocs.leo. For full documentation for rst3 see: http://webpages.charter.net/edreamleo/rstplugin3.html.

- The spellpyx (spell checking) plugin is now much easier to use.

- The vim and openWith plugins now use Python's subprocess module if it is present.

- Improved the Pretty Printing command.

- The usual assortment of bug fixes.
@killcolor https://sourceforge.net/forum/message.php?msg_id=3341105 By: rogererens

Here would be a nice place to insert 2 screen shots that illustrate the points discussed: one of a very small @thin tree in Leo, and one of the contents of the file that's derived from that node, as seen in vim or jEdit or notepad.

Also the paragraph on clones might benefit from a screen shot or two, especially since the tutorial contains a lot of text and ideas to grasp. Pictures in between give the opportunity to ponder on the meaning of all that for a while while staring at them...
This is the rST version of the Tech Report handed out at EuroPython in 2005.

**Important**: Leo's tutorial is now a clearer explanation of the basics. This tech report should be rewritten.

@tabwidth -4
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

########################################## The Essentials of Leo ##########################################

.. contents::
Leo organizes all data into nodes containing a **headline**, an expandable page of **body text** and a (possibly empty) subtree of **descendant nodes**. The **contents** of a node are its headline and body text. Leo’s main window contains an **outline** pane at the top left, a **log pane** at the top right, and a **body pane** at the bottom. The outline pane shows headlines; the body pane shows the body text of the selected headline. The log pane displays messages from Leo.

Small red arrows mark **cloned nodes** (clones). Clones share the same content and descendants. All clones of the same node are equivalent, so changing the contents of one node (call it node N) changes the contents of all clones of N. Furthermore, inserting, deleting or changing any descendant of node N causes the corresponding insertion, deletion or change in all other clones of N.
Clones allow you to organize data in multiple ways within the same outline. You do not have to choose a single ‘correct’ organization: you can organize your data in as many ways as you like.

You can use **organizer nodes** to create explicit relations (relationships) among the data in your outline. The headline of the organizer node is the relationship’s name. Now make clones of nodes from other parts of the outline that participate in the relation. Drag the newly created clones so they become children of the organizer node. You may want to create other (non-cloned) children of the organizer node that contain data found nowhere else in the outline. Voilà: you have just created the set of all nodes that pertain to the relationship. The organizer node is the relation; the terms relation, relationship and organizer node are interchangeable.

Three kinds of relations deserve special mention. A **view** is a relation (an organizer node) containing all nodes related to a desired view (or slice) of the data in the outline. Similarly, a **task** is an organizer node containing all nodes related to a task. Relations are not limited to tasks or views: the notion of relationship is completely general. Headlines naturally describe the data in body text. That is, nodes relate **metadata** (descriptions of data) to data. Separating data from metadata is useful for humans. It is even more valuable for scripts: scripts can access data and metadata without complex parsing.
Plugins are Python (.py) files contained in Leo’s plugins folder. Users can write plugins to change how Leo works and to add new features without changing Leo’s core code. We’ll discuss plugins in more detail later.
Leo can generate many external files called **derived files** from an outline. Leo outlines can organize files throughout your computer’s file system. Nodes whose headlines start with ‘@’ are special nodes. Several **special nodes** indicate the root of a tree that generates a derived file::

@asis filename Creates a derived file. Ignores all markup in body text. @file filename Creates a derived file. Duplicates outline structure in .leo file. @noref filename Creates a derived file. Ignores all section references. @nosent filename Creates a derived file without sentinels. @thin filename (Recommended) Like @file, but thin derived files contain all outline structure.

Leo recognizes several other special nodes::

@settings Defines settings local to the .leo file. @url url Double-clicking the node’s icon opens the url in Leo or in a browser.

The scripting plugin scans for the following nodes when opening an outline::

@button Creates a button in the **icon area** at the top of the Leo window. @plugin plugin Enables a plugin if the plugin has not already been enabled. @script Executes a script when opening the outline. This is a security risk: it is disabled by default.

Plugins, @button nodes and @script nodes can create other kinds of special nodes::

@suite Creates a suite of unit tests from script in body. Requires scripting plugin. @test Creates a unit text from script in body. Requires scripting plugin. @rst Outputs a tree containing markup for reStructuredText. Requires rst2 plugin. @run command Double clicking the node’s icon executes the command. Requires run_nodes plugin.
Leo’s Execute Script command **preprocesses** the script to be executed by scanning a node N and its descendants looking for markup. **Markup** is special syntax that controls this preprocessing. If node N contains no markup, the resulting script is just N’s body text. Otherwise, the preprocessed script will include text from descendant nodes as described below. The main kinds of markup are **section references**, **directives** and **doc parts**.

1. **Section references** have the form::

<<section name>>

The ``<<`` and ``>>`` must appear on the same line. Conversely, any line containing ``<<`` and ``>>`` is a section reference, regardless of context. However, section references are not recognized in doc parts. Any characters may appear between ``<<`` and ``>>``.

Section references are functional pseudo-code: while preprocessing a script, Leo replaces section references by the actual text of the section’s definition. Sections are defined in **section definition nodes**, whose headlines start with a section reference and whose body text defines the section. Each section definition node must descend from the node containing the section reference.

2. **Directives** start with ‘@’ in the leftmost column of body text. Directives specify options and control Leo’s operation. The ``@others`` directive is the minimal markup needed to organize scripts. ``@others`` tells Leo to insert the preprocessed text of all descendant nodes (except section definition nodes) at the spot at which the ``@others`` directive occurs. Nodes are inserted in **outline order**, the order in which nodes appear in the outline. **Important**: Leo adds the whitespace preceding the ``@others`` directive to the indentation of all preprocessed text.

Using ``@others`` is more convenient than using section references. Use ``@others`` when the order of included text does not matter::

class myClass: @others # Include the methods of the class. Order doesn’t matter.

Use section references when the order of included text does matter. In the following script, for example, << imports >> ensures that imports come first. The ``@others`` directive then includes the body text of all other descendant nodes::

@language python << imports>> @others # Define classes & functions in child nodes. main()

Here is a list of all of Leo’s standard directives::

@whitespace (or @doc) Starts a doc part & ends code part. @all Like @others, but includes all descendant nodes. @c, @code Starts a code part and ends a doc part. @color Enables syntax coloring. @delims Temporarily changes comment delims. @nocolor, @killcolor Disables syntax coloring. @comment Sets comment delimiters in external (derived) files. @language languagename Sets language for syntax coloring and comments. @lineending lineending Sets ending of lines in derived files. @others Inserts body text of all descendants except definition nodes. @pagewidth n Sets page width for justifying comments in doc parts. @path path Sets prefix to use in relative file names in @file nodes, etc. @root filename Marks the root of a tree that creates an external file. @raw, @end_raw Inhibits sections references in a range of text. (@file only.) @tabwidth n Sets width of tabs (negative widths convert tabs to spaces.) @wrap, @nowrap Controls wrapping of text in body pane.

3. Doc parts start with the ‘@’ directive and continue until the end of the body text or until the ‘@c’ directive. Body text not in a doc part is in a code part. Here is an example of a doc part::

@ This is a doc part. Doc parts may span many lines. Leo converts doc parts to comments. Leo reformats the doc part by justifying lines so they are no longer than the page width. @c

Leo reformats doc parts by justifying the text into comment lines. The ``@pagewidth`` directive controls the length of these comment lines. The ``@language`` and ``@comment`` directives specify the comment delimiters used in doc parts.
The ``Execute Script`` command preprocesses the selected text of the presently selected outline node, or the entire text of the node if there is no selected text. See the section called ``Markup for Scripts`` for a discussion of how Leo preprocesses scripts. That section also discusses how Leo organizes scripts using outlines. Conversely, scripts can use outlines to organize their data. To write such scripts you must understand at least the basics of Leo’s modules and classes...
Leo’s source code is organized as a collection of modules. The following paragraphs describe five of the most important modules. See ``LeoPy.leo`` (Leo’s full source code) for more details: scripts have full access to all of Leo’s classes and data.

1. The **leoGlobals** module contains utility functions. By convention, in Leo’s code ``g`` is always the ``leoGlobals`` module.

2. The **leoApp** module defines a class representing the entire Leo application. **g.app** is the singleton object of this class: the application object. The instance variables (ivars) of the application object are Leo’s global variables.

3. The leoCommands module defines the Commands class. A commander is an instance of this class. Commanders contain the operations that can be performed on a particular outline. Each open Leo outline has its own commander. By convention, in Leo’s code **c** is always a commander.

4. The leoFrame module defines the base leoFrame class for objects that create and manage the visual appearance of Leo’s windows and panes. The **leoTkinterFrame** and **leoTkinterTree** modules contain subclasses of the base classes in the leoFrame module. A frame (an instance of the leoFrame class, or a subclass) contains all the internal data needed to manage a Leo window. **c.frame** is the frame associated with commander c. If **f** is a frame, **f.c** is the frame’s commander, **f.body** is the frame’s body pane, **f.tree** is the frame’s outline pane, and **f.log** is the frame’s log pane.

5. The leoNodes module defines several classes that implement Leo’s fundamental data structures. These classes are complex. Happily, scripts can and should ignore these complications by accessing nodes using high-level methods of the position class.

A **position** (an instance of the position class) is the state of some traversal of an outline. Equivalently, a position is a particular visual place in an outline. Cloned nodes may appear many times in an outline. Non-cloned nodes may also appear in many places: consider a non-cloned descendant of a cloned node. By convention, in Leo’s source code p is a position.
When executing scripts Leo predefines the following three symbols: **c** is the commander of the outline in which the script is defined, **g** is the leoGlobals module and **p** is the position of the selected node in c’s outline, i.e., ``c.currentPosition()``.
Scripts should get and set data using high-level access methods. Here are some important getters::

g.app The application object. Its ivars are Leo’s global variables. g.app.windowList The list of all open frames. c.currentPosition() The position of the selected node. c.rootPosition() The position of the first node in the outline. p.headString() The headline of position p. p.bodyString() The body text of position p. p.childIndex() The number of siblings that precede p. p.numberOfChildren() The number of p’s children. p.level() The number of p’s ancestors. p.hasChildren() True if p has children. p.isAncestorOf(p2) True if p2 is a child, grandchild, etc. of p. p.isCloned() True if p is a clone. p.isDirty() True if p’s contents have been changed. p.isExpanded() True if p has children and p’s outline is expanded. p.isMarked() True if p’s headline is marked. p.isVisible() True if all of p’s ancestors are expanded.

And here are some important setters::

c.setBodyString(p,s) Set body text of p to s. c.setHeadString(p,s) Set headline of p to s.
Scripts can visit some or all of the nodes of a Leo outline using the following iterators::

c.allNodes_iter # All positions in the outline, in outline order. p.children_iter() # All children of p. p.parents_iter() # All parents of p. p.siblings_iter() # All siblings of p, including p. p.following_siblings_iter() # All siblings following p, not including p.

For example, the following prints all the nodes of an outline, properly indented::

for p in c.allNodes_iter(): print ' '*p.level(), p.headString()
Scripts may open other Leo outlines, or execute any of Leo’s commands. Here are some examples::

ok,frame = g.openWithFileName(path,c) # Opens the .leo file found at path. c.deleteOutline() # Deletes the selected node. c.insertHeadline() # Inserts a new node after present position.

For more examples, see ``Chapter 7: Scripting Leo with Python``, in ``Leo’s Users Guide``.
The scripting plugin creates two buttons in the icon area at the top of the Leo window. The ``Run Script`` button executes the script in the selected node just like the ``Execute Script`` command. The ``Script Button`` button creates a new button whose headline is the headline of the presently selected node, call it node N. Pressing this button executes the script in node N with p predefined as ``c.currentPosition()`` at the time the script is executed. This clever trick brings the script to the data in the selected outline.
``test.leo`` contains all of Leo’s unit tests. An ``@button node`` in test.leo creates a blue ``Unit Test`` button in the icon area. This button is an excellent example of bringing scripts to data. The ``Unit Test`` button executes all the unit tests specified by ``@test`` and ``@suite`` nodes in the selected outline. **Important**: ``@button``, ``@test`` and ``@suite`` nodes require the scripting plugin to be enabled.

``@test`` nodes greatly simplify unit testing. The ``Unit Test`` button creates a unit test from the body text of each ``@test`` node. In effect, the ``Unit Test`` button automatically creates an instance of ``unittest.TestCase`` whose run method is the body text of the @test node. There is no need to create ``TestCase`` objects explicitly!

``@suite`` nodes support legacy unit tests. When the ``Unit Test`` script button finds an ``@suite node`` it executes the script in its body text. This script should create a suite of unit tests and set::

g.app.scriptDict['suite'] = suite

where suite is the created suite. The ``Unit Test`` button then runs that created suite of unit tests.
Plugins are Python (.py) files in Leo’s plugin subdirectory. It is easy to create new plugins: Leo’s users have contributed dozens of plugins that extend Leo’s capabilities in new ways. Leo imports all enabled plugins during startup. The file pluginsManager.txt lists all enabled plugins. You can use the plugin manager plugin to control plugins without updating ``pluginsManager.txt`` by hand.

Plugins can override any class, method or function in Leo’s core, the files in Leo’s src subdirectory (the files derived from LeoPy.leo). Besides altering Leo’s core, plugins can register functions called hooks that Leo calls at various times during Leo’s execution. Events that trigger hooks include key pressed events, screen drawing events, node selection events and many others. When importing a plugin, Leo will call the top-level init() function if it exists. This function should register the plugin’s hooks by calling leoPlugins.registerHandler.

For full details about hooks and events see ``Chapter 13: Writing Plugins``, in ``Leo’s Users Guide``. The file ``leoPlugins.leo`` contains all plugins that are presently distributed with Leo; studying these plugins is a good way of learning to write your own plugins.
- Leo’s home page: google edreamleo or http://webpages.charter.net/edreamleo/front.html

- Edward K. Ream: edreamleo@charter.net, 166 N. Prospect Ave., Madison WI 53726, (608) 231-0766
Leo 4.3.3 final September 17, 2005

Leo 4.3.3 fixes several bugs reported in Leo 4.3.2 final in the last several days.

To learn about Leo, see: http://webpages.charter.net/edreamleo/intro.html

The highlights of 4.3.3 (and 4.3.2) -----------------------------------

- Improved Leo's documentation: - A tutorial introduction to Leo: http://webpages.charter.net/edreamleo/intro.html - A 5-minute guide to programming with Leo: http://webpages.charter.net/edreamleo/intro.html#quick-start-for-programmers

- The new rst3 plugin creates .html and .tex files from reStructuredText embedded in Leo files. Any node of the source outline may contain options for the rst3 plugin, which makes this plugin much more useful and flexible than the previous rst plugins. All of Leo's documentation was created using this plugin from sources in LeoDocs.leo. For full documentation for rst3 see: http://webpages.charter.net/edreamleo/rstplugin3.html.

- The spellpyx (spell checking) plugin is now much easier to use.

- The vim and openWith plugins now use Python's subprocess module if it is present.

- Improved the Pretty Printing command.

- The usual assortment of bug fixes.
Here is a summary of the changes:

- General: All chapters created with rst3 plugin. This ensures a uniform look. The source is in LeoDocs.leo. Removed all references to older versions of Leo, except when discussing old file formats in the Appendices. Corrected all text so it discusses present version.

- rst3 plugin itself: Correct bug that caused chapters to be formatted differently when processing multiple @rst trees.

- rst3 button in LeoDocs.leo: The script first looks *up* the tree, looking for an @rst node. If found, it processes just that tree. If not found, it processes all @rst nodes *below* the originally selected node. The button is now much more convenient to use.

- Preface: Shorter, no history. No longer a dead end.

- What People are Saying About Leo: No longer a dead end.

- FAQ: Reorganized, simplified, revised. Added entries for running Leo in a console window and debugging docutils. Improved entry for using cvs.

- Chapter 1: Installation: Now the first chapter. Revised.

- Chapter 2: Tutorial: Completely rewritten. Like Python's tutorial, this chapter contains everything a beginner needs to understand and use Leo. The `Quickstart for programmers` section is the heart of this chapter. All terms used have links either to their definition in the tutorial or in the Glossary. Newbies should be able to digest this chapter easily. This chapter should make Leo comprehensible to many more people.

- Chapter 3: Using Outlines: Revised per general remarks above.

- Chapter 4: Writing Programs in Leo. Completely rewritten. The old chapter was an embarrassment. The new chapter is a reference guide, properly organized as such. The introduction warns newbies away.

- Chapter 5: Using Leo's Commands. 'Minor' revisions and corrections create a substantially better result.

- Chapter 6: Leo and literate programming: Reformatting helps. New words about rST markup and other improvements over traditional LP.

- Chapter 7: Scripting Leo with Python: Rewritten, simplified, updated and corrected. The sources in LeoDocs.leo are directly executable. rST sources use literal blocks instead of code-blocks so that the sources are simplified. (Important when executing examples). Properly discusses positions, including 'supremely important' section on copying positions.

- Chapter 8: Customizing Leo. Heavily revised. Discusses leoSettings.leo, not leoConfig.txt. Security warnings are more reasonable. Section on script buttons. Rewrote section on uA's (Adding extensible attributes to nodes and .leo files).

- Chapter 9: History of Leo. Rewritten. Much shorter and more useful. Discusses the major milestones, concentrating on explaining the major differences between versions. Gone are details of how discoveries came to be. They are in LeoPostings.leo, which will be included in the distribution.

- Chapter 10: Theory of Operation. Largely rewritten. Discusses positions properly. Omits discussion of how clones were implemented before 4.2.

- Chapter 11: White Papers. A new chapter. This is a slightly-edited version of writing that had been buried in the appendices.

- Appendices. Heavily revised and reformatted. Rewrote sections on file formats.

- Glossary: A separate chapter. All terms have links to their definition. All definitions are rST targets so other chapters may refer to them. Added several new entries.
- Fixed bug with non-unicode characters in file name

http://sourceforge.net/forum/message.php?msg_id=3224635

Leo crashed try to read .leo files whose name contained non-ascii characters.

- Fixed bug with non-unicode characters in settings value

http://sourceforge.net/forum/message.php?msg_id=3222750

Leo crashed try to write settings whose values contained non-ascii characters.

- Fixed bug tangling sections with non-unicode characters.

http://sourceforge.net/forum/message.php?msg_id=3307318
http://sourceforge.net/forum/message.php?msg_id=3218558
The fix was to add an entry of 'unknown' state to state_dict. This fixes the crash by brute force, but may not be strictly correct. However, this is pretty much moot: we shall soon be moving to the new colorizer.
The code gets c = keywords.get('c') in several places. The protection is to return if c is None. This affects the following files: plugins_menu.py, pluginsTest.py, plugin_manager.py
http://sourceforge.net/forum/message.php?msg_id=3231597

test.leo had some non-@ignore'd @thin nodes for files not in the distribution.

- Only files used by unit tests should be on cvs and the distribution. - test\unittest\batchTest.py and test\unittest\errorTest.py were already on cvs. - Added these files to the distribution.

- Other test files should be distributed in @ignore nodes.

- Leo's distribution checklist now has an item to check that the distributed test.leo can be opened without errors.
See http://webpages.charter.net/edreamleo/rstplugin3.html for full documentation of this plugin.

The rst3 plugin creates output files from Leo outlines containing reStructuredText (rST) ReStructuredText is a simple and powerful text formatting markup language. Outlines are a natural way to organize rST (or any text).

This plugin adds the Write Restructured Text command to Leo's Edit menu. The Write Restructured Text command searches the selected outline looking for rst root nodes whose headline have the form @rst <filename>. The plugin then creates the named file in various ways depending which rst3 options are in effect.

By default, the rst3 plugin creates rST headings automatically from outlines, so the higher-level nodes in the outline correspond to higher-level sections in the output. Creating rST headings automatically relieves you from one of the most tedious chores in creating rST markup.

To use this plugin effectively, Python's docutils module must be installed. The rst3 plugin will use the SilverCity syntax coloring package if it installed.

This plugin sends .htm, .html or .tex files to the docutils module for further processing. Docutils generates HTML files or LaTeX files depending on the file's extension. HTML files generated by docutils refer to three .css (cascading style sheet) files that should exist in the same directory as the generated HTML file. You can control the formatting of the HTML file by altering these .css files.
This plugin now allows quotes within words, but strips quotes and other cruft from the beginning and end of words. As a result, using the spellpyx spell checker is much easier than before.

Leo's extensions folder now contains aspell23.pyd and aspell24.pyd. These are Python dll's compiled for Python 2.3 and 2.4 respectively. You must rename one of these files to be aspell.pyd and move aspell.pyd to the aspell folder. For more details, see the installation nodes in the docstring for the spellpyx plugin.
These plugins now use Python's subprocess module if it is present. The subprocess module comes standard with Python 2.4. For Linux systems, Leo will use subprocess.py in Leo's extensions folder if necessary.

For Windows systems you can install Python's subprocess module in Python 2.2 or 2.3 as follows:

- Go to http://www.effbot.org/downloads/#subprocess

- Download and execute one of the following installers, depending on your version of Python: subprocess-0.1-20041012.win32-py2.3.exe subprocess-0.1-20041012.win32-py2.2.exe

This installer installs the subprocess sources and also _subprocess.pyd in Python's site-packages folder.
Calling print directly is dangerous: it will fail for unicode characters.
The new Pretty Print code has the following improvements:

- Strip trailing blanks in get. - Many improvement to doOp. - Improved DoMultiline: - Added special case logic to ensure '#' is preceded by space except at start of line. - Added blank after multi-line string if needed. - Added lastName token for special-case handling depending on previous token. - No change to put, putArray or doName.
- Fixed bug that caused the Open With command to crash if the subprocess module was not installed.

- Fixed problems in the niceNocent and fastGotoNode plugins.
Leo 4.4 alpha 4 December 5, 2005

Leo 4.4 a4 introduces the 'Newer World Order' for redrawing the screen, corrects numerous bugs in the 4.4 code base, and introduces several new features.

You should be able to use this version safely. There are no known serious bugs, but several minibuffer commands are not ready for prime time. All the major features of 4.4 are in place.

To learn about Leo, see: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4: ---------------------------------- - An Emacs-like mini-buffer: you can now execute any command by typing its long name. Support for tab completion.

- A tabbed log pane. The Find and Spell Check commands now use tabs instead of dialogs, making those commands much easier to use. Plugins or scripts can easily create new tabs. The Completion tab shows possible typing completions.

- Support for almost all commands in the Emacs Cmds menu, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles.

- Per-pane key bindings. You can bind shortcuts to multiple commands depending on which of Leo's panes presently has focus. For example, you can use arrow keys to move nodes in the outline pane, while retaining their defaults in Leo's body pane. Per-pane key bindings are essential for mouseless Leo.

- @command nodes create minibuffer commands. You can bind key shortcuts to @button and @command nodes.

- A rewrite of Leo's keystroke handling. In particular, Leo handles key events immediately rather than queuing them for idle time.

- Leo recovers from crashes much more reliably than in any previous version.

- Leo updates the screen immediately rather than waiting for idle time. This 'Newer World Order' simplifies the code and improves performance.

Known bugs in Leo 4.4a4 ----------------------- - Several minibuffer commands do not work. See the release notes for details.

Coming in later releases of Leo 4.4: ------------------------------------ - An auto-complete command that shows class members in the Completion tab.

- More support for mouseless Leo. There will be commands to manipulate all aspects of Leo using commands, so your fingers will never have to leave the keyboard.

- Support for Vim and other 'plain-key' input modes.
Here are the default bindings relating to the minibuffer. Any of these may be changed by changing @shortcuts nodes in leoSettings.leo.

Alt-x: Just like Emacs: starts minibuffer. The prompt is 'full-command' Type a full command name, then hit <Return> to execute the command. Tab completion works, but not for file names.

Alt-c: Like Emacs Control-C: (Ctrl-C conflicts with XP cut). starts minibuffer. The prompt is 'quick-command'. This mode is not completed, but stuff like `Ctrl-C r` and `Ctrl r r` do work.

Alt-u: Like Emacs Ctrl-u: (Ctrl-u conflicts with move-outline-up). Add a repeat count for later command. Ctrl-u 999 a adds 999 a's, but many features remain unfinished.

Ctrl-g: Just like Emacs Ctrl-g: Closes the mini-buffer.

The @bool useMinibuffer setting in leoSettings.leo just controls whether the minibuffer is visible. The minibuffer exists (and you can type into it) even if it isn't visible! You can use the show-mini-buffer, hide-mini-buffer and toggle-mini-buffer commands to show or hide the minibuffer.
The most important new features of Leo 4.4 have to do with key bindings.

See the children of this node for details.

1. The minibuffer exists regardless of this setting, but will not be shown initially if it is False.

2. Hiding the minibuffer does not change any bindings or the operation of Leo in any other way. Therefore, if you do hide the minibuffer initially, and never want to use it, you should not bind shortcuts to any commands that use the minibuffer.

3. You can execute the show-mini-buffer, hide-mini-buffer and toggle-mini-buffer commands (or any other minibuffer command!) if the minibuffer is hidden. Indeed, the following will work even if the minibuffer is hidden.

<alt-x>show-mini-buffer<return>
This options controls whether Leo creates a Cmds menu.

This menu is not ready yet, though nothing bad happens if this option is True.
http://sourceforge.net/forum/message.php?msg_id=3355954

'body_text_selection_background_color' Default is 'Gray80' 'body_text_selection_foreground_color' Default is 'white'
- The contract-and-go-right command moves to the parent node and collapses the parent node.

- The goto-first-sibling and goto-last-sibling commands allow rapid movement through an ouline without collapsing nodes.

- The print-bindings and print-commands show what commands exist and what keys are bound to them.

- The help command gives a brief quick start introduction to Leo's Emacs-like features.
Leo maintains the following dictionaries. As usual, k refers to c.keyHandler:

- c.keyHandler.registerCommand can be called from scripts to register new alt-x commands. It probably won't work from plugins yet.

New dictionaries and methods make it easier to customize and extend Leo:

- c.commandsDict describes all commands. Keys are full Emacs command names; values are functions f.

- k.inverseCommandsDict: keys are f.__name__, values are emacs command names.

- k.leoCallbackDict: keys are leoCallback functions, values are called functions.

- k.bindingsDict: keys are shortcuts, values are g.bunches with the following members: func, name, warningGiven, fromMenu.
The following helper functions make it easy to discover the binding presently in effect for a command:

- k.getShortcutForCommandName(self,commandName) returns the shortcut given f.__name__.

- k.getShortcutForCommand(self,f) returns the shortcut for f.
@nocolor

c.keyHandlerregisterCommand (self,commandName,shortcut,func)

This function make the func available as a minibuffer command, and optionally binds a shortcut to func. You can wrap any method in a function, so the restriction to functions is not significant.

Here is an example take from an @button node::

@color

k = c.keyHandler

def f (event): g.es_print('Hello',color='purple')

k.registerCommand('print-hello','Alt-Ctrl-Shift-p',f) k.registerCommand('print-hello2',None,f)
The following bugs exist in 4.3 final.
This makes it much harder to hang Leo after taking an exception. Leo 4.4a1 is *much* more robust than Leo 4.3 final in this regard.
Added big kludge to menu.createMenuEntries so that f.OnCut/Copy/PasteFromMenu get called **only** when explicitly selected from the menu (rather than from a shortcut). This allows the code in cut/copy/paste-text to be different as needed.

Users can override the shortcut by assigning shortcuts to cut/copy/paste-text commands. The shortcut will appear in the menu, but does **not** get bound to c.frame.menu.

This is an essential step in solving the infamous Control-V problem. The code appears to work properly on XP. Not tested other places.

This is the last best hope to solve this problem: the code interacts as little as possible with Tk.
http://sourceforge.net/forum/message.php?msg_id=3351985

Leo did not read empty tnodes like <t/> properly.
http://sourceforge.net/forum/message.php?msg_id=3376527
It now computes the minimum leading whitespace of all non-blank lines. The old code computed the leading whitespace of the *first* non-blank line. This would give the wrong results if the first line were indented.
@nocolor

The scripting plugin has been improved as follows:

1. You can bind shortcuts in @button nodes. Like this:

@button name @key=shortcut

This binds the shortcut to the script in the script button. The button's name is 'name', but you can see the full headline in the status line when you move the mouse over the button. This is a clean and simple way of discovering the shortcut.

2. You can create your own minibuffer commands with @command nodes.

A node whose headline has the form:

@command command-name

a new minibuffer command whose name is 'command-name'.

A node whose headline has the form:

@command command-name @key=shortcut

creates new minibuffer command and binds shortcut to it.

3. The scripting plugin no longer contains the 'bindLate' code-level option. The scripts for all @button or @command nodes are computed 'dynamically', that is, when the button is pushed or the command is executed from the minibuffer. This is the most useful way, and the most intuitive.

Previously, scripts for @button nodes were never dynamic, while scripts in @button nodes created by the 'Script button' button were dynamic only if bindLate was True. You could call this a bug: it was unhelpful, annoying and confusing.

4. The scripting plugin no longer prints an 'end of script' message. This allows scripts to select tabs in the log pane
@color

# Plugins and scripts can easily create new tabs in the log panel. # Important: you can run any of these examples using the 'Run Script' button.

# To create a tab named "Test" or make it visible if it already exists:

c.frame.log.selectTab('Test')

# When first created, a tab contains a text widget. # To write to this widget, add the tabName argument to g.es:

g.es('Test',color='blue',tabName='Test')

# Plugins and scripts can easily replace the default Text widget with other Tk widgets. # c.frame.log.tabFrame contains the Tk.Frame that contains all the other widgets of the frame. # c.frame.log.logCtrl contains the Tk.Text widget that is initially the only widget in this frame. # So to remove this text widget just do:

c.frame.log.logCtrl.pack_forget()

# Now you can pack any other widgets into c.frame.log.tabFrame.

import Tkinter as Tk ; log = c.frame.log log.selectTab('Test') log.logCtrl.pack_forget() f = Tk.Frame(log.tabFrame,bg='red',height='1inch',width='2inch') f.pack(side='left',expand=0,fill='none')
Leo can optionally generate matching brackets depending on the setting:

@bool autocomplete-brackets = TrueOrFalse

If True, Leo will immediately type the corresponding closing bracket whenever you type a '(', '[' or '{' character. You can use the forward-char command to move past the closing bracket, and Leo will move past any closing bracket if you type the closing bracket with the cursor just to the left of a closing bracket.
**Important**: The print-bindings and print-commands commands (new in a1) show what commands exist and what keys are bound to them.

- The help command tells how to use the minibuffer.

- The show-minibuffer, hide-minibuffer and toggle-mini-buffer commands show and hide the minibuffer.

It *is* possible to execute these command even if the minibuffer isn't presently visible. For example, typing

<alt-x>toggle-mini-buffer<return>

should always work.

- The open-find-tab command opens the Find tab. The Find tab replaces the old Find panel. The Find panel is deprecated.

- The open-spell-tab command opens the Spell-checking tab.

- The show-colors command creates the 'Colors' tab in the log pane. This tab allows you to experiment with picking fonts.

- The show-fonts command creates the 'Fonts' tab in the log pane. This tab allows you to experiment with picking colors.
At the bottom of Leo's window you will now see an area labeled the mini-buffer. You can't type in it directly, you activate the buffer by typing Alt-x or Alt-c. Typing Alt-x takes you to 'full-command' mode. Type the full name of a command, followed by a 'return'.

- To get help, type Alt-x help. - For a list of commands, type Alt-x print-commands. - For a list of present key bindings, type Alt-x print-bindings. - To leave the mini-buffer at any time type Ctrl-g.

Note: you can redefine any of these keys as you wish.

Important: you can execute any of Leo's 'legacy' commands from the mini-buffer. For example, Alt-x about-leo or Alt-x open-find-dialog. Note: Leo's Find *dialog* is deprecated. You will find it much more convenient to use Leo's new Find *tab*. Use the open-find-tab command.

You can use tab-completion in the minibuffer to cycle through the list of commands that start with what is in the buffer. Typing backspace takes you back to the what you previously typed (less on character.) The 'Completion' tab shows all possible completions. This tab appears automatically when you type a tab in the minibuffer.

The mini-buffer reduces the need for shortcuts dramatically. For example, none of Leo's import commands need a shortcut because it is easy enough to execute them from the minibuffer. In particular, executing commands from the minibuffer is much easier than executing commands by hand from a menu.
leoSettings.leo contains one functional @shortcuts node and one disabled @@shortcuts node. These node contain entries for every command.

You can assign key shortcuts to any command, as discussed in the comments in that file. You can leave the nodes as they are, use them as base for modifications, or roll your own. You should define a binding for every function, even if that binding is 'None'. If you don't, Leo will issue a warning.

Leo now supports per-pane bindings. Bindings of the form:

command-name ! pane = shortcut

bind the shortcut to the command only withing a single pane. The possible values for 'pane' are:

pane affected panes ---- -------------- all body,log,tree body body log log mini minibuffer text body,log tree tree
The scripting plugin has been improved in two ways:

1. You can specify key bindings in @button nodes as follows:

@button name @key=shortcut

This binds the shortcut to the script in the script button. The button's name is 'name', but you can see the full headline in the status line when you move the mouse over the button.

2. You can create new minibuffer commands with @command nodes:

@command name @key=shortcut

This creates a new minibuffer command and binds shortcut to it.
Abbreviations may not work at present. A new kind of abbreviation is presently hard coded in add_ekr_altx_commands in leoKeys.py. For example, one ekr-shortcut is: 'f', which is bound to leo-find-panel. Typing Alt-x f Return executes leo-find-panel. These may be quicker than Emacs abbreviations, or not.
These 'hard-coded' bindings are no longer needed and interfere with per-pane bindings.
- The open-find-tab command opens the Find tab.

- The open-spell-tab command opens the Spell-checking tab.

The Find and Spell *tabs* replace the corresponding legacy *dialogs*. Using tabs eliminates previous problems with dialogs obscuring Leo's main window.

Two essential components of the settings dialog now are implemented in the tabbed log:

- The show-colors command creates the 'Colors' tab in the log pane.

- The show-fonts command creates the 'Fonts' tab in the log pane.

These two tabs allow you to pick color or font names without using the @settings dialog.

Important: scripts and plugins can easily create new tabs in the Log pane. See Chapter 7 of the Users Guide for details.
Leo's core now supports tabs in the log pane.
Leo 4.4a2 contains a large number of code-level improvements--some very significant. For full details, see the (Projects) section of LeoPy.leo.
The following bugs existed in the 4.4a1 code base and have now been fixed:

- Removed warnings from compare dialog.
Tk/Tkinter make it easy to customize the contents of any of Leo's panes. The following sections will discuss the 'official' ivars that make it possible for scripts to access and alter the contents of panes. The next three sections will give examples of modifying each pane.
- The node::

@shortcuts traditional Leo shortcuts with important emacs bindings

contains Leo key bindings.

- The spelling settings in leoSettings.leo replace the settings in spellpyx.ini.

- You can specify the background of tabs using the following pattern::

@color log_pane_XXX_tab_background_color = aColor

For example::

@color log_pane_Find_tab_background_color = #d6c7d3

- The @bool autocomplete-brackets setting controls whether Leo types a matching closing bracket immediately when you type '(', '[' or '{'.
@nocolor

The New World Order means that drawing happens immediately, not at idle time.

The Newer World Order means that c.endUpdate is equivalent to c.redraw_now.
http://sourceforge.net/forum/message.php?msg_id=3411030

The fix was to add guards so the code does not assume w._name exists for all widgets w.
Scripts.leo contains general-purpose scripts.

unitTest.leo contains all of Leo's unit tests.

test.leo is now for recent tests. Its small size speeds up my workflow.
Changed the following plugins:

cleo.py, footprints.py,__wx_gui.py, zodb.py
Removed tree.redrawScheduled, tree.updateCount and tree.disableRedraw

Three major complications are gone.
http://sourceforge.net/forum/message.php?msg_id=3412644

You can invoke minibuffer commands by name. For example:

c.executeMinibufferCommand('open-outline')

Note: c.keyHandler.funcReturn contains the value returned from the command. In many cases, as above, this value is simply 'break'.
For now, I just set c.useTextMinibuffer = False, so Leo uses a Tk.Label rather than a Tk.Text widget.

This will cause less confusion than always having the minibuffer enabled.
http://sourceforge.net/forum/message.php?msg_id=3415021

The code now uses the settings in leoSettings.leo.
@nocolor http://sourceforge.net/forum/message.php?msg_id=3414639

The entries for Perl and Perlpod are now as follows:

@color

self.language_extension_dict = { "perl" : "pl", "perlpod" : "pod", }

self.extension_dict = { "pl" : "perl", "pod" : "perlpod", }
http://sourceforge.net/forum/message.php?msg_id=3418304

Fixed an edge effect when backward searching for a match that occurs at the very end of body text. In the process I removed an ancient hack.
This code should never have existed. It was used only in the macro plugin.
The plugin can not call bodyWantsFocus.
Later may never come in the Newer World Order, so everything must happen immediately.
This ensures that the widget is always visible.
http://sourceforge.net/forum/message.php?msg_id=3425070

This code was contributed by Roger Erens.

When the Clone Find All checkbox is checked, the Find All command creates a new root node called Found: <your search pattern>

This node contains clones of the nodes found by the Find All command. It is your own responsibility to navigate to this new node and to clean it up when it's no longer needed.
The tab now scrolls properly.
http://sourceforge.net/forum/message.php?msg_id=3434727

- Added calls to c.frame.body.onBodyChanged in cut/paste handlers.

- Added call to c.selectPosition(c.currentPosition()) in undo/redo. This is essential because previous calls to c.selectPosition may have had redraw_flag = False.
http://sourceforge.net/forum/message.php?msg_id=3425967

When creating a new Leo outline (no leo file created yet), the Save As command created the file Test4.leo instead of the expected Test4.3.leo
http://sourceforge.net/forum/message.php?msg_id=3427809

Allowed relative path to stylesheets.

http://sourceforge.net/forum/message.php?msg_id=3433717

The rst3 plugin now traverses the tree as was done previously in the @button rst3 nodes.

http://sourceforge.net/forum/message.php?msg_id=3456419

The rst3 plugin now looks up and down the tree for settings doc parts.

The rst3 plugin now supports the default_path option.
@nocolor

- The focusIn/Out trace is a great tool.

- doTabCompletion now calls w.update before calling bodyWantsFocus.

- Eliminated w.update from g.app.gui.set_focus. It is now called only in those places where it is truly essential, such as in k.doTabCompletion and wherever else it might be required.

- Pmw.Notebook does a *lot* when it switches panes (e.g., the _layout method) and potentially any of the things it does could result in focus shifting to widget. Rather than trying to make sense of it all, Leo will simply call w.update as necessary to force completion of the Pmw.Notebook work before trying to set focus.
http://sourceforge.net/forum/message.php?msg_id=3440420

Added @string vim_cmd and @string vim_exe settings. The defaults now correspond to default installations of vim.
http://sourceforge.net/forum/message.php?msg_id=3436726

The dialog warns about the extensions folder not containing Pmw. This can happen when getting files from cvs.
http://sourceforge.net/forum/message.php?msg_id=3437089

The new default binding causes focus to move to the body pane when the user hits <Return> to end editing in a headline.
http://sourceforge.net/forum/message.php?msg_id=3442064

This was not, in fact, a problem with the plugins manager plugin.

The bug was in << put up a dialog requiring a valid id >> in app.setLeoID. The code set g.app.gui to None after calling g.app.gui.runAskLeoIDDialog the code set!

While I was at it, Leo's core now always inits Pmw when creating Tk.Tk. This removes the necessity for Plugins to do this.
1: Outline not marked dirty during editing

https://sourceforge.net/forum/message.php?msg_id=3447570

2: Inserting a headline didn't save previous edits of headlines
Leo 4.4a4 completes the transition to the 'Newer World Order'.
.. December 3, 2005

@ @rst-options code_mode=False default_path = generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

########################### |leo| Using JythonShell ###########################

This chapter describes how to use the Jython Shell created by LeoUser.

.. contents::
.. rST links used in this document...

.. External links...

.. Hard links to Leo's web site...

.. WARNING: image targets may not have upper case letters!

.. _front: front.html

.. |blank| image:: blank.gif .. |leo| image:: leo.gif :target: front_
-------------

|leo|
- Up-Down Arrow moves the selection up or down. - Tab inserts the current selection.

The completion list shows the best prefix entered after the '.' Any other key withdraws the autocompleter.
Enter Processes the current line from the prompt to the end, regardless of where the cursor is.

Ctrl Enter This keystroke has two meanings:

1. process the current line with a ':' appended to the end of it, regardless of where the cursor is. This is the behavior if there is character data on the line.

2. If the line is pure whitespace, then the line is interpreted as a '' string with a length of 0.
Executing will dynamically expand a prefix to matching words already entered within the interpreter. For example: cactus cac( keystroke ) will expand cac to cactus. This will cycle through all matches to cac within the buffer upon repeated execution.

Ctrl A Moves current position to the end of the prompt.

Ctrl E Moves current position to the end of the line.

Ctrl K Removes all text from current position to end of the line.

Ctrl N Start typing, and then use this keystroke to search downwards only through the history items that match what you've typed so far. If you use this keystroke at a blank prompt, they just behave like normal arrow keys.

Ctrl P Start typing, and then use this keystroke to search upwards through only the history items that match what you ve typed so far. If you use this keystroke at a blank prompt, they just behave like normal arrow keys.

Ctrl R Opens a search prompt. Begin typing and the system searches your history for lines that contain what you ve typed so far, completing as much as it can.

Ctrl T Places triple quotes around the text on the current line.

Ctrl Z Suppresses the current output for the duration of the execution statement. This is useful in cases where there is a tremendous amount of output occurring and the user decides that he no longer wishes to see all of it. For gigantic outputs, this can be a shell saver.

Delete Removes all text from the prompt to the end of the line.

Down Moves the current line down one item in the history. By moving, this means the current line is replaced with history item.

Up Moves the current line up one item in the history By moving, this means the current line is replaced with history item.
Typing a reference name followed by a ? will create a object view which gives the user a variety of information about the Object in question. Example::

a = 'meoooowwww' a? # Upon Enter, a panel will appear below showing Object information.
Typing ! at the command prompt followed by the system command you wish to execute will start the command as a process and return a JPID for the process that can be manipulated by the magic command set.
Entering one of the following commands will cause its corresponding command to execute:
JPIDs are not PIDs of the OS. They are a system by which the JythonShell can keep track of Processes created by it, and means by which the user can manipulate those Processes.

The CWD does not indicate what the process is working in. It is intended to function with the Magic Commands. This system does not interoperate with java.io.File or Jython open. To achieve interoperability the user should use the magic command of the form::

%cwd reference

This will place a java.io.File in the reference. The File instance is a copy of the CWD File and will allow the user to open, write, create, close streams and such in the JythonShell's CWD
``%alias`` *anAlias* defines alias name as an alias for cmd. Afterwards, typing alias name params will execute the system command cmd params (from your underlying operating system). Aliases have lower precedence than magic functions and Python normal variables, so if foo is both a Python variable and an alias, the alias can not be executed until you remove the Python using ``del foo``.
Toggles autocalling off and on. Autocalling is the ability to do something like::

dir a

instead of dir( a ).
Toggles autoindenting off and on.
Runs a method/function in a background thread. For example::

%bg doit()

This executes doit in a thread. The status of the operation can be seen by looking at the jobs object::

jobs.status() #Prints the status of the jobs.

Alternatively you can access the status like so::

jobs[jobnumber].result

jobnumber is printed out when the method/function is about to execute. The result will be the return value of the method/function or it will tell you the job isn't finished yet.
Changes the current working directory of the Jython Shell. ``..`` signifies the parent directory. Absolute and relative paths are allowed.
Destroys all JPIDs.
Clears the shell of all text and starts over with a fresh prompt.
Shows the current working directory of the Jython Shell.
Sets the reference to a java.io.File instance representing the current directory.
Deserialize an Object stored on disk into the reference.
Same as %edit.

Brings up the Jython Shell editor and executes the resulting code.

This command allows you to conveniently edit multi-line code right in your JythonShell session. If called without arguments, ``%edit`` opens up an empty editor with a temporary file and will execute the contents of this file when you close it (don t forget to save it!). Options:

-p Calls the editor with the same data as the previous time it was used, regardless of how long ago (in your current session) it was.

-x Suppresses execution of the edited code upon exit. This is mainly useful if you are editing programs which need to be called with command line arguments, which you can then do using %run.

If args are given, the following possibilities exist:

- The arguments are numbers or pairs of colon-separated numbers, e.g., ``1 4:8 9``. These are interpreted as lines of previous input to be loaded into the editor. The syntax is the same of the %macro command.

- If the argument doesn't start with a number, it is evaluated as a variable and its contents loaded into the editor. You can thus edit any string which contains python code (including the result of previous edits).
Prints all environment variables.
Prints all or part of the history. If given, the ``-n`` argument signifies that line numbers should not be printed out.

%hist [ -n ] Prints the total history or the last 40 items in it.

%hist [ -n ] n1 Prints the last n1 items in the history.

%hist [ -n ] n1 n2 Prints the items from index n1 to index n2.
Destroys JPID n.
Shows the contents of the current working directory.
Shows a java array of File instances. For example::

%ls a # a now holds a java array of File instances
Returns the current available set of magic commands.
Defines a macro that can be executed by using the name given. For example::

%macro macex 9:10 11 12:13 4

creates a macro called macex and puts line 9-10, 11 12-13 and 4 from the history into it Hence entering macex and typing enter will cause those lines to rexecute.

To see the contents of the macro type: ``print macroname``. To remove a macro type: ``del macroname``.
%magic Prints out the description of the magic commands.

%magic %magiccommandname Prints the usage/description of the given magic command.
Same as 'print'.
%pdb Starts the Pdb debugger.

%pdb filename

Runs the file under Pdb in the shell.

%pdb [on|1|off|0 ] Toggles automatic startup of Pdb on an exception. Examples::

%pdb on --> now on %pdb off --> now off %pdb 1 --> now on %pdb 0 --> now off
Prints out the doc string of the passed in object if one can be found, otherwise does nothing.

The object may be a module, a method, an object, etc.
Attempts to locate the source file of the passed in object and displays the contents of the source in the shell.
An alias for the ? object viewer syntax. If the references is valid, a widget containing info on the reference will appear.
Executes a statement entered on the same line in the profile module.
%ps Prints out all JPID's the JythonShell has collected.

%ps aReference Puts a java Set of Processes in the reference. For example:

%ps a #a now holds a Set of Processes.
Repeats the last input.
%rehash Updates the alias table with all entries in $PATH. This command does **not** check execute permissions or whether the contents of $PATH are truly files (instead of directories or something else).

%rehashx Updates the alias table with all executable files in $PATH. This command **does** explicitly check that every entry in $PATH is a file, so it is slower than %rehash.
Resets the namespace by removing all names defined by the user. Input/Output history remain in case you need them.
Runs the named file inside IPython as a program. Options:

-n: Suppresses setting ``__name__`` to ``__main__``. Instead, sets ``__name__`` to the file's name without extension (as Python does under import).

This allows running scripts and reloading the definitions in them without calling code protected by::

if __name__ == __main__:

-i: Runs the file in JythonShell's namespace instead of an empty one. This is useful if you are experimenting with code written in a text editor which depends on variables defined interactively.

-t: Prints timing information at the end of the run.

-N n: If -t is given this option indicates how many times you want the script to run. ``n`` must be an integer. The final timing report will include total and per run results.
This command uses the same syntax as %macro for line extraction, but instead of creating a macro it saves the resulting string to file whose name is given. It ensures the filename ends with a .py extension, and it asks for confirmation before overwriting existing files.
Runs the given command using ``command.getoutput()`` and updates the user's interactive namespace with a variable called varname containing the value of the call. Your command can contain shell wildcards, pipes, etc. The ``=`` is mandatory, and the variable name must be a valid Python identifier. Options:

-l: List output. Splits the output on newlines into a list before assigning it to the given variable. By default the output is stored as a single string.

-v: Verbose. Prints the contents of the variable.
%see n Shows any output JPID n has collected.

%see n aReference Places any output JPID n has collected in the reference.
Sends the reference as input to JPID n.
Saves the object referenced by reference as a serialized Object.
Places the reference into the editor if the reference is a JComponent subclass. Useful for quick gazing of what a Swing component looks like.
Runs the given command using commands.getoutput(), and returns the result formatted as a list (split on). The output is stored in ipython's regular output cache Out[N] and in the N automatic variables.
Shows the threads running and the state they are in. Selecting a thread shows the thread's stack.
Removes the given alias.
Loads data from a url into a reference. For example::

%url a http://python.org

take the data at ``http://python.org`` and places it in ref.
Suspends the JythonShell until JPID n has finished.
Prints the list of identifiers that have been defined interactively.
Returns a sorted list of all interactive variables. If arguments are given, only variables of types matching these arguments are returned. Examples::

%who_ls %who_ls str int #this prints out variables whose type is str and int
Prints a table of identifiers that have been defined interactively.
Transforms reference ref2 with the stylesheet in ref1 putting the result in ref3.
http://sourceforge.net/forum/message.php?msg_id=3450435
http://sourceforge.net/forum/message.php?msg_id=3389810
- The abbreviation and buffer commands are not ready yet.

- repeat-complex-command does not work.

- Moving the cursor when the 'mark' has been defined does not expand the visibly selected text.

- Yanking and killing have not been well tested.

- C-u 5 <return> works but is not undone properly. Also, the kill-line command does not work as in Emacs.

- Many new commands must be generalized to handle the more complex environment Leo offers. For example, search commands must be told whether to limit the search a single node, or a node or and its descendants, or the entire outline. We need a set-variable command that sets a (Python) variable using an emacs-style variable name.

- The notion of the 'point' must be expanded so it indicates a node as well as text location.

- New commands are needed to support 'mouseless-Leo'. The user must be able to drive all dialogs from the keyboard, or to get the same effect without using a dialog at all. Examples: dismiss-top-dialog, scroll-outline-up/down. We also need commands to change focus and to manage menus. Examples: focus-in-body, focus-in-tree, etc, activate-edit-menu, etc.
Leo 4.4 alpha 5 January 6, 2006

This release completes the last major features of Leo 4.4:

- User-specified key-binding modes. - Support for multiple key-bindings for individual minibuffer commands.

This will be the last alpha version of Leo 4.4. Beta 1 is coming in about a week. You should be able to use this version safely; there are no known serious bugs.

To learn about Leo, see: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4: ---------------------------------- - An Emacs-like mini-buffer: you can now execute any command by typing its long name. Support for tab completion.

- A tabbed log pane. The Find and Spell Check commands now use tabs instead of dialogs, making those commands much easier to use. Plugins or scripts can easily create new tabs. The Completion tab shows possible typing completions.

- Support for most commands in the Emacs Cmds menu, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles.

- Per-pane key bindings. You can bind shortcuts to multiple commands depending on which of Leo's panes presently has focus. For example, you can use arrow keys to move nodes in the outline pane, while retaining their defaults in Leo's body pane.

- User-specified key-binding modes. This feature makes it possible to emulate all aspects of Emacs and Vim as far as key bindings are concerned.

- @command nodes create minibuffer commands. You can bind key shortcuts to @button and @command nodes.

- Leo recovers from crashes much more reliably than in any previous version.

- Leo handles keystrokes and updates the screen immediately rather than waiting for idle time.
http://sourceforge.net/forum/message.php?msg_id=3464874
http://sourceforge.net/forum/message.php?msg_id=3466412

New in Leo 4.4: Leo calls the 'headkey1' and 'headkey2' hooks only when the user completes the editing of a headline, and ch is always '\r', regardless of platform.

http://sourceforge.net/forum/message.php?msg_id=3462294
http://sourceforge.net/forum/message.php?msg_id=3467558

What I did:

- atFile.readError deletes root's entire subtree. - atFile.read only warns about unvisited node if there is no error.
http://sourceforge.net/forum/message.php?msg_id=3461068

And a recent bug: clicking in the expand/contract box didn't save the headline.
The problem was caused by the recent change to g.app.gui.setTextSelection.

The default for the new 'insert' keyword must be sel.end for compatibility with old code.
Read @file Nodes and Import Derived File commands no longer create copies of the root node.
The provide batch-mode unit testing.
Leo now supports the following commands, shown below with their present bindings:

back-char ! text = LtArrow back-char-extend-selection ! text = Shift-LtArrow back-paragraph ! text = Alt-braceleft back-paragraph-extend-selection ! text = Alt-Shift-braceleft back-sentence ! text = Alt-a back-sentence-extend-selection = None back-word ! text = Alt-b # No conflict back-word-extend-selection ! text = Alt-Shift-b beginning-of-buffer ! text = Alt-less # Note: same as Alt-Shift-less beginning-of-buffer-extend-selection = None beginning-of-line ! text = Ctrl-a beginning-of-line-extend-selection = None exchange-point-mark = None forward-char ! text = RtArrow forward-char-extend-selection ! text = Shift-RtArrow forward-paragraph ! text = Alt-braceright forward-paragraph-extend-selection ! text = Alt-Shift-braceright forward-sentence ! text = Alt-e forward-sentence-extend-selection ! text = Alt-Shift-e forward-word ! text = Alt-f forward-word-extend-selection ! text = Alt-Shift-f next-line ! text = DnArrow next-line-extend-selection ! text = Shift-DnArrow previous-line ! text = Uparrow previous-line-extend-selection ! text = Shift-UpArrow

The -extend-selection variants move the cursor and also extend the selection from the insert point in the indicated direction. As usual exchange-point-mark switches the insert point from one side of the selection to the other: which side of the selection the insert point is on does make a difference.

I also added three commands that implement so-called 'extend mode':

clear-extend-mode = None set-extend-mode = None toggle-extend-mode = None

When extend mode is on (it is off at first), all cursor movement commands listed above extend the selection. Very handy. Thanks to Brian for this suggestion.

This is the start of mouseless Leo. For the first time all the common Emacs cursor-movement commands exist. These commands should work in any text widget.
leoSettings.leo now contains a node called:

@@shortcuts traditional Leo bindings

This node contains the 'classic' Leo key bindings that appeared in Leo 4.3. I have proofed these settings carefully, but some errors may remain. Please report any errors or any other suggestions for these settings.
You must install the Aspell package if you want to use Leo's Spell tab.

1. Download and install the Aspell package from http://aspell.sourceforge.net/ Typically this will create a directory called Aspell/bin

2. If you are using Python 2.3 or Python 2.4 you must copy a dll from Leo's extensions folder to the Aspell/bin directory. This step is *not* needed if you are using Python 2.5 or later. Leo's extensions folder comes with two dll's: aspell23.pyd and aspell24.pyd, for Python 2.3 and 2.4 respectively. Make a copy of the appropriate dll, **rename it** to be aspell.pyd, and copy the renamed aspell.pyd file to Aspell/bin.

3. Specify the location of the Aspell and Aspell/bin directories using the aspell_dir and aspell_bin_dir settings in LeoSettings.leo.
Leo no longer creates a duplicate root node when importing derived files.

The code is due to LeoUser.
The reason for this assert is unclear.
This is the end of the ill-fated settings dialog.

Important: you can use the show-colors and show-fonts commands to help set colors and fonts in leoSettings.leo.
Leo now allows you to specify input modes. You enter mode ``x`` with the ``enter-x-mode`` command. The purpose of a mode is to create different bindings for keys within a mode. Often plain keys are useful in input modes.

You can specify modes with ``@mode`` nodes in leoSettings.leo. ``@mode`` nodes work just like ``@shortcuts`` nodes, but in addition they have the side effect of creating the ``enter-<mode name>-mode`` command.

Notes:

- You can exit any mode using the ``keyboard-quit`` (Control-g) command. This is the **only** binding that is automatically created in each mode. All other bindings must be specified in the ``@mode`` node. In particular, the bindings specified in @shortcuts nodes are **not** in effect in mode (again, except for the keyboard-quit binding).

- Leo supports something akin to tab completion within modes: if you type a key that isn't bound in a mode a 'Mode' tab will appear in the log pane. This tab shows all the keys that you can type and the commands to which they are bound. The mode-help command does the same thing.

- ``@shortcuts`` nodes specify the bindings for what might be called the 'top-level' mode. These are the bindings in effect when no internal state is present, for example, just after executing the keyboard-quit command.

- The ``top_level_unbound_key_action`` setting determines what happens to unbound keys in the top-level mode. Leo ignores unbound keys in all other modes. The possibilities are 'insert', 'replace' and 'ignore'.

- The ``set-insert-mode``, ``set-overwrite-mode`` and ``set-ignore-mode`` commands alter what happens to unbound keys in the top-level mode.

With all these options it should be possible to emulate the keyboard behavior of any other editor.
A **dangerous** delete is a deletion of a node so that all the data in the node is deleted *everywhere* in an outline. The data is gone, to be retrieved only via undo or via backups. It may not be obvious which deletes are dangerous in an outline containing clones. Happily, there is a very simple rule of thumb::

Deleting a non-cloned node is *always* dangerous. Deleting a cloned node is *never* dangerous.

We could also consider a delete to be dangerous **if it results in a node being omitted from a derived file.** This can happen as follows. Suppose we have the following outline (As usual, A' indicates that A is marked with a clone mark)::

- @thin spam.py - A' - B - Projects - A' - B

Now suppose we clone B, and move the clone so the tree looks like this::

- @thin spam.py - A' - B' - Projects - A' - B' - B'

If (maybe much later), we eliminate B' as a child of A will get::

- @thin spam.py - A' - Projects - A' - B

B has not been destroyed, but B is gone from @thin spam.py! So in this sense deleting a clone node can also be called dangerous.
Leo 4.4 beta 1 January 17, 2006

The code is stable; there are no known serious bugs. Some features are incomplete.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4: -------------------------- - An Emacs-like mini-buffer: you can now execute any command by typing its long name, with tab completion.

- Many new commands, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles. You can use Leo without using a mouse.

- Flexible key bindings and input modes. You can emulate the operation of Emacs, Vim, or any other editor.

- A tabbed log pane. The Find and Spell Check commands now use tabs instead of dialogs, making those commands much easier to use. Plugins or scripts can easily create new tabs. The Completion tab shows possible typing completions.

- Dozens of other new features and bug fixes since Leo 4.3.3.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://sourceforge.net/cvs/?group_id=3458 Quotes: http://webpages.charter.net/edreamleo/testimonials.html
A 'backward' delete at the start of a headline deletes the first character. delete-char did not work in headlines.
http://sourceforge.net/forum/message.php?msg_id=3465251
http://sourceforge.net/forum/message.php?msg_id=3495741

The plugin now uses sys.getdefaultencoding() to set the encoding.
This could have been the source of weird find behavior.
The fix was to have x.getSelectedText return '' instead of None.
http://sourceforge.net/forum/message.php?msg_id=3510983
https://sourceforge.net/forum/message.php?msg_id=3514627

c.endUpdate now restores the previous focus by default.
http://sourceforge.net/forum/message.php?msg_id=3514755
http://sourceforge.net/forum/message.php?msg_id=3515341
http://sourceforge.net/forum/message.php?msg_id=3509141

Problems with cleo. Installed patch: http://sourceforge.net/forum/message.php?msg_id=3517080

https://sourceforge.net/forum/message.php?msg_id=3515025

Problems with fastgotonode and and groupOperations.
http://sourceforge.net/forum/message.php?msg_id=3518722

To generate HTML file I entered the outline header "@file bbb.xml" under which I put the following body text:

//////////////// beginning of excerpt @first <?xml version="1.0" encoding="windows-1250" ?> @language html @ comment line @c @others //////////////// end of excerpt

This works OK. But, if I put a space after the sole @ above "comment line", save and close the .leo file and then open it, Leo protests in log pane on the right:

//////////////// beginning of excerpt ----- error reading @file: bbb.xml Missing open block comment //////////////// end of excerpt
This corrects a problem that shows up as 'Invalid cross-device link' messages on Linux.

http://sourceforge.net/forum/message.php?msg_id=3519803
These should be considered bug fixes.

- copyBindingsToWidget now binds keys in priority order. This also simplifies and clarifies the code.

- Removed k.onTextWidgetKey. Added a callback that invokes k.masterCommand.
Hitting Backspace immediately put the focus in the log. Another backspace put the focus in the body pane.

The problem was in log.clearTab. It must do call t.update().
extensionHelper resets movePoint any time there is no selection.
The fix was to call endUpdate() rather than endUpdate(changed) in onHeadChanged.
g.top and the associated g.app.log logic is inherently unreliable.
This allows code to determine in a standard way whether a window is in the process of being destroyed.
This includes k.masterCommand and all event handlers.
Leo now calls doCommand on all commands, so the 'command' hooks and error processing always get done.
@nocolor
http://sourceforge.net/forum/message.php?msg_id=3518792

EKR: The change in focus happened in c.endEditing in at.writeFromString.

I added a new restoreFocus keyword arg to c.endEditing.
http://sourceforge.net/forum/message.php?msg_id=3515616

Could we have a visible-line-up and visible-line-down command? (I.e. to move the cursor up or down by a visible rather than a logical line). With these commands, the arrows plugin could be permanently retired!

What I did:

- next-line and prev-line now work as requested. This obsoletes the arrow plugin. - Removed the redundant tree.OnUpKey and tree.OnDownKey - Retired the arrows plugin.

- Created the extendHelper method. This creates and maintains the moveSpot, moveCol an moveSpotNode ivars, and is responsible for extending the selection range.
Still to do:

Specify what mode to enter after each command:

- command-name -> mode-name = binding

will specify what mode to enter after each command. At present, all commands exit to the top-level mode.

- Add @string active-keyset setting?
Leo 4.4 beta 2 February 14, 2006

This version fixes dozens of bugs, improves performance and polishes the user interface. The code is stable; there are no known serious bugs.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4b2: ---------------------------- - Much better 'fit and finishes'. - New commands that support mouseless Leo. - Minibuffer search commands provide all features of Leo's legacy search commands. - User modes are fully functional and you can create special bindings for the minibuffer. - New master key and click handlers and improved allocation of screen widgets.

Coming in Leo 4.4b3: -------------------- - A revived chapters plugin. - Autocompleter Tab. - Improved incremental searches.

The highlights of Leo 4.4: -------------------------- - An Emacs-like mini-buffer: you can now execute any command by typing its long name, with tab completion.

- Many new commands, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles. You can use Leo without using a mouse.

- Flexible key bindings and input modes. You can emulate the operation of Emacs, Vim, or any other editor.

- A tabbed log pane. The Find and Spell Check commands now use tabs instead of dialogs, making those commands much easier to use. Plugins or scripts can easily create new tabs. The Completion tab shows possible typing completions.

- Dozens of other new features and bug fixes since Leo 4.3.3.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://sourceforge.net/cvs/?group_id=3458 Quotes: http://webpages.charter.net/edreamleo/testimonials.html
@nocolor

Must check for c.exists in c.executeScript after executing the script.
@nocolor

- keyboard-quit now ends editing.

- print-bindings shows plain keys only in 'ignore' mode.

- Removed k.add_ekr_altx_commands and k.makeHardBindings.

- Added binding to vim plain shortcuts: mode-help = h

- Print the initial mode when first creating a window. The change had to be made in g.openWithFileName because of the UNL plugin.

- Improved print-bindings & mode help.

- endMode retains the widget on entry, so e.g., inserting a new node retaining the headline editing state.

@color
@nocolor

- Added initialClickExpandsOrContractsNode settings. Clicking an node expands or contracts the node if this setting is True. EKR much prefers False.

- Selecting a headline should not select text in it.

@color
@nocolor

What I did:

- endMode must not change focus.

- modeHelp calls c.endEditing(retainFocus=True)

@color
Traceback (most recent call last):

File "c:\prog\leoCVS\leo\src\leoCommands.py", line 250, in doCommand val = command() # Call legacy command

File "C:\prog\leoCVS\leo\src\leoTkinterFrame.py", line 1777, in cutText oldText = w.get('1.0','end')

AttributeError: Canvas instance has no attribute 'get'
Call w.see('insert'), not w.see('insert-5L')
The outline jumps around too much when expanding/contracting nodes
# This is required now that scrolling is disabled by default.
- Replaced frame.xWantsFocus with c.xWantsFocus. - Added event arg to all legacy commands. - Replaced k.tkBindingFromSetting by k.shortcutFromSetting. - Replaced k.canonicalizeShortcut by k.shortcutFromSetting. - Replaced k.bindShortcut with bindKey. - k.makeBindingsFromCommandsDict does not call k.bindKey for mode bindings. - Call update_idletasks when writing to the log. - Updated selection point immediately in masterKeyHandler. Otherwise, updateStatusLine would be one click behind.
@nocolor

This is logically and practically dubious. True, a screen redraw shouldn't mess with the focus, but there are the following problems:

1. c.endUpdate can happen anytime, and it could interfere with other efforts to set focus. 2. g.app.get_focus might get the 'wrong' or a 'bad' focus.
A *major* improvement to the tree allocation code:

1. Use p.key() to as keys to tree.visibleText. This greatly speeds up tree.findEditWidget

2. Eliminated the brain-dead requirement that previously-allocated widgets must match the position. - The allocation code just gets *any* previously allocated widget. This eliminates an n**2 search! - The ancient problem was that theId refers to the *window* not its Text widget: the *window* must be moved to the right spot.

3. recycleWidgets is simpler and a bit faster.

4. destroyWidgets now works: (the bug was not clearing tree.ids).
- Improved format of print-commands and print-bindings commands.

- Eliminated clone-find-all, selection-only, show-context checkboxes when show_only_find_tab_options setting is True.

- All minibuffer find commands copy the find string from the Find tab into the minibuffer.

- The replace-string command sets up arguments for Tab find. This is different from the normal Emacs replace-string command, but it works well in Leo.

- Leo doesn't abort the minibuffer if the command does not exist. This is much more convenient.
Leo's extensions folder contains Pmw in official distributions, but not in the Cvs repository, so you won't be able to use a Leo in a sandbox unless you copy Pmw to the extensions folder or have Pmw otherwise available on Python's path.
In the new drawing scheme, tree.redraw_now always calls c.endEditing, which calls tree.onHeadChanged. The effect of this was to reverse the action of undo/redoNodeContents.

The solution was to change the edit widget directly before calling tree.redraw_now. To do this, I created the new tree.setHeadline method.
* Found the reason why focus was *still* sticking in the outline pane: - The click handlers must return 'break', not continue. - However, OnActivateHeadline must return 'continue' when the headline is active so that Tk will handle the click properly.

- UNL does not seem to be causing problems.

- No need to save/restore focus in status line.

- Added several new traces to tkTree class.

* tree.redraw_now now ends editing properly. This fixes lots of bugs. In particular, it avoid any chance that p.edit_widget won't correspond to the present position.

- k.masterClickHandler calls tree.OnDeactivate() if there is no callback function. This solves most headline focus problems, provided that all panes bind clicks to k.masterClickHandler.

- toggle-active-pane now ends editing properly.

- insert-headline now calls c.editPosition after calling c.endUpdate().
Backspace in empty body text sometimes moved focus to canvas, and sometimes improperly drew icon.

Made several fixes to onBodyChanged. There was no test for unchanged text! This could have created all sorts of problems for undo.
@ This revealed several problems:

- Most find dialog commands do not actually exist. All find commands except open-find-dialog actual refer to the find tab.

- Several other minor shortcut problems.
http://sourceforge.net/forum/message.php?msg_id=3549737

for extend selection, with binding to arrow keys, if you switch from up to down arrow, the selection restarts again. this should just change extend direction while still using the same selection.
select-all-text, move back/forward line/char, start/end-of-line.
All minibuffer search commands, with the exception of the isearch (incremental) commands, simply provide a minibuffer interface to Leo's legacy find commands. This means that all the powerful features of Leo's legacy commands are available to the minibuffer search commands.

Note: all bindings shown are the default bindings for these commands. You may change any of these bindings using @shortcuts nodes in leoSettings.leo.

Settings

leoSettings.leo now contains several settings related to the Find tab:

- @bool show_only_find_tab_options = True

When True (recommended), the Find tab does not show the 'Find', 'Change', 'Change, Then Find', 'Find All' and 'Change All' buttons.

- @bool minibufferSearchesShowFindTab = True

When True, Leo shows the Find tab when executing most of the commands discussed below. It's not necessary for it to be visible, but I think it provides good feedback about what search-with-present-options does. YMMY. When True, the sequence Control-F, Control-G is one way to show the Find Tab.

Basic find commands

- The open-find-tab command makes the Find tab visible. The Find tab does **not** need to be visible to execute any search command discussed below.

- The hide-find-tab commands hides the Find tab, but retains all the present settings.

- The search-with-present-options command (Control-F) prompts for a search string. Typing the <Return> key puts the search string in the Find tab and executes a search based on all the settings in the Find tab. This command is my 'workhorse' search command.

- The show-search-options command shows the present search options in the status line. At present, this command also shows the Find tab.

Search again commands

- The find-tab-find command (F3) is the same as the search-with-present-options command, except that it uses the search string in the find-tab. This is what I use as my default 'search again' command.

- Similarly, the find-tab-find-previous command (F2) repeats the command specified by the Find tab, but in reverse.

- The find-again command a combination of the search-with-present-options and find-tab-find command. It is the same as the find-tab-find command if a search pattern other than '<find pattern here>' exists in the Find tab. Otherwise, the find-again is the same as the search-with-present-options command.

Setting find options

- Several minibuffer commands toggle the checkboxes and radio buttons in the Find tab, and thus affect the operation of the search-with-present-options command. Some may want to bind these commands to keys. Others, will prefer to toggle options in a mode.

Here are the commands that toggle checkboxes: toggle-find-ignore-case-option, toggle-find-in-body-option, toggle-find-in-headline-option, toggle-find-mark-changes-option, toggle-find-mark-finds-option, toggle-find-regex-option, toggle-find-reverse-option, toggle-find-word-option, and toggle-find-wrap-around-option.

Here are the commands that set radio buttons: set-find-everywhere, set-find-node-only, and set-find-suboutline-only.

- The enter-find-options-mode (Ctrl-Shift-F) enters a mode in which you may change all checkboxes and radio buttons in the Find tab with plain keys. As always, you can use the mode-help (Tab) command to see a list of key bindings in effect for the mode.

Search commands that set options as a side effect

The following commands set an option in the Find tab, then work exactly like the search-with-present-options command.

- The search-backward and search-forward commands set the 'Whole Word' checkbox to False.

- The word-search-backward and word-search-forward set the 'Whole Word' checkbox to True.

- The re-search-forward and re-search-backward set the 'Regexp' checkbox to True.

Find all commands

- The find-all command prints all matches in the log pane.

- The clone-find-all command replaces the previous 'Clone Find' checkbox. It prints all matches in the log pane, and creates a node at the beginning of the outline containing clones of all nodes containing the 'find' string. Only one clone is made of each node, regardless of how many clones the node has, or of how many matches are found in each node.

Note: the radio buttons in the Find tab (Entire Outline, Suboutline Only and Node only) control how much of the outline is affected by the find-all and clone-find-all commands.

Search and replace commands

The replace-string prompts for a search string. Type <Return> to end the search string. The command will then prompt for the replacement string. Typing a second <Return> key will place both strings in the Find tab and executes a **find** command, that is, the search-with-present-options command.

So the only difference between the replace-string and search-with-present-options commands is that the replace-string command has the side effect of setting 'change' string in the Find tab. However, this is an extremely useful side effect, because of the following commands...

- The find-tab-change command (Ctrl-=) replaces the selected text with the 'change' text in the Find tab.

- The find-tab-change-then-find (Ctrl--) replaces the selected text with the 'change' text in the Find tab, then executes the find command again.

The find-tab-find, find-tab-change and find-tab-change-then-find commands can simulate any kind of query-replace command. **Important**: Leo presently has separate query-replace and query-replace-regex commands, but they are buggy and 'under-powered'. Fixing these commands has low priority.

- The find-tab-change-all command changes all occurrences of the 'find' text with the 'change' text. Important: the radio buttons in the Find tab (Entire Outline, Suboutline Only and Node only) control how much of the outline is affected by this command.

Incremental search commands

Leo's incremental search commands are completely separate from Leo's legacy search commands. At present, incremental search commands do not cross node boundaries: they work only in the body text of single node.

Coming in Leo 4.4b3: the incremental commands will maintain a list of previous matches. This allows for

a) support for backspace and b) an incremental-search-again command.

Furthermore, this list makes it easy to detect the end of a wrapped incremental search.

Here is the list of incremental find commands: isearch-backward, isearch-backward-regexp, isearch-forward and isearch-forward-regexp.'''
@nocolor http://sourceforge.net/forum/message.php?msg_id=3549737

\src\leoEditCommands.py:340: Warning: 'yield' will become a reserved keyword

for python2.2 leoEditCommands.py needs from __future__ import generators

Also changed the following plugins:

at_produce.py fastGotoNode.py rst3.py zodb.py
http://sourceforge.net/forum/message.php?msg_id=3549737

The fix was to call getBool rather than getString.
http://sourceforge.net/forum/message.php?msg_id=3237845

On startup, it asked me for a unique id, "possibly your CVS username". As a non-windows-user, that made no sense at all to me - at very least, it should fill in os.getenv("USER") as a default, because it's right on non-windows systems, isn't it? (If it isn't, there's no explanation at that point that would tell me otherwise, that's the value I used anyway...) Just an out-of-box-experience issue.
http://sourceforge.net/forum/message.php?msg_id=3534349 By: edcdave

Saving the Leo file is not sufficient - I have to exit the document and open it again before the rst destination directory is set correctly.

The fix was to set c.frame.openDirectory in save.
The problem: event.widget is the minibuffer. It must be the body text.

- k.fullCommand saves the initial event and passes it on to callAltXFunction.

- There was a bug in c.masterFocusHandler. The correct test for 'no change' is:

if c.hasFocusWidget and c.requestedFocusWidget == c.hasFocusWidget:

** Important: the 'extra' calls to set_focus are correct. The minibuffer messes with the tab pane, and so we *must* be careful to yank the focus back to the body.
http://sourceforge.net/forum/message.php?msg_id=3538274

It's not clear that there were serious problems with the plugin, but I improved the code and error messages. All features work for me.

Several plugins use the icon-double-click hook. The reported problems could have been due to plugin conflicts.
http://sourceforge.net/forum/message.php?msg_id=3517080
http://sourceforge.net/forum/message.php?msg_id=3571431 By: ktenney

To reiterate a request:

When doing File->Open the default directory should the directory which was navigated to for previous 'Open'

What I did:

- Defined g.app.globalOpenDir # The directory last used to open a file.
New settings:

- @int max_undo_stack_size - @bool minibufferSearchesShowFindTab - @bool show_only_find_tab_options

New debugging settings:

@bool allow_idle_time_hook @bool gc_before_redraw @bool show_tree_stats @bool trace_bindings @bool trace_doCommand @bool trace_f.set_focus @bool trace_focus = False @bool trace_g.app.gui.set_focus @bool trace_gc @bool trace_gc_calls @bool trace_gc_verbose @bool trace_masterClickHandler @bool trace_masterCommand @bool trace_masterFocusHandler @bool trace_masterKeyHandler @bool trace_modes @bool trace_redraw_now @bool trace_select @bool trace_tree @bool trace_tree_alloc @bool trace_tree_edit @bool use_syntax_coloring @string trace_bindings_filter @string trace_bindings_pane_filter
Debugging commands:

- dump-all-objects, ump-new-objects, verbose-dump-objects. - free-text-widgets.

Find commands:

See the child of this node for details.

- find-again. - find-all and clone-find-all. - find-tab-find command, find-tab-find-previous. - find-tab-change, find-tab-change-all, find-tab-change-then-find. - hide-find-tab, open-find-tab. - re-search-forward and re-search-backward. - replace-string. - search-with-present-options. - search-backward and search-forward. - show-search-options. - word-search-backward and word-search-forward.

Search options:

- set-find-everywhere, set-find-node-only, and set-find-suboutline-only. - toggle-find-ignore-case-option, toggle-find-in-body-option, toggle-find-in-headline-option, toggle-find-mark-changes-option, toggle-find-mark-finds-option, toggle-find-regex-option, toggle-find-reverse-option, toggle-find-word-option, toggle-find-wrap-around-option.

Mouseless Leo:

- activate-cmds-menu, activate-edit-menu, activate-file-menu activate-help-menu, activate-outline-menu, activate-plugins-menu, activate-window-menu. - contract-body-pane, contract-log-pane, contract-outline-pane, contract-pane. - expand-body-pane, expand-log-pane, expand-outline-pane, expand-pane. - fully-expand-body-pane, fully-expand-log-pane, fully-expand-outline-pane, fully-expand-pane. - hide-body-pane, hide-log-pane, hide-outline-pane, hide-pane. - click-click-box, click-headline, click-icon-box, double-click-headline, double-click-icon-box, simulate-begin-drag, simulate-end-drag. (These commands trigger event hooks. In particular, double-click-icon-box will invoke the vim or xemacs plugins if they are enabled.)
The problem with focus 'sticking' in the Pmw.Notebook was due to a call to bringToFront. Apparently, the side effect was to assign a focus to the widget that had it previously. This makes sense, and can not be considered a Tk bug.

Remove almost all calls to w.update in Leo.

No more calls to w.after that were used to draw the status line. The master key and click handlers now call the label update method directly. This may ease a major stress on Tk.
- @mode nodes in leoSettings.leo allow you to specify input modes with separate key bindings.

See the child of this node for full details.

- All key bindings specified with !mini pane specifier apply to all modes.

Leo 4.4 experimental 1 February 15, 2006

This version is an emergency measure. It's goals:

1. To fix some of the key-handling issues in Leo 4.4 b2. 2. To allow further experimentation with key handling. 3. To allow easy reporting of any other key handling problems.

Please do not use this version (or Leo 4.4b2) unless you are ready to report bugs.

My apologies for the key handling problems in Leo 4.4 b2. I hope this version will be all that is necessary to fix those problems.

Here are the details of the key-handling changes:

- Added support for trace_key_event setting. - Added support for ignore_caps_lock setting. - Added Caps_Lock and Num_Lock to k.tkNamesList and in the list of special keys in k.masterCommand and k.masterKeyHandlerHelper. - Added support for k.ignore_unbound_non_ascii_keys logic in masterKeyHandlerHelper. - Disabled unknown keysym trace in k.strokeFromEvent. - Enabled the international keyboard on XP as an aid to testing. - Added support for swap_mac_keys setting in k.shortcutFromSetting.
extract = Shift-Ctrl-D extract-names = Shift-Ctrl-N extract-section = Shift-Ctrl-S # Shift-Ctrl-E: end-of-line-extend-selection

write-at-file-nodes = Shift-Ctrl-W # Was enter-file-mode. write-dirty-at-file-nodes = Shift+Ctrl+Q

# Removed definitions of find and file modes. I never used them.
http://sourceforge.net/forum/message.php?msg_id=3545403
The patch was reported at:

http://sourceforge.net/forum/message.php?msg_id=3577681

Thanks to caugm.
http://sourceforge.net/forum/message.php?msg_id=3573470

What I did:

- Added support for trace_key_event setting. - Added support for ignore_caps_lock setting. - Added Caps_Lock and Num_Lock to k.tkNamesList and in the list of special keys in k.masterCommand and k.masterKeyHandlerHelper. - Added support for k.ignore_unbound_non_ascii_keys logic in masterKeyHandlerHelper. - Disabled unknown keysym trace in k.strokeFromEvent. - Enabled the international keyboard on XP as an aid to testing. - Added support for swap_mac_keys setting in k.shortcutFromSetting.
Leo 4.4 alpha 6 February 17, 2006

Leo 4.4 b2 was broken on some platforms. Leo 4.4 a6 should fix those problems forever. However, only wider distribution will verify that for certain.

Besides fixing the fatal problems with Leo 4.4b2, this version fixes two minor bugs and adds some new settings in leoSettings.leo.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4 b2 and a6: ---------------------------- - Smoother user interface. - New commands that support mouseless Leo. - Minibuffer search commands provide all features of Leo's legacy search commands. - User modes are fully functional; you can create special bindings for the minibuffer. - New master key and click handlers and improved allocation of screen widgets.

Coming in Leo 4.4b3: -------------------- - A revived chapters plugin. - Autocompleter Tab. - Improved incremental searches.

The highlights of Leo 4.4: -------------------------- - An Emacs-like mini-buffer: you can now execute any command by typing its long name, with tab completion.

- Many new commands, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles. You can use Leo without using a mouse.

- Flexible key bindings and input modes. You can emulate the operation of Emacs, Vim, or any other editor.

- A tabbed log pane. The Find and Spell Check commands now use tabs instead of dialogs, making those commands much easier to use. Plugins or scripts can easily create new tabs. The Completion tab shows possible typing completions.

- Dozens of other new features and bug fixes since Leo 4.3.3.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://sourceforge.net/cvs/?group_id=3458 Quotes: http://webpages.charter.net/edreamleo/testimonials.html
The new scheme binds to keystrokes, not commands. This should be as portable and robust as all previous versions (except b2, which was broken).

- Created k.completeAllBindings, called last in k.makeAllBindings. This binds all keystrokes in k.bindingsDict to k.masterKeyHandler with an optional stroke argument. This allows k.masterKeyhandler to dispense with the problematic call to k.strokeFromEvent. This is all that is really required.

- Added code to menu.createMenuEntries that clears the accelerator on MacOS for any key that isn't a control, alt or command key. This solves the recurring problems with the Return key. The only effect is that the menu won't mention a binding that is actually in effect, but apparently that cannot be helped.

- Added g.safeCompareStrings, which may, or may not, fix the crasher when comparing k.abortAllModesKey to the incoming keystroke in k.masterKeyHandler. It's a bit tricky to test.

- The ignore_caps_lock is no longer functional. Sigh. This depends on knowing the Caps_Lock bit in key events. I may put this back later, but I can't delay a6 even a minute for this.
- Fixed crasher in k.masterCommand.

- Arrow keys no longer destroy UNL line
- @bool trace_autocompleter # The autocompleter itself is not ready yet. - @bool trace_key_event - @bool trace_minibuffer - @bool trace_status_line
This white paper originally appeared in November 2003 as a series of postings to comp.lang.python. Many features have been added since then. I rewrote this paper in February 2006.

Those who use Leo know that it is a superb environment for programming, authoring and managing data and project. Leo's power comes from combining just two basic elements:

- The organization power of outlines, including clones. - The power and simplicity of the Python language.

This paper explains in detail how combining these two features can, in fact, create immense and largely unexpected power and flexibility. To summarize:

- Outlines with clones are a superb filing cabinet for organizing text, including programs and scripts, or in fact any other information. This is the obvious aspect of outlines, but it is by no means the most powerful.

- Scripts can be composed of multiple nodes using noweb markup. Not only do outlines organize scripts, but scripts can be composed of outlines. In other words, Leo can *compose* scripts by concatenating descendant nodes and sections. Leo uses the noweb markup language to compose scripts in a flexible manner.

- Outline nodes split text, including programs and scripts, into *easily accessible*, discreet parts. Scripts may access nodes and their headlines and body text without any parsing.

- Nodes provide an easy associating the *description* of data with the data itself. Indeed, headlines naturally describe the node's body text. Leo's users have discovered many ways to take advantage of the unification of data and its description.

- Programs may treat nodes as *separate objects*, no matter what data the nodes contain. Because nodes are truly separate objects, it becomes easy and natural to define new *operations* on those objects, **based on the description of those outline found in the node's headline**.

The combination of these features created a chain reaction of creative uses for outlines. The result has been an explosion of new ideas and capabilities.

Leo supports the following kinds of 'special' nodes: @test, @suite, @script, @url, @button, @button timer, @rst, @command, etc. Each of these kinds of nodes defines new objects and new operations on those objects. The following paragraph show how Leo's users can use these new objects and their operations

Scripting

- The execute script command executes the body text of the presently selected node in an environment containing three variables: ``c``, ``g`` and ``p``. Thus, all scripts have full and *easy* access to all data in the outline containing the script.

- The scripting plugin creates support for script nodes. We can treat a node as a script, and *apply that script to any other part of an outline*. This is called 'bringing scripts to data'. Leo's users can do this using script buttons as follows. Any @button node creates a script button in Leo's icon area. The name of the button is the node's headline; the script is the node's body text. The user can also create new script buttons using the 'Script Button' button. Pressing the 'Script Button' button creates a new script button, just as if the presently selected node were an @button node. Bringing scripts to data is an immensely powerful and useful feature: it has eliminated the need for Leo's previous script-find features.

- @command nodes create new minibuffer commands, complete with keyboard shortcuts. The headline defines the command name and an optional keyboard shortcut; the body text defines the command.

Unit testing

- We can treat a node as an individual unit test, and *automatically* create a subclass of UnitTest.TestCase for the script in that node. This is Leo's @test node feature. Leo will convert the body text of any @test node into a unit tests.

- Similarly, @suite nodes create suites of unit tests using the script in the @suite node.

- A unit test can get test data from any node in the outline in which it resides. Thus, outlines can contain not only unit tests, but the data for those tests.

Text formatting

- The rst3 plugin creates support for @rst nodes. @rst trees use outline structure to create document structure. This is a revolution in organizing documents. Full details [ref]

Organizing data

- @url nodes contain references to web addresses, including files on a local disk. Double-clicking an @url node opens a web browser on the given URL.

Plugins

- Plugins support many other kinds of user-defined objects and their associated operations. Some examples are @view, @read-only, @folder, @produce, @run, @startfile, etc. Writing plugins is easy. Python makes the programming as easy as possible; and Leo provides plugins with easy access to outlines and their data.
The body text of any Leo node may contain a Python script. The Execute Script commands executes this script in a in an environment, that predefines three variables: ``c``, ``g`` and ``p``. These variables allow easy access to all the data in the present outline. For example: the following script prints all the node of the outline in which the script is embedded::

for p in c.allNodes_iter(): indent = ' '*p.level() print '%s + %s' % (indent,p.headString()) # print the node's headline. print p.bodyString() # print the node's body.

For that matter, scripts can access any data anywhere on your hard drive, or all the data available on the web, for that matter. You knew that, but this "innocent" fact will be important later.

**Result 1**: Leo is a great environment in which to write Python scripts.
Leo's outline can organize any text (or other data for that matter).

**Result 2**: Leo is a great way to organize standalone scripts.

This seemingly simple result will turn out to have important implications.
As shown in the example above, scripts may get access to the headline or body text of any node in a Leo outline. Therefore, scripts may use the *structure* of the outline to gain access to

a) other scripts, b) fragments of code for exec or eval or c) other data.

**Result 3**: Scripts have can treat outline structure as first-class data.

The first "big" reason why the combination of Python & Leo is spectacular. It gets better...
The body text of a node is the perfect place data itself (including other scripts). The headline of the node is the perfect place to *describe* the data. That is, headlines are a natural place for meta-data. Scripts can use this meta-data in many creative ways.

**Result 4**: Scripts have easy access to user-definable meta-data.
I first saw the power of results 2, 3 and 4 when creating unit tests for Leo. Indeed, the body text of a node is the perfect place for putting regression test data. Headlines describe the data, which is exactly what is needed for organizing tests. Indeed, I use a script to create regression tests based on the structure of the outline of the children of the node containing the script (!)

For example, I run the following script to create and run unit tests of Leo's colorizer::

import unittest,leoTest suite = leoTest.makeColorSuite("colorizerTests","tempNode") runner = unittest.TextTestRunner() runner.run(suite)

This works as follows: the arguments to makeColorSuite tell it to look up the tree for of an ancestor of the present node (the node containing this script) for a node whose headline is "colorizerTests". makeColorSuite then looks for children of *that* node for nodes containing test data. The node whose headline is "tempNode" is used by the colorizer during the tests. Here is the actual code of makeColorSuite::

def makeColorSuite(testParentHeadline,tempHeadline): """Create a colorizer test for every descendant of testParentHeadline.""" u = testUtils() ; c = top() ; v = c.currentVnode() root = u.findRootNode(v) temp_v = u.findNodeInTree(root,tempHeadline) vList = u.findSubnodesOf(testParentHeadline) # Create the suite and add all test cases. suite = unittest.makeSuite(unittest.TestCase) for v in vList: test = colorTestCase(c,v,temp_v) suite.addTest(test) return suite

The power and simplicity of this code is breathtaking. All that is required are two utility routines, findNodeInTree and findSubnodesOf that find various nodes in an outline based on the outline structure and the headlines of the nodes:

- findNodeInTree(root,tempHeadline) returns the node in the entire tree contain the current node whose headline is tempHeadline.

- u.findSubnodesOf(testParentHeadline) returns a list of all children of the node whose name is testParentHeadline.

In short, it is absolutely trivial for a script embedded in a Leo outline to generate unit tests based on the data in the outline in which the script is embedded!

Notice, please, what does *not* have to be done:

A. No unit tests are created statically: everything is driven by data (the outline itself)

B. No Python test data is created *at all*. Before I saw this approach, I was putting text for the syntax-coloring text in Python strings and passing those strings to the regression tests. Now, the *unchanged* data in the body text of nodes becomes the regression test data.

C. There is no need to mark meta-data as separate from test data: headlines are naturally distinct from body text.

We see now that Reasons 2, 3 and 4 are a lot more potent than they might appear at first. Indeed, Leo plus Python is the ultimate merging of code, structure and data. Scripts can use data organized in outlines. Outlines organize scripts. Outlines (particularly their structure) are *data* for scripts. Outlines contains metadata for scripts. Outlines naturally keep data and meta-data separate.

Please notice, this discussion merely hints at all the games that scripts could play with outline structure. Just for example, scripts can easily insert, delete and reorganize nodes. And the uses to which outline structure may be put are practically unlimited, as we shall see later...

Let's turn now to a completely separate topic...
A few days ago I have added a script-based option to Leo's Find/Change panel. For more than 30 years I have been disgusted with tools like regular expressions. Calling re powerful is an utter joke; it's way too complex and way too wimpy. Script-based find-change is infinitely more powerful. Instead of containing find text or change *text*, Leo's Find/Change panel may contains find or change *scripts*. This becomes possible because scripts have complete access to both the structure of the outline and all of Leo's code.

It all works so smoothly: The find script is responsible for traversing the tree and for highlighting the found text or otherwise indicating to the change script what the found text was. Leo dedicates a Python dict called app.searchDict for communication between the search script and the change script. The change script is responsible for:

- changing the text, typically by using c.setBodyString(p,newText), and

- implementing undo, typically by calling c.frame.onBodyChanged(p,"Change",oldText=oldText).

Some details:

- When executing the search and change scripts when the user selects the Find All or Change All commands, Leo executes the find or change scripts repeatedly only if app.searchDict.get("continue") evaluates to True. Otherwise these scripts are only executed once. Otherwise, scripts can use app.searchDict as they please.

- For simplicity, most find and change scripts will ignore settings in the Find Panel like "whole word", "pattern match", and "reverse": the scripts know what to do! However, these settings are available to the scripts via ivars such as c.whole_word_flag, etc. if desired.

- Either the find and change scripts may use Python's re module. For example, the find script could set app.searchDict["m"] to the match object returned by re's match method. The change script would then compute the result, change the text and set the undo info as usual.

In effect, Leo's Find/Change panel becomes a new platform for running scripts interactively. Leo now has all the find/change capability of pattern matching languages like Snobol and Icon, using the capabilities of the plain Python language. Moreover, Leo can deliver these capabilities interactively or not depending which buttons you push in Leo's Find/Change panel.

One last point. As I mentioned much earlier, there is no reason to confine the find and change scripts to operate on data only within a Leo outline. These scripts could as easily traverse your file system as the Leo outline. But notice: scripts could pull data from the file system into the outline so that you can see the effects of changes as the scripts operate. Again, this can all happen interactively if you like.

No, one more last point. It's convenient to defined an initScriptFind utility very similar to the makeColorSuite utility, used like this::

# Initialize Leo's find panel using the named children of this node. from leoGlobals import * initScriptFind("Find script","Change script") # Start searching at the top. top().selectVnode(c.rootVnode())

Put the search script in a child node called "Find script" (no quotes), put the change script in a child node called "Change script", execute this script and the following happens:

- The body text of "Find script" node gets put in the find text of Leo's Find/Change dialog.

- The body text of "Change script" node gets put in the find text of Leo's Find/Change dialog.

- The Script Find radio buttons gets selected, as does the Script Change checkbox.

- The root of the outline becomes the selected node.

Presto! Leo is ready for a script search.
One more feature greatly expands the generality and power of Leo's outlines combined with Python. Plugins may now attach arbitrary data to any node of a Leo outline. This is done merely by "injecting" an ivar called unknownAttributes ivar into Leo's fundamental vnode or tnode objects (or adding items to the unknownAttributes dict if it already exists). The unknownAttributes ivar should be a Python dictionary whose keys are xml attribute names and whose values are the values of those attributes.

When writing a file, Leo will write "foreign" attributes in the <v> or <t> xml elements of Leo's .leo file if the corresponding vnode or tnode contains this unknownAttributes ivar. Similarly, Leo will create an unknownAttributes ivar for a vnode or tnode if the corresponding <v> or <t> element contains an attribute not normally used by Leo. Leo performs the standard xml escapes when writing unknown attributes, so plugins can put *anything* in the unknownAttributes dictionary. In particular, plugins may put xml in v.unknownAttributes or t.unknownAttributes.

This means, for example, that plugins may add anything that can be represented by xml (and that is *everything*) in any node of a Leo outline. In effect, Leo's file format is now completely extensible. BTW, plugins can override any aspect of Leo's behavior, so not only can Leo passively accept the data in "extended" .leo files, but plugins can extend Leo to *use* this data!
All the power of Leo derives directly from the power, flexibility and dynamism of Python. But making structure explicit as Leo outlines do adds an important new dimension, literally and figuratively, to Python. Moreover, Leo's Find/Change dialog creates a new environment from which to run Python scripts. At long last the full power of the unification of code and data is becoming apparent.
See the documentation for the `Rst3 plugin`_ for details.
Script buttons are a quick way of automating any task. Extremely useful. See the `Scripting plugin`_ for details.

Leo's core provides additional support for @test, @suite, @timer nodes. For details, see the documentation for `test buttons`_.
Leo 4.4 alpha 7 February 28, 2006

This version fixes some minor problems with Leo 4.4a6 and adds autocompletion and calltips.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4: -------------------------- - An Emacs-like mini-buffer: you can now execute any command by typing its long name, with tab completion.

- Many new commands, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles. You can use Leo without using a mouse.

- Flexible key bindings and input modes. You can emulate the operation of Emacs, Vim, or any other editor.

- A tabbed log pane. The Find and Spell Check commands now use tabs instead of dialogs, making those commands much easier to use. Plugins or scripts can easily create new tabs. The Completion tab shows possible typing completions.

- Autocompletion and calltips. Autocompletion works much like tab completion.

- Dozens of other new features and bug fixes since Leo 4.3.3.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://sourceforge.net/cvs/?group_id=3458 Quotes: http://webpages.charter.net/edreamleo/testimonials.html
# http://sourceforge.net/forum/message.php?msg_id=3583335
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3586962 By: bwmulder

the open-find-dialog is broken.

Error: 4 TypeError Exception in Tk callback Function: <function findButtonCallback at 0x04E219F0> (type: <type 'function'>) Args: () Traceback (innermost last): File "C:\Python24\lib\site-packages\Pmw\Pmw_1_2\lib\PmwBase.py", line 1747, in __call__ return apply(self.func, args) TypeError: findButtonCallback() takes at least 1 argument (0 given)
# This was causing problems. It may be an easy fix, but I kinda doubt it.
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3597694 By: tfer

Template Plug-in (maybe others too) co,plain when activated: exception executing command Traceback (most recent call last): File "leoCommands.py", line 265, in doCommand val = command(event) File "c:\Leo_Cvs\Leo\plugins\plugins_menu.py", line 350, in about PluginAbout(self.name, self.version, self.doc) File "c:\Leo_Cvs\Leo\plugins\plugins_menu.py", line 576, in __init__ g.app.dialogs += 1 AttributeError: LeoApp instance has no attribute 'dialogs'
Typing a period when @language python is in effect starts autocompletion. Typing '(' during autocompletion shows the calltip. Typing Return or Control-g (keyboard-quit) exits autocompletion or calltips.

Autocompletion

Autocompletion shows what may follow a period in code. (Actually you can specify any character using the auto-complete shortcut setting.) For example, after typing g. Leo will show a list of all the global functions in leoGlobals.py. Autocompletion works much like tab completion in the minibuffer. Unlike the minibuffer, the presently selected completion appears directly in the body pane.

A leading period brings up 'Autocomplete Modules'. (The period goes away.) You can also get any module by typing its name. If more than 25 items would appear in the Autocompleter tab, Leo shows only the valid starting characters. At this point, typing an exclamation mark shows the complete list. Thereafter, typing further exclamation marks toggles between full and abbreviated modes.

If x is a list 'x.!' shows all its elements, and if x is a Python dictionary, 'x.!' shows x.keys(). For example, 'sys.modules.!' Again, further exclamation marks toggles between full and abbreviated modes.

During autocompletion, typing a question mark shows the docstring for the object. For example: 'g.app?' shows the docstring for g.app. This doesn't work (yet) directly for Python globals, but '__builtin__.f?' does. Example: '__builtin__.pow?' shows the docstring for pow.

Autocompletion works in the Find tab; you can use <Tab> to cycle through the choices. The 'Completion' tab appears while you are doing this; the Find tab reappears once the completion is finished.

Calltips

Calltips appear after you type an open parenthesis in code. Calltips shows the expected arguments to a function or method. Calltips work for any Python function or method, including Python's global function. Examples:

a) 'g.toUnicode(' gives 'g.toUnicode(s, encoding, reportErrors=False' b) 'c.widgetWantsFocusNow' gives 'c.widgetWantsFocusNow(w' c) 'reduce(' gives 'reduce(function, sequence[, initial]) -> value'

The calltips appear directly in the text and the argument list is highlighted so you can just type to replace it. The calltips appear also in the status line for reference after you have started to replace the args.

Options

Both autocompletion and calltips are initially enabled or disabled by the enable_autocompleter and enable_calltips settings in leoSettings.leo. You may enable or disable these features at any time with these commands: enable-auto-completer-command, enable-calltips-command, disable-auto-completer-command and disable-calltips-command.
You must create .leoRecentFiles.txt in the config directory. .leoRecentFiles.txt is part of the standard releases but is not part of the cvs repository.
Leo 4.4 beta 3 April 14, 2006

This version fixes some minor problems and adds various features. This code has been in use for several weeks without any major problems reported.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4: -------------------------- - An Emacs-like mini-buffer: you can now execute any command by typing its long name, with tab completion.

- Many new commands, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles. You can use Leo without using a mouse.

- Flexible key bindings and input modes. You can emulate the operation of Emacs, Vim, or any other editor.

- A tabbed log pane. The Find and Spell Check commands now use tabs instead of dialogs, making those commands much easier to use. Plugins or scripts can easily create new tabs. The Completion tab shows possible typing completions.

- Autocompletion and calltips. Autocompletion works much like tab completion.

- Dozens of other new features and bug fixes since Leo 4.3.3.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://sourceforge.net/cvs/?group_id=3458 Quotes: http://webpages.charter.net/edreamleo/testimonials.html
http://sourceforge.net/forum/message.php?msg_id=3608246

Added the following commands:

scroll-outline-down-line scroll-outline-down-page scroll-outline-up-line scroll-outline-up-page
It now properly creates bindings.
http://sourceforge.net/forum/message.php?msg_id=3572598
This is equivalent to the Unit Test script button in unitTest.leo
http://sourceforge.net/forum/message.php?msg_id=3619340

Just tried out CVS today, and on Linux left/right and L/R in outline mode (Ctrl-Shift-O) seem to do nothing, whereas they should expand/contract parent nodes.
http://sourceforge.net/forum/message.php?msg_id=3639193

The dirty bits were not updated properly in several undo/redo operations.
http://sourceforge.net/forum/message.php?msg_id=3642892

The present code is probably the best compromise between strict accuracy and marking too many nodes dirty.
http://sourceforge.net/forum/message.php?msg_id=3606515

Added insert-newline command and fixed some related commands.
Apparently g.app.unitTesting isn't set properly for the new-window test.
The bug: Hit control-f, then select the text that doesn't have focus.
http://sourceforge.net/forum/message.php?msg_id=3641107

ConfigSettings.initEncoding now uses the g.app.config settings if no other settings are available.

In particular, this causes at.encoding to be inited to a reasonable value.
- onBodyChanged now converts everything to unicode, either directly or by calling g.app.gui.getAllText.

- Replaced all calls to g.safeStringCompare by g.app.gui.getAllText which calls g.toUnicode.

- Converted all shortcuts to unicode in shortcutFromSetting (a.k.a strokeFromSetting)

- Removed g.safeStringCompare. This function was a bad idea.

Important: Leo is supposed to convert all characters to unicode, so there should never be a need for safeStringCompare. The proper way to avoid UnicodeError's is to call g.toUnicode(s,g.app.tkEncoding).
http://sourceforge.net/forum/message.php?msg_id=3607355
http://sourceforge.net/forum/message.php?msg_id=3573148

c.openWith now calls g.enableIdleTimeHook
These commands now set g.app.globalOpenDir.
http://sourceforge.net/forum/message.php?msg_id=3585710
http://sourceforge.net/forum/message.php?msg_id=3637393

I'm trying to set up a default stylesheet for a project and want this to be held relative to the project directory (where the .leo file is). The default is to place it in the same directory as the output, which is a couple of levels down.

http://sourceforge.net/forum/message.php?msg_id=3639216

g.os_path_dirname(self.outputFileName) with self.c.frame.openDirectory. This makes the path relative to the project. Not 100% as the stylesheet filename would need a path embedded in it to move the location down the tree. However, it is consistent with the way the output file is named.
See the chapters2 in leoPlugins.leo.

See also:

http://sourceforge.net/forum/message.php?msg_id=3626542

https://sourceforge.net/forum/message.php?msg_id=3629055

http://sourceforge.net/forum/message.php?msg_id=3632004
Cleaned up the code and added support minibuffer commands:

group-operations-clear-marked = Alt-Ctrl-Shift-l group-operations-mark-for-copy = Alt-Ctrl-Shift-c group-operations-mark-for-move = Alt-Ctrl-Shift-m group-operations-mark-for-clone = Alt-Ctrl-` group-operations-mark-target = Alt-Ctrl-Shift-t group-operations-operate-on-marked = Alt-Ctrl-Shift-o group-operations-transfer = Alt-Ctrl-Shift-d

This code has not been tested with the chapters2 plugin.
http://sourceforge.net/forum/message.php?msg_id=3617936

The fix was to plugins_menu.py: the cmd_callback must have an event argument.
The fix: all menu commands now have event=None in their argument list.
Alas, @if-gui can't be made to work. The problem is that plugins can set g.app.gui, but plugins need settings so the leoSettings.leo files must be parsed before g.app.gui.guiName() is known.
It's not ready for prime time.
Missing modules can cause installation problems. If the installer doesn't work (or puts up a dialog containing no text), you may install Leo from the .zip file as described at `How to install Leo on Windows`_. However you are installing Leo, be sure to `run Leo from a console window`_ because as a last resort Leo prints error messages to the console.
@nocolor http://sourceforge.net/forum/message.php?msg_id=3671350

Change aString.lstrip and aString.rstrip to the aString.replace. @color
leoID = ekr (in c:\Documents and Settings\Ed) reading settings in C:\prog\leoCVS\leo\config\leoSettings.leo reading settings in C:\prog\leoCVS\leo\src\LeoPy.leo rst3 plugin: SilverCity not loaded AttributeError Exception in Tk callback Function: <function bindKeyCallback at 0x016F2E70> (type: <type 'function'>) Args: (<Tkinter.Event instance at 0x03510288>,) Event type: KeyPress (type num: 2) Traceback (innermost last): File "C:\prog\leoCVS\leo\extensions\Pmw\Pmw_1_2\lib\PmwBase.py", line 1752, in __call__ return apply(self.func, args) File "C:\prog\leoCVS\leo\src\leoKeys.py", line 2002, in bindKeyCallback return k.masterKeyHandler(event,stroke=stroke) File "C:\prog\leoCVS\leo\src\leoKeys.py", line 2928, in masterKeyHandler val = self.masterKeyHandlerHelper(event,stroke) File "C:\prog\leoCVS\leo\src\leoKeys.py", line 2992, in masterKeyHandlerHelper val = k.callStateFunction(event) # Calls end-command. File "C:\prog\leoCVS\leo\src\leoKeys.py", line 2219, in callStateFunction val = k.state.handler(event) File "C:\prog\leoCVS\leo\src\leoKeys.py", line 348, in autoCompleterStateHandler self.insertNormalChar(ch,keysym) File "C:\prog\leoCVS\leo\src\leoKeys.py", line 856, in insertNormalChar self.calltip(obj) File "C:\prog\leoCVS\leo\src\leoKeys.py", line 455, in calltip obj = getattr(string,obj.__name__) AttributeError: 'module' object has no attribute 'startswith'
exception executing command Traceback (most recent call last): File "C:\prog\leoCVS\leo\src\leoCommands.py", line 264, in doCommand val = command(event) File "C:\prog\leoCVS\leo\src\leoCommands.py", line 884, in clearRecentFiles u.afterClearRecentFiles(bunch) File "C:\prog\leoCVS\leo\src\leoUndo.py", line 621, in afterClearRecentFiles u.pushBead(bunch) File "C:\prog\leoCVS\leo\src\leoUndo.py", line 192, in pushBead u.setUndoTypes() File "C:\prog\leoCVS\leo\src\leoUndo.py", line 341, in setUndoTypes u.cutStack() File "C:\prog\leoCVS\leo\src\leoUndo.py", line 136, in cutStack if bunch.kind == 'beforeGroup': AttributeError: 'Bunch' object has no attribute 'kind'
# No change for now C:\prog\tigris-cvs\leo\src\leoKeys.py:1050: Parameter (thread) not used

# Fixed C:\prog\tigris-cvs\leo\src\leoTkinterFrame.py:1428: Function returns a value and also implicitly returns None C:\prog\tigris-cvs\leo\src\leoTkinterTree.py:1222: Local variable (delta) not used C:\prog\tigris-cvs\leo\src\leoKeys.py:1931: Local variable (f) not used C:\prog\tigris-cvs\leo\src\leoGlobals.py:5246: Local variable (buttonList) not used C:\prog\tigris-cvs\leo\src\leoCommands.py:493: No global (enableIdleTimeHook) found
Leo 4.4 beta 4 April 21, 2006

This version fixes a long-standing MacOS bug. It is likely to be the last beta release before 4.4 final. This release also adds several new commands and contains a script for updating leoSettings.leo.

Warning: The previous beta was not widely distributed. Please do some testing in your environment before recommending this version of Leo to others, (such as your students).

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4: -------------------------- - An Emacs-like mini-buffer: you can now execute any command by typing its long name, with tab completion.

- Many new commands, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles. You can use Leo without using a mouse.

- Flexible key bindings and input modes. You can emulate the operation of Emacs, Vim, or any other editor.

- A tabbed log pane. The Find and Spell Check commands now use tabs instead of dialogs, making those commands much easier to use. Plugins or scripts can easily create new tabs. The Completion tab shows possible typing completions.

- Autocompletion and calltips. Autocompletion works much like tab completion.

- Dozens of other new features and bug fixes since Leo 4.3.3.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://sourceforge.net/cvs/?group_id=3458 Quotes: http://webpages.charter.net/edreamleo/testimonials.html
See the (presently disabled) script button in scripts.leo at:

Buttons-->@@button updateSettings

From the docstring:

Here is a **preliminary** script that updates a new leoSettings.leo file (path2) from the settings in a previous leoSettings.leo file (path1). Presumably, the path2 file is the leoSettings.leo file from a new distribution, and the path1 file a leoSettings.leo file containing settings that you have modified. You must specify the full path of both files in the top-level @button node.

**Warning**: This script modifies the path2 file. Make sure that you don't mind modifying this file.

**Warning**: This script is unsophisticated in its update algorithm. If if finds corresponding nodes (node with the same settings name) in both outlines it simply replaces the node in the path2 file with the node in the path1 file. In particular, it does not keep track of individual shortcuts: it replaces the body of one @shortcuts node with the body of the corresponding @shortcuts node.

**Note**: If the path1 file contains a settings node not in the path2 file it attempts to create a new node in the corresponding place in the path2 file. If this is not possible, say because the structures of the files are different, the script places the new node as the last child of the @settings node in the path2 file.
The mini-buffer is a text area at the bottom of the body pane. You use it like the Emacs mini-buffer to invoke commands by their so-called *long name*. The following commands affect the minibuffer:

- **full-command**: (default shortcut: Alt-x) Puts the focus in the minibuffer. Type a full command name, then hit <Return> to execute the command. Tab completion works, but not yet for file names.

- **quick-command-mode**: (default shortcut: Alt-x) Like Emacs Control-C. This mode is defined in leoSettings.leo. It is useful for commonly-used commands.

- **universal-argument**: (default shortcut: Alt-u) Like Emacs Ctrl-u. Adds a repeat count for later command. Ctrl-u 999 a adds 999 a's.

- **keyboard-quit**: (default shortcut: Ctrl-g) Exits any minibuffer mode and puts the focus in the body pane.

For example, to print a list of all commands type Alt-X print-commands <Return>.

The following sections list the various commands that you can invoke from the minibuffer. **Important**: you may bind keystrokes to any of these commands. See `Chapter 8: Customizing Leo`_ for full details.
@nocolor http://sourceforge.net/forum/message.php?msg_id=3688804 By: paulpaterson

It seems that copying and pasting nodes with CTRL-SHIFT-C, V is not working. - (legacy bindings) - select a node - CTRL-SHIFT-C - CTRL-SHIFT-V - Vim opens up! I expect to paste the node. The clipboard doesn't seem to contain any XML - The menu items show that these keys are bound to the copy and paste node commands

*** Also on legacy bindings the arrow keys don't seem to move the cursor in the body.
@nocolor http://sourceforge.net/forum/message.php?msg_id=3692247 By: vpe

After cutting selection in the headline, headline area shrinks too much. Example: headline is 'NewHeadline', select last 'e', ctrl-x, it shrinks to 'Ne'

To fix by hand: add

s=g.app.gui.getAllText(w)

Just before

w.configure(width=f.tree.headWidth(s=s))

in cutText in leoTkFrame.py
@nocolor http://sourceforge.net/forum/message.php?msg_id=3692247

Find panel cannot be re-opened. Run open-find-dialog. Close it. Run open-find-dialog again -- crash.

The fix was to move the line:

self.top.protocol("WM_DELETE_WINDOW", self.onCloseWindow)

from createBindings to createFrame in the leoTkinterFind class.
TclError Exception in Tk callback Function: <function bindKeyCallback at 0x0169B170> (type: <type 'function'>) Args: (<Tkinter.Event instance at 0x01865EB8>,) Event type: KeyPress (type num: 2) Traceback (innermost last): File "C:\prog\tigris-cvs\leo\extensions\Pmw\Pmw_1_2\lib\PmwBase.py", line 1752, in __call__ return apply(self.func, args) File "c:\prog\tigris-cvs\leo\src\leoKeys.py", line 1991, in bindKeyCallback return k.masterKeyHandler(event,stroke=stroke) File "c:\prog\tigris-cvs\leo\src\leoKeys.py", line 2931, in masterKeyHandler val = self.masterKeyHandlerHelper(event,stroke) File "c:\prog\tigris-cvs\leo\src\leoKeys.py", line 2990, in masterKeyHandlerHelper val = k.callStateFunction(event) # Calls end-command. File "c:\prog\tigris-cvs\leo\src\leoKeys.py", line 2208, in callStateFunction val = k.state.handler(event) File "c:\prog\tigris-cvs\leo\src\leoKeys.py", line 2289, in fullCommand k.callAltXFunction(k.mb_event) File "c:\prog\tigris-cvs\leo\src\leoKeys.py", line 2327, in callAltXFunction func(event) File "C:\prog\tigris-cvs\leo\src\leoCommands.py", line 2801, in showFindPanel c.frame.findPanel.bringToFront() File "C:\prog\tigris-cvs\leo\src\leoTkinterFind.py", line 469, in bringToFront self.top.withdraw() # Helps bring the window to the front. File "c:\python24\lib\lib-tk\Tkinter.py", line 1562, in wm_withdraw return self.tk.call('wm', 'withdraw', self._w) TclError: bad window path name ".25637872"

================================================ Event contents: char: delta: 13 height: ?? keycode: 13 keysym: Return keysym_num: 65293 num: ?? serial: 1486 state: 0 time: 1717970 type: 2 widget: .17570752.17571352.19882152.minibuffer width: ?? x: 183 x_root: 576 y: -62 y_root: 859

# getLeadinWord must clear self.membersList to disable completion.
leoID = ekr (in c:\Documents and Settings\Ed) reading settings in C:\prog\tigris-cvs\leo\config\leoSettings.leo reading settings in C:\Documents and Settings\Ed\My Documents\ekr.leo rst3 plugin: SilverCity not loaded exception executing command Traceback (most recent call last):

File "C:\prog\tigris-cvs\leo\src\leoCommands.py", line 264, in doCommand val = command(event)

File "C:\prog\tigris-cvs\leo\src\leoCommands.py", line 2969, in pasteOutline u.afterInsertNode(pasted,undoType,undoData)

File "C:\prog\tigris-cvs\leo\src\leoUndo.py", line 750, in afterInsertNode u.pushBead(bunch)

File "C:\prog\tigris-cvs\leo\src\leoUndo.py", line 182, in pushBead if bunch2 and bunch2.kind == 'beforeGroup':

AttributeError: 'Bunch' object has no attribute 'kind'
New commands:

add-space-to-lines, add-tab-to-lines clean-lines clear-selected-text goto-global-line help-for-command open-outline-by-name (filename completion) remove-space-from-lines remove-tab-from-lines
Leo 4.4 release candidate 1 April 28, 2006

This version fixes a few minor bug reported in 4.4b4 and adds 9 new commands. The open-outline-by-name command supports filename completion.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4: -------------------------- - An Emacs-like mini-buffer: you can now execute any command by typing its long name, with tab completion.

- Many new commands, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles. You can use Leo without using a mouse.

- Flexible key bindings and input modes. You can emulate the operation of Emacs, Vim, or any other editor.

- A tabbed log pane. The Find and Spell Check commands now use tabs instead of dialogs, making those commands much easier to use. Plugins or scripts can easily create new tabs. The Completion tab shows possible typing completions.

- Autocompletion and calltips. Autocompletion works much like tab completion.

- Dozens of other new features and bug fixes since Leo 4.3.3.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
http://sourceforge.net/forum/message.php?msg_id=3692247

After cutting selection in the headline, headline area shrank too much.
http://sourceforge.net/forum/message.php?msg_id=3692247

Find panel cannot be re-opened. Run open-find-dialog. Close it. Run open-find-dialog again -- crash.
# getLeadinWord must clear self.membersList to disable completion.
Traceback (most recent call last):

File "C:\prog\tigris-cvs\leo\src\leoCommands.py", line 264, in doCommand val = command(event)

File "C:\prog\tigris-cvs\leo\src\leoCommands.py", line 2969, in pasteOutline u.afterInsertNode(pasted,undoType,undoData)

File "C:\prog\tigris-cvs\leo\src\leoUndo.py", line 750, in afterInsertNode u.pushBead(bunch)

File "C:\prog\tigris-cvs\leo\src\leoUndo.py", line 182, in pushBead if bunch2 and bunch2.kind == 'beforeGroup':

AttributeError: 'Bunch' object has no attribute 'kind'
Useful, e.g., after a find.
self.beginCommand(undoType='xxx') ... self.endCommand(changed=True,setLabel=True)
New commands:

add-space-to-lines add-tab-to-lines clean-lines clear-selected-text goto-global-line help-for-command remove-space-from-lines remove-tab-from-lines
At present, only the open-outline-by-name command supports filename completion.
https://sourceforge.net/forum/message.php?msg_id=3699799
The jEdit_ editor drives its syntax colorer using xml **language description files.** `jEdit's documentation`_ contain a complete description of these xml files. Each xml file describes one **colorizing mode**. A mode consists of one or more **rulesets**, and each ruleset consists of a list of **colorizing rules**. In addition, modes, rulesets and rules may have associated **properties** and **attributes**. Various rules may specify that the colorizer uses another ruleset (either in the same mode or another mode).

**Important**: jEdit's xml language description files contain no explicit ``<RULE>`` elements Rules are simply sub-elements of an enclosing ``<RULES>`` element. The element indicates the kind of rule that is specified, for example, ``<SPAN>``, ``<SEQ>``, etc. By the term **rule element** we shall mean any sub-element of the ``<RULES>`` element.

Rather than using the xml language description files directly, Leo uses Python **colorer control files**, created automatically from the xml files by a script called ``jEdit2Py``. These Python files contain all the information in the jEdit's xml files, so we can (loosely) speak of modes, rulesets, rules, properties and attributes in the Python colorer control files. Later sections of this documentation will make this loose correspondence exact.

**Important**: throughout this documentation, **x.py** will refer to the Python colorer for language ``x``, and **x.xml** will refer to the corresponding xml language-description file.

Using Python colorer control files has the following advantages:

- Running ``jEdit2Py`` need only be done when x.xml changes, and the speed of the xml parser in jEdit2Py does not affect the speed of Leo's colorizer in any way. Moreover, the ``jEdit2Py`` script can contain debugging traces and checks.

- Colorer control files are valid .py files, so all of Python's import optimizations work as usual. In particular, all the data in colorer control files is immediately accessible to Leo's colorer.

- Colorer control files are easier for humans to understand and modify than the equivalent xml file. Furthermore, it is easy to insert debugging information into Python colorer control files.

- It is easy to modify the Python colorer control files 'by hand' without changing the corresponding xml file. In particular, it would be easy to define entirely new kinds of pattern-matching rules in Python merely by creating functions in a colorer control file.
@language rest
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. July, 2006

|back| |leo| |next|

######################################### Chapter 15: Controlling Syntax Coloring #########################################

This chapter discusses how to control Leo's new syntax colorer using Python files derived from jEdit_'s xml language description files. It also discusses settings related to syntax coloring.

**Important**: this material is for those who want to support Leo's colorizing code. You do *not* need to understand this chapter in order to use Leo's colorizers.

The __jEdit_colorizer__.py plugin was an early prototype of the new colorizer. This code has been retired. The threading_colorizer.py plugin uses a separate helper thread to do the colorizing. Coding details for this plugin are discussed in this chapter.

.. contents::
.. External links...

.. _jEdit: http://www.jedit.org/ .. _`jEdit's documentation`: http://www.jedit.org/42docs/users-guide/writing-modes-part.html

.. Relative links...

.. _`Ruleset name`: `Ruleset names`_ .. _`Chapter 8`: customizing.html

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: rstplugin3.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: debuggers.html
-----------------------

|back| |leo| |next|
When Leo's syntax colorer sees the ``'@language x'`` directive, it will import ``x.py`` from Leo's ``modes`` folder. The colorer can then access any module-level object ``obj`` in ``x.py`` as ``x.obj``.

Colorizer control files contain **rules functions** corresponding to rule elements in x.xml. The colorizer can call these functions as if they were members of the colorizer class by passing 'self' as the first argument of these functions. I call these rules *functions* to distinguish them from the corresponding **rules methods** which are actual methods of the colorizer class. Rules *functions* merely call corresponding rules *methods*. Indeed, rules functions are simply a way of binding values to keyword arguments of rules methods. These keywords arguments correspond to the xml attributes of rule elements in x.xml.

The colorizer calls rules functions until one matches, at which point a range of text gets colored and the process repeats. The inner loop of the colorizer is this code::

for f in self.rulesDict.get(s[i],[]): n = f(self,s,i) if n > 0: i += n ; break else: i += 1

- rulesDict is a dictionary whose keys are rulesets and whose values are ruleset dictionaries. Ruleset dictionaries have keys that are single characters and whose values are the list of rules that can start with that character.

- s is the full text to be colorized.

- i is the position within s is to be colorized.

Rules methods (and functions) return n > 0 if they match, and n == 0 if they fail.
The following sections describe the top-level data in ``x.py``.
**x.properties** is a Python dictionary corresponding to the <PROPS> element in ``x.xml``. Keys are property names; values are strings, namely the contents of ``<PROPERTY>`` elements in ``x.xml``. ``x.properties`` contains properties for the entire mode. That is, only modes have ``<PROPS>`` elements. For example, here is ``x.properties`` in ``php.py``::

# properties for mode php.xml properties = { "commentEnd": "-->", "commentStart": "<!--", "indentCloseBrackets": "}", "indentOpenBrackets": "{", "lineUpClosingBracket": "true", }
``x.py`` contains a **keyword dictionary** for each ruleset in ``x.xml``. ``x.py`` contains an empty keywords dictionary if a ruleset contains no ``<KEYWORDS>`` element.

Keys are strings representing keywords of the language describe by the mode. Values are strings representing syntactic categories, i.e. a ``TYPE`` attribute valid in ``x.xml``, namely: ``COMMENT1``, ``COMMENT2``, ``COMMENT3``, ``COMMENT4``, ``FUNCTION``, ``KEYWORD1``, ``KEYWORD2``, ``KEYWORD3``, ``KEYWORD4``, ``LABEL``, ``LITERAL1``, ``LITERAL2``, ``LITERAL3``, ``LITERAL4``, ``MARKUP``, ``NULL`` and ``OPERATOR``.

For example, here (parts of) some keyword dictionaries in php.py::

# Keywords dict for mode php::PHP php_PHP_keywords_dict = { "COM_invoke": "keyword2", "COM_load": "keyword2", "__CLASS__": "keyword3", ... "abs": "keyword2", "abstract": "keyword1", "accept_connect": "keyword2", ... }

# Keywords dict for mode php::JAVASCRIPT_PHP php_JAVASCRIPT_PHP_keywords_dict = {}

# Keywords dict for mode php::PHPDOC php_PHPDOC_keywords_dict = { "@abstract": "label", "@access": "label", "@author": "label", ... "@var": "label", "@version": "label", }

``x.py`` also contains **x.keywordsDictDict**. Keys are ruleset names, values are keywords dictionaries. Here is ``keywordsDictDict`` for php.py::

# Dictionary of keywords dictionaries for php mode. keywordsDictDict = { "php_javascript": php_javascript_keywords_dict, "php_javascript_php": php_javascript_php_keywords_dict, "php_main": php_main_keywords_dict, "php_php": php_php_keywords_dict, "php_php_literal": php_php_literal_keywords_dict, "php_phpdoc": php_phpdoc_keywords_dict, "php_tags": php_tags_keywords_dict, "php_tags_literal": php_tags_literal_keywords_dict, }

The colorizer can get the keywords dictionary for a ruleset as follows::

keywordsDict = x.keywordsDictDict(rulesetName)

**Note**: The ``jEdit2Py`` script creates 'friendly' names for keyword dictionaries *solely* as an aid for people reading the code. Leo's colorer uses only the name ``x.keywordsDictDict``; Leo's colorer never uses the actual names of keywords dictionaries such as ``php_PHPDOC_keywords_dict``.
``x.py`` contains one **rule function** for every rule in every ruleset (``<RULES>`` element) in ``x.xml``. These rules have names ``rule1`` through ``ruleN``, where ``N`` is the total number of rules in all rulesets in ``x.xml``.

Each rules *function* merely calls a rules *method* in Leo's colorizer. Which method gets called depends on the corresponding element in `x.xml`. For example, the first rule in php.xml is::

<SPAN TYPE="MARKUP" DELEGATE="PHP"> <BEGIN>&lt;?php</BEGIN> <END>?&gt;</END> </SPAN>

and the corresponding rule function is::

def php_rule0(colorer, s, i): return colorer.match_span(s, i, kind="markup", begin="<?php", end="?>", at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="PHP",exclude_match=False, no_escape=False, no_line_break=False, no_word_break=False)

``php_rule0`` calls ``colorer.match_span`` because the corresponding xml rule is a ``<SPAN>`` element.

For each ruleset, ``x.py`` also contains a **rules dictionary**, a Python dictionary whose keys are characters and whose values are all lists of rules functions that that can match the key. For example::

# Rules dict for phpdoc ruleset. rulesDict8 = { "*": [rule64,], "0": [rule70,], "1": [rule70,], "2": [rule70,], "3": [rule70,], "4": [rule70,], "5": [rule70,], "6": [rule70,], "7": [rule70,], "8": [rule70,], "9": [rule70,], "<": [rule65,rule66,rule67,rule68,rule69,], "@": [rule70,], "A": [rule70,], "B": [rule70,], ... "X": [rule70,], "Y": [rule70,], "Z": [rule70,], "_": [rule70,], "a": [rule70,], "b": [rule70,], ... "x": [rule70,], "y": [rule70,], "z": [rule70,], "{": [rule63,], }

**Note**: The order of rules in each rules list is important; it should be the same as rules element in ``x.xml``.

Finally, ``x.py`` contains **x.rulesDictDict**. Keys are ruleset names, values are rules dictionaries. The colorer can get the rules list for character ch as follows::

self.rulesDict = x.rulesDictDict.get(rulesetName) # When a mode is inited. ... rules = self.rulesDict.get(ch,[]) # In the main loop.

For example, here is the rules dictionary for php.py::

# x.rulesDictDict for php mode. rulesDictDict = { "php_javascript": rulesDict6, "php_javascript_php": rulesDict7, "php_main": rulesDict1, "php_php": rulesDict4, "php_php_literal": rulesDict5, "php_phpdoc": rulesDict8, "php_tags": rulesDict2, "php_tags_literal": rulesDict3, }

**Note**: The ``jEdit2Py`` script creates 'friendly' names for rules lists *solely* as an aid for people reading the code. Leo's colorer uses only the name ``x.rulesDictDict``; Leo's colorer never uses the actual names of rules lists such as ``rulesDict8``, and Leo's colorer never uses the actual names of rules functions such as ``rule64``.
A **ruleset name** is a Python string having the form ``'x_setname'``, where ``setname`` is the value of the ``SET`` attribute of the ``<RULES>`` element in ``x.xml``. For example, the ruleset name of the ruleset whose ``SET`` attribute is ``JAVASCRIPT`` in ``php.xml`` is ``'php_JAVASCRIPT'``. **Important**: by convention, the ruleset name of the default ``<RULES>`` element is ``'x_main'``; note that default ``<RULES>`` element have no ``SET`` attributes.

The colorizer uses ruleset names to gain access to all data structures in ``x.py``. To anticipate a bit, ruleset names are keys into two standard dictionaries, ``x.rulesDict`` and ``x.keywordsDictDict``, from which the colorizer can get all other information in ``x.py``::

# The rules list for the 'JAVASCRIPT' ruleset in php.xml. rules = x.rulesDict('php_JAVASCRIPT')

# The keywords dict for the 'JAVASCRIPT' ruleset in php.xml. keywordsDict = x.keywordsDictDict('php_JAVASCRIPT')

In fact, ruleset names (and ``x.rulesDict`` and ``x.keywordsDictDict``) are the **only** names that the colorizer needs to know in order to access all information in ``x.py``.
This section describes each rules method in Leo's new colorizer. Rules methods are called by rules functions in colorizer control file; they correspond directly to rules elements in jEdit's language description files. In fact, this documentation is a 'refactoring' of `jEdit's documentation`_.

All rule methods attempt to match a pattern at a particular spot in a string. These methods all return True if the match succeeds.
::

def match_eol_span (self,s,i,kind,begin, at_line_start = False, at_whitespace_end = False, at_word_start = False, delegate = '', exclude_match = False):

``match_eol_span`` succeeds if ``s[i:].startswith(begin)`` and the ``at_line_start``, ``at_whitespace_end`` and ``at_word_start`` conditions are all satisfied.

If successful, ``match_eol_span`` highlights from i to the end of the line with the color specified by ``kind``. If the ``exclude_match`` argument is ``True``, only the text before the matched text will be colored. The ``delegate`` argument, if present, specifies the ruleset to color the colored text.
::

def match_eol_span_regexp (self,s,i,kind,regex, at_line_start = False, at_whitespace_end = False, at_word_start = False, delegate = '', exclude_match = False):

``match_eol_span_exp`` succeeds if:

1. The regular expression ``regex`` matches at ``s[i:]``, and

2. The ``at_line_start``, ``at_whitespace_end`` and ``at_word_start`` conditions are all satisfied.

If successful, ``match_eol_span_regexp`` highlights from i to the end of the line. If the ``exclude_match`` argument is ``True``, only the text before the matched text will be colored. The ``delegate`` argument, if present, specifies the ruleset to color the colored text.
::

def match_keywords (self,s,i):

``match_keywords`` succeeds if ``s[i:]`` starts with an identifier contained in the mode's keywords dictionary ``d``.

If successful, ``match_keywords`` colors the keyword. ``match_keywords`` does not take a ``kind`` keyword argument. Instead, the keyword is colored as specified by ``d.get(theKeyword)``.
::

def match_mark_following (self,s,i,kind,pattern, at_line_start = False, at_whitespace_end = False, at_word_start = False, exclude_match = False):

match_mark_following succeeds if s[i:].startswith(pattern), and the ``at_line_start``, ``at_whitespace_end`` and ``at_word_start`` conditions are all satisfied.

If successful, ``match_mark_following`` colors from ``i`` to the start of the next token with the color specified by ``kind``. If the ``exclude_match`` argument is ``True``, only the text after the matched text will be colored.
::

def match_seq (self,s,i,kind,seq, at_line_start = False, at_whitespace_end = False, at_word_start = False, delegate = ''):

``match_seq`` succeeds if ``s[i:].startswith(seq)`` and the ``at_line_start``, ``at_whitespace_end`` and ``at_word_start`` conditions are all satisfied.

If successful, ``match_seq`` highlights from ``i`` to the end of the sequence with the color specified by ``kind``. The ``delegate`` argument, if present, specifies the ruleset to color the colored text.
::

def match_seq_regexp (self,s,i,kind,regex, at_line_start = False, at_whitespace_end = False, at_word_start = False, delegate = ''):

``match_seq`` succeeds if:

1. The regular expression ``regex`` matches at ``s[i:]``, and

2. The ``at_line_start``, ``at_whitespace_end`` and ``at_word_start`` conditions are all satisfied.

If successful, ``match_seq_regexp`` highlights from ``i`` to the end of the sequence with the color specified by ``kind``. The ``delegate`` argument, if present, specifies the ruleset to color the colored text.
::

def match_span (self,s,i,kind,begin,end, at_line_start = False, at_whitespace_end = False, at_word_start = False, exclude_match = False, delegate = '' no_escape = False, no_line_break = False, no_word_break = False):

``match_span`` succeeds if there is an index ``j > i`` such that ``s[:i].startswith(begin)`` and ``s[i:j].endswith(end)`` and the ``at_line_start``, ``at_whitespace_end``, ``at_word_start``, ``no_escape``, ``no_line_break`` and ``no_word_break`` conditions are all satisfied.

If successful, ``match_span`` highlights from ``s[i:j`` with the color specified by ``kind``; but if the ``exclude_match`` argument is ``True``, the ``begin`` and ``end`` text are not colored. The ``delegate`` argument, if present, specifies the ruleset to color the colored text.
::

def match_span (self,s,i,kind,regex,end, at_line_start = False, at_whitespace_end = False, at_word_start = False, exclude_match = False, delegate = '' no_escape = False, no_line_break = False, no_word_break = False):

``match_span_regex`` succeeds if:

1. The regular expression ``regex`` matches at ``s[i:]``,

2. There is an index ``j > i`` such that ``s[i:j].endswith(end)``,

3. The ``at_line_start``, ``at_whitespace_end``, ``at_word_start``, ``no_escape``, ``no_line_break`` and ``no_word_break`` conditions are all satisfied.

If successful, ``match_span`` colors ``s[i:j]``, with the color specified by ``kind``; but if the ``exclude_match`` argument is ``True``, the ``begin`` and ``end`` text are not colored. The ``delegate`` argument, if present, specifies the ruleset to color the colored text.
::

def match_terminate (self,s,i,kind,at_char):

``match_terminate`` succeeds if ``s[i:]`` contains at least ``at_char`` more characters.

If successful, ``match_terminate`` colors ``at_char`` characters with the color specified by ``kind``.
::

def match_mark_previous (self,s,i,kind,pattern, at_line_start = False, at_whitespace_end = False, at_word_start = False, exclude_match = False):

``match_mark_previous`` succeeds if s[i:].startswith(pattern),and the ``at_line_start``, ``at_whitespace_end`` and ``at_word_start`` conditions are all satisfied.

If successful, ``match_mark_previous`` colors from the end of the previous token to ``i`` with the color specified by ``kind``. If the ``exclude_match`` argument is ``True``, only the text before the matched text will be colored.
All rule methods take three required arguments and zero or more optional keyword arguments.

Here is a list of the required arguments and their meaning:

- **self**: An instance of Leo's colorizer.

- **s**: The string in which matches may be found.

- **i**: The location within the string at which the rule method looks for a match.

Here is a list of all optional keyword arguments and their meaning:

- **at_line_start**: If ``True``, a match will succeed only if ``i`` is at the start of a line.

- **at_whitespace_end**: If ``True``, the match will succeed only if ``i`` is at the first non-whitespace text in a line.

- **at_word_start**: If ``True``, the match will succeed only if ``i`` is at the beginning of a word.

- **delegate**: If non-empty, the value of this argument is a `ruleset name`_. If the match succeeds, the matched text will be colored recursively with the indicate ruleset.

- **exclude_match**: If ``True``, the actual text that matched will not be colored. The meaning of this argument varies slightly depending on whether one or two sequences are matched. See the individual rule methods for details.

- **kind**: A string representing a class of tokens, i.e., one of: ``'comment1'``, ``'comment2'``, ``'comment3'``, ``'comment4'``, ``'function'``, ``'keyword1'``, ``'keyword2'``, ``'keyword3'``, ``'keyword4'``, ``'label'``, ``'literal1'``, ``'literal2'``, ``'literal3'``, ``'literal4'``, ``'markup'``, ``'null'`` and ``'operator'``.

- **no_escape**: If ``True``, the ruleset's escape character will have no effect before the ``end`` argument to ``match_span``. Otherwise, the presence of the escape character will cause that occurrence of the end string to be ignored.

- **no_line_break**: If ``True``, the match will not succeed across line breaks.

- **no_word_break**: If ``True``, the match will not cross word breaks.

New in Leo 4.4.1 final: the regular expression rule matchers no longer get a ``hash_char`` argument because such matchers are called only if the present search pattern starts with ``hash_char``.
``x.importDict`` is a Python dictionary. Keys are ruleset names; values are a list of ruleset names. For example::

# Import dict for php mode. importDict = { "php_javascript_php": ["javascript::main"], }

For any ruleset ``R`` whose ruleset name is ``N``, ``x.importDict.get(N)`` is the list of rulesets names whose rulesets appear in a ``DELEGATE`` attribute of an ``<IMPORT>`` rule element in ``R's`` ruleset. Such **imported** ruleset are copied to the end of the ``R's`` rules list. Leo's colorizer does this copying only once, when loading ruleset ``R`` for the first time.

**Note 1**: Loading imported rulesets must be done at 'run time'. It should definitely not be done by ``jEdit2Py`` at 'compile time'; that would require running ``jEdit2Py`` on *all* .xml files whenever any such file changed.

**Note 2**: Multiple ``<IMPORT>`` rule elements in a single ruleset are allowed: delegated rules are copied to the end of ``N's`` rules list in the order they appear in the ruleset.

**Note 3**: The ``DELEGATE`` attribute of ``<IMPORT>`` elements is, in fact, completely separate from the ``DELEGATE`` attributes of other rules as discussed in `Arguments to rule methods`_. Indeed, the ``DELEGATE`` attribute of ``<IMPORT>`` elements creates entries in ``x.importDict``, which in turn causes the colorizer to append the rules of the imported ruleset to the end of the present rules list. In contrast, the ``DELEGATE`` attributes of other rules sets the ``delegate`` argument to rules methods, which in tern causes the colorizer to recursively color the matched text with the **delegated** ruleset. In short:

- The rules of **imported** rulesets are appended to the end of another rules list; the rules of **delegated** rulesets never are.

- **Imported** ruleset names appear as the values of items in ``x.importDict``; **delegated** ruleset names appear as ``delegate`` arguments to rule methods.
``x.py`` contains a **attribute dictionary** for each ruleset in ``x.xml``. Keys are attribute names, values strings representing the values of the attributes. This dictionary is empty if a ruleset contains no attributes. The valid keys are:

- ``'default'``: the default token type. ``'null'`` is the default.

- ``'digit_re'``: a regular expression. Words matching this regular expression are colored with the ``digit`` token type.

- ``'ignore_case'``: ``'true'`` or ``'false'``. Default is ``'true'``.

- ```highlight_digits'``: ``'true'`` or ``'false'``. Default is ``'true'``.

- ``'no_word_sep'``: A list of characters treated as 'alphabetic' characters when matching keywords.

For example, here is one attribute dictionary in php.py::

# Attributes dict for php_javascript ruleset. php_javascript_attributes_dict = { "default": "MARKUP", "digit_re": "", "highlight_digits": "true", "ignore_case": "true", "no_word_sep": "", }

``x.py`` also contains **x.attributesDictDict**. Keys are ruleset names, values are attribute dictionaries. Here is ``attributesDictDict`` for php.py::

# Dictionary of attributes dictionaries for php mode. attributesDictDict = { "php_javascript": php_javascript_attributes_dict, "php_javascript_php": php_javascript_php_attributes_dict, "php_main": php_main_attributes_dict, "php_php": php_php_attributes_dict, "php_php_literal": php_php_literal_attributes_dict, "php_phpdoc": php_phpdoc_attributes_dict, "php_tags": php_tags_attributes_dict, "php_tags_literal": php_tags_literal_attributes_dict, }

**Note**: The ``jEdit2Py`` script creates 'friendly' names for attribute dictionaries *solely* as an aid for people reading the code. Leo's colorer uses only the name ``x.attributeDictDict``; Leo's colorer never uses the actual names of attribute dictionaries.
Leo 4.4 Final May 11, 2006

Leo 4.4 Final is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4: -------------------------- - An Emacs-like mini-buffer: you can now execute any command by typing its long name, with tab completion.

- Many new commands, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles. You can use Leo without using a mouse.

- Flexible key bindings and input modes. You can emulate the operation of Emacs, Vim, or any other editor.

- A tabbed log pane. The Find and Spell Check commands now use tabs instead of dialogs, making those commands much easier to use. Plugins or scripts can easily create new tabs. The Completion tab shows possible typing completions.

- Autocompletion and calltips. Autocompletion works much like tab completion. To enable autocompletion, bind a key to the auto-complete command.

- Dozens of other new features and bug fixes since Leo 4.3.3.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
import leoPlugins

rst3 = leoPlugins.getPluginModule('rst3')

if rst3: controller = rst3.controllers.get(c) if controller: p,s = controller.writeNodeToString(ext='.html') print '*' * 40,p print s else: rst3 = leoPlugins.loadOnePlugin('rst3',verbose=True) if rst3: g.es('rst3 loaded') rst3.onCreate('tag',{'c':c}) else: # Ask to be removed. g.app.scriptDict['removeMe'] = True
# Problems with pdf files.

import leoPlugins

rst3 = leoPlugins.getPluginModule('rst3')

if rst3: controller = rst3.controllers.get(c) if controller: p,s = controller.writeNodeToString(ext='.pdf') print '*' * 40,p print s else: rst3 = leoPlugins.loadOnePlugin('rst3',verbose=True) if rst3: g.es('rst3 loaded') rst3.onCreate('tag',{'c':c}) else: # Ask to be removed. g.app.scriptDict['removeMe'] = True
import leoPlugins

rst3 = leoPlugins.getPluginModule('rst3')

if rst3: controller = rst3.controllers.get(c) if controller: p,s = controller.writeNodeToString(ext='.tex') print '*' * 40,p print s else: rst3 = leoPlugins.loadOnePlugin('rst3',verbose=True) if rst3: g.es('rst3 loaded') rst3.onCreate('tag',{'c':c}) else: # Ask to be removed. g.app.scriptDict['removeMe'] = True
import leoPlugins

rst3 = leoPlugins.getPluginModule('rst3')

if rst3: controller = rst3.controllers.get(c) if controller: p,s = controller.writeNodeToString(ext=None) # Convert rst nodes to rst text. print '*' * 40,p print s else: rst3 = leoPlugins.loadOnePlugin('rst3',verbose=True) if rst3: g.es('rst3 loaded') rst3.onCreate('tag',{'c':c}) else: # Ask to be removed. g.app.scriptDict['removeMe'] = True
A new method has been added to the rst3 plugin to make it more easily to drive the plugin from scripts::

def writeNodeToString (self,p=None,ext=None)

writeNodeToString scans p's tree (p defaults to presently selected node) looking for @rst nodes. When the first @rst node is found, writeNodeToString processes the node as usual, with the following changes:

- @rst need not be followed by a filename; any filename and its extension are *ignored*.

- Only the ``ext`` argument to writeNodeToString determines the type of output produced. The valid values for the ``ext`` argument are None (for rst output), '.html', '.pdf', and '.tex'.

- Instead of writing the result to a file, writeNodeToString returns the tuple (p,s), where p is the node whose tree produced the output, and s is the output itself.

- writeNodeToString returns after processing at most one @rst node.

Scripts can easily use writeNodeToString to convert @rst trees into various kinds of output. For example, here is the body of @button rst->html in LeoDocs.leo::

import leoPlugins rst3 = leoPlugins.getPluginModule('rst3') if rst3: controller = rst3.controllers.get(c) if controller: p,s = controller.writeNodeToString(ext='.html') print '*' * 40,p print s

Notes:

- This script scans the presently selected tree for @rst nodes, just like the @button rst script does. In particular, if the presently selected tree does not contain an @rst node the search continues in parent trees. When an @rst node is found, it converts the node (and descendants) to html and returns p, the found @rst node and s, the html itself.

- The script shown above merely prints the output, but many other actions could be taken. In particular, because writeNodeToString returns p it would be possible to write a script that would scan multiple @rst nodes.

- None and '.tex' are also valid values for the ext argument to writeNodeToString. None converts the @rst tree to a single reStructuredText string, as shown in @button rst->rst.

- There is some support for ext='.pdf', but this is experimental code. Expect crashes.
@language rest
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. May 27, 2006

|back| |leo| |next|

####################################### Chapter 16: Debugging with Leo #######################################

This chapter discusses debugging Python scripts with Leo. Be aware of the distinction between **Leo-specific** scripts and **general** scripts. Leo-specific scripts access data in the Leo outline in which they are contained; general scripts do not.

.. contents::
.. External links...

.. _Idle: http://www.python.org/idle/ .. _pdb: http://docs.python.org/lib/module-pdb.html .. _winpdb: http://www.digitalpeers.com/pythondebugger/

.. _`the FAQ`: http://webpages.charter.net/edreamleo/FAQ.html#how-can-i-use-python-s-pdb-debugger-with-leo .. _`running Leo in a console`: http://webpages.charter.net/edreamleo/FAQ.html#how-can-i-run-leo-from-a-console-window .. _`embedded winpdb`: http://www.digitalpeers.com/pythondebugger/embedded.htm .. _`Leo's forums`: http://sourceforge.net/forum/?group_id=3458 .. _`work flow`: http://webpages.charter.net/edreamleo/FAQ.html#how-can-i-use-leo-to-develop-leo-itself

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: coloring.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: zodb.html
The following settings in leoSettings.leo control debugger operation. The settings shown here will be assumed to be in effect throughout this chapter.

``@string debugger_kind = winpdb``

This setting controls what debugger the 'Debug Script' script button uses. Eventually this setting will control what debugger the debug command uses. At present the only valid value is 'winpdb'

``@bool write_script_file = True``

True: The execute script command writes the script to be executed to a file, then executes the script using Python's execFile function. The script_file_path setting specifies the path to this file. False (legacy): The execute script command uses Python's exec command to execute the script.

``@string script_file_path = ../test/scriptFile.py``

The path to the file to be written by the execute-script command. Notes:

- This setting has effect only if the write_script_file setting is True. - Use ``/`` as the path delimiter, regardless of platform. - The default path is ``../test/scriptFile.py`` if no path is given. - The path starts at g.app.loadDir, so for example ``../test/scriptFile.py`` is equivalent to ``leo/test/scriptFile.py``. - The filename should end in ``.py``.

``@string debugger_path`` = None

@ignore can only be used in the root node of @file trees. It tells Leo to ignore the tree.

The @ignore directive can not be used elsewhere in @thin trees and @file trees because of the way Leo recreates outlines from derived files. This is an absolutely crucial restriction and will never go away. For a few more details, see `Leo 4.0: Eliminating error 'recovery'`_ in `Chapter 9: History of Leo`_.

There are several workaround, as shown in LeoPy.leo:

- keep notes in the outline outside of any derived file.

- Use @all to gather notes in a derived file, as in done in @thin leoProjects.txt.
Leo 4.4.1 beta 1 June 3, 2006

Leo 4.4.1 beta 1 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.1: ---------------------------- - A new colorizer plugin controlled by jEdit language description files. At present this plugin only reliably colors @language python code. - Multiple editors in Leo's body pane. - Search commands now support regex replace patterns: \1, \2, etc. - Support for external debuggers: see http://webpages.charter.net/edreamleo/debuggers.html - The scripting plugin now creates a Debug Script button. - Several new commands including run-unit-test, python-help and toggle-invisibles. - The help-for-command commands now contains information for almost all commands. - A new shortcut_button plugin.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
http://sourceforge.net/forum/message.php?msg_id=3729858

Fixed crasher in Leo 4.4 by initing self.p in Quickfind ctor.
http://sourceforge.net/forum/message.php?msg_id=3737879
http://sourceforge.net/forum/message.php?msg_id=3737745

- Added event keyword argument to parameterize function.
http://sourceforge.net/forum/message.php?msg_id=3737745

The fix was to add a c argument to g.findTopLevelNode and g.findNodeInTree.
This runs the winpdb debugger in a separate process.

The winpdb debugger must be installed for this command to work.

For more details, see: http://webpages.charter.net/edreamleo/debuggers.html
This fixes all conflicts between Leo and Idle.
- Allow \1, \2, etc. replacements in re searches.

- Allow \n and \t in plain searches.

- The shortcut for the replace-string command now changes from the find command to the replace command.
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3575014

Actually, the run-unit-tests command first appeared in Leo 4.4, but it never got properly announced.
http://sourceforge.net/forum/message.php?msg_id=3729823

This is intended to help with redraw problems on Linux.
It is now clearer what the selected values are.
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3737745

Added warnings in various places that the setting:

@bool expanded_click_area = True

interferes with the Universal Scrolling plugin.
The add-editor command adds a new editor, the delete-editor command deletes the presently selected editor, and the cycle-editor-focus command cycles focus between editors in the body text.
@nocolor

leoSettings.leo now contains the following setting, with default as shown:

@bool autoindent_in_nocolor_mode = True

True: auto-indent regardless of how text is colored. False: disable auto-indenting if in range @nocolor or @kill.

This will make the default action work as Roger Erens requested, and will allow you to make Leo work exactly as before if you want.
@shortcut nodes never worked and apparently nobody ever used them.
-----------------------

|back| |leo| |next|
This plugin puts two buttons in the icon area. The 'Save Hoist' button hoists the presently selected node and creates a button which can later rehoist the same node. The 'Dehoist' button performs one level of dehoisting.

This plugin replaces the old chapters plugin.

leoKeys.py handles key bindings. There are two kinds of bindings, gui bindings and pane bindings.

**Gui bindings** are the actual binding as seen by Tkinter (or whatever gui is in effect). Leo binds every key that has a binding to k.masterKeyHander. For Tkinter, a *separate* binding must be made, rather than a single <Key> binding, because, alas, Tkinter key events provide insufficient enough information to tell what key actually caused the key event(!) This is a significant hole in Tkinter's event mechanism.

At present Leo makes gui bindings in several places, all equivalent. Bindings are made to callbacks, all of which have this form::

def callback(event=None,k=k,stroke=stroke): return k.masterKeyHandler(event,stroke)

As a result, changing gui bindings actually has no effect whatever. It would be clearer to have a single place to make these bindings...

In any case, the purpose of these callbacks is to capture the value of 'stroke' so that it can be passed to k.masterKeyHandler. This relieves k.masterKeyHandler of the impossible task of computing the stroke from the event. **Important**: No function argument is ever passed to k.masterKeyHandler from these callbacks, because k.masterKeyHandler binds keys to command handlers as described next.

**Pane bindings** are bindings represented by various Python dictionaries in the keyHandlerClass (see below). k.masterKeyHandler and its helpers use these dictionaries to call the proper command or mode handler. This logic is hairy, but it is completely separate from the gui binding logic.

Here are the dictionaries that k.masterKeyHandler uses:

- c.commandsDict: Keys are minibuffer command names; values are functions f.

- k.inverseCommandsDict: Keys are f.__name__l values are emacs command names.

- k.bindingsDict: Keys are shortcuts; values are *lists* of g.bunch(func,name,warningGiven).

- k.masterBindingsDict: Keys are pane names: 'all','text',etc. or mode names. Values are dicts: keys are strokes; values are g.Bunch(commandName,func,pane,stroke).

- k.modeWidgetsDict: Keys are mode names; values are lists of widgets to which bindings have been made.

- k.settingsNameDict: Keys are lowercase settings; values are 'real' Tk key specifiers. Important: this table has no inverse.

- inverseBindingDict: This is *not* an ivar; it is computed by k.computeInverseBindingDict(). Keys are emacs command names; values are *lists* of shortcuts.
This prompts for a string s, then puts the result of help(s) in Leo's log pane.
Creates a 'Shortcut' button in the icon area. Pressing the Shortcut button creates *another* button which when pressed will select the presently selected node at the time the button was created.
This plugin creates a 'Shortcut' button in the icon area. Pressing the Shortcut button creates *another* button which when pressed will select the presently selected node at the time the button was created.
http://sourceforge.net/forum/message.php?msg_id=3761285

There were actually two bugs:

- parseLeoSentinel was not recognizing the closing comment delim (!!)

- putDirective was incorrectly setting delims for @language and @comment delims. This is wrong: the init code calls scanAllDirectives, and the comment delims **must not change** in the file (except as the result of @delims.)
@ @rst-options code_mode=False doc_only_mode= True generate_rst=True http_server_support = False show_organizer_nodes=False show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. August 28, 2005

# Note the use of @ @rst-markup and @ @rst-options throughout this tree to control doc_mode_only mode.

|back| |leo| |next|

@ @rst-markup

##################################### Documentation for leoFind.py #####################################

@c

.. External links...

.. _`CWEB`: http://www-cs-faculty.stanford.edu/~knuth/cweb.html .. _`noweb`: http://www.eecs.harvard.edu/~nr/noweb/

.. Relative links...

.. _front: front.html .. _`Leo's tutorial`: intro.html

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: outlines.html

.. |next| image:: arrow_rt.gif :target: commands.html

.. |blank| image:: blank.gif

.. |leo| image:: leo.gif :target: front.html
@language python @tabwidth -4 @pagewidth 80

import leoGlobals as g import re import string

<< Theory of operation of find/change >>

class leoFind:

"""The base class for Leo's Find commands."""

@others
@ The find and change commands are tricky; there are many details that must be handled properly. This documentation describes the leo.py code. Previous versions of Leo used an inferior scheme. The following principles govern the leoFind class:

1. Find and Change commands initialize themselves using only the state of the present Leo window. In particular, the Find class must not save internal state information from one invocation to the next. This means that when the user changes the nodes, or selects new text in headline or body text, those changes will affect the next invocation of any Find or Change command. Failure to follow this principle caused all kinds of problems in the Borland and Macintosh codes. There is one exception to this rule: we must remember where interactive wrapped searches start. This principle simplifies the code because most ivars do not persist. However, each command must ensure that the Leo window is left in a state suitable for restarting the incremental (interactive) Find and Change commands. Details of initialization are discussed below.

2. The Find and Change commands must not change the state of the outline or body pane during execution. That would cause severe flashing and slow down the commands a great deal. In particular, c.selectVnode and c.editPosition methods must not be called while looking for matches.

3. When incremental Find or Change commands succeed they must leave the Leo window in the proper state to execute another incremental command. We restore the Leo window as it was on entry whenever an incremental search fails and after any Find All and Change All command.

Initialization involves setting the self.c, self.p, self.in_headline, self.wrapping and self.s_ctrl ivars. Setting self.in_headline is tricky; we must be sure to retain the state of the outline pane until initialization is complete. Initializing the Find All and Change All commands is much easier because such initialization does not depend on the state of the Leo window.

Using Tk.Text widgets for both headlines and body text results in a huge simplification of the code. Indeed, the searching code does not know whether it is searching headline or body text. The search code knows only that self.s_ctrl is a Tk.Text widget that contains the text to be searched or changed and the insert and sel Tk attributes of self.search_text indicate the range of text to be searched. Searching headline and body text simultaneously is complicated. The selectNextPosition() method handles the many details involved by setting self.s_ctrl and its insert and sel attributes.
@ @rst-options show_organizer_nodes=True @c

def __init__ (self,c,title=None):

self.c = c

# Spell checkers use this class, so we can't always compute a title. if title: self.title = title else: << compute self.title >>

<< init the gui-independent ivars >>
@ @rst-options show_organizer_nodes=False @c

if not c.mFileName: s = "untitled" else: path,s = g.os_path_split(c.mFileName)

self.title = "Find/Change for %s" % s
self.wrapPosition = None self.onlyPosition = None self.find_text = "" self.change_text = "" self.unstick = False

@ New in 4.3: - These are the names of leoFind ivars. (no more _flag hack). - There are no corresponding commander ivars to keep in synch (hurray!) - These ivars are inited (in the subclass by init) when this class is created. - These ivars are updated (in the subclass by update_ivars) just before doing any find. @c

<< do dummy initialization to keep Pychecker happy >>

self.intKeys = [ "batch","ignore_case", "node_only", "pattern_match", "search_headline", "search_body", "suboutline_only", "mark_changes", "mark_finds", "reverse", "script_search","script_change","selection_only", "wrap", "whole_word", ]

self.newStringKeys = ["radio-find-type", "radio-search-scope"]

# To do: this should depend on language. self.word_chars = string.letters + string.digits + '_'

# Ivars containing internal state... self.c = None # The commander for this search. self.clone_find_all = False self.p = None # The position being searched. Never saved between searches! self.in_headline = False # True: searching headline text. self.s_ctrl = None # The search text for this search. self.wrapping = False # True: wrapping is enabled. # This is _not_ the same as self.wrap for batch searches.

@ Initializing a wrapped search is tricky. The search() method will fail if p==wrapPosition and pos >= wrapPos. selectNextPosition() will fail if p == wrapPosition. We set wrapPos on entry, before the first search. We set wrapPosition in selectNextPosition after the first search fails. We also set wrapPosition on exit if the first search succeeds. @c

self.wrapPosition = None # The start of wrapped searches: persists between calls. self.onlyPosition = None # The starting node for suboutline-only searches. self.wrapPos = None # The starting position of the wrapped search: persists between calls. self.errors = 0 self.selStart = self.selEnd = None # For selection-only searches.
@ @rst-options show_organizer_nodes=False @c

if 1: self.batch = None self.clone_find_all = None self.ignore_case = None self.node_only = None self.pattern_match = None self.search_headline = None self.search_body = None self.suboutline_only = None self.mark_changes = None self.mark_finds = None self.reverse = None self.script_search = None self.script_change = None self.selection_only = None self.wrap = None self.whole_word = None
# The user has pushed the "Change All" button from the find panel.

def changeAllButton(self):

c = self.c self.setup_button() c.clearAllVisited() # Clear visited for context reporting.

if self.script_change: self.doChangeAllScript() elif self.selection_only: self.change() else: self.changeAll()
# The user has pushed the "Change" button from the find panel.

def changeButton(self):

self.setup_button()

if self.script_change: self.doChangeScript() else: self.change()
# The user has pushed the "Change Then Find" button from the find panel.

def changeThenFindButton(self):

self.setup_button()

if self.script_change: self.doChangeScript() if self.script_search: self.doFindScript() else: self.findNext() else: if self.script_search: self.change() self.doFindScript() else: self.changeThenFind()
# The user has pushed the "Find All" button from the find panel.

def findAllButton(self):

c = self.c self.setup_button() c.clearAllVisited() # Clear visited for context reporting.

if self.script_search: self.doFindAllScript() elif self.selection_only: self.findNext() else: self.findAll()
# The user has pushed the "Find" button from the find panel.

def findButton(self):

self.setup_button()

if self.script_search: self.doFindScript() else: self.findNext()
# Initializes a search when a button is pressed in the Find panel.

def setup_button(self):

c = self.c self.p = c.currentPosition()

c.bringToFront() if 0: # We _must_ retain the editing status for incremental searches! c.endEditing()

self.update_ivars() self.adjust_ivars()
# The user has selected the "Replace" menu item.

def changeCommand(self,c):

self.setup_command()

if self.script_search: self.doChangeScript() else: self.change()
# The user has pushed the "Change Then Find" button from the Find menu.

def changeThenFindCommand(self,c):

self.setup_command()

if self.script_search: self.doChangeScript() self.doFindScript() else: self.changeThenFind()
def dismiss (self): pass
# The user has selected the "Find Next" menu item.

def findNextCommand(self,c):

self.setup_command()

if self.script_search: self.doFindScript() else: self.findNext()
# The user has selected the "Find Previous" menu item.

def findPreviousCommand(self,c):

self.setup_command()

self.reverse = not self.reverse

if self.script_search: self.doFindScript() else: self.findNext()

self.reverse = not self.reverse
def handleUserClick (self,p):

"""Reset suboutline-only search when the user clicks a headline."""

try: if self.c and self.suboutline_only: # g.trace(p) self.onlyPosition = p.copy() except: pass
# Initializes a search when a command is invoked from the menu.

def setup_command(self):

# g.trace('leoFind')

if 0: # We _must_ retain the editing status for incremental searches! self.c.endEditing()

self.update_ivars() self.adjust_ivars()
def adjust_ivars (self):

'''New in 4.3.

Adjust ivars, particularly the find and change text. This is called just before executing a command and just after calling update_ivars.

Plugins may replace this code as desired.'''

if 0: # The TkFind class now removes tailing newlines.

ft = self.find_text if not ft: return

# Remove a trailing newline unless that is all there is. if len(ft) > 1 and ft[-1] in ('\n','\r'): ft = ft[:-1] self.adjust_find_text(ft) if 0: g.es('before:',repr(self.find_text)) g.es(' after:',repr(ft)) self.find_text = ft

return
@ This routine performs a single batch change operation, updating the head or body string of p and leaving the result in s_ctrl. We update the body if we are changing the body text of c.currentVnode().

s_ctrl contains the found text on entry and contains the changed text on exit. pos and pos2 indicate the selection. The selection will never be empty. NB: we can not assume that self.p is visible. @c

def batchChange (self,pos1,pos2):

c = self.c ; u = c.undoer p = self.p ; st = self.s_ctrl ; gui = g.app.gui # Replace the selection with self.change_text if gui.compareIndices(st,pos1, ">", pos2): pos1,pos2=pos2,pos1 gui.replaceSelectionRangeWithText(st,pos1,pos2,self.change_text) s = gui.getAllText(st) # Update the selection. insert=g.choose(self.reverse,pos1,pos1+'+'+str(len(self.change_text))+'c') gui.setSelectionRange(st,insert,insert) gui.setInsertPoint(st,insert) # Update the node if self.in_headline: << change headline >> else: << change body >>
if len(s) > 0 and s[-1]=='\n': s = s[:-1]

if s != p.headString():

undoData = u.beforeChangeNodeContents(p)

p.initHeadString(s) if self.mark_changes: p.setMarked() p.setDirty() if not c.isChanged(): c.setChanged(True)

u.afterChangeNodeContents(p,'Change Headline',undoData)
if len(s) > 0 and s[-1]=='\n': s = s[:-1]

if s != p.bodyString():

undoData = u.beforeChangeNodeContents(p)

c.setBodyString(p,s) if self.mark_changes: p.setMarked() p.setDirty() if not c.isChanged(): c.setChanged(True)

u.afterChangeNodeContents(p,'Change Body',undoData)
def change(self):

if self.checkArgs(): self.initInHeadline() self.changeSelection()
def changeAll(self):

c = self.c ; u = c.undoer ; undoType = 'Change All' current = c.currentPosition() st = self.s_ctrl ; gui = g.app.gui if not self.checkArgs(): return self.initInHeadline() saveData = self.save() self.initBatchCommands() count = 0 c.beginUpdate() try: # In update... u.beforeChangeGroup(current,undoType) while 1: pos1, pos2 = self.findNextMatch() if not pos1: break count += 1 self.batchChange(pos1,pos2) line = gui.getLineContainingIndex(st,pos1) self.printLine(line,allFlag=True) p = c.currentPosition() u.afterChangeGroup(p,undoType,reportFlag=True) g.es("changed: %d instances" % (count)) finally: c.endUpdate() self.restore(saveData)
# Replace selection with self.change_text. # If no selection, insert self.change_text at the cursor.

def changeSelection(self):

c = self.c ; p = self.p ; gui = g.app.gui # g.trace(self.in_headline) t = g.choose(self.in_headline,c.edit_widget(p),c.frame.bodyCtrl) oldSel = sel = gui.getTextSelection(t) if sel and len(sel) == 2: start,end = sel if start == end: sel = None if not sel or len(sel) != 2: g.es("No text selected") return False

# Replace the selection in _both_ controls. start,end = oldSel change_text = self.change_text

# Perform regex substitutions of \1, \2, ...\9 in the change text. if self.pattern_match and self.match_obj: groups = self.match_obj.groups() if groups: change_text = self.makeRegexSubs(change_text,groups) change_text = change_text.replace('\\n','\n').replace('\\t','\t')

gui.replaceSelectionRangeWithText(t, start,end,change_text) gui.replaceSelectionRangeWithText(self.s_ctrl,start,end,change_text)

# Update the selection for the next match. gui.setSelectionRangeWithLength(t,start,len(self.change_text)) c.widgetWantsFocus(t)

# No redraws here: they would destroy the headline selection. c.beginUpdate() try: if self.mark_changes: p.setMarked() if self.in_headline: c.frame.tree.onHeadChanged(p,'Change') else: c.frame.body.onBodyChanged('Change',oldSel=oldSel) finally: c.endUpdate(False) c.frame.tree.drawIcon(p) # redraw only the icon.

return True
def makeRegexSubs(self,s,groups):

'''Carefully substitute group[i-1] for \i strings in s. The group strings may contain \i strings: they are *not* substituted.'''

digits = '123456789' result = [] ; n = len(s) i = j = 0 # s[i:j] is the text between \i markers. while j < n: k = s.find('\\',j) if k == -1 or k + 1 >= n: break j = k + 1 ; ch = s[j] if ch in digits: j += 1 result.append(s[i:k]) # Append up to \i i = j gn = int(ch)-1 if gn < len(groups): result.append(groups[gn]) # Append groups[i-1] else: result.append('\\%s' % ch) # Append raw '\i' result.append(s[i:]) return ''.join(result)
def changeThenFind(self):

if not self.checkArgs(): return

self.initInHeadline() if self.changeSelection(): self.findNext(False) # don't reinitialize
def doChangeScript (self):

g.app.searchDict["type"] = "change" self.runChangeScript()

def doChangeAllScript (self):

"""The user has just pressed the Change All button with script-change box checked.

N.B. Only this code is executed."""

g.app.searchDict["type"] = "changeAll" while 1: self.runChangeScript() if not g.app.searchDict.get("continue"): break

def runChangeScript (self):

try: assert(self.script_change) exec self.change_text in {} # Use {} to get a pristine environment. except: g.es("exception executing change script") g.es_exception(full=False) g.app.searchDict["continue"] = False # 2/1/04
def doFindScript (self):

g.app.searchDict["type"] = "find" self.runFindScript()

def doFindAllScript (self):

"""The user has just pressed the Find All button with script-find radio button checked.

N.B. Only this code is executed."""

g.app.searchDict["type"] = "findAll" while 1: self.runFindScript() if not g.app.searchDict.get("continue"): break

def runFindScript (self):

try: exec self.find_text in {} # Use {} to get a pristine environment. except: g.es("exception executing find script") g.es_exception(full=False) g.app.searchDict["continue"] = False # 2/1/04
def findAll(self):

c = self.c ; t = self.s_ctrl ; u = c.undoer gui = g.app.gui ; undoType = 'Clone Find All' if not self.checkArgs(): return self.initInHeadline() data = self.save() self.initBatchCommands() count = 0 ; clones = [] while 1: pos, newpos = self.findNextMatch() if not pos: break count += 1 line = gui.getLineContainingIndex(t,pos) self.printLine(line,allFlag=True) if self.clone_find_all and self.p.v.t not in clones: if not clones: << create the found node and begin the undo group >> << create a clone of p under the find node >> if self.clone_find_all and clones: c.setChanged(True) u.afterChangeGroup(c.currentPosition(),undoType,reportFlag=True) c.redraw_now() g.es("found: %d matches" % (count)) self.restore(data)
u.beforeChangeGroup(c.currentPosition(),undoType) undoData = u.beforeInsertNode(c.currentPosition()) oldRoot = c.rootPosition() found = oldRoot.insertAfter() found.moveToRoot(oldRoot) found.setHeadString('Found: ' + self.find_text) u.afterInsertNode(found,undoType,undoData,dirtyVnodeList=[])
clones.append(self.p.v.t) undoData = u.beforeCloneNode(self.p) q = self.p.clone(self.p) q.moveToLastChildOf(found) u.afterCloneNode(q,undoType,undoData,dirtyVnodeList=[])
def findNext(self,initFlag=True):

c = self.c if not self.checkArgs(): return

if initFlag: self.initInHeadline() data = self.save() self.initInteractiveCommands() else: data = self.save()

pos, newpos = self.findNextMatch()

if pos: self.showSuccess(pos,newpos) else: if self.wrapping: g.es("end of wrapped search") else: g.es("not found: " + "'" + self.find_text + "'") self.restore(data)
# Resumes the search where it left off. # The caller must call set_first_incremental_search or set_first_batch_search.

def findNextMatch(self):

c = self.c

if not self.search_headline and not self.search_body: return None, None

if len(self.find_text) == 0: return None, None

p = self.p while p: pos, newpos = self.search() if pos: if self.mark_finds: p.setMarked() c.frame.tree.drawIcon(p) # redraw only the icon. return pos, newpos elif self.errors: return None,None # Abort the search. elif self.node_only: return None,None # We are only searching one node. else: p = self.p = self.selectNextPosition() return None, None
def resetWrap (self,event=None):

self.wrapPosition = None self.onlyPosition = None
def search (self):

"""Search s_ctrl for self.find_text under the control of the whole_word, ignore_case, and pattern_match ivars.

Returns (pos, newpos) or (None,None)."""

c = self.c ; p = self.p ; w = self.s_ctrl ; gui = g.app.gui index = gui.getInsertPoint(w) s = gui.getAllText(w) index = gui.toPythonIndex(s,w,index) stopindex = g.choose(self.reverse,0,len(s)) pos,newpos = self.searchHelper(s,index,stopindex,self.find_text, backwards=self.reverse,nocase=self.ignore_case, regexp=self.pattern_match,word=self.whole_word) if pos == -1: return None,None pos = gui.toGuiIndex(s,w,pos) newpos = gui.toGuiIndex(s,w,newpos) << fail if we are passed the wrap point >> gui.setTextSelection(w,pos,newpos,insert=newpos) return pos, newpos
if self.wrapping and self.wrapPos and self.wrapPosition and p == self.wrapPosition:

if self.reverse and gui.compareIndices(w,pos, "<", self.wrapPos): # g.trace("wrap done") return None, None

if not self.reverse and gui.compareIndices(w,newpos, ">", self.wrapPos): return None, None
def searchHelper (self,s,i,j,pattern,backwards,nocase,regexp,word,swapij=True):

if swapij and backwards: i,j = j,i

# g.trace(backwards,i,j,repr(s[i:i+20]))

if not s[i:j] or not pattern: # g.trace('empty',i,j) return -1,-1

if regexp: pos,newpos = self.regexHelper(s,i,j,pattern,backwards,nocase) elif backwards: pos,newpos = self.backwardsHelper(s,i,j,pattern,nocase,word) else: pos,newpos = self.plainHelper(s,i,j,pattern,nocase,word)

return pos,newpos
def regexHelper (self,s,i,j,pattern,backwards,nocase):

try: flags = re.MULTILINE if nocase: flags |= re.IGNORECASE re_obj = re.compile(pattern,flags) except Exception: g.es('Invalid regular expression: %s' % (pattern),color='blue') self.errors += 1 # Abort the search. return -1, -1

if backwards: # Scan to the last match. last_mo = None while 1: mo = re_obj.search(s,i,j) if mo is None: break i = mo.end() last_mo = mo self.match_obj = mo = last_mo else: self.match_obj = mo = re_obj.search(s,i,j)

if mo is None: return -1, -1 else: k = mo.start() k2 = mo.end() if 0: g.trace('i: %d, j: %d k: %d, k2: %d, s[k:k2]: %s, len(s): %d, s[-1]: %s,' % ( i,j,k,k2,repr(s[k:k2]),len(s),repr(s[-1]))) # g.trace('groups',mo.groups()) return k, k2
def backwardsHelper (self,s,i,j,pattern,nocase,word):

if nocase: s = s.lower() ; pattern.lower()

n = len(pattern) if word: while 1: k = s.rfind(pattern,i,j) # g.trace(i,j,k) if k == -1: return -1, -1 if self.matchWord(s,k,pattern): return k,k+n else: j = max(0,k-1) else: k = s.rfind(pattern,i,j) # g.trace(i,j,k) if k == -1: return -1, -1 else: return k,k+n
def plainHelper (self,s,i,j,pattern,nocase,word):

# g.trace(repr(s[i:i+20]))

n = len(pattern) if nocase: s = s.lower() ; pattern = pattern.lower() pattern = pattern.replace('\\n','\n').replace('\\t','\t')

if word: while 1: k = s.find(pattern,i,j) # g.trace(k,n) if k == -1: return -1, -1 elif self.matchWord(s,k,pattern): return k, k + n else: i = k + n else: k = s.find(pattern,i,j) if k == -1: return -1, -1 else: return k, k + n
def matchWord(self,s,i,pattern):

ok = g.match_word(s,i,pattern) and ( i == 0 or s[i-1] not in self.word_chars or s[i] not in self.word_chars )

# g.trace(ok,repr(s),i) return ok
# Selects the next node to be searched.

def selectNextPosition(self):

c = self.c ; p = self.p

if self.selection_only: return None

# Start suboutline only searches. if self.suboutline_only and not self.onlyPosition: # p.copy not needed because the find code never calls p.moveToX. # Furthermore, p might be None, so p.copy() would be wrong! self.onlyPosition = p

# Start wrapped searches. if self.wrapping and not self.wrapPosition: assert(self.wrapPos != None) # p.copy not needed because the find code never calls p.moveToX. # Furthermore, p might be None, so p.copy() would be wrong! self.wrapPosition = p

if self.in_headline and self.search_body: # just switch to body pane. self.in_headline = False self.initNextText() # g.trace('switching to body',g.callers(5)) return p

if self.reverse: p = p.threadBack() else: p = p.threadNext()

# New in 4.3: restrict searches to hoisted area. # End searches outside hoisted area. if c.hoistStack: if not p: if self.wrapping: g.es('Wrap disabled in hoisted outlines',color='blue') return bunch = c.hoistStack[-1] if not bunch.p.isAncestorOf(p): g.es('Found match outside of hoisted outline',color='blue') return None

# Wrap if needed. if not p and self.wrapping and not self.suboutline_only: p = c.rootPosition() if self.reverse: # Set search_v to the last node of the tree. while p and p.next(): p = p.next() if p: p = p.lastNode()

# End wrapped searches. if self.wrapping and p and p == self.wrapPosition: # g.trace("ending wrapped search") p = None ; self.resetWrap()

# End suboutline only searches. if (self.suboutline_only and self.onlyPosition and p and (p == self.onlyPosition or not self.onlyPosition.isAncestorOf(p))): # g.trace("end outline-only") p = None ; self.onlyPosition = None

# p.copy not needed because the find code never calls p.moveToX. # Furthermore, p might be None, so p.copy() would be wrong! self.p = p # used in initNextText(). if p: # select p and set the search point within p. self.in_headline = self.search_headline self.initNextText() return p
def checkArgs (self):

val = True if not self.search_headline and not self.search_body: g.es("not searching headline or body") val = False if len(self.find_text) == 0: g.es("empty find patttern") val = False return val
# Initializes for the Find All and Change All commands.

def initBatchCommands (self):

c = self.c self.in_headline = self.search_headline # Search headlines first. self.errors = 0

# Select the first node. if self.suboutline_only or self.node_only or self.selection_only: self.p = c.currentPosition() if self.selection_only: self.selStart,self.selEnd = c.frame.body.getTextSelection() else: self.selStart,self.selEnd = None,None else: p = c.rootPosition() if self.reverse: while p and p.next(): p = p.next() p = p.lastNode() self.p = p

# Set the insert point. self.initBatchText()
# Returns s_ctrl with "insert" point set properly for batch searches. def initBatchText(self): p = self.p self.wrapping = False # Only interactive commands allow wrapping. s = g.choose(self.in_headline,p.headString(), p.bodyString()) return self.init_s_ctrl(s)

# Call this routine when moving to the next node when a search fails. # Same as above except we don't reset wrapping flag. def initNextText(self): p = self.p s = g.choose(self.in_headline,p.headString(), p.bodyString()) return self.init_s_ctrl(s)
# Guesses which pane to start in for incremental searches and changes. # This must not alter the current "insert" or "sel" marks.

def initInHeadline (self):

c = self.c ; p = self.p

# Do not change this without careful thought and extensive testing! if self.search_headline and self.search_body: # A temporary expedient. if self.reverse: self.in_headline = False else: # Search headline first. self.in_headline = ( p == c.frame.tree.editPosition() and c.get_focus() != c.frame.body.bodyCtrl) else: self.in_headline = self.search_headline
# For incremental searches

def initInteractiveCommands(self):

c = self.c ; p = self.p ; gui = g.app.gui

self.errors = 0 if self.in_headline: c.frame.tree.setEditPosition(p) t = c.edit_widget(p) sel = None else: t = c.frame.bodyCtrl sel = gui.getTextSelection(t) pos = gui.getInsertPoint(t) st = self.initNextText() c.widgetWantsFocus(t) gui.setInsertPoint(st,pos) if sel: self.selStart,self.selEnd = sel else: self.selStart,self.selEnd = None,None self.wrapping = self.wrap if self.wrap and self.wrapPosition == None: self.wrapPos = pos # Do not set self.wrapPosition here: that must be done after the first search.
def printLine (self,line,allFlag=False):

both = self.search_body and self.search_headline context = self.batch # "batch" now indicates context

if allFlag and both and context: g.es('-' * 20,self.p.headString()) theType = g.choose(self.in_headline,"head: ","body: ") g.es(theType + line) elif allFlag and context and not self.p.isVisited(): # We only need to print the context once. g.es('-' * 20,self.p.headString()) g.es(line) self.p.setVisited() else: g.es(line)
# Restores the screen after a search fails

def restore (self,data):

c = self.c ; gui = g.app.gui in_headline,p,t,insert,start,end = data

c.frame.bringToFront() # Needed on the Mac

# Don't try to reedit headline. c.selectPosition(p)

if not in_headline: # Looks good and provides clear indication of failure or termination. gui.setSelectionRange(t,insert,insert) gui.setInsertPoint(t,insert) gui.makeIndexVisible(t,insert)

#g.trace(c.widget_name(t))

if 1: # I prefer always putting the focus in the body. c.invalidateFocus() c.bodyWantsFocusNow() else: c.widgetWantsFocusNow(t)
def save (self):

c = self.c ; p = self.p ; gui = g.app.gui t = g.choose(self.in_headline,c.edit_widget(p),c.frame.bodyCtrl) insert = gui.getInsertPoint(t) sel = gui.getSelectionRange(t) if len(sel) == 2: start,end = sel else: start,end = None,None return (self.in_headline,p,t,insert,start,end)
def showSuccess(self,pos,newpos):

"""Displays the final result.

Returns self.dummy_vnode, c.edit_widget(p) or c.frame.bodyCtrl with "insert" and "sel" points set properly."""

c = self.c ; p = self.p ; gui = g.app.gui

c.frame.bringToFront() # Needed on the Mac c.beginUpdate() try: c.selectPosition(p) finally: c.endUpdate() if self.in_headline: c.editPosition(p) # Set the focus and selection after the redraw. t = g.choose(self.in_headline,c.edit_widget(p),c.frame.bodyCtrl) insert = g.choose(self.reverse,pos,newpos) # New in 4.4a3: a much better way to ensure progress in backward searches. # g.trace(id(t),pos,newpos) c.widgetWantsFocusNow(t) gui.setSelectionRange(t,pos,newpos,insert=insert) # c.widgetWantsFocusNow(t) gui.makeIndexVisible(t,insert) if self.wrap and not self.wrapPosition: self.wrapPosition = self.p
def init_s_ctrl (self,s): __pychecker__ = '--no-argsused' self.oops()

def bringToFront (self): self.oops()

# New in 4.3: allows base class to adjust controls. def adjust_find_text(self,s): __pychecker__ = '--no-argsused' self.oops()

def oops(self): print ("leoFind oops:", g.callers(),"should be overridden in subclass")

def update_ivars(self): self.oops()
------------------

|back| |leo| |next|
@language rest
.. June 8, 2006

@ @rst-options code_mode=False doc_only_mode=False default_path = generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|back| |leo| |next|

#################################### Chapter 13: Writing Plugins ####################################

.. contents::
.. External links...

.. _docutils: http://docutils.sourceforge.net .. _LaTeX: http://www.latex-project.org/ .. _reStructuredText: http://docutils.sourceforge.net/rst.html .. _SilverCity: http://silvercity.sourceforge.net

.. Relative links...

.. _`Event handlers`: scripting.html#event-handlers .. _`Chapter 7\: Scripting Leo with Python`: scripting.html .. _`Chapter 8\: Customizing Leo`: customizing.html

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: plugins.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: rstplugin3.html
-----------------------

|back| |leo| |next|
These commands are for debugging Leo itself::

collect-garbage debug disable-gc-trace dump-all-objects dump-new-objects dump-outline enable-gc-trace free-tree-widgets print-focus print-gc-summary print-stats verbose-dump-objects
The following commands print various helpful messages. Apropos commands print longer discussions of specific topics. The help-for-command command prompts for a command name (you can use typing completion to specify the command) and then prints a brief description of that command::

apropos-autocompletion apropos-bindings apropos-find-commands help help-for-command mode-help print-bindings print-commands python-help
The following commands work just like their Emacs counterparts. Use the help-for-command command for further details::

abbrev-mode add-global-abbrev add-space-to-lines add-tab-to-lines advertised-undo append-to-buffer append-to-register call-last-keyboard-macro capitalize-word center-line center-region clean-lines clear-extend-mode clear-kill-ring clear-rectangle clear-selected-text close-rectangle copy-rectangle-to-register copy-text copy-to-register count-region dabbrev-completion dabbrev-expands delete-comments delete-file delete-indentation delete-rectangle delete-spaces diff digit-argument downcase-region downcase-word end-kbd-macro escape eval-expression expand-region-abbrevs fill-paragraph fill-region fill-region-as-paragraph flush-lines full-command goto-char how-many increment-register indent-region indent-relative indent-rigidly indent-to-comment-column insert-body-time insert-file insert-keyboard-macro insert-parentheses insert-register inverse-add-global-abbrev jump-to-register keep-lines keyboard-quit kill-all-abbrevs kill-buffer kill-line kill-paragraph kill-rectangle kill-region kill-region-save kill-sentence kill-word line-number list-abbrevs list-buffers-alphabetically load-file make-directory match-bracket name-last-kbd-macro negative-argument number-command number-command-0 number-command-1 number-command-2 number-command-3 number-command-4 number-command-5 number-command-6 number-command-7 number-command-8 number-command-9 open-rectangle point-to-register prepend-to-buffer prepend-to-register read-abbrev-file remove-blank-lines remove-directory remove-sentinels remove-space-from-lines remove-tab-from-lines rename-buffer repeat-complex-command reverse-region run-unit-tests select-paragraph set-comment-column set-fill-column set-fill-prefix shell-command shell-command-on-region sort-columns sort-fields sort-lines split-line start-kbd-macro string-rectangle suspend switch-to-buffer tabify transpose-chars transpose-lines transpose-words unindent-region universal-argument unmark-all untabify upcase-region upcase-word view-lossage view-register what-line yank yank-pop yank-rectangle zap-to-character
Here is a list of all of Leo's find commands. The apropos-find-commands command will print a detailed help message discussing these commands::

clone-find-all find-character find-tab-change find-tab-change-all find-tab-change-then-find find-tab-find find-tab-find-all find-tab-find-prev find-word isearch-backward isearch-backward-regexp isearch-forward isearch-forward-regexp isearch-with-present-options query-replace query-replace-regex re-search-backward re-search-forward replace-string search-again search-backward search-forward search-with-present-options set-find-everywhere set-find-node-only set-find-suboutline-only toggle-find-ignore-case-option toggle-find-in-body-option toggle-find-in-headline-option toggle-find-mark-changes-option toggle-find-mark-finds-option toggle-find-regex-option toggle-find-reverse-option toggle-find-word-option toggle-find-wrap-around-option word-search-backward word-search-forward
The following basic editing commands are typically bound to key strokes::

back-char back-char-extend-selection back-paragraph back-paragraph-extend-selection back-sentence back-sentence-extend-selection back-to-indentation back-word back-word-extend-selection backward-delete-char backward-kill-paragraph backward-kill-sentence backward-kill-word beginning-of-buffer beginning-of-buffer-extend-selection beginning-of-line beginning-of-line-extend-selection cut-text delete-char end-of-buffer end-of-buffer-extend-selection end-of-line end-of-line-extend-selection exchange-point-mark extend-to-word forward-char forward-char-extend-selection forward-paragraph forward-paragraph-extend-selection forward-sentence forward-sentence-extend-selection forward-word forward-word-extend-selection insert-newline move-lines-down move-lines-up move-past-close move-past-close-extend-selection newline-and-indent next-line next-line-extend-selection paste-text previous-line previous-line-extend-selection redo select-all set-mark-command undo
The following commands invoke Leo's outline commands::

clone-node contract-all contract-node contract-or-go-left contract-parent copy-node cut-node de-hoist delete-node demote expand-to-level-1 expand-to-level-2 expand-to-level-3 expand-to-level-4 expand-to-level-5 expand-to-level-6 expand-to-level-7 expand-to-level-8 expand-to-level-9 expand-all expand-and-go-right expand-next-level expand-node expand-or-go-right expand-prev-level go-back go-forward goto-first-node goto-first-sibling goto-last-node goto-last-sibling goto-last-visible goto-line goto-line-number goto-next-changed goto-next-clone goto-next-marked goto-next-node goto-next-sibling goto-next-visible goto-parent goto-prev-node goto-prev-sibling goto-prev-visible hoist insert-node mark mark-changed-items mark-changed-roots mark-clones mark-subheads move-outline-down move-outline-left move-outline-right move-outline-up outline-to-CWEB outline-to-noweb paste-node paste-retaining-clones promote sort-children sort-siblings
Here are various miscellaneous minibuffer commands::

about-leo add-comments check-all-python-code check-outline check-python-code clear-recent-files convert-all-blanks convert-all-tabs convert-blanks convert-tabs execute-script export-headlines exit-leo extract extract-names extract-section flatten-outline goto-global-line import-at-file import-at-root import-cweb-files import-derived-file import-flattened-outline import-noweb-files insert-headline-time new open-leoDocs-leo open-leoPlugins-leo open-leoSettings-leo open-offline-tutorial open-online-home open-online-tutorial open-outline open-outline-by-name open-python-window open-with open-with-idle open-with-word open-with-wordpad pretty-print-all-python-code pretty-print-python-code read-at-file-nodes read-outline-only reformat-paragraph revert save-buffers-kill-leo save-file save-file-as save-file-to settings set-colors set-font show-colors show-find-options show-fonts show-invisibles spell-change spell-change-then-find spell-find spell-ignore tangle tangle-all tangle-marked toggle-angle-brackets untangle untangle-all untangle-marked weave write-abbrev-file write-at-file-nodes write-dirty-at-file-nodes write-missing-at-file-nodes write-outline-only
The following commands simulate mouse clicks, double-clicks or drags::

abort-edit-headline activate-cmds-menu activate-edit-menu activate-file-menu activate-help-menu activate-outline-menu activate-plugins-menu activate-window-menu add-editor cascade-windows click-click-box click-headline click-icon-box close-window contract-body-pane contract-log-pane contract-outline-pane contract-pane cycle-editor-focus cycle-focus delete-editor double-click-headline double-click-icon-box edit-headline end-edit-headline equal-sized-panes expand-body-pane expand-log-pane expand-outline-pane expand-pane focus-to-body focus-to-log focus-to-minibuffer focus-to-tree fully-expand-body-pane fully-expand-log-pane fully-expand-outline-pane fully-expand-pane hide-body-pane hide-find-tab hide-invisibles hide-log-pane hide-mini-buffer hide-outline-pane hide-pane hide-spell-tab iconify-frame minimize-all open-compare-window open-find-dialog open-find-tab open-spell-tab press-rst3-button press-save-button press-spell-button resize-to-screen scroll-down scroll-down-extend-selection scroll-outline-down-line scroll-outline-down-page scroll-outline-up-line scroll-outline-up-page scroll-up scroll-up-extend-selection show-mini-buffer simulate-begin-drag simulate-end-drag toggle-active-pane toggle-invisibles toggle-mini-buffer toggle-split-direction
These commands put Leo into various kinds of modes.

- The ``enter-*-mode`` commands enter modes defined by @mode nodes in leoSettings.leo (or in other .leo files).

- The set-command-state, set-insert-state, set-overwrite-state commands determine how treats unbound plain keys. Leo ignores such keys in command state, inserts them into the body pane in insert state, and overwrites the character at the cursor position in overwrite state.

- Other commands determine whether autocompletion or calltips are in effect.

- When extend mode is effect, basic editing commands that move the cursor also extend the selected text. For example, in extend mode the ``back-char`` command works the same as the ``back-char-extend-selection`` command.

Here is the full list of mode-related commands::

auto-complete auto-complete-force disable-autocompleter disable-calltips enable-autocompleter enable-calltips enter-apropos-mode enter-commands-mode enter-edit-mode enter-emacs-mode enter-extract-mode enter-file-mode enter-gui-mode enter-help-mode enter-kill-mode enter-modes-mode enter-move-outline-mode enter-outline-mode enter-quick-command-mode enter-toggle-find-mode exit-named-mode set-command-state set-extend-mode set-insert-state set-overwrite-state set-silent-mode show-calltips show-calltips-force toggle-autocompleter toggle-calltips toggle-extend-mode toggle-input-state
@language rest
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|prev| |leo| |next|

########################################## What's New in Leo 4.4 ##########################################

This page summarizes the changes made in Leo 4.4. For full details see the release notes section in LeoDocs.leo.

The main features of Leo 4.4 are:

- An Emacs-like mini-buffer: you can now execute any command by typing its long name, with tab completion.

- Many new commands, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles. You can use Leo without using a mouse.

- Flexible key bindings and input modes. You can emulate the operation of Emacs, Vim, or any other editor.

- A tabbed log pane. The Find and Spell Check commands now use tabs instead of dialogs, making those commands much easier to use. Plugins or scripts can easily create new tabs. The Completion tab shows possible typing completions.

- Autocompletion and calltips. Autocompletion works much like tab completion. To enable autocompletion, bind a key to the auto-complete command.

.. contents::
Leo 4.4.1 beta 2 June 23, 2006

Leo 4.4.1 beta 2 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.1: ---------------------------- - A new colorizer plugin controlled by jEdit language description files. At present this plugin only reliably colors @language python code. - Multiple editors in Leo's body pane. - Search commands now support regex replace patterns: \1, \2, etc. - Support for external debuggers: see http://webpages.charter.net/edreamleo/debuggers.html - The scripting plugin now creates a Debug Script button. - Several new commands including run-unit-test, python-help and toggle-invisibles. - The help-for-command commands now contains information for almost all commands. - A new shortcut_button plugin.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
Called c.bringToFront() after open/save/import dialogs.
FAIL: @test return ends editing of headline

---------------------------------------------------------------------- Traceback (most recent call last): File "c:\prog\tigris-cvs\leo\src\leoTest.py", line 155, in runTest exec script + '\n' in {'c':c,'g':g,'p':p} File "<string>", line 14, in ? AssertionError: oops2

---------------------------------------------------------------------- Ran 438 tests in 193.628s

FAILED (failures=1) >>>
http://sourceforge.net/forum/message.php?msg_id=3764077
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3771032 By: paulpaterson

The cycle-editor-focus command causes Leo to lock up on my machine (WinXP, Python 2.4).

@color
http://sourceforge.net/forum/message.php?msg_id=3771014
lstrip and rstrip do not exist in Python 2.2.1.
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3778764 By: davidmcnab

When I hit my 'change-editor-focus' binding, the cursor jumps to unpredictable places within the next editor pane.
Added makeMasterGuiBinding.
Leo now supports bindings of the form:

command-name !command = shortcut

You will find examples in leoSettings.leo in the node

@keys EKR bindings: vim mode bindings-->Shortcuts-->@shortcuts top-level keys

Such bindings are essential for all plain key bindings that are *only* to be executed in command mode. Most, but *not* all plain key bindings should be bound in the !command 'pane'. The two exceptions presently are '.' which *always* invokes the autocompleter code and '(' which *always* invokes the calltips code.

It is now possible to have a *single* set of key bindings be 'Emacs-like' and 'Vim-like' at the same time. See the node EKR bindings: vim mode bindings in leoSettings.leo.

One setting switches between emacs-like operation and vim-like operation:

For emacs, use: @strings [ignore,insert,overwrite] top_level_unbound_key_action = insert

For vim, use: @strings [ignore,insert,overwrite] top_level_unbound_key_action = ignore

Vim-like modes are made possible by two new features:

1. Entry commands in @mode nodes. In the body of @mode nodes, lines of the form

--> command-name

tell Leo to execute the command when entering the mode. More than one such lines may exist; Leo executes them in the order they appear. Entry commands are potentially a very powerful feature. To avoid chaos, entry commands should not alter the minibuffer :-)

2. Silent modes. In order to keep the selected text visible, Leo must *not* move focus into the minibuffer for editing commands. The set-silent-mode command tells Leo to treat the mode described in the @mode node as a silent mode. A true mode is created, but it only affects key bindings and the minibuffer never becomes active.

Thus, all @mode nodes for vim-like modes contain the following line:

--> set-silent-mode.
All sets of key bindings in leoSettings.leo now start with @keys in the headline of the root node. The @keys convention is used *only* by the Check Bindings script. So now, instead of having a static list of key bindings sets (which is guaranteed to get out-of-date), the Check Bindings script can scan all of leoSettings.leo for sets of key bindings.

Another improvement to the Check Bindings script. Besides doing a better job of checking, you may now specify optional commands, such as commands defined in plugins. The Check Bindings will not complain if the commands don't presently exists in k.commandsDict. You specify such commands by adding items to the following lists in the root node of the Check Bindings script, i.e., the node Buttons-->@button Check Bindings.

optionalCommandPrefixes = ['group-operations'] optionalCommandNames = []
- added isearch-with-present-options. - many small improvements to isearch code. - regex searches now highlighted properly. - isearches are (and should be) confined to a single body text. - Backspace now handled properly.

A small glitch. Starting a regexp pattern with '.' will cause the entire pattern to turn red initially, which is technically correct but perhaps a bit confusing.
http://sourceforge.net/forum/message.php?msg_id=3767016
The commands that enable and disable calltips now update the status line.
Creating a script button creates the press-xxx-button command, and you can specify settings for such commands using @shortcuts nodes.
@nocolor

The scripting plugin now creates a press-x-button command for each scripting button named x. You can bind shortcuts to such commands by placing @shortcuts nodes in an @setting tree in the outline containing the @button nodes. test.leo shows an example.

What I did:

- The scripting plugin now defines button bindings with the 'button' pane specifier. This takes precedence over all other specifiers.

- k.bindKeyToDict now does a better job of detecting and warning about redefinitions.

- k.printBindings now properly sorts entries. This was causing me a great deal of confusion.

- k.registerCommand now properly gets shortcuts from settings if possible, and makes bindings in the new 'button' pane specifier.

- masterKeyHandlerHelper now supports the 'button' pane specifier, which overrides all others.

@color
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3772475

Maybe put a link to the html TOC into the Help Menu, "%leodir%/doc/html/leo_TOC.html".

This is more intuitive (to newbies) than the LeoDocs.leo link. I found this very confusing in the beginning.

What I did:

- Created open-users-guide command. - Created Open Users Guide menu item. - Removed Open Offline Tutorial menu item.

@color
# Important: this can be done better using per-pane bindings as in the default leoSettings.leo.
http://sourceforge.net/forum/message.php?msg_id=3778744

Added editor_orientation setting: valid values are vertical and horizontal.
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3767601 http://sourceforge.net/forum/message.php?msg_id=3768413 Craig

I have an @thin file with @Doc and @Code sections scattered though out the tree, where each node has one or more doc and code sections.

I would like to be able to use the rst3 plugin to produce an html file containing only info from the doc sections, ignoring the code sections.

I added the
@nocolor http://sourceforge.net/forum/message.php?msg_id=3770732 By: ktenney

In << Theory of operation of find/change >> the opening paragraph does not appear in the html,
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3780216 Craig

In Doc_Only_Mode the rst3 plugin outputs headlines irrespective of the show_headlines setting. The other modes do honor this setting.

I scratched around and managed to fix this by changing the node: rst3.py-->class rstClass-->write methods-->writeBody & helpers-->handleDocOnlyMode

In Line 25 I added a new statement: if showHeadlines: and indented the following 3 lines to make them conditional on this if: if result or showThisHeadline or showOrganizers or p == self.topNode: # g.trace(len(result),p.headString()) self.writeHeadlineHelper(p)
@nocolor http://sourceforge.net/forum/message.php?msg_id=3785400 By: craigj3

I have a @url node pointing to a Leo file which has a filename with %20 in it. When I double-click this node I get:

"can not open: \\\Documents%20and%20Settings\tftcj1.EDCON\My%20Documents\Proj\RI CAA\PcasCellLink.leo"

Taking a look with a debugger, I see that Plugins-->Enhancing the icon and status areas-->@thin UNL.py-->onUrl1 line 29ish does not covert %20 to spaces before calling openWithFileName.
@nocolor http://sourceforge.net/forum/message.php?msg_id=3783225 Craig

I am looking at the image plugin for organizing photos, and discovered that it is limited to gif files only. I found this a bit silly as installing the ImageTk module from the Python Imaging Library and making a two line change to the plugin enables it to be used on practically any image type.

The two line are: 1. a new import:- import ImageTk

2. In <<select image>> line 9 change photo = Tk.PhotoImage(master=a.root, file=filename)

to

photo = ImageTk.PhotoImage(master=a.root, file=filename)
@nocolor http://sourceforge.net/forum/message.php?msg_id=3779706 By: mstarzyk

My point was not about not found CSS, but that .html files are written to default_path directory, but .txt files are not written to default_path directory.
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3784636 By: craigj3

I note that the scheduler plugin is currently broken.

The problem was that all commands now get an event arg.

The Begin Recording and End Recording commands do not seem to work...
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|prev| |leo| |next|

########################################## What's New in Leo 4.4.1 ##########################################

This page summarizes the changes made in Leo 4.4.1. For full details see the release notes section in LeoDocs.leo.

The main features of Leo 4.4.1 are:

- Multiple editors in Leo's body pane and - A new colorizer plugin controlled by jEdit language description files. - Search commands now support regex replace patterns: \1, \2, etc. - Support for external debuggers: see http://webpages.charter.net/edreamleo/debuggers.html - The scripting plugin now creates a Debug Script button. - Several new commands including run-unit-test, python-help and toggle-invisibles. - The help-for-command commands now contains information for almost all commands. - A new shortcut_button plugin.

.. contents::
- The print-bindings command now properly sorts bindings. - The help-for-command command now works for almost all commands. - Improved filename completion. - Better listings for print-commands and print-bindings &amp; mode-help commands. - Allow shortcuts to be overridden outside of leoSettings.leo. - Finished Cmds menu. - Improved show-fonts command. - Strip quotes from color, font settings. - Warn about invalid Enter and Leave key bindings.
- Removed warning about changed node. - Added scroll-outline-left/right commands. - Leo outputs decorators correctly, assuming the decorator does not conflict with a Leo directive. - Wrote script to convert g.es to g.et where appropriate. The first step in translating all Leo messages. - Leo highlights (flashes) matching brackets when typing typing (, ), [, ], { or }. - Fixed long-standing problem reporting indentation errors. - Fixed long-standing bug in Remove Sentinels command. - Fixed long-standing bugs in import commands. - The scroll-up/down commands now scroll the outline if focus is in outline pane. However, his can be done better using per-pane bindings as in the default leoSettings.leo. - Incremental searches are (properly) confined to a single body text. - Backspace now handled properly in incremental searches. - The add-editor command adds a new editor in the body pane. The delete-editor command deletes the presently selected editor, and the cycle-editor-focus command cycles focus between editors in the body text. - The standard \1, \2, etc. replacements can now be performed in regular expression searches. - The standard escapes \n and \t are now valid in plain searches. - The shortcut for the replace-string command now changes from the find command to the replace command.
::

@bool autoindent_in_nocolor_mode @bool flash_matching_brackets @bool idle_redraw @bool trace_bind_key_exceptions @bool warn_about_redefined_shortcuts @color flash_brackets_background_color @color flash_brackets_foreground_color @int flash-brackets-delay @int flash_brackets_count @string close_flash_brackets @string open_flash_brackets @string editor_orientation
::

cycle-focus debug find-character find-word hide-invisibles isearch-with-present-options open-users-guide python-help run-unit-test toggle-autocompleter toggle-calltips toggle-invisibles
- The slideshow plugin - The mod_scripting plugin now creates a press-x-button command for every button 'x'. You can specify settings for such commands using @shortcuts nodes. - The shortcut_button plugin plugin creates a 'Shortcut' button in the icon area. Pressing the Shortcut button creates *another* button which when pressed will select the presently selected node at the time the button was created. - Added Debug button to scripting plugin.
- Added script to update new copies of leoSetttings.leo from previous copies. - Made all edit command undoable. - Improved registerCommand. - Suppressed autocompletion after numbers. - Added colorizing support for Lua language. - Added run-unit-test command. - Autocompletion and calltips. - Leo remembers the previous open directory. - Fixed problem with view plugin. - Installed cleo patch. - User input modes. - Installed many standard bindings to leoSettings.leo. - Added Check Bindings script in leoSettings.leo. - Scripts now maintain original focus. - Improved cursor move/extend commands. - Added support for @mode nodes. - keyboard-quit restores default input mode. - Created ut.leo, ut.py and ut.bat. - Added modes/\*.xml to distribution. - Revised cursor movement commands and added selection-extension commands. - Added classic key bindings in leoSettings.leo. - Allow multiple key bindings to the same command. - Settings command now opens leoSettings.leo. - Moved all scripts into scripts.leo. - Improved how the New Tab and Rename Tab commands work in the log pane. - Improved the appearance of the Spell tab. - Added Clone-find checkbox to the Find tab. - Improved find tab. - Improved formatting of shortcuts in print-commands and print-bindings. - Added settings for vim plugin. - Put up a dialog if can't import Pmw. - Bound <Return> to end-edit-headline. - Leo now ignores key bindings in menu tables. - Created scripts.leo and unitTest.leo. - c.executeMinibufferCommand executes a minibuffer command by name. - Improved perl entries in language dicts. - The tabbed log. - The Find tab replaces the old Find panel; the old Find panel is deprecated.
- Changed path to stylesheet in the rst3 plugin. - Fixed crasher in Word (and other) plugins. - Fixed problem with labels plugin. - Added the following commands for the groupoperations plugin::

group-operations-clear-marked group-operations-mark-for-copy group-operations-mark-for-move group-operations-mark-for-clone group-operations-mark-target group-operations-operate-on-marked group-operations-transfer

- Installed cleo patch. - The scripting plugin now supports shortcuts in @button nodes::

@button name @key=shortcut

- The scripting plugin now supports @command nodes::

@command name @key=shortcut
Added new settings::

@bool allow_idle_time_hook @bool autocomplete-brackets. @bool gc_before_redraw @bool minibufferSearchesShowFindTab @bool show_only_find_tab_options @bool show_tree_stats @bool trace_autocompleter @bool trace_bindings @bool trace_doCommand @bool trace_f.set_focus @bool trace_focus @bool trace_g.app.gui.set_focus @bool trace_gc @bool trace_gc_calls @bool trace_gc_verbose @bool trace_key_event @bool trace_masterClickHandler @bool trace_masterCommand @bool trace_masterFocusHandler @bool trace_masterKeyHandler @bool trace_minibuffer @bool trace_modes @bool trace_redraw_now @bool trace_select @bool trace_status_line @bool trace_tree @bool trace_tree_alloc @bool trace_tree_edit @bool useCmdMenu @bool useMinibuffer @bool use_syntax_coloring @color body_text_selection_background_color @color body_text_selection_foreground_color. @color log_pane_Find_tab_background_color @color log_pane_Spell_tab_background_color, etc. @int max_undo_stack_size, @string trace_bindings_filter @string trace_bindings_pane_filter

- Added @shortcuts nodes. - Leo now supports per-pane bindings of the form::

command-name ! pane = shortcut

- The spelling settings replace the settings in spellpyx.ini.
This section provides step-by-step instructions for turning a script button into a plugin. The plugin will define a minibuffer command that does the same thing as pressing the button.

We shall start with a script button whose script is::

g.es_print('c: %s' % (c.fileName()),color='red') g.es_print('p: %s' % (p.headString()),color='red')

Not very exciting, but it uses the predefined ``c`` and ``p`` constants. Our plugin will create a minibuffer command called print-cp.

Here are the step-by-step instructions:

1. Open leoPlugins.leo and use the Copy Node command to copy the tree at:

Plugins--> Templates: these show recommended ways of defining plugins.-->Template for Tk plugin with per-commander controller class

2. Paste the tree somewhere else and rename it to @thin print_cp.py. I copied the tree to::

Plugins-->Example code-->@thin print_cp.py

3. Update the docstring, the __version__ constant and the << imports >> section. Note that unlike when using script buttons, you must have the following imports::

import leoGlobals as g import leoPlugins

4. Because this plugin doesn't require any gui interface, we simplify the ``init`` function::

def init (): leoPlugins.registerHandler('after-create-leo-frame',onCreate) return True

The init function registers the onCreate hook and returns True to indicate that it loaded properly.

5. Leave the ``onCreate`` function unchanged. It creates a per-commander instance of the pluginController class. This class exists mainly to bind self.c properly to a commander.

6. Change the constructor (__init__ method) of the pluginController class to this::

def __init__ (self,c): self.c = c c.k.registerCommand('print-cp',shortcut=None,func=self.print_cp) script = "c.k.simulateCommand('print-cp')" g.makeScriptButton(c,script=script,buttonText='Print c & p',bg='red')

This registers the print_cp *method* of the print_cp class as the print-cp minibuffer command, and creates a script button with the following script::

c.k.simulateCommand('print-cp')

7. Define the print_cp method as follows::

def print_cp (self,event=None): c = self.c ; p = c.currentPosition() g.es_print('c: %s' % (c.fileName()),color='red') g.es_print('p: %s' % (p.headString()),color='red')

The print_cp method must have the event argument as shown because it implements a minibuffer command. The print_cp method gets the proper commander from the ``c`` ivar (instance variable) and computes the current position ``p`` as shown.

8. Enable the print_cp plugin using the plugins manager plugin, or just add the following line somewhere in pluginsManager.txt::

print_cp.py

9. Test the plugin by restarting Leo (I just start test.leo). You can test the plugin by pressing the 'Print c&p' button or by typing <Alt-x> print-cp <Return>.

That's all. You can find the completed version of the print_cp plugin in leoPlugins.leo, or leoPluginsRef.leo if you are using cvs.
.. Links used in this document.

.. WARNING: image targets may not have upper case letters!

.. |prev| image:: arrow_lt.gif :target: new-4-4-1.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: Blank.gif
.. Links used in this document.

.. WARNING: image targets may not have upper case letters!

.. |prev| image:: arrow_lt.gif :target: new-4-4-2.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: new-4-4.html
-----------------------

|prev| |leo| |next|
-----------------------

|prev| |leo| |next|
http://sourceforge.net/forum/message.php?msg_id=3784292

http://webpages.charter.net/edreamleo/install.html#updating-settings-from-previous-versions-of-leo
http://sourceforge.net/forum/message.php?msg_id=3778946

http://webpages.charter.net/edreamleo/writingPlugins.html#turning-script-buttons-into-plugins
http://sourceforge.net/forum/message.php?msg_id=3790857
http://sourceforge.net/forum/message.php?msg_id=3790814
Leo 4.4.1 beta 3 June 29, 2006

Leo 4.4.1 beta 3 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.1: ---------------------------- - A new colorizer plugin controlled by jEdit language description files. At present this plugin only reliably colors @language python code. - Multiple editors in Leo's body pane. - Search commands now support regex replace patterns: \1, \2, etc. - Support for external debuggers: see http://webpages.charter.net/edreamleo/debuggers.html - The scripting plugin now creates a Debug Script button. - Several new commands including run-unit-test, python-help and toggle-invisibles. - The help-for-command commands now contains information for almost all commands. - A new shortcut_button plugin.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
Leo 4.4 was a year-long effort to incorporate an Emacs-style minibuffer and related commands into Leo. Thinking in terms of minibuffer commands frees my thinking. Leo 4.4 also featured many improvements in how keys are bound to commands, including per-pane bindings and user-defined key-binding modes.

Development on long-delayed projects accelerated after 4.4 final went out the door. Recent projects include:

- Controlling syntax coloring with jEdit's xml language-description files. See Chapter 15. - Support for debugging scripts using external debuggers. See Chapter 16. - Modifying Leo's vnodes and tnodes so that Leo's data can be used with ZODB. See Chapter 17. - Using pymacs to write Leo scripts within Emacs. See Chapter 18. - Using the leoBridge module to embed Leo support in other programs. See Chapter 19. - Using Leo to run unit tests. See Chapter 20.
http://sourceforge.net/forum/message.php?msg_id=3795258

The column display doesn't change while typing.

http://sourceforge.net/forum/message.php?msg_id=3510448

The fix was to getLastTracebackFileAndLineNumber.

I also created handleScriptException.
http://sourceforge.net/forum/message.php?msg_id=3413805
- Underindented comments do not end the scan of Python classes or methods. - Handles continued signature lines properly.
Note: Editing headline text will happen in insert mode unless

@strings top_level_unbound_key_action = overwrite
After executing a command we must be careful to test c.exists.
- A better trace, and the trace goes to the log pane.

- Eliminated k.keysymHistory: Tk keysyms are pretty useless.
@nocolor

- Improved prompt. - Added message if no previous complex command. - Added mode entries.
http://sourceforge.net/forum/message.php?msg_id=3794854
@killcolor

Here are the relevant settings:

@bool flash_matching_brackets: True: flash matching bracket when typing (, ), [, ], { or }.

@color flash_brackets_background_color and @color flash_brackets_foreground_color.

@int flash_brackets_count: The number of times to flash matching brackets.

@int flash-brackets-delay: One half the total cycle time of bracket flashes, in milliseconds.
# Ctrl-k is no longer needed by the match-brackets command now that brackets flash automatically.
When True, this provides a full traceback for all exceptions taken when binding keyboard shortcuts.
@killcolor

@bool flash_matching_brackets: True: flash matching bracket when typing (, ), [, ], { or }.

@color flash_brackets_background_color and @color flash_brackets_foreground_color.

@int flash_brackets_count: The number of times to flash matching brackets.

@int flash-brackets-delay: One half the total cycle time of bracket flashes, in milliseconds.
You can 'revert' to old key bindings as follows:

1. Open leoSettings.leo.

2. Find the node 'Keyboard shortcuts'.

3. Disable the old bindings by moving the node '@keys EKR bindings: Emacs keys + modes' so that it is a child of the node: '@ignore Unused key bindings'.

4. Notice that there are two child nodes of the node '@ignore Unused key bindings' that refer to legacy key bindings:

- '@keys Legacy Leo shortcuts with important Emacs bindings'

- '@keys Legacy Leo bindings'.

5. Move **one** of these two legacy nodes up one level so that it is a child of the node 'Keyboard shortcuts'. It should **not** be a child of the node '@ignore Unused key bindings'.
By Rich Ries

There is no direct way to make script buttons available in multiple Leo files. Sure, you could copy and paste the @button nodes, but there is a slightly easier way using the "New Buttons" plugin.

1) Create and test and debug your desired Script Button.

2) With the Script Button node selected, run Plugins --> New buttons --> Make Template From

Open a new Leo file.

3) Assuming you have only the one New Button Template defined, left-click the New button, and a new node will be added to your outline. (Otherwise, you'll need to select the Template you want.)

4) Press [Script Button] to create the new script button.

It's easier to *do* this than to *explain* it!
Leo 4.4.1 beta 4 August 24, 2006

Leo 4.4.1 beta 4 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.1: ---------------------------- - Leo outputs decorators correctly, provided that the decorator is not a Leo directive. - A new colorizer plugin controlled by jEdit language description files. - A new shadow files plugin that allows derived files not to have sentinel lines. - Multiple editors in Leo's body pane. - Search commands now support regex replace patterns: \1, \2, etc. - Support for external debuggers: see http://webpages.charter.net/edreamleo/debuggers.html - The scripting plugin now creates a Debug Script button. - Several new commands including run-unit-test, python-help, toggle-invisibles, and scroll-outline-left/right. - The help-for-command commands now contains information for almost all commands. - A new shortcut_button plugin.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
http://sourceforge.net/forum/forum.php?thread_id=1542384&forum_id=10228
http://sourceforge.net/forum/message.php?msg_id=3839322
http://sourceforge.net/forum/message.php?msg_id=3805745
http://sourceforge.net/forum/message.php?msg_id=3841115

There is still some doubt about what the best operation of this command should be.
http://leo.zwiki.org/9RussianUnicodeWordsAreNotDetectedProperlyInBodyPane
http://sourceforge.net/forum/message.php?msg_id=3874380

Setting a value for background color in the body pane had no effect.

There were several problems, among which conflicting and confusing settings. In particular, the insert_mode_bg_color setting overrides the body_text_background_color setting.

I changed the code so that insert_mode_bg_color defaults to body_text_background_color, and put all the settings for the body text in one place.
http://sourceforge.net/forum/message.php?msg_id=3802624

Added @font menu font setting
http://sourceforge.net/forum/message.php?msg_id=3834645
http://sourceforge.net/forum/message.php?msg_id=3802513

Added these settings:

@string open_flash_brackets = ([{ @string close_flash_brackets = )]}
Leo *already* outputs decorators correctly, assuming the decorator does not conflict with a Leo directive.
http://sourceforge.net/forum/message.php?msg_id=3858363
These were overly complicated an not useful.
The shadow plugin allows you to use Leo with files which contain no Leo comments, and still have information flow in both directions: from the file into Leo, and from Leo into the file.

To use this plugin:

1. Install the shadow script button found in leoPy.leo in the node::

Code-->Buttons and settings-->@@button shadow

That is, copy and paste this @button node to your Leo outline, and change @@button to @button.

2. Position the cursor somewhere in your tree.

3. Clicking the shadow button will create a shadow file for all @thin nodes in the selected outline.

After this initial setup, changes in Leo will be reflected both in the file in the Leo subfolder, and the file without sentinels. Conversely, changes in the file without sentinels will flow back to the file in the leo subfolder, and show up in Leo. Text insertions within a node will show up as expected. Text insertion at the end of the node will show up and the end of the node. Note that the plugin never structures input; this has to be done manually within Leo.

You can set settings for this plugin in leoSettings.leo at::

@settings-->Plugins-->shadow plugin.

- @string shadow_subdir (default: LeoFolder): name of the shadow directory.

- @string shadow_prefix (default: x): prefix of shadow files. This prefix allows the shadow file and the original file to have different names. This is useful for name-based tools like py.test.
Leo 4.4.1 final August 30, 2006

Leo 4.4.1 final is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.1: ---------------------------- - Leo outputs decorators correctly, provided that the decorator is not a Leo directive. - A new colorizer plugin controlled by jEdit language description files. - A new shadow files plugin that allows derived files not to have sentinel lines. - Multiple editors in Leo's body pane. - Search commands now support regex replace patterns: \1, \2, etc. - Support for external debuggers: see http://webpages.charter.net/edreamleo/debuggers.html - The scripting plugin now creates a Debug Script button. - Several new commands including run-unit-test, python-help, toggle-invisibles, and scroll-outline-left/right. - The help-for-command commands now contains information for almost all commands. - A new shortcut_button plugin.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
# Possibly a less intrusive warning should be used.
@nocolor http://sourceforge.net/forum/message.php?msg_id=3885494 By: mikecrowe

OK, I found out how to duplicate this one. This caused me a lot of grief until I found out what is causing it.

NodeA: ...Child1 ...Child2 ...Child3

NodeB: ...CloneChild1 ...CloneChild2 ...CloneChild3

Now, put cursor on NodaA. Ctrl-Shift-C (copy node). Next, put cursor on CloneChild3. Paste Node as Clone You should get an invalid paste clone message.

Now, first cursor move (for me) puts NodeB as top node, ERASING all other nodes. Warning: DO NOT SAVE NOW. It will erase all other nodes.
@nocolor

- Created getLeoOutlineHelper. This simplifies the code. - Init self.checking in getLeoFile and getLeoOutline. - Use self.checking in getVnodes, getVnode and createVnode. Using self.checking in getVnode complicates an already way-too-complex method, but it can't be helped.
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3886250 By: znafets

A .leoID.txt with a \n behind the idstring creates a problem. It will be read in g.app.leoID and being used as is when writing the Leo file.

The fix is in app.setLeoID -> << return if we can set leoID from "leoID.txt" >>
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3890031 By: terry_n_brown

I have a tree of some 2500 nodes, run a script that marks probably 1500-2000 of them, and that's quick (2-3 seconds max.).

I can clear all the marks with:

for p in c.allNodes_iter(): p.v.clearMarked()

and that also is quick (2-3 seconds max.). But when I use the menu option Unmark All, that takes forever (1-2 minutes :-) running 100% CPU all the while.
This section discusses only those settings that affect syntax coloring. See `Chapter 8`_ for a general discussion of Leo's settings.

Both the old colorizer (in Leo's core) and the new colorizer (the threading_colorizer plugin) now support @font settings for colorizing options. The settings for the old colorizer are::

comment_font, cweb_section_name_font, directive_font, doc_part_font, keyword_font, leo_keyword_font, section_name_font, section_name_brackets_font, string_font, undefined_section_name_font, latexBackground_font, and latex_background_font.

The settings for the new colorizer are all of the above (except keyword_font) plus the following::

comment1, comment2_font, comment3_font, comment4_font, function_font, keyword1_font, keyword2_font, keyword3_font, keyword4_font, label_font, literal1_font, literal2_font, literal3_font, literal4_font, markup_font, null_font, and operator_font.

To specify a font, say for keyword_font, to be used as the default font for **all** languages, put the following in the body text of an @font node in leoSettings.leo::

# keyword_font_family = None keyword_font_size = 16 keyword_font_slant = roman # roman, italic keyword_font_weight = bold # normal, bold

Comments are allowed and undefined settings are set to reasonable defaults. At present, comments can not follow a setting: comments must start a line.

You can specify per-language settings by preceding the settings names by a prefix x. Such settings affect only colorizing for language x (i.e., all the modes in modes/x.py when using the new colorizer). For example, to specify a font for php (only), put the following in the body text of an @font node in leoSettings.leo::

# php_keyword_font_family = None php_keyword_font_size = 16 php_keyword_font_slant = roman # roman, italic php_keyword_font_weight = bold # normal, bold
Leo 4.4.1.1 final September 3, 2006

Leo 4.4.1.1 final is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo 4.4.1.1 corrects a serious last-minute unicode bug in Leo 4.4.1. This version also adds the new slideshow plugin.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.1: ---------------------------- - Leo outputs decorators correctly, provided that the decorator is not a Leo directive. - A new colorizer plugin controlled by jEdit language description files. - A new shadow files plugin that allows derived files not to have sentinel lines. - A new slide show plugin allows you to use Leo outlines as slide shows. - Multiple editors in Leo's body pane. - Search commands now support regex replace patterns: \1, \2, etc. - Support for external debuggers: see http://webpages.charter.net/edreamleo/debuggers.html - The scripting plugin now creates a Debug Script button. - Several new commands including run-unit-test, python-help, toggle-invisibles, and scroll-outline-left/right. - The help-for-command commands now contains information for almost all commands. - A new shortcut_button plugin.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
@language rest
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. September 13, 2006

|back| |leo| |next|

####################################### Chapter 17: Using ZODB with Leo #######################################

This chapter discusses how to write Leo scripts that store and retrieve data using ZODB_.

.. contents::
.. External links...

.. _ZODB: http://www.zope.org/Wikis/ZODB/guide/zodb.html .. _`Installing ZODB`: http://www.zope.org/Wikis/ZODB/guide/node3.html#SECTION000310000000000000000

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: debuggers.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: emacs.html
-----------------------

|back| |leo| |next|
This function inits the zodb. pathToZodbStorage is the full path to the zodb storage file. You can call g.init_zodb as many times as you like. Only the first call for any path actually does anything: subsequent calls for a previously opened path simply return the same value as the first call.
This vnode method returns v2, a copy of v that is completely detached from the outline. v2.t is a completely new tnode. v2.fileIndex is None initially, but is may be convenient to copy this field::

v2 = v.detach() v2.t.fileIndex = v.t.fileIndex
To enable zodb scripting within Leo, you must set ``use_zodb = True`` in the root node of leoNodes.py. You must also install ZODB itself. See `Installing ZODB`_ for details.

When ZODB is installed and ``use_zodb`` is ``True`` Leo's vnode and tnode classes become subclasses of ZODB.Persistence.Persistent. This is all that is needed to save/retrieve vnodes or tnodes to/from the ZODB.

**Important notes**:

- Scripts **should not** store or retrieve positions using the ZODB! Doing so makes sense neither from Leo's point of view nor from ZODB's point of view.

- The examples below show how to store or retrieve Leo data by accessing the so-called root of a ZODB connection. However, these are only examples. Scripts are free to do with Leo's vnodes and tnodes *anything* that can be done with ZODB.Persistence.Persistent objects.
Scripts should call g.init_zodb to open a ZODB.Storage file. g.init_zodb returns an instance of ZODB.DB. For example::

db = g.init_zodb (zodbStorageFileName)

You can call g.init_zodb as many times as you like. Only the first call for any path actually does anything: subsequent calls for a previously opened path simply return the same value as the first call.
The following script writes v, a tree of vnodes, to zodb::

db = g.init_zodb (zodbStorageFileName) connection = db.open() try: root = connection.root() root[aKey] = v # See next section for how to define aKey. finally: get_transaction().commit() connection.close()

Notes:

- v must be a vnode (or a tnode). Scripts should *not* attempt to store Leo positions in the zodb. v can be the root of an entire outline or a subtree. For example, either of the following would be reasonable::

root[aKey] = c.rootPosition().v root[aKey] = c.currentPosition().v

- To write a single vnode without writing any of its children you can use v.detach. For example::

root[aKey] = v.detach()

- **Important**: It is simplest if only one zodb connection is open at any one time, so scripts would typically close the zodb connection immediately after processing the data. The correct way to do this is in a finally statement, as shown above.

- The script above does not define aKey. The following section discusses how to define reasonable zodb keys.
The following script reads a tree of vnodes from zodb and sets p as the root position of the tree::

try: connection = db.open() root = connection.root() v = root.get(aKey) p = leoNodes.position(v) finally: get_transaction().commit() connection.close()
The keys used to store and retrieve data in connection.root() can be any string that uniquely identifies the data. The following are only suggestions: you are free to use any string you like.

1. When saving a file, you would probably use a key that is similar to a real file path. For example::

aKey = c.fileName()

2. When saving a single vnode or tree of vnodes, say v, a good choice would be to use v's gnx, namely::

aKey = g.app.nodeIndices.toString(v.t.fileIndex)

Note that v.detach() does not automatically copy v.t.fileIndex to the detached node, so when writing a detached node you would typically do the following::

v2 = v.detach() v2.t.fileIndex = v.t.fileIndex aKey = g.app.nodeIndices.toString(v2.t.fileIndex)
The scripts shown above close the zodb connection after processing the data. This is by far the simplest strategy. I recommend it for typical scripts.

**Important**: if must **leave the connection open** if your script modifies persistent data in any way. (Actually, this statement is not really true, but you must define zodb transaction managers if you intend to use multiple connections simultaneously. This complication is beyond the scope of this documentation.) For example, it would be possible to create a new Leo outline from the data just read, but the script must leave the connection open. I do not recommend this tactic, but for the adventurous here is some sample code::

connection = self.db.open() root = connection.root() v = root.get(fileName) if v: c2 = c.new() c2.openDirectory = c.openDirectory # A hack. c2.mFileName = fileName # Another hack. c2.beginUpdate() try: c2.setRootVnode(v) c2Root = c2.rootPosition() c2.atFileCommands.readAll(c2Root) g.es_print('zodb read: %s' % (fileName)) finally: c2.endUpdate() # Do *not* close the connection while the new Leo window is open! else: g.es_print('zodb read: not found: %s' % (fileName))

This will work **provided** that no other zodb connection is ever opened while this connection is opened. Unless special zodb precautions are taken (like defining zodb transaction managers) calling get_transaction().commit() will affect **all** open connections. You have been warned.
Find the @thin leoApp.py node in leoPy.leo. In the ctor for the LeoApp class set ``self.use_psyco`` to True or False. You will find this ctor in the node::

Code-->Core classes...-->@thin leoApp.py-->app.__init__

Note that this ivar can not be set using settings in leoSettings.leo because Leo uses g.app.use_psyco before processing configuration settings.
Add the following to the start of your scripts::

@first # -*- coding: utf-8 -*-

Without this line, constructs such as::

u = u'a-é-賢-z' u = 'a-é-賢-z'

will not work when executed with Leo's execute script command. Indeed, the Execute Script command creates the script by writing the tree containing the script to a string. This is done using Leo's write logic, and this logic converts the unicode input to a utf-8 encoded string. So *all non-ascii characters* (including both the é and 賢 characters) get converted to their equivalent in the utf-8 encoding. Call these encoding <e1> and <e2>. In effect the script becomes::

u = u'a-<e1>-<e2>-z' u = 'a-<e2>-<e>-z'

which is certainly *not* what the script writer intended! Rather than defining strings using actual characters, Instead, one should use the equivalent escape sequences. For example::

u = u'a-\u0233-\u8ce2-z' u = 'a-\u0233-\u8ce2-z'
.. _OPML: http://en.wikipedia.org/wiki/OPML .. _`OPML 2.0 standard`: http://www.opml.org

**Warning**: the OPML plugin is not fully functional at present. Use with caution.

The OPML plugin creates two new commands that read and write Leo outlines in OPML_ format. The read-opml-file command creates a Leo outline from an .opml file. The write-opml-file command writes the present Leo outline to an .opml file.

Various settings control what gets written to .opml files, and in what format. As usual, you specify settings for the OPML plugin using leoSettings.leo. The settings for the OPML are found in the node::

@settings-->Plugins-->opml plugin

Here are the settings that control the format of .opml files. The default values are shown.

- ``@bool opml_read_derived_files = True``

If True, Leo reads derived files when reading .opml files.

- ``@string opml_namespace = leo:com:leo-opml-version-1``

The namespace urn for the xmlns attribute of ``<opml>`` elements. This value typically is not used, but it should refer to Leo in some way.

- ``@bool opml_use_outline_elements = True``

If True, Leo writes body text to ``<:body>`` elements nested in ``<outline>`` elements. Otherwise, Leo writes body text to ``:body`` attributes of ``<outline>`` elements.

**Note**: Leo-specific attributes and elements are clearly distinguished from 'standard' opml elements: they are preceded by a colon, which marks them as members of the default namespace specified specified by this option. Thus, all OPML text generated by this plugin should conform to the `OPML 2.0 standard`_.

- ``@string opml_version = 2.0``

The opml version string written to the ``<OPML>`` element. Use ``2.0`` unless there is a specific reason to use ``1.0``.

- ``@bool opml_write_body_text = True``

If True, Leo writes body text to the OPML file.

- ``@bool opml_write_derived_files = True``

If True, Leo writes derived files when writing .opml files.

- ``@bool opml_write_leo_details = True``

If True, Leo writes the native attributes of Leo's ``<v>`` elements as attributes of the opml ``<outline>`` elements. The native attributes of ``<v>`` elements are ``a``, ``descendentTnodeUnknownAttributes``, ``expanded``, ``marks``, ``t``, and ``tnodeList``.

- ``@bool opml_write_leo_globals_attributes = True``

If True, Leo writes `body_outline_ratio`` and ``global_window_position`` attributes to the ``<head>`` element of the .opml file.

- ``@bool opml_write_uAs = True``

If True, Leo writes unknown attributes (uA's) in <:uA> sub-elements of <outline> elements.
Three commands in the Cmds:Body Editors menu allow to create and destroy separate editors in the body pane. The Add Body Editor (add-editor) command adds a new editor in the body pane. The Delete Body Editor (delete-editor) command deletes the presently selected editor, The Change Body Editor (cycle-editor-focus) command cycles focus between editors in the body text.
This section describe the format of derived files. Leo's `sentinel lines`_ are comments, and this section describes those comments.

The format of derived files produced by Leo 4.0 and later meets the following goals:

- The minimum of sentinels needed to properly recreate the outline.

- A robust way of telling whether newlines belong to sentinels or not. Prior to Leo 4.0, deleting blank lines before and after sentinel lines could corrupt the outline structure of the derived file.

- A minimum of intrusion and ugliness.

**New in Leo 4.2**: Files derived from ``@thin`` use gnx's in ``@+node`` and ``@-node`` sentinels. Such gnx's permanently and uniquely identify nodes. Gnx's have the form::

id.yyyymmddhhmmss id.yyyymmddhhmmss.n

The second form is used if two gnx's would otherwise be identical.

- ``id`` is a string unique to a developer, e.g., a cvs id.

- ``yyyymmddhhmmss`` is the node's creation date.

- ``n`` is an integer.

Here are the sentinels used by Leo, in alphabetical order. Unless otherwise noted, the documentation applies to all versions of Leo. In the following discussion, ``gnx`` denotes a gnx as described above.

\@<< A sentinel of the form ``@<<section_name>>`` represents a section reference.

If the reference does not end the line, the sentinel line ending the expansion is followed by the remainder of the reference line. This allows the Read code to recreate the reference line exactly.

\@@ The ``@@`` sentinel represents any line starting with ``@`` in body text except ``@``*whitespace*, ``@doc`` and ``@others``. Examples::

@@nocolor @@pagewidth 80 @@tabwidth 4 @@code

\@afterref **(Leo 4.0 and later)** Marks non-whitespace text appearing after a section references.

\@+all **(Leo 4.0 and later)** Marks the start of text generated by the ``@all`` directive.

\@-all **(Leo 4.0 and later)** Marks the end of text generated by the ``@all`` directive.

\@at and \@doc The ``@+doc`` and ``@-doc`` sentinels delimit doc parts within a node that starts with ``@doc``. These sentinels are nested within ``@body`` directives. Similarly, ``@+at`` and ``@-at`` sentinels delimit doc parts within a node that start with ``@`` *whitespace*. We use the following **trailing whitespace convention** to determine where putDocPart has inserted line breaks::

A line in a doc part is followed by an inserted newline if and only if the newline if preceded by whitespace.

To make this convention work, Leo's write code deletes the trailing whitespace of all lines that are followed by a "real" newline.

**Leo 4.0 and later**: The ``@+doc`` and ``@+at`` sentinels now contain the whitespace that follows the corresponding ``@doc`` or ``@`` directives.

\@+body **(Leo 3.x only)** Marks the start of body text.

\@-body **(Leo 3.x only)** Marks the end of body text.

\@delims The ``@delims`` sentinel inserts ``@@delims`` sentinels into the derived file. The new delimiter strings continue in effect until the next ``@@delims`` sentinel *in the derived file* or until the end of the derived file. Adding, deleting or changing ``@@delim`` *sentinels* will destroy Leo's ability to read the derived file. Mistakes in using the ``@delims`` *directives* have no effect on Leo, though such mistakes will thoroughly mess up a derived file as far as compilers, HTML renderers, etc. are concerned.

\@+leo Marks the start of any derived file. This sentinel has the form::

<opening_delim>@leo<closing_delim>

The read code uses single-line comments if ``<closing_delim>`` is empty. The write code generates single-line comments if possible.

**New in Leo 4.0**: The ``@+leo`` sentinel contains other information following ``@leo``. For example::

<opening_delim>@leo-ver=4-thin<closing_delim>

\@-leo Marks the end of the Leo file. Nothing but whitespace should follow this directive.

\@+middle **(Leo 4.0 and later)** Marks the start of intermediate nodes between the node that references a section and the node that defines the section. Typically no such sentinels are needed: most sections are defined in a direct child of the referencing node.

\@-middle **(Leo 4.0 and later)** Marks the end of intermediate nodes between the node that references a section and the node that defines the section.

\@+node and \@-node Mark the start and end of a node.

**Leo 4.2 and later**:: ``@+node`` and ``@-node`` sentinels use gnx's as described above::

@+node:gnx:<headline> @-node:gnx:<headline>

Leo generates these sentinels only for nodes containing body text. Leo no longer generates other ``@+node`` sentinels to indicate outline structure. As a result, there is no longer any need for ``@+body`` sentinels.

**Before Leo 4.2**:: ``@+node`` and ``@-node`` sentinels used child indices, and status fields as described below::

@+node:<child_index>:<status_fields>:<headline> @-node::<child_index>:<status_fields>:<headline>

``<child_index>`` is a number from 1 to n indicating the index of the node in the list of its parent's children. ``<status_field>`` is the cloneIndex field of the form: "C=nnn", where nnn is an immutable clone index. ``<headline>`` contains *headline* text, not reference text.

\@nl **(Leo 4.0 and later)** Adds a newline to the body text.

\@nonl **(Leo 4.0 and later)** Suppresses a newline from the body text.

\@others The ``@+others`` sentinel indicates the start of the expansion of an ``@+others`` directive, which continues until the matching ``@-others`` sentinel. ``@others`` sentinels are nested within ``@body`` sentinels; the expansion of the ``@others`` directive always occurs within the body text of some node.

\@verbatim ``@verbatim`` indicates that the next line of the derived file is not a sentinel. This escape convention allows body text to contain lines that would otherwise be considered sentinel lines.

\@@verbatimAfterRef ``@verbatimAfterRef`` is generated when a comment following a section reference would otherwise be treated as a sentinel. In Python code, an example would be::

<< ref >> #+others

This sentinel is required only when blank lines are suppressed between sentinel lines.
Leo 4.4.2 beta 1 September 29, 2006

Leo 4.4.2 beta 1 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.2: ---------------------------- - You can now store settings in myLeoSettings.leo without fear of those settings being changed by cvs updates or in future versions of Leo. - Leo's vnode and tnode classes are now completely independent of the rest of Leo. Some api's have been changed. This 'big reorg' and may affect scripts and plugins. - Leo's vnode and tnode classes can optionally be compatible with ZODB databases, i.e., they can optionally derive from ZODB.Persistence.Persistent. See Chapter 17: Using ZODB with Leo for details. - The leoOPML plugin defines commands to read and write OPML files. - The slideshow plugin allows Leo to run slideshows defined by @slideshow and @slide nodes. - The leo_to_rtf and leo_to_html plugins create rtf and html files from Leo outlines. - Much faster navigation through the outline using Alt-arrow keys. - When focus is in the outline pane, you can move to headlines by typing the first letter of headlines. - The find command now closes nodes not needed to show the node containing the present match. - Numerous changes that make Leo easier to use without using a mouse. - Many new minibuffer commands now appear in the Cmds menu.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|prev| |leo| |next|

########################################## What's New in Leo 4.4.2 ##########################################

This page summarizes the changes made in Leo 4.4.2 For full details see the release notes section in LeoDocs.leo.

.. contents::
.. Links used in this document.

.. _Emacs: http://www.xemacs.org/ .. _pymacs: http://pymacs.progiciels-bpi.ca/index.html

.. _`Chapter 18: Leo and Emacs`: emacs.html

.. WARNING: image targets may not have upper case letters!

.. |prev| image:: arrow_lt.gif :target: new-4-4-3.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: new-4-4-1.html
- Added support for controlling Leo from Emacs_ with pymacs_. See `Chapter 18: Leo and Emacs`_ for full details. - Added Minibuffer and Settings submenus of the Cmds menu. - At long last Leo creates a proper help menu on the Mac. - Added a new convention for menu tables. If the first item (a string representing the menu label) starts with '*' Leo will convert hyphens to spaces and upcase the label. This convention allows a single string to represent both the menu label and its associated minibuffer command. As part of this reorganization, all menu tables in Leo's core now use only strings. This is an essential precondition to supporting @menu nodes in leoSettings.leo. - Leo's Help menu now contains the Open scripts.leo command. - Leo uses ctypes to import Aspell when run from Python 2.5 or later. Leo no longer needs Python-specific versions of aspell.dll. - Added support for x-windows middle-button paste. This only works when the paste is made in the pane containing the selected text. - Leo looks for myLeoSettings.leo files in the same place Leo looks for leoSettings.leo files. - Created three scripts (in test.leo) that help create unit tests for Leo's edit commands. Create Created runEditCommandTest for use by these scripts. - Improved print-bindings command. The bindings are sorted by prefix: this is a big help in understanding bindings. For each prefix, first print items with only a single character after the prefix. - Made writing .leo files faster. The new code almost exactly twice as fast as the old. - Added p.archivedPosition. This is a key first step towards Leap 204. - Integrated sax with read logic. - You can now store settings in myLeoSettings.leo without fear of those settings being changed by cvs updates or in future versions of Leo. - Eliminated unnecessary redraws when moving the cursor in the outline pane. - Much faster navigation through the outline using Alt-arrow keys. - When focus is in the outline pane, you can move to headlines by typing the first letter of headlines. - The find command now closes nodes not needed to show the node containing the present match. - Numerous changes that make Leo easier to use without using a mouse. - Many new minibuffer commands now appear in the Cmds menu.

Further improved outline navigation:

- Generalized navigation in outline pane to ignore @file, @thin, etc prefixes. - Made outline navigation cumulative. When keystrokes in the outline pane are typed 'close' together Leo first tries to look for prefix + ch, where ch is the character just typed and prefix is the previous match. The term 'close together' is specified by the setting @float outline_nav_extend_delay. The outline search revers to a single-character if the extended search fails, so in fact the delay is not too significant. In practice everything works well without me thinking at all about what is happening.
- Improved the mod_scripting plugin. Every button created by the plugin creates a corresponding command. The command name is the 'cleaned' version of the button name. Likewise, the plugin also creates a delete-x-button command, where x is the command name as just discussed. So now you can delete script buttons without right-clicking. - Made 'About Plugin' dialog scrollable. - Fixed bugs in groupoperations, multifile, nodenavigator and shortcut_button plugins. - The rst3 plugin now registers the rst3-process-tree command. - The leoOPML.py plugin defines commands to read and write OPML files. - The slideshow.py plugin allows Leo to run slideshows defined by @slideshow and @slide nodes. - The leo_to_rtf and leo_to_html plugins create rtf and html files from Leo outlines. - The paste_as_headlines.py plugins creates multiple headlines at once. - The word_count.py plugin.

Improved the mod_scripting plugin:

- Made showing the Run Script button optional. - The Script Button button now creates the press-script-button-button command. - A new utility method does a much better job of massaging button and command names.
-----------------------

|prev| |leo| |next|
What I did:

- Removed c argument from t, v and p ctors. - Removed c argument from most position methods. - In particular, p.link, p.unlink, v.link and v.unlink no longer update c.currentPosition() - Moved all position methods that still had a c argument to the Commands class. - Removed p.allNodes_iter. - Added c.findRootPosition and c.findRootVnode. - c.rootPosition now returns c.findRootPosition(c.currentPosition())

As a result:

- The tnode, vnode and position classes are *completely* independent of Leo. In particular, no tnode, vnode or position method gets a c argument. - The p.link, p.unlink, v.link and v.unlink are significantly simpler. - The machinery for keeping the root position up-to-date is simple and confined to one place in the Commands class.
It now prints the binding for the command.
Rewrote moveWordHelper. It now avoids Tk and regexes. *Much* simpler.
@nocolor

My present thinking is that scripts should be able to store/retrieve persistent objects to/from the zodb. That is, the zodb plugin is likely to be retired.

Leo's vnode and tnode classes now derive from ZODB.Persistence.Persistent if leoNodes.use_zodb is True. It remains to be seen whether having use_zodb = True will cause any serious problems.

See the posting below (Scripting using zodb) for latest details.

See the node 'zodb get/put buttons' in test.leo for examples of how scripts can access zodb easily.

Created g.init_zodb and v.detach.
> Do you see zodb as persisting Leo files or Leo nodes?

Interesting question. I now see the zodb plugin as a proof-of-concept for *user-defined* scripts. The zodb plugin is probably going to go away.

Let us suppose that db is a ZODB.DB instance. (To see how to create such an instance, see the init_zodb method in the zodb plugin. Perhaps I'll defines something like g.openZodb to make this easier.) Then the statements:

connection = db.open() root = connection.root() root[aKey] = v get_transaction().commit() connection.close()

will write all of v's data (all vnodes and tnodes) to the zodb. This is true whatever v is: it can be the root of an entire outline, or any suboutline. If you want to write a single node, you would have to 'detach' that node from the outline. You can do this by copying the node and then unlinking the node from its descendants. Perhaps I could add a convenience method to the vnode class to make this easier.

>Do you see zodb work as providing enhanced access to nodes across multiple files?

Scripts could do so easily. Happily, the distinction between 'long-lived' and 'short-lived' connections is not important for scripts: a script should hold a connection open only for as long as needed. So it would be easy to write any number of vnode trees to the zodb. Later, another script could access any of the data in the zodb by zodb key. Like this:

connection = db.open() root = connection.root() v = root.get(aKey) p = leoNodes.position(v,[])

After running this script, p is a position representing the root of the tree of 'imported' vnodes. The script above does not 'connect' the imported trees to an outline, nor should it do so. As I write this, I realize that the position ctor should make the second argument optional, so that leoNodes.position(v) would be equivalent to leoNodes.position(v,[]).

Each script should open at most connection at a time and be sure to close any zodb connection it creates. The proper way to do this is in a finally statement, like this:

try: ....connection = db.open() ....root = connection.root() ....v = root.get(aKey) ....p = leoNodes.position(v,[]) ....<< do something with the nodes in p's tree>> finally: ....get_transaction().commit() ....connection.close()

In short, the recent changes to Leo's vnode and tnode classes give scripts the ability to save/retrieve Leo data to/from the zodb in any way a script wants, without any further support from Leo, or from me.

I shall spend an hour or two more with the zodb plugin, but it looks to me that the plugin has served its purpose. Rather than trying to guess how people will want to use the zodb, it will be simpler and more general to have people write scripts that do exactly what they want. In particular, such scripts can easily sidestep the problems with multiple open connections.

Edward

P.S. Please note that the scripts shown above could not have been written without all the recent work with the zodb plugin and the big code reorg.

P.P.S. A couple of unit tests involving the new v/t.__hash__ methods just failed, so it may be just a little bit longer before the code on cvs is truly zodb ready. I'll also be working on example scripts and the convenience methods described above.

EKR
- Removed all modes except Alt-C mode. - Use Shift-arrows for outline moves when focus is in outline pane. - Put help / apropos commands in help menu. - Put focus commands in Cmds menu. - When focus is in outline, normal character navigates like Windows explorer. - Put Scrolling commands in Cmds menu. - Screened out(some) unwanted characters from affecting outline navigation.More work is needed. - Esc character is never inserted into text. - Replaced @button clones-tab with @command clones-tab. - Scripting plugins now sets verbose=True so @commands get shown. * Alt keys (outline move commands) should set focus to outline even if nothing else happens. - Closing a window no longer puts focus in limbo: added force argument to c.set_focus. - New gui bindings: (I should actually be able to remember these). cycle-all-focus = Alt-Y contract-pane = Alt+Ctrl+- expand-pane = Alt+Ctrl-= focus-to-tree = Alt-space scroll-outline-down-page = Alt-PageDn scroll-outline-down-page ! tree = PageDn scroll-outline-up-page = Alt-PageUp scroll-outline-up-page ! tree = PageUp scroll-outline-left = Alt+Ctrl+LtArrow scroll-outline-right = Alt+Ctrl+RtArrow - Put find-character and back-find-character in Edit:Find menu. - Use Alt-S,Alt-R for incremental searches. - Created find-character-extend-selection and back-find-character-extend-selection. - Added binding (Ctrl-W) and entry in Cmds menu for select-word-at-cursor. - Added binding (Ctrl-P) for repeat-complex-command. - Added binding (Ctrl-B) for execute-script. * Fixed bug in extend mode. - Added binding (Ctrl-space) for toggle extend mode. - Removed most cursor move bindings involving ctrl keys. Exception: ctrl-a and ctrl-e. ** The idea is that I'll use extend mode instead. - Stay in outline mode: added @bool stayInTreeAfterEditHeadline setting. - Added Cmds:Toggle Settings submenu. - Use emacs names in Cmds menu (and in some other places): allow single item in menu tables.
http://sourceforge.net/forum/message.php?msg_id=3935368
http://sourceforge.net/forum/message.php?msg_id=3935780

This greatly speeds searches that used to open many nodes.
http://sourceforge.net/forum/message.php?msg_id=3935981

@url nodes of the form::

@url -- aComment

now get the actual url from the entire first line of body text. Such url's need not be quoted if they contain spaces.

The myLeoSettings.leo file is a way of ensuring that your customized settings are not altered when updating Leo from cvs or while installing a new version of Leo. The myLeoSettings.leo acts much like Python's site-customize.py file. The myLeoSettings.leo file will never be part of any Leo distribution, and it will never exist in Leo's cvs repository. This solution is *much* better than trying to update leoSettings.leo with scripts.

Leo loads settings from myLeoSettings.leo *after* loading settings from leoSettings.leo files but *before* loading settings from the .leo file being opened.
The following plugins are new in Leo 4.4.2 b2:

leo_to_rtf leo_to_html leoOPML (At present, contained in leoOPML.leo instead of leoPlugins.leo) paste_as_headlines slideshow word_count

The __saxRead__.py plugin is an **experimental** for use by EKR. It will be folded into Leo's core in the near future.
This plugin takes an outline stored in LEO and outputs it as a numbered list to an RTF file. The RTF file can be loaded into Microsoft Word and formatted as a proper outline.

If this plug-in loads properly, you should have an "Outline to Microsoft RTF" option added to your File > Export... menu in Leo.

Settings such as outputting just the headlines (vs. headlines & body text) and whether to include or ignore the contents of @file nodes are stored in the rtf_export.ini file in your Leo\plugins folder.

The default export path is also stored in the INI file. By default, it's set to c:\ so you may need to modify it depending on your system.
This plugin takes an outline stored in LEO and converts it to html which is then either saved in a file or shown in a browser.

The outline can be represented as a bullet list, a numbered list or using html <h?> type headings. Optionally, the body text may be included in the output.

If desired, only the current node will be included in the output rather than the entire outline.

An xhtml header may be included in the output, in which case the generated html will be valid XHTML 1.0 Strict.

The plugin is fully scriptable as all its functionality is available through a Leo_to_HTML object which can be imported and used in scripts.

Several commands and menu items are provided to give easy access to the plugins various features and options may be set via leo_to_html.ini file and the plugins properties dialog.
This plugin reads and writes Leo outlines in .opml (http://en.wikipedia.org/wiki/OPML) format.

The OPML plugin creates two new commands that read and write Leo outlines in OPML format. The read-opml-file command creates a Leo outline from an .opml file. The write-opml-file command writes the present Leo outline to an .opml file.

Various settings control what gets written to .opml files, and in what format. As usual, you specify settings for the OPML plugin using leoSettings.leo. The settings for the OPML are found in the node: @settings-->Plugins-->opml plugin

Here are the settings that control the format of .opml files. The default values are shown.

- @string opml_namespace = leo:com:leo-opml-version-1

The namespace urn for the xmlns attribute of <opml> elements. This value typically is not used, but it should refer to Leo in some way.

- @bool opml_use_outline_elements = True

If True, Leo writes body text to <:body> elements nested in <outline> elements. Otherwise, Leo writes body text to :body attributes of <outline> elements.

- @string opml_version = 2.0

The opml version string written to the <OPML> element. Use 2.0 unless there is a specific reason to use 1.0.

- @bool opml_write_body_text = True

Leo writes body text to the OPML file only if this is True.

- @bool opml_write_leo_details = True

If True, Leo writes the native attributes of Leo's <v> elements as attributes of the opml <outline> elements. The native attributes of <v> elements are a, descendentTnodeUnknownAttributes, expanded, marks, t, and tnodeList.

- @bool opml_write_leo_globals_attributes = True

If True, Leo writes body_outline_ratio` and global_window_position attributes to the <head> element of the .opml file.
This plug-in takes any text is stored in the clipboard and creates new headlines for each line of text. The paste routine checks to make sure the line of text is not greater than 50 characters in length. If it is, the routine truncates the headline to 50 characters and pastes the entire line into the body text of that node.

If the plug-in is functioning properly, a "Paste as Headlines" option should appear in the Edit menu directly under the existing Paste option.
This plugin displays a message box with information about the body text of the current node such as number of: characters, words, lines, and paragraphs. It adds a "Word Count..." option to the bottom of the Edit menu that will activate the message box.

The Word Count... menu has a shortcut key of 'W'.
This plugin supports slideshows in Leo outlines.

It defines four new commands:

- next-slide-show: move to the start of the next slide show, or the first slide show if no slide show has been seen yet.

- prev-slide-show: move to the start of the previous slide show, or the first slide show if no slide show has been seen yet.

- next-slide: move to the next slide of a present slide show.

- prev-slide: move to the previous slide of the present slide show.

Slides shows consist of a root @slideshow node with descendant @slide nodes. @slide nodes may be organized via non-@slide nodes that do not appear in the slideshow.

All these commands ignore @ignore trees.
Leo has many commands that select nodes in the outline. These commands can be found in the Outline:Go To menu.

When focus is in the outline Pane, you can move to from node to node by typing the first letter of a headline. For example, typing 'a' will go to the next visible headline that starts with either 'a' or 'A', wrapping around to the start of the outline if needed. Typing an uppercase 'A' will go to the next headline that starts with 'a' or 'A', making the node visible (expanding its ancestors) if the node was not visible.

When keystrokes (in the outline pane) are typed 'close' together in time Leo first looks for prefix + ch, where ch is the character just typed and prefix is the previous match. The term 'close together' is defined by the setting:

@float outline_nav_extend_delay = 2.0

The outline nav search reverts to a single-character search if the extended search fails, so in fact the delay is not too significant. In practice everything works well without thinking about what is happening.
Leo's vnode and tnode classes are now completely independent of the rest of Leo. Some api's have been changed. This 'big reorg' and may affect scripts and plugins.
Leo's vnode and tnode classes can optionally be compatible with ZODB databases, i.e., they can optionally derive from ZODB.Persistence.Persistent. See Chapter 17: Using ZODB with Leo for details.
Plugins and scripts can create new tabs in the log panel. The following creates a tab named test or make it visible if it already exists::

c.frame.log.selectTab('Test')

g.es, g.enl, g.ecnl, g.ecnls write to the log tab specified by the optional tabName argument. The default for tabName is 'Log'. The put and putnl methods of the tkinterLog class also take an optional tabName argument which defaults to 'Log'.

Plugins and scripts may call the c.frame.canvas.createCanvas method to create a log tab containing a Tk.Canvas widget. Here is an example script::

log = c.frame.log ; tag = 'my-canvas' w = log.canvasDict.get(tag) if not w: w = log.createCanvas(tag) w.configure(bg='yellow') log.selectTab(tag)
The c.frame.log class contains the following 'official' ivars::

g.es('tabName',c.frame.log.tabName) # The name of the active tab. g.es('tabFrame',c.frame.log.tabFrame) # The Tk.Frame containing all the other widgets of the tab. g.es('logCtrl',c.frame.log.logCtrl) # Tk.Text widget containing the log text.

The following ivars provide access to the body pane::

g.es('bodyFrame',c.frame.body.frame) # The Tk.Frame widget containing the c.frame.body.bodyCtrl

The following ivars provide access to the outline pane::

g.es('canvas',c.frame.tree.canvas) # The Tk.Canvas on which Leo's outline is drawn.

Tkinter provides a way of determining the enclosing widget of any widget. The body text is enclosed in a Pmw.PanedWidget to support multiple editors.

w = c.frame.body.bodyCtrl parent = w.pack_info().get('in') g.es('bodyCtrl.parent',parent) # The Tk.Frame containing the body text.
The following line removes the initial text widget::

c.frame.log.logCtrl.pack_forget()

To make the text widget visible again::

c.frame.log.logCtrl.pack(side='top',expand=1,fill='both')

Plugins and scripts can pack any other widgets into c.frame.log.tabFrame. For example, the following replaces the default text widget with a red box::

import Tkinter as Tk

# Remove the old contents. w = c.frame.log.logCtrl parent = w.pack_info().get('in') w.pack_forget()

# Replace with a red frame. f = c.frame.newLog = Tk.Frame(parent,background='red') f.pack(side='left',expand=1,fill='both')

And the following will restore the original pane::

c.frame.newLog.pack_forget() w = c.frame.log.logCtrl w.pack(side='left',expand=1,fill='both')
Warning: you will find it hard to execute scripts after removing the body pane, so you had best make the following two scripts into script buttons before executing them :-)

Plugins and scripts can pack any other widgets into c.frame.log.tabFrame. For example, the following replaces the default text widget with a red box::

import Tkinter as Tk

w = c.frame.body.bodyCtrl parent = w.pack_info().get('in') w.pack_forget()

f = c.frame.newBody = Tk.Frame(parent,background='red') f.pack(side='left',expand=1,fill='both')

To restore::

c.frame.newBody.pack_forget() w = c.frame.body.bodyCtrl w.pack(side='left',expand=1,fill='both')
The following replaces the outline pane with a red frame::

import Tkinter as Tk

w = c.frame.tree.canvas parent = w.pack_info().get('in') w.pack_forget()

f = c.frame.newTree = Tk.Frame(parent,background='red') f.pack(side='left',expand=1,fill='both')

And this script restores the outline::

c.frame.newTree.pack_forget() c.frame.tree.canvas.pack(side='left',expand=1,fill='both')
The following is no substitute for a full discussion of programming the Tk.Text widget: it can do lots.

To clear the log::

w = c.frame.log.logCtrl w.delete('1.0','end')

To write a line to the end of the log::

w = c.frame.log.logCtrl w.insert('end','This is a test\n')

To get the entire contents of the log::

w = c.frame.log.logCtrl g.es(w.get('1.0','end')+'\n')
http://sourceforge.net/forum/message.php?msg_id=3932641

LEO *always* outputs the first line of a node without indentation even if it is indented in the node.
This was a very weird one. It's not clear why it wasn't biting before.

Traceback (most recent call last): File "c:\prog\tigris-cvs\leo\src\leo.py", line 321, in <module> run(fileName) File "c:\prog\tigris-cvs\leo\src\leo.py", line 151, in run g.app.gui.runMainLoop() File "c:\prog\tigris-cvs\leo\src\leoTkinterGui.py", line 182, in runMainLoop self.root.mainloop() File "c:\python25\lib\lib-tk\Tkinter.py", line 1023, in mainloop self.tk.mainloop(n) File "C:\prog\tigris-cvs\leo\extensions\Pmw\Pmw_1_2\lib\PmwBase.py", line 1756, in __call__ _reporterror(self.func, args) File "C:\prog\tigris-cvs\leo\extensions\Pmw\Pmw_1_2\lib\PmwBase.py", line 1782, in _reporterror msg = exc_type + ' Exception in Tk callback\n' TypeError: unsupported operand type(s) for +: 'type' and 'str'
- created g.isWordChar. It does proper test for letters and numbers. - Used g.isWordChar in extendToWord and moveWordHelper. - OnBodyDoubleClick now just calls c.editCommands.extendToWord.

So Russian characters, e.g., no longer 'interrupt' words.

Another fix: extend-to-word now works properly at the very end of a word.
Installer does not complain about missing Python and does not install anything either. Here is a fix to this behavior. In most user-friendly way it would be better to provide a clickable link to Python site and a way to specify the path manually, but for now it is just that - a fix.
w was set to self.w, rather than event.widget.
Added self.editWidget. This sets self.w and makes sure w is a text widget.
This fixes a long-standing, annoying bug.
The solution was to call setTimestamp if needed in getNewIndex.

- Make showing the Run Script button optional. - The Script Button button now creates the press-script-button-button command. - A new utility method does a much better job of massaging button and command names.
New in beta 2: Leo looks for myLeoSettings.leo files in the same place Leo looks for leoSettings.leo files.
http://sourceforge.net/forum/message.php?msg_id=3935780

This greatly speeds searches that used to open many nodes.

Added support for @bool collapse_nodes_during_finds setting.
The code that writes .leo files is now almost exactly twice as fast as the old code.
http://sourceforge.net/forum/message.php?msg_id=3941670

The code on cvs now supports the 'extended' character search. When keystrokes (in the outline pane) are typed 'close' together in time Leo first tries to look for prefix + ch, where ch is the character just typed and prefix is the previous match.

By 'close together' I mean the time interval specified by the new setting:

@float outline_nav_extend_delay = 2.0

The unit of time is seconds.

The outline nav search revers to a single-character if the extended search fails, so in fact the delay is not too significant. In practice everything works well without me thinking at all about what is happening.
The bindings are sorted by prefix: this is a big help in understanding bindings. For each prefix, first print items with only a single character after the prefix.
Possibly define kill-sentence and kill-paragraph in terms of these.
Leo 4.4.2 beta 2 October 9, 2006

Leo 4.4.2 beta 2 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.2: ---------------------------- - You can now store settings in myLeoSettings.leo without fear of those settings being changed by cvs updates or in future versions of Leo. - Leo's vnode and tnode classes are now completely independent of the rest of Leo. Some api's have been changed. This 'big reorg' and may affect scripts and plugins. - Leo's vnode and tnode classes can optionally be compatible with ZODB databases, i.e., they can optionally derive from ZODB.Persistence.Persistent. See Chapter 17: Using ZODB with Leo for details. - The leoOPML plugin defines commands to read and write OPML files. - The slideshow plugin allows Leo to run slideshows defined by @slideshow and @slide nodes. - The leo_to_rtf and leo_to_html plugins create rtf and html files from Leo outlines. - Much faster navigation through the outline. - When focus is in the outline pane, you can move to headlines by typing the first letter of headlines. - The find command now optionally closes nodes not needed to show the node containing the present match. - Numerous changes that make Leo easier to use without using a mouse, including new commands and options. - Many new minibuffer commands now appear in the Cmds menu. - A sax parser can now optionally read .leo files. - Fixed numerous bugs.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
See: http://sourceforge.net/forum/forum.php?thread_id=1587064&forum_id=10226

Leo's theory of relativity

1. We can archive any position p by saving the list [p.childIndex() for p in p.self_and_parents_iter()]. Let us call the *reverse* of this list the **parents index list**. Clearly, this list provides an unambiguous way of reaching position p from the root node. Archived positions, like all other positions, become invalid when the outline changes.

2. Leo's position class can be based on parents index lists. Let us call such positions **new positions**. Replacing legacy positions with new position will have important benefits:

- The only structure information in vnodes will be a v.links field. Two interpretations of v.links are possible. When Leo's data is a DAG (the clone world), v.links is a lists of v's children. This is the legacy world we all know and love. When Leo's data is an arbitrary graph, v.links is simply the list of all vnodes to which v points, with *no* necessary restrictions on what nodes may be contained in v.links.

- New positions provide a self contained way of traversing an arbitrary graphs **largely independently** of the data. This is Leo's theory of relativity. The notions of 'parent' and 'sibling' have meaning *only* in the context of a particular position. The v.links field appears to be the absolute minimum amount of structure information that vnodes must contain. v.links defines the children or linked-to nodes in a general graph.

- Leo's data can be considered an unrooted tree: *any* node could be considered the root. New positions provide enough information to traverse an arbitrary graph starting at any node.

- The fundamental p.moveToX methods should be significantly faster. All of Leo's iterators use p.moveToX methods.

3. The changeover to new positions can be done easily. Initially, the api of the new position class will be identical to the api of the present position class. Later, the api for the new position class might be extended in an upward compatible manner. The api's for the vnode and tnode class will remain strictly unchanged.

4. These changes imply no change to the separation of data into vnodes and tnodes. This separation is required to handle clones. Furthermore, the format of .leo files is a separate issue from the internal representation of Leo's data, as proved by the opml plugin. Thus, the transition to new positions will have *no* effect on file formats, and no effect of scripts. All scripts will continue to work *exactly* as they have before, *except* scripts, e.g. unit tests, that probe Leo's internals.

Summary

Leo's theory of relativity is this: the position class provides a 'frame of reference' for traversing data. **Only in a particular frame of reference** do the notions of 'parent' and 'siblings' have meaning. Leo's theory of relatively is the ultimate expression of LeoUser's notion of a 'sea of nodes'. It provides a solid context on which to base traversals of either outlines with clones (DAG's) or general directed graphs.

Leo's position class, far from being just a technical tool, is important theoretically. The position class (old or new) provides the essential tool needed to separate data from traversals of the data. The re-visioning of the position and vnode classes brings that potential into reality.
- Removed .leoRecentFiles.txt from the distribution and cvs and added @bool write_recent_files_as_needed. The presence or absence of .leoRecentFiles.txt no longer controls whether Leo creates and updates .leoRecentFiles.txt. - Added @bool insert_new_nodes_at_end. - Added @bool select_all_text_when_editing_headlines. Creating a new node always selects the entire text, regardless of this option. - Leo looks for myLeoSettings.leo files in the same place Leo looks for leoSettings.leo files. - Added settings for all mod_scripting switches. - Added @bool collapse_nodes_during_finds. This greatly speeds searches that used to open many nodes. See: http://sourceforge.net/forum/message.php?msg_id=3935780 - Added @bool outline_pane_has_initial_focus. - Added @bool sparse_move_outline_left. - Added bindings for Alt-Shift-Arrow keys to force an outline move. - Added @bool use_sax_based_read = False. True: Use a sax-based parser to read .leo files. This is slower than using Leo's legacy xml parser, but may solve some unicode problems.

Changed default settings::

focus-to-body = Alt-D focus-to-tree = Alt-T toggle-extend-mode = Alt-3
::

extend-to-line extend-to-paragraph extend-to-sentence forward-end-word forward-end-word-extend-selection
True: Use a sax-based parser to read .leo files. This is slower than using Leo's legacy xml parser, but may solve some unicode problems.

False: Use Leo's legacy xml parser code.
@command whatever @key Alt-1 didn't work Actually, no Alt-n keys worked for n in (1,2,3,4,5) in any context.
http://sourceforge.net/forum/message.php?msg_id=3956836
http://sourceforge.net/forum/message.php?msg_id=3958333
The warning was disabled due to a programming error (not not) Enabling this found two errors: view-lossage (missing comma) and find-with-present-options --> search-with-present-options.
https://sourceforge.net/forum/message.php?msg_id=3957980

This was a major effort. What I did:

- Defined g.isWordChar in terms of ch.isalnum()

- Replace almost all instances of string.letters and string.digits by calls to ch.isalnum(), ch.isalpha(), ch.isdigit(), etc.

- Similarly, replaced word_chars.

- The new code uses string literals only for

a) small constants like '+-' and b) constants in a very limited context, as in the input to regexp.
http://sourceforge.net/forum/message.php?msg_id=3960993
https://sourceforge.net/forum/message.php?msg_id=3961623
No longer needed now that the datenodes plugins gets settings from cvs.
Did not restore selection after indent/undent commands.
The 'hang' was due to removeRKeys, which removes the bindings create by setRegion (set-mark-command) by *also* cleared all the other bindings! For now I have simply disabled the set-mark-command and commented out all calls to removeRKeys.

Note that toggle-extend-mode (Alt-3) is a good way to define regions.
onFocusIn and its associated binding were a very bad idea. It is not needed: k.masterClickHandler simply calls the new onClick method.

What I did:

- Eliminating onFocusIn and its associated binding. Hurray: this also fixed the Find problem. - Fixed problem with deleting nodes when multiple editors are present. - Fixed minor problem with cycle-all-focus. - Removed title bar when penultimate editor is deleted.
Double-clicking @url <leo-file> did not bring Leo file to top.
What I did

- @bool write_recent_files_as_needed = True

People who don't want Leo to update .leoRecentFiles.txt can set this to False.

- Remove .leoRecentFiles from cvs - Remove .leoRecentFiles from distribution list.
http://sourceforge.net/forum/message.php?msg_id=3588148

One way to make Leo more newbie friendly is to add menu items for key features that are likely to cause confusion in the beginning.
This is much more visible.
Added support for @bool sparse_move_outline_left

When True, Leo collapses the (former) parent of a node when moving that node left. Takes getting used to, but I like it.

Note that the move-outline-up/down commands can have the effect of moving an outline left.
At long last Leo creates a proper help menu on the Mac.
This would greatly simplify menu entries.
This is an important step towards making all menus configurable.
The open-scripts-leo command.
http://sourceforge.net/forum/message.php?msg_id=3958380
http://sourceforge.net/forum/message.php?msg_id=3423121
http://sourceforge.net/forum/message.php?msg_id=3959003
http://sourceforge.net/forum/message.php?msg_id=3962632
- Every button created by the plugin creates a corresponding command. The command name is the 'cleaned' version of the button name.

- Every button created by the plugin also creates a delete-x-button command, where x is the command name as just discussed. So now you can delete script buttons without right-clicking.

- I took the time to revise, refactor, clean up, reorganize and better document the code. This was overdue: the previous code had grown difficult to understand through multiple small accretions. I can actually understand the new code.
http://sourceforge.net/forum/message.php?msg_id=3963657
As always, you can set max_undo_stack_size in myLeoSettings.leo.
A highly useful option. However, creating a new node always selects the entire text, regardless of this options.
- Added bindings for toggle-autocompleter (Alt-1) and toggle-calltips (Alt-2)

- Ctrl-. and ctrl-( do not seem to do anything.

** Mystery solved: there was a trace in the calltip logic!

Disabled these binding:

auto-complete-force = None # This command needs work before it is useful. Ctrl-period show-calltips-force = None # This command needs work before it is useful. Alt-parenleft

The problem is that autocompletion depends on state: self.leadinWord, prevObjects, etc. Thus, it's not presently possible to start the process anywhere. Similar remarks apply to calltips, which relies on autocompleter state.

This is a complex problem, and not very serious now that there is an easy way of toggling autocompleter and calltips on and off. It's been added to a 'later' section of the to-do list.
Added the node: Candidates for settings in myLeoSettings.leo. This lists the most 'controversial' settings in leoSetting.leo, and is a quick-start to creating myLeoSettings.leo."
- Added shift-ctrl keys to extend the selection. focus-to-body = Alt-D focus-to-tree = Alt-T toggle-extend-mode = Alt-3
Leo 4.4.2 beta 3 October 20, 2006

Leo 4.4.2 beta 3 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

The beta release fixed dozens of bugs and smoothed many rough edges. There are no known major bugs in Leo. This will be the last beta release before LEo 4.4.2 final.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.2: ---------------------------- - You can now store settings in myLeoSettings.leo without fear of those settings being changed by cvs updates or in future versions of Leo. - Leo's vnode and tnode classes are now completely independent of the rest of Leo. Some api's have been changed. This 'big reorg' and may affect scripts and plugins. - Leo's vnode and tnode classes can optionally be compatible with ZODB databases, i.e., they can optionally derive from ZODB.Persistence.Persistent. See Chapter 17: Using ZODB with Leo for details. - The leoOPML plugin defines commands to read and write OPML files. - The slideshow plugin allows Leo to run slideshows defined by @slideshow and @slide nodes. - The leo_to_rtf and leo_to_html plugins create rtf and html files from Leo outlines. - Much faster navigation through the outline. - When focus is in the outline pane, you can move to headlines by typing the first letter of headlines. - The find command now optionally closes nodes not needed to show the node containing the present match. - Numerous changes that make Leo easier to use without using a mouse, including new commands and options. - Many new minibuffer commands now appear in the Cmds menu. - A sax parser can now optionally read .leo files. - Fixed numerous bugs.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html What's new: http://webpages.charter.net/edreamleo/new-4-4-2.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
Set @bool ignore_unbound_non_ascii_keys = False in LeoSettings.leo or myLeoSettings.leo.
This is a known bug in Tk/Tkinter and there is no good workaround. Some keyboards allow you to disable the caps-lock key.
@language rest
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. September 13, 2006

|back| |leo| |next|

####################################### Chapter 18: Leo and Emacs #######################################

This chapter several topics relating to the Emacs editor.

.. contents::
.. Links

.. _elisp: http://en.wikipedia.org/wiki/Emacs_Lisp .. _Emacs: http://www.xemacs.org/ .. _ZODB: http://www.zope.org/Wikis/ZODB/guide/zodb.html .. _`Installing ZODB`: http://www.zope.org/Wikis/ZODB/guide/node3.html#SECTION000310000000000000000 .. _pymacs: http://pymacs.progiciels-bpi.ca/index.html

.. _`Chapter 8: Customizing Leo`: customizing.html

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: zodb.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: leoBridge.html
-----------------------

|back| |leo| |next|
The leoPymacs module is intended to be called from Emacs using pymacs. It contains the following top-level functions:

- get_app()

Returns the hidden app created by the leoPymacs.init function.

- dump(anyPythonObject)

Returns str(repr(anyPythonObject)).

- get_g()

Returns the leoGlobals module of the hidden app created by the leoPymacs.init function.

- get_script_result()

Returns g.app.scriptResult, where g.app is the hidden app.

- init() Calls leo.run(pymacs=True) to create a hidden Leo application. Later calls to open can open hidden Leo outlines that can be accessed via runScript.

- open(fileName)

Opens the .leo file given by fileName. fileName must be the full path to a .leo file. Returns the commander of the open Leo outline, or None if the outline could not be opened.

- run_script(c,script,p=None)

Executes a script in the context of a commander ``c`` returned by the leoPymacs.open. c may be None, in which case a dummy commander is created in which to run the script. In the executed script, p is set to c.currentPosition() if no p argument is specified. Returns g.app.scriptResult, where g.app is the hidden app.
Leo's leoPymacs module is a simple 'server' for the pymacs_ package. Using pymacs and leoPymacs, elisp_ scripts in Emacs_ can open .leo files and execute *Python* scripts as if they were executed inside Leo. In particular, such scripts can use Leo's predefined c, g and p variables. Thus, *Python* scripts running in Emacs can:

- Open any .leo file. - Access any part of the outline. - Change any part of the outline, including derived files, - Save .leo files. - Execute *any* Leo script.

In short, you can now do from Emacs anything that you can do with Leo scripting inside Leo.

Here are step-by-step instructions for executing Python scripts in Emacs:

**Step 1. Install pymacs**

The pymacs installation instructions should be clear enough. A clarification is needed about two-way communication between Python and lisp scripts: in truth, Python scripts can call the Pymacs.lisp function *only* if the Python script was invoked from emacs. Otherwise, calling Pymacs.lisp will hang the process making the call. For example, executing the following script as an ordinary Leo script will hang Leo::

from Pymacs import lisp print lisp("""2+2""") # Hangs

**Step 2. Load the leoPymacs module from Emacs, creating a hidden Leo application**

From inside Emacs, you load Leo's leoPymacs module as follows::

(pymacs-load "leoPymacs" "leo-")

The call to pymacs-load is similar to ``'import leoPymacs as leo-'`` in Python. The side effect of pymacs-load is to define the elisp function leo-x for every top-level function x in leoPymacs.py, namely leo-dump, leo-get-app, leo-get-g, leo-get-script-result, leo-init, leo-open and leo-run-script. The first call to any of these functions creates a **hidden Leo application** in which .leo files may be loaded, modified and saved, and in which Leo scripts may be executed. This hidden Leo application uses Leo's nullGui class as its gui, so Leo commands and Leo scripts that require a fully functional gui will not work as expected in the hidden Leo application. Steps 3 and 4 tell how to use this hidden Leo application.

pymacs-load works like a Python reload, so you can redefine leoPymacs.py while Emacs is running. However, calling pymacs-load destroys the old hidden Leo application and creates a new one, so typically you would want to call pymacs-load only once per Emacs session. Like this::

(setq reload nil) ; change nil to t to force a reload.

(if (or reload (not (boundp 'leoPymacs))) (setq leoPymacs (pymacs-load "leoPymacs" "leo-")) (message "leoPymacs already loaded") )

**Step 3. From Emacs, open .leo files**

Once we have loaded the leoPymacs module we can open a .leo file as follows::

(setq c (leo-open fileName))

This binds the elisp ``c`` variable to the Leo commander created by opening fileName. fileName should be the full path to a .leo file. In the next step we will use this ``c`` variable to execute *Leo* scripts in the context of an open Leo outline.

Sometimes we want to execute a Leo script before opening any Leo commanders. For example, we might want to compute the fileName passed to leo-open. leo-run-script allows the ``c`` argument to be nil, in which case leo-run-script creates a dummy commander in which to run the script. For example, the following script calls ``g.os_path_join`` and ``g.os_path_abspath``::

(setq script "g.app.scriptResult = g.os_path_abspath(g.os_path_join( g.app.loadDir,'..','test','ut.leo'))" )

(setq fileName (leo-run-script nil script))

leo-run-script returns the value of ``g.app.scriptResult`` As shown above, Python scripts may set ``g.app.scriptResult`` to indicate their result. elisp scripts can also get ``g.app.scriptResult`` using leo-script-result. Note that the Python script may span multiple lines.

**Step 4. From Emacs, execute Leo (Python) scripts**

From emacs we can execute a Python script **as if** it were executed in an open Leo outline. Suppose aLeoScript is an **elisp** string containing a Leo (Python) script. We can execute that script in the hidden Leo application as follows::

(leo-run-script c aLeoScript)

For example::

(setq c (leo-open fileName) (csetq script "print 'c',c,'h',c.currentPosition().headString()") (leo-run-script c script)

Putting this all together, we get::

; Step 1: load leoPymacs if it has not already been loaded. (setq reload nil) (if (or reload (not (boundp 'leoPymacs))) (setq leoPymacs (pymacs-load "leoPymacs" "leo-")) (message "leoPymacs already loaded") )

; Step 2: compute the path to leo/test/ut.leo using a Leo script. (setq script "g.app.scriptResult = g.os_path_abspath( g.os_path_join(g.app.loadDir,'..','test','ut.leo'))" ) (setq fileName (leo-run-script nil script))

; Step 3: execute a script in ut.leo. (setq c (leo-open fileName)) (setq script "print 'c',c.shortFileName() ,'current:',c.currentPosition().headString()") (leo-run-script c script)
Leo's mini-buffer is a text area at the bottom of the body pane. You use Leo's minibuffer like the Emacs mini-buffer to invoke commands by their so-called *long name*. The following commands affect the minibuffer:

- **full-command**: (default shortcut: Alt-x) Puts the focus in the minibuffer. Type a full command name, then hit <Return> to execute the command. Tab completion works, but not yet for file names.

- **quick-command-mode**: (default shortcut: Alt-x) Like Emacs Control-C. This mode is defined in leoSettings.leo. It is useful for commonly-used commands.

- **universal-argument**: (default shortcut: Alt-u) Like Emacs Ctrl-u. Adds a repeat count for later command. Ctrl-u 999 a adds 999 a's.

- **keyboard-quit**: (default shortcut: Ctrl-g) Exits any minibuffer mode and puts the focus in the body pane.

For example, to print a list of all commands type Alt-X print-commands <Return>.
Leo 4.4.2.1 final October 29, 2006

Leo 4.4.2.1 final is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo 4.4.2.1 final fixes a recent bug that caused Leo not to create the .leoRecentFiles.txt file properly in some situations. There are no known significant bugs in this version of Leo.

Leo 4.4.2 final fixes a few bugs and adds support for pymacs.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.2: ---------------------------- - You can now store settings in myLeoSettings.leo without fear of those settings being changed by cvs updates or in future versions of Leo. - Leo's vnode and tnode classes are now completely independent of the rest of Leo. Some api's have been changed. This 'big reorg' and may affect scripts and plugins. - Leo's vnode and tnode classes can optionally be compatible with ZODB databases, i.e., they can optionally derive from ZODB.Persistence.Persistent. See Chapter 17: Using ZODB with Leo for details. - The leoOPML plugin defines commands to read and write OPML files. - The slideshow plugin allows Leo to run slideshows defined by @slideshow and @slide nodes. - The leo_to_rtf and leo_to_html plugins create rtf and html files from Leo outlines. - Much faster navigation through the outline. - When focus is in the outline pane, you can move to headlines by typing the first letter of headlines. - The find command now optionally closes nodes not needed to show the node containing the present match. - Numerous changes that make Leo easier to use without using a mouse, including new commands and options. - Many new minibuffer commands now appear in the Cmds menu. - A sax parser can now optionally read .leo files. - Fixed numerous bugs.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html What's new: http://webpages.charter.net/edreamleo/new-4-4-2.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
http://sourceforge.net/forum/message.php?msg_id=3971242
The new colorizer was innocent: the problem is that at.directiveKind4 uses leoColor.leoKeywords, so multipath must add entries to leoColor.leoColors.
It required a space after the '@'
http://sourceforge.net/forum/message.php?msg_id=3975898
For full details, see Chapter 18 of Leo's Users Guide: Emacs and Leo.
http://sourceforge.net/forum/message.php?msg_id=3980193

CC2 allocated objects one-at-a-time (simple allocation), in blocks of fixed-sized objects (block allocation) or in blocks of variable-sized objects (lifetime-based allocation). Simple-allocation was used for short-lived objects and will not be discussed further. Block allocation was used in several ways, the most interesting of which was to allocate "cons cells" used to represent lists. These cons cells could be reused by placing them on a global avail list. Thus, the blocks holding cons cells could (and did) have permanent lifetime: they were never deallocated.

The most interesting aspect of CC2's storage allocation scheme was what I eventually came to call **lifetime-based** storage allocation. This was, for me, an new discovery, though clearly I was not the first to discover it. The Aha is that a lifetime is defined by the time (or equivalently by the place in program code) at which objects are **deallocated**. A lifetime may hold many different kinds of objects that were allocated at many different times. The essence of lifetime-based allocation is that **the proper time to specify when an object will be deallocated is when the object is created**.

Lifetime-based allocation is a superb invention:

- It becomes an effective design tool. Thinking of objects in terms of their lifetimes often shows the essence of a design problem.

- It can be used for any kind of object, regardless of its size or type.

- It reduces the number of calls to calloc and free by one or two orders of magnitude over naive schemes. Furthermore, it typically requests standard-sized blocks (say 8K or more) from calloc, further easing the burden on calloc and free.

- CC2 could allocate objects with a particular lifetime using small, extremely fast, macros. The macros expanded to C code something like this::

if lifetime -> avail >= sizeof(theObjectKind) { // Allocate the storage. theObject = lifetime -> ptr lifetime -> ptr += sizeof(theObjectKind) } else { << allocate theObject in another block >> }

Importantly, the speed of the else clause makes absolutely no difference because it is so seldom executed. Thus, it uses a function call. Clearly then, this code is optimal: it could not be improved even if coded in assembly language.

This white paper describes the storage allocation used in a commercial optimizing C compiler written for Tuple, Inc. ca. 1993. The last section discusses tantalizing possibilities for the pypy project. These possibilities are why I wrote this paper.

Storage allocation is crucial to any compiler because of the number, size and complexity of data which must be allocated. You might event say that a compiler consists of storage allocation and everything else. I paid a lot of attention to storage allocation in CC2, and that work paid off. The resulting compiler was a few percent faster than the CodeWarrior C compiler, perhaps the fastest C compiler in existence at that time. The original notes were written around 1993, so I would do some things differently today. However, the design discussed below still seems relevant today. Indeed, attention to low-level details can make a huge difference.
What makes lifetime-based allocation so powerful is that so few lifetimes are typically required. Indeed, CC2 had only the following lifetimes:

- Permanent: These objects were never deallocated. Examples were list pointers held in cons cells and other kinds of application-wide objects.

- Tokenizer: Tokenizing in C is complex due to C's various preprocessing directives and macro expansion. Objects with tokenizer lifetime are deallocated before the parser starts.

- Function: Objects with function lifetime are deallocated after the compiler generates code for the function.

- File: Objects with file lifetime are deallocated after the compiler completes a source file.

That's all. Similarly, if Leo were recast as a C program only the following lifetimes would be needed:

- Permanent: application-wide objects.

- Window/outline: All data associated with a single Leo outline. This is a 'semi-permanent' lifetime. Leo has unlimited undo, so it is essentially impossible to delete any data object (an object that could be written to an output file) until the entire outline closes.

- Dialog: data associated with a temporary dialog.

- Function/method: data not used outside a single function or method.

The remarkable thing about dynamic languages like Python is how often objects can, in fact, be assigned static lifetimes.
Lifetime allocation isn't used in Java, Python, etc. because these languages have no way of knowing (in general) what the lifetime of any object will be. Furthermore, translating Python to C would be straightforward were it not for storage allocation issues. For example, most of Leo's code could easily be translated into C, **provided** that the lifetime of all objects were known. Again, just for example, the prospect of translating the Python version of Leo to a fully optimized C version is tantalizing.

This is where pypy comes in: its extensive flow analysis may be sufficient to discover lifetimes for a significant percentage of objects. Perhaps user hints may be effective. For example, pypy offers the chance to make something like `region inference`_ truly useful. Note that the pypy project might benefit from deducing lifetimes even if not all objects could be assigned a static lifetime. Another reason why lifetimes are not a standard technique is that they are a potentially dangerous optimization. Errors in specifying lifetimes will result in dangling pointer references. But this danger might disappear if pypy could deduce lifetimes automatically.
The following three section discuss three ways of debugging scripts with winpdb_. The first two sections tell how to debug general scripts; the last section tells how to debug Leo-specific scripts.

winpdb_ and its documentation have been improved recently. For more details, see the `embedded winpdb`_ docs. The discussion of embedded debugging may have been written specifically with Leo in mind.
This way of debugging can only be used for general scripts, not leo-specific scripts. The debug command writes the script to scriptFile.py and invokes winpdb. winpdb opens and is already 'attached' to the script to be debugged. You can single-step as you like. Leo continues to run, but killing the debugger will also kill Leo.
``test.leo`` contains an ``@button windpdb`` node. Select the test to be debugged, then press the winpdb button or do ``<Alt>x winpdb<return>``. This way is essentially the same as using the debug command, though the code is slightly different.
This way of debugging scripts allows winpdb to debug scripts that use c, g and p. A bit more work is needed because winpdb does not start automatically. Here are step-by step instructions:

1. Insert the following two lines of code at the start of the script to be debugged::

import rpdb2 rpdb2.start_embedded_debugger('go',fAllowUnencrypted=True)

2. Execute Leo's execute-script command (*not* the debug command). Leo will appear to hang: start_embedded_debugger is waiting for *another* copy of winpdb to 'attach' to the script's process. The default timeout is 5 minutes, after which an exception gets thrown.

3. Start winpdb explicitly by executing something like the following in a console::

python /python25/Scripts/_winpdb.py -t

The -t option tells winpdb that no encoding of password is necessary. The password is specified in the call to rpdb2.start_embedded_debugger in your script. In our example, the password is 'go'.

4. Use winpdb's ``File:Attach`` command to attach winpdb to Leo. Specify the password as 'go' and you will see the scriptFile.py containing your entire script. You can now execute or single-step through the script. To repeat, c, g and p are defined, so you can debug any script this way.
Inserting g.trace statements in my Python code is usually my first debugging choice. The g.trace statement prints the name of the function in which the call to g.trace occurs, followed by the value of its arguments. The output of the g.trace goes to the console, so you must be `running Leo in a console`_ to use g.trace.

Inserting and deleting g.trace statements is fast, provided that your `work flow`_ makes it easy to restart the program under test. As a result, using g.trace statements is similar to setting tracepoints in a debugger, with the advantage that (disabled) tracepoints remain in the source code for future use. You will find many examples of using g.trace throughout Leo's source code.

My second choice is using g.pdb to set breakpoints for the pdb_ debugger. Pdb uses the console for all interaction, so you must be `running Leo in a console`_. See `the FAQ`_ for a discussion of both g.trace and g.pdb.
**Joined nodes** represent the same data. Joined nodes are vnodes v1 and v2 such that v1.t == v2.t. Joined vnodes are distinct (v1 != v2) if the vnodes are clones of each other. Joined nodes are in fact the same node (v1 == v2) if they are descendants of clone nodes. In particular, we can say that p1.v is joined to p2.v if p1.v.t == p2.v.t regardless of whether p1.v == p2.v. Thus a script can process nodes exactly once if it ignores nodes joined to previously visited nodes. A later section will provide an example of this common scripting pattern.

The following script illustrates a common idiom. It prints each headline of an outline, eliminating duplications that would happen as the result of cloned trees::

d = {} for p in c.allNodes_iter(): if p.v.t not in d: print p.headString() d[p.v.t] = p.v.t

As mentioned in the introduction, joined nodes share the same tnode. Thus, when we visit a position p we print p.headString() only if p.v.t is not already in the dictionary. We then enter p.v.t in the dictionary to prevent printing the headlines of any future node joined to p.v.
Leo's ``Execute Script`` command predefines ``c`` to be the commander of the outline containing the script. ``g`` and ``p`` are predefined as follows::

import leoGlobals as g p = c.currentPosition()

These definitions provide an easy way to access or change any information in a Leo outline. For example, as discussed below, the following script will print every headline in the Leo outline in which the script occurs.

for z in c.allNodes_iter(): print z.headString()
Leo 4.4.3 alpha 1 January 26, 2006

Leo 4.4.3 alpha 1 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

Important: the wxGui plugin is still alpha-quality code at present.

The highlights of Leo 4.4.3: ---------------------------- - A functional wxWidgets plugin. - Removed all gui-dependent code from Leo's core. - Better support for the winpdb debugger. - Many minor improvements, new settings and bug fixes.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
Example:

print "\\" + " this is a test"

The escape mechanism must treat an even number of trailing escapes as not an escape.
http://sourceforge.net/forum/message.php?msg_id=3924236

Added unit tests for yank and all kill commands.
http://sourceforge.net/forum/message.php?msg_id=3991369

The bindings to f.f.OnControlKeyDown/Up were mistakenly deleted in createOuterFrames.
http://sourceforge.net/forum/message.php?msg_id=4112347
# Simplified version by EKR: stringCompare not used.

def CheckVersion (s1,s2,condition=">=",stringCompare=None,delimiter='.',trace=False):

vals1 = [g.CheckVersionToInt(s) for s in s1.split(delimiter)] ; n1 = len(vals1) vals2 = [g.CheckVersionToInt(s) for s in s2.split(delimiter)] ; n2 = len(vals2) n = max(n1,n2) if n1 < n: vals1.extend([0 for i in xrange(n - n1)]) if n2 < n: vals2.extend([0 for i in xrange(n - n2)]) for cond,val in ( ('==', vals1 == vals2), ('!=', vals1 != vals2), ('<', vals1 < vals2), ('<=', vals1 <= vals2), ('>', vals1 > vals2), ('>=', vals1 >= vals2), ): if condition == cond: result = val ; break else: raise EnvironmentError,"condition must be one of '>=', '>', '==', '!=', '<', or '<='."

if trace: # print '%10s' % (repr(vals1)),'%2s' % (condition),'%10s' % (repr(vals2)),result print '%7s' % (s1),'%2s' % (condition),'%7s' % (s2),result return result
def CheckVersionToInt (s):

try: return int(s) except ValueError: aList = [] for ch in s: if ch.isdigit(): aList.append(ch) else: break if aList: s = string.join(aList) return int(s) else: return 0
def test_CheckVersionToInt (*args):

assert g.CheckVersionToInt('12') == 12,'fail 1' assert g.CheckVersionToInt('2a5') == 2, 'fail 2' assert g.CheckVersionToInt('b2') == 0, 'fail 3'
This is much less confusing.
http://sourceforge.net/forum/message.php?msg_id=4014079
http://sourceforge.net/forum/message.php?msg_id=4005750

I like the option @string relative_path_base_directory = .

which puts @file nodes in the same directory as the current Leo file.

I would like it if open('file.txt','w').close()

put file.txt in the same directory as the current Leo file.
The spell tab is only shown if Aspell was properly imported.
http://sourceforge.net/forum/message.php?msg_id=3987635
New settings

The following two new settings now control whether the execute-script and debug commands write the script to an external file.

- @bool write_script_file = True

True: The execute script command writes the script to be executed to a file, then executes the script using Python's execFile function. The script_file_path setting specifies the path to this file.

False (legacy): The execute script command uses Python's exec command to execute the script.

- @string script_file_path = ../test/scriptFile.py

The path to the file to be written by the execute-script command.

Notes:

- This setting has effect only if the write_script_file setting is True. - Use / to as the path delimiter, regardless of platform. - The default path is ../test/scriptFile.py if no path is given. - The path starts at g.app.loadDir, so for example ../test/scriptFile.py is equivalent to leo/test/scriptFile.py - The filename should end in .py.

From here on, let us assume the settings are as shown above. There are at least three ways of debugging scripts, depending on your preferences and whether the script contains leo-specific code (g, c or p) or not.

First way: The debug command

The debug command now works almost exactly like Kent's original @button node. This way of debugging can only be used for general scripts, not leo-specific scripts.

The debug command writes the script to scriptFile.py and invokes the debugger as specified by the existing @string debugger_kind option. winpdb opens and is already 'attached' to the script to be debugged. You can single-step as you like. Leo continues to run, but killing the debugger will also kill Leo. When started this way, winpdb is really 'attached' to *all* of Leo, which means you can single step past the end of the script into Leo's executeScript code and from there into all of Leo(!)

As I write this I realize that the code uses arguments specific to winpdb. That may have to be generalized, though I am not sure why anyone would want to use another debugger...

Second way: @button winpdb

This is almost exactly equivalent to the debug command, except that the script file must be *different* from the script file specified by the script_file_path setting (The @button code *itself* uses the execute-script command, so we have to pass the script code, not the @button code to the debugger).

Third way: The execute-script command with explicit debugger breaks

The third way of debugging scripts allows winpdb to debug scripts that use c, g and p. I'm actually not sure of exactly how and why it works, but it certainly does work.

In contrast to the previous two ways, a little more work is needed because winpdb does not start automatically. But I am getting ahead of myself.

To use this way, insert the following two lines of code at the start of the script to be debugged::

import rpdb2 rpdb2.start_embedded_debugger('go',fAllowUnencrypted=True)

Now just execute the execute-script command (*not* the debug command) Leo will appear to hang. Indeed, the start_embedded_debugger command is waiting for *another* copy of winpdb to 'attach' to the script's process. This process is all of Leo! The default timeout is 5 minutes: I'm not sure what happens when the timeout happens: probably an exception gets thrown.

So you must start winpdb explicitly. On XP just do something like

python c:\python25\Scripts\_winpdb.py -t

The -t option tells winpdb that no encoding of password is necessary. The password is specified in the call to rpdb2.start_embedded_debugger in your script. In this example, the password is 'go'. Use the File:Attach command in winpdb to attach winpdb to Leo. Specify the password as 'go' and you will see the scriptFile.py containing your entire script. You can execute or single-step through the script.

To repeat, the big difference is that c, g and p are defined, so you can debug any script this way. As before, killing winpdb also kills Leo.

P.S. winpdb and its documentation has been improved recently. See

http://www.digitalpeers.com/pythondebugger/ and especially

http://www.digitalpeers.com/pythondebugger/embedded.htm

The discussion of embedded debugging may have been written specifically with Leo in mind. It certainly could have been.
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3991223

I assigned both Control and Shift modifiers to do scrolling: this is so my finger can hit a key in the lower left corner of the keyboard, and I don't have to worry too much about my aim (I have LARGE fingers). Also, I stop the scrolling on the JUST button release -- less worry about my finger slipping off the key.
@nocolor

http://sourceforge.net/forum/message.php?msg_id=3916155

When a node is among several other nodes at the same level of hierarchy, which are all children of a node, and the "MOVE LEFT" command is executed, the node does move left in the outline hierarchy, but it also move down to just before the next node at the higher hierarchy level - the level to which it is moving left.

EKR: I love this new option: how did we ever live without it?

@color
@nocolor

This option tells how to treat an uppercase letter typed when the outline pane is active but no headline is being edited. In such situations Leo searches for an node whose headline starts with the present prefix, ignoring case The prefix starts with the first letter typed and other letters are added if they are typed within a 'short' period of time, as specified by the outline_nav_extend_delay

True: Look in invisible nodes. False: Look only in visible nodes.

I set this option to False because it is too easy form me to type Shift-whatever when I meant Ctrl-whatever.

@color
http://sourceforge.net/forum/message.php?msg_id=3985382

Leo's core is now largely free of gui-dependent code, and should be completely free of such code by the time Leo 4.4.3 final is released.
Positions become invalid when the user deletes or moves the node to which the position refers. Plugins and scripts that store positions for use at a later time should make sure the position p is still valid by calling c.positionExists(p).

The following code will find a position p2 describing the same node as p::

if not c.positionExists(p): for p2 in c.allNodes_iter(): if p2.v == p.v: # found c.selectPosition(p2) else: print 'position no longer exists'
http://sourceforge.net/forum/message.php?msg_id=4113315
Leo 4.4.3 alpha 2 March 17, 2006

Leo 4.4.3 alpha 2 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

This version of Leo should be safe enough for production use. It is an alpha distribution because not all plugins have been tested on the reorganized code base.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.3: ---------------------------- - A leoBridge module that allows full access to all of Leo's capabilities from programs running outside of Leo. - Added support for @enabled-plugins nodes in settings files. - The__wx_gui plugin is now functional. - Removed all gui-dependent code from Leo's core. - Better support for the winpdb debugger. - Many minor improvements, new settings and bug fixes.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
@nocolor http://sourceforge.net/forum/message.php?msg_id=4132529

I'm generating Leo files with ElementTree and ran into a minor issue.

ElementTree generates an empty tag with a space before the closing slash:

<globals />

in Leo's code for dummy elements to allow copied nodes to be valid Leo files, the empty tags are generated without the space

leoFileCommands.py 2917 self.put('<globals/>\n') self.put('<preferences/>\n') self.put('<find_panel_settings/>\n')

it then checks for these tags in getDummyElements() leoFileCommands.py 1298

Since ElementTree has the space before the slash, it's XML is considered invalid by Leo according to this test.

I would like it if the space could be added in Leo's self.put(...) and the check in getDummyElements()

The XML specs show the space as optional.

@color
http://sourceforge.net/forum/message.php?msg_id=4134384
Down arrow wasn't handled properly.
http://sourceforge.net/forum/message.php?msg_id=3994218
# The buggy code only happens when there is no binding for backward-delete-char. # http://sourceforge.net/forum/forum.php?thread_id=1681392&forum_id=10227
It's about Nav_buttons v1.5 (cvs version from last Saturday)

Pressing the green back button causes

Error: 1 AttributeError Exception in Tk callback Function: <bound method Commands.goPrevVisitedNode of Commander 39717104: u'F:\\D\\PIM\\PIM_main.leo'> (type: <type 'instancemethod'>) Args: () Traceback (innermost last): File "F:\C\Programs\Leo_cvs\extensions\Pmw\Pmw_1_2\lib\PmwBase.py", line 1752, in __call__ return apply(self.func, args) File "F:\C\Programs\Leo_cvs\src\leoCommands.py", line 4435, in goPrevVisitedNode c.treeCommandHelper(v) AttributeError: Commands instance has no attribute 'treeCommandHelper'
http://sourceforge.net/forum/message.php?msg_id=4201463
http://sourceforge.net/forum/message.php?msg_id=4205072
Traceback (most recent call last):

File "c:\prog\tigris-cvs\leo\src\leoGlobals.py", line 2474, in doHook return f(tag,keywords)

File "c:\prog\tigris-cvs\leo\src\leoPlugins.py", line 92, in doPlugins return doHandlersForTag(tag,keywords)

File "c:\prog\tigris-cvs\leo\src\leoPlugins.py", line 70, in doHandlersForTag val = callTagHandler(bunch,tag,keywords)

File "c:\prog\tigris-cvs\leo\src\leoPlugins.py", line 49, in callTagHandler result = handler(tag,keywords)

File "C:\prog\tigris-cvs\leo\plugins\rClick.py", line 156, in rClicker n0,p0=ind0.split('.',2)

AttributeError: 'int' object has no attribute 'split'
Leo did not write to the log pane that settings, either present in myLeoSettings.leo or the current file, were read.
http://sourceforge.net/forum/message.php?msg_id=4162357
The leoBridge module allows complete access to all aspects of Leo from programs running independently of Leo. Let us call such a program a **host** program. Using the leoBridge module, foreign programs can get access to:

- all of Leo's source code, - the contents of any .leo file, - the commander of any .leo file.

Host programs use the leoBridge module as follows::

import leoBridge controller = leoBridge.controller(gui='nullGui') g = controller.globals() c = controller.openLeoFile(path)

Let us look at these statements in detail. The statements::

import leoBridge controller = leoBridge.controller(gui='nullGui')

import the leoBridge module and create a **bridge controller**. In effect, these statements embed an 'invisible' copy Leo into the host program. This embedded copy of Leo uses a 'null' gui, which simulates all aspects of Leo's normal gui code without creating any screen objects.

The statement::

g = controller.globals()

provides access to Leo's leoGlobals module, and properly inits globals such as g.app, g.app.gui, etc. Host programs **should not** import leoGlobals directly, because doing so would not init the g.app object properly.

The statement::

c = controller.openLeoFile(path)

invisibly opens the .leo file given by the ``path``argument. This call returns a completely standard Leo commander, properly inited. This is the big payoff from the leoBridge module: the host program gets instant access to c.config.getBool, etc. Do you see how sweet this is?

The following script runs leo/test/leoBridgeTest.py outside of Leo. leoBridgeTest.py uses the leoBridge module to run all unit tests in leo/test/unitTest.leo. Try it::

import os,sys

path = g.os_path_abspath( g.os_path_join( g.app.loadDir,'..','test','leoBridgeTest.py'))

os.system('%s %s' % (sys.executable,path))
http://sourceforge.net/forum/message.php?msg_id=4169720
Any .leo file may now contain an @enabled-plugins node as a child of an @settings node. If such a node exists, Leo treats the body text of the @enabled-plugins node exactly as it would the contents of the pluginsManager.txt file.

Notes:

A) Leo attempts to load all plugins every time an @enabled-plugins node is seen. If the plugin has already been loaded, Leo silently ignores the request to re-enable the plugin. Leo never attempts to disable a plugin while processing enabled plugin strings. Thus, plugins enabled in an @enabled-plugins node in leoSettings.leo *will* be enabled regardless of the contents of any other @enabled-plugins node.

B) Leo will read the pluginsManager.txt file only if no @enabled-plugins node is found. The pluginsManager.txt file will no longer be part of the Leo distribution. Instead, the default plugins will be enabled in an @enabled-plugins node in leoSettings.leo.

C) g.app.gui.getEnabledPlugins contains the last value last processed @enabled-plugins node, or the contents of the first pluginsManager.txt file encountered.
@language rest
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. March 17, 2007

|back| |leo| |next|

############################################################ Chapter 19: Embedding Leo with the leoBridge module ############################################################

The leoBridge module allows complete access to all aspects of Leo from programs running independently of Leo. Let us call such a program a **host** program. Using the leoBridge module, host programs can get access to:

- all of Leo's source code, - the contents of any .leo file, - the commander of any .leo file.

.. contents::
.. Links

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: emacs.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: unitTesting.html
Host programs use the leoBridge module as follows::

import leoBridge controller = leoBridge.controller(gui='nullGui') g = controller.globals() c = controller.openLeoFile(path)

Let us look at these statements in detail. The statements::

import leoBridge controller = leoBridge.controller(gui='nullGui')

import the leoBridge module and create a **bridge controller**. In effect, these statements embed an invisible copy Leo into the host program. This embedded copy of Leo uses a null gui, which simulates all aspects of Leo's normal gui code without creating any screen objects.

The statement::

g = controller.globals()

provides access to Leo's leoGlobals module, and properly inits globals such as g.app, g.app.gui, etc. *Host programs should not import leoGlobals directly*, because doing so would not init the g.app object properly.

The statement::

c = controller.openLeoFile(path)

invisibly opens the .leo file given by the path argument. This call returns a completely standard Leo commander, properly inited. This is the big payoff from the leoBridge module: the host program gets instant access to c.config.getBool, etc. Do you see how sweet this is?

For example, the following script runs leo/test/leoBridgeTest.py outside of Leo. leoBridgeTest.py uses the leoBridge module to run all unit tests in leo/test/unitTest.leo::

import os,sys

path = g.os_path_abspath( g.os_path_join( g.app.loadDir,'..','test','leoBridgeTest.py'))

os.system('%s %s' % (sys.executable,path))

The file leo/test/test.leo contains the source code for leoBridgeTest.py. Here it is, stripped of its sentinel lines::

'''A program to run unit tests with the leoBridge module.'''

import leoBridge import leoTest

def main (): tag = 'leoTestBridge'

# Setting verbose=True prints messages that would be sent to the log pane. bridge = leoBridge.controller(gui='nullGui',verbose=False) if bridge.isOpen(): g = bridge.globals() path = g.os_path_abspath(g.os_path_join( g.app.loadDir,'..','test','unitTest.leo')) c = bridge.openLeoFile(path) g.es('%s %s' % (tag,c.shortFileName())) runUnitTests(c,g)

print tag,'done'

def runUnitTests (c,g): nodeName = 'All unit tests' # The tests to run. try: u = leoTest.testUtils(c) p = u.findNodeAnywhere(nodeName) if p: g.es('running unit tests in %s...' % nodeName) c.selectPosition(p) c.debugCommands.runUnitTests() g.es('unit tests complete') else: g.es('node not found:' % nodeName) except Exception: g.es('unexpected exception') g.es_exception() raise

if __name__ == '__main__': main()
-----------------------

|back| |leo| |next|
Organizer nodes have headlines that do no start with @. Organizer nodes may be inserted freely without changing the meaning of an @setting tree.
Leo ignores any subtree of an ``@settings`` tree whose headline starts with ``@ignore``.

You can use several other kinds of nodes to cause Leo to ignore parts of an ``@settings`` tree:

- ``@if`` *expression*

A node whose headline starts with ``@if`` *expression* acts like an organizer node if the expression evaluates to True, otherwise acts like an ``@ignore`` node. If the expression is empty the body text should contain a script that will be evaluated (in an empty context).

- ``@ifplatform`` *platform-name*

Same as ``@if sys.platform == "platform-name":`` except that it isn't necessary to import sys.
Simple settings nodes have headlines of the form::

@<type> name = val

set the value of ``name`` to ``val``, with the indicated type.

<type> may be one of the following:

=============== ========================================================================================= <type> Valid values --------------- ----------------------------------------------------------------------------------------- \@bool True, False, 0, 1 \@color A Tk color name or value, such as 'red' or 'xf2fddff' (without the quotes) \@directory A path to a directory \@float A floating point number of the form nn.ff. \@int An integer \@ints[list] An integer (must be one of the ints in the list). Example: @ints meaningOfLife[0,42,666]=42 \@keys[name] Gives a name to a set of bindings for the Check Bindings script in leoSettings.leo. \@path A path to a directory or file \@ratio A floating point number between 0.0 and 1.0, inclusive. \@string A string \@strings[list] A string (must be one of the strings in the list). Example: @strings tk_relief['flat','groove','raised']='groove' =============== =========================================================================================

**Note**: For a list of Tk color specifiers see:

- http://www.tcl.tk/man/tcl8.4/TkCmd/colors.htm - http://www.tcl.tk/man/tcl8.4/TkLib/GetColor.htm

**Important**: you can use the show-colors minibuffer command to guide you in making these settings.
Complex settings nodes have headlines of the form::

@<type> description

The type may be one of the following:

=================== ===================================================================== <type> Valid values ------------------- --------------------------------------------------------------------- \@buttons Child @button nodes create global buttons \@commands Child @command nodes create global buttons \@enabled-plugins Body text contains a list of enabled plugins \@font Body text contains a font description \@menus Child @menu and @item nodes create menus and menu items. \@mode [name] Body text contains a list of shortcut specifiers. \@recentfiles Body text contains a list of file paths. \@shortcuts Body text contains a list of shortcut specifies. =================== =====================================================================

The actual settings are specified in the body text. At present, there are seven kinds of complex settings nodes:

- ``@buttons``

An @buttons tree in a settings file defines global buttons that are created in the icon area of all .leo files. All @button nodes in the @commands tree create global buttons. All @button nodes outside the commands tree create buttons local to the settings file.

- ``@commands``

**New in Leo 4.4.8**: An @commands tree in a settings file defines global commands. All @command nodes in the @commands tree create global commands. All @command nodes outside the commands tree create commands local to the settings file.

- ``@data``

The body text contains a list of strings, one per line. Lines starting with '#' are ignored.

- ``@enabled-plugins``

The body text of the @enabled plugins node contains a list of enabled plugins. This body text is treated exactly as the contents of the pluginsManager.txt file. Notes:

A) Leo attempts to load all plugins every time an @enabled-plugins node is seen. If the plugin has already been loaded, Leo silently ignores the request to re-enable the plugin. Leo never attempts to disable a plugin while processing enabled plugin strings. Thus, plugins enabled in an @enabled-plugins node in leoSettings.leo *will* be enabled regardless of the contents of any other @enabled-plugins node.

B) Leo will read the pluginsManager.txt file only if no @enabled-plugins node is found. The pluginsManager.txt file will no longer be part of the Leo distribution. Instead, the default plugins will be enabled in an @enabled-plugins node in leoSettings.leo.

C) g.app.gui.getEnabledPlugins contains the last value last processed @enabled-plugins node, or the contents of the first pluginsManager.txt file encountered.

- ``@font``

The body text contains a list of settings for a font. For example::

body_text_font_family = Courier New body_text_font_size = None body_text_font_slant = None body_text_font_weight = None

**Important**: you can use the show-fonts minibuffer command to guide you in making these settings.

- ``@menus``

Leo creates its menus from the @menu, @item and @popup nodes in the @menus tree. Within @menus trees, @menu nodes create menus and @item nodes create menu items.

The menu name always follows @menu. If the menu name is 'Plugins', Leo will create the Plugins menu and populate the menu by calling the 'create-optional-menus' hook. This creates the Plugins menu as usual. Nested @menu nodes define submenus.

The command name follows @item. If the body text of an @item node exists, this body text is the menu name. Otherwise, the menu name is the command name. However, if the command name starts with a ``'*'``, hyphens are removed from the menu name. Menu names and command names may contain a single ampersand (&). If present, the following character is underlined in the name. If the command name in an @item node is just a hyphen (-), the item represents a menu separator.

``@popup`` *<widget-name>* creates a popup menu for use by the rClick plugin. The children of this node should be @menu and @item nodes, used as with @menus.

- ``@mode`` *<mode name>*

The body text contains a list of shortcut specifiers. ``@mode`` nodes work just like ``@shortcuts`` nodes, but in addition they have the side effect of creating the ``enter-<mode name>-mode`` command.

- ``@recentfiles``

The body text contains a list of paths of recently opened files, one path per line. Leo writes the list of recent files to ``.leoRecentFiles.txt`` in Leo's ``config`` directory, again one file per line.

- ``@shortcuts``

The body text contains a list of shortcut specifiers.
The __wx_gui.py plugin is now minimally functional. All significant unit tests pass with this plugin in effect. However, problems remain. See the bug list in the plugin for details.
Leo 4.4.3 beta 1 May 18, 2006

Leo 4.4.3 beta 1 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.3: ---------------------------- - Added support for chapters in Leo's core. Chapters are disabled by default. To enable, set @bool use_chapters = True. - Added support for zipped .leo files. - Added a leoBridge module that allows full access to all of Leo's capabilities from programs running outside of Leo. - Removed all gui-dependent code from Leo's core. - Better support for the winpdb debugger. - Added support for @enabled-plugins nodes in settings files. - Added support for @open-with nodes in settings files. - The__wx_gui plugin is now functional. - Many minor improvements, new settings, commands and bug fixes.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
It is True by default. In effect, this setting was False in previous versions of Leo, which might be considered a bug.
http://sourceforge.net/forum/message.php?msg_id=3737745

http://sourceforge.net/forum/message.php?msg_id=3785897

Would it be possible to have the table of "Open With" editors to be part of the config system? I find myself patching the list every time I D/L a new Leo version to add the editor I use. This would also help isolate the user from the "guts" of Leo, thereby being less intimidating.
Leo now supports zipped .leo files:

- Leo now has save-file-as-zipped and save-file-as-unzipped commands, and corresponding Save File As Zipped and Save File as Unzipped items in the File menu. These are exactly the same as Leo's Save As commands except that they temporarily force Leo to write the file in either zipped or unzipped format.

- Leo remembers whether a file was originally zipped. The read logic handles either zipped or unzipped .leo files automatically. The write logic will zip the file if it was originally zipped or if the save-file-as-zipped command is being executed.

- Leo writes files with .leo extension, regardless of whether the file is zipped or not. Zipped .leo files contain a single archive, whose name is the same as the .leo file itself.

Notes:

- The new save commands suffice to compress and expand .leo files on a file-by-file basis. In particular, there is no need for any user settings.

- Outside of Leo you can change the extension to .leo.zip and use stuffit or other program to expand the .leo file contained within. I've only tested this on XP, but it should work everywhere...

- At present the code uses Python's zipfile module to read and write zipped files. In turn, the zipfile module uses the zlib module to do the compression. Conceivably somebody might want Leo to use some other compression technique, say Python's tarfile module. However, I think the present way should suffice for most people.
# Found via unit test. Happens regardless of chapters.
# Returns in finally clauses prevent the re-raising of the saved exception(!!)
https://sourceforge.net/forum/message.php?msg_id=4283692
http://sourceforge.net/forum/message.php?msg_id=4215654

There was a bug with ordinary hoisting: in the "Outline" menu the "Delete Node" menu item was not disabled when the local root is selected.
- Added support for chapters to Leo's core

Chapters are regions of a Leo outline whose root is an @chapter node. @chapter nodes may appear anywhere in an outline, but the create-chapter command (see below) creates @chapter nodes as children of a single @chapters node.

Selecting a chapter shows only then nodes in the selected chapter; in this respect, chapters are like hoists. The main chapter represents the entire outline and can not be deleted by name. When chapters are in effect, Leo creates a hidden @chapters node containing one @chapter node for every chapter except the 'main' chapter.

Associated settings:

- The @bool use_chapters setting determines whether chapters are enabled. - The @bool use_chapter_tabs setting determines whether the chapters pop-up menu appears in the icon area. Choosing a chapter name from this list selects a chapter.

When chapters are enabled, the Cmds:Chapters menu shows all available chapter commands:

- The create-chapter command creates an @chapter node and with a single node. - The delete-chapter command deletes the presently selected chapter. - The select-chapter command makes only the nodes of the selected chapter visible. - The move-node-to-chapter, clone-node-to-chapter and copy-node-to-chapter commands add a node (and its descendants) to another chapter.
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|prev| |leo| |next|

########################################## What's New in Leo 4.4.3 ##########################################

The highlights of Leo 4.4.3:

- @test and @suite nodes may now be embedded directly in derived files. - Added support for chapters in Leo's core. - Added support for zipped .leo files. - The new leoBridge module allows full access to all of Leo's capabilities from programs running outside of Leo. - Better support for the winpdb debugger. - Added support for @enabled-plugins and @open-with nodes in settings files. - Removed all gui-dependent code from Leo's core. - The__wx_gui plugin is now functional.

.. contents::
.. Links used in this document.

.. _`leoBridge chapter`: leoBridge.html .. _`debugging with Leo`: debuggers.html

.. WARNING: image targets may not have upper case letters!

.. |prev| image:: arrow_lt.gif :target: new-4-4-4.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: new-4-4-2.html
-----------------------

|prev| |leo| |next|
::

apropos-debugging-commands clean-all-lines clone-node-to-chapter copy-node-to-chapter create-chapter delete-chapter goto-first-visible-node move-node-to-chapter print-plugin-handlers print-plugins print-settings save-file-as-unzipped save-file-as-zipped select-chapter
- @test and @suite nodes may now be embedded in derived files. - Added support for chapters to Leo's core

Chapters are regions of a Leo outline whose root is an @chapter node. @chapter nodes may appear anywhere in an outline, but the create-chapter command (see below) creates @chapter nodes as children of a single @chapters node.

Selecting a chapter shows the nodes in the selected chapter; in this respect, chapters are like hoists. The main chapter represents the entire outline and can not be deleted by name. When chapters are in effect, Leo creates a hidden @chapters node containing one @chapter node for every chapter except the 'main' chapter.

Associated settings:

- The @bool use_chapters setting determines whether chapters are enabled. - The @bool use_chapter_tabs setting determines whether the chapters pop-up menu appears in the icon area. Choosing a chapter name from this list selects a chapter.

When chapters are enabled, the Cmds:Chapters menu shows all available chapter commands:

- The create-chapter command creates an @chapter node and with a single node. - The delete-chapter command deletes the presently selected chapter. - The select-chapter command makes only the nodes of the selected chapter visible. - The move-node-to-chapter, clone-node-to-chapter and copy-node-to-chapter commands add a node (and its descendants) to another chapter.

- Added support for compressed .leo files

Leo now has save-file-as-zipped and save-file-as-unzipped commands, and corresponding Save File As Zipped and Save File as Unzipped items in the File menu. These are exactly the same as Leo's Save As commands except that they temporarily force Leo to write the file in either zipped or unzipped format. Leo remembers whether a file was originally zipped. The read logic handles either zipped or unzipped .leo files automatically. The write logic will zip the file if it was originally zipped or if the save-file-as-zipped command is being executed. Leo writes files with .leo extension, regardless of whether the file is zipped or not. Zipped .leo files contain a single archive, whose name is the same as the .leo file itself.

**Notes**: The new save commands suffice to compress and expand .leo files on a file-by-file basis. In particular, there is no need for any user settings. Outside of Leo you can change the extension to .leo.zip and use stuffit or other program to expand the .leo file contained within. I've only tested this on XP, but it should work everywhere...At present the code uses Python's zipfile module to read and write zipped files.

- Added leoBridge module. See the `leoBridge chapter`_ for full details.

- Removed all (or almost all) gui-independent from Leo's core.

- Improved support for the winpdb debugger. See the `debugging with Leo`_ chapter for full details.
::

@openwith nodes @enabled-plugins nodes @bool center_selected_tree_node @bool chdir_to_relative_path @bool contractVisitedNodes @bool force_newlines_in_at_nosent_bodies @bool invisible_outline_navigation @bool show_full_tracebacks_in_scripts @bool use_chapter_tabs @bool use_chapters

For details of these new settings, see leoSettings.leo

- The __wx_gui.py plugin is now minimally functional. Alas, some problems remain. See the bug list in the plugin for details.

- Added new search path for pluginsManager.txt For details, see: http://sourceforge.net/forum/message.php?msg_id=4169720

- Changed bindings in the UniversalScrolling plugin.

- Registered the write-restructured-text command in rst3 plugin.
- See the release notes for a list of the many bugs fixed in Leo 4.4.3.

- Warn on dubious section brackets. For details, see http://sourceforge.net/forum/message.php?msg_id=4162357

- Added Find and Spell tabs to log pane on startup. The spell tab is only shown if Aspell was properly imported.

- Added shortcuts for goto-first/last-sibling commands.

- Made escape in the minibuffer work like ctrl-g.

- Only do one message re writing recent files.

- Added handleUrlInUrlNode helper for OnIconDoubleClick.

- Made copied nodes valid Leo files. For details, see http://sourceforge.net/forum/message.php?msg_id=4014079

- changeAll now works like findAll

- Created standard pluginsManager.txt only if it does not exist.

- Clear status line in repeat-complex-command.
Leo 4.4.3 beta 2 June 12, 2006

Leo 4.4.3 beta 2 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.3: ---------------------------- - Added support for chapters in Leo's core. Chapters are disabled by default. To enable, set @bool use_chapters = True. - Added support for zipped .leo files. - Added a leoBridge module that allows full access to all of Leo's capabilities from programs running outside of Leo. - Removed all gui-dependent code from Leo's core. - Better support for the winpdb debugger. - Added support for @enabled-plugins nodes in settings files. - Added support for @open-with nodes in settings files. - Added support for @bool write_strips_blank_lines setting. - The__wx_gui plugin is now functional. - Leo can use aspell on Linux when using Python 2.5 or later. - Many minor improvements, new settings, commands and bug fixes.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
http://sourceforge.net/forum/message.php?msg_id=4315027

The fix was to g.skip_to_end_of_line (!)

All such functions now return len(s) as a boundary condition. This is a major change. All unit tests pass.
http://sourceforge.net/forum/message.php?msg_id=4320971
@nocolor

http://sourceforge.net/forum/message.php?msg_id=4309448

Still to do: update urls for tigris.
http://sourceforge.net/forum/message.php?msg_id=4301021
- Select a node by clicking on it. - The node is selected, but shift-arrow does not work.

However, clicking the canvas does work.

The fix was to give the canvas, not the headline focus when clicking on a headline. This results in canvas bindings, not text bindings, having priority. This is not a kludge: the text widget isn't active, so text bindings should not be in effect.
http://sourceforge.net/forum/message.php?msg_id=4340244
http://sourceforge.net/forum/message.php?msg_id=4341644
The following chapter commands now exist:

clone-node-to-chapter convert-node-to-chapter copy-node-to-chapter create-chapter create-chapter-from-node move-node-to-chapter remove-chapter rename-chapter select-chapter
http://sourceforge.net/forum/message.php?msg_id=4318634

- Use ctypes.util.find_library('aspell') to find aspell lib.
http://sourceforge.net/forum/message.php?msg_id=4255709

Added globalDynamicAbbrevs setting. Added tab completion for dabbrev-expand.
This for the use of the hoist plugin.
@nocolor

http://sourceforge.net/forum/message.php?msg_id=4134565

The following are now enabled by default:

# Plugin_manager.py needs plugins_menu.py plugins_menu.py plugin_manager.py open_with.py mod_scripting.py rst3.py UNL.py

# Enabled by default in Leo 4.4.3. (order is important) nav_buttons.py hoist.py image.py leo_to_html.py

I left out cleo because it has been reported not to be fully functional with Leo 4.4.3.
http://sourceforge.net/forum/message.php?msg_id=4356197
Leo 4.4.3 beta 3 June 23, 2006

Leo 4.4.3 beta 3 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

This release fixes all known bugs and adds several new features.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.3: ---------------------------- - Added support for chapters in Leo's core. - Added support for zipped .leo files. - Added a leoBridge module that allows full access to all of Leo's capabilities from programs running outside of Leo. - Removed all gui-dependent code from Leo's core. - Better support for the winpdb debugger. - Added support for @enabled-plugins nodes in settings files. - Added support for @open-with nodes in settings files. - Added support for @bool write_strips_blank_lines setting. - The__wx_gui plugin is now functional. - Leo can use aspell on Linux when using Python 2.5 or later. - @test nodes can now be run from any .leo file. - Many minor improvements, new settings, commands and bug fixes.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
# ctypes comes standard with Python 2.5, but can be installed for Python 2.4.
# Created menu-command-key command that just returns 'continue'.
http://sourceforge.net/forum/message.php?msg_id=4362825
Selecting a node now never truncates the beadList.
CleanLines was adding a trailing newline. The fix was to suppress this during unit tests.
Alt-home is now bound to goto-first-visible rather than goto-first.
This script runs all @test nodes as follows:

- Copies all @suite and @tests nodes to dynamicUnitTests.leo.

- Runs leoDynamicTest.py in a separate process. In turn, leoDynamicTest.py use the leoBridge module to run dynamicUnitTests.leo. (test.leo contains the source code for leoDynamicTest.py.)

Thus, all unit tests will be run with the latest Leo sources.

Allowing @test nodes in leoPy.leo is important: unit tests can be placed near the code they are intended to test.
The test 'if g.unitTesting:' is a shorter replacement for the test 'if g.app and g.app.unitTesting:'.

Using g.getTestVars eliminates pychecker warnings about undefined c and p variables.
Leo is distributed either as an executable installer (.exe) file or as a .zip file.

To install Leo using the executable installer:

1. Download the latest version of Leo's installer from `Leo's download page`_. The installer will be called something like LeoSetup-4-4-3.exe.

2. Run the installer. By default, the install will install Leo in your 'Program Files' directory.

To install Leo from the .zip file:

1. Download the latest version of Leo (a .zip file) from `Leo's download page`_.

2. Unzip the .zip file and place the unpacked leo folder in the 'Program Files' folder or any convenient location.

After you have installed Leo, you should add the location of your leo/src folder to your python path. One way to do this is adding something like the following to python/Lib/sitecustomize.py::

import sys sys.path.append(r'<path-to-leo>leo\src')

Another way is to append <path-to-leo> to the Windows PYTHONPATH environment variable.

Now that you have installed Leo and told Python where to find Leo, you are ready to `run Leo`_.

**Note**: If you haven't already created a HOME environment variable, it would be good to define home to be "%USERPROFILE%\My Documents". You can check whether HOME exists by typing 'echo %HOME%' (without the quotes) in a console window.
By Randall Voth: Leo works reliably only on MacOS X 10.3 (Panther) and above. To run Leo on Macintosh OS X 10:

1. Download and install ``MacPython 2.3 for Panther addons``. Python is already included in OS X 10.3 so only the addons are necessary at http://www.cwi.nl/~jack/macpython.html

2. Download and install TclTkAqua from http://tcltkaqua.sourceforge.net/

3. Run the PackageManager found in ``/Applications/MacPython-2.3`` and install ``_tkinter-2.3-binary`` by clicking on the package in the list and clicking the [Install:] button with ``Install dependencies`` checked.

4. Download Leo (platform independent source.zip) from http://leo.sourceforge.net/

5. Unzip the contents into a directory by double-clicking the downloaded file. Typically you would put the Leo folder into the ``Applications`` directory.

6. Control-click on ``/path_to_unzipped_dir/leo/src/leo.py`` and open with ``PythonLauncher``.

7. It is a good idea to set ``PythonLauncher`` as the default program to open python scripts by clicking on ``leo.py``, choosing Get Info from the Finder's File menu, and selecting "PythonLauncher" as the default program to ``Open With:`` By clicking the ``Change All...`` button, all python scripts will be opened with ``PythonLauncher``.

8. Download ``Pmw`` from http://pmw.sourceforge.net/ ``Pmw`` must be installed in order to use the Settings panel. Drag the downloaded gzip file into ``/System/Library/Frameworks/Python.framework/Versions/2.3/lib/python2.3/site-packages`` Double click on it to unzip and untar the file into a folder to make it available to Python
- Added support for chapters to Leo's core

Chapters are regions of a Leo outline whose root is an @chapter node. @chapter nodes may appear anywhere in an outline, but the create-chapter command (see below) creates @chapter nodes as children of a single @chapters node.

Selecting a chapter shows only then nodes in the selected chapter; in this respect, chapters are like hoists. The main chapter represents the entire outline and can not be deleted by name. When chapters are in effect, Leo creates a hidden @chapters node containing one @chapter node for every chapter except the 'main' chapter.

Associated settings:

- The @bool use_chapters setting determines whether chapters are enabled. - The @bool use_chapter_tabs setting determines whether the chapters pop-up menu appears in the icon area. Choosing a chapter name from this list selects a chapter.

When chapters are enabled, the Cmds:Chapters menu shows all available chapter commands:

- The create-chapter command creates an @chapter node and with a single node. - The delete-chapter command deletes the presently selected chapter. - The select-chapter command makes only the nodes of the selected chapter visible. - The move-node-to-chapter, clone-node-to-chapter and copy-node-to-chapter commands add a node (and its descendants) to another chapter.
The 'official' way to start a replace command is::

<Ctrl-shift-r>find-pattern<return>replace-text<return>

But suppose you with start with::

<ctrl-f>find-pattern

and then realize you want to do a replace instead of a find. No problem. The following also works::

<Ctrl-f>find-pattern<Ctrl-shift-r>replace-text<return>

In other words, you can think of `<ctrl-f>` as meaning 'show the find dialog'. There is another trick you should know. After typing `<ctrl-f>` or `<shift-ctrl-r>` you can use `<alt-ctrl>` keys to set or clear find options. For example::

<ctrl-f><alt-ctrl-w><find-pattern><return>

That is, `<ctrl-f>`shows the find dialog, `<alt-ctrl-w>` toggles the Whole Word checkbox and `<return>` starts the search. You can type the `<alt-ctrl>` keys anytime after `<ctrl-f>` (or `<shift-ctrl-r>`) and before `<return>`. You can also type multiple `<alt-ctrl-keys>` to toggle multiple checkboxes.
::

activate-cmds-menu activate-edit-menu activate-file-menu activate-help-menu activate-outline-menu activate-plugins-menu activate-window-menu add-space-to-lines add-tab-to-lines clean-lines clear-selected-text click-click-box click-headline click-icon-box clone-find-all contract-and-go-right contract-body-pane contract-log-pane contract-outline-pane contract-pane double-click-headline double-click-icon-box dump-all-objects dump-new-objects expand-body-pane expand-log-pane expand-outline-pane expand-pane find-again find-all find-tab-change find-tab-change-all find-tab-change-then-find find-tab-find command find-tab-find-previous free-text-widgets fully-expand-body-pane fully-expand-log-pane fully-expand-outline-pane fully-expand-pane goto-first-sibling goto-global-line goto-last-sibling help help-for-command hide-body-pane hide-find-tab hide-log-pane hide-minibuffer hide-outline-pane hide-pane, open-find-tab open-find-tab open-outline-by-name (uses filename completion) open-spell-tab print-bindings print-commands re-search-backward re-search-forward remove-space-from-lines remove-tab-from-lines replace-string scroll-down scroll-down-extend-selection scroll-outline-down-line scroll-outline-down-page scroll-outline-up-line scroll-outline-up-page scroll-up scroll-up-extend-selection search-backward search-forward search-with-present-options set-find-everywhere set-find-node-only set-find-suboutline-only show-colors show-fonts show-minibuffer show-search-options simulate-begin-drag simulate-end-drag toggle-find-ignore-case-option toggle-find-in-body-option, toggle-find-in-headline-option toggle-find-mark-changes-option toggle-find-mark-finds-option toggle-find-regex-option toggle-find-reverse-option toggle-find-word-option and toggle-find-wrap-around-option toggle-mini-buffer verbose-dump-objects word-search-backward word-search-forward
- Added @font menu font setting. - Added support for commands to be executed on entry to a mode. - Added support for bindings that are active only in command, enter and insert key states. - Added support for @abbrev nodes in leoSettings.leo. - Improved check bindings script in leoSettings.leo. - Allow @mode outside of leoSettings.leo. - Added warnings about the @bool expanded_click_area setting.
Leo's setup.py script is intended only to create source distributions. It can't be used to install Leo because Leo is not a Python package.
Chapters are regions of a Leo outline whose root is an @chapter node. @chapter nodes may appear anywhere in an outline, but the create-chapter command (see below) creates @chapter nodes as children of the first @chapters node in the outline.

Selecting a chapter shows only then nodes in the selected chapter; in this respect, chapters are like hoists. The main chapter represents the entire outline and can not be deleted by name. When chapters are in effect, Leo creates a hidden @chapters node containing one @chapter node for every chapter except the 'main' chapter.

Associated settings:

- The @bool use_chapters setting determines whether chapters are enabled. - The @bool use_chapter_tabs setting determines whether the chapters pop-up menu appears in the icon area. Choosing a chapter name from this list selects a chapter.

When chapters are enabled, the Cmds:Chapters menu shows all available chapter commands:

- The create-chapter command creates an @chapter node and with a single node. - The delete-chapter command deletes the presently selected chapter. - The select-chapter command makes only the nodes of the selected chapter visible. - The move-node-to-chapter, clone-node-to-chapter and copy-node-to-chapter commands add a node (and its descendants) to another chapter.
Leo 4.4.3 final June 26, 2006

Leo 4.4.3 final is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.3: ---------------------------- - Added support for chapters in Leo's core. - Added support for zipped .leo files. - Added a leoBridge module that allows full access to all of Leo's capabilities from programs running outside of Leo. - Removed all gui-dependent code from Leo's core. - Better support for the winpdb debugger. - Added support for @enabled-plugins nodes in settings files. - Added support for @open-with nodes in settings files. - Added support for @bool write_strips_blank_lines setting. - The__wx_gui plugin is now functional. - Leo can use aspell on Linux when using Python 2.5 or later. - @test nodes can now be run from any .leo file. - Many minor improvements, new settings, commands and bug fixes.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
@language rest @tabwidth -4
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. June, 2007

|back| |leo| |next|

############################################################ Chapter 20: Unit testing with Leo ############################################################

This chapter describes how you can execute Python unit test from within Leo outlines.

.. contents::
.. Links

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: leoBridge.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: IPythonBridge.html
-----------------------

|back| |leo| |next|
**@test nodes** are nodes whose headlines start with @test. The unit test commands convert the body text of @test nodes into a unit test automatically. That is, Leo's unit test commands automatically create a unittest.TestCase instances which run the body text of the @test node. For example, let us consider one of Leo's actual unit tests. The headline is::

@test consistency of back/next links

The body text is::

if g.unitTesting: c,p = g.getTestVars() # Optional: prevents pychecker warnings. for p in c.allNodes_iter(): back = p.back() next = p.next() if back: assert(back.getNext() == p) if next: assert(next.getBack() == p)

When either of Leo's unit test commands finds this @test node the command will run a unit test equivalent to the following::

import leoGlobals as g

class aTestCase (unittest.TestCase): def shortDescription(): return '@test consistency of back/next links' def runTest(): c,p = g.getTestVars() for p in c.allNodes_iter(): back = p.back() next = p.next() if back: assert(back.getNext() == p) if next: assert(next.getBack() == p)

As you can see, using @test nodes saves a lot of typing:

- You don't have to define a subclass of unittest.TestCase. - Within your unit test, the c, g and p variables are predefined, just like in Leo scripts. - The entire headline of the @test node becomes the short description of the unit test.

**Important note**: notice that the first line of the body text is a **guard line**::

if g.unitTesting:

This guard line is needed because this particular @test node is contained in the file leoNodes.py. @test nodes that appear outside of Python source files do not need guard lines. The guard line prevents the unit testing code from being executed when Python imports the leoNodes module; the g.unitTesting variable is True only while running unit tests.

Note: Leo predefines the c, g, and p variables in @test and @suite nodes, just like in other scripts. Thus, the line::

c,p = g.getTestVars()

is not needed. However, it prevents pychecker warnings that c and p are undefined.
test.leo and leoPy.leo contain two unit testing buttons::

@button unit-tests @key=Alt+4 @button all-unit-tests @key=Alt+5

The script in the unit-tests button is::

import leoTest leoTest.runTestsExternally (c,all=False)

The script in the all-unit-tests button is::

import leoTest leoTest.runTestsExternally (c,all=True)

As you can see, each button writes a message, and calls runTestsExternally. The only difference in these scripts is the 'all' argument.

These buttons create bindings for the 'unit-tests' and 'all-unit-tests' commands. Alternatively, you can dispense with these buttons and instead use the run-unit-tests and run-all-unit-tests commands directly. As always, you can create bindings for these commands in leoSettings.leo or myLeoSettings.leo.
**@suite nodes** are nodes whose headlines start with @suite. @suite nodes allow you to create and run custom subclasses of unittest.TestCase.

Leo's test commands assume that the body of an suite node is a script that creates a suite of tests and places that suite in g.app.scriptDict['suite']. Something like this::

if g.unitTesting: __pychecker__ = '--no-reimport' # Prevents pychecker complaint. import unittest c,p = g.getTestVars() # Optional. suite = unittest.makeSuite(unittest.TestCase) << add one or more tests (instances of unittest.TestCase) to suite >> g.app.scriptDict['suite'] = suite

**Note**: as in @test nodes, the guard line, 'if unitTesting:', is needed only if the @suite node appears in a Python source file.

Leo's test commands first execute the script and then run suite in g.app.scriptDict.get('suite') using the standard unittest text runner.

You can organize the script in an @suite nodes just as usual using @others, section references, etc. For example::

if g.unitTesting: __pychecker__ = '--no-reimport' import unittest c,p = g.getTestVars() # Optional. # children define test1,test2..., subclasses of unittest.TestCase. @others suite = unittest.makeSuite(unittest.TestCase) for test in (test1,test2,test3,test4): suite.addTest(test) g.app.scriptDict['suite'] = suite
The run-all-unit-tests-locally and run-unit-tests-locally commands run unit tests in the process that is running Leo. These commands *can* change the outline containing the unit tests.

The run-all-unit-tests and run-unit-tests commands run all tests in a separate process, so unit tests can never have any side effects. These commands never changes the outline from which the tests were run. These commands do the following:

1. Copy all @test, @suite and @unit-test nodes (including their descendants) to the file test/dynamicUnitTest.leo.

2. Run test/leoDynamicTest.py in a separate process.

- leoDynamicTest.py opens dynamicUnitTest.leo with the leoBridge module. Thus, all unit tests get run with the nullGui in effect.

- After opening dynamicUnitTest.leo, leoDynamicTest.py runs all unit tests by executing the leoTest.doTests function.

- The leoTests.doTests function searches for @test and @suite nodes and processes them generally as described above. The details are a bit different from as described, but they usually don't matter. If you *really* care, see the source code for leoTests.doTests.
On startup, Leo looks for two arguments of the form::

--script scriptFile

If found, Leo enters batch mode. In batch mode Leo does not show any windows. Leo assumes the scriptFile contains a Python script and executes the contents of that file using Leo's ``Execute Script`` command. By default, Leo sends all output to the console window. Scripts in the scriptFile may disable or enable this output by calling ``app.log.disable`` or ``app.log.enable``

Scripts in the scriptFile may execute any of Leo's commands except the ``Edit Body`` and ``Edit Headline`` commands. Those commands require interaction with the user. For example, the following batch script reads a Leo file and prints all the headlines in that file::

path = r"c:\prog\leoCVS\leo\test\test.leo"

g.app.log.disable() # disable reading messages while opening the file flag,newFrame = g.openWithFileName(path,None) g.app.log.enable() # re-enable the log.

for p in newFrame.c.allNodes_iter(): g.es(g.toEncodedString(p.headString(),"utf-8"))
Sometimes the code in an @test or @suite node requires other nodes. The @unit-test node groups nodes so that all nodes are available when running unit tests. That is, all nodes in an @unit-test are copied to test/DynamicUnitTest.leo. (See `How the unit test commands work`_ for full details.)
Leo is not your ordinary text editor, class browser, project manager or database manager, though it resembles these programs in some respects. Understanding what Leo is does take some work: many people have reported an 'Aha!' experience when they first understand what Leo is all about.

Leo is built on simple foundations:

- Leo is an outliner. All Leo data resides in an `outline`_. Outlines can contain text, computer programs, web sites, pictures, or any other kind of data. Leo can show such information, including pictures and movies, directly in the outline.

- Using `cloned nodes`_, you can put the same information (outline node) in multiple places. You don't have to decide, once and for all, where the 'right' place to put data: you can 'file' information in as many places as you like. But Leo is more than just the ultimate filing cabinet. Using clones, an outline can, in effect, show multiple views of the data *in that outline*. Again, you do not have to decide, once and for all, which is the 'right' view. You can have as many views as you like. For example, suppose you have an outline that contains all of your slides (or links to them.) Using clones, any of your slides could appear in as many slideshows as you like.

These features allow you to organize personal information such as web links or pictures. Other features make Leo a powerful environment for programming and web development:

- Unlike most file and class browsers, Leo has a memory. Leo allows you complete freedom to organizer and reorganize your outline as you like. Leo remembers the organization and expansion state of your outline when you save it, and restores the outline and expansion state when you reload the outline.

- Leo is a virtual file system and data manager. Leo can generate files based on data contained in outline. Such `derived files`_ can contain anything that the outline contains: text, computer programs, pictures, etc.

- You can use outlines to organize your programs, data and scripts. Using a markup language based on noweb_, you can easily tell Leo how to assemble programs and scripts from text in a portion of an outline.

- Leo's import commands convert already-existing programs into Leo pre-organized outlines, much like class browsers do. Unlike class browsers, you are then free to reorganize the outline so that it is easy to understand. This is a great way to study other people's programs.

- The structure of Leo outlines is directly accessible to Python scripts. Scripts can directly access all nodes (headlines and body text) of an outline. There is no need to 'parse' data into constituent parts. Furthermore scripts can easily insert, delete and move nodes. For example, unit tests can create nodes that represent the expected result of a unit test.

- Any Leo script can easily be applied to a selected part of the outline. This is an incredibly powerful and flexible feature. For example, it is very easy to create 'text editing' scripts that automate tedious, repetitive programming tasks.

- It is easy to write `plugins`_ to alter any aspect of Leo's operation. Dozens of plugins already exist.

- Nodes naturally represent both data (body text) and its description or meta-data (headline). By convention, many plugins and commands look for headlines of the form @x. Examples include @test and @suite for unit tests, @url for web links, @slideshow and @slide for groups of slides, @auto for automatically imported files, @folder for nodes created automatically from a folder on the computer's file system, and many others. Two kinds of meta-data deserve special mention. Unit tests can easily define their own meta-data, such as 'before' and 'after'. These data describe the initial conditions of the unit tests and the expected result. The @rst plugin uses various kinds of @rst nodes to organize `reStructuredText`_ and to control how that text is organized. For full details, see `Chapter 14: Using the Rst3 Plugin`_.

- Leo coexists well with other editors such as Emacs and Vim. Leo has several plugins that allow you easily to switch between Emacs (or Vim) and Leo. Moreover, Leo allows you complete flexibility to use the key bindings you like.

Several people have asked me, "How can Leo help me with programming?". Here is a short answer that summarizes the discussion so far:

- Leo's outlines allow you to see the organization of complex programs more clearly than with any other tool.

- Leo's allows you to organize programs and scripts more flexibly than with any other tool. In particular, noweb is a perfect match for outlines.

- Leo scripts are much more powerful than in other scripting environments because Leo scripts have easy access to headlines and data without having to parse data. **Outline structure is real data**: scripts can easily access the parents and descendants of any node. The practical benefits are almost endless.

- You can do things with Leo that are not possible with Emacs or Vim. In fact, you can do things with Leo that are not even *conceivable or expressible* with Emacs or Vim.

One last word. Leo has a strong and active community of users on `SourceForge`_. Working with this community has been a constant source of joy and inspiration. Suggestions and plugins from users continue to drive Leo in excellent new directions. Who knows what the next plugin will bring? -- Edward K. Ream
@language rest
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|prev| |leo| |next|

############ Preface ############

.. links...

.. _`SourceForge`: http://sourceforge.net/projects/leo/ .. _`noweb`: http://www.eecs.harvard.edu/~nr/noweb/ .. _reStructuredText: http://docutils.sourceforge.net/rst.html

.. _outline: intro.html#introduction .. _plugins: intro.html#plugins-settings .. _scripting: intro.html#scripting-leo .. _users: http://sourceforge.net/projects/leo/

.. _`cloned nodes`: intro.html#clones-views .. _`derived files`: intro.html#derived-files

.. _`Chapter 14\: Using the Rst3 Plugin`: rstplugin3.html

.. WARNING: image targets may not have upper case letters!

.. |leo| image:: leo.gif :target: front.html

.. |prev| image:: arrow_lt.gif :target: leo_TOC.html

.. |next| image:: arrow_rt.gif :target: testimonials.html
----------------

|prev| |leo| |next|
Leo 4.4.3.1 July 3, 2006

Leo 4.4.3.1 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.3.1: ---------------------------- - Fixed a few minor bugs reported since Leo 4.4.3 was released. - Added better support for unit testing in Leo.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
It's a bit tricky to ensure that leo/src is in sys.path The code now changes the working directory to leo/src, and leoDynamicTest.py adds os.getcwd() to sys.path if it is not there.

https://sourceforge.net/forum/message.php?msg_id=4385604
Misspelled words were not selected properly on Linux.
http://sourceforge.net/forum/message.php?msg_id=4385699
Moving into a chapters node from the main chapter did an automatic hoist.
- Made inter-outline moves & copies work again. - Also, warn that inter-outline clones transfer have no effect. - Note: none of these operations are presently undoable.

In short, this code is no worse than it has ever been.
# Added calls to c,p = g.getTestVars()

(fixed) leoNodes.py:2801: No global (p) found (fixed) leoNodes.py:2804: No global (c) found

(fixed) leoConfig.py:1739: No global (c) found

(fixed) leoKeys.py:4446: No global (c) found

(fixed) leoEditCommands.py:7823: No global (c) found (fixed) leoEditCommands.py:8508: No global (e) found
def es_print(s,*args,**keys):

print g.toEncodedString(s,'ascii')

if g.app.gui and not g.app.gui.isNullGui and not g.unitTesting: g.es(s,*args,**keys)
if g.unitTesting: if 0: # Not usually enabled. g.es_print('\ntest of es_print: Ă',color='red')
def es(s,*args,**keys): # print 'es','app.log',repr(app.log),'log.isNull',not app.log or app.log.isNull,repr(s) log = app.log if app.killed: return newline = keys.get("newline",True) color = keys.get('color') tabName = keys.get('tabName','Log') # Default goes to log pane *Not* the presently active pane. if color == 'suppress': return # New in 4.3. if type(s) != type("") and type(s) != type(u""): # 1/20/03 s = repr(s) for arg in args: if type(arg) != type("") and type(arg) != type(u""): # 1/20/03 arg = repr(arg) s = s + ", " + arg if app.batchMode: if app.log: app.log.put(s) elif g.unitTesting: if log and not log.isNull: s = g.toEncodedString(s,'ascii') if newline: print s else: print s, else: if log and log.isNull: pass elif log: # print 'g.es',s log.put(s,color=color,tabName=tabName) for ch in s: if ch == '\n': log.newlines += 1 else: log.newlines = 0 if newline: g.ecnl(tabName=tabName) # only valid here elif newline: app.logWaiting.append((s+'\n',color),) # print s else: app.logWaiting.append((s,color),) # print s,
For full details, see Chapter 20: Unit testing with Leo.
It is essential to protect them with::

if g.unitTesting:

A new unit test ensures that this is so.
http://sourceforge.net/forum/message.php?msg_id=4382336
As described later, Leo's unit tests commands copy various nodes to test/dynamicUnitTest.leo, and then run these unit tests in a separate process.

The run-all-unit-tests command copies all @test, @suite nodes @unit-tests trees and their descendants to test/dynamicUnitTest.leo.

The run-unit-tests command searches for copies nodes to test/dynamicUnitTest.leo as follows:

1. The run-unit-test command copies all @test and @suite nodes in all @mark-for-unit-tests trees.

2. The run-unit-test command copies all @test and @suite nodes in the presently selected tree. If the presently selected tree contains no such tree, it looks up the tree looking for @test, @suite and @unit-test nodes. If such a node is found, the run-unit-test command copies all @test and @suite nodes in the nodes tree.

In practice, these rules usually run the intended unit tests, namely all tests in @mark-for-unit-tests trees and all unit tests 'near' the presently selected node.
Leo's **unit test commands** run the unit tests created by @test and @suite nodes. run-unit-tests and run-unit-tests-locally run all unit tests in the presently selected part of the Leo outline; run-all-unit-tests and run-all-unit-tests-locally run all unit tests in the entire Leo outline.

**You must be running Leo from a console to see the output the unit tests**. Leo's unit test commands run all the unit tests using the standard unittest text test runner, and the output of the unit tests appears in the console.

test/unitTest.leo contains many examples of using @test and @suite nodes.
Why, oh why, would anyone be interested in Leo? After all, Emacs and Vim are superb text editors, and Visual Studio and Eclipse are great IDE's. How can Leo possibly compete with such strong competition? What does Leo offer that these other tools don't?

Leo does have something unique to offer--something missing from Emacs,Vim, Visual Studio and Eclipse. Leo's users often speak of an Aha! moment when they understand what this 'something' is. The Aha! arises from considering programs, design and data in a new light. You might call this 'The Leo Way'. In essence, Leo shows that computer programs, designs and data are *not*, after all, mostly about text. Yes, people usually *express* programs, designs and data as text. Yes, people manipulate programs, designs and data *using* text, but *text is not the whole story*.

In The Leo Way, text is simply a manifestation (a shadow) of something more fundamental. That 'something else' might be called 'organization' or 'structure' or 'views' or even 'architecture'. However, let us use the term **node** to represent the fundamental unit of structure in Leo. We'll see why in a moment.

In architectural terms, nodes are bricks that make up a building. In computer programming terms, nodes make up methods, classes, files and entire applications. So the term 'node' does *not* have a fixed meaning--it is simply a unit of organization. Any node can be built from other nodes, and any node can be used by any other node. Leo represent nodes directly, as nodes (headlines) in an outline. An outline node contains a headline and body text. The **outline pane** shows all headlines; the **body pane** shows the body text of the presently selected node.

**Outline structure is real data**

To repeat: the fundamental unit in Leo is *not* text. True, headlines and body *consist* of text, but a node is just not text, it is a true (Python) object. This means several specific things:

1. Because nodes are true objects, Leo commands understand what a node is, and where a node fits into the entire outline. I'll say more about outline organization soon, but let me give an example. Every node has exactly one parent node, (except for top-level nodes that have no parents) and every node has zero or more children and zero or more siblings. A node's parent, children and siblings are real properties of the node, *completely independent* of the node's headline or body text. Furthermore, any of Leo's commands (or user-written scripts or plugins, the big sisters of user scripts.) can *easily* access the all aspects of an outline *without* having to parse any text whatsoever. Commands, scripts and plugins can easily do the following: get the root of the outline, the presently selected node in the outline, the parent, siblings, children or descendants of any node in the outline, etc., etc. Commands, scripts and plugins can easily insert, delete or move nodes, and can alter the headline or body text in any node. All this *without* parsing text.

2. Having nodes be true objects means that commands scripts and plugins can treat the headline text as *something truly different from* body text. The natural interpretation of headline text is as a description of the body text. This is important! Headlines often control Leo's commands. For example, headlines that start with @thin, @file, @asis, @auto, etc. serve to guide and control Leo's read and write commands. Headlines that start with @test, @suite and @mark-for-unit-tests guide Leo's unit testing commands. Moreover, it is easy to create new conventions for headlines that control user-written scripts or plugins. For example, plugins define specific meanings for headlines that start with @url, @rst, @bookmark, @slideshow, etc., etc. So the separation of headline and body text, **as true components of a node object**, is a very big deal.

3. One application of these ideas deserves special mention. Leo's scripting plugin provides support for @button nodes. The headline is @button <command-name>. The body text contains a script. When Leo opens a Leo outline, each @button node creates a command and an icon. Clicking the icon (or executing the command) applies the script in the @button node **to the presently selected outline**. That is, the script is executed in a context in which it is easy to get access to all aspects of the outline in which the script is embedded. This is a major advance in scripting. It allows you to 'bring scripts to data', i.e., any part of an outline. In particular, it is very easy to create **editing scripts** that automate what would otherwise be boring and repetitive editing tasks.

**Leo outlines aren't your average outline**

Earlier I said that *any* node can be built from other nodes, and *any* node can be used by any other node. It takes a very special kind of outline for this to be possible. In a typical outline, such as Emacs outline mode, for example, nodes appear exactly once in the outline. This makes it impossible to 'reuse' nodes in multiple places. Leo removes that limitation: any outline node can be **cloned**, and clones can appear in as many places in an outline as you like.

Cloned nodes are distinct: they must be distinct so they can be moved throughout the outline, but **cloned nodes share all their information**. That is, changing the headline or body text in a node instantly changes the headline and body text in all the other nodes cloned to it. Furthermore, similar remarks apply to the children and descendants of any node--changing any child (or other descendant) of a node, say node A, instantly makes corresponding changes to all nodes cloned to node A.

Earlier I said that you can think of nodes as representing 'organization' or 'structure' or 'views' or even 'architecture'. Clones are the crucial feature that allows this point of view. For example, we can build up multiple 'views' of data in an outline using clones as follows:

- Create a 'view node' that will represent a *user-specified* view.

- Clone all nodes that are to be part of the view, and move them so that each clone is a child of the view node.

That's about all there is to it. The view node, and its children *is* a new view of the outline. This notion of 'view' is so important that Leo supports it directly. Leo's **chapters** are simply views created as I have just described. When you select one chapter, you only see the nodes of that chapter in Leo's outline pane.

**Conclusions & encouragements**

So Leo offers a new way to understand, organize and manipulate *any* kind of complex data, including computer programs, *designs* of computer programs, web sites, personal data, whatever. The Aha that I invite you to experience is this: Outlines are more than mere eye candy. Having organization be real data creates an entirely new dimension, literally and figuratively, in computer programming, computer design and data organization, including web-site design, database design, etc. Leo's commands use headline and body text in many creative ways. So can you and your scripts. It's easy, it's fun, and it's revolutionary.

That's about it, except for some words of caution and advice:

1. Leo has been under active development for over 10 years. The new world created by nodes is rich and varied. You won't learn it all in a day or so. Please be patient. Start by learning Leo's basic features as explained in the tutorial. You can learn more advanced features later.

2. Those of you who are comfortable with Emacs should feel pretty much at home with Leo. Leo has shamelessly stolen the best features of Emacs, including the minibuffer and many Emacs-like commands.

3. For those of you who are *not* comfortable with Emacs, please understand that you do *not* need to understand all of Leo's commands in order to use Leo. Start by ignoring the minibuffer. Later, the minibuffer can become your friend, but you can get the Aha! without it.

Edward K. Ream July, 2007
This section contains code-level notes for the threading colorizer. You do not need to understand this material in order to use the threading colorizer.

The threading_colorizer plugin uses a separate **helper thread** to compute the ranges of text that should be colored. **The helper thread must not contain any calls to Tk**. Tk is not thread safe--calling Tk in the helper thread will cause hard crashes in the Tk dll. However, the code in the helper thread is gui independent. The **main thread** contains all of Leo's code except for a helper thread. The main thread contains all calls to Tk, all entry points to the colorizer, and idleHandler, an idle-time handler.

Only one helper thread is ever active at any one time. If a keystroke occurs while the helper thread is active, the colorizer code in the main thread sets the killFlag ivar and calls join to wait for the helper thread to terminate. The helper thread will terminate promptly because it looks at killFlag each time through its main loop. Using a separate helper thread allows the main thread to continue working while the helper thread computes. This allows Tk (in the main thread) to respond to events. This in turn allows the colorizer code in the main thread to kill the helper thread if it is still working.

The helper thread runs to completion before the main thread uses any of its results. Thus, no thread locking is needed, an important simplification. Once the helper thread completes, the main thread computes the tags to be sent to Tk, and actually sends those tags. When the user is typing rapidly, the colorizer will ignore the results of all helper threads except the last.

After the helper thread generates the list of all requested tags, the main thread uses a kind of sort-merge algorithm to compare the existing tags (obtained from Tk) with the requested tags. In many cases, the lists are the same and colorizer issues *no* calls to Tk. This is a sensational optimization. It absolutely minimizes the load on Tk.

When the 'interruptible' argument to the colorizer is False, no threading is used and the main thread completely colors the entire text. This must be done when multiple body editors are present.
The run-unit-tests command now includes *all* @mark-for-unit-test trees.
The old __jEdit_colorizer__.py plugin has been retired.
Leo 4.4.4 beta 1 August 10, 2007

Leo 4.4.4 beta 1 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.4: ----------------------------

- A threading_colorizer plugin replaces the __jEdit_colorizer__ plugin. This plugin features much better performance.

- Support for @auto nodes. Such nodes allow people to collaborate using Leo without inserting Leo sentinels in the files Leo generates.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
@auto trees allows people to use Leo in collaborative environments without using sentinels in the files Leo generates. In contrast to @nosent, @auto trees can change when the corresponding file changes outside of Leo.

Leo will automatically recreate (import) all @auto trees when reading a .leo file, and will write all dirty @auto trees when saving a .leo file. There are two exceptions to this statement:

1. Leo will never read (import) or write an @auto tree if the root @auto tree is under the influence of an @ignore directive.

2. Saving a .leo file does not save @auto nodes if a) they haven't been changed or b) they do not contain a **significant** amount of information. An @auto tree contains a significant amount of information if it has children or if the root node contains more than 10 characters.

Leo creates @auto trees by parsing the corresponding derived file. Parsers create descendant nodes of the @auto tree: one node for each class, method and function in the derived file.

Parsers presently exist for C, elisp, Java, Pascal, PHP and Python. Leo determines the language using the file's extension. If no parser exists for a language, the entire body of an @auto tree contains a significant amount of information if it has any children or if the root node contains more than 10 non-blank lines. the derived file is copied to the body of the @auto node.

Leo does not write the contents of @auto trees to .leo files. In this respect, @auto trees work much like @thin trees. @auto trees whose root node is under the scope of an @ignore directive *will* be written to the .leo, just like @thin trees.
All present parsers are short overrides of a powerful base parser class. Thus, it would be simple to add support for other languages. See the node

@thin leoImport.py-->Import-->Scanners for createOutline

in leoPy.leo to see how easy it is to create new parsers.

Three new commands in the File:Read/Write menu allow you to manually read and write @auto nodes from the presently selected outline. As always, an @ignore directive in the @auto node or its ancestors will suppress any of these commands:

- The Read @auto Nodes (read-at-auto-nodes) command reads all @auto nodes in the presently selected outline. An @ignore directive will suppress this import.

- The Write @auto Nodes (write-at-auto-nodes) command writes all @auto nodes. An @ignore directive will suppress this import. Caution: the write will occur even if Leo has not previously read the @auto node.

- The Write Dirty @auto Nodes (write-dirty-at-auto-nodes) is the same as the write-at-auto-nodes command, except that only changed @auto trees are written.

Most users will rarely use these explicit commands, because reading and writing .leo files handles @auto nodes well enough. However, you can use the read-at-auto-nodes command to update @auto nodes without having to reload the .leo file.
Leo performs several checks to ensure that the result of importing an external file will be equivalent to the file that writing the @auto tree would produce.

These checks can produces **errors** or **warnings**. Errors indicate a potentially serious problem. Leo inserts an @ignore directive in the @auto tree if any error is found. This @ignore directive prevents the @auto tree from modifying the external file. If you @ignore directive, a later write of the @auto tree will attempt to fix the problems that gave rise to the errors. There are no guarantees however.

**Strict languages** are languages like Python for which leading whitespace is especially significant. Before importing a file for a strict language, Leo **regularizes** the leading whitespace of all lines of the original source file. That is, Leo converts blanks to tabs or tabs to blanks depending on the value of the @tabwidth directive in effect for the @auto node. Leo cannot guarantee to reproduce the original source file exactly if problems are discovered while regularizing leading whitespace.

After importing a file, Leo verifies that writing the @auto node would create the same file as the original file. For strict languages, the comparison must be exact, or nearly so. For non-strict languages, differences in leading whitespace generate warnings, not errors.

File comparison mismatches can arise for several reasons:

1. Bugs in the import parsers. Please report any suspected bugs immediately.

2. Underindented lines in classes, methods or functions in strict languages. An **underindented line** is a line that is indented less then the starting line of the class, method or function in which it appears. Leo outlines can not represent such lines exactly: every line of node implicitly has at least the indentation of any unindented line of the node.

Leo will issue a warning (not an error) for underindented Python comment lines. Such lines can not change the meaning of Python programs.
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|prev| |leo| |next|

########################################## What's New in Leo 4.4.4 ##########################################

Leo 4.4.4 contains many important features originally planned for later releases. The highlights of Leo 4.4.4:

- **The Great Graph Aha**: A Leo outline doesn't have to *be* an arbitrary graph in order to *represent* an arbitrary graph.

That is, simple scripts allow Leo outlines to represent arbitrary directed graphs. There is no need for a separate 'graph world'. The graphed.py plugin is a direct result of this Aha. It allows you to create general graphs from Leo outlines.

- Support for **@auto nodes**. Such nodes allow people to collaborate using Leo without inserting Leo sentinels in the files Leo generates.

- **@menus trees** in settings files create all of Leo's menus. It is now dead easy to make Leo's menus look the way you want.

- **@buttons trees** in settings files create common @button nodes created in all Leo outlines.

- A new, faster, **colorizer plugin** replaces the __jEdit_colorizer__ plugin.

- New commands for **resolving cvs conflicts**.

- Leo's core is now compatible with jython.

.. contents::
.. Links used in this document.

.. _`leoBridge chapter`: leoBridge.html .. _`debugging with Leo`: debuggers.html

.. WARNING: image targets may not have upper case letters!

.. |prev| image:: arrow_lt.gif :target: new-4-4-5.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: new-4-4-3.html
::

check-derived-file check-leo-file compare-leo-outlines insert-child read-at-auto-nodes read-file-into-node write-at-auto-nodes write-dirty-at-auto-nodes write-file-from-node
- The graphed plugin allows users to manipulate parts of Leo outlines as if they were general graphs. It is still early days for this exciting plugin.

- The threading_colorizer plugin replaces the __jEdit_colorizer__ plugin. This plugin features an elegant new algorithm that has much better performance and eliminates almost all flash.
- See the release notes for a list of bugs fixed in Leo 4.4.4.

- Added the 'clear-all-marks' hook.

- Added button font setting. See the node: "@settings-->Fonts-->@font button font" in leoSettings.leo.

- Plugins and scripts may call the c.frame.canvas.createCanvas method to create a log tab containing a Tk.Canvas widget. Here is an example script::

log = c.frame.log ; tag = 'my-canvas' w = log.canvasDict.get(tag) if not w: w = log.createCanvas(tag) w.configure(bg='yellow') log.selectTab(tag)

- Improved the yank and yank-pop commands and added @bool add_ws_to_kill_ring setting.

- Improved the debug command: it now adds the following code to the beginning of debug scripts::

class G: def es(s,c=None): pass g = G()

- Added the @bool rst3 strip_at_file_prefixes setting.

- Added the g.app.inBridge ivar.

- Added @bool big_outline_pane setting. False (legacy): Top pane contains outline and log panes. True: Top pane contains only the outline pane. Bottom pane contains body and log panes.
-----------------------

|prev| |leo| |next|
@auto trees allow people to use Leo in collaborative environments without using sentinels in the files Leo generates. In contrast to @nosent, @auto trees can change when the corresponding file changes outside of Leo.

Leo will automatically recreate (import) all @auto trees when reading a .leo file, and will write all dirty @auto trees when saving a .leo file. There are two exceptions to this statement:

1. Leo will never read (import) or write an @auto tree if the root @auto tree is under the influence of an @ignore directive.

2. Saving a .leo file does not save @auto nodes if a) they haven't been changed or b) they do not contain a **significant** amount of information. An @auto tree contains a significant amount of information if it has children or if the root node contains more than 10 characters.

Leo creates @auto trees by parsing the corresponding derived file. Parsers create descendant nodes of the @auto tree: one node for each class, method and function in the derived file.

Parsers presently exist for C, elisp, Java, Javascript, Pascal, PHP, Python and xml. Leo determines the language using the file's extension. Notes:

- If no parser exists for a language, the entire body of the derived file is copied to the body of the @auto node.

- Javascript regexps that look like section references cause problems, but that can not be helped.

- Use the @data import_xml_tags setting in leoSettings.leo to specify the xml tags that create outline nodes. By default, the **organizer tags** are html, body, head, and div.
Leo performs several checks to ensure that the result of importing an external file will be equivalent to the file that writing the @auto tree would produce.

These checks can produces **errors** or **warnings**. Errors indicate a potentially serious problem. Leo inserts an @ignore directive in the @auto tree if any error is found. This @ignore directive prevents the @auto tree from modifying the external file. If you @ignore directive, a later write of the @auto tree will attempt to fix the problems that gave rise to the errors. There are no guarantees however.

Before importing a file, Leo **regularizes** the leading whitespace of all lines of the original source file. That is, Leo converts blanks to tabs or tabs to blanks depending on the value of the @tabwidth directive in effect for the @auto node. Leo also checks that the indentation of any non-blank line is not a multiple of the indentation specified by the @tabwidth directive in effect for the @auto node.

Leo cannot guarantee to reproduce the original source file exactly if problems are discovered while regularizing leading whitespace. **Strict languages** are languages such as Python for which leading whitespace must be preserved exactly as it appears in the original source file. Problems during regularizing generate errors for strict languages and warnings for non-strict languages.

After importing a file, Leo verifies that writing the @auto node would create *exactly* the same file as the original file. Such file comparison mismatches generate errors unless the problem involves only leading whitespace for non-strict languages. Whenever a mismatch occurs the first non-matching line is printed.

File comparison mismatches can arise for several reasons:

1. Bugs in the import parsers. Please report any suspected bugs immediately.

2. Underindented lines in classes, methods or function. An **underindented line** is a line that is indented less then the starting line of the class, method or function in which it appears. Leo outlines can not represent such lines exactly: every line of node implicitly has at least the indentation of any unindented line of the node.

Leo will issue a warning (not an error) for underindented Python comment lines. Such lines can not change the meaning of Python programs.
Three commands in the File:Read/Write menu allow you to manually read and write @auto nodes from the presently selected outline. As always, an @ignore directive in the @auto node or its ancestors will suppress any of these commands:

- The Read @auto Nodes (read-at-auto-nodes) command reads all @auto nodes in the presently selected outline. An @ignore directive will suppress this import.

- The Write @auto Nodes (write-at-auto-nodes) command writes all @auto nodes. An @ignore directive will suppress this import. Caution: the write will occur even if Leo has not previously read the @auto node.

- The Write Dirty @auto Nodes (write-dirty-at-auto-nodes) is the same as the write-at-auto-nodes command, except that only changed @auto trees are written.

Most users will rarely use these explicit commands, because reading and writing .leo files handles @auto nodes well enough. However, you can use the read-at-auto-nodes command to update @auto nodes without having to reload the .leo file.
You enable or disable plugins using @enabled-plugins nodes in leoSettings files (leoSettings.leo, myLeoSettings.leo or the .leo file being loaded). See `Specifying settings`_ for full details of settings files.

The body text of the @enabled-plugins node contains a list of enabled plugins. Notes:

- Leo attempts to load all plugins every time an @enabled-plugins node is seen. If the plugin has already been loaded, Leo silently ignores the request to re-enable the plugin. Leo never attempts to disable a plugin while processing enabled plugin strings. Thus, plugins enabled in an @enabled-plugins node in leoSettings.leo *will* be enabled regardless of the contents of any other @enabled-plugins node.

- g.app.gui.getEnabledPlugins contains the last value last processed @enabled-plugins node, or the contents of the first pluginsManager.txt file encountered.
Question and answer from plumloco.

Add the equivalent of::

import sys leosrc = "path/to/leo/src" if leosrc not in sys.path: sys.path.append(leosrc) import leoBridge

at the head of each file that uses leoBridge.

The problem is not importing leoBridge itself but (if I use 'from leo.src') the importing of plugins, who get a different leoGlobals from leoBridge, without g.app etc, and so do not work if they rely on dynamic values in g.etc.

> Why can't you simply add leo/src to sys.path in sitecustomize.py?

Putting leo\src on the python path as you suggest would put forty python modules in the global module namespace for all python programs when I want just one. Also, I have a safe working copy of leo and a cvs/testing version. I would wish to test any programs against the testing version while using the working version, but both /src directories can't be exposed at the same time.

> Do you need plugins while running from the leoBridge?

Afraid so, at least the rst3 plugin. The solution I am using now is to place::

sys.modules['leoGlobals'] = leoGlobals

in leoBridge after import leoGlobals.

This, together with placing an empty __init__.py in leo/src, allows my scripts to be portable over the several computers/platforms I need to use them on, and makes testing scripts against multiple leo versions easy. It does mean that my scripts are not portable to other leo users but that is not likely to be a problem.
Email from Terry Brown

A softish bug, but the use of findNodeInTree() in the UNL code can take you to the wrong place if more than one node in the tree has the same headString. Patch below - can still go wrong if more than one sibling has the same name, but the UNL system doesn't have a solution for that.

An observation - the UNL jumping code will drop you as far down the path as it gets, i.e. you're moved to the last node that was one the path, even if the path ends before the last part of the UNL is reached. This is ok, i.e. "this is as far as I could follow the UNL", the alternative would be to not move at all if the whole UNL can't be followed.

Cheers -Terry

anon_cvs> cvs diff leo/plugins/UNL.py Index: leo/plugins/UNL.py =================================================================== RCS file: /cvs/leo/plugins/UNL.py,v retrieving revision 1.14 diff -r1.14 UNL.py 183c183,186 < p = g.findNodeInTree(c2,p,headline) --- > for tmpp in p.copy().children_iter(): > if tmpp.headString() == headline: > p = tmpp > break 206c209,212 < p = g.findNodeInTree(c,p,headline) --- > for tmpp in p.copy().children_iter(): > if tmpp.headString() == headline: > p = tmpp > break

http://sourceforge.net/forum/message.php?msg_id=4444579
http://sourceforge.net/forum/message.php?msg_id=4445685
http://sourceforge.net/forum/message.php?msg_id=4446937
# The code that was removing tags was not working properly.
http://sourceforge.net/forum/message.php?msg_id=4437415
http://sourceforge.net/forum/message.php?msg_id=4462693
http://sourceforge.net/forum/message.php?msg_id=4464980
@nocolor

http://sourceforge.net/forum/message.php?msg_id=4465132 By: terry_n_brown

So I changed all my indentation to multiples of four, having decided I like the extra line space this buys over aligning with the opening (.

leo said this when it read the file:

@auto did not import the file perfectly

but never mentioned @ignore or anything. I made a trivial change and saved and diff could find no difference except my trivial change... which seems perfect to me...?

@color
https://sourceforge.net/forum/message.php?msg_id=4459798
http://sourceforge.net/forum/message.php?msg_id=4509897
http://sourceforge.net/forum/message.php?msg_id=4514130
http://sourceforge.net/forum/message.php?msg_id=4468174
When saving a .leo file, Leo now *reads* an @auto node if

1) the derived file exists, 2) an 'insignificant' amount of data exists in the @auto tree, and 3)the @auto node has not been read previously.

This promises to fix some quite awkward use cases.

The 'perfect import' code now is a bit more relaxed, especially for 'non-strict' languages (all languages except Python):

- Leo leaves leading whitespace alone for non-strict languages.

- Leo complains about intermixed tabs and blanks in leading whitespace only for strict languages.

- Leo ignores leading whitespace in the perfect import tests for non-strict languages.

These changes mean that Leo might change a derived file if such a change occurs only in leading whitespace in a non-strict language.
Leo 4.4.4 beta 2 September 19, 2007

Leo 4.4.4 beta 2 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.4: ----------------------------

- A threading_colorizer plugin replaces the __jEdit_colorizer__ plugin. This plugin features much better performance.

- Support for @auto nodes. Such nodes allow people to collaborate using Leo without inserting Leo sentinels in the files Leo generates.

- New commands for resolving cvs conflicts.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
The so-called resolve-cvs-conflict project has resolved itself into small, easily understood commands.

The **read-file-into-node** command prompts for a filename, and creates an node whose headline is @read-file-into-node <filename> and whose body text is the entire contents of the file.

The **write-file-from-node** command writes the body text of the selected not to a file. If the headline of the presently selected node starts with @read-file-into-node the command use the filename that follows in the headline. Otherwise, the command prompts for a filename.

When a cvs conflict occurs, the user will:

- read the file into a node using the read-file-into-node command,

- fix the conflict, as with any other editor, and

- write the file with the write-file-from-node command.

Any file can be fixed in this way, including derived files and .leo files. The only complication is that the user must not change sentinel lines. Two new commands check the contents of a node: The **check-derived-file** and **check-leo-file** commands tell whether a trial read of the presently selected node can be done successfully. The check-derived-file command assumes the body text is a derived file; the check-leo-file command assumes the body text is an entire .leo file.

The **compare-leo-outlines** command prompts for another (presumably similar) .leo file that will be compared with the presently selected outline file (main window). It then creates clones of all inserted, deleted and changed nodes.
All @buttons tree in a settings file defines global buttons that are created in the icon area of all .leo files. You define @button nodes in the @buttons tree as usual.
Leo 4.4.4 beta 3 October 23, 2007

Leo 4.4.4 beta 3 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo 4.4.4 contains many important features originally planned for later releases. It's been a good month :-)

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.4: ----------------------------

- The Great Graph Aha (tm): simple scripts allow Leo outlines to represent arbitrary directed graphs. There is no need for a separate 'graph world'. The graphed.py plugin is a direct result of this Aha. The graphed.py plugin allows you to create general graphs from Leo outlines.

- @menus trees in settings files create all of Leo's menus. It is now dead easy to make Leo's menus look the way you want.

- @buttons trees in settings files create common @button nodes created in all Leo outlines.

- @auto nodes eliminate sentinels in derived files, thereby allowing people to collaborate using Leo more easily.

- New commands for resolving cvs conflicts.

- A threading_colorizer plugin replaces the __jEdit_colorizer__ plugin. This plugin features much better performance and a new, elegant algorithm.

- Leo is now compatible with jython.

- The usual assortment of bug fixes and other minor improvements.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
http://sourceforge.net/forum/message.php?msg_id=4543844
See the node:

@settings-->Fonts-->@font button font

in leoSettings.leo.
@button nodes in the @buttons tree in settings file define **global buttons** that appear in all Leo outlines.
Leo creates its menus using @menus trees. Within @menus trees, @menu nodes create menus and @item nodes create menu items.

Notes:

- The menu name always follows @menu. If the menu name is 'Plugins', Leo will create the Plugins menu and populate the menu by calling the 'create-optional-menus' hook. This creates the Plugins menu as usual.

- Nested @menu nodes contain submenus.

- The command name follows @item. If the body text of an @item node exists, this body text is the menu name. Otherwise, the menu name is the command name. However, if the command name starts with a '*', hyphens are removed from the menu name.

- Menu names and command names may contain a single ampersand (&). If present, the following character is underlined in the name.

- If the command name in an @item node is just a hyphen (-), the item represents a menu separator.

- Unicode characters, e.g., Chinese characters *are* allowed.
The c.frame.logcreateCanvas convenience method create a canvas tab in the log pane. Here is a sample script:

log = c.frame.log ; tag = 'my-canvas'

w = log.canvasDict.get(tag) if not w: ..w = log.createCanvas(tag) ..w.configure(bg='yellow')

log.selectTab(tag)
The Great Graph Aha is:

A Leo outline doesn't have to *be* an arbitrary graph in order to *represent* an arbitrary graph.

So the graph world is unnecessary because we can use Leo nodes and trees as data to other graphing packages.** That is, Python scripts can build arbitrary graphs using Leo's existing nodes and trees. And Python scripts can manipulate those graphs. And Python scripts could do the reverse: manipulate the Leo outline by traversing general graphs. So there is no need to complicate Leo's fundamental data structures. Hurray! Instead, we build on the strengths of already existing graphing packages.

The Great Graph Aha created the opportunity for immediate action:

1. test.leo contains the essential scripts to implement graphs in Leo files. These short, simple, self-contained, easily modifiable scripts make possible everything ever envisaged by the (now-defunct) graph world project::

leo2graph: convert a normal Leo tree to a NetworkX graph. at-graph2graph: convert an @graph tree to a NetworkX graph. at-networkx2graph: convert an @networkx tree to a NetworkX graph at-networkx2at-graph: create an @graph tree from an @networkx tree.

2. The graphed plugin allows users to manipulate parts of Leo outlines as if they were general graphs. It is still early days for this exciting plugin.
The graphed plugin allows users to manipulate parts of Leo outlines as if they were general graphs. It is still early days for this exciting plugin.
Leo creates its menus from the @menu and @item nodes in the @menus tree. Within @menus trees, @menu nodes create menus and @item nodes create menu items.

The menu name always follows @menu. If the menu name is 'Plugins', Leo will create the Plugins menu and populate the menu by calling the 'create-optional-menus' hook. This creates the Plugins menu as usual. Nested @menu nodes define submenus.

The command name follows @item. If the body text of an @item node exists, this body text is the menu name. Otherwise, the menu name is the command name. However, if the command name starts with a '*', hyphens are removed from the menu name. Menu names and command names may contain a single ampersand (&). If present, the following character is underlined in the name. If the command name in an @item node is just a hyphen (-), the item represents a menu separator.
- Replaced all 'yield' statements with iterators.

- Added 'jyLeo' keyword to leo.run.

- All of Leo's startup code works with the swing gui enabled (jyLeo = True in leo.run).
Essentially all of Leo's startup code now runs with jython 2.2 and the (unfinished!) swing gui.
This inserts a child node.
Hurray--these are no longer needed.

The following methods exist for the convenience of plugins.

**g.enableIdleTimeHook(idleTimeDelay=100)**

Enables the "idle" hook. Afterwards, Leo will call the "idle" hook approximately every idleTimeDelay milliseconds. Leo will continue to call the "idle" hook periodically until ``disableIdleTimeHook`` is called.

**g.disableIdleTimeHook()**

Disables the "idle" hook.

**c.frame.menu.createMenuItemsFromTable (self,menuName,table,openWith=0)**

This method adds items to the menu whose name is menuName. The table argument describes the entries to be created. This table is a sequence of items of the form ``(name,None,command)``:

- ``name`` is the command name. - ``None`` was a shortcut in previous versions of Leo, but shortcuts for user-defined commands should now be defined in @shortcuts nodes. - ``command`` is the routine to execute when the menu item is selected. - An entry of the form ``("-",None,None)`` creates a separator line between menu items.

For example::

table = ("Toggle Active Pane",None,self.OnToggleActivePane), ("-",None,None), ("Toggle Split Direction",None,self.OnToggleSplitDirection)) c.frame.menu.createMenuItemsFromTable("Window",table)

If the ``openWith`` keyword argument is 1 the items are added to a submenu of the Open With menu. However, it will be more convenient to use the ``createOpenWithMenuFromTable`` method to create the ``Open With`` menu.

**c.frame.menu.createNewMenu (self,menuName,parentName="top")**

This method creates a new menu:

- menuName is the name of the menu to be created. - parentName is the name of the parent menu, or "top" if the menu is to created in the menu bar.

This method returns the menu object that was created, or None if there was a problem. Your code need not remember the value returned by this method. Instead, your code will refer to menus by name.

**c.frame.menu.createOpenWithMenuFromTable (self,table)**

This method adds items to submenu of the ``Open With`` menu item in the ``File`` menu. The table argument describes the entries to be created. This table is a sequence of items of the form ``(name,shortcut,data)``:

- name is the command name - shortcut is the shortcut, or None to indicate no shortcut. - data is a tuple of the form (command,arg,ext) - command is one of "os.system", "os.startfile", "os.spawnl", "os.spawnv" or "exec". - arg is an argument to be passed to the given command. - ext is a file extension or None.

When the user selects the ``Open With`` item corresponding to the table item Leo executes ``command(arg)``. If ``ext`` is not ``None``, the temp file has the given extension. Otherwise, Leo computes an extension based on what ``@language`` directive is in effect. For example::

table = ( ("Idle", "Alt+Shift+I",("os.system",idle_arg,".py")), ("Word", "Alt+Shift+W",("os.startfile",None,".doc")), ("Wordpad","Alt+Shift+T",("os.startfile",None,".txt")))

top().frame.createOpenWithMenuFromTable(table)

**c.frame.menu.deleteMenu (self,menuName)**

Deletes the menu whose name is given, including all entries in the menu.

**c.frame.menu.deleteMenuItem (self,itemName,menuName="top")**

Deletes the item whose name is itemName from the menu whose name is menuName. To delete a menu in the menubar, specify ``menuName="top"``.

**c.frame.menu.setRealMenuNamesFromTable(table)**

Translates names of menus and menu items into another language. For example::

table = ( ("Help", "&Aide"), ("About Leo...", "Au &sujet de Leo..."), ("Online Home Page", "&Page d'Accueil en ligne"), ("Open Online Tutorial", "Ouvrir &Tutoriel en ligne"), ("Open LeoDocs.leo", "Ouvrir Leo&Docs.leo"), ("Open LeoConfig.leo", "Ouvrir Leo&Config.leo"), ("Apply Settings", "Appliquer les &Réglages"), )

c.frame.menu.setRealMenuNamesFromTable(table)
Two methods in leoGlobals.py allow scripts and plugins to enable and disable 'idle' events. **g.enableIdleTimeHook(idleTimeDelay=100)** enables the "idle" hook. Afterwards, Leo will call the "idle" hook approximately every idleTimeDelay milliseconds. Leo will continue to call the "idle" hook periodically until disableIdleTimeHook is called. **g.disableIdleTimeHook()** disables the "idle" hook.
In some cases the find-previous command did not work.

After much investigation, the cause of the bug was found to be a blunder in backwardsHelper. Changed:

pattern.lower()

to:

pattern = pattern.lower()
There were at least 3 bugs:

At least three bugs.

- Place cursor on last (blank) line. Cursor up goes one line too far. - Place cursor at end of line 1. Second cursor down does nothing. - Place cursor at end of xxxx line. Second cursor down goes one line too far.

xxxxxxxxx line 1 line 2

The fix was to g.getLine--potentially a major change.
This should have been done long ago.
http://sourceforge.net/forum/message.php?msg_id=4573990
https://sourceforge.net/forum/message.php?msg_id=4576436
Optimized yank, by using yanked leading whitespace if it exists

New default bindings: Alt-Y: yank-pop. Alt-Ctrl-Y: cycle-all-focus.

New option: add-ws-to-kill-ring (or kill-ws-adds-to-kill-ring)
Suppressed doc-part-delims when show_doc_parts_as_paragraphs is True.
The new code is simple and elegant. Almost all flash is gone.
http://sourceforge.net/forum/message.php?msg_id=4568499

I like doctests, often debug with g.es() statements, and open winpdb to examine what's going on.

I've a small patch to the debug command leoEditCommands.py-->debugCommandsClass-->debug to simplify this.

The patch writes the following to the beginning of the script being debugged;

class G: def es(s,c=None): pass g = G()

This makes the g.es() statements legal.

The patch also checks for doctests in the script, and if found, converts them to regular code.

A node containing;

>>> import inspect, sys >>> insp = sys.modules['inspect'] >>> print insp.__name__ inspect >>> g.es(dir(insp))

can be run as a doctest; <alt x> dt (if the dtest.py plugin is active)

or sent to winpdb; <alt x> debug

The patch doesn't change the handling of regular scripts.

It goes right after; if not winpdb: return

#check for doctest examples try: import doctest parser = doctest.DocTestParser() examples = parser.get_examples(script)

# if this is doctest, extract the examples as a script if len(examples) > 0: script = doctest.script_from_examples(script)

except ImportError: pass

# special case; debug code may include g.es("info string") # insert code fragment to make this expression legal outside Leo hide_ges = "class G:\n def es(s,c=None):\n pass\ng = G()\n" script = hide_ges + script
From the documentation at: http://webpages.charter.net/edreamleo/rstplugin3.html#options

strip_at_file_prefixes (default: True)

True: remove @auto, @file, @nosent and @thin from the start of headlines.
This is used, at present, by g.getScript. It is a natural status ivar in any case.
- Use the term 'event handler' for hook. This is much better terminology.

- Move the discussion of event handlers to the scripting chapter.

- Removed the discussion of all menu convenience routines: they are not needed now that Leo supports @menus nodes.

- The 'writing plugins' chapter is now very simple.
The run-unit-tests command runs tests using the bridge, which uses a nullGui and a stringTextWidget.

Added a hack to g.getScript so it always gets the script from p.bodyString when g.app.gui.inBridge is True.
Leo 4.4.4 beta 4 October 27, 2007

Leo 4.4.4 beta 4 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

This beta 4 version fixes all bugs reported against Leo 4.4.4 beta 3.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

Leo 4.4.4 contains many important features originally planned for later releases.

The highlights of Leo 4.4.4: ----------------------------

- The Great Graph Aha (tm): simple scripts allow Leo outlines to represent arbitrary directed graphs. There is no need for a separate 'graph world'. The graphed.py plugin is a direct result of this Aha. The graphed.py plugin allows you to create general graphs from Leo outlines.

- @menus trees in settings files create all of Leo's menus. It is now dead easy to make Leo's menus look the way you want.

- @buttons trees in settings files create common @button nodes created in all Leo outlines.

- @auto nodes eliminate sentinels in derived files, thereby allowing people to collaborate using Leo more easily. **Warning**: for now, please make backup copies of files imported with @auto.

- New commands for resolving cvs conflicts.

- A threading_colorizer plugin replaces the __jEdit_colorizer__ plugin. This plugin features much better performance and a new, elegant algorithm.

- Leo is now compatible with jython.

- Better support for icons in headlines.

- The usual assortment of bug fixes and other minor improvements.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
Replaced the (useless) trace with an error message to the console window.
http://sourceforge.net/forum/message.php?msg_id=4574271
This should have been done a long time ago.
http://sourceforge.net/forum/message.php?msg_id=4585396

The threading colorizer must be run with interruptible=False when there are multiple body editors.
False (legacy): Top pane contains outline and log panes. True: Top pane contains only the outline pane. Bottom pane contains body and log panes.
To allow Python's print statement to print unicode characters properly, you must change Python's default encoding to something other than 'ascii'. To do this, put the following in your sitecustomize.py file in Python's Lib folder::

import sys sys.setdefaultencoding('utf-8') # 'iso-8859-1' is another choice.

You must restart Python after doing this: sys.setdefaultencoding can not be called after Python starts up.

Leo's g.es_print function attempts to convert incoming arguments to unicode using the default encoding. For example, the following Leo script always prints La Peña::

@first # -*- coding: utf-8 -*- # The line above is required for Python 2.5

for s in (u'La Pe\xf1a','La Peña',u'La Peña'): g.es_print(s)

For still more details, see:

http://www.diveintopython.org/xml_processing/unicode.html
First, you must change Python's default encoding to something other than 'ascii'. To do this, put the following in your sitecustomize.py file in Python's Lib folder::

import sys sys.setdefaultencoding('utf-8') # 'iso-8859-1' is another choice.

You must restart Python after doing this: sys.setdefaultencoding can not be called after Python starts up.

Leo's g.es_print function attempts to convert incoming arguments to unicode using the default encoding. For example, the following Leo script always prints La Peña::

@first # -*- coding: utf-8 -*- # The line above is required for Python 2.5

for s in (u'La Pe\xf1a','La Peña',u'La Peña'): g.es_print(s)

For still more details, see: http://www.diveintopython.org/xml_processing/unicode.html
This fixes a fairly old crasher in the fastGotoNode plugin.
The prototype in test.leo now will use PIL (Python Imaging Library) if available, so many more kinds of icons can be used. Buttons now exist to add icons to do the following:

- Add any icon to any node. - Delete all icons from a single node or the entire tree. - Print the icon files associated with a node. - Print the sizes of icons in a directory.

Fixed a bug in the icon handling in the outline widget that caused duplicate icons not to be drawn properly.
The prototype in test.leo now uses PIL (Python Imaging Library) if available, so many more kinds of icons can be used.

Buttons now exist to add icons to do the following:

- Add any icon to any node. - Delete all icons from a single node or the entire tree. - Print the icon files associated with a node. - Print the sizes of icons in a directory.

In addition, fixed a bug in the icon handling in the outline widget that caused duplicate icons not to be drawn properly.
Scripts can invoke various dialogs using the following methods of the g.app.gui object. Here is a partial list. You can use typing completion(default bindings: Alt-1 and Alt-2) to get the full list! ::

g.app.gui.runAskOkCancelNumberDialog(c,title,message) g.app.gui.runAskOkCancelStringDialog(c,title,message) g.app.gui.runAskOkDialog(c,title,message=None,text='Ok') g.app.gui.runAskYesNoCancelDialog(c,title,message=None, yesMessage='Yes',noMessage='No',defaultButton='Yes') g.app.gui.runAskYesNoDialog(c,title,message=None)

The values returned are in ('ok','yes','no','cancel'), as indicated by the method names. Some dialogs also return strings or numbers, again as indicated by their names.

Scripts can run File Open and Save dialogs with these methods::

g.app.gui.runOpenFileDialog(title,filetypes,defaultextension,multiple=False) g.app.gui.runSaveFileDialog(initialfile,title,filetypes,defaultextension)

For details about how to use these file dialogs, look for examples in Leo's own source code. The runOpenFileDialog returns a list of file names.
Leo 4.4.4 Final November 2, 2007

Leo 4.4.4 Final is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

Leo 4.4.4 contains many important features originally planned for later releases.

The highlights of Leo 4.4.4: ----------------------------

- The Great Graph Aha (tm): simple scripts allow Leo outlines to represent arbitrary directed graphs. There is no need for a separate 'graph world'. The graphed.py plugin is a direct result of this Aha. The graphed.py plugin allows you to create general graphs from Leo outlines.

- @menus trees in settings files create all of Leo's menus. It is now dead easy to make Leo's menus look the way you want.

- @buttons trees in settings files create common @button nodes created in all Leo outlines.

- @auto nodes eliminate sentinels in derived files, thereby allowing people to collaborate using Leo more easily. **Warning**: for now, please make backup copies of files imported with @auto.

- New commands for resolving cvs conflicts.

- A threading_colorizer plugin replaces the __jEdit_colorizer__ plugin. This plugin features much better performance and a new, elegant algorithm.

- Leo is now compatible with jython.

- Better support for icons in headlines.

- Many bug fixes and other minor improvements.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
http://sourceforge.net/forum/message.php?msg_id=4591494
The fix doesn't actually remember which chapter was previously selected; it picks some chapter containing the initially selected node. This works exactly for non-cloned nodes, but can select the 'wrong' chapter for cloned nodes. Still, this is a big improvement over the previous code, which would not select any node if the selected node was not in the main chapters.
It is too confusing at present, because it doesn't support @enabled-plugins nodes.
http://sourceforge.net/forum/forum.php?thread_id=1853660&forum_id=10228
The spell tab now uses the same font as the find tab.
http://sourceforge.net/forum/message.php?msg_id=4596477
Leo 4.4.5 beta 1 November 16, 2007

Leo 4.4.5 beta 1 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

Leo 4.4.5 fixes several long-delayed bug fixes and adds several new features.

The highlights of Leo 4.4.5: ----------------------------

- Fixes all known bugs. - Leo now recognizes directives in headlines. - Adds 3 new sort-lines commands. - Adds commands to insert and delete icons from headlines. - Adds all the Tango 16x16 icons to Leo's icon library. - Adds support for @rst-preformat nodes to the rst3 plugin.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
@nocolor

https://sourceforge.net/forum/message.php?msg_id=3768494 By: ktenney

I'm using current CVS, W2k

1 open a Leo file (I'm using a batch file / console)

2 click Edit->Open <-- Having this dialog open is the problem.

3 return focus to the Leo window

4 click Help->Open leoDocs.leo

Zombie!

@color
http://sourceforge.net/forum/message.php?msg_id=3525277

The atFile read logic only **adds** nodes, it never deletes nodes. Thus, the 'changed2' node 'survived' the atFile read logic. The 'changed2' node became a 'vampire' node that couldn't be killed.

The fix will require some care. The present atFile.read logic is robust because it *doesn't* delete nodes. I suspect the solutions will be as follows:

A. The atFile.read code can not delete the subtree of @thin nodes initially, because it doesn't know whether there will be read errors later. If there are read errors absolutely nothing must change. This ensures that read errors never destroy information.

B. A new post-pass will look for vampire nodes: nodes that were not actually read from the derived file. I think (but haven't proven) that all descendants of vampire nodes are also vampire nodes. If that is so the post-pass will simply delete vampire nodes without worrying about whether they have descendants.
@nocolor

From: Terry Brown <terry_n_brown@yahoo.com>

** Also, no ignore inserted.

Current CVS, ubuntu

From the code below I get:

reading: /mnt/removable/bkup_proj/Mammals/mammaldb/mammaldb.leo *** first mismatch at line 119 original line: def provide(self, what): generated line: def provide(self, what): @auto did not import the file perfectly first mismatched line: 119 u'def provide(self, what):\n' inserting @ignore Errors inhibited read @auto /mnt/removable/bkup_proj/Mammals/mammaldb/mammalShow.py

In the code below line 119 is not the first "def provide(self, what):" but the second, the one in class mainPages - I've included the preceding class def because context seems to be important.

@color
@nocolor

In the following code:

extern "C" { #include "stuff.h" void init(void); #include "that.h" }

produces the following in the log window:

Leo Log Window... Leo 4.4.4 final, build 1.216 , November 2, 2007 Python 2.5.1, Tk 8.4.14, Pmw 1.2 Windows 5, 1, 2600, 2, Service Pack 2

leoID = rshanley (in C:\) global config dir: C:\Program Files\Leo\config home dir: C:\ reading settings in C:\Program Files\Leo\config\leoSettings.leo *** first mismatch at line 2 original line: { generated line: import command did not import the file perfectly first mismatched line: 2 u'\n' input... 0 extern "C" 1 { 2 #include "stuff.h" 3 void init(void); 4 #include "that.h" 5 } output... 0 extern "C" 1 inserting @ignore imported C:/test/aa.cc

@color
@nocolor

http://sourceforge.net/forum/forum.php?thread_id=1865290&forum_id=10226

@bool at_auto_warns_about_leading_whitespace

@color
http://sourceforge.net/forum/message.php?msg_id=4464649 By: terry_n_brown

An argument I'm always having with leo has to do with its conversion of file paths to 'absolute' forms.

In the file browser I select '/home/tbrown/misc/foo.leo'. Leo reinterprets this as '/media/hda2/usr1/home/tbrown/misc/foo.leo'

Then I switch machines, and while '/home/tbrown/misc/foo.leo' would still be valid, '/media/hda2/usr1/home/tbrown/misc/foo.leo' isn't - on the other machine it would be '/media/hdb1/home/tbrown/misc/foo.leo'.

I end up with the two entries in recent files, having to identify the right one.

If the Tk dialog is returning '/home/tbrown/misc/foo.leo', which I assume it is because that's what it's displaying, I wish leo would use and store that.
http://sourceforge.net/forum/message.php?msg_id=4615931
http://sourceforge.net/forum/message.php?msg_id=4618014
http://sourceforge.net/forum/message.php?msg_id=4620890
From email from Terry Brown

python /home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leo.py /home/tbrown/.tnb.leo

(should be all on one line, i.e. run and open /home/tbrown/.tnb.leo)

gives the traceback below. Opening the file from within Leo works fine.

Bah - I just now looked at it closely enough to realize it's the evil pickled Tk classes in cleo uAs. So I don't know whether you want to fix that or not, it makes sense Leo would read the file specified on the command line before Tk is initialized - if it's just scanning for settings maybe it could catch and ignore failed uA reads at that time?

At some point I want to take pickled Tk vars out of cleo, I was thinking when that guy was working on the wx gui would be a good time, too bad he got sick.

reading settings in /mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/config/leoSettings.leo reading settings in /home/tbrown/leoSettings.leo reading settings in /home/tbrown/myLeoSettings.leo reading settings in /home/tbrown/.tnb.leo Traceback (most recent call last): File "/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leo.py", line 398, in <module> run(fileName) File "/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leo.py", line 118, in run g.app.config.readSettingsFiles(fileName,verbose) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoConfig.py", line 1649, in readSettingsFiles c = self.openSettingsFile(path) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoConfig.py", line 1674, in openSettingsFile theFile,path,readAtFileNodesFlag=False,silent=True) # closes theFile. File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 892, in open silent=silent) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 779, in getLeoFile self.getAllLeoElements(fileName,silent) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1317, in getAllLeoElements self.getVnodes() File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1898, in getVnodes appendToCurrentStack=append1,appendToTopStack=append2) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1781, in getVnode appendToCurrentStack=append1,appendToTopStack=append2) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1781, in getVnode appendToCurrentStack=append1,appendToTopStack=append2) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1781, in getVnode appendToCurrentStack=append1,appendToTopStack=append2) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1781, in getVnode appendToCurrentStack=append1,appendToTopStack=append2) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1781, in getVnode appendToCurrentStack=append1,appendToTopStack=append2) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1781, in getVnode appendToCurrentStack=append1,appendToTopStack=append2) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1781, in getVnode appendToCurrentStack=append1,appendToTopStack=append2) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1781, in getVnode appendToCurrentStack=append1,appendToTopStack=append2) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1781, in getVnode appendToCurrentStack=append1,appendToTopStack=append2) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1738, in getVnode attr,val = self.getUa("vnode") File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/src/leoFileCommands.py", line 1658, in getUa val2 = pickle.loads(binString) File "/usr/lib/python2.5/pickle.py", line 1374, in loads return Unpickler(file).load() File "/usr/lib/python2.5/pickle.py", line 858, in load dispatch[key](self) File "/usr/lib/python2.5/pickle.py", line 1217, in load_build setstate(state) File "/mnt/removable/bkup_usr1/home/tbrown/.gnome-desktop/Package/leo/cvs/leo/plugins/cleo.py", line 130, in __setstate__ Tk.Variable.__init__(self) File "/usr/lib/python2.5/lib-tk/Tkinter.py", line 188, in __init__ self._tk = master.tk AttributeError: 'NoneType' object has no attribute 'tk' Exception exceptions.AttributeError: "TkPickleVar instance has no attribute '_tk'" in <bound method TkPickleVar.__del__ of <cleo.TkPickleVar instance at 0xb73a876c>> ignored
This option has effect only when importing so-called non-strict languages, for which leading whitespace is not terribly significant.

True: @auto warns about mismatches that occur solely in leading whitespace.
Added sort-lines-ignoring-case, reverse-sort-lines and reverse-sort-lines-ignoring-case.
This provides further information when there are problems using aspell.
There is also an @bool trace_plugins setting.
And reorganized the unit tests by Leo source file.
http://sourceforge.net/forum/message.php?msg_id=4622384

vim.py does not open url nodes if the new setting:

@bool vim_plugin_opens_url_nodes

is False (or does not exist).
The code now remembers the relative file name as well as the full path name. This allows Leo to find the icon when multiple machines are involved.
http://sourceforge.net/forum/message.php?msg_id=4614081
http://tango.freedesktop.org/Tango_Icon_Library

These icons are now part of Leo's distribution.
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|prev| |leo| |next|

########################################## What's New in Leo 4.4.5 ##########################################

Leo 4.4.5 fixes several long-delayed bug fixes and adds several new features.

The highlights of Leo 4.4.5:

- Fixes all known bugs. - Adds 3 new sort-lines commands. - Adds commands to insert and delete icons from headlines. - Adds all the Tango 16x16 icons to Leo's icon library. - Adds support for @rst-preformat nodes to the rst3 plugin.

.. contents::
.. Links used in this document.

.. _`leoBridge chapter`: leoBridge.html .. _`debugging with Leo`: debuggers.html

.. WARNING: image targets may not have upper case letters!

.. |prev| image:: arrow_lt.gif :target: new-4-4-6.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: new-4-4-4.html
- Leo now supports all directives in headlines.

- Moved all unit tests to unitTest.leo and reorganized the unit tests by Leo source file.

- Installed small icon set from Tango library.

- The rst3 plugin now supports @rst-preformat nodes.
::

delete-all-icons delete-first-icon delete-last-icon delete-node-icons insert-icon reverse-sort-lines reverse-sort-lines-ignoring-case. sort-lines-ignoring-case toggle-collapse_nodes_during_finds
-----------------------

|prev| |leo| |next|
- Fixed hung (zombie) windows. http://sourceforge.net/forum/message.php?msg_id=3768494

- Fixed resurrected (vampire) nodes. http://sourceforge.net/forum/message.php?msg_id=3525277
- @bool at_auto_warns_about_leading_whitespace

This option has effect only when importing so-called non-strict languages, for which leading whitespace is not terribly significant.

- @bool diagnose-aspell-installation

This provides further information when there are problems using aspell.

- @bool warn_when_plugins_fail_to_load

There is also an @bool trace_plugins setting.

- @bool vim_plugin_opens_url_nodes

vim.py does not open url nodes if this setting is False.
pylint reported the following errors:

E1101:1877:atFile.readEndNode: Instance of 'atFile' has no 'correctedLines' member E1101:2725:atFile.norefWrite: Instance of 'atFile' has no 'putBuffered' member
http://sourceforge.net/forum/message.php?msg_id=4632695
http://sourceforge.net/forum/message.php?msg_id=4646055
https://sourceforge.net/forum/message.php?msg_id=4643992
The init base classes can now be inited in a more standard way.
http://sourceforge.net/forum/message.php?msg_id=4639426
http://sourceforge.net/forum/message.php?msg_id=4639872
Several problems still remain:

- Files that contain what look like section references.

- Underindented docstrings.
http://sourceforge.net/forum/message.php?msg_id=4658901
http://sourceforge.net/forum/message.php?msg_id=4652514
http://sourceforge.net/forum/message.php?msg_id=4654762
@nocolor

I have clones that traverse chapters.

Given the following Chapters:

> Main > Big Picture > Smaller Chunk

I have in Main, my organization, with my group in it. It's also cloned around all the other views (really, everything starts in the Big Picture).

This is the layout of my clone:

1: Chapter:Main > me 2: Chapter:Main > MyOrg > me 3: Chapter:Big Picture > CEO > Some Big Honcho > MyOrg > me 4: Chapter:Smaller Chunk > Some Big Honcho > MyOrg > me

If I Go-To-Next-Clone (ALT-N) from (1), focus will move to the selected node in Chapter:Main, namely (2).

So here's the issue:

Let each successive line below represent a starting focus, and the next line the node that ALT-N selects. If focus changes in the Outline pane (including Chapter pane change) to match the Node, that case is marked with [f] - a successful focus transition.

The issue are the lines w/o [f]; Here's a couple of test runs.

1: [f] (starting node / focus) 2: [f] 3: 4: 1: [f]

Next test:

3: [f] 1: [f] 1: [f] 4: 3: 1: [f]

Next test:

4: [f] 3: 1: [f] 2: [f] 4: 3: 1: [f] 2: [f] ... and so on...

In cases with NO [f], the outline pane seems moved to the "end", but no node selected.

Not a show stopper, but a bug nonetheless.

@color
http://sourceforge.net/forum/message.php?msg_id=4634600
Leo 4.4.5 beta 2 December 7, 2007

Leo 4.4.5 beta 2 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

This beta 2 release fixes several recently reported bugs. A final release is due in about a week.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

Leo 4.4.5 fixes several long-delayed bug fixes and adds several new features.

The highlights of Leo 4.4.5: ----------------------------

- Fixes all known bugs. - Leo now recognizes directives in headlines. - Adds 3 new sort-lines commands. - Adds commands to insert and delete icons from headlines. - Adds all the Tango 16x16 icons to Leo's icon library. - Adds support for @rst-preformat nodes to the rst3 plugin.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
This following is adapted from Terry Brown's entry in Leo's wiki.

You can not just run leoBridge from Leo, because the leoBridge module is design to run a separate copy of Leo. However, it is possible to run leoBridge from a subprocess. That turned out to be more, um, interesting than anticipated, so I'm recording the results here.

The idea is that script A running in Leo (i.e. in a regular GUI Leo session) calls script B through subprocess.Popen(), script B uses LeoBridge to do something (parse unloaded Leo files), and returns the result to script A. Passing the result back via the clipboard seemed like a possibility, but XWindows / tcl/tk clipboard madness being what it is, that didn't seem to work.

First trick, calling script B from script A::

import subprocess p = subprocess.Popen(('python', path_to_script_B, parameter_for_script_B,), stdout=subprocess.PIPE, env={'PYTHONPATH': g.app.loadDir,'USER': g.app.leoID}, ) p.wait()

Setting PYTHONPATH in the environment seemed like the easiest way to let script B find leoBridge.py (which it needs to import). But by setting the env parameter you limit script B's environment to be **only** PYTHONPATH, which causes leoBridge to fail because, in unix at least, it depends on USER in the environment. So you need to pass that through too.

Now, because passing stuff back on the clipboard seems unreliable, at least in XWindows, script B passes results back to script A via stdout (print), but there's some Leo initialization chatter you want to avoid. So put a sentinel, 'START_CLIPBOARD', in the output, and collect it like this::

response = p.stdout.readlines() while response and 'START_CLIPBOARD' not in response[0]: del response[0] del response[0] # delete the sentinel as well response = ''.join(response)

This is the basic mechanism. What I *actually* wanted to do was have script B generate a branch of nodes and pass that back to script A for insertion in the tree script A is running in. That's relatively easy if you use::

c.setCurrentPosition(pos_of_branch_to_return) c.copyOutline() print '<!-- START_CLIPBOARD -->' print g.app.gui.getTextFromClipboard() print '<!-- END_CLIPBOARD -->'

at the end of script B, and back in script A, after you've rebuilt `response` as shown above, just::

g.app.gui.replaceClipboardWith(response) c.pasteOutline()

Leo 4.4.5 final December 11, 2007

Leo 4.4.5 final is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo 4.4.5 fixes several long-delayed bug fixes and adds several new features.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.5: ----------------------------

- Fixes all known bugs. - Leo now recognizes directives in headlines. - Adds 3 new sort-lines commands. - Adds commands to insert and delete icons from headlines. - Adds all the Tango 16x16 icons to Leo's icon library. - Adds support for @rst-preformat nodes to the rst3 plugin.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
http://sourceforge.net/forum/message.php?msg_id=4668960

It seems in derived files you can delete some text and save, causing the derived file to be written and all dirty flags cleared. But then undo makes the text come back, as expected, but save only saves the outline, because the dirty flag wasn't set on the node in which the text was restored by undo.
Added k.overrideCommand.
http://sourceforge.net/forum/message.php?msg_id=4671771
http://sourceforge.net/forum/message.php?msg_id=4667105
The command now clears all .leoRecentFiles.txt files and write a message.
This was a very long-standing bug: the most annoying in all of Leo.
The last char was not colored in the following doc part:

@

<tag />
http://sourceforge.net/forum/message.php?msg_id=4676037
This prevents over-long traces.
The patch attached against leoConfig.py (current CVS) adds a machine specific config file to the config files Leo loads.

I synchronize files between multiple (3) machines. This means I can't use different myLeoSettings files on each.

Tk fonts are screen dpi sensitive. But (in Linux at least) Tk's attempts to switch a font you picked to something equivalent at a different dpi always result in a font that looks terrible.

So every time I switch machines I edit ~/myLeoSettings.leo to move the font defs I picked for the current machine to the bottom of the body text for the appropriate settings node, and then restart Leo.

This patch means I don't have to do that any more. I'm sure there are other uses for it. Python doesn't seem to have a generic machine name finding function, hence the sequence of alternatives.
The version of plugins_menu.py at http://leo.zwiki.org/Plumloco separates out the gui dependent dialogs (the menus are already gui independent) and made them general purpose dialogs available to all plugins.

I have also slightly enhanced the dialogs to provide user defined buttons.
The finds the next cloned node, regardless of whether the presently selected node is a clone or not.
The command toggles whether moving a node left collapses the outline.
Use @data import_xml_tags setting to specify the xml tags that act as organizers.
This fixes a focus problem.
Javascript regexps that look like section references cause problems, but that can not be helped.
Leo 4.4.6 beta 1 December 17, 2007

Leo 4.4.6 beta 1 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo 4.4.6 fixes several recently reported bugs, all minor.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.6: ---------------------------- - Fixes all known bugs. - Added @auto importers for javascript and xml files. - Added find-next-clone and toggle-sparse-move commands.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|prev| |leo| |next|

########################################## What's New in Leo 4.4.6 ##########################################

Leo 4.4.6 fixes all known bugs and adds a few new features.

.. contents::
.. Links used in this document.

.. _`leoBridge chapter`: leoBridge.html .. _`debugging with Leo`: debuggers.html

.. WARNING: image targets may not have upper case letters!

.. |prev| image:: arrow_lt.gif :target: new-4-4-8.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: new-4-4-5.html
::

find-next-clone toggle-sparse-move

Replaced the delete-all-icons command with a script in scripts.leo. This command was too dangerous.
- Added support for @data nodes in settings files.

- The @data import_xml_tags setting specifies the xml tags that act as organizers. This settings is used by @auto when importing xml files.
-----------------------

|prev| |leo| |next|
http://sourceforge.net/forum/message.php?msg_id=4682598
http://sourceforge.net/forum/message.php?msg_id=4681175

- There was a horrendous bug in the match_seq_regexp matcher which could cause the colorizer to loop. - There was another horrendous bug in match_regexp_helper that cause spurious matches. - Added some more defensive code to have the colorizer recover more gracefully in this case. - The jedit2py script was not associating regexp rules whose regex starts with '\' with the proper character. The proper character is the hash_char character, not the '\' character. As a result, regexp's that start with '\' never got matched.

The following colorizers are affected by the change:

modes/apacheconf.py modes/erlang.py modes/moin.py modes/perl.py modes/php.py modes/pl1.py modes/rest.py modes/shell.py modes/shellscript.py
http://sourceforge.net/forum/message.php?msg_id=4687706
Leo 4.4.6 beta 2 January 15, 2008

Leo 4.4.6 beta 2 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo 4.4.6 fixes several recently reported bugs, all minor.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.6: ---------------------------- - Fixes all known bugs. - Added @auto importers for javascript and xml files. - Added find-next-clone and toggle-sparse-move commands.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
You can add an icon to the presently selected node with c.editCommands.insertIconFromFile(path). path is an absolute path or a path relative to the leo/Icons folder. A relative path is recommended if you plan to use the icons on machines with different directory structures.

For example::

path = 'rt_arrow_disabled.gif' c.editCommands.insertIconFromFile(path)

Scripts can delete icons from the presently selected node using the following methods::

c.editCommands.deleteFirstIcon() c.editCommands.deleteLastIcon() c.editCommands.deleteNodeIcons()
See http://webpages.charter.net/edreamleo/scripting.html#inserting-and-deleting-icons
http://sourceforge.net/forum/message.php?msg_id=4712329
http://sourceforge.net/forum/message.php?msg_id=4714779
- Added support for @auto xml and @auto javascript. Use @data import_xml_tags setting to specify the xml tags that act as organizers. Javascript regexps that look like section references cause problems, but that can not be helped.
Leo 4.4.6 final January 26, 2008

Leo 4.4.6 final is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

Leo 4.4.6 fixes several recently reported bugs, all minor.

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.6: ---------------------------- - Fixes all known bugs. - Added @auto importers for javascript and xml files. - Added find-next-clone and toggle-sparse-move commands.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Home: http://sourceforge.net/projects/leo/ Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
@language rest
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

.. June, 2007

|back| |leo| |next|

############################################################ Chapter 21: IPython and Leo ############################################################

To use this plugin, you must run Leo from a console window. When this plugin is enabled, Leo's start-ipython command starts IPython_ in this console. Leo's ipython plugin provides two-way communication (a bridge) between Leo and IPython: you can run Leo scripts from IPython, and IPython scripts from Leo.

Remarkably, Leo and IPython run simultaneously in the same process, yet their separate event loops do not interfere with each other. Even more remarkably, scripts run from IPython *immediately* change Leo, *exactly* as if the script were run from Leo. Conversely, scripts run from Leo *immediately* affect the IPython interpreter. Care may be needed when running such scripts while lengthy IPython scripts are running. As the result of this truly remarkable connection between Leo and IPython, Leo might plausibly be said to be an `IPython Notebook`_.

The bridge between Leo and IPython is powerful because it is simple. Indeed,

1. **You can run any IPython script from Leo**. On the Leo side, as single variable::

ip = IPython.ipapi.get()

assigns ip to IPython's _ip variable. The ip variable allows scripts running in Leo to do *anything* that an IPython script can do.

2. **You can run any Leo script from IPython**. The ipython plugin injects a single object named '_leo' into the IPython namespace. IPython scripts access Leo's c and g objects as follows::

c,g = _leo.c, _leo.g

The c and g variables allow scripts running in IPython to do *anything* that a Leo script can do.

This is basically everything that is required for IPython-Leo interaction. However, you probably wont use 'c' and 'g' directly, but use a series of convenience wrappers described in this document that make interactive work painless and powerful.

.. contents::

.. Links

.. _discussions: http://sourceforge.net/forum/forum.php?thread_id=1911662&forum_id=10226 .. _ipython: http://ipython.scipy.org/ .. _IPython: http://ipython.scipy.org/ .. _`IPython Notebook`: http://projects.scipy.org/ipython/ipython/wiki/NoteBook .. _extensionAPI: http://ipython.scipy.org/moin/IpythonExtensionApi

.. _`The Ipython Extension API`: extensionAPI_

.. _`Chapter 7\: Scripting Leo with Python`: scripting.html

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif :target: unitTesting.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: appendices.html
-----------------------

|back| |leo| |next|
This plugin creates an instance of the **ipythonController** class for each Leo window. The ipythonController objects manage a singleton instance of IPython's IPShellEmbed class. See http://ipython.scipy.org/doc/manual/node9.html. Creating this singleton instance starts IPython running in the console from which Leo was run. As mentioned in the introduction, Leo and IPython appear to run simultaneously. Their event loops do not interfere with each other.

The term **startup time** refers to the time that the singleton IPython instance is created.

Initializing Leo from IPython is easier than initializing IPython from Leo. Indeed, the start-ipython command typically blocks and never returns, so it is not possible to schedule a Leo script to be run after the start-ipython command returns. Instead, it will typically be more convenient to use IPython's normal facilities to schedule a script that initializes Leo when IPython starts.

The start-ipython command starts IPython running in the console and injects leox, a **Leo Interface Object** into IPython's user namespace. Using the leox object, IPython scripts can gain access to Leo's c and g variables::

c,g = leox.c,leox.g

Thus, IPython scripts can do *anything* that can be done in Leo. See `Scripting Leo from IPython`_ for full details.

Conversely, Leo scripts can gain access to IPython's _ip variable::

ip = c.ipythonController.ip

Thus, Leo scripts can do *anything* that can be done in IPython. See `Scripting IPython from Leo`_ for full details.
This plugin creates the following Leo commands commands:

- The start-ipython command starts the singleton IPython instance running in the console and injects a Leo Interface Object into IPython's user namespace. **Run the start-ipython command before running the other commands**.

**Important**: The start-ipython command blocks. That is, the command does not finish execution until IPython exits. In a typical workflow, IPython exits after Leo does, so the the start-ipython command *never* completes.

Remarkably, this does not affect Leo's main loop: Leo itself does not block. However, because the start-ipython command blocks, it is not possible for the command to do any follow up initialization of IPython. In practice, this does not matter, because IPython provides several ways of executing scripts on startup. In short, it is often more convenient to initialize Leo from IPython than to initialize IPython from Leo.

- The push-to-ipython command pushes data to IPython. By default, it executes the body text of the presently selected node in IPython.
Just as c and g provide full access to all aspects of Leo, IPython's _ip var (and _ip.IP) provide full access of all of IPython's internals. See extensionAPI_ for details. The following script sets ip to IPython's _ip var::

ip = c.ipythonController.ip # set ip to IPython's _ip var.

With ip defined as above, IPython scripts **running in Leo** can do anything that a script running in IPython can do.

Leo scripts can simulate this plugins's minibuffer commands as follows.

To simulate the start-ipython command::

x = c.ipythonController if x and not x.started(): x.startIPython()

To simulate the push-to-ipython command::

x = c.ipythonController if x and x.started(): x.pushToIPython()

To run a given script in IPython::

x = c.ipythonController if x and x.started(): x.pushToIPython(script=script)
The start-ipython command injects the leox object into IPython's user namespace. The c and g ivars of the leox object are the leoGlobals module and the commander of the Leo outline that created the IPython shell, respectively. Thus scripts **running in IPython** can do *anything* a Leo script can do. For, such scripts can insert and delete nodes in Leo outlines. The changes will become visible as soon as the script (running in IPython) redraws the screen.

See `Chapter 7\: Scripting Leo with Python`_ for full details about how to script Leo. The following are merely examples about what can be done from IPython. All these examples have been tested.

1. g.app.windowList is a list of all open Leo frames, so an IPython script can get a list of all commanders as follows::

c,g = leox.c, leox.g commanders = [f.c for f in g.app.windowList]

2. IPython scripts can use the c.config object to get Leo settings. Suppose the body text of an @data ipython-bridge-startup-script setting contains a script to be executed when ipython starts up. An Ipython script can get that startup script as follows::

c = leox.c startupScript = c.config.getData('ipython-bridge-startup-script')

3. Suppose the body text of an @data ipython-bridge-auto-open setting contains a list of .leo files to be automatically opened on startup. The following IPython script opens those files::

c,g = leox.c, leox.g files = c.config.getData('ipython-bridge-auto-open-leo-files') # getData strips lines starting with '#'. for z in files: fileName = g.os_path_abspath(g.os_path_join(g.app.loadDir,z)) g.openWithFileName(fileName, old_c=c)
This plugin would not have been possible without the help of Ville M. Vainio.
http://groups.google.com/group/leo-editor/browse_thread/thread/4fa4709969fc04d
When reading an @auto tree, createOutline now does the following:

1. When importing Python files, createOutline uses the encoding implied by Python's # -*- coding line. This line must be the first line of the imported file.

2. Otherwise, createOutline scans the @auto node and its ancestors for Leo's @encoding directive.

3. If no such @encoding directive is found, createOutline uses the encoding specified by the setting: @string default_at_auto_file_encoding = utf-8

4. If this setting does not exist, the utf-8 encoding is used.
If the @bool open_with_save_on_update setting is True, Leo will automatically save the outline whenever an external editor changes the outline.
Leo 4.4.7 beta 1 February 12, 2008

Leo 4.4.7 beta 1 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

This version features the ipython plugin that provides a two-way bridge between Leo and IPython. See http://webpages.charter.net/edreamleo/IPythonBridge.html

Leo's main discussion is now at: http://groups.google.com/group/leo-editor

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.7: ---------------------------- - The ipython plugin creates a simple, powerful, effective bridge between IPython and Leo. See http://webpages.charter.net/edreamleo/IPythonBridge.html - Improved handling of unicode encodings in @auto files. - All import commands now support @path directives in ancestor nodes. - Fixed several minor bugs.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Forum: http://groups.google.com/group/leo-editor Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
There appear to be problems with Python's subprocess module on Ubuntu.
The version of PIL that ships with Ubuntu (and presumably Debian and maybe some other distributions) no longer includes the ImageTk module. ImageTk is now located in the python- imaging-tk package.
Leo 4.4.7 final February 18, 2008

Leo 4.4.7 final is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

This version features a new ipython plugin that provides a two-way bridge between Leo and IPython. See http://webpages.charter.net/edreamleo/IPythonBridge.html

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.7: ---------------------------- - The ipython plugin creates a simple, powerful, effective bridge between IPython and Leo. See http://webpages.charter.net/edreamleo/IPythonBridge.html - Improved handling of unicode encodings in @auto files. - All import commands now support @path directives in ancestor nodes. - Fixed several minor bugs.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Forum: http://groups.google.com/group/leo-editor Download: http://sourceforge.net/project/showfiles.php?group_id=3458 CVS: http://leo.tigris.org/source/browse/leo/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
http://groups.google.com/group/leo-editor/browse_thread/thread/4fa4709969fc04d
There appear to be problems with Python's subprocess module on Ubuntu.
The version of PIL that ships with Ubuntu (and presumably Debian and maybe some other distributions) no longer includes the ImageTk module. ImageTk is now located in the python- imaging-tk package.
If the @bool open_with_save_on_update setting is True, Leo will automatically save the outline whenever an external editor changes the outline.
When reading an @auto tree, createOutline now does the following:

1. When importing Python files, createOutline uses the encoding implied by Python's # -*- coding line. This line must be the first line of the imported file.

2. Otherwise, createOutline scans the @auto node and its ancestors for Leo's @encoding directive.

3. If no such @encoding directive is found, createOutline uses the encoding specified by the setting: @string default_at_auto_file_encoding = utf-8

4. If this setting does not exist, the utf-8 encoding is used.
http://mail.google.com/mail/#inbox/1184b70ea10f5aa3

Leo now contains minimal support for arguments to minibuffer commands.

- k.simulateCommand now puts arguments following the command name in k.givenArgs. Whitespace separates arguments.

- k.simulateCommand knows nothing about what the arguments mean. That is up to the individual commands.

- At present, only the following minibuffer commands now support k.givenArgs: open-outline, open-outline-by-name, save-file, save-file-as, save-file-as-unzipped and save-file-as-zipped.

These commands use ''.join(k.givenArgs) to get the file name, which may cause problems if the file name contains whitespace.

- At present, the repeat-complex-command command does not support arguments.
@language rest @color
Leo 4.4.8 beta 1 March 5, 2008

Leo 4.4.8 beta 1 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

This version features a new ipython plugin that provides a two-way bridge between Leo and IPython. See http://webpages.charter.net/edreamleo/IPythonBridge.html

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.8: ---------------------------- - Leo's source code is now managed by bzr. See the Bzr link below. - Leo's discussion is now hosted by Google Groups: See the Forum link below. - The first, third, fifth etc. arguments to g.es and g.es_print can now be translated using Python's gettext.gettext function. - Completed ILeo: a bridge between IPython and Leo. See http://webpages.charter.net/edreamleo/IPythonBridge.html - Added support for arguments to minibuffer commands.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Forum: http://groups.google.com/group/leo-editor Download: http://sourceforge.net/project/showfiles.php?group_id=3458 Bzr: http://code.launchpad.net/leo-editor/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
<a href="http://sourceforge.net/project/showfiles.php?group_id=3458&amp;package_id=29106"> Download Leo[4.4.8 final]</a>
.. _gettext: http://docs.python.org/lib/module-gettext.html

It is easy to translate Leo's menu strings: simply create an @menus tree in leoSettings.leo or myLeoSettings.leo that contains the translated menu names.

**New in Leo 4.4.8**: Leo now contains support for translating messages sent to Leo's log:

- Rather than using an '_' function to denote strings to be translated, Leo's g.es and g.es_print functions translate "odd" (first, third, fifth) arguments, leaving "even" arguments untranslated. Keyword arguments, color, newline, etc. are never translated.

- All calls to g.es and g.es_print in Leo's core follow this convention.

- g.translateString does the actual translation using Python's `gettext`_ module.

- You can use the script in the node "@button print g.es stats" in scripts.leo to create catalogs of all scripts that need to be translated. Such catalogs are used by Python's gettext module. (This script was also used to check that the proper arguments to g.es and g.es_print were translated.)
Leo 4.4.8 beta 2 March 14, 2008

Leo 4.4.8 beta 2 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

This version features a new ipython plugin that provides a two-way bridge between Leo and IPython. See http://webpages.charter.net/edreamleo/IPythonBridge.html

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.8: ---------------------------- - Leo's source code is now managed by bzr. See the Bzr link below. - Leo's discussion is now hosted by Google Groups: See the Forum link below. - The first, third, fifth etc. arguments to g.es and g.es_print can now be translated using Python's gettext.gettext function. - Completed ILeo: a bridge between IPython and Leo. See http://webpages.charter.net/edreamleo/IPythonBridge.html - Added support for arguments to minibuffer commands. - @menu trees can now refer to commands created by @command and @button nodes - Added support for common @commands nodes in settings files.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Forum: http://groups.google.com/group/leo-editor Download: http://sourceforge.net/project/showfiles.php?group_id=3458 Bzr: http://code.launchpad.net/leo-editor/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
@nocolor

Eureka! I have just discovered an elegant solution to this problem!

The Aha is this: we can create a "base" timestamp just *once*, when the commander (i.e. the nodeIndices class) is created. Thereafter, code that writes gnx's simply calls nodeIndices.getIndex if the node doesn't already have an index (or if indices are being reassigned in a copied tree).

In other words, there is no need to be picky about timestamps, the base timestamp will do, so there is no need to assign indices before writing nodes!

I didn't see this before because computing timestamps is quite time consuming. In fact, we can't do so "on the fly". That being so, the old code computed the "new" timestamp once in assignFileIndices, which lead me away from getting gnx's as needed. But if there is only *one* timestamp everything becomes easy. There is no need to "batch" the computation of gnx's. In other words, timestamps don't have to be up- to-the-second accurate. They simply guarantee that two nodes (in a particular outline) created by the *same* person can't collide.

This is the way it is written in "The Book". All calls to assignFileIndices disappear! All the code I wrote this morning that remembers whether indices have been assigned disappears. I'll keep a do-nothing assignFileIndices around for compatibility with old scripts.

This is *so* important. It eliminates forever a source of serious file write problems. Furthermore, nodeIndices.getIndex becomes substantially simpler. Even though the code was short, it implied some very tricky assumptions. Every time I read it I had to recreate why it worked. Those mental gymnastics should disappear.

A great day for Leo.

@color
# This should have been done long ago.
http://sourceforge.net/forum/message.php?msg_id=4677335
This allows @menu items to refer to commands created by @button.
http://mail.google.com/mail/#inbox/1184b70ea10f5aa3

Leo now contains minimal support for arguments to minibuffer commands.

- k.simulateCommand now puts arguments following the command name in k.givenArgs. Whitespace separates arguments.

- k.simulateCommand knows nothing about what the arguments mean. That is up to the individual commands.

- At present, only the following minibuffer commands now support k.givenArgs: open-outline, open-outline-by-name, save-file, save-file-as, save-file-as-unzipped and save-file-as-zipped.

These commands use ''.join(k.givenArgs) to get the file name, which may cause problems if the file name contains whitespace.

- At present, the repeat-complex-command command does not support arguments.
@language rest @color
.. _gettext: http://docs.python.org/lib/module-gettext.html

It is easy to translate Leo's menu strings: simply create an @menus tree in leoSettings.leo or myLeoSettings.leo that contains the translated menu names.

**New in Leo 4.4.8**: Leo now contains support for translating messages sent to Leo's log:

- Rather than using an '_' function to denote strings to be translated, Leo's g.es and g.es_print functions translate "odd" (first, third, fifth) arguments, leaving "even" arguments untranslated. Keyword arguments, color, newline, etc. are never translated.

- All calls to g.es and g.es_print in Leo's core follow this convention.

- g.translateString does the actual translation using Python's `gettext`_ module.

- You can use the script in the node "@button print g.es stats" in scripts.leo to create catalogs of all scripts that need to be translated. Such catalogs are used by Python's gettext module. (This script was also used to check that the proper arguments to g.es and g.es_print were translated.)
- Added show-marks-dialog and show-recent-sections-dialog commands. - Select an item initially. - Added bindings for up and down arrows.
@ @rst-options code_mode=False generate_rst=True http_server_support = False show_organizer_nodes=True show_headlines=True show_leo_directives=True stylesheet_path=..\doc write_intermediate_file = False verbose=True @c

|prev| |leo| |next|

####################################### What's New in Leo 4.4.7 and Leo 4.4.8 #######################################

.. contents::
.. Links used in this document.

.. _`leoBridge chapter`: leoBridge.html .. _`debugging with Leo`: debuggers.html .. _gettext: http://docs.python.org/lib/module-gettext.html

.. WARNING: image targets may not have upper case letters!

.. |prev| image:: arrow_lt.gif :target: glossary.html

.. |leo| image:: leo.gif :target: front.html

.. |next| image:: arrow_rt.gif :target: new-4-4-6.html
- Better support for unicode in \@auto trees.

- All import commands now honor \@path

- Leo now supports arguments to minibuffer commands.

- Leo can now translate messages sent to Leo's log. Rather than using an '_' function to denote strings to be translated, Leo's g.es and g.es_print functions translate "odd" (first, third, fifth) arguments, leaving "even" arguments untranslated. Keyword arguments, color, newline, etc. are never translated. g.translateString does the actual translation using Python's `gettext`_ module.

- \@menu items may not refer to commands created by @button and @command nodes.
- Added support for @commands trees in leoSettings files.

- Added support for @bool open_with_save_on_update setting. If True, Leo will automatically save the outline whenever an external editor changes the outline.
-----------------------

|prev| |leo| |next|
@language rest
- The ipython plugin creates a simple, powerful, effective bridge between IPython and Leo. See http://webpages.charter.net/edreamleo/IPythonBridge.html

- Improved marks/recent buttons plugin.
Leo 4.4.1 through 4.4.8 contained many incremental improvements, as documented in Chapters 15 through 21 of this Users Guide.
- Supported multiple editors in body pane. - Added the jEdit_colorizer plugin. See `Chapter 15: Controlling Syntax Coloring`_. - Added the slideshow plugin.
- Added support for myLeoSettings.leo - The 'Big Reorg' made Leo's vnodes and tnode classes independent of the rest of Leo. - Added support for ZODB. See `Chapter 17: Using ZODB with Leo`_. - Added leoPymacs module. See `Chapter 18: Leo and Emacs`_. - Added the leoOPML, leo_to_rtf and leo_to_html plugins. - Added outline navigation: typing a letter selects the next outline node that starts with that letter. - Added autocontract during finds. - Added new commands and options to make Leo usable without a mouse. - Added an option sax parser for reading .leo files.
- Added support for chapters in Leo's core. - Added support for zipped .leo files. - Added the leoBridge module. See `Chapter 19: Embedding Leo with the leoBridge Module`_. - Removed all gui-dependent code from Leo's core. - Added better support for the winpdb debugger. - Added support for @enabled-plugins and @open-with nodes in settings files.
- The Great Graph Aha: Outlines don't have to *be* graphs to *represent* graphs. This Aha meant that there is no need for a separate 'graph world'. - Added support for @menus and @buttons trees in settings files. - Added perfect import of foreign files with @auto nodes. - Added new commands for resolving cvs conflicts. - Replaced the jEdit_colorizer plugin with the threading_colorizer plugin. - Made Leo compatible with jython. - Added better support for icons in headlines.
- Leo now recognizes directives in headlines. - Added support for @rst-preformat nodes to the rst3 plugin.
- Added the ILeo, the IPython bridge. See `Chapter 21: ILeo - the IPython bridge`_. - Added support for translating messages to Leo's log.
This fixes a bug that can corrupt .leo files.
http://groups.google.com/group/leo-editor/browse_thread/thread/62fe73901d14f6c3
http://groups.google.com/group/leo-editor/browse_thread/thread/f802b083dee96312
http://mail.google.com/mail/#inbox/11899019a43f74ca

When you have two editors open on the same node most actions show up in both editors, however, if you do an undo the change only show up in the selected editor. (The change shows up in the other editor when you select it).
http://groups.google.com/group/leo-editor/browse_thread/thread/71822f48720e71bc/6e0fd1c72fa39817#6e0fd1c72fa39817
The new setting is @string target_language, not @language default_target_language.
@nocolor

http://groups.google.com/group/leo-editor/browse_thread/thread/6a5087a59d6d23

- Changed menu1 to menu2 in several plugins. - Changed menu2 to menu-update. - Moved after-create-leo-frame to after menu2.
This hugely speeds up spelling when there are lots of misspelled words.
@nocolor

http://groups.google.com/group/leo-editor/browse_thread/thread/62fe73901d14f6c3

And, while you're looking at the editor code :-) - in linux when you paste in text to a body editor with a middle mouse button click, it's not stored unless you follow that with a key stroke or some other action in the body editor. If you instead middle button paste to the editor and then click on another node in the tree, the text's forgotten.

To do-->@thin ../doc/leoToDoLater.txt-->Can't or won't-->Known Bugs: can't be fixed or can wait-->Bug: can't be fixed-->Cut/paste bug on X windows (waiting for help)

@color
Leo 4.4.8 beta 3 March 28, 2008

Leo 4.4.8 beta 3 is available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

This version features a new ipython plugin that provides a two-way bridge between Leo and IPython. See http://webpages.charter.net/edreamleo/IPythonBridge.html

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.8: ---------------------------- - Leo's source code is now managed by bzr: see link below. - Leo's discussion is now hosted by Google Groups: see link below. - Arguments to g.es and g.es_print can be translated using gettext. - Completed ILeo: a bridge between IPython and Leo. See http://webpages.charter.net/edreamleo/IPythonBridge.html - Minibuffer commands may have arguments. - @menu trees can now refer to commands created by @command and @button nodes. - Added support for common @commands nodes in settings files.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Forum: http://groups.google.com/group/leo-editor Download: http://sourceforge.net/project/showfiles.php?group_id=3458 Bzr: http://code.launchpad.net/leo-editor/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
http://groups.google.com/group/leo-editor/browse_thread/thread/ed5d82429e1ec821

The following sequence of commands caused problems:

add-editor add-editor delete-editor delete-editor add-editor
Leo 4.4.8 rc1 April 3, 2008

Leo 4.4.8 rc1 is now available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

This version features a new ipython plugin that provides a two-way bridge between Leo and IPython. See http://webpages.charter.net/edreamleo/IPythonBridge.html

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.8: ---------------------------- - Leo's source code is now managed by bzr: see link below. - Leo's discussion is now hosted by Google Groups: see link below. - Arguments to g.es and g.es_print can be translated using gettext. - Completed ILeo: a bridge between IPython and Leo. See http://webpages.charter.net/edreamleo/IPythonBridge.html - Minibuffer commands may have arguments. - @menu trees can now refer to commands created by @command and @button nodes. - Added support for common @commands nodes in settings files.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Forum: http://groups.google.com/group/leo-editor Download: http://sourceforge.net/project/showfiles.php?group_id=3458 Bzr: http://code.launchpad.net/leo-editor/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
Leo 4.4.8 final April 6, 2008

Leo 4.4.8 final is now available at: http://sourceforge.net/project/showfiles.php?group_id=3458&package_id=29106

This version features a new ipython plugin that provides a two-way bridge between Leo and IPython. See http://webpages.charter.net/edreamleo/IPythonBridge.html

Leo is a text editor, data organizer, project manager and much more. See: http://webpages.charter.net/edreamleo/intro.html

The highlights of Leo 4.4.8: ---------------------------- - Leo's source code is now managed by bzr: see link below. - Leo's discussion is now hosted by Google Groups: see link below. - Arguments to g.es and g.es_print can be translated using gettext. - Completed ILeo: a bridge between IPython and Leo. See http://webpages.charter.net/edreamleo/IPythonBridge.html - Minibuffer commands may have arguments. - @menu trees can now refer to commands created by @command and @button nodes. - Added support for common @commands nodes in settings files.

Links: ------ Leo: http://webpages.charter.net/edreamleo/front.html Forum: http://groups.google.com/group/leo-editor Download: http://sourceforge.net/project/showfiles.php?group_id=3458 Bzr: http://code.launchpad.net/leo-editor/ Quotes: http://webpages.charter.net/edreamleo/testimonials.html
The purpose of ILeo, or leo-ipython bridge, is being a two-way communication channel between Leo and IPython. The level of integration is much deeper than conventional integration in IDEs; most notably, you are able to store and manipulate **data** in Leo nodes, in addition to mere program code - essentially making ILeo a hierarchical spreadsheet, albeit with non-grid view of the data. The possibilities of this are endless, and the approach can be applied in wide range of problem domains with very little actual coding.

IPython users are accustomed to using things like %edit to produce non-trivial functions/classes (i.e. something that they don't want to enter directly on the interactive prompt, but creating a proper script/module involves too much overhead). In ILeo, this task consists just going to the Leo window, creating a node and writing the code there, and pressing alt+I (push-to-ipython).

Obviously, you can save the Leo document as usual - this is a great advantage of ILeo over using %edit, you can save your experimental scripts all at one time, without having to organize them into script/module files (before you really want to, of course!)
You need at least Leo 4.4.8, and IPython 0.8.3

The ILeo concept is still being developed actively, so if you want to get access to latest features you can get IPython from Launchpad by installing bzr and doing::

bzr branch lp:ipython cd ipython python eggsetup.py develop

You need to enable the 'ipython.py' plugin in Leo:

- Help -> Open LeoSettings.leo

- Edit @settings-->Plugins-->@enabled-plugins, add/uncomment 'ipython.py'

- Alternatively, you can add @settings-->@enabled-plugins with body ipython.py to your leo document.

- Restart Leo. Be sure that you have the console window open (start leo.py from console, or double-click leo.py on windows)

- Press alt+shift+i OR alt-x start-ipython to launch IPython in the console that started leo. You can start entering IPython commands normally, and Leo will keep running at the same time.

- Note that you can just press alt-I (push-to-ipython) - it will start IPython if it has not been previously started. However, when you open a new leo document, you have to execute start-ipython (alt+shift+I) again to tell IPython that the new commands should target the new document. IPython session will not be restarted, only the leo commander object is updated in the existing session.

- If you want to specify command line arguments to IPython (e.g. to choose a profile, or to start in 'pylab' mode), add this to your @settings: '@string ipython_argv = ipython -pylab' (where -pylab is the command line argument)
IPython code ------------

Just enter IPython commands on a Leo node and press alt-I to execute push-to-ipython in order to execute the script in IPython. 'commands' is interpreted loosely here - you can enter function and class definitions, in addition to the things you would usually enter at IPython prompt - calculations, system commands etc.

Everything that would be legal to enter on IPython prompt is legal to execute from ILeo.

Results will be shows in Leo log window for convenience, in addition to the console.

Suppose that a node had the following contents::

1+2 print "hello" 3+4

def f(x): return x.upper()

f('hello world')

If you press alt+I on that node, you will see the following in Leo log window (IPython tab)::

In: 1+2 <2> 3 In: 3+4 <4> 7 In: f('hello world') <6> 'HELLO WORLD'

(numbers like <6> mean IPython output history indices; the actual object can be referenced with _6 as usual in IPython).

Plain Python code -----------------

If the headline of the node ends with capital P, alt-I will not run the code through IPython translation mechanism but use the direct python 'exec' statement (in IPython user namespace) to execute the code. It wont be shown in IPython history, and sometimes it is safer (and more efficient) to execute things as plain Python statements. Large class definitions are good candidates for P nodes.
The real fun starts when you start entering text to leo nodes, and are using that as data (input/output) for your IPython work.

Accessing Leo nodes happens through the variable **wb** (short for "WorkBook") that exist in the IPython user namespace. Nodes that are directly accessible are the ones that have simple names which could also be Python variable names; 'foo_1' will be accessible directly from IPython, whereas 'my scripts' will not. If you want to access a node with arbitrary headline, add a child node '@a foo' (@a stands for 'anchor'). Then, the parent of '@a foo' is accessible through 'wb.foo'.

You can see what nodes are accessible be entering (in IPython) wb.<TAB>. Example::

[C:leo/src]|12> wb. wb.b wb.tempfile wb.rfile wb.NewHeadline wb.bar wb.Docs wb.strlist wb.csvr [C:leo/src]|12> wb.tempfile <12> <ipy_leo.LeoNode object at 0x044B6D90>

So here, we meet the 'LeoNode' class that is your key to manipulating Leo content from IPython!

LeoNode -------

Suppose that we had a node with headline 'spam' and body::

['12',2222+32]

we can access it from IPython (or from scripts entered into other Leo nodes!) by doing::

C:leo/src]|19> wb.spam.v <19> ['12', 2254]

'v' attribute stands for 'value', which means the node contents will be run through 'eval' and everything you would be able to enter into IPython prompt will be converted to objects. This mechanism can be extended far beyond direct evaluation (see '@cl definitions').

'v' attribute also has a setter, i.e. you can do::

wb.spam.v = "mystring"

Which will result in the node 'spam' having the following text::

'mystring'

What assignment to 'v' does can be configured through generic functions ('simplegeneric' module, see ipy_leo.py for examples).

Besides v, you can set the body text directly through::

wb.spam.b = "some\nstring",

headline by::

wb.spam.h = 'new_headline'

(obviously you must access the node through wb.new_headline from that point onwards), and access the contents as string list (IPython SList) through 'wb.spam.l'.

If you do 'wb.foo.v = 12' when node named 'foo' does not exist, the node titled 'foo' will be automatically created and assigned body 12.

LeoNode also supports go() that focuses the node in the Leo window, and ipush() that simulates pressing alt+I on the node (beware of the possible recursion!).

You can access unknownAttributes by .uA property dictionary. Unknown attributes allow you to store arbitrary (pickleable) python objects in the Leo nodes; the attributes are stored when you save the .leo document, and recreated when you open the document again. The attributes are not visible anywhere, but can be used for domain-specific metadata. Example::

[C:leo/src]|12> wb.spam.uA['coords'] = (12,222) [C:leo/src]|13> wb.spam.uA <13> {'coords': (12, 222)}

Accessing children with iteration and dict notation ---------------------------------------------------

Sometimes, you may want to treat a node as a 'database', where the nodes children represent elements in the database. You can create a new child node for node 'spam', with headline 'foo bar' like this::

wb.spam['foo bar'] = "Hello"

And assign a new value for it by doing::

wb.spam['foo bar'].v = "Hello again"

Note how you can't use .v when you first create the node - i.e. the node needs to be initialized by simple assignment, that will be interpreted as assignment to '.v'. This is a conscious design choice.

If you try to do wb.spam['bar'] = 'Hello', ILeo will assign '@k bar' as the headline for the child instead, because 'bar' is a legal python name (and as such would be incorporated in the workbook namespace). This is done to avoid crowding the workbook namespace with extraneous items. The item will still be accessible as wb.spam['bar']

LeoNodes are iterable, so to see the headlines of all the children of 'spam' do::

for n in wb.spam: print n.h
If the first line in the body text is of the form '@cl sometext', IPython will evaluate 'sometext' and call the result with the rest of the body when you do 'wb.foo.v' or press alt+I on the node. An example is in place here. Suppose that we have defined a class (I use the term class in a non-python sense here)::

def rfile(body,node): """ @cl rfile

produces a StringIO (file like obj) of the rest of the body """

import StringIO return StringIO.StringIO(body)

(note that node is ignored here - but it could be used to access headline, children etc.),

Now, let's say you have node 'spam' with text::

@cl rfile hello world and whatever

Now, in IPython, we can do this::

[C:leo/src]|22> f = wb.spam.v [C:leo/src]|23> f <23> <StringIO.StringIO instance at 0x04E7E490> [C:leo/src]|24> f.readline() <24> u'hello\n' [C:leo/src]|25> f.readline() <25> u'world\n' [C:leo/src]|26> f.readline() <26> u'and whatever' [C:leo/src]|27> f.readline() <27> u''

You should declare new @cl types to make ILeo as convenient your problem domain as possible. For example, a "@cl etree" could return the elementtree object for xml content.
@ipy-startup ------------

If this node exist, the *direct children* of this will be pushed to IPython when ILeo is started (you press alt+shift-i). Use it to push your own @cl definitions, import the modules you will be using elsewhere in the document, etc.

The contents of of the node itself will be ignored.

@ipy-results ------------

If you press alt+I on a node that has @cl, it will be evaluated and the result will be put into this node. Otherwise, it will just be displayed in log tab.

@ipy-root ---------

You can set up a subportion of the leo document as a "sandbox" for your IPython work. Only the nodes under @ipy-root will be visible through the 'wb' variable.

Also, when you create a new node (wb.foo.v = 'stuff'), the node foo will be created as a child of this node.

@a nodes --------

You can attach these as children of existing nodes to provide a way to access nodes with arbitrary headlines, or to provide aliases to other nodes. If multiple @a nodes are attached as children of a node, all the names can be used to access the same object.
Sometimes, you might want to configure what alt+I on a node does. You can do that by creating your own push function and expose it using ipy_leo.expose_ileo_push(f, priority). The function should check whether the node should by handled by the function and raise IPython.ipapi.TryNext if it will not do the handling, giving the next function in the chain a chance to see whether it should handle the push.

This example would print an uppercase version of node body if the node headline ends with U (yes, this is completely useless!)::

def push_upcase(node): if not node.h.endswith('U'): raise TryNext print node.b.upper()

ipy_leo.expose_ileo_push(push_upcase, 12)

(the priority should be between 0-100, with 0 being the highest (first one to try) - typically, you don't need to care about it and can usually omit the argument altogether)
Get list of all headlines of all the nodes in leo::

[node.h for node in wb]

Create node with headline 'baz', empty body::

wb.baz

Create 10 child nodes for baz, where i is headline and 'Hello ' + i is body::

for i in range(10): wb.baz[i] = 'Hello %d' % i

Create 5 child nodes for the current node (note the use of special _p variable, which means "current node") and moves focus to node number 5::

for i in range(10): _p[i] = 'hello %d' % d _p[5].go()
This idea got started when I (Ville M. Vainio) saw this post by Edward Ream (the author of Leo) on IPython developer mailing list:

http://lists.ipython.scipy.org/pipermail/ipython-dev/2008-January/003551.html

I was using FreeMind as mind mapping software, and so I had an immediate use case for Leo (which, incidentally, is superior to FreeMind as mind mapper). The wheels started rolling, I got obsessed with the power of this concept (everything clicked together), and Edwards excitement paralleled mine. Everything was mind-bogglingly easy/trivial, something that is typical of all promising technologies.

Discussions_ on SourceForge show how the goal of close cooperation between Leo and IPython went from vague dream to completed reality over the span of about 10 days.

%mb ---

Execute leo minibuffer command. Tab completion works. Example::

mb open-outline

%lee ----

Stands for "LEo Edit". Allows you to open file(s), and even objects in Leo for editing. Examples::

lee *.txt

Opens all txt files in @auto nodes

::

lee MyMacro

Opens the macro MyMacro for editing. Press alt-I to push the edited macro back to IPython.

::

s = 'hello word' lee s

Opens the variable s for editing. Press alt+I to push the new value to IPython.

::

lee hist

Opens IPython interactive history (both input and output) in Leo.
If you install matplotlib and numpy, you can use ILeo to interactively edit and view your data. This is convenient for storing potentially valuable information in Leo document, and yields an interactive system that is comparable in convenience to various commercial mathematical packages (at least if you compare it agains plain IPython, that forgets the data on exit unless explicitly saved to data files or %store:d).

Startup -------

It's probably safest to rely on TkAgg backend, to avoid two event loops running in the same process. TkAgg is the default, so the only thing you need to do is to install numpy and matplotlib::

easy_install numpy easy_install matplotlib

Finally, you need to start up IPython with '-pylab' option. You can accomplish this by having the following under some @settings node::

@string ipython_argv = ipython -pylab

Then, you just need to press alt+I to launch IPython.

Usage -----

The simplest use case is probably pushing an existing array to Leo for editing. Let's generate a simple array and edit it::

[c:/ipython]|51&gt; a = arange(12).reshape(3,4) [c:/ipython]|52&gt; a &lt;52&gt; array([[ 0, 1, 2, 3], [ 4, 5, 6, 7], [ 8, 9, 10, 11]]) [c:/ipython]|53&gt; %lee a

This (the magic command %lee, or 'leo edit') will open variable 'a' for editing in Leo, in a convenient pretty-printed format. You can press alt+I on the node to push it back to IPython.

If you want to store the variable in a node with a different name (myarr), you can do::

[c:/ipython]|54&gt; wb.myarr.v = a

Then, you can always get the value of this array with wb.myarr.v. E.g. you could have a node that plots the array, with content::

# press alt+i here to plot testarr

plot(wb.myarr.v)

And, as per instructions, pressing alt+I will launch a new Tk window with the plotted representation of the array! </t>
Sometimes you may decide to launch Leo when an IPython session is already running. This is typically the case when IPython is launched from/as another application (Turbogears/Django shell, Sage, etc.), or you only decide later on that you might want to roll up some scripts or edit your variables in Leo.

Luckily, this is quite easy, if not automatic (yet) using IPython's %run command that runs python code in the IPython process. The only special consideration is that we need to run IPython.Shell.hijack_tk() to prevent Leo Tk mainloop from blocking IPython in %run. Here we launch an embedded Leo instance, and create a macro 'embleo' for later use (so that we don't have to repeat these steps)::

IPython 0.8.3.bzr.r57 [on Py 2.5.1] [C:opt/Console2]|2> import IPython.Shell [C:opt/Console2]|3> IPython.Shell.hijack_tk() [C:opt/Console2]|4> cd c:/leo/leo/src [c:leo/src]|5> %run leo.py

reading settings in C:\leo\leo\config\leoSettings.leo

... Leo is starting at this point, but IPython prompt returns ...

[c:leo/src]|6> macro embleo 2-5

[c:leo/src]|7> store embleo Stored 'embleo' (Macro)

Now, in Leo, you only need to press Alt+Shift+I (launch-ipython) to actually make the document visible in IPython. Despite the name, launch-ipython will not create a new instance of IPython; if an IPython session already exists, it will be automatically used by ILeo.