# Plugins¶

This chapter discusses the plugins contained in leoPlugins.leo. These plugins are part of Leo’s official distribution. The next chapter, 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 Using @button nodes. Script buttons are extraordinarily useful.

## Enabling plugins¶

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 processed @enabled-plugins node.

## Summary¶

active_path.py
Synchronizes @path nodes with folders.
add_directives.py
Allows users to define new @directives.
at_folder.py
Synchronizes @folder nodes with folders.
at_produce.py
Executes commands in nodes whose body text starts with @produce.
at_view.py
Adds support for @clip, @view and @strip nodes.
attrib_edit.py
Edits user attributes in a Qt frame.
backlink.py
bibtex.py
Manages BibTeX files with Leo.
bigdash.py
Creates a global search window.
bzr_qcommands.py
Adds a context menu to each node containing all the commands in the bzr Qt interface. Bzr is invoked based on the path of the current node.
chapter_hoist.py
Creates hoist buttons.
colorize_headlines.py
Manipulates appearance of individual tree widget items.
contextmenu.py
Defines various useful actions for context menus (Qt only).
datenodes.py
Allows users to insert headlines containing dates.
debugger_pudb.py
Makes g.pdb() enter the Pudb debugger instead of pdb.
detect_urls.py
Colorizes URLs everywhere in a node’s body on node selection or saving. Double clicking on any URL launches it in the default browser.
dtest.py
Sends code to the doctest module and reports the result.
dump_globals.py
Dumps Python globals at startup.
EditAttributes.py
Lets the user associate text with a specific node.
empty_leo_file.py
Allows Leo to open any empty file as a minimal .leo file.
enable_gc.py
Enables debugging and tracing for Python’s garbage collector.
expfolder.py
Adds @expfolder nodes that represent folders in the file system.
FileActions.py
Defines actions taken when double-clicking on @<file> nodes and supports @file-ref nodes.
geotag.py
Tags nodes with latitude and longitude.
graphcanvas.py
Adds a graph layout for nodes in a tab. Requires Qt and the backlink.py plugin.
import_cisco_config.py
Allows the user to import Cisco configuration files.
initinclass.py
Modifies the Python @auto importer so that the importer puts the __init__ method (ctor) into the body of the class node.
interact.py
Adds buttons so Leo can interact with command line environments.
ipython.py
Creates a two-way communication (bridge) between Leo scripts and IPython running in the console from which Leo was launched.
leo_interface.py
Allows the user to browse XML documents in Leo.
leo_pdf.py
This NOT a Leo plugin: this is a docutils writer for .pdf files.
leo_to_html.py
Converts a leo outline to an html web page.**.
leo_to_rtf.py
Outputs a Leo outline as a numbered list to an RTF file. The RTF file can be loaded into Microsoft Word and formatted as a proper outline.
leocursor.py
Creates a LeoCursor object that can walk around a Leo outline and decode attributes from nodes.
leomylyn.py
Provides a “Mylyn” like experience for Leo.
leoremote.py
Remote control for Leo.
leoscreen.py
Allows interaction with shell apps via screen.
lineNumbers.py
Adds #line directives in perl and perlpod programs.
livecode.py
Creates a live code-evaluation pane.
macros.py
Creates new nodes containing parameterized section references.
maximizeNewWindows.py
Maximizes all new windows.
mime.py
Opens files with their default platform program.
mod_autosave.py
Autosaves the Leo outline every so often.
mod_framesize.py
Sets a hard coded frame size.
mod_http.py
A minimal http plugin for Leo, based on AsyncHttpServer.py.
mod_read_dir_outline.py
Allows Leo to read a complete directory tree into a Leo outline. Converts directories into headlines and puts the list of file names into bodies.
mod_scripting.py
Creates script buttons and @button, @command, @plugin and @script nodes.
mod_timestamp.py
Timestamps all save operations to show when they occur.
multifile.py
Allows Leo to write a file to multiple locations.
nav_qt.py
Adds “Back” and “Forward” buttons (Qt only).
niceNosent.py
Ensures that all descendants of @file-nosent nodes end with exactly one newline, replaces all tabs with spaces, and adds a newline before class and functions in the derived file.
nodeActions.py
Allows the definition of double-click actions.
nodeTags.py
Provides node tagging capabilities to Leo.
open_shell.py
Creates an ‘Extensions’ menu containing two commands: Open Console Window and Open Explorer.
outline_export.py
Modifies the way exported outlines are written.
paste_as_headlines.py
Creates new headlines from clipboard text.
plugins_menu.py
pretty_print.py
Customizes pretty printing.
printing.py
Supports printing for the Qt gui.
projectwizard.py
Creates a wizard that creates @auto nodes.
quickMove.py
Creates buttons to move nodes quickly to other nodes.
quicksearch.py
Adds a fast-to-use search widget, like the “Find in files” feature of many editors.
quit_leo.py
Shows how to force Leo to quit.
read_only_nodes.py
redirect_to_log.py
Sends all output to the log pane.
run_nodes.py
Runs a program and interface Leos through its input/output/error streams.
screen_capture.py
Supports taking screen shots. See http://leo-editor.github.io/screen_capture.html
screenshots.py
Creates stand-alone slideshows containing screenshots.
script_io_to_body.py
Sends output from the Execute Script command to the end of the body pane.
scripts_menu.py
Creates a Scripts menu for LeoPy.leo.
scrolledmessage.py
Provides a Scrolled Message Dialog service for Qt.
setHomeDirectory.py
Sets g.app.homeDir to a hard-coded path.
slideshow.py
Support slideshows in Leo outlines.
spydershell.py
startfile.py
Launches (starts) a file given by a headline when double-clicking the icon.
stickynotes.py
Adds simple “sticky notes” feature (popout editors) for Qt gui.
timestamp.py
Manages attributes containing node creation/modification/viewed times.
todo.py
Provides to-do list and simple task management for leo (Qt only).
tomboy_import.py
Allows imports of notes created in Tomboy / gnote.
trace_gc_plugin.py
Traces changes to Leo’s objects at idle time.
trace_keys.py
Traces keystrokes in the outline and body panes.
trace_tags.py
Traces most common hooks, but not key, drag or idle hooks.
valuespace.py
Supports outline-based calculations similar to spreadsheets.
viewrendered.py
Creates a window for live rendering of rst, html, etc. This plugin uses docutils, http://docutils.sourceforge.net/, to do the rendering, so installing docutils is recommended. Supports @graphics-script, @image, @html, @movie and @svg nodes.
viewrendered2.py
An alternate/enhanced version of viewrendered.py.
vim.py
Enables two-way communication with VIM.
word_count.py
Counts characters, words, lines, and paragraphs in the body pane.
word_export.py
Adds the Plugins:Word Export:Export menu item to format and export the selected outline to a Word document, starting Word if necessary.
xemacs.py
Allows you to edit nodes in emacs/xemacs.
xsltWithNodes.py
zenity_file_dialogs.py
Replaces Leo’s file dialogs on Linux with external calls to the zenity gtk dialog package.

## Gui-independent plugins¶

### Commands & directives¶

Allows users to define new @directives.

#### bzr_qcommands.py¶

Adds a context menu to each node containing all the commands in the bzr Qt interface. Bzr is invoked based on the path of the current node.

#### empty_leo_file.py¶

Allows Leo to open any empty file as a minimal .leo file.

#### import_cisco_config.py¶

Allows the user to import Cisco configuration files.

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.

#### initinclass.py¶

Modifies the Python @auto importer so that the importer puts the __init__ method (ctor) into the body of the class node.

This makes it easier to keep the instance variable docs in the class docstring in sync. with the ivars as manipulated by __init__, saves repeating explanations in both places.

Note that this is done after the consistency checks by the @auto import code, so using this plugin is at your own risk. It will change the order of declarations if other methods are declared before __init__.

#### leo_interface.py¶

Allows the user to browse XML documents in Leo.

This file implements an interface to XML generation, so that the resulting file can be processed by leo.

#### lineNumbers.py¶

Adds #line directives in perl and perlpod programs.

Over-rides two methods in leoAtFile.py to write #line directives after node sentinels. This allows compilers to give locations of errors in relation to the node name rather than the filename. Currently supports only perl and perlpod.

#### macros.py¶

Creates new nodes containing parameterized section reference.

This plugin adds nodes under the currently selected tree that are to act as section references. To do so, go the Outline menu and select the ‘Parameterize Section Reference’ command. This plugin looks for a top level node called ‘Parameterized Nodes’. If it finds a headline that matches the section reference it adds a node/nodes to the current tree.

To see this in action, do the following:

1. Important: in the examples below, type << instead of < < and type >> instead of > >. Docstrings can not contain section references!

2. Create a node called ‘Parameterized Nodes’, with a sub-node called < < Meow >>. The body of < < Meow > > should have the text:

I mmmm sooo happy I could  < < 1$> >. But I don't know if I have all the < < 2$  > >
money in the world.

3. In a node called A, type:

< < meow( purrrrrr, zzooot )  > >
(leave the cursor at the end of the line)

4. In a node called B, type:

 < < meow ( spit or puke, blinking  )  > >
(leave the cursor at the end of the line)

5. Leave the cursor in Node A at the designated point.

6. Go to Outline and select Parameterize Section Reference.

The plugin searches the outline, goes to level one and finds a Node with the Headline, “Parameterized Nodes”. It looks for nodes under that headline with the the headline << meow >>. It then creates this node structure under Node A:

< < meow ( purrrrrr, zzooot ) > >
< <2$> > < <1$> >

1. Examine the new subnodes of Node A:

< < meow ( purrrrrr, zzooot ) > > contains the body text of the < < meow > > node. < < 1$> > contains the word purrrrrr. < < 2$ > > contains the word zzooot.

2. Go to Node B, and leave the cursor at the designated point.

Go to Outline Menu and select Parameterize Section Reference command.

1. Examine the new subnodes of Node B.

It’s a lot easier to use than to explain!

#### mod_autosave.py¶

Autosaves the Leo outline every so often.

The time between saves is given by the setting, with default as shown:

@int mod_autosave_interval = 300


This plugin is active only if:

@bool mod_autosave_active = True


Allows Leo to read a complete directory tree into a Leo outline. Converts directories into headlines and puts the list of file names into bodies.

Ce plug-in permet de traduire l’arborescence d’un répertoire en une arborescence Leo : Chaque dossier est converti en noeud dans Leo ; son nom est placé dans l’entête du noeud et chaque nom de fichier qu’il contient est listé dans son contenu.

Feedback on this plugin can be sent to:

Frédéric Momméja
<frederic [point] mommeja [at] laposte [point] net>


#### mod_timestamp.py¶

Timestamps all save operations to show when they occur.

#### nodeActions.py¶

Allows the definition of double-click actions.

When the user double-clicks a node this plugin checks for a match of the clicked node’s headline text with a list of patterns. If a match occurs, the plugin executes the associated script.

nodeAction nodes may be located anywhere in the outline. Such nodes should contain one or more pattern nodes as children. The headline of each pattern node contains the pattern; the body text contains the script to be executed when the pattern matches the double-clicked node.

For example, the “nodeActions” node containing a “launch URL” pattern node and a “pre-process python code” node could be placed under an “@settings” node:

@settings
|
+- nodeActions
|
+- http:\\*
|
+- @file *.py


Configuration

The nodeActions plugin supports the following global configurations using Leo’s support for setting global variables within an @settings node’s sub-nodes in the leoSettings.leo, myLeoSettings.leo, and the project Leo file:

@bool nodeActions_save_atFile_nodes = False

True: Double-click on an @file type node will save the file to disk before executing the script. Double-click on an @file type node will not save the file to disk before executing the script. (default)

@int nodeActions_message_level = 1

Specifies the type of messages to be sent to the log pane. Specifying a higher message level will display that level and all lower levels. The following integer values are supported:

0 no messages
1 Plugin triggered and the patterns that were matched (default)
2 Double-click event passed or not to next plugin
3 Patterns that did not match
4 Code debugging messages


Patterns

Pattern matching is performed using python’s support for Unix shell-style patterns unless overwritten by the “X” pattern directive. The following pattern elements are supported:

*           matches everything
?           matches any single character
[<seq>]     matches any character in <seq>
[!<seq>]    matches any character **not** in <seq>


Unix shell-style pattern matching is case insensitive and always starts from the beginning of the headline. For example:

Pattern Matches Does not match
*.py Abc_Test.py
.py .py - Test Abc_Test.py
test* Test_Abc.py Abc_Test.py

To enable a script to run on any type of @file node (@thin, @shadow, ...), the pattern can start with “@files” to match on any external file type. For example, the pattern “@files *.py” will match a node with the headline “@file abcd.py”.

The headline of the double-clicked node is matched against the patterns starting from the first sub-node under the “nodeActions” node to the last sub-node.

Only the script associated with the first matching pattern is invoked unless overwritten by the “V” pattern directive.

Using the “V” pattern directive allows a broad pattern such as “@files *.py” to be invoked, and then, by placing a more restrictive pattern above it, such as “@files *_test.py”, a different script can be executed for those files requiring pre-processing:

+- nodeActions
|
+- @files *_test.py
|
+- @files *.py


Note: To prevent Leo from trying to save patterns that begin with a derived file directive (@file, @auto, ...) to disk, such as “@file *.py”, place the “@ignore” directive in the body of the “nodeActions” node.

Pattern nodes can be placed at any level under the “nodeActions” node. Only nodes with no child nodes are considered pattern nodes. This allows patterns that are to be used in multiple Leo files to be read from a file. For example, the following structure reads the pattern definition from the “C:\Leo\nodeActions_Patterns.txt” file:

+- nodeActions
|
+- @files C:\\Leo\\nodeActions_Patterns.txt
|
+- http:\\*
|
+- @file *.py


Pattern directives

The following pattern specific directives can be appended to the end of a pattern (do not include the ‘:’):

[X]: Use python’s regular expression type patterns instead of the Unix shell-style pattern syntax. For example, the following patterns will match the same headline string: Unix shell-style pattern: @files *.py Regular Expression pattern: ^@files .*\.py$[X]  Matching the pattern will not block the double-click event from being passed to the remaining patterns. The “V” represents a down arrow that symbolizes the passing of the event to the next pattern below it. For example, adding the “[V]” directive to the “@files *_test.py” in the Patterns section above, changes its script from being ‘an alternate to’ to being ‘a pre-processor for’ the “@files *.py” script: +- nodeActions | +- @files *_test.py [V] | +- @files *.py  Matching the pattern will not block the double-click event from being passed to other plugins. The “>” represents a right arrow that symbolizes the passing of the event to the next plugin. If the headline matched more than one headline, the double-click event will be passed to the next plugin if the directive is associated with any of the matched patterns. The directive(s) for a pattern must be contained within a single set of brackets, separated from the pattern by a space, with or without a comma separator. For example, the following specifies all three directives: ^@files .*\.py$ [X,V>]


Scripts

The script for a pattern is located in the body of the pattern’s node. The following global variables are available to the script:

c
g
pClicked - node position of the double-clicked node
pScript - node position of the invoked script


Examples

Double-clicking on a node with a “http:\\www.google.com” headline will invoke the script associated with the “http:\\*” pattern. The following script in the body of the pattern’s node displays the URL in a browser:

import webbrowser
hClicked = pClicked.h     #Clicked node's Headline text
webbrowser.open(hClicked) #Invoke browser


The following script can be placed in the body of a pattern’s node to execute a command in the first line of the body of a double-clicked node:

g.os.system('"Start /b ' + pClicked.bodyString() + '"')


#### outline_export.py¶

Modifies the way exported outlines are written.

Creates new headlines from clipboard text.

If the pasted text would be greater than 50 characters in length, the plugin truncates the headline to 50 characters and pastes the entire line into the body text of that node. Creates a “Paste as Headlines” option the Edit menu directly under the existing Paste option.

#### pretty_print.py¶

Customizes pretty printing.

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

#### quickMove.py¶

Creates buttons to move nodes quickly to other nodes.

Quickly move/copy/clone nodes from around the tree to one or more target nodes. It can also create bookmark and tagging functionality in an outline (see Set Parent Notes below).

Select a node Foo and then use the Move To Last Child Button command. This adds a ‘to Foo’ button to the button bar. Now select another node and click the ‘to Foo’ button. The selected node will be moved to the last child of the node ‘Foo’.

To First Child Button works the same way, except that moved nodes are inserted as the first child of the target node.

Clone and Copy variants are like Move, but clone or copy instead of moving.

Link works in conjunction with the backlink plugin (and also the graphcanvas plugin) creating a link to/from the target and current nodes.

Jump buttons act as bookmarks, taking you to the target node.

You can right click on any of these buttons to access their context menu:

Goto Target
takes you to the target node (like a Jump button).
Make Permanent
makes the button permanent, it will reappear when the file is saved / closed / re-opened.
Set Parent
allows you to move buttons to sub-menu items of other quickMove buttons. This implicitly makes the moved button permanent. It also causes the moved button to lose its context menu.
Remove Button
comes from the mod_scripting plugin, and just removes the button for the rest of the current session.
Set Parent Notes
Set Parent doesn’t allow you to do anything with quickMove you couldn’t do with a long strip of separate buttons, but it collects quickMove buttons as sub-menu items of one quickMove button, saving a lot of toolbar space.
Bookmarks

Create somewhere out of the way in your outline a node called Bookmarks. Use the quickMove menu to make it a Jump To button, and use its context menu to make it permanent. There is no particular reason to jump to it, but it needs to be a quickMove button of some kind.

Now, when you want to bookmark a node, first use the quickMove menu to make the node a Jump To button, and then use the context menu on the button to set its parent to your Bookmarks button. It becomes a sub-menu item of the Bookmarks button.

Tags

In conjunction with the backlinks plugin you can use quickMove to tag nodes. The backlinks plugin adds a Links tab to the Log pane.

To see the tags on a node, you need to be looking at the Links tab in the Log pane. To see all the nodes with a particular tag, click on the Tags button to jump to the tag list, and select the node which names the tag of interest. The nodes with that tag will be listed in th Links tab in the Log pane.

#### setHomeDirectory.py¶

Sets g.app.homeDir to a hard-coded path.

#### word_count.py¶

Counts characters, words, lines, and paragraphs in the body pane.

It adds a “Word Count...” option to the bottom of the Edit menu that will activate the command.

### Debugging¶

#### debugger_pudb.py¶

Makes g.pdb() enter the Pudb debugger instead of pdb.

Pudb is a full-screen Python debugger: http://pypi.python.org/pypi/pudb

#### dump_globals.py¶

Dumps Python globals at startup.

#### enable_gc.py¶

Enables debugging and tracing for Python’s garbage collector.

#### quit_leo.py¶

Shows how to force Leo to quit.

#### trace_gc_plugin.py¶

Traces changes to Leo’s objects at idle time.

#### trace_keys.py¶

Traces keystrokes in the outline and body panes.

#### trace_tags.py¶

Traces most common hooks, but not key, drag or idle hooks.

### External programs¶

#### ipython.py¶

Creates a two-way communication (bridge) between Leo scripts and IPython running in the console from which Leo was launched.

Using this bridge, scripts running in Leo can affect IPython, and vice versa. In particular, scripts running in IPython can alter Leo outlines!

For full details, see Leo Users Guide: http://leoeditor.com/IPythonBridge.html

#### open_shell.py¶

Creates an ‘Extensions’ menu containing two commands: Open Console Window and Open Explorer.

The Open Console Window command opens xterm on Linux. The Open Explorer command Opens a Windows explorer window.

This allows quick navigation to facilitate testing and navigating large systems with complex directories.

Current limitations: - Not tested on Mac OS X ... - On Linux, xterm must be in your path.

#### tomboy_import.py¶

Allows imports of notes created in Tomboy / gnote.

Usage:

• Create a node with the headline ‘tomboy’
• Select the node, and do alt+x act-on-node
• The notes will appear as children of ‘tomboy’ node
• The next time you do act-on-node, existing notes will be updated (they don’t need to be under ‘tomboy’ node anymore) and new notes added.

#### vim.py¶

Enables two-way communication with gvim (recommended) or vim. with the following commands:

vim-open-file
Opens the nearest ancestor @file or @clean node in vim. Leo will update the file in the outline when you save the file in vim.
vim-open-node
Opens the selected node in vim. Leo will update the node in the outline when you save the file in vim.

#### xemacs.py¶

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.

#### word_export.py¶

Adds the Plugins:Word Export:Export menu item to format and export the selected outline to a Word document, starting Word if necessary.

### Files and nodes¶

#### active_path.py¶

Synchronizes @path nodes with folders.

If a node is named '@path path_to_folder’, the content (file and folder names) of the folder and the children of that node will synchronized whenever the node’s status-iconbox is double clicked.

For files not previously seen in a folder a new node will appear on top of the children list (with a mark).

Folders appear in the list as /foldername/. If you double click on the icon-box of the folder node, it will have children added to it based on the contents of the folder on disk. These folders have the '@path‘ directive as the first line of their body text.

When files are deleted from the folder and the list is updated by double clicking the files will appear in the list as filename (or /foldername/).

You can describe files and directories in the body of the nodes.

You can organize files and directories with organizer nodes, an organizer node name cannot contain with ‘/’.

Files and folders can be created by entering a node with the required name as its headline (must start and/or end with “/” for a folder) and then double clicking on the node’s status-iconbox.

@auto nodes can be set up for existing files can be loaded by double clicking on the node’s status-iconbox. If you prefer @shadow or something else use the “active_path_attype” setting, without the “@”.

There are commands on the Plugins active_path submenu:

• show path - show the current path
• set absolute path - changes a node “/dirname/” to “@path /absolute/path/to/dirname”.
• purge vanished (recursive) - remove entries
• update recursive - recursive load of directories, use with caution on large file systems

If you want to use an input other than double clicking a node’s status-iconbox set active_path_event to a value like ‘iconrclick1’ or ‘iconclick1’.

There are @settings for ignoring directory entries and automatically loading files. re.search is used, rather than re.match, so patterns need only match part of the filename, not the whole filename.

The body of the @setting @data active_path_ignore is a list of regex patterns, one per line. Directory entries matching any pattern in the list will be ignored. The names of directories used for matching will have forward slashes around them (‘/dirname/’), so patterns can use this to distinguish between directories and files.

The body of the @setting @data active_path_autoload is a list of regex patterns, one per line. File entries matching any pattern in the list will be loaded automatically. This works only with files, not directories (but you can load directories recursively anyway).

Set @bool active_path_load_docstring = True to have active_path load the docstring of .py files automatically. These nodes start with the special string:

@language rest # AUTOLOADED DOCSTRING


which must be left intact if you want active path to be able to double-click load the file later.

@float active_path_timeout_seconds (default 10.) controls the maximum time active_path will spend on a recursive operation.

@int active_path_max_size (default 1000000) controls the maximum size file active_path will open without query.

active_path is a rewrite of the at_directory plugin to use @path directives (which influence @auto and other @file type directives), and to handle sub-folders more automatically.

#### at_folder.py¶

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.

#### at_produce.py¶

Executes commands in nodes whose body text starts with @produce.

WARNING: trying to execute a non-existent command will hang Leo.

To use, put in the body text of a node:

@produce echo hi


This plugin creates two new commands: at-produce-all and at-produce-selected.

at-produce-all scans the entire tree for body text containing @produce. at-produce-selected just scans the selected tree.

Whatever follows @produce is executed as a command.

@produce commands are executed in the order they are found, that is, in outline order.

The at-produce commands produce a log node as the last top-level node of the outline. Any output, including error messages, should be there.

This plugin is not intended as a replacement for make or Ant, but as a simple substitute when that machinery is overkill.

#### at_view.py¶

Adds support for @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.

#### datenodes.py¶

Allows users to insert headlines containing dates.

‘Date nodes’ are nodes that have dates in their headlines. They may be added to the outline one at a time, a month’s-worth at a time, or a year’s-worth at a time. The format of the labels (headlines) is configurable.

There are options to omit Saturdays and Sundays.

An ‘Insert Date Nodes ...’ submenu will be created (by default) in the ‘Outline’ menu. This menu can be suppressed by using either of the following settings:

- @bool suppress-datenodes-menus


The following commands are available for use via the minibuffer or in @menu/@popup settings:

- datenodes-today
- datenodes-this-month
- datenodes-this-year


#### expfolder.py¶

Adds @expfolder nodes that represent folders in the file system.

Double clicking on the icon of an @expfolder heading reads the files in the directory at the path specified and creates child nodes for each file in the subfolder. Subdirectories are made into child @expfolder nodes so the tree can be easily traversed. If files have extensions specified in the expfolder.ini file they are made into @text nodes so the content of the files can be easily loaded into leo and edited. Double clicking a second time will delete all child nodes and refresh the directory listing. If there are any changed @text nodes contained inside you will be prompted about saving them.

The textextensions field on the expfolder Properties page contains a list of extensions which will be made into @text nodes, separated by spaces.

For the @text and @expfolder nodes to interact correctly, the textnode plugin must load before the expfolder plugin. This can be set using the Plugin Manager’s Plugin Load Order pane.

#### FileActions.py¶

Defines actions taken when double-clicking on @<file> nodes and supports @file-ref nodes.

Double-clicking any kind of @<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 these elements:

• ‘c’ and ‘g’ and ‘p’: as in the regular execute script command.
• ‘filename’: 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 all kinds @<file> nodes. 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.

#### geotag.py¶

Tags nodes with latitude and longitude.

#### leocursor.py¶

Creates a LeoCursor object that can walk around a Leo outline and decode attributes from nodes.

Node names can be used through . (dot) notation so cursor.Data.Name._B for example returns the body text of the Name node which is a child of the Data node which is a child of the cursors current location.

See .../plugins/examples/leocursorexample.leo for application.

#### mime.py¶

Opens files with their default platform program.

Double-clicking @mime nodes will attempt to open the named file as if opened from a file manager. @path parent nodes are used to find the full filename path. Fore example:

@mime foodir/document.pdf


The string setting ‘mime_open_cmd’ allows specifying a program to handle opening files:

@settings
@string mime_open_cmd = see
.. or ..
@string mime_open_cmd = see %s


Where ‘%s’ is replaced with the full pathname.

Note: This plugin terminates handling of the ‘icondclick1’ event by returning True. If another plugin using this event (e.g. vim.py) is also enabled, the order in @enabled-plugins matters. For example: if vim.py is enabled before mime.py, double-clicking on an @mime node will both open the body text in [g]vim AND call the mime_open_cmd.

This plugin is complementary to the UNL.py plugin’s @url nodes. Use @url for opening either URLs or Uniform Node Locators in “*.leo” files and use @mime nodes for opening files on the local file system. It also replaces the startfile.py plugin, where here the headline must start with @mime to activate this plugin.

For other sys.platform’s, add an elif case to the section “guess file association handler” and either define a default _mime_open_cmd string, where “%s” will be replaced with the filename, or define a function taking the filename string as its only argument and set as open_func.

#### multifile.py¶

Allows Leo to write a file to multiple locations.

This plugin 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-like systems):

@multipath /machine/unit/:/machine/robot/:/machine/


New in version 0.6 of this plugin: the separator used above is ‘;’ not ‘:’, for example:

@multipath c:\prog\test;c:\prog\unittest


It will places 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.

Note: I put # in front of the directives here because I don’t want someone browsing this file to accidentally save multiple copies of this file to their system!

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.

#### niceNosent.py¶

Ensures that all descendants of @file-nosent nodes end with exactly one newline, replaces all tabs with spaces, and adds a newline before class and functions in the derived file.

Here’s my first attempt at customizing leo. 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.

So I coded the directive plugin. It 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


If FTP authentication (username/password) is required, it can be specified as follows:

@read-only ftp://username:password@ftp.someserver.org/filepath


For more details, see the doc string for the class FTPurl.

Davide Salomoni

#### run_nodes.py¶

Runs a program and interface Leos 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 unlimited number of arguments to <command>.

The output of the program is written in the log pane (Error output 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)

#### startfile.py¶

Launches (starts) a file given by a headline when double-clicking the icon.

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

#### timestamp.py¶

By Kent Tenney

The timestamp plugin manages the following node attributes:

• str_ctime: creation time
• str_atime: time node contents were last viewed

#### xsltWithNodes.py¶

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.
• Creates a sibling containing the results.

### Scripting¶

#### leoscreen.py¶

Allows interaction with shell apps via screen.

Analysis environments like SQL, R, scipy, ipython, etc. can be used by pasting sections of text from an editor (Leo) and a shell window. Results can be pasted back into the editor.

This plugin streamlines the process by communicating with screen, the shell multiplexer

Commands

leoscreen-run-text
Send the text selected in Leo’s body text to the shell app. Selects the next line for your convenience.
leoscreen-get-line
Insert a line of the last result from the shell into Leo’s body text at the current insert point. Lines are pulled one at a time starting from the end of the output. Can be used repeatedly to get the output you want into Leo.
leoscreen-get-all
Insert all of the last result from the shell into Leo’s body text at the current insert point.
leoscreen-get-note
Insert all of the last result from the shell into a new child node of the current node.
leoscreen-show-all
Show the output from the last result from the shell in a temporary read only window. Important: The output is not stored.
leoscreen-show-note
Insert all of the last result from the shell into a new child node of the current node and display that node a a stickynote (requires stickynote plugin).
leoscreen-next
Switch screen session to next window.
leoscreen-prev
Switch screen session to preceding window.
leoscreen-other
Switch screen session to last window displayed.
leoscreen-get-prefix

Interactively get prefix for inserting text into body (#, –, //, etc/) Can also set using:

c.leo_screen.get_line_prefix = '#'

leoscreen-more-prompt
Skip one less line at the end of output when fetching output into Leo. Adjusts lines skipped to avoid pulling in the applications prompt line.
leoscreen-less-prompt
Skip one more line at the end of output when fetching output into Leo Adjusts lines skipped to avoid pulling in the applications prompt line.

Settings

leoscreen_prefix
Prepended to output pulled in to Leo. The substring SPACE in this setting will be replaced with a space character, to allow for trailing spaces.
leoscreen_time_fmt
time.strftime format for note type output headings.

Theory of operation

leoscreen creates a instance at c.leo_screen which has some methods which might be useful in @button and other Leo contexts.

Example SQL setup

In a Leo file full of interactive SQL analysis, I have:

@settings
@string leoscreen_prefix = --SPACE
@button rollback
import time
c.leo_screen.run_text('ROLLBACK;  -- %s\n' % time.asctime())
@button commit
import time
cmd = 'COMMIT;  -- %s' % time.asctime()
c.leo_screen.run_text(cmd)
c.leo_screen.insert_line(cmd)


which creates a button to rollback messed up queries, another to commit (requiring additional action to supply the newline as a safeguard) and sets the prefix to “– ” for text pulled back from the SQL session into Leo.

Implementation note: screen behaves differently if screen -X is executed with the same stdout as the target screen, vs. a different stdout. Although stdout is ignored, Popen() needs to ensure it’s not just inherited.

#### mod_scripting.py¶

Creates script buttons and @button, @command, @plugin and @script nodes.

This plugin puts buttons in the icon area. Depending on settings the plugin will create the ‘Run Script’, the ‘Script Button’ and the ‘Debug Script’ buttons.

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 newly created 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.
3. Select the node on which you want to run the script.
4. Push the new button.

That’s all.

For every @button node, this plugin creates two new minibuffer commands: x and delete-x-button, where x is the ‘cleaned’ name of the button. The ‘x’ command is equivalent to pushing the script button.

You can specify global buttons in leoSettings.leo or myLeoSettings.leo by putting @button nodes as children of an @buttons node in an @settings trees. Such buttons are included in all open .leo (in a slightly different color). Actually, you can specify global buttons in any .leo file, but @buttons nodes affect all later opened .leo files so usually you would define global buttons in leoSettings.leo or myLeoSettings.leo.

The cleaned name of an @button node is the headline text of the button with:

• Leading @button or @command removed,
• @key and all following text removed,
• @args and all following text removed,
• all non-alphanumeric characters converted to a single ‘-‘ characters.

Thus, cleaning headline text converts it to a valid minibuffer command name.

You can delete a script button by right-clicking on it, or by executing the delete-x-button command.

The ‘Debug Script’ button runs a script using an external debugger.

This plugin optionally scans for @button nodes, @command, @plugin nodes and @script nodes whenever a .leo file is opened.

• @button nodes create script buttons.
• @command nodes create minibuffer commands.
• @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.

You can specify the following options in leoSettings.leo. See the node: @settings–>Plugins–>scripting plugin. Recommended defaults are shown:

@bool scripting-at-button-nodes = True
True: adds a button for every @button node.

@bool scripting-at-commands-nodes = True
True: define a minibuffer command for every @command node.

@bool scripting-at-plugin-nodes = False
True: dynamically loads plugins in @plugins nodes when a window is created.

@bool scripting-at-script-nodes = False
True: dynamically executes script in @script nodes when a window is created.
This is dangerous!

@bool scripting-create-debug-button = False
True: create Debug Script button.

@bool scripting-create-run-script-button = False
True: create Run Script button.
Note: The plugin creates the press-run-script-button regardless of this setting.

@bool scripting-create-script-button-button = True
True: create Script Button button in icon area.
Note: The plugin creates the press-script-button-button
regardless of this setting.

@int scripting-max-button-size = 18
The maximum length of button names: longer names are truncated.


You can bind key shortcuts to @button and @command nodes as follows.

@button name @key=shortcut

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.

@command name @key=shortcut

Creates a new minibuffer command and binds shortcut to it. As with @buffer nodes, the name of the command is the cleaned name of the headline.

This plugin is based on ideas from e’s dynabutton plugin, quite possibly the most brilliant idea in Leo’s history.

You can run the script with sys.argv initialized to string values using @args. For example:

@button test-args @args = a,b,c


will set sys.argv to [u’a’,u’b’,u’c’]

#### script_io_to_body.py¶

Sends output from the Execute Script command to the end of the body pane.

### Servers¶

#### leoremote.py¶

Remote control for Leo.

Example client:

from leo.external import lproto
import os

pc.send("""
g.es("hello world from remote")
c = g.app.commanders()[0]
""")

# note how c persists between calls
pc.send("""c.k.simulateCommand('stickynote')""")


#### mod_http.py¶

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

2. Start a web browser, and enter the following url: http://localhost:8130/

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 = 8130
@string rst_http_attributename = 'rst_http_attribute'


Note: the browser_encoding constant (defined in the top node of this file) must match the character encoding used in the browser. If it does not, non-ascii characters will look strange.

### Slideshows and screenshots¶

#### screenshots.py¶

Creates stand-alone slideshows containing screenshots.

This plugin defines five commands. The apropos-slides command prints this message to Leo’s log pane. The slide-show-info command prints the settings in effect.

The make-slide and make-slide-show commands, collectively called slide commands, create collections of slides from @slideshow trees containing @slide nodes.

Slides may link to screenshots. The slide commands can generate screenshots from @screenshot-tree nodes, but this feature has proven to be clumsy and inflexible. It is usually more convenient to use screenshots taken with a program such as Wink. The meld-slides command creates references to externally-generated screenshots within @slide nodes.

@slide nodes may contain @url nodes. These @url nodes serve two purposes. First, they allow you to see various files (slides, initial screenshots, working files and final screenshots). Second, these @url nodes guide the meld script and the four commands defined by this plugin (see below). By inserting or deleting these @url nodes you (or your scripts) can customize how the commands (and meld) work. In effect, the @url nodes become per-slide settings.

Prerequisites

Inkscape (Required)
An SVG editor: http://www.inkscape.org/ Allows the user to edit screenshots. Required to create final output (PNG) files.
PIL (Optional but highly recommended)
The Python Imaging Library, http://www.pythonware.com/products/pil/
Wink (Optional)
A program that creates slideshows and slides. http://www.debugmode.com/wink/

Summary

@slideshow <slideshow-name>
Creates the folder: <sphinx_path>/slides/<slideshow-name>
@slide <ignored text>
Creates slide-<slide-number>.html (in the sphinx _build directory). Note: the plugin skips any @slide nodes with empty body text.
@screenshot
Specifies the contents of the screenshot.

Options are child nodes of @slideshow or @slide nodes that control the make-slide and make-slide-show commands. See the Options section below.

The make-slide and make-slide-show commands create the following @url nodes as children of each @slide node:

@url built slide
Contains the absolute path to the final slide in the _build/html subfolder of the slideshow folder. If present, this @url node completely disables rebuilding the slide.
@url screenshot
Contains the absolute path to the original screenshot file. If present, this @url node inhibits taking the screenshot.
@url working file
Contains the absolute path to the working file. If present, this @url node disables taking the screenshot, creating the working file. The final output file will be regenerated if the working file is newer than the final output file.
@url final output file
Contains the absolute path to the final output file.

Thus, to completely recreate an @slide node, you must delete any of the following nodes that appear as its children:

@url screenshot
@url working file
@url built slide


Making slides

For each slide, the make-slide and make-slide-show commands do the following:

1. Create a slide.
If the @slide node contains an @screenshot tree, the plugin appends an .. image:: directive referring to the screenshot to the body text of the @slide node. The plugin also creates a child @image node referring to the screenshot.
1. (Optional) Create a screenshot.

The plugin creates a screenshot for an @slide node only if the @slide node contains an @screenshot node as a direct child.

Important: this step has largely been superseded by the @button meld script in LeoDocs.leo.

Taking a screenshot involves the following steps:

1. Create the target outline: screenshot-setup.leo.
The target outline contains consists of all the children (and their descendants) of the @screenshot node.
1. Create the screenshot, a bitmap (PNG) file.
The slide commands take a screen shot of the target outline. The @pause option opens the target outline but does not take the screenshot. The user must take the screenshot manually. For more details, see the the options section below.
1. Convert the screenshot file to a work file.
The work file is an SVG (Scalable Vector Graphics) file: http://www.w3.org/Graphics/SVG/.
1. (Optional) Edit the work file.
If the @slide node has a child @edit node, the plugin opens Inkscape so that the user can edit the work file.
1. Render the final output file.
The plugin calls Inkscape non-interactively to render the final output file (a PNG image) from the work file. If the Python Imaging Library (PIL) is available, this step will use PIL to improve the quality of the final output file.
1. Build the slide using Sphinx.
After making all files, the plugins runs Sphinx by running ‘make html’ in the slideshow folder. This command creates the final .html files in the _build/html subfolder of the slideshow folder.
1. Create url nodes.

Depending on options, and already-existing @url nodes, the make-slide and make-slide-show commands may create one or more of the following @url nodes:

@url built slide
@url screenshot
@url working file
@url final output file


Options and settings

You specify options in the headlines of nodes. Global options appear as direct children of @slideshow nodes and apply to all @slide nodes unless overridden by a local option. Local options appear as direct children of an @slide node and apply to only to that @slide node.

Global options nodes

The following nodes may appear either as a direct child of the @slideshow node or as the direct child of an @slide node.

@sphinx_path = <path>
This directory contains the slides directory, and the following files: ‘conf.py’, ‘Leo4-80-border.jpg’, ‘Makefile’ and ‘make.bat’.
@screenshot_height = <int>
The height in pixels of screenshots.
@screenshot_width = <int>
The height in pixels of screenshots.
@template_fn = <path>
The absolute path to inkscape-template.svg
@title = <any text>
The title to use for one slide or the entire slideshow.
@title_pattern = <pattern>

The pattern used to generate patterns for one slide or the entire slideshow. The title is computed as follows:

d = {
'slideshow_name':slideshow_name,
'slide_name':    slide_name,
'slide_number':  sc.slide_number,
}
title = (pattern % (d)).title()


If neither an @title or @title_pattern option node applies, the title is the headline of the @slide node. If this is empty, the default pattern is:

'%(slideshow_name)s:%(slide_number)s'

@verbose = True/False
True (or true or 1): generate informational message. False (or false or 0): suppress informational messages.
@wink_path = <path>
This path contains screenshots created by wink. This is used only by the meld-slides command.

Local options nodes

The following nodes are valid only as the direct child of an @slide node.

@callout <any text>
Generates a text callout in the working .svg file. An @slide node may have several @callout children.
@edit = True/False
If True (or true or 1) the plugin enters Inkscape interactively after taking a screenshot.
@markers = <list of integers>
Generates ‘numbered balls’ in the working .svg file.
@pause = True/False

If True (or true or 1) the user must take the screenshot manually. Otherwise, the plugin takes the screenshot automatically.

If the slide node contains an @pause node as one of its directive children, the slide commands open the target node, but do not take a screen shot.

The user may adjust the screen as desired, for example by selecting menus or showing dialogs. The user must then take the screen shot manually. Important: the screenshot need not be of Leo–it could be a screenshot of anything on the screen.

As soon as the user closes the target outline, the slide commands look for the screen shot on the clipboard. If found, the slide commands save the screenshot to the screenshot file.

@screenshot
The root of a tree that becomes the entire contents of screenshot. No screenshot is taken if this node does not exist.
Causes the given headline in the @screenshot outline to be selected before taking the screenshot.

Settings

@string screenshot-bin = <path to inkscape.exe>
The full path to the Inkscape program.

File names

Suppose the @slide node is the n’th @slide node in the @slideshow tree whose sanitized name is ‘name’. The following files will be created in (relative to) the slideshow directory:

slide-n.html.txt:   the slide's rST source.
screenshot-n.png:   the original screenshot.
screenshot-n.svg:   the working file.
slide-n.png:        the final output file.
_build/html/slide-n.html: the final slide.


#### slideshow.py¶

Support slideshows in Leo outlines.

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

### Text formatting¶

#### bibtex.py¶

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 = {Journal1}
+@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.

#### dtest.py¶

Sends code to the doctest module and reports the result.

When the Dtest plugin is enabled, the dtest command is active. Typing:

Alt-X dtest


will run doctest on a file consisting of the current node and it’s children. If text is selected only the selection is tested.

From Wikipedia:

'Doctest' is a module included in the Python programming language's
standard library that allows for easy generation of tests based on
output from the standard Python interpreter.


http://tinyurl.com/cqh53 - Python.org doctest page

http://tinyurl.com/pxhlq - Jim Fulton’s presentation:

Literate Testing:
Automated Testing with doctest


#### leo_to_html.py¶

Converts a leo outline to an html web page.

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. It is based on the original leoToHTML 1.0 plugin by Dan Rahmel which had bullet list code by Mike Crowe.

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

Save Outline as HTML  (equivalent to export-html)
Save Node as HTML     (equivalent to export-html-node)
Show Outline as HTML  (equivalent to show-html)
Show Node as HTML     (equivalent to show-html-node)


Unless the following appears in an @setting tree:

@bool leo_to_html_no_menus = True


in which case the menus will not be created. This is so that the user can use @menu and @item to decide which commands will appear in the menu and where.

Commands

Several commands will also be made available

export-html
will export to a file according to current settings.
export-html-*
will export to a file using bullet type ‘*’ which can be number, bullet or head.

The following commands will start a browser showing the html.

show-html
will show the outline according to current settings.
show-html-*
will show the outline using bullet type ‘*’ which can be number, bullet or head.

The following commands are the same as above except only the current node is converted:

export-html-node
export-html-node-*
show-html-node
show-html-node-*


Properties

There are several settings that can appear in the leo_to_html.ini properties file in leo’s plugins folder or be set via the Plugins > leo_to_html > Properties... menu. These are:

exportpath:
The path to the folder where you want to store the generated html file. Default: c:\
Default: ‘Yes’ to include only headlines in the output.
flagignorefiles:
Default: ‘Yes’ to ignore @file nodes.
use_xhtml:
Yes to include xhtml doctype declarations and make the file valid XHTML 1.0 Strict. Otherwise only a simple <html> tag is used although the output will be xhtml compliant otherwise. Default: Yes
bullet_type:

If this is ‘bullet’ then the output will be in the form of a bulleted list. If this is ‘number’ then the output will be in the form of a numbered list. If this is ‘heading’ then the output will use <h?> style headers.

Anything else will result in <h?> type tags being used where ‘?’ will be a digit starting at 1 and increasing up to a maximum of six depending on depth of nesting. Default: number

browser_command:

Set this to the command needed to launch a browser on your system or leave it blank to use your systems default browser.

If this is an empty string or the browser can not be launched using this command then python’s webbrowser module will be tried. Using a bad command here will slow down the launch of the default browser, better to leave it blank. Default: empty string

Configuration

At present, the file leo/plugins/leo_to_html.ini contains configuration settings. In particular, the default export path, “c:” must be changed for *nix systems.

#### leo_to_rtf.py¶

Outputs a Leo outline 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 Leoplugins 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.

### User interface¶

#### UNL.py¶

Supports Uniform Node Locators (UNL’s) for linking to nodes in any Leo file.

UNL’s specify nodes within any Leo file. You can use them to create cross-Leo-file links! UNL

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.

Format of UNL’s:

UNL’s referring to nodes within the present outline have the form:

headline1-->headline2-->...-->headlineN


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


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

#### chapter_hoist.py¶

Creates hoist buttons.

This plugin puts two buttons in the icon area: a button called ‘Save Hoist’ and a button called ‘Dehoist’. 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

Requires at least version 0.19 of mod_scripting.

#### detect_urls.py¶

Colorizes URLs everywhere in node’s body on node selection or saving. Double click on any URL launches it in default browser.

URL regex: (http|https|file|ftp)://[^s’”]+[w=/]

#### EditAttributes.py¶

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.

#### interact.py¶

Adds buttons so Leo can interact with command line environments.

Currently implements bash shell and psql (postresql SQL db shell).

Single-line commands can be entered in the headline with a blank body, multi-line commands can be entered in the body with a descriptive title in the headline. Press the bash or psql button to send the command to the appropriate interpreter.

The output from the command is always stored in a new node added as the first child of the command node. For multi-line commands this new node is selected. For single-line command this new node is not shown, instead the body text of the command node is updated to reflect the most recent output. Comment delimiter magic is used to allow single-line and multi-line commands to maintain their single-line and multi-line flavors.

Both the new child nodes and the updated body text of single-line commands are timestamped.

For the bash button the execution directory is either the directory containing the .leo file, or any other path as specified by ancestor @path nodes.

Currently the psql button just connects to the default database. ”;” is required at the end of SQL statements.

Requires pexpect module.

#### maximizeNewWindows.py¶

Maximizes all new windows.

#### mod_framesize.py¶

Sets a hard coded frame size.

Prevents Leo from setting custom frame size (e.g. from an external .leo document)

Selecting these menu items will bring up a short About Plugin dialog with the details of the plugin. In some circumstances a submenu will be created instead and an ‘About’ menu entry will be created in this.

INI files and the Properties Dialog

If a file exists in the plugins directory with the same file name as the plugin but with a .ini extension instead of .py, then a Properties item will be created in a submenu. Selecting this item will pop up a Properties Dialog which will allow the contents of this file to be edited.

The .ini file should be formated for use by the python ConfigParser class.

Special Methods

Certain methods defined at the top level are considered special.

cmd_XZY
If a method is defined at the module level with a name of the form cmd_XZY then a menu item XZY will be created which will invoke cmd_XZY when it is selected. These menus will appear in a sub menu.

applyConfiguration

This method, if it exists, will be called when the user clicks on the plugin name in the plugins menu (or the About item in its submenu), but only if the plugin was loaded properly and registered with g.plugin_signon.

Special Variable Names

Some names defined at the top level have special significance.

__plugin_name__
This will be used to define the name of the plugin and will be used as a label for its menu entry.
__plugin_priority__
Plugins can also attempt to select the order they will appear in the menu by defining a __plugin_priority__. 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. Properties and INI files.

#### redirect_to_log.py¶

Sends all output to the log pane.

Creates a Scripts menu for LeoPy.leo.

#### zenity_file_dialogs.py¶

Replaces the gui file dialogs on Linux with external calls to the zenity gtk dialog package.

This plugin is more a proof of concept demo than a useful tool. The dialogs presented do not take filters and starting folders can not be specified.

Despite this, some Linux users might prefer it to the gui dialogs.

## Qt only plugins¶

### attrib_edit.py¶

Edits user attributes in a Qt frame.

This plugin creates a frame for editing attributes similar to:

Name:   Fred Blogs
Home:   555-555-5555
Work:   555-555-5556


attrib_edit is also intended to provide attribute editing for other plugins, see below.

The attributes can be stored in different ways, three modes are implemented currently:

v.u mode
These attributes are stored in the “unknownAttributes” (uA) data for each node, accessed via v.u.
Field:
Attributes are lines starting (no whitespace) with “AttributeName:” in the body text.
@Child
Attributes are the head strings of child nodes when the head string starts with '@AttributeName‘ where the first letter (second character) must be capitalized.

The plugin defines the following commands, available either in the plugin’s sub-menu in the Plugins menu, or as Alt-X attrib-edit-*.

attrib-edit-modes

Select which attribute setting / getting modes to use. More than one mode can be used at the same time.

You can also control which modes are active by listing them with the @data attrib_edit_active_modes setting. For example:

Field:
@Child
# v.u mode


would cause only the “Field:” and “@Child” modes to be active be default.

attrib-edit-manage
Select which attributes, from all attributes seen so far in this outline, to include on the current node.
attrib-edit-scan
Scan the entire outline for attributes so attrib-edit-manage has the complete list.
attrib-edit-create

Create a new attribute on the current node. If Field: or @Child modes are active, they simply remind you how to create an attribute in the log pane. If the “v.u mode” mode is active, you’re prompted for a path for the attribute. For example:

addressbook First


to store the attribute in v.u[‘addressbook’][‘_edit’][‘First’]

As a convenience, entering a path like:

todo metadata created|creator|revised


would create:

v.u.['todo']['metadata']['_edit']['created']


Technical details

See the source for complete documentation for use with other plugins. Here are some points of interest:

• In addition to v.u['addressbook']['_edit']['first'], paths like v.u['addressbook']['_edit']['_int']['age'] may be used to identify type, although currently there’s no difference in the edit widget.
• In the future the plugin may allow other plugins to register to provide attribute path information, instead of just scanning for [‘_edit’] entries in v.u.
• Currently there’s no sorting of the attributes in “v.u mode”, which is a problem for some applications. It’s unclear where the desired order would be stored, without even more repetition in v.u. When other plugins can register to manipulate the attribute list each plugin could address this, with unordered presentation in the absence of the client plugin.
• There’s code to have the editor appear in a tab instead of its own area under the body editor, but (a) this is always being buried by output in the log window, and (b) there’s a bug which leaves some (harmless) ghost widgets in the background. Enable by @setting attrib_edit_placement to ‘tab’.

### bigdash.py¶

Creates a global search window

Use the global-search command to show this window. To restore the original appearance of the window, type help.

Requires the whoosh library (‘easy_install whoosh’) to do full text searches.

### bookmarks.py¶

Open bookmarks in a list, and show bookmarks in a pane.

Manipulates appearance of individual tree widget items.

This plugin is mostly an example of how to change the appearance of headlines. As such, it does a relatively mundane chore of highlighting @thin, @auto, @shadow nodes in bold.

Defines various useful actions for context menus (Qt only).

Examples are:

• Edit in $EDITOR • Edit @thin node in$EDITOR (remember to do “refresh” after this!)
• Refresh @thin node from disk (e.g. after editing it in external editor)
• Go to clone

def nextclone_rclick(c,p, menu):
""" Go to next clone """

# only show the item if you are on a clone
# this is what makes this "context sensitive"
if not p.isCloned():
return

def nextclone_rclick_cb():
c.goToNextClone()

# in response to right click on tree item

action.connect(action, QtCore.SIGNAL("triggered()"), nextclone_rclick_cb)


And call this in your plugin once:

g.tree_popup_handlers.append(nextclone_rclick)


### graphcanvas.py¶

Adds a graph layout for nodes in a tab. Requires Qt and the backlink.py plugin.

### leomylyn.py¶

By Ville M. Vainio See: http://en.wikipedia.org/wiki/Mylyn

I went on to start a “leo mylyn” plugin to exercise using the childrenModified and contentModified signals.

If you want to play with it, enable leomylyn.py, modify stuff around the tree and do alt-x mylyn-scores.

Of course as it is useless in this state, but becomes useful when it has a proper gui (maybe in Nav pane), where you would then have a list of “most interesting” nodes.

In the future, this could be able to remember the scores through the sessions, degrade the old scores by time, etc. Also, a scoreset would be associated with a “project” (e.g.”own research”, “work project foo”), each of them having their own typical node working set.

Mylyn was a nice boost back in the eclipse days, it could work for Leo too. My main motivation right now was to demonstrate the signals with something that is much simpler than using them in qmlnotebook.

### livecode.py¶

The livecode-show commands shows the live code evaluation pane. Hover on the buttons for helpful tool-tips.

Depends on https://pypi.python.org/pypi/meta which you can install with:

pip install meta


The dependency on meta is for recursively turning AST node trees back into printable identifiers like “m[m[5]]”. For example:

a = 7


is easy, but:

m[m[5]] = 7


is not.

### nodetags.py¶

Provides node tagging capabilities to Leo

By Jacob M. Peck

#### API¶

This plugin registers a controller object to c.theTagController, which provides the following API:

tc = c.theTagController
tc.get_all_tags()
# return a list of all tags used in the current
# outline, automatically updated to be consistent
tc.get_tagged_nodes('foo')
# return a list of positions tagged 'foo'
tc.get_tags(p)
# return a list of tags applied to the node at
# position p; returns [] if node has no tags
tc.add_tag(p, 'bar') # add the tag 'bar' to the node at position p
tc.remove_tag(p, 'baz')
# remove the tag 'baz' from p if it is in the tag list


Internally, tags are stored in p.v.unknownAttributes[‘__node_tags’] as a set.

#### UI¶

The “Tags” tab in the Log pane is the UI for this plugin. The bar at the top is a search bar, editable to allow complex search queries. It is pre-populated with all existing tags in the outline, and remembers your custom searches within the given session. It also acts double duty as an input box for the add (+) button, which adds the contents of the search bar as a tag to the currently selected node.

The list box in the middle is a list of headlines of nodes which contain the tag(s) defined by the current search string. These are clickable, and doing so will center the focus in the outline pane on the selected node.

Below the list box is a dynamic display of tags on the currently selected node. Left-clicking on any of these will populate the search bar with that tag, allowing you to explore similarly tagged nodes. Right-clicking on a tag will remove it from the currently selected node.

The status line at the bottom is purely informational.

The tag browser has set-algebra querying possible. Users may search for strings like ‘foo&bar’, to get nodes with both tags foo and bar, or ‘foo|bar’ to get nodes with either or both. Set difference (-) and symmetric set difference (^) are supported as well. These queries are left-associative, meaning they are read from left to right, with no other precedence. Parentheses are not supported. See below for more details.

#### Tag Limitation¶

The API is unlimited in tagging abilities. If you do not wish to use the UI, then the API may be used to tag nodes with any arbitrary strings. The UI, however, due to searching capabilities, may not be used to tag (or search for) nodes with tags containing the special search characters, &|-^. The UI also cannot search for tags of zero-length, and it automatically removes surrounding whitespace (calling .strip()).

### printing.py¶

This plugin supports printing using the Qt GUI. Written by Jacob M. Peck.

### projectwizard.py¶

Creates a wizard that creates @auto nodes.

Opens a file dialog and recursively creates @auto & @path nodes from the path where the selected file is (the selected file itself doesn’t matter.)

### quicksearch.py¶

Adds a fast-to-use search widget, like the “Find in files” feature of many editors.

Just load the plugin, activate “Nav” tab, enter search text and press enter.

The pattern to search for is, by default, a case insensitive fnmatch pattern (e.g. foo*bar), because they are typically easier to type than regexps. If you want to search for a regexp, use ‘r:’ prefix, e.g. r:foo.*bar.

Regexp matching is case sensitive; if you want to do a case-insensitive regular expression search (or any kind of case-sensitive search in the first place), do it by searching for “r:(?i)Foo”. (?i) is a standard feature of Python regular expression syntax, as documented in

http://docs.python.org/library/re.html#regular-expression-syntax

### screen_capture.py¶

By Terry Brown. See http://leo-editor.github.io/screen_capture.html

screen_capture now captures an image immediately, screen_capture_5sec waits five seconds, so you can position the pointer, open menus etc. The only feedback is in the console, as messages in the log would be distracting in the captured image.

### screencast.py¶

Screencasts promise to be easy to be much easier to create than slideshows, while also being more interesting, informative and flashy. It is so much easier to write a screencast script than it is to lay out a slide, take a screenshot, and then manage resulting slide.

In particular, there are few continuity problems with screencasts. Continuity is a huge problem with slideshows! If I change one slide, I am likely to want to change all following slides. Which means I have to retake all the slides, and file the new versions in the proper places. In contrast, any changes to screencasts naturally propagate forward. There might be an effect on following screencasts scenes, but this will happen rarely with a reasonable scene design, and any problems should be easy to fix.

With screencasts, the movie script is also the python script! There is no “translation” from one to the other. Furthermore, all the work to produce a screencast is done (naturally!) within Leo. No need to create and manage external data. This is another huge advantage and it make producing screencasts much faster than producing slideshows.

Screencasts may be the long-awaited tools that will allow me to show Leo in action so that other will finally be able to understand it easily.

### scrolledmessage.py¶

Provides a Scrolled Message Dialog service for Qt.

The plugin can display messages supplied as plain text or formatted as html. In addition the plugin can accept messages in rst format and convert them to be displayed as html.

The displayed format can be controlled by the user via check boxes, so rst messages may be viewed either as text or as html. Html messages can also be viewed as raw text, which will be a good debug feature when creating complex dynamically generated html messages.

The user interface is provided by a ScrolledMessage.ui file which is dynamically loaded each time a new dialog is loaded.

The dialog is not modal and many dialogs can exist at one time. Dialogs can be named and output directed to a dialog with a specific name.

The plugin is invoked like this:

g.doHook('scrolledMessage', c=c, msg='message', title='title',  ...etc    )


or:

g.app.gui.runScrolledMessageDialog(c=c, ...etc)


All parameters are optional except c.

Parameters

msg:

The text to be displayed (html, rst, plain).

If the text starts with ‘rst:’ it is assumed to be rst text and is converted to html for display after the rst: prefix has been removed. If the text starts with ‘<’ it is assumed to be html. These auto detection features can be overridden by ‘flags’.

label:
The text to appear in a label above the display. If it is ‘’, the label is hidden.
title:
The title to appear on the window or dock.
flags:

Says what kind of message: ‘rst’, ‘text’, ‘html’. This overrides auto-detection.

Flags can be combined, for example, ‘rst html’ causes the message to be interpreted as rst and displayed as html.

### spydershell.py¶

Execute alt-x spyder-launch to start spyder. Execute alt-x spyder-update to pass current c,p,g to spyder interactive session. spyder-update also shows the window if it was closed before.

### stickynotes.py¶

Adds simple “sticky notes” feature (popout editors) for Qt gui.

Adds the following (Alt-X) commands:

stickynote
pop out current node as a sticky note
stickynoter
pop out current node as a rich text note
stickynoteenc
pop out current node as an encrypted note
stickynoteenckey
enter a new en/decryption key
tabula
add the current node to the stickynotes in the Tabula sticky note dock window, and show the window
tabula-show
show the Tabula sticky note dock window (without adding the current node)
tabula-marked
add all marked nodes to the stickynotes in the Tabula sticky note dock window, and show the window

Sticky notes are synchronized (both ways) with their parent Leo node.

Encrypted mode requires the python-crypto module.

The first time you open a note in encrypted mode you’ll be asked for a pass phrase. That phrase will be used for the rest of the session, you can change it with Alt-X stickynoteenckey, but probably won’t need to.

The encrypted note is stored in base64 encoded encrypted text in the parent Leo node, if you forget the pass phrase there’s no way to un-encrypt it again. Also, you must not edit the text in the Leo node.

When creating an encrypted note, you should start with an empty node. If you want to encrypt text that already exists in a node, select-all cut it to empty the node, then paste it into the note.

### todo.py¶

Provides to-do list and simple task management for leo (Qt only).

This plugin adds time required, progress and priority settings for nodes. With the @project tag a branch can display progress and time required with dynamic hierarchical updates.

For full documentation see:

### valuespace.py¶

Supports outline-based calculations similar to spreadsheets.

### viewrendered.py¶

Creates a window for live rendering of rst, html, etc. Qt only. Supports @graphics-script, @image, @html, @movie and @svg nodes.

viewrendered.py creates a single Alt-X style command, viewrendered, which opens a new window where the current body text is rendered as HTML (if it starts with ‘<’), or otherwise reStructuredText. reStructuredText errors and warnings may be shown. For example, both:

Heading
-------

This is **really** a line of text.


and:

<h1>Heading<h1>

<tt>This</tt> is <b>really</b> a line of text.


will look something like:

This is really a line of text.

### viewrendered2.py¶

As mentioned in my previous post I’ll attempt to elaborate on the plugin I’ve used to make Leo more useful to me, in case it is useful for others also. Apologies for the very long post, but I wanted get get all its features and warts exposed here to get some feedback on whether others see this as useful or that this is only valuable to me. If it’s useful to others then it may be worth polishing up quite a bit.

#### Why a better viewrendered plugin?¶

I like to use reStructuredText (reST) for all of my note-taking, idea development, project and task management and automation of desktop activities (e.g. initiating a backup). You could say it is the control center of my daily activities, including calculating and showing dashboards of where I am and where I’m going.

This means I need a tool which seamlessly shows me the full-fidelity browser-rendered version of what I am writing and be able to print my notes for meetings, cut and paste nicely formatted output to my office e-mails and documents, as well as show some of the material as a slideshow.

The existing viewrendered plugin couldn’t seem to do what I needed (especially math) and I was almost ready to abandon Leo again. This time I bit the bullet and created a more capable renderer in viewrendered2 (VR2). Initially I made a plugin that rendered, on demand, to my normal web browser. This worked well, but I really thought live rendering like “viewrendered” would be better, and for that I needed close control over scroll positions etc. that I couldn’t get with an external browser. So the plugin became much more complex as I merged it with the existing viewrendered plugin, but was ultimately more powerful and useful to me.

#### Objectives¶

• Show a “full” html representation of any reST node or tree, without an @rst root node, including more features than the existing viewrendered plugin:

proper html layout
math (mathjax, etc.)
clickable URLs
clickable hyperlinks within the page (e.g. TOC)
good quality zoom
cut and paste html with ctl-C
s5 slideshows
javascript
svg images
configurable css

• Allow showing of node tree rather than just the current node. This can give a better overview perspective of the tree contents.

• Be able to lock the rendering on the root node of a tree, to view the effect editing a sub-node within the larger html document.

• Provide proper rendering of any combination of node types in a tree, so long as they have been properly designated by @language directives (i.e. reST, text, code, css, ...).

• Allow viewing (and printing) of an entire source file from an @file type root node.

• Be able to export any of these renderings to a full web-browser to take advantage of the large rendering window (especially for slideshows, as well as printing, saving output.

• Be able to integrate automatically executed code nodes intermingled with reST nodes to provide an automatic calculation-based “Notebook” or “Report” type output.

• Don’t increase the dependencies of Leo.

#### Implementation¶

VR2 is implemented mostly as an ~600 line expansion of the update_rst method in the viewrendered.py plugin. The text-oriented class used for rendering in VR1 has been replaced by the QWebView class which provides the full rendering functionality of a real web-browser. To make this flexible, a toolbar has been attached to the top with a few controls.

Because I wanted to retain compatibility with VR1, I created the viewrendered2.py plugin, but retained all the class naming which occurred within VR1. This means that it remains compatible with the existing mechanisms (like free_layout) of showing and creating panes for VR1. I tried this with an expectation that it would fail, but it appears to work without any unintended side-effects.

Tooltips have been added where Qt allows, with the philosophy that a user shouldn’t need a manual to use this pane.

VR2 has been used a lot under Windows 7 and a little under Ubuntu 13.10.

#### Issues / Limitations¶

I use VR2 every few minutes every working day. However, VR2 is likely to still have a lot of rough edges and, in particular, bugs that show up with different work flows or css folder layouts etc. In fact, VR2 is still a work in progress and therefore still being fiddled with, so bugs creep in regularly.

But overall, my perception of its deficiencies are:

• Does not handle reST headings within the node bodies well (sometimes very slow render, blocking Leo).
• VR2 attempts to reconcile reST headings that originate from explicit headings within the nodes against reST headings that are automatically generated by the node hierarchy. In many cases, this is impossible, resulting in many errors which drastically slows down rendering. - Recommend not using headings within the nodes themselves, leaving the node hierarchy to do this automatically.
• If the node triggers one of the special viewrendered node header types (@md, @image, @movie, @html) VR2 simply defaults to the old handlers for those types. This means it jumps back to whatever pane type VR1 uses, so the features of VR2 disappear. I suspect that VR2 could incorporate these types into the new version and retain these new features. I should look at that.
• Doesn’t integrate with rst3 plugin, especially honouring @others etc. There are some conflicts in objectives, so this may never be fully resolved. It would probably make sense for rst3 settings to get used for VR2 as well, along with additional VR2 specific settings. Currently, VR2 has its own @settings-style settings. The rst3 code is not used.
• For slideshow purposes, a patch to docutils s5_writer is required to be able to handle an arbitrary hierarchy of nodes (forces all headings to start a new slide). Otherwise, only the 2nd level nodes (from the root) force a new slide.
• The integration of VR2 code into the existing viewrendered plugin code is rudimentary. I took the shortcut of not trying to understand this code well and confining my integration to the rst rendering only. Better integration would be a good future step.

With the plugin being able to execute javascript etc. there may be some form of security issue, but I can’t see it myself (given that Leo can execute arbitrary python code anyway).

#### Future¶

• Expand the export button if pandoc is installed, adding optional output formats such as docx, odt, plus additional slideshow formats.
• Use new reST functionality to replace other media viewrendered methods for images, svg, movies, etc. * Integrate better with rst3?