.. rst3: filename: html/FAQ.html
####
FAQ
####
This is Leo's Frequently Asked Questions document.
.. index:: FAQ
.. contents:: Contents
:depth: 4
:local:
.. Links used in this document...
.. External links
.. _docutils: https://docutils.sourceforge.net/
.. _`git repository`: https://github.com/leo-editor/leo-editor
.. _unicode: https://www.unicode.org/
.. Glossary
.. _directive: glossary.html#directive
.. _directives: glossary.html#directives
.. _`external file`: glossary.html#external-file
.. _`external files`: glossary.html#external-files
.. _headline: glossary.html#headline
.. _headlines: glossary.html#headlines
.. _node: glossary.html#node
.. _nodes: glossary.html#nodes
.. _outliner: glossary.html#outliner
.. _sections: glossary.html#sections
.. _`section name`: glossary.html#section-name
.. _`section names`: glossary.html#section-names
.. _sentinels: glossary.html#sentinels
.. _`sentinel line`: glossary.html#sentinel
.. _`sentinel lines`: glossary.html#sentinel
.. _setting: glossary.html#setting
.. _settings: glossary.html#settings
.. FAQ
.. _`How to install Leo on Windows`: installing.html#installing-leo-on-windows
.. _`run Leo in a console`: running.html#running-leo-from-a-console-window
.. Tutorial
.. _`scripting tutorial`: tutorial-scripting.html
.. _`Leo's tutorials`: tutorial.html
.. _`Clones`: tutorial-pim.html#clones
.. _`Views`: tutorial-pim.html#views
.. Other local references
.. _command: commands.html
.. _`History of Leo`: appendices.html#history-of-leo
.. _`Leo 4.0: Eliminating error 'recovery'`: appendices.html#leo-4-0-eliminating-error-recovery
Learning to use Leo
+++++++++++++++++++
How can I learn Leo, or python, or anything
*******************************************
Let us think of lessons not as explanations, but as puzzles to be solved by the student. The puzzles themselves need no lengthy explanations. They can even be cryptic. This attitude arises from two principles:
1. The less said, the better.
2. Invite people to learn for themselves.
**Pick something that interests you**
Pick a real, worthy, programming task that you (the student) personally want/need to do in Leo. *This step is essential*! It is *useless* to try to learn in a vacuum.
EKR's first python program was C2Py. leoAttic.txt contains the original version. Leo's c-to-python commands contained revised code.
**Overcome fear of crashes and mistakes**
- Run Leo from a console.
- Single-step through your code with g.pdb()
- Deliberately put a crasher in your code and see what happens.
The only way to hard crash Leo is to pass bad pointers to PyQt. Python should catch all other problems. If it doesn't, report a bug to the python people ;-)
**Discover how Leo's code works**
- Where is Leo's source code? Hint: look for leoPy.leo in LeoDocs.leo.
- Look at Leo's demote command.
- What are three ways of finding the demote command?
- How does demote change the outline?
- How does demote handle undo?
- Study any other Leo command that relates to your project.
- Use the cff command to find all definitions of x.
- Use the cff command to find all uses of x.
**Start using Leo for real**
- Add a new command using @button.
- Create an external file containing your real-world project.
Execute it outside of Leo.
- Write a Leo plugin.
- Advanced: fix one of Leo's bugs.
**Attitude**
Students should always feel free to ask for help, but struggle teaches us the most. **It doesn't matter how long it takes to learn something**. In our culture, we value quickness. But that is a trap. All learning builds momentum:
- Put 10 units of effort in, get 1 unit of results out.
- Put 1 in, get 1 out.
- Put 1 in, get 10 out.
There is no other way! How many times have we given up just because things were not easy or clear at first?
**That which we learn, we learn by doing**
Reading about (and thinking about) are useful, but not good enough. That is why students must have a project that is important to them. The project will put them into action.
What's the best way to learn to use Leo?
****************************************
First, read `Leo's tutorials`_. This will be enough to get you started if you just want to use Leo as an outliner_. If you intend to use Leo for programming, read the `scripting tutorial`_, then look at Leo's source code in the file LeoPy.leo. Spend 5 or 10 minutes browsing through the outline. Don't worry about details; just look for the following common usage patterns:
- The (Projects) tree shows how to use clones to represent tasks.
- Study @file leoNodes.py. It shows how to define more than one class in single file.
- Most other files show how to use a single @others directive to define one class.
- Most methods are defined using @others, *not* section definition nodes.
When is using a section better than using a method?
***************************************************
Use methods for any code that is used (called or referenced) more than once.
Sections_ are convenient in the following circumstances:
- When you want to refer to snippets of code the can not be turned into methods. For example, many plugins start with the code like this::
<< docstring >>
<< imports >>
<< version history >>
<< globals >>
None of these sections could be replaced by methods.
- When you want to refer to a snippet of code that shares local variables with the enclosing code. This is surprisingly easy and safe to do, *provided* the section is used only in one place. `Section names`_ in such contexts can be clearer than method names. For example::
<< init ivars for writing >>
In short, I create sections when convenient, and convert them to functions or methods if they need to be used in several places.
Abbreviations
+++++++++++++
What are some useful abbreviations?
***********************************
Edward Ream::
alp;;=@language python\n
alr;;=@language rest\n@wrap\n
date;;={|{import time;x=time.asctime()}|}
trace;;=trace = <|bool|> and not g.unitTesting
John Lunzer::
hl;;={|{x=c.p.h}|}
es;;=g.es(contents,color='<|color|>')
ts;;={|{x=time.strftime("%Y%m%d%H%M%S")}|}
Rob (Largo84)::
ol;;=
\n - <|item|>
\n
li;;=<|ITEM|>
link;;=<|TEXT|>
enum;;=\begin{enumerate}\n \item <|item|>\n\end{enumerate}
For more examples, see LeoSettings.leo.
Clones
++++++
How can I eliminate clone wars?
*******************************
Clone wars can be most annoying. The solution is simple::
**Keep clones only in the outline and in one other external file**
In particular, catchall files like leo/doc/leoProjects.txt or leo/doc/leoToDo.txt should never contain clones.
How can I use clones to reorganize an outline?
**********************************************
Clones make reorganizing an outline significantly easier and faster. Simply make top-level clones of the nodes you keep encountering during the reorg. This makes moving a node a snap: just move it from one clone to another.
How does EKR use clones?
************************
.. https://groups.google.com/d/msg/leo-editor/4s44H9cUJGY/ewRBDBSw-A8J
For the last several weeks I've used clones in a new, more effective way, inspired by git's stash/unstash commands. Here are the main ideas.
1. [Most important] I avoid putting clones in two different *external* files.
For any task, I create a task node that resides in @file leoToDo.txt. I clone that node and put it in the outline, *never* in any other @file node. This instantly eliminates clone wars.
2. I use top-level "stashed" nodes/trees in my local copy of leoPy.leo.
These clones are *not* written to any external file, so they would be lost if I lost leoPy.leo. But the risks are negligible because all stashed nodes are clones of nodes that *do* exist in external files.
3. I have two main stashed trees: recent files and recent code.
The "recent files" tree contains clones of all the @file nodes I have worked on recently. This speeds up access to them. That happens surprisingly often--often enough to be well worth maintaining the tree. Furthermore, because Leo's new pylint command now works on trees, I can check all recently-changed files simply by running pylint on the "recent files" tree.
The "recent code" tree is even more valuable, for three reasons. The first is obvious--it speeds access to recently-changed nodes.
Second, the "recent code" tree allows me to work on multiple tasks without getting overwhelmed by details and loose nodes lying around. I add organizer nodes as needed to make accessing the nodes faster, and also to jog my memory about what I was doing when I changed those nodes ;-)
Third, the "recent code" tree allows me *not* to put clones in the @file leoProjects.txt tree. This leads me to...
4. I use clones in a stylized way when fixing and committing bugs.
I always use clones when working on a project. A "task" node contains clones of all nodes related to the task. The task node typically remains in leoToDo.txt until the task is completely finished. While working on the bug, I create a clone of the task node, and move that clone to the bottom top-level node of the outline. Among other things, this makes it easy to limit searches without actually choosing "suboutline only" in the Find panel. This workflow is decades old.
The following is the heart of the new workflow. When a task is complete, I do the following:
A. First, I create a **stashed-task** node, containing all the clones that were previously in the task node.
The *stashed-task* becomes pre-writing for the commit log. The *task* node instantly becomes pre-writing for the release notes, so if it needs to discuss any code in the clones that have just been moved to the stashed-task node, I write those words immediately, while all details are fresh in my mind.
B. Now I move the cloned task node that is in leoToDo.txt to the appropriate place in leoProjects.txt.
C. Next I do the commit.
The *other* clone of the task node, and the stashed task node are still within easy reach, and I typically use both nodes to create the commit log. The commit will typically consist of the changed leoToDo.txt and leoProjects.txt and whatever .py files the task itself changed. Happily, leoToDo.txt and leoProjects.txt are now up-to-date because of steps A and B.
D. Finally, I clean up.
I delete the top-level clone of the task node, and move the stashed-task
node to the "recent code" tree.
E. Later, when it appears that activity has died down on various projects, I'll delete nodes from the "recent files" an "recent code" trees. This is a minor judgment call: I want to leave nodes in the trees while they are useful, but not significantly longer than that. I do *not* regard these trees as permanently useful. leoProjects.txt should contain *all* permanent notes about a project.
===== Conclusions
This work flow may seem complicated. Believe me, it is not. It's easier to use than to describe.
This workflow has big advantages:
1. Clone wars are gone for good.
2. All recent data is easily available.
3. Task nodes and stashed-task nodes provide natural places for proto-documentation.
4. Banning clones from leoProjects.txt forces me to complete the first draft of the documentation before committing the fix.
How does Leo handle clone conflicts?
************************************
Some people seem to think that it is difficult to understand how Leo handles "clone wars": differing values for a cloned nodes that appear in several external files. That's not true. The rule is::
**The last clone that Leo reads wins.**
That is, for any cloned node C, Leo takes the value of C.h and C.b to be the values specified by the last copy that Leo reads.
There is only one complication::
**Leo reads the entire outline before reading any external files.**
Thus, if C appears in x.leo, y.py and z.py, Leo will choose the value for C in x.py or y.py, depending on which @ node appears later in the outline.
**Note**: Whenever Leo detects multiple values for C when opening an outline, Leo creates a "Recovered nodes" tree. This tree contains all the various values for C, nicely formatted so that it is easy to determine where the differences are.
How can Leonine scripts simulate half clones?
*********************************************
All clones of the same node share the same VNode, and thus they all have exactly the same headline, body text, and children. Therefore, changing p.b or p.h, or adding a child to one clone modifies the underlying VNode, reflected instantly in all other clones.
However, Leo's users often request a vague enhancement informally known as "half clones." We can make this ill-defined notion precise by saying that we often want to treat clones differently depending on **context**, the **Position** of that clone within the entire outline.
**Using context in scripts**
Scripts are not limited to using the data in `p.v`, that is, `p.b`, `p.h`, `p.u`, or `p.gnx`. Scripts may access:
- Any ancestor or descendant of `p`.
- Any data accessible from `c`, that is, *all* the data in the outline, including cached data!
Scripts can define their own conventions, including:
- Special-format comments embedded in `p.b`,
- Special-purpose conventions for headlines.
**Changing text depending on context**
.. code-block:: python
def in_context(p: Position, context: str) -> bool:
return any(z.h == context for z in p.parents())
for p in c.all_positions():
if in_context(p, 'FAQ'):
handle_faq_node(p)
elif in_context(p, 'Reference'):
handle_ref_node(p)
**Simulating half clones**
Scripts may simulate half clones by ignoring children (of clones) in some contexts and processing those *same* children in other contexts. That's all there is to it!
When is deleting a node dangerous?
**********************************
A **dangerous** delete is a deletion of a node so that all the data in the node is deleted *everywhere* in an outline. The data is gone, to be retrieved only via undo or via backups. It may not be obvious which deletes are dangerous in an outline containing clones. Happily, there is a very simple rule of thumb::
Deleting a non-cloned node is *always* dangerous.
Deleting a cloned node is *never* dangerous.
We could also consider a delete to be dangerous **if it results in a node being omitted from an external file.** This can happen as follows. Suppose we have the following outline (As usual, A' indicates that A is marked with a clone mark)::
- @file spam.py
- A'
- B
- Projects
- A'
- B
Now suppose we clone B, and move the clone so the tree looks like this::
- @file spam.py
- A'
- B'
- Projects
- A'
- B'
- B'
If (maybe much later), we eliminate B' as a child of A will get::
- @file spam.py
- A'
- Projects
- A'
- B
B has not been destroyed, but B is gone from @file spam.py! So in this sense deleting a clone node can also be called dangerous.
When may I delete clones safely?
********************************
Q: When can I delete a clone safely?
A: Any time! The only time you can "lose" data is when you delete a non-cloned node, save your work and exit Leo.
Q: What gets "lost" when I delete a non-cloned node?
A: The node, and all it's non-cloned children. In addition, if the node contains all clones of a cloned node, all copies of the cloned node will also be "lost".
Q: Anything else I should be careful about concerning clones?
Not really. If you move any node out "underneath" an @file (@clean, etc) node, the contents of that node disappears from the external file.
I hope this encourages more people to use clones. Leo's clone-find commands are something that every Leo programmers should be using every day.
Why doesn't Leo support cross-outline clones?
*********************************************
Any outline (.leo file) may contain clones that appear in multiple external files defined *within* that outline. There is no problem with such **intra-outline clones**.
In contrast, **cross-outline clones** are clones that appear in more than one outline. Leo's paste-retaining-clones command makes it possible for two outlines to contain nodes with the same gnx. Conceivably, both outlines could use those clones in the *same* external file!
Leo will never encourage cross-outline clones, because such clones are inherently dangerous. Indeed, neither outline would have full responsibility for its own data.
Indeed, the shared clones would be subject to the well-known multiple-update problem. Suppose the two outlines were open simultaneously, and each outline changed the shared clones in different ways. Whichever outline changed the data last would "win." The changes in the other outline would be lost forever!
In short, Leo will never support features that encourage cross-outline clones.
Why is Alt-N (goto-next-clone) important?
*****************************************
clone-find-all-flattened often includes clones of nodes whose location is unclear. No problem! Just select the mysterious node and do Alt-N (goto-next-clone). Leo will select the next clone of that node, wrapping the search as necessary. One or two Alt-N takes me to the "real" node, the node having an ancestor @ node.
Ideally, the meaning of all nodes would be clear from their headlines. I typically use the following conventions. For section definitions, the headline should contain file or class name. Examples::
<< imports >> (leoCommands.py)
<< docstring >> (LeoApp)
Why should I use clones?
************************
You will lose much of Leo's power if you don't use clones. See `Clones`_ and `Views`_ for full details.
Customizing Leo
+++++++++++++++
How can I create a pane for matplotlib charts?
**********************************************
I'm trying to create a interactive chart in a embedded in a new leo pane using matplotlib. However, I am not sure about the the best way to implement this. I would appreciate some guidance on this please? The questions I would like answered are:
1. How do I create a new blank pane for embedding a chart as well as other QtWidgets.
2. Can I do this in a script or do I need to work with leo source?
I want to create a data processing and visualization tool kit in leo. Like Excel but using nodes instead of columns. Nodes will have data and I want to create new data nodes by applying python functions to data in existing nodes. The thing missing is the visualization within a leo pane (I can easily launch a chart in it's own window).
**Terry Brown**
You can run this script from any body pane::
'''
A script that adds a MatPlotLib pane to Leo.
After running this script, right click on one of the pane dividers and
select Insert. A new pane with a button 'Action' appears. Click it, and
select "Add matplot" from the context menu.
'''
from leo.core.leoQt import QtWidgets
class MatplotPaneProvider:
def __init__(self, c):
self.c = c
if hasattr(c, 'free_layout'):
splitter = c.free_layout.get_top_splitter()
if splitter:
splitter.register_provider(self)
def ns_provides(self):
return[('Add matplot', '_add_matplot_pane')]
def ns_provide(self, id_):
if id_ == '_add_matplot_pane':
c = self.c
w = QtWidgets.QSlider() ### w = myMatplotWidget()
return w
def ns_provider_id(self):
# used by register_provider() to unregister previously registered
# providers of the same service
# provider ID is not the same as the service id_ above
return "completely unique value here"
MatplotPaneProvider(c)
**OP**
I have managed to get a matplotlib graph embedded within a pane in leo as a widget. I now need some help with how to interact with the widget using scripts in leo. I am unsure about the following:
*1/ How do I expose the widget within the leo environment?*
If you were only going to have one and you weren't going to destroy it, you could just do something simple like c._matplot = self in its constrictor (assuming c was passed to the constructor).
If you're going to have more than one and they may be destroyed, it might be simplest to let the free_layout / nested_splitter system manage them::
ts = c.free_layout.get_top_splitter()
matplotters = ts.findChildren(myMatplotWidget)
should return a list of the widgets of your class in the layout, but only if they're in the main window, widgets in extra windows opened from the "Open window" context menu item would be missed, I can add a find_children() method to complement the find_child() method the splitters already have to account for this.
Detail: the above is just using Qt's QObject.findChildren(), the nested_splitter find_child() and (not yet written) find_children() versions search the extra windows as well.
Here I have created a self.mat in your MatplotPaneProvider class to make the widget accessible but it doesn't feel like the correct way to do this::
mat = MatplotPaneProvider(c)
mat.mat.someMethod()
mat.mat.someOtherMethod()
2. I would also like to make the widget accessible from any script within leo. What's the leo way of doing this?
See above
3. If I create more than 1 pane containing these widgets. How do I switch between them in scripts?
See above
4. Running this script more than once creates multiple items for Add Matplot when pressing the Action button. How do I stop this from happening? I have already tried returning a unique integer in * ns_provider_id *but that did not work.*
The value returned by ns_provider_id should be unique for the provider class, but constant. So it can just return something like "matplotlib provider ver 1"
How can I customize settings for a particular external file?
************************************************************
How it is possible to specify settings in @file? As I understand every setting should be a single outline.
Vitalije:
You can use clones. For example::
--@settings
----my-shared-settings
------...
----some-specific-settings-for-this-outline
------....
--@file my-shared-settings-somewhere.txt
----my-shared-settings
where `my-shared-settings` node is cloned from the @file subtree.
Quite often I use some script to combine some nodes, process them and generate some output file. And such script I put in a node with the following headline: ``@button n-save @key=Ctrl-s``. Then whenever I open this outline and whenever I hit Ctrl-s to save the outline, this script is executed. Of course I put in this script `c.save()` call and on every save my files are regenerated.
When working for a web I often use Coffeescript, some html template generators like Pug, Sass for generating css files, ... Now all of these command line tools have watching mode where they watch folders for file changes and whenever source file is changed they regenerate the output file. But then you also need to run some packaging tool to bundle all generated files. Instead of watching for file changes, my script bound to Ctrl-s regenerate source files in memory and without saving them execute suitable tool only on changed sources and produced outputs bundle in the final file. This makes the whole process much faster.
Attached to this message is a Leo file that I have extracted from one of my projects. I hope that I didn't miss anything that the script require.
In the outline you can find build server implemented in Coffeescript. You have to use npm or yarn to install necessary modules for this server to work. Once installed you start server by executing
`coffee tools/build-server.coffee` and it will start listening on port 8011. The script bound to Ctrl-s will search outline for nodes with the headlines like: @vendor, @pug, @coffee, @bulma and for each found node, it checks if the content of this node and its subtree has changed since last time and if it is, this content is sent to build server which transforms the source and returns result that script writes to output file.
How can I enable and disable support for psyco?
***********************************************
Find the @file leoApp.py node in leoPy.leo. In the ctor for the LeoApp class set self.use_psyco to True or False. You will find this ctor in the node::
Code-->Core classes...-->@file leoApp.py-->app.__init__
Note that this ivar can not be set using settings in leoSettings.leo because Leo uses g.app.use_psyco before processing configuration settings.
How can I modify an existing theme?
***********************************
In the directory leo-editor/leo/themes are a number of theme files. These
can be loaded using the File, Open Outline menu option in Leo. Opening an
outline automatically loads it. Keep opening outlines until you find one
you like.
Then close all of the theme files.
Copy the theme file you chose from leo-editor/leo/themes to ~/.leo/themes
(you will have to create the themes folder here) and rename it something
like this: Original file is BreezeDarkTheme.leo rename to
BreezeDarkThemeLocal.leo
Now open your myLeoSettings.leo file.
Add the following to the headline of a new node as a child of your @settings node::
@string theme-name = BreezeDarkThemeLocal
Now save the file and restart Leo.
You should now be using the theme of your choice. From here you need to
open the local theme file with Leo. The font sizing and colors are under
Theme Settings in the tree.
How can I put background images in the body pane?
*************************************************
Put the following in the style-sheet:
QTextEdit#richTextEdit { background-image: url('/home/tbrown/Desktop/cow2.jpg'); }
If you wanted node specific backgrounds Leo would have to start setting an attribute on the body widget, probably the gnx, so you could do::
QTextEdit#richTextEdit[leo_gnx='tbrown.20130430222443.19340'] {
background-image: url('/home/tbrown/Desktop/cow2.jpg');
}
How can I run code at startup?
******************************
The following plugin, placed in ~/.leo/plugins, runs code at 'start1' time, that is, while other plugins are loading::
import leo.core.leoGlobals as g
print('===== local_plugin.py in ~/.leo/plugins/')
def hook(tag, keys):
g.trace(tag)
def init():
g.registerHandler('start1', hook)
return True
Alternatively, the plugin could run code at 'start2' time, after all plugins have been loaded, or at any other time, as described `on this page `_.
How can I sync settings across .leo files?
******************************************
Organize your myLeoSettings.leo file like this::
@settings
-my settings
-@bool .... = True
-@data fldsdf
@file mysettings.txt
my settings
Syncing mySettings.txt will synchronize your settings across your .leo files.
**Note**: Changed settings will not be available in other open outlines until you reload settings. You can do this with the reload-all-settings command.
How do I enable a theme .leo file?
**********************************
To enable a theme .leo file, put the following setting in myLeoSettings.leo::
@string theme-name =
Dark themes::
@string theme-name = BreezeDarkTheme
@string theme-name = EKRDark
@string theme-name = LeoBlackSolarized
@string theme-name = ZephyrDarkTheme
Light themes::
@string theme-name = DefaultTheme
@string theme-name = EKRLight
@string theme-name = PaperLightTheme
You can also define a theme directly in myLeoSettings.leo as follows:
- *Remove* (or disable) any previous @theme tree in myLeoSettings.leo.
- *Select* one of the @theme trees in leoSettings.leo.
- *Copy* the entire @theme tree to myLeoSettings.leo.
- *Move* the copied tree to the *end* of the @settings tree.
- *Test* by restarting Leo.
How can I use Leo's legacy key bindings?
****************************************
You can 'revert' to old key bindings as follows:
1. Open leoSettings.leo.
2. Find the node 'Keyboard shortcuts'.
3. Disable the old bindings by moving the node '@keys EKR bindings: Emacs keys + modes' so that it is a child of the node: '@ignore Unused key bindings'.
4. Notice that there are two child nodes of the node '@ignore Unused key bindings' that refer to legacy key bindings:
- '@keys Legacy Leo shortcuts with important Emacs bindings'
- '@keys Legacy Leo bindings'.
5. Move **one** of these two legacy nodes up one level so that it is a child of the node 'Keyboard shortcuts'. It should **not** be a child of the node '@ignore Unused key bindings'.
How do I add a new menu item from a plugin?
*******************************************
c.frame.menu.createMenuItemsFromTable will append items to the end of an existing menu. For example, the following script will add a new item at the end of the 'File' menu::
def callback(*args,**keys):
g.trace()
table = (("Test1",None,callback),)
c.frame.menu.createMenuItemsFromTable('File',table)
Plugins can do anything with menus using c.frame.menu.getMenu. For example, here is a script that adds a Test menu item after the 'Open With' menu item in the File menu::
def callback(*args,**keys):
g.trace()
fileMenu = c.frame.menu.getMenu('File')
# 3 is the position in the menu. Other kinds of indices are possible::
fileMenu.insert(3,'command',label='Test2',command=callback)
How do I set selection colors and fonts?
****************************************
See the node ``@data qt-gui-plugin-style-sheet`` in your theme file or ``myLeoSettings.leo``.
How do I submit a plugin?
*************************
You have two options:
- Get git write access, and add the @file file to the plugins directory.
- Just send the @file file to me at edreamleo@gmail.com.
Excel
+++++
How can I show Leo files with Excel?
************************************
.. From: https://sourceforge.net/forum/message.php?msg_id=3240374
Using Leo's File-Export-Flatten Outline commands creates a MORE style outline which places all Leo body sections on the left margin. The headlines_ are indented with tabs which Excel will read as a tab delimited format. Once inside Excel there are benefits.
1. The most obvious benefit inside Excel is that the body sections (Excel first column) can be selected easily and highlighted with a different font color. This makes the MORE format very readable. Save a copy of your sheet as HTML and now you have a web page with the body sections highlighted.
2. It is possible to hide columns in Excel. Hiding the first column leaves just the headlines showing.
3. Formulas based on searching for a string can do calculations in Excel. For example if a heading "Current Assets" appears on level 4 then the body formula::
=INDEX(A:A,MATCH("Current Assets",D:D,0)+1)
will retrieve it. The +1 after match looks down one row below the matched headline. The trick is to place all your headlines in quotes because Excel will see + "Current Assets" from the MORE outline. When Excel tries without the quotes it thinks it is a range name and displays a #N/A error instead of the headline. Also you must place a child node_ below to get the + sign instead of a - sign which would give a MORE headline of -"Current assets" , also is an error.
I think there is some interesting possibility here because of the enforcement of Leo body text being always in the first column. The Leo outline provides additional reference to organizing the problem not typical of spreadsheet models. Beyond scripting in Python, Excel is good at doing interrelated calculations and detecting problems like circular references. In Excel Tools-Options-General is a setting for r1c1 format which then shows numbers instead of letters for column references. Using this would allow entries like this in the leo body::
1000
3500
=R[-1]C+R[-2]C
In Excel you would see 4500 below those two numbers. This is completely independent of where the block of three cells exists on the sheet.
Files
+++++
Can @file trees contain material not in the external file?
**********************************************************
No. Everything in an @file trees must be part of the external file: orphan and @ignore nodes are invalid in @file trees. This restriction should not be troublesome. For example, you can organize your outline like this::
+ myClass
..+ ignored stuff
..+ @file myClass
(As usual, + denotes a headline.) So you simply create a new node_, called myClass, that holds your @file trees and stuff you don't want in the @file trees.
How can I avoid getting long lines in external files?
*****************************************************
**Question**: I must follow a coding standard when writing source code. It includes a maximum line length restriction. How can I know the length of a line when it gets written to the external file?
**Answer**: If a node belongs to a external file hierarchy, its body might get indented when it is written to the external file. It happens when an @others directive or a section name appears indented in a higher-level node body. While (**line**, **col**) in status area show the line and column containing the body text's cursor, **fcol** shows the cursor coordinate relative to the external file, not to the current node. The relation **fcol >= col** is always true.
How can I create a template .leo file?
**************************************
**Question**: It would be nice if Leo could open empty files. I tend to be "document oriented" rather than "application oriented" in my thinking and prefer "create empty file at location -> open it with program" to "start program -> create new file -> save it at location".
**Answer** by Paul Paterson: If you are on Windows 98/2000/XP then the procedure is as follows...
1. Start Leo
2. Click New
3. Click Save as...
4. Save the file as "c:\\windows\\shellnew\\leofile.leo" (or c:\\winnt for 2000/XP)
5. Open regedit "start...run...regedit"
6. Open HKEY_CLASSES_ROOT and find the ".leo" extension type
7. Go New ... Key from the context menu
8. Call the new key ShellNew
9. Select the new key, right-click, choose New...String Value from the context menu
10. Call it FileName
11. Double-click on the string, and modify it to be the filename of the leofile.leo file you created, including the extension
12. Exit the registry editor and restart Windows Explorer (you may need to reboot on Windows 98)
Now you should have a New:Leo File option in Explorer. This creates a duplicate of the file you saved. This can be useful because you could make a template Leo file containing some standard nodes_ that you always have and then save this.
How can I create Javascript comments?
*************************************
**Question**: I'm writing a Windows Script Component, which is an XML file with a CData section containing javascript. I can get the XML as I want it by using @language html, but how can I get the tangling comments inside the CData section to be java-style comments rather than html ones?
**Answer**: In @file trees you use the @delims directive to change comment delimiters. For example::
@delims /* */
Javascript stuff
@delims <-- -->
HTML stuff
**Important**: Leo can not revert to previous delimiters automatically; you must change back to previous delimiters using another @delims directive_.
How can I disable PHP comments?
*******************************
By Zvi Boshernitzan: I was having trouble disabling '
or::
@first
How can I export as a user-friendly HTML file?
**********************************************
**Question**: Is there a way to export an outline in an html format where the format of the html is similar to the desktop version of Leo with the expands and collapses? I want to send someone a copy of my outline that they can use in a browser to view.
**Answer**: Use the "leo_to_html_outline_viewer" plugin.
(It is enabled by default as of Leo 6.8.7. For existing installs, add "leo_to_html_outline_viewer.py" to the @enabled-plugins node's body in your "myLeoSettings.leo" file.)
This plugin adds an "Export HTML Outline Viewer" entry in the File->Export Files menu which outputs the Leo outline as a self-contained HTML interactive outline viewer.
The file is saved in the user's home/.leo folder and also opened with your default viewer.
How can I open special .leo files easily?
*****************************************
You can open files such as CheatSheet.leo, quickstart.leo, leoSettings.leo, myLeoSettings.leo and scripts.leo with commands starting with 'leo-'.
leo- shows the complete list of commands::
leo-cheat-sheet
leo-dist-leo
leo-docs-leo
leo-plugins-leo
leo-py-leo
leo-quickstart-leo
leo-scripts-leo
leo-settings
How can I specify the root directory of a thumb drive?
******************************************************
Use the %~dp0 syntax. Example::
%~dp0\Python27\python.exe %~dp0\Leo-editor\launchLeo.py
https://ss64.com/nt/syntax-args.html
https://stackoverflow.com/questions/5034076/what-does-dp0-mean-and-how-does-it-work
FYI, this FAQ entry fixes the following bug: https://bugs.launchpad.net/leo-editor/+bug/613153 unable to describe root directory on thumb drive
How can I use Leo with older C compilers
****************************************
By Rich Ries. Some older C compilers don't understand the "//" comment symbol, so using @language C won't work. Moreover, the following does not always work either::
@comment /* */
This generates the following sentinel line::
/*@@comment /* */*/
in the output file, and not all C compilers allow nested comments, so the last \*\/ generates an error. The solution is to use::
#if 0
@comment /* */
#endif
Leo is happy: it recognizes the @comment directive_. The C compiler is happy: the C preprocessor strips out the offending line before the C compiler gets it.
How can I use Leo with unsupported languages?
*********************************************
The @first directive_ is the key to output usable code in unsupported languages. For example, to use Leo with the Basic language, use the following::
@first $IFDEF LEOHEADER
@delims '
@c
$ENDIF
So this would enable a basic compiler to "jump" over the "true" Leo-header-lines. Like this::
$IFDEF LEOHEADER <-conditional compilation directive
#@+leo-ver=4 <-these lines not compiled
#@+node:@file QParser005.INC
#@@first
#@delims '
'@@c
$ENDIF <-... Until here!
This changes the comment symbol the apostrophe, making comments parseable by a BASIC (or other language.)
How do I inhibit sentinels in external files?
*********************************************
.. _`Mulder/Ream update algorithm`: appendices.html#the-mulder-ream-update-algorithm
Use @clean trees. Files derived from @clean trees contain no sentinels_. However, Leo can update @clean trees from changes made to the corresponding external file. The `Mulder/Ream update algorithm`_ makes this magic happen.
How do I make external files start with a shebang line?
*******************************************************
Use the @first directive_ in @file or @clean trees. The @first directive puts lines at the very start of files derived from @file. For example, the body text of @file spam.py might be::
@first #! /usr/bin/env python
The body text of @file foo.pl might be::
@first #/usr/bin/perl
\@first directives must be the *very first* lines of @file nodes. More than one @first directive may exist, like this::
@first #! /usr/bin/env python
@first # more comments.
How do I prevent Leo from expanding sections?
*********************************************
Use @asis trees. Files derived from @asis trees contain no sentinels. Leo creates the external file simply by writing all body text in outline order. Leo can't update the outline unless the external file contains sentinels, so Leo does not update @asis trees automatically when you change the external file in an external editor.
Why can't I use @ignore directives in @file trees?
**************************************************
``@ignore`` can only be used in the root node of @file trees. It tells Leo
to ignore the tree.
The ``@ignore`` directive can not be used elsewhere in @file trees because
of the way Leo recreates outlines from external files. This is an
absolutely crucial restriction and will never go away. For details, see the
entry for 2003 in the `History of Leo`_.
There are several workaround, as shown in LeoPy.leo:
- keep notes in the outline outside of any external file.
- Use ``@all`` to gather notes in a external file, as in done in @file
leoProjects.txt.
Git
++++
How can I use git to check Leo's importers?
*******************************************
When I study a program, I like to import it into Leo. I have several scripts that do this: some create @auto nodes; others create @file nodes. Whatever the method used, the import process has the potential to change many files. Usually, I just change @auto and @file to @@auto or @@file, so that any changes I make while studying the code won't affect the originals.
But this "safety first" approach means that I can't actually use Leo to insert tracing statements (or for any other changes.) Happily, there is a way to import "live" code into Leo safely::
Create a git repository for the code before importing it
The Aha is to create the repository *wherever the code is*, including,
say, python/Lib/site-packages.
- git diff ensures that import hasn't significantly altered the code,
This is exactly what I need: I can make changes to important tools *safely* within Leo.
How can I use Leo with git?
***************************
Imo, git rivals python as the greatest productivity tool ever devised for programmers.
My workflow on Ubuntu and Windows is essentially identical. Simple aliases (Ubuntu) and .bat files (Windows) support the following console commands::
gs (expands to git status)
gd (git diff) Uses an external diff program,
but I'm starting to prefer text diffs.
ga . (git add .)
ga file (git add file)
gc (git commit: configured to open Scite to create a commit message)
gc -m "a one-line commit message"
push (git push)
I use gitk on both platforms to review commits.
And that's about it. I use "git help" and "git help command" as needed.
How should I use Leo with git, etc.?
************************************
.. _`reference .leo files`: FAQ.html#what-is-a-reference-leo-file
Use @clean or @auto unless everyone in your work group uses Leo. In that case, using @file is best. Use local copies of `reference .leo files`_ instead of the reference files themselves.
What is a reference .leo file?
******************************
`leoeditor/leo/core` contains a **reference .leo file**: **LeoPyRef.leo**.
This file should change only when adding new external files to Leo.
Developers should use a local copy of LeoPyRef.leo (conventionally called
**leoPy.leo**) for their own work.
Why do files sometimes change when switching branches?
******************************************************
Private copies of LeoPyRef.leo, that is, leoPy.leo, are "global". That is, they persist unchanged when switching branches. In effect, they act like (sometimes) unwanted caches.
If you change the *structure* of @file nodes in leoPy.leo in one branch, such changes will "propagate" to other branches, even though the contents of each node has remained the same.
You can see such changes clearly using leo --diff.
In short, don't make unnecessary structural changes in leoPy.leo when in branches other than master.
Graphics
++++++++
How can I display graphics in Leo?
**********************************
One way is to link directly to the media file from a Leo node_ (with @url) and write a script button to wrap all URL-nodes under the current node_ in a single HTML page. Then, you can view your media in two ways:
- Individually. You can directly click on the @url link to display the media in the browser (assuming you have your MIME/filetype associations set up correctly for your browser).
- In a group. You can click on a script button (you have to code this yourself, very simple) which should collect all @url nodes_ under the current node_ and dynamically generate a HTML page displaying either links to or embedded versions of the media (using the HTML trick described above to invoke the browser). This way, you can create collections of @url nodes under a single node_ (like a bookmark folder), and press a single button to view the @url collection as a single entity in the browser (with all browser capabilities like displaying the media).
You could probably generalize this idea of "collect all @url nodes under current node_ and display as HTML in browser" into a general-purpose plugin. However, the plugin would have to be somewhat smart in mapping a link to its corresponding HTML code (e.g. an image link gets mapped to an
HTML tag, a link to a Flash file gets mapped to an