Release Notes

Contents

Release Notes#

Leo 6.8.x release notes#

Leo 6.8.10 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.8.10 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [outline-oriented text editor](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.8.10

  • Add authentication & secure websockets to leoserver.py.

  • Add the show-node-files command.

  • Add the clone-diff-pr command.

  • Add the c.p setter.

  • Update most theme files.

  • Add vv-dark.leo theme.

  • Add a Leo launcher generator for MacOS.

  • Remove the todo.py plugin.

  • Breaking changes to Leo’s API: See the What’s New section for details.

  • The usual bug fixes.

Links

Leo 6.8.9 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.8.9 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [outline-oriented text editor](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.8.9

  • Add Find/Change history. How did we ever live without this?

  • Replace the ,, Easter Egg with Leo’s Find commands.

  • Add support for @language pug.

  • Enhanced security for Leo’s server.

  • Significant code-level improvements and performance optimizations.

  • Deprecate support for –gui=console.

  • The usual bug fixes.

Links

Leo 6.8.8 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.8.8 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [outline-oriented text editor](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.8.8

  • Replace Leo’s legacy beautifier commands by full support for [ruff format](https://docs.astral.sh/ruff/formatter/).

  • Make the add-comments command compatible with ruff format.

  • Add the @bool raise-file-update-dialogs setting.

  • Add the dump-last-colorizer-trace command.

  • Remove support for leoflexx and –gui=browser.

  • Add check_leo.py script.

  • Add gdc.summary_diff_two_revs script helper.

  • Fix several minor bugs.

Links

Leo 6.8.7 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.8.7 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.8.7

  • PR #4403: Add support for Python 3.14. Require Python 3.10 or above.

  • PR #4423: All of Leo’s importers now import @clean files perfectly.

  • PR #4412: Greatly improve Leo’s parse-body command.

  • PR #4418: Fix bugs involving the _mod_time attribute in .leo files.

  • PR #4456: Added leo_to_html_outline_viewer.py plugin.

  • PR #4456: Add check_leo script.

  • Fix several other minor bugs. See the What’s new section for details.

Links

Leo 6.8.6 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.8.6.1 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.8.6 and Leo 6.8.6.1

  • Leo 6.8.6.1 fixes a bug introduced in Leo 6.8.6 that could corrupt @clean nodes.

  • Read only unchanged @clean nodes: a huge performance boost!

  • Support @leo <path>; nodes. See https://leo-editor.github.io/leo-editor/directives.html#leo-directives - The open-at-leo-file command opens the given outline. - The c.makeLinkLeoFiles method helps scripts create a top-level

    outline containing links to sub-outlines.

  • Support for virtual python environments: a long-awaited update for LeoInteg!

  • Add a theme file for SwotMoknokai.

Links

Leo 6.8.5 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.8.5 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.8.5

  • This release contains minor bug fixes and code cleanups.

  • The signatures of the`k.registerCommand` and k.registerCommandShortcut methods have changed.

Links

Leo 6.8.4 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.8.4 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.8.4

  • Improve the Rust importer.

  • Allow rest comments to be colored differently from @language rest.

  • Support @language typst.

  • Several other improvements to syntax coloring.

  • Add the show-buttons-and-at-commands command.

  • Add the find-source-for-command command.

  • Add the beautify-script command.

  • The execute-script command beautifies c.p’s tree if @bool beautify-python-code-on-write = True.

  • Remove the join-leo-irc command.

  • Scripts (including @command and @button scripts) may now return a value.

  • Replace c.scanAllDirectives with 7 seven new Commands getters.

  • Deprecate c.scanAllDirectives and 17 other directives-related functions.

  • Call g.deprecated in all deprecated functions to issue a deprecation warning.

  • Several significant code cleanups.

  • The usual minor bug fixes.

Breaking change

  • Syntax coloring for @language rest may require a new setting in myLeoSettings.leo. See the What’s new in Leo 6.8.4 for details.

Links

Leo 6.8.3 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.8.3 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.8.3

  • Five PRs improve and generalize Leo’s colorizer.

  • PR #4140: Improve @language jupytext.

  • PR #4178: Add @language openscad.

  • PR #4198: Add @language glsl

  • PR #4203: Add @language vue

  • PRs #4207 and #4209: Upgrade Leo’s website.

  • The usual assortment of small bug fixes and code cleanups.

Links

Leo 6.8.0 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.8.0 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.8.0

This release contains several breaking changes to Leo’s API. See the What’s new in Leo 6.8.0 section for details.

Significant changes

  • PR #3828: Leo now requires PyQt6.

  • PR #3911: Leo’s core no longer uses the free_layout or nested_splitter plugins.

  • PR #3872: Improve how Leo searches for definitions. Add @bool prefer-nav-pane.

  • PR #3922: Improved the restart-leo command.

New and improved

  • PR #3870: Leo’s beautifier works faster.

  • PR #3841: Add g.traceUnique and g.traceUniqueClass functions.

  • PR #3893: Add vr-fully-expand, vr-toggle-visibility and vr-keep-open commands.

  • PR #3902: Add the toggle-unl-view command.

  • PR #3921: Add the show-qt-widgets command.

  • The usual minor improvements and bug fixes.

Links

Leo 6.7.x release notes#

Leo 6.7.8 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.7.8 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.7.8

This release simplifies Leo’s install process. See https://leo-editor.github.io/leo-editor/getting-started.html

  • PR #3757: (leoTokens.py) Make Leo’s beautifier 3x faster.

  • PR #3771: Revert colorizing of f-strings.

  • PR #3786: Support Nim.

  • PR #3790: Add “get-unl” command to Leo’s server.

  • PR #3805: Fix problems with auto-completion and calltips.

  • PR #3806: Fix problems with Leo’s go-back and go-forward commands.

  • PR #3807: Improve Leo’s Python importer.

  • PR #3817: Allow relative paths in gnx-based UNLs.

  • The usual minor improvements and bug fixes.

Links

Leo 6.7.7 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.7.7 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.7.7

  • PR #3761: Improve leoserver.py to support LeoInteg.

  • Assorted minor improvements.

Links

@nowrap

Leo 6.7.6 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.7.6 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.7.6

Support for Python 3.12:

  • PR #3693: update leoAst.py for Python 3.12.

  • PR #3701: Colorize PEP 701 f-strings.

Other significant improvements:

  • PR #3645: Allow mixed external files on the command line.

    Retire the –load-type command-line option.

  • PR #3575: Add the indented_languages plugin.

  • PR #3642: Add the clean-all-lines command.

  • PR #3659: Add python-to-rust command.

  • PR #3673: Add summarize command.

  • scripts.leo contains @button scripts by Thomas Passin.

The usual assortment of minor bug fixes and code-level improvements.

Links

@nowrap

Leo 6.7.5 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.7.5 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.7.5

  • PR #3568: Improve word-oriented finds and improve Leo’s spell checker.

  • PRs #3515 and #3517: Significantly improve python importer.

  • PRs #3509 and #3511: Improve rust importer.

Other improvements

  • PR #3560: Retire the g.SherlockTracer class.

  • PR #3552: Clear dirty bits when writing sqLite DBs.

  • PR #3541: Use c.doCommandByName instead of c.k.simulateCommand.

  • PR #3538: Make file-diff-files undoable.

  • PR #3533: Reload outlines rather than restarting Leo.

  • PR #3531: Add move-outline-to-first-child & move-outline-to-last-child commands.

  • PR #3528: Improve copy-gnx command.

  • PR #3525: Add promote-section-references command.

  • PR #3521: Improve what-line command.

  • PR #3519: Make the mark-node-and-parents and unmark-node-and-parents commands undoable.

  • PR #3503: Fix bug involving back slashes in search patterns.

  • PR #3499: Retire the read-outline-only command.

  • PR #3607: Add scheme importer

  • Fix several other minor bugs.

Links

@nowrap

Leo 6.7.4 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.7.4 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.7.4

Warning: breaking changes to Leo’s api

p.get_UNL returns gnx-based unls. Previously it returned path-based gnxs. See the first comment of PR #3424 for full details.

gnx-based unls

  • PR #3215 and #3424: gnx-based unls (clickable links). These links will break only if the original node is deleted.

New settings

  • @string unl-status-kind = gnx

  • @bool full-unl-paths = True

  • @data unl-path-prefixes

Other improvements

  • PR #3330: Improve importers for C, C++, and cython.

  • PR #3345: Improve importer architecture.

  • PR #3363 & #3379: Improve c.recursiveImport.

  • PR #3376: Improve python importer.

Large code changes

  • PR #3365: Simplify mypy annotations (128 files).

  • PR #3367: Import Callable from collections.abc instead of typing (50 files).

Retire three plugins

  • PR #3215: Retire the settings_finder, backlink, and quickMove plugins.

50+ issues and 70+ pull requests.

Links

@nowrap

Leo 6.7.3 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.7.3 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.7.3

  • PR #3260: Improved and safer handling of paths in @<file> nodes.

    Leo supports Python’s standard os.path expansions. Leo no longer supports {{python-expression}} in headlines.

  • Several large code cleanups: 460+ files changed.

Commands

  • PR #3227: Add commands to add/remove numbers from headlines.

  • PR #3255: Add write-zip-archive command.

  • PR #3192: Add show-color-settings and the show-font-settings commands.

Other changes

  • PR #3208: Add ‘reload-settings’ hook.

  • PR #3214: Optionally expand headlines on mouse-over.

  • PR #3224: Improve mod_autosave plugin.

  • PR #3241: Simplify Leo’s path wrappers.

  • PRs #3264 and #3277: Simplify Leo’s path-related code.

  • Tweaks and small bug fixes: 20+ issues and 30+ pull requests.

Links

@nowrap

Leo 6.7.2 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.7.2 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.7.2

Commands:

  • PR #3031: Add check-nodes command. It helps keep @clean files in sync.

  • PR #3056: Leo’s beautify command is now PEP8 compliant.

  • PR #3140: Run pylint on node.

  • PR #3166: Add the execute-external-file command.

Settings and features:

  • PR #2979: Add @bool run-flake8-on-write setting.

  • PR #2983: Add –black-sentinels command-line option.

  • PR #3038: Add @string rst3-action setting.

  • PR #3053: Add @string gxn-kind setting: Support gnxs formatted as UUIDs.

  • PR #3132: Add @bool rst3-remove-leo-directives setting.

Other changes:

  • 80+ issues and 100+ pull requests.

Links

@nowrap

Leo 6.7.1 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.7.1 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.7.1

  • Several enhancements to leoserver.py.

  • Add support for ocaml syntax coloring.

  • Improve markdown importer.

  • @bool plain-key-outline-search is False by default, disabling a confusing feature.

  • Several minor code cleanups.

  • Remove four unused commands.

Links

@nowrap

Leo 6.x release notes#

Leo 6.6.3 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.6.3 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo, https://leo-editor.github.io/leo-editor/ is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.6.3

  • Enhance leoserver.py to support LeoInteg and LeoJS.

  • Improve how Leo handles url’s.

  • Simplify the GlobalConfigManager class.

  • The usual assortment of tweaks and bug fixes.

Links

@nowrap

Leo 6.6.2 release nodes#

Leo https://leo-editor.github.io/leo-editor/ 6.6.2 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.6.2

  • Add “File Only” option in Leo’s Find Pane.

  • Remove pylint-leo.py, pyflakes-leo.py and related code.

  • Add mypy annotations for Leo’s most important files.

  • Fixed 9 minor bugs.

6.6.2 Links

General Links

@nowrap

Leo 6.6.1 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.6.1 is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/6.6.1/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.6.1

  • Improve support for Python 3.10 and PyQt6.

  • Simplify the TokenOrderGenerator class in leoAst.py.

  • Improve argument handling when running leo.core.leoAst externally. Run python -m leo.core.leoAst -h for details.

  • Control-clicking on a file name searches for the corresponding @<file> node.

  • Create clickable links when copying text into the log pane.

  • Leo’s mypy command runs without blocking Leo.

  • Improve the add-mypy-annotations command.

  • Clean all files with reindent.

  • The usual minor bug fixes.

6.6.1 Links

General Links

@nowrap

Leo 6.6 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.6 final is now available on [GitHub](leo-editor/leo-editor) and [pypi](https://pypi.org/project/leo/6.6/).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.6

  • Replaced @raw and @end_raw with @section-delims.

  • Leo recognizes section references only when they appear on an otherwise blank line.

  • Many improvements to the python-to-typescript command.

  • Improved python importer.

  • Added plugins/picture_viewer.py, a stand-alone app that displays images.

  • Added plugins/remove_duplicate_pictures.py, an app that finds duplicate pictures.

  • The user may choose other commands after starting repeat-complex-command.

  • Improved leoserver.py to support leointeg.

  • Many bug fixes.

6.6 Links

General Links

@nowrap

Leo 6.5 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.5 is now available on [GitHub](leo-editor/leo-editor).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.5

  • Add python-to-typescript and view-recent-commands.

  • Add c.findCommands.interactive_search_helper.

  • Leo now uses only traditional unit tests. Remove support for @test and @suite. Remove leoTest.py.

  • Many code-level cleanups.

  • 450+ pull requests.

6.5 Links

General Links

@nowrap

6.5: Commands#

#2256: view-recent-commands leo-editor/leo-editor#2256

#2267: python-to-typescript leo-editor/leo-editor#2267

6.5: Features#

#1766: Use traditional unit tests leo-editor/leo-editor#1766 PR: leo-editor/leo-editor#2159

#2194: black-compatible sentinels leo-editor/leo-editor#2194

#2219: c.findCommands.interactive_search_helper leo-editor/leo-editor#2219

6.5: Settings#

@data python-to-typescript-types

A list of key/value pairs. Keys are argument names (as used in Leo); values are typescript type names.

6.5: Testing#

  • leoTest2.py create temporary Leo applications and outlines for unit tests.

  • Remove @test, @suite, unitTest.leo and leoTest.py.

Leo 6.4 release notes#

Leo https://leo-editor.github.io/leo-editor/ 6.4 is now available on [GitHub](leo-editor/leo-editor).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.4

  • Support for [LeoInteg](boltex/leointeg): “Leo in vs-code”. - Add leoserver.py, stand-alone server for Leo. - Add support for .leojs, a json outline format.

  • Support for Qt6.

  • The wax_off.py script converts function annotations to stub (.pyi) files.

  • Remove support for @root. Create a conversion script.

  • Simplify and generalize rst3 command.

  • Add git-diff-pr command: Leonine diffs for Pull Requests and .leo files.

  • Add execute-general-script command and c.general_script_helper.

  • Several significant code-level changes.

  • Fixed 160+ issues and merged almost 400 Pull Requests.

Links

6.4: Bugs#

For a list of all the bugs fixed in Leo 6.4 see: leo-editor/leo-editor#issues

6.4: Code#

For a list of all changes to codebase see: leo-editor/leo-editor#issues

Only the highlights are shown below.

#1413: New undo pattern#

leo-editor/leo-editor#1413

PR: leo-editor/leo-editor#1759

#1715: Add execute-general-script#

leo-editor/leo-editor#1715

Add c.general_script_helper.

#1721: Remove most calls to c.setBody/HeadString#

leo-editor/leo-editor#1721

#1806: Rewrite leoFind.py, with unit tests#

leo-editor/leo-editor#1806

#1944: Annotations & stub files#

leo-editor/leo-editor#1944 PR: leo-editor/leo-editor#1948

#1973 and #2005: Support Qt6#

leo-editor/leo-editor#2005 leo-editor/leo-editor#1973

#2005: Add more qt imports#

leo-editor/leo-editor#2005

#2081: Use sys.excepthook, not @g.callback#

leo-editor/leo-editor#2081

#2103: stubs for leoGlobals.py#

leo-editor/leo-editor#2103

6.4: Commands#

Add commands: - convert-at-root: #1832. - copy-gnx: #1841. - mypy: #1831. - reformat-selection: #1754. - show-all-tags.

Change commands: - reload-settings now changes settings in all open outlines.

#1715: Add execute-general-script#

leo-editor/leo-editor#1715

Add c.general_script_helper.

#1754: reformat-paragraph#

leo-editor/leo-editor#1754

w.see works for the first time ever!

#1831 & #2049: mypy command#

leo-editor/leo-editor#1831

leo-editor/leo-editor#2049

#1841: copy-gnx#

leo-editor/leo-editor#1841

#1955: improve extract command#

leo-editor/leo-editor#1955

PR #1849: reload-settings now changes all settings#

leo-editor/leo-editor#1849

6.4: Major features#

#0442: json: .leojs files#

leo-editor/leo-editor#442

#1672: Remove support for Qt docks#

leo-editor/leo-editor#1672

Leo’s Qt docks caused great confusion. Leo is better off without them.

#1715: Add execute-general-script#

leo-editor/leo-editor#1715

Add c.general_script_helper.

#1768: Change cursor in command mode#

leo-editor/leo-editor#1768

#1772: Add git-diff-pr command#

leo-editor/leo-editor#1772

Added gdc.diff_pull_request.

#1781: Leonine diffs of .leo files#

leo-editor/leo-editor#1781

#1813: Add leoserver.py and leoclient.py#

leo-editor/leo-editor#1813

#1832: Retire @root and convert-at-root command#

leo-editor/leo-editor#1832

#1846: Support pyQt6#

leo-editor/leo-editor#1846

#1867: Simplify rst3#

leo-editor/leo-editor#1867

6.4: Other features#

#1240: Alert for changed .leo file#

leo-editor/leo-editor#1240

#1780: Improve support for backup scripts#

leo-editor/leo-editor#1780

#1792: Improve themes for newbies#

leo-editor/leo-editor#1792

#1798: Better error reports#

leo-editor/leo-editor#1798

Note: Leo can not recognize @path directives in the body text of @file nodes!

#1808: Pylint checks last file by default#

leo-editor/leo-editor#1808

#1840: one-shot headline-only#

leo-editor/leo-editor#1840

Add leo/scripts/wax_off.py#

This script creates stub (.pyi) files from def lines containing annotations, then removes the annotations.

The wax_off script allows you to add annotations directly in your .py files, and then move most of the clutter to stub files.

Imo, the wax_off script makes my make_stub_files project obsolete.

6.4: Settings & command-line options#

Add @bool allow-text-zoom = True leo-editor/leo-editor#1923

Add support for –trace-speed. leo-editor/leo-editor#1936

Add settings for Leo’s mypy command: leo-editor/leo-editor#1831 leo-editor/leo-editor#2049 @data mypy-arguments @int mypy-link-limit @string mypy-config-file

Add settings for highlighting the selected line: @bool highlight-body-line = False @string line-highlight-color = None

Leo 6.3 release notes#

Leo 6.3, https://leo-editor.github.io/leo-editor/ is now available on [GitHub](leo-editor/leo-editor).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.3

  • leoAst.py: The unification of Python’s token and ast worlds.

  • Retired all Qt Dock code.

  • Improved viewrendered and viewrendered3 plugins.

  • Improved several importer plugins.

  • Refactored Leo’s key handling code.

Links

6.3: Bugs#

For a list of all bugs fixed in Leo 6.3 see: leo-editor/leo-editor#issues The first comment in each bug contains a summary of the bug and its fix.

Crash on reloading workbook while simulating newbie experience leo-editor/leo-editor#1381

Headline icons doubled leo-editor/leo-editor#1559

Abbreviations w/ German keyboards leo-editor/leo-editor#1563

Open theme file fails on posix leo-editor/leo-editor#1564

Tab pane disappears leo-editor/leo-editor#1570 PR: leo-editor/leo-editor#1660

No command function for ‘About…’ leo-editor/leo-editor#1595

Crash in c.executeMinibufferCommand leo-editor/leo-editor#1596

leoAst.py fails for python 3.8 leo-editor/leo-editor#1600

Typescript colorizer does not color block comments properly leo-editor/leo-editor#1602

Exit after refresh-from-disk leo-editor/leo-editor#1603

open-theme-file on arch linux leo-editor/leo-editor#1621

Set language for cloned nodes leo-editor/leo-editor#1625

forward-word-extend-selection doesn’t work the same as back-word-extend-selection leo-editor/leo-editor#1653

Remove duplicates in nested splitter Open Window list leo-editor/leo-editor#1678

Performance bugs on open leo-editor/leo-editor#1688

@test nodes not colored correctly leo-editor/leo-editor#1696

Problems with marked bits leo-editor/leo-editor#1694

Bug in php importer leo-editor/leo-editor#1717

unittest fails w/ python3.8 leo-editor/leo-editor#1700

6.3: Code#

Major change

Refactor Leo’s key handling code leo-editor/leo-editor#1269

Other changes

Remove pylint complaints from npyscreen sources leo-editor/leo-editor#1709

Remove pyflakes complaints from mod_http.py leo-editor/leo-editor#1710

6.3: Commands#

contract-all-subheads leo-editor/leo-editor#1632

cycle-editor-focus (Restored) leo-editor/leo-editor#1575

import-legacy-external-files leo-editor/leo-editor#1581

paste-as-template leo-editor/leo-editor#1593

move-lines-to-next-node leo-editor/leo-editor#1606

open-leo-py-ref-leo (Aka leo-py-ref-leo)

restart-leo leo-editor/leo-editor#1128

show-settings: Add [T] to legend to indicate theme file settings. leo-editor/leo-editor#1698

6.3: Importers#

JS importer fails with reveal.js leo-editor/leo-editor#1481

Python importer does not import black.py properly leo-editor/leo-editor#1493

Create a Rust importer leo-editor/leo-editor#1538

Create a cython importer leo-editor/leo-editor#1608

Fix ts importer problems leo-editor/leo-editor#1617

Fix c++ importer problems leo-editor/leo-editor#1626

6.3: Features#

Major features

leoAst.py: Unify the ast and token worlds leo-editor/leo-editor#1440

Retire qt docks leo-editor/leo-editor#1672

Other features

Better alt-click popups leo-editor/leo-editor#1286

Add support for –trace=zoom leo-editor/leo-editor#1569

Ctrl-click should ignore defs in @nosearch leo-editor/leo-editor#1592

Show github branch in outline title leo-editor/leo-editor#1616

Add support for @language json leo-editor/leo-editor#1619

#1620: git-diff clones added nodes leo-editor/leo-editor#1620

Added @button write-leoPyRef.leo leo-editor/leo-editor#1716

6.3: Settings and command-line options#

Added @bool add-context-to-headline leo-editor/leo-editor#1605

Removed the following command-line options:

–dock –global-docks –init-docks –no-dock –use-docks

Added support for –trace=zoom

6.3: Plugins#

Render asciidoc and pandoc markup in VR leo-editor/leo-editor#333

VR plugin should honor headline directives leo-editor/leo-editor#1287

Plugins:About does not show VR https://github.com/leo-editor/leo-editor/issues/1332

Use standard opml tags leo-editor/leo-editor#1473

Context menu leo-editor/leo-editor#1531

Deprecated settings_finder plugin leo-editor/leo-editor#1669

Leo 6.2 release notes#

Leo 6.2.1, https://leo-editor.github.io/leo-editor/ is now available on [GitHub](leo-editor/leo-editor).

Leo is an [IDE, outliner and PIM](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.2

  • Added the fstringify-files and diff-fstringify-files commands.

  • Improved the beautify-files command. Added the diff-beautify-files commands.

  • Added the TokenOrderGenerator and TokenOrderTraverser classes in leoAst.py. Leo’s fstringify and beautify commands use these classes.

  • Added importers for the rust language and todo.txt files.

  • Added the viewrendered3 plugin.

  • Leo’s legacy layout is now the default.

  • Fixed all known bugs, including some notable, long-standing bugs.

  • Fixed several “fit and finish” issues.

  • Removed unused settings from leoSettings.leo.

Links

6.2: Code#

Convert Leo’s code to fstrings: leo-editor/leo-editor#1421

Unify the ast and token worlds: leo-editor/leo-editor#1440 This was a major project: - Add TokenOrderGenerator and TokenOrderTraverser classes. - Add the Fstringify and Orange classes.

Simplify startup logic: leo-editor/leo-editor#1472

Retire @doc file convention: leo-editor/leo-editor#1496

Add ivars for command1/2 event handlers: leo-editor/leo-editor#1508

Replace idle-time handlers with QApplication.processEvents: https://groups.google.com/d/msg/leo-editor/EvBDDCybV2E/tnRAZDqXCgAJ Changed g.recursiveUNLSearch and QtIconBarClass.goto_command.

Rewrote c.deletePositionsInList: leo-editor/leo-editor#1539

6.2: Commands#

Added fstringify-files and diff-fstringify-files commands.

Improved beautify-files command and add diff-beautify-files command.

Removed beautify-node and beautify-tree commands.

Restored Leo’s pane commands: leo-editor/leo-editor#1518 At present, they work only w/o docks.

6.2: Features#

Persistent body editors: leo-editor/leo-editor#1268

Improve alt-click popups: leo-editor/leo-editor#1286

Add tool tips for headlines: leo-editor/leo-editor#1310

Add an importer for todo.txt files leo-editor/leo-editor#1499

6.2: Bugs#

For a list of all bugs fixed in Leo 6.2 see: leo-editor/leo-editor#issues The first comment in each bug contains a summary of the bug and its fix.

Notable bugs:

Leo-Bridge can be wrong about an outline read from a file: leo-editor/leo-editor#1437 The fix is due to Vitalije Milosevic.

Possible problems with marks: leo-editor/leo-editor#1484

execute_shell_commands creates zombie processes: leo-editor/leo-editor#1489

6.2: Settings and command-line options#

Leo’s legacy layout is now the default: leo-editor/leo-editor#1514 - Add –use-docks option. - Deprecate –no-dock option. - The–global-docks command-line option implies –use-docks. - The default for @string initial-split-orientation is horizontal.

Retired the @bool beautify-autobeautify setting.

Removed many unused settings from leoSettings.leo.

Leo 6.1 release notes#

Leo 6.1, https://leo-editor.github.io/leo-editor/ is now available on [GitHub](leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.1

  • Pyzo in Leo: Pyzo can optionally run within Leo.

  • Added support for asciidoc and asciidoctor.

  • Added support for pandoc and sphinx.

  • Added support for black.

  • The history_tracer plugin animates git commits.

  • Integration of Leo with VS code.

  • New command-line arguments: –global-docks and –window-spot.

  • New cursor-movement commands.

Special thanks to Vitalije Milosevic, Brian Theado, and Matt Wilkie for their contributions to Leo 6.1.

Links

6.1: Major features#

#1093: pyzo_in_leo plugin#

leo-editor/leo-editor#1093 The pyzo_in_leo plugin embeds pyzo (https://pyzo.org/) within Leo.

#1315: The history_tracer plugin animates git commits#

leo-editor/leo-editor#1315

Support for asciidoc and asciidoctor#

Issues related to asciidoc: leo-editor/leo-editor#issues

Background

asciidoc3 is a python tool. asciidoctor is a ruby tool, claiming to be 100 times faster than asciidoc.

The asciidoc markup language is virtually identical, regardless of the tool used. For full details, see the asciidoctor User manual: https://asciidoctor.org/docs/user-manual/

Here are the recent improvements…

Live rendering of asciidoc and pandoc markup

The VR plugin recognizes @adoc node and @language md. The VR plugin renders only p.b.

Improved adoc command

Given an @adoc node of the form @adoc <full path>, this command does the following:

  1. Scan the @adoc tree, writing the result to adoc_test.adoc.

The scan converts headlines to section markup. See help-for-command for adoc for more details.

  1. Calls asciidoctor or asciidoc3 to convert adoc_test to adoc.html.

This command prefers asciidoctor to to asciidoc3 if both exist.

New adoc-with-preview command

Runs the adoc command, then shows the resulting html in the default browser.

Support for pandoc, including @language pandoc#

Background

pandoc is a tool for converting pandoc markup (a variant of markdown) to html, and many other formats.

Support for @language pandoc

leo/modes/pandoc.py is based on leo/modes/md.py.

Live rendering of pandoc markup

The VR plugin recognizes @pandoc nodes (see below) and @language pandoc.

The VR plugin renders only p.b.

New pandoc and pandoc-with-preview commands

Much like the corresponding adoc commands, but uses pandoc markup, which is a variant of markdown.

The pandoc tool must exist, because Leo uses it to convert @pandoc trees to html.

Support for black#

#1266: orange (beautify & blacken) leo-editor/leo-editor#1266

#1272: Added support for black (https://pypi.org/project/black/) leo-editor/leo-editor#1272

#1325: black keeps overindented comments: leo-editor/leo-editor#1325

Support for sphinx#

leo-editor/leo-editor#1388

6.1: Bugs#

This page shows all bugs related to Leo 6.1: leo-editor/leo-editor#issues

Minor bugs#

#0490: scroll wheel problems leo-editor/leo-editor#490

#1273: dashed border after dialog leo-editor/leo-editor#1273

#1274: leoQt.py should return None for everything when in bridge leo-editor/leo-editor#1274

#1276: clear-*-uas don’t set outline dirty leo-editor/leo-editor#1276

#1285: Control-clicks can find definitions in the wrong outline leo-editor/leo-editor#1285

#1295: too many @first lines leo-editor/leo-editor#1295

#1307: @first/last invalid in @clean leo-editor/leo-editor#1307

#1318: better arrangement for docks in new windows leo-editor/leo-editor#1318

#1327: Missing outlines for non-existent files leo-editor/leo-editor#1327

#1333: undo glitch leo-editor/leo-editor#1333

#1334: @language C crashes Leo leo-editor/leo-editor#1334

#1335: ipython–exec leo-editor/leo-editor#1336

#1340: body/outline ratio in new files leo-editor/leo-editor#1344

#1345: unit tests fail from bridge leo-editor/leo-editor#1345

#1347: @asis problems leo-editor/leo-editor#1347

#1349: Find Status leo-editor/leo-editor#1349

#1361: at.precheck is broken leo-editor/leo-editor#1361

#1362: crash when reloading leo-editor/leo-editor#1362

#1373: Adoc writes to Scripts folder instead of .leo folder when no @path given leo-editor/leo-editor#1373

#1379: Crash on saving workbook while simulating a new user’s experience leo-editor/leo-editor#1378

#1380: Opening workbook for new user selects top-level nodes repeatedly leo-editor/leo-editor#1380

#1381: Crash on reloading workbook while simulating newbie experience leo-editor/leo-editor#1381

#1385: Console gui doesn’t ask to create leoid leo-editor/leo-editor#1385

#1392: external file not always saved leo-editor/leo-editor#1392

#1403: Catch exceptions during startup leo-editor/leo-editor#1403

#1404: ensure well-formed gnx’s leo-editor/leo-editor#1404

#1415: crash when .leo doesn’t exist leo-editor/leo-editor#1415

#1416: select first .leo file on the command line leo-editor/leo-editor#1416

#1338: {{ conflicts#

leo-editor/leo-editor#1338

g.getUrlFromNode was expanding path expressions in body text!

This was a serious bug that could lead to the execution of unchecked code.

See also: #1341: limit path expressions leo-editor/leo-editor#1341

6.1: Code features#

#1316: unify g.TypedDict classes leo-editor/leo-editor#1316

#1323: convert to fstrings leo-editor/leo-editor#1323

#1350: LeoBridge option to not use the cache leo-editor/leo-editor#1350

#1364: Use “”” for all docstrings leo-editor/leo-editor#1364

#1394: External file not always saved leo-editor/leo-editor#1394 - p.setDirty() is now much faster than before. - Added c.all_positions_for_v generator.

6.1: Features#

This page shows all enhancements related to Leo 6.1: leo-editor/leo-editor#issues

#1253: Support @language asciidoc leo-editor/leo-editor#1253

#1297: warnings about @first & @last leo-editor/leo-editor#1297

#1342: use labels in Find Tab leo-editor/leo-editor#1342

#1351: removed click/drag commands leo-editor/leo-editor#1351

#1353: new cursor commands leo-editor/leo-editor#1353

#1371: support pandoc and @language pandoc leo-editor/leo-editor#1371

#1383: Expand ~ in all paths leo-editor/leo-editor#1383

#1398: Support path expressions in @rst, @adoc, @pandoc and @sphinx nodes leo-editor/leo-editor#1398

New show-clone-ancestors and show-clone-parents commands

6.1: Settings, directives, command-line arguments#

#1263: –window-spot#

leo-editor/leo-editor#1263

#1289: –global-docks#

leo-editor/leo-editor#1289

#1306: @nopyflakes#

leo-editor/leo-editor#1306

Leo 6.0 release notes#

Leo 6.0 final, https://leo-editor.github.io/leo-editor/ is now available on [GitHub](leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 6.0

  • Leo’s default gui uses Qt Docks. Use –no-dock to use Leo’s legacy gui.

  • Several commands now generate clickable links in the Log pane. This greatly speeds navigation.

  • The usual assortment of bug fixes and minor improvements.

Links

Acknowledgements#

The following people contributed significantly to Leo 6.0:

Terry Brown: Born in New Zealand, living in Duluth, Minnesota for 22 years. Ross Burnett Josef Dalcolmo: Born in Italy, living and working in Germany. Chris George: Notch Hill, British Columbia, Canada. Bob Hossley Seth Johnson Rob Keeney: Suwanee, Georgia, USA. John Lunzer. Виталије Милошевић (Vitalije Milosevitch): Serbia. Lewis Neal, Sydney, Australia. Viktor Ransmayr: Munich, Germany. Matt Wilkie: Whitehorse, Yukon, Canada. 周琦 (ZoomQuiet): China.

The following people have made numerous contributions to Leo throughout the years:

Offray Vladimir Luna Cárdenas: Bogotá, Colombia. Kent Tenney: Ashland Wisconsin, USA. Ville M. Vainio.

EKR lives in Madison, Wisconsin, USA

6.0: Major features#

Leo requires python 3#

Complete transition to python 3 leo-editor/leo-editor#1137

Chinese characters in command names leo-editor/leo-editor#1121

Use super wherever possible leo-editor/leo-editor#1169

Leo uses a dock-based gui by default#

Leo now uses Qt dock widgets by default.

With default settings, Leo looks very much like it always has, but using Qt docks allows you to rearrange the screen to your liking.

Leo remembers the layout of docks when you close Leo, and restores that layout when you restart layout.

Two new settings customize the appearance of docks:

@bool dockable-log-tabs = False
@string central-dock-widget = outline

See the corresponding nodes in leoSettings.leo for full details.

Note: When changing the above settings, it’s best to add the –init-docks setting the next time you run Leo.

Note: Right-clicking the title area of any dock brings up a menu of docks. You can show or hide any dock (except the central widget) using this menu. Don’t be afraid to hide any dock. You can restore it at any later time, including after restarting Leo.

Issues related to Leo docks:

Support docks in Leo’s core leo-editor/leo-editor#1150

Use –no-dock to use Leo’s legacy Qt gui. leo-editor/leo-editor#1171

6.0: Bugs#

This page shows all bugs related to Leo 6.0: leo-editor/leo-editor#issues

Fixes to LeoWapp#

Duplicate headlines leo-editor/leo-editor#1127

LeoWapp key handling in minibuffer leo-editor/leo-editor#1131

insert-child duplicates p.b leo-editor/leo-editor#1142

Ctrl-S doesn’t save leo-editor/leo-editor#1143

LeoWapp focus issues leo-editor/leo-editor#1146

Other bugs#

Problems syntax coloring TeX and LaTeX files leo-editor/leo-editor#1088

git-diff crash leo-editor/leo-editor#1136

Fixed a serious crasher leo-editor/leo-editor#1161

Ctrl-minus selects multiple nodes leo-editor/leo-editor#1168

Recent files menu leo-editor/leo-editor#1188

–maximize doesn’t work leo-editor/leo-editor#1189

open-outline buglet leo-editor/leo-editor#1200

Log pane does not report full commit number leo-editor/leo-editor#1209

Never crash during startup leo-editor/leo-editor#1215

Fix the ctagscompleter plugin leo-editor/leo-editor#1211

Status Bar Won’t Accept Style leo-editor/leo-editor#1218

vim-mode-*-border settings do not work on Qt 5 leo-editor/leo-editor#1221

gui=console. delete line command d is not working leo-editor/leo-editor#1224

gui=console. Backspace, delete keys not working leo-editor/leo-editor#1238

The bookmarks plugin is polluting the .leo file with inappropriate data leo-editor/leo-editor#1247

vr-lock gets overwritten leo-editor/leo-editor#1256

Hard crash in @contextmenu plugin if file not found leo-editor/leo-editor#1257

stickynoteenc traceback leo-editor/leo-editor#1265

Fixed misalignment in LeoQtLog.put

6.0: Features#

This page shows all enhancements related to Leo 6.0: leo-editor/leo-editor#issues

New and improved commands#

Huge speed up of replace-all leo-editor/leo-editor#1152

Added find-long-lines. Uses @bool max-find-long-lines-length = 110

Added find-missing-docstrings. Honors @nopylint. leo-editor/leo-editor#1178

Added import-free-mind-files

Added print-window-state. This command is for Leo’s developers.

The pylint command generates clickable log messages. leo-editor/leo-editor#1173

The pylint command honors @nopylint. leo-editor/leo-editor#1178

Improved python_terminal plugin. Important: this plugin segfaults when Leo starts up on some machines. leo-editor/leo-editor#1212

Code features#

Reform how Leo handles git time stamps leo-editor/leo-editor#1126

Added unit tests for find methods leo-editor/leo-editor#1179

Suppress menu items at load time leo-editor/leo-editor#1199

Added g.es_clickable_link.

Added g.GetRepresentativeObjects

Other features#

Disallow nested @<file> nodes: a failed experiment leo-editor/leo-editor#1134

Support colorizing of Lua long brackets leo-editor/leo-editor#1175

Add dock commands to Window Menu leo-editor/leo-editor#1261

6.0: Settings and command-line arguments#

New command-line arguments:

–init-docks leo-editor/leo-editor#1205

–no-dock Use Leo’s legacy gui instead of the new Qt docks gui.

–trace=aList leo-editor/leo-editor#1145

New settings:

For the find-long-lines command: @bool max-find-long-lines-length = 110

For docks: @bool dockable-log-tabs = False @string central-dock-widget = outline

Leo 5.x release notes#

Leo 5.9 release notes#

Leo 5.9 final, https://leo-editor.github.io/leo-editor/ is now available on [GitHub](leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 5.9

This will be the last version of Leo that supports Python 2.

Major features - LeoWapp: Leo in a browser. - Optional syntax coloring using pygments. - Optional you may use @color & @font directives instead of pygments styles. - Integrated debugger.

Other features - Experimental: nested @clean nodes, useful for LaTex files. - A major refactoring of the code that writes external files. - Better error recovery. - Support for continuous integration with TravisCI. - More than 50 minor bug fixes.

Links

5.9: Bugs fixed#

For the complete list, see: leo-editor/leo-editor#issues

#0804: ~= in style sheets#

leo-editor/leo-editor#804

Changed various style sheets as a workaround for a serious Qt bug.

#0981: & #977: File syncing#

leo-editor/leo-editor#981 leo-editor/leo-editor#977

#0998: Fix recursive import problems#

leo-editor/leo-editor#998

#1002: self.assertEqual in a @test node is not comparing lists properly#

leo-editor/leo-editor#1002

#1007: console gui doesn’t load#

leo-editor/leo-editor#1007

#1018: marks#

leo-editor/leo-editor#1018

fc.setCachedBits scans all nodes for cached data. This simplifies fc.compute_attribute_bits.

#1021: Fixed add-editor#

leo-editor/leo-editor#1021

The culprit was a mistaken fix to #690: leo-editor/leo-editor#690

#1023: Marked and expansion bits no longer affect .leo files#

leo-editor/leo-editor#1023

#1032: importers should not clean blank lines#

leo-editor/leo-editor#1032

#1033: No @path directive added for empty imported files#

leo-editor/leo-editor#1033

#1036: and #1046: strip control chars before reading .leo files#

leo-editor/leo-editor#1036 leo-editor/leo-editor#1046

#1048: & #1037: trailing blank lines#

Leo no longer generates @nonl sentinels, so regularizing trailing ws is much easier.

#1048 @clean: leo-editor/leo-editor#1048 #1037 @file: leo-editor/leo-editor#1037

#1049: crash kills Leo#

leo-editor/leo-editor#1049

#1051: eliminate ui interface refs#

leo-editor/leo-editor#1051

Removed @string qt-ui-file-name.

#1053: Unwanted @shadow message on saves#

leo-editor/leo-editor#1053

This was an ancient bug!

The fix was to call c.setFileTimeStamp(fileName) in x.replaceFileWithString.

#1056: Column numbers in the status line do not work#

leo-editor/leo-editor#1056

#1057: Unwanted loadOnePlugin messages on startup#

leo-editor/leo-editor#1057

#1059: cycle-tab-focus exception#

leo-editor/leo-editor#1059

#1065: refresh-from-disk#

leo-editor/leo-editor#1065

#1098: crash in json scanner#

leo-editor/leo-editor#1098

#1100: changes to external files#

leo-editor/leo-editor#1100

#1111: Read minimal .leo files without crashing#

leo-editor/leo-editor#1111

#1113: @language lisp crash w/ pygments#

leo-editor/leo-editor#1113

#1114: bigdash does not load#

leo-editor/leo-editor#1114

#1116: Crash in viewrendered plugin#

leo-editor/leo-editor#1116

#1118: Crash in console gui#

leo-editor/leo-editor#1118

5.9: Features#

#0525: Nested @clean#

leo-editor/leo-editor#525

This is an experimental feature. It may be removed in future.

See this posting: https://groups.google.com/forum/#!msg/leo-editor/WGQIzBzQ058/QTJRUvl9CwAJ

#0568 & #1102: pygments syntax coloring#

Leo now optionally supports syntax coloring with pygments. See https://pygments.org/docs/

Related Leo issues:

New settings (defaults as shown):

  • @bool use-pygments = False

  • @bool use-pygments-styles = True

  • @string pygments-style-name = default

  • Created a ‘leonine’ style. See: leo-editor/leo-editor-contrib

#0672: Leo uses TravisCI#

leo-editor/leo-editor#672

TravisCI: https://travis-ci.org/

#0915: Leo debugger#

leo-editor/leo-editor#915

Added the xdb command and various db-* commands, corresponding to the pdb commands:

xdb: Start a Leo’s integrated debugger in a separate thread.

At present, you should run Leo from a console window. That will change soon. See below.

Start the debugger from any part of any @<file> tree. Now you are ready to execute all the db-* commands. You can execute these commands from the minibuffer, or, if the xdb_pane.py plugin is enabled, from the the Debug pane. The following correspond to the pdb commands:

db-b: Set a breakpoint at the line shown in Leo. It should be an executable line. db-c: Continue, that is, run until the next breakpoint. db-h: Print the help message (in the console, for now) db-l: List a few lines around present location. db-n: Execute the next line. db-q: End the debugger. db-r: Return from the present function/method. db-s: Step into the next line. db-w: Print the stack.

There are two additional commands:

db-again: Run the previous db-command. db-input: Prompt for any pdb command, then execute it.

The db-input command allows you can enter any pdb command at all. For example: “print c”.

But you don’t have to run these commands from the minibuffer, as discussed next.

Setting breakpoints in the gutter

When @bool use_gutter = True, Leo shows a border in the body pane. By default, the line-numbering.py plugin is enabled, and if so, the gutter shows correct line number in the external file.

After executing the xdb command, you can set a breakpoint on any executable line by clicking in the gutter to the right of the line number. You can also set a breakpoint any time the debugger is stopped.

Using the gutter is optional. You can also set breakpoints with the db-b command or by typing “d line-number” or “d file-name:line-number using the db-input command, or by using the Debug pane (see below)

The Debug pane

The xdb_pane.py plugin creates the Debug pane in the Log pane. The pane contains buttons corresponding to all the commands listed above. In addition, there is an input area in which you can enter pdb commands. This is a bit easier to use than the db-input command.

Soon, all xdb/pdb output will be sent to an output area in the debug pane. Once that happens, you will be able to run the debugger without running Leo from a console window.

#0926: Organize @outline-data tree-abbreviations#

leo-editor/leo-editor#926

#1005: LeoWapp: Leo in a browser#

Leo 6.8.8 removes support for LeoWapp and –gui=browser. Use LeoJS or LeoInteg instead.

leo-editor/leo-editor#1005

LeoWapp (Leo as a web browser), implemented using flexx: https://flexx.readthedocs.io/en/stable/

Start Leo using the –gui=browser option. Like this:

leo --gui=browser
leo --gui=browser-firefox-browser​

The code is in leo/plugins/leoflexx.py, but this is not a plugin.

Prerequisites#

Install flexx: https://flexx.readthedocs.io/en/stable/start.html

What you should see#

You should see the flexx (Tornado) server start up in the console. Something that looks like Leo should then appear in the browser. Everything you see is real, and most of it is “live”.

#1031, #1050 and #1003: Better error recovery#

When saving a file, Leo now raises a dialog warning if quitting might lose data.

There are three related issues: leo-editor/leo-editor#1031 leo-editor/leo-editor#1050 leo-editor/leo-editor#1003

#1047: Tree Window Resizes on Paste Node#

leo-editor/leo-editor#1047

The following call FastRead().readFileFromClipboard:

  • fc.getLeoOutlineFromClipBoard.

  • fc.getLeoOutlineFromClipBoardRetainingClones.

  • fc.getPos/VnodeFromClipboard.

#1081: @asis#

leo-editor/leo-editor#1081

Added warning when @asis or @nosent files change outside of Leo.

#1085: The py3 branch#

leo-editor/leo-editor#1085

This branch removes all Python 2 compatibility code. It will be the basis of Leo 6.0.

#1090: –script path#

leo-editor/leo-editor#1090

command line–script relative path is relative to leo/core instead of file-system

#1107: Automatic sessions#

leo-editor/leo-editor#1107

Removed –session-save and –session-restore command-line arguments.

Leo saves and restores loaded files only if file names are not given on the command line.

Startup

  • If the command line contains file names, Leo will load only those files. In that case, Leo does not save session data on exit.

  • Otherwise, Leo loads files from the previously saved session data in session.leo. If session.leo does not exist, Leo will load the default workbook.leo

Shutdown - Leo saves session data to leo.session only if g.app.loaded_session is True.

This will work as usual for newbies: Leo will open the default Workbook.

Added g.get_files_in_directory#
Added promote-headline command#

Copies the headlines of all descendants to the parent’s body text.

Retired the head-to-prev node and tail-to-next-node commands#

5.9: Code#

#1040: Simplify atFile.write code#

leo-editor/leo-editor#1040

This was a major refactoring of Leo’s code.

See this post: https://groups.google.com/forum/#!topic/leo-editor/JfAUMMOSdvQ

Added leo/core/leoFastRedraw.py#

This module contains the fast-redraw code that used to be in leoflexx.py.It deserves to be in Leo’s core because it does not in any way depend on which gui is in effect.

Created py3 branch, for Leo 6.0#

leo-editor/leo-editor#1085 This branch assumes Python 3. It will be the basis of Leo 6.0.

  • Removed isPython3 switches.

  • Removed g.u.

  • Removed g.ue.

The following methods will not be removed: - Replace isBytes, isCallable, isInt, isList, isString

5.9: Settings & command-line arguments#

New settings (defaults as shown):

  • @bool use_gutter = False

  • @bool use-pygments = False

  • @bool use-pygments-styles = True

  • @bool use_xdb_pane_output_= True

  • @string pygments-style-name = default

  • Created a ‘leonine’ style. See: leo-editor/leo-editor-contrib

Changed/improved settings:

  • Improved –trace-coloring traces

  • #993: use -, not underscore, for settings names.

Removed settings:

  • Removed –session-save and –session-restore command-line arguments.

  • Removed @string trailing-body-newlines.

  • Remove @string qt-ui-file-name. leo-editor/leo-editor#993

Leo 5.8 release notes#

Leo 5.8 final, https://leo-editor.github.io/leo-editor/ is now available on [GitHub](leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 5.8

  • Much faster file-read code.

  • Leo no longer caches file contents. Removed –no-cache!

  • Leo using ElementTree instead of sax to read .leo files.

  • Refactored and improved Leo’s key-handling code.

  • Improved Leo’s outline drawing code.

  • The usual minor bug fixes.

Links

Bugs#

For the full list, see: leo-editor/leo-editor#issues

Fixed in b1#

leo-editor/leo-editor#841

leo-editor/leo-editor#893

leo-editor/leo-editor#917

leo-editor/leo-editor#922

leo-editor/leo-editor#933

Changes:

  • LM.openEmptyWorkBook now saves/restores clipboard.

  • Deleted qt_gui.setClipboardSelection. It is now a synonym for replaceClipboardWith.

  • qtew.setSelectionRange now sets the selection only if there is selected text.

leo-editor/leo-editor#936

The change was to load_session.

leo-editor/leo-editor#938

The fix was in abbrev.init_tree_abbrev_helper.

leo-editor/leo-editor#940

added update_nodes method.

leo-editor/leo-editor#943

The fix was to getVnodeFromClipboard.

The fix was to set @<file> nodes dirty by brute force in find.changeAllCommand.

leo-editor/leo-editor#947

See also:

leo-editor/leo-editor#722 leo-editor/leo-editor#880

leo-editor/leo-editor#956

async is a new keyword.

leo-editor/leo-editor#967

See c.backup_helper.

Traceback (most recent call last):
File “c:leo.repoleo-editorleopluginsqt_frame.py”, line 3152, in linkClicked

url = link.url()

AttributeError: ‘QUrl’ object has no attribute ‘url’

It now works in folders besides the leo-editor folder.

Fixed in b2#

leo-editor/leo-editor#969 The fix: call c.treeWantsFocusNow in tt.selectTab.

leo-editor/leo-editor#970

Fixed #970 with several small, subtle, tweaks:

fast.readWithElementTree simply returns False if the .leo file is invalid.

This necessitated further tweaks:

  • LM.readOpenedLeoFile never closes Leo by setting finish_quit kwarg to True.

  • LM.getPreviousSettings uses global settings if the file is invalid.

  • LM.computeThemeFilePath uses global settings if the file is invalid.

  • fast.getGlobalData is more careful to handle exceptions.

Code#

#296: private plugin directories#

leo-editor/leo-editor#296

The legacy code (plugins.regularizeName) tries to import leo.plugins.x if x.py is given in the @enabled-plugins node.

The new code just makes regularizeName more flexible.

#924: Improved performance of at.readAll#

leo-editor/leo-editor#924

CProfile: .leo FAST = False#
        12766782 function calls (12734775 primitive calls) in 8.997 seconds

  Ordered by: internal time

  ncalls  tottime  percall  cumtime  percall filename:lineno(function)

       1    1.571    1.571    1.857    1.857 {built-in method exec_}
     584    1.029    0.002    1.029    0.002 {built-in method __new__ of type object at 0x00000000664AB3F0}
    6787    0.217    0.000    0.217    0.000 {built-in method nt.stat}

  145181    0.205    0.000    0.421    0.000 spellCommands.py:243(add_expanded_line)

     165    0.181    0.001    0.353    0.002 leoAtFile.py:5163(scan_lines)

  630654    0.162    0.000    0.222    0.000 leoGlobals.py:5551(isUnicode)
  212111    0.140    0.000    0.247    0.000 leoGlobals.py:4530(match_word) #
   35851    0.130    0.000    0.261    0.000 ntpath.py:471(normpath)
  608210    0.124    0.000    0.124    0.000 {method 'find' of 'str' objects}
    1829    0.119    0.000    0.229    0.001 sre_parse.py:470(_parse)
  204516    0.106    0.000    0.106    0.000 leoNodes.py:198(__init__) # Position!!!

  105948    0.097    0.000    0.168    0.000 leoFileCommands.py:184(characters) # sax !!!
  204348    0.096    0.000    0.202    0.000 leoNodes.py:1338(copy) # !!! Creates new position.
  360621    0.096    0.000    0.228    0.000 leoGlobals.py:5628(toUnicode) #
   11498    0.095    0.000    0.095    0.000 leoGlobals.py:2961(<listcomp>) # g.compute_directives_re
  679634    0.095    0.000    0.095    0.000 {method 'add' of 'set' objects}
  891774    0.093    0.000    0.094    0.000 {built-in method builtins.isinstance}
  106763    0.093    0.000    0.316    0.000 leoNodes.py:1203(moveToThreadNext)
   10434    0.093    0.000    0.405    0.000 leoGlobals.py:4494(is_special)
 1251070    0.092    0.000    0.093    0.000 {built-in method builtins.len}
   11498    0.092    0.000    0.306    0.000 leoGlobals.py:2911(get_directives_dict)
  357802    0.085    0.000    0.085    0.000 {method 'replace' of 'str' objects}
    5428    0.083    0.000    0.083    0.000 {built-in method winreg.OpenKey}
  132725    0.083    0.000    0.211    0.000 leoNodes.py:2228(headString)
   98090    0.078    0.000    0.106    0.000 leoNodes.py:1150(moveToNext)
   72669    0.078    0.000    0.371    0.000 leoCommands.py:812(all_unique_positions)
   58372    0.074    0.000    0.102    0.000 ntpath.py:121(splitdrive)
  122175    0.073    0.000    0.112    0.000 leoNodes.py:780(hasNext)
   12535    0.072    0.000    0.088    0.000 leoNodes.py:1931(__init__)
  158376    0.071    0.000    0.118    0.000 leoGlobals.py:4585(skip_line)
     692    0.067    0.000    0.067    0.000 {built-in method marshal.loads}
       2    0.061    0.031    0.106    0.053 spellCommands.py:132(add_words_from_dict)
  393812    0.061    0.000    0.061    0.000 {method 'startswith' of 'str' objects}
    1070    0.058    0.000    0.058    0.000 {method 'splitlines' of 'str' objects}
  239689    0.055    0.000    0.055    0.000 leoNodes.py:1025(_parentVnode)
    2718    0.050    0.000    0.285    0.000 {built-in method builtins.__build_class__}


  175148    0.048    0.000    0.049    0.000 {built-in method builtins.hasattr}
   58267    0.047    0.000    0.113    0.000 leoGlobals.py:6958(toUnicodeFileEncoding)
      46    0.046    0.001    0.373    0.008 {method 'Parse' of 'pyexpat.xmlparser' objects}
  459482    0.044    0.000    0.044    0.000 {method 'lower' of 'str' objects}
  185835    0.044    0.000    0.060    0.000 leoGlobals.py:5579(isWordChar)
       1    0.042    0.042    0.665    0.665 mod_scripting.py:521(createAllButtons)
  506941    0.041    0.000    0.041    0.000 {method 'append' of 'list' objects}
     754    0.041    0.000    0.041    0.000 {built-in method io.open}
  119664    0.039    0.000    0.229    0.000 leoNodes.py:654(headString)
  268078    0.039    0.000    0.042    0.000 {method 'get' of 'dict' objects}
     895    0.038    0.000    0.217    0.000 leoNodes.py:740(get_UNL)
  312129    0.038    0.000    0.038    0.000 {method 'strip' of 'str' objects}
       2    0.037    0.019    0.469    0.234 spellCommands.py:231(read_words)
  122208    0.036    0.000    0.036    0.000 sre_parse.py:232(__next)
     695    0.036    0.000    0.061    0.000 <frozen importlib._bootstrap_external>:830(get_data)
  119664    0.034    0.000    0.263    0.000 leoNodes.py:1601(__get_h)
   40561    0.034    0.000    0.102    0.000 leoNodes.py:517(self_and_parents)
    9827    0.033    0.000    0.105    0.000 todo.py:525(loadIcons)
   93422    0.031    0.000    0.035    0.000 {method 'join' of 'str' objects}
   11993    0.030    0.000    0.053    0.000 leoGlobals.py:6665(os_path_expandExpression)
  118705    0.029    0.000    0.064    0.000 sre_parse.py:253(get)
       8    0.027    0.003    0.027    0.003 {built-in method setStyleSheet}
   55751    0.026    0.000    0.036    0.000 leoNodes.py:1184(moveToParent)
    8005    0.026    0.000    0.287    0.000 leoGlobals.py:6784(os_path_join)
    7894    0.025    0.000    0.497    0.000 leoGlobals.py:6744(os_path_finalize_join)
     932    0.025    0.000    0.028    0.000 sre_compile.py:250(_optimize_charset)
     695    0.025    0.000    0.025    0.000 {method 'read' of '_io.FileIO' objects}
  206990    0.025    0.000    0.025    0.000 leoNodes.py:282(__bool__)
    3386    0.025    0.000    0.382    0.000 leoGlobals.py:2965(get_directives_dict_list)
   50243    0.023    0.000    0.023    0.000 {method 'match' of '_sre.SRE_Pattern' objects}
    4659    0.023    0.000    0.025    0.000 leoFileCommands.py:1187(handleVnodeSaxAttributes)
     541    0.022    0.000    0.022    0.000 {method 'read' of '_io.BufferedReader' objects}
       6    0.022    0.004    0.144    0.024 leoCommands.py:1317(checkGnxs)
   20098    0.022    0.000    0.038    0.000 editCommands.py:834(getIconList)
   10469    0.022    0.000    0.054    0.000 ntpath.py:74(join)
   750/1    0.021    0.000    9.016    9.016 {built-in method builtins.exec}
   14584    0.021    0.000    0.339    0.000 re.py:286(_compile)
  250111    0.020    0.000    0.020    0.000 {method 'isalnum' of 'str' objects}
   13190    0.020    0.000    0.166    0.000 leoGlobals.py:6717(os_path_expanduser)
   13769    0.019    0.000    0.080    0.000 leoNodes.py:1282(safeMoveToThreadNext)
   17085    0.019    0.000    0.032    0.000 nodetags.py:185(get_tags)
       1    0.018    0.018    0.018    0.018 {msleep}
   64193    0.018    0.000    0.025    0.000 leoGlobals.py:5543(isString)
   24206    0.018    0.000    0.021    0.000 leoNodes.py:1117(moveToFirstChild)
   11498    0.018    0.000    0.123    0.000 leoGlobals.py:2954(compute_directives_re)
    5428    0.017    0.000    0.017    0.000 {built-in method winreg.EnumKey}
   19656    0.017    0.000    0.100    0.000 leoCommands.py:749(all_positions)
      65    0.016    0.000    0.016    0.000 {method 'execute' of 'sqlite3.Connection' objects}
   13025    0.016    0.000    0.027    0.000 leoFileCommands.py:143(<listcomp>)
   19424    0.016    0.000    0.022    0.000 leoNodes.py:1104(moveToBack)
    4659    0.015    0.000    0.119    0.000 leoFileCommands.py:1155(createSaxVnode)
   17/15    0.015    0.001    0.024    0.002 {built-in method _imp.create_dynamic}
       4    0.015    0.004    0.015    0.004 {built-in method show}
    3362    0.015    0.000    0.440    0.000 leoCommands.py:1936(scanAtPathDirectives)
    6737    0.015    0.000    0.031    0.000 leoGlobals.py:4572(skip_id)
     524    0.015    0.000    0.015    0.000 {built-in method nt._isdir}
   26695    0.015    0.000    0.024    0.000 leoGlobals.py:4516(match)
  134173    0.014    0.000    0.014    0.000 {built-in method nt.fspath}
   13593    0.014    0.000    0.032    0.000 leoFileCommands.py:198(endElement)
   13593    0.014    0.000    0.109    0.000 leoFileCommands.py:258(startElement)
3186/403    0.014    0.000    0.057    0.000 sre_compile.py:64(_compile)
       1    0.014    0.014    0.132    0.132 mimetypes.py:230(read_windows_registry)
   11130    0.014    0.000    0.068    0.000 leoNodes.py:1999(findAtFileName)
     169    0.014    0.000    0.015    0.000 leoAtFile.py:225(initReadIvars)
   13775    0.013    0.000    0.107    0.000 leoCommands.py:832(safe_all_positions)
    9834    0.013    0.000    0.013    0.000 {built-in method today}
      27    0.013    0.000    0.013    0.000 {built-in method repaint}
   46946    0.013    0.000    0.023    0.000 leoNodes.py:2599(__get_u)
    4755    0.013    0.000    0.026    0.000 ntpath.py:199(split)
     834    0.013    0.000    0.013    0.000 {built-in method winreg.QueryValueEx}
   36552    0.013    0.000    0.013    0.000 {method 'split' of 'str' objects}
       2    0.013    0.006    0.018    0.009 QNCalendarWidget.py:35(build)
   67396    0.012    0.000    0.012    0.000 {method 'pop' of 'list' objects}
       8    0.012    0.001    0.012    0.002 {built-in method addTab}
    1347    0.012    0.000    0.935    0.001 leoGlobals.py:3448(fullPath)
  105011    0.011    0.000    0.012    0.000 sre_parse.py:248(match)
   13593    0.011    0.000    0.123    0.000 expatreader.py:332(start_element)
   26391    0.011    0.000    0.011    0.000 {method 'finditer' of '_sre.SRE_Pattern' objects}
    1307    0.011    0.000    0.139    0.000 <frozen importlib._bootstrap_external>:1233(find_spec)
   17084    0.011    0.000    0.061    0.000 leoChapters.py:245(parseHeadline)
    8200    0.011    0.000    0.015    0.000 leoGlobals.py:4654(skip_ws)
   39321    0.010    0.000    0.015    0.000 todo.py:607(getat)
   13196    0.010    0.000    0.017    0.000 ntpath.py:308(expanduser)
    7582    0.010    0.000    0.062    0.000 leoGlobals.py:6748(<listcomp>)
   10437    0.010    0.000    0.424    0.000 leoNodes.py:2116(isAtIgnoreNode)
   19424    0.010    0.000    0.049    0.000 leoNodes.py:697(getBack)
    4659    0.009    0.000    0.028    0.000 leoNodes.py:112(scanGnx)
   13025    0.009    0.000    0.047    0.000 leoFileCommands.py:138(attrsToList)
   13025    0.009    0.000    0.011    0.000 xmlreader.py:308(getNames)
   29515    0.009    0.000    0.156    0.000 leoCommands.py:737(all_unique_nodes)
       2    0.009    0.004    0.009    0.004 {built-in method setCalendarWidget}
     727    0.009    0.000    0.009    0.000 {method 'connect' of 'PyQt5.QtCore.pyqtBoundSignal' objects}
       1    0.009    0.009    0.009    0.009 backend.py:71(Backend)
       2    0.009    0.004    0.162    0.081 leoChapters.py:318(setAllChapterNames)
    8780    0.009    0.000    0.082    0.000 ntpath.py:538(abspath)
    8780    0.008    0.000    0.008    0.000 {built-in method nt._getfullpathname}
    7582    0.008    0.000    0.484    0.000 leoCommands.py:1884(os_path_finalize_join)
   17318    0.008    0.000    0.008    0.000 {method 'search' of '_sre.SRE_Pattern' objects}
    4043    0.008    0.000    0.012    0.000 leoMenu.py:247(<listcomp>)
     190    0.008    0.000    0.008    0.000 {built-in method _hashlib.openssl_md5}
     172    0.008    0.000    0.008    0.000 {built-in method nt.access}
 4669/10    0.008    0.000    0.128    0.013 leoFileCommands.py:1138(createSaxChildren)
  9828/1    0.008    0.000    0.189    0.189 todo.py:497(new)
       1    0.008    0.008    0.063    0.063 backlink.py:412(loadLinksInt)
     677    0.008    0.000    0.008    0.000 {method 'decode' of 'bytes' objects}
    4706    0.007    0.000    0.041    0.000 leoFileCommands.py:389(startVnode)
   14989    0.007    0.000    0.012    0.000 {built-in method builtins.getattr}
  104772    0.007    0.000    0.007    0.000 {built-in method builtins.ord}
   12535    0.007    0.000    0.015    0.000 leoNodes.py:102(new_vnode_helper)
   34954    0.007    0.000    0.007    0.000 {method 'lstrip' of 'str' objects}
   96309    0.007    0.000    0.007    0.000 {method 'isspace' of 'str' objects}
    5893    0.007    0.000    0.018    0.000 enum.py:801(__and__)
    5628    0.007    0.000    0.013    0.000 leoGlobals.py:1881(add)
   16355    0.007    0.000    0.013    0.000 leoNodes.py:2173(bodyString)
       1    0.007    0.007    0.173    0.173 todo.py:519(loadAllIcons)
   42287    0.006    0.000    0.006    0.000 {method 'group' of '_sre.SRE_Match' objects}
4489/2090 0.006 0.000 0.008 0.000 sre_parse.py:173(getwidth)

4158 0.006 0.000 0.034 0.000 leoFileCommands.py:361(tnodeAttributes) 4706 0.006 0.000 0.029 0.000 leoFileCommands.py:406(vnodeAttributes) 5632 0.006 0.000 0.067 0.000 leoGlobals.py:6826(os_path_normpath)

11224 0.006 0.000 0.013 0.000 leoGlobals.py:1931(get)

8005 0.006 0.000 0.167 0.000 leoGlobals.py:6801(<listcomp>) 2294 0.006 0.000 0.030 0.000 leoAtFile.py:3705(putCodeLine) 4252 0.006 0.000 0.063 0.000 leoKeys.py:2956(registerCommandShortcut) 5220 0.006 0.000 0.015 0.000 leoAtFile.py:4321(os)

13832 0.006 0.000 0.009 0.000 leoGlobals.py:4647(skip_to_char)

19 0.006 0.000 0.073 0.004 leoCommands.py:1181(setChanged)

6405 0.006 0.000 0.027 0.000 leoConfig.py:1728(getShortcut)

24357 0.006 0.000 0.006 0.000 leoNodes.py:2621(__get_gnx) 13593 0.006 0.000 0.037 0.000 expatreader.py:335(end_element)

98 0.006 0.000 0.009 0.000 {built-in method builtins.sorted}

3137/2629 0.006 0.000 0.007 0.000 proxy_metaclass.py:77(__getattribute__)

12884 0.006 0.000 0.007 0.000 enum.py:515(__new__)

794/141 0.006 0.000 2.083 0.015 <frozen importlib._bootstrap>:966(_find_and_load)
1928 0.006 0.000 0.370 0.000 leoConfig.py:1898(visitNode)

1 0.006 0.006 1.436 1.436 leoAtFile.py:703(readAll)

4605 0.006 0.000 0.051 0.000 leoGlobals.py:6641(os_path_basename)

15928 0.006 0.000 0.018 0.000 leoNodes.py:651(bodyString) 12535 0.006 0.000 0.007 0.000 leoNodes.py:45(check_gnx) 14212 0.006 0.000 0.336 0.000 re.py:231(compile)

167 0.006 0.000 0.049 0.000 leoGlobals.py:3683(readFileIntoString)

1 0.006 0.006 0.040 0.040 qt_gui.py:46(__init__) 7 0.005 0.001 0.058 0.008 leoKeys.py:2264(makeBindingsFromCommandsDict)

749 0.005 0.000 0.162 0.000 <frozen importlib._bootstrap>:870(_find_spec) 693 0.005 0.000 0.007 0.000 <frozen importlib._bootstrap_external>:430(_validate_bytecode_header)

13208 0.005 0.000 0.009 0.000 leoGlobals.py:207(__init__) 15928 0.005 0.000 0.023 0.000 leoNodes.py:1572(__get_b)

80 0.005 0.000 0.008 0.000 qt_frame.py:4354(__init__)

8005 0.005 0.000 0.031 0.000 leoGlobals.py:6792(<listcomp>) 6570 0.005 0.000 0.013 0.000 <frozen importlib._bootstrap_external>:57(_path_join)

693 0.005 0.000 0.178 0.000 <frozen importlib._bootstrap_external>:743(get_code)

18155 0.005 0.000 0.005 0.000 leoGlobals.py:1866(_checkKeyType)

4055 0.005 0.000 0.057 0.000 leoNodes.py:2014(anyAtFileNodeName) 4252 0.005 0.000 0.069 0.000 leoKeys.py:2913(registerCommand)

13517 0.005 0.000 0.007 0.000 sre_parse.py:163(__getitem__)

cProfile: .leo FAST = True#

11685846 function calls (11653798 primitive calls) in 8.145 seconds

ncalls tottime percall cumtime percall filename:lineno(function)

# Slow but not terrible.

145181 0.208 0.000 0.422 0.000 spellCommands.py:243(add_expanded_line)

# Benchmark: scan_lines is fast. # Cumulative time is a bit surprising. It calls regex methods and the Vnode ctor.

165 0.162 0.001 0.333 0.002 leoAtFile.py:5163(scan_lines)

# Expected…
12544 0.067 0.000 0.082 0.000 leoNodes.py:1931(vnode.__init__) # Expected.

1829 0.119 0.000 0.230 0.001 sre_parse.py:470(_parse) # Expected.

# Marks big surprises. # These take almost as long as fast_at.scan_line.

# Benchmarks: lots of calls. Fast, but these do add almost 1.0 seconds to the total.

679649 0.093 0.000 0.093 0.000 {method ‘add’ of ‘set’ objects}

1236269 0.089 0.000 0.089 0.000 {built-in method builtins.len}

691 0.088 0.000 0.088 0.000 {built-in method marshal.loads}

5428 0.087 0.000 0.087 0.000 {built-in method winreg.OpenKey}

776730 0.082 0.000 0.082 0.000 {built-in method builtins.isinstance}

57936 0.072 0.000 0.100 0.000 ntpath.py:121(splitdrive)

248025 0.067 0.000 0.067 0.000 {method ‘replace’ of ‘str’ objects}

2 0.061 0.030 0.105 0.053 spellCommands.py:132(add_words_from_dict)

393127 0.061 0.000 0.061 0.000 {method ‘startswith’ of ‘str’ objects}

1070 0.058 0.000 0.058 0.000 {method ‘splitlines’ of ‘str’ objects}

166257 0.046 0.000 0.047 0.000 {built-in method builtins.hasattr}
2718 0.042 0.000 0.279 0.000 {built-in method builtins.__build_class__}

1 0.041 0.041 0.655 0.655 mod_scripting.py:521(createAllButtons) #

40356 0.033 0.000 0.101 0.000 leoNodes.py:517(p.self_and_parents)

# Benchmarks: the actual read code is very fast.
748 0.040 0.000 0.041 0.000 {built-in method io.open}

6 0.031 0.005 0.031 0.005 {method ‘feed’ of ‘xml.etree.ElementTree.XMLParser’ objects}

696 0.028 0.000 0.028 0.000 {method ‘read’ of ‘_io.FileIO’ objects} #

# g functions. Why are they called so often? These add about 1.0 seconds.

521491 0.138 0.000 0.188 0.000 leoGlobals.py:5551(g.isUnicode) # 212321 0.135 0.000 0.243 0.000 leoGlobals.py:4530(g.match_word) # 355472 0.095 0.000 0.229 0.000 leoGlobals.py:5628(g.toUnicode) #

11373 0.095 0.000 0.095 0.000 leoGlobals.py:2961(<listcomp>) # g.compute_directives_re 10435 0.093 0.000 0.397 0.000 leoGlobals.py:4494(g.is_special) # 11373 0.091 0.000 0.302 0.000 leoGlobals.py:2911(g.get_directives_dict) #

158556 0.069 0.000 0.115 0.000 leoGlobals.py:4585(g.skip_line) #

57881 0.048 0.000 0.115 0.000 leoGlobals.py:6958(g.toUnicodeFileEncoding) #

186038 0.044 0.000 0.061 0.000 leoGlobals.py:5579(g.isWordChar) #

# Position and vnode methods. Why are they called so often?

204403 0.104 0.000 0.104 0.000 leoNodes.py:198(p.__init__) # Very bad 204235 0.094 0.000 0.198 0.000 leoNodes.py:1338(p.copy) # Very bad 106781 0.091 0.000 0.311 0.000 leoNodes.py:1203(p.moveToThreadNext) # 132602 0.082 0.000 0.214 0.000 leoNodes.py:2228(v.headString) #

72681 0.079 0.000 0.367 0.000 leoCommands.py:812(c.all_unique_positions) # 98137 0.078 0.000 0.105 0.000 leoNodes.py:1150(p.moveToNext) #

122195 0.073 0.000 0.111 0.000 leoNodes.py:780(p.hasNext) # 239756 0.053 0.000 0.053 0.000 leoNodes.py:1025(v._parentVnode) # 119593 0.039 0.000 0.231 0.000 leoNodes.py:654(p.headString) # 119593 0.034 0.000 0.265 0.000 leoNodes.py:1601(p.__get_h) #

55575 0.026 0.000 0.035 0.000 leoNodes.py:1184(p.moveToParent) #

originals#
      11685846 function calls (11653798 primitive calls) in 8.145 seconds
ncalls  tottime  percall  cumtime  percall filename:lineno(function)

# Probably from cProfile, not a big deal…:

   1    1.129    1.129    1.305    1.305 {built-in method exec_}
 584    1.025    0.002    1.025    0.002 {built-in method __new__ of type object at 0x00000000664AB3F0}
6775    0.219    0.000    0.219    0.000 {built-in method nt.stat}

# Surprise, but not horrible:

145181    0.208    0.000    0.422    0.000 spellCommands.py:243(add_expanded_line) #

# The first benchmark: 165 files scanned in about 0.16 seconds. Very good:

165    0.162    0.001    0.333    0.002 leoAtFile.py:5163(fast_at.scan_lines)

# marks routines that have way too many calls, and add way too much time

# Each of these items adds almost as much time as scan_lines!:

521491    0.138    0.000    0.188    0.000 leoGlobals.py:5551(g.isUnicode) #
212321    0.135    0.000    0.243    0.000 leoGlobals.py:4530(g.match_word) #
 35564    0.131    0.000    0.260    0.000 ntpath.py:471(normpath)
  1829    0.119    0.000    0.230    0.001 sre_parse.py:470(_parse) # Expected, imo.
585766    0.119    0.000    0.119    0.000 {method 'find' of 'str' objects}
204403    0.104    0.000    0.104    0.000 leoNodes.py:198(__init__)
355472    0.095    0.000    0.229    0.000 leoGlobals.py:5628(g.toUnicode) #
 11373    0.095    0.000    0.095    0.000 leoGlobals.py:2961(g.compute_directives_re()) #
204235    0.094    0.000    0.198    0.000 leoNodes.py:1338(p.copy) # Very bad, very surprising.
679649    0.093    0.000    0.093    0.000 {method 'add' of 'set' objects}
 10435    0.093    0.000    0.397    0.000 leoGlobals.py:4494(g.is_special) #
 11373    0.091    0.000    0.302    0.000 leoGlobals.py:2911(g.get_directives_dict) #
106781    0.091    0.000    0.311    0.000 leoNodes.py:1203(p.moveToThreadNext) # Slow!

# Benchmark: lots of calls, not too much time:

1236269    0.089    0.000    0.089    0.000 {built-in method builtins.len}
 ...
 132602    0.082    0.000    0.214    0.000 leoNodes.py:2228(v.headString) #

  72681    0.079    0.000    0.367    0.000 leoCommands.py:812(c.all_unique_positions) #
  98137    0.078    0.000    0.105    0.000 leoNodes.py:1150(p.moveToNext) #
 122195    0.073    0.000    0.111    0.000 leoNodes.py:780(p.hasNext) #
  57936    0.072    0.000    0.100    0.000 ntpath.py:121(splitdrive)
 158556    0.069    0.000    0.115    0.000 leoGlobals.py:4585(g.skip_line) #
 248025    0.067    0.000    0.067    0.000 {method 'replace' of 'str' objects}

# Another benchmark: about the expected number of calls, and a reasonable time:

 12544    0.067    0.000    0.082    0.000 leoNodes.py:1931(v.__init__)

     2    0.061    0.030    0.105    0.053 spellCommands.py:132(add_words_from_dict)
393127    0.061    0.000    0.061    0.000 {method 'startswith' of 'str' objects}
  1070    0.058    0.000    0.058    0.000 {method 'splitlines' of 'str' objects}
239756    0.053    0.000    0.053    0.000 leoNodes.py:1025(p._parentVnode) #
 57881    0.048    0.000    0.115    0.000 leoGlobals.py:6958(g.toUnicodeFileEncoding) # ???
166257    0.046    0.000    0.047    0.000 {built-in method builtins.hasattr}
186038    0.044    0.000    0.061    0.000 leoGlobals.py:5579(g.isWordChar) #
...

# The last benchmarks: Python’s readers are very fast:

  6    0.031    0.005    0.031    0.005 {method 'feed' of 'xml.etree.ElementTree.XMLParser' objects}
696    0.028    0.000    0.028    0.000 {method 'read' of '_io.FileIO' objects}
cProfile, with FAST = True (much improved)#

9245840 function calls (9213587 primitive calls) in 7.827 seconds

Ordered by: internal time

ncalls tottime percall cumtime percall filename:lineno(function)

# cProfile stuff.

1 1.727 1.727 2.014 2.014 {built-in method exec_}

584 1.022 0.002 1.022 0.002 {built-in method __new__ of type object at 0x00000000664AB3F0}

6785 0.212 0.000 0.212 0.000 {built-in method nt.stat}

# Costly, but no obvious improvements.

145181 0.184 0.000 0.355 0.000 spellCommands.py:243(add_expanded_line)

# Benchmark: good speed.

165 0.165 0.001 0.337 0.002 leoAtFile.py:5163(scan_lines)

37909 0.139 0.000 0.275 0.000 ntpath.py:471(normpath)

1837/450 0.118 0.000 0.228 0.001 sre_parse.py:470(_parse)

12016 0.099 0.000 0.099 0.000 leoGlobals.py:2988(<listcomp>) # g.compute_directives_re

671831 0.093 0.000 0.093 0.000 {method ‘add’ of ‘set’ objects}
12016 0.092 0.000 0.313 0.000 leoGlobals.py:2938(get_directives_dict) # improved.
5428 0.086 0.000 0.086 0.000 {built-in method winreg.OpenKey}

692 0.081 0.000 0.081 0.000 {built-in method marshal.loads}

97755 0.078 0.000 0.272 0.000 leoNodes.py:1202(moveToThreadNext) # reasonable. 61012 0.076 0.000 0.105 0.000 ntpath.py:121(splitdrive)

706639/706638 0.073 0.000 0.074 0.000 {built-in method builtins.isinstance}
316660 0.071 0.000 0.111 0.000 leoGlobals.py:5652(toUnicode) # improved

12677 0.071 0.000 0.087 0.000 leoNodes.py:1930(__init__) 91198 0.070 0.000 0.094 0.000 leoNodes.py:1149(moveToNext) 73099 0.067 0.000 0.313 0.000 leoCommands.py:812(all_unique_positions) #

113534 0.066 0.000 0.099 0.000 leoNodes.py:779(hasNext) # 258990 0.065 0.000 0.065 0.000 {method ‘replace’ of ‘str’ objects}

2 0.062 0.031 0.107 0.053 spellCommands.py:132(add_words_from_dict) #

398502 0.061 0.000 0.061 0.000 {method ‘startswith’ of ‘str’ objects}

1070 0.057 0.000 0.057 0.000 {method ‘splitlines’ of ‘str’ objects}

89903 0.056 0.000 0.114 0.000 leoNodes.py:2226(headString)

723318 0.053 0.000 0.053 0.000 {built-in method builtins.len}

61081 0.050 0.000 0.099 0.000 leoGlobals.py:7007(toUnicodeFileEncoding)

224156 0.048 0.000 0.048 0.000 leoNodes.py:1024(_parentVnode) 234204 0.045 0.000 0.045 0.000 {method ‘find’ of ‘str’ objects} 167094 0.043 0.000 0.044 0.000 {built-in method builtins.hasattr}

74688 0.042 0.000 0.042 0.000 leoNodes.py:198(p.__init__) # Improved

385978 0.041 0.000 0.041 0.000 {method ‘append’ of ‘list’ objects}

2714/2693 0.040 0.000 0.275 0.000 {built-in method builtins.__build_class__}
74513 0.039 0.000 0.081 0.000 leoNodes.py:1337(p.copy) # Improved

748 0.038 0.000 0.038 0.000 {built-in method io.open} # Benchmark

122261 0.037 0.000 0.037 0.000 sre_parse.py:232(__next) 298205 0.036 0.000 0.036 0.000 {method ‘strip’ of ‘str’ objects}

695 0.036 0.000 0.061 0.000 <frozen importlib._bootstrap_external>:830(get_data)

9902 0.034 0.000 0.106 0.000 todo.py:525(loadIcons)

748/1 0.034 0.000 7.845 7.845 {built-in method builtins.exec}

246489 0.033 0.000 0.036 0.000 {method ‘get’ of ‘dict’ objects} 329433 0.033 0.000 0.033 0.000 {method ‘lower’ of ‘str’ objects}

2 0.032 0.016 0.397 0.199 spellCommands.py:231(read_words)

12629 0.031 0.000 0.050 0.000 leoGlobals.py:6714(os_path_expandExpression)

6 0.031 0.005 0.031 0.005 {method ‘feed’ of ‘xml.etree.ElementTree.XMLParser’ objects}

47 0.030 0.001 0.030 0.001 {method ‘execute’ of ‘sqlite3.Connection’ objects}

124514 0.030 0.000 0.042 0.000 leoGlobals.py:5585(isUnicode) # Improved 118750 0.029 0.000 0.065 0.000 sre_parse.py:253(get)

895 0.029 0.000 0.140 0.000 leoNodes.py:738(get_UNL)

87970 0.029 0.000 0.032 0.000 {method ‘join’ of ‘str’ objects}

8 0.027 0.003 0.027 0.003 {built-in method setStyleSheet}

8417 0.027 0.000 0.288 0.000 leoGlobals.py:6833(os_path_join)

76292 0.026 0.000 0.122 0.000 leoNodes.py:652(headString) # 41651 0.026 0.000 0.063 0.000 leoNodes.py:515(self_and_parents) #

695 0.026 0.000 0.026 0.000 {method ‘read’ of ‘_io.FileIO’ objects}

8308 0.025 0.000 0.502 0.000 leoGlobals.py:6793(os_path_finalize_join)

54732 0.024 0.000 0.033 0.000 leoNodes.py:1183(moveToParent)

932 0.024 0.000 0.027 0.000 sre_compile.py:250(_optimize_charset)

197714 0.023 0.000 0.023 0.000 leoNodes.py:282(__bool__)

50253 0.023 0.000 0.023 0.000 {method ‘match’ of ‘_sre.SRE_Pattern’ objects} 12016 0.023 0.000 0.131 0.000 leoGlobals.py:2981(compute_directives_re) # 20236 0.022 0.000 0.038 0.000 editCommands.py:834(getIconList) 10881 0.022 0.000 0.055 0.000 ntpath.py:74(join) 16381 0.022 0.000 0.338 0.000 re.py:286(_compile)

3598 0.022 0.000 0.370 0.000 leoGlobals.py:2992(get_directives_dict_list) # Improved!

76292 0.021 0.000 0.143 0.000 leoNodes.py:1600(__get_h)

541 0.021 0.000 0.021 0.000 {method ‘read’ of ‘_io.BufferedReader’ objects}

4731/6 0.021 0.000 0.052 0.009 leoFileCommands.py:2689(v_element_visitor) # benchmark
13788 0.021 0.000 0.169 0.000 leoGlobals.py:6766(os_path_expanduser)

6 0.020 0.003 0.107 0.018 leoCommands.py:1317(checkGnxs) # Improved

17125 0.018 0.000 0.031 0.000 nodetags.py:185(get_tags) 13994 0.018 0.000 0.063 0.000 leoNodes.py:1281(safeMoveToThreadNext)

5428 0.017 0.000 0.017 0.000 {built-in method winreg.EnumKey}

1 0.017 0.017 0.017 0.017 {msleep}

19806 0.017 0.000 0.098 0.000 leoCommands.py:749(all_positions)

4 0.016 0.004 0.016 0.004 {built-in method show}

17/15 0.016 0.001 0.025 0.002 {built-in method _imp.create_dynamic} 62440 0.016 0.000 0.022 0.000 leoGlobals.py:5571(isString) 22448 0.015 0.000 0.018 0.000 leoNodes.py:1116(moveToFirstChild)

3574 0.015 0.000 0.449 0.000 leoCommands.py:1936(scanAtPathDirectives)

19424 0.015 0.000 0.021 0.000 leoNodes.py:1103(moveToBack)

140295 0.015 0.000 0.015 0.000 {built-in method nt.fspath}
6737 0.015 0.000 0.030 0.000 leoGlobals.py:4593(skip_id)

524 0.015 0.000 0.015 0.000 {built-in method nt._isdir}

3195/405 0.014 0.000 0.056 0.000 sre_compile.py:64(_compile)

1 0.014 0.014 0.134 0.134 mimetypes.py:230(read_windows_registry)

11554 0.014 0.000 0.064 0.000 leoNodes.py:1997(findAtFileName)

169 0.014 0.000 0.015 0.000 leoAtFile.py:225(initReadIvars)

38576 0.013 0.000 0.013 0.000 {method ‘split’ of ‘str’ objects} 47187 0.013 0.000 0.023 0.000 leoNodes.py:2597(__get_u)

9909 0.013 0.000 0.013 0.000 {built-in method today}

834 0.013 0.000 0.013 0.000 {built-in method winreg.QueryValueEx}

4747 0.012 0.000 0.025 0.000 ntpath.py:199(split) 1406 0.012 0.000 0.925 0.001 leoGlobals.py:3476(fullPath)

105023 0.012 0.000 0.012 0.000 sre_parse.py:248(match)

2 0.012 0.006 0.017 0.009 QNCalendarWidget.py:35(build) 8 0.011 0.001 0.012 0.001 {built-in method addTab}

27635 0.011 0.000 0.011 0.000 {method ‘finditer’ of ‘_sre.SRE_Pattern’ objects} 13794 0.011 0.000 0.018 0.000 ntpath.py:308(expanduser)

1307 0.011 0.000 0.134 0.000 <frozen importlib._bootstrap_external>:1233(find_spec)

45828 0.011 0.000 0.015 0.000 leoGlobals.py:5617(isWordChar) # 18002 0.011 0.000 0.017 0.000 leoGlobals.py:4540(match)

8200 0.011 0.000 0.015 0.000 leoGlobals.py:4675(skip_ws)

39621 0.010 0.000 0.015 0.000 todo.py:607(getat)

683 0.010 0.000 0.010 0.000 {method ‘decode’ of ‘bytes’ objects}

8006 0.010 0.000 0.059 0.000 leoGlobals.py:6797(<listcomp>)

17124 0.009 0.000 0.053 0.000 leoChapters.py:245(parseHeadline) 17991 0.009 0.000 0.009 0.000 {method ‘search’ of ‘_sre.SRE_Pattern’ objects}

25 0.009 0.000 0.009 0.000 {built-in method repaint}

1 0.009 0.009 0.009 0.009 backend.py:71(Backend) 2 0.009 0.004 0.009 0.004 {built-in method setCalendarWidget}

48232 0.009 0.000 0.009 0.000 {method ‘pop’ of ‘list’ objects} 14000 0.009 0.000 0.074 0.000 leoCommands.py:832(safe_all_positions)

721 0.009 0.000 0.009 0.000 {method ‘connect’ of ‘PyQt5.QtCore.pyqtBoundSignal’ objects}

9202 0.009 0.000 0.085 0.000 ntpath.py:538(abspath) 9202 0.008 0.000 0.008 0.000 {built-in method nt._getfullpathname} 4040 0.008 0.000 0.012 0.000 leoMenu.py:247(<listcomp>)

184 0.008 0.000 0.008 0.000 {built-in method _hashlib.openssl_md5}

2 0.008 0.004 0.150 0.075 leoChapters.py:318(setAllChapterNames)

8006 0.008 0.000 0.491 0.000 leoCommands.py:1884(os_path_finalize_join) 8712 0.008 0.000 0.014 0.000 leoGlobals.py:4554(match_word) # Much improved

109997 0.008 0.000 0.008 0.000 {method ‘isalnum’ of ‘str’ objects} 9903/1 0.008 0.000 0.185 0.185 todo.py:497(new)

1 0.008 0.008 0.062 0.062 backlink.py:412(loadLinksInt)

37052 0.007 0.000 0.007 0.000 {method ‘lstrip’ of ‘str’ objects} 14946 0.007 0.000 0.012 0.000 {built-in method builtins.getattr}

172 0.007 0.000 0.007 0.000 {built-in method nt.access}

17008 0.007 0.000 0.013 0.000 leoNodes.py:2171(bodyString)

6248 0.007 0.000 0.070 0.000 leoGlobals.py:6875(os_path_normpath) 5920 0.007 0.000 0.018 0.000 enum.py:801(__and__)

104812 0.007 0.000 0.007 0.000 {built-in method builtins.ord}

96311 0.007 0.000 0.007 0.000 {method ‘isspace’ of ‘str’ objects} 12677 0.007 0.000 0.014 0.000 leoNodes.py:102(new_vnode_helper)

5628 0.007 0.000 0.013 0.000 leoGlobals.py:2053(add) 8417 0.007 0.000 0.171 0.000 leoGlobals.py:6850(<listcomp>)

1 0.007 0.007 0.174 0.174 todo.py:519(loadAllIcons)

4500/2094 0.007 0.000 0.008 0.000 sre_parse.py:173(getwidth)

42452 0.007 0.000 0.007 0.000 {method ‘group’ of ‘_sre.SRE_Match’ objects} 29691 0.006 0.000 0.113 0.000 leoCommands.py:737(all_unique_nodes)

8417 0.006 0.000 0.029 0.000 leoGlobals.py:6841(<listcomp>)

10931 0.006 0.000 0.012 0.000 leoGlobals.py:2103(get)

4250 0.006 0.000 0.059 0.000 leoKeys.py:2956(registerCommandShortcut) 2294 0.006 0.000 0.029 0.000 leoAtFile.py:3705(putCodeLine)

12946 0.006 0.000 0.007 0.000 enum.py:515(__new__)

5220 0.006 0.000 0.014 0.000 leoAtFile.py:4321(os) 6406 0.006 0.000 0.027 0.000 leoConfig.py:1728(getShortcut)

96 0.006 0.000 0.009 0.000 {built-in method builtins.sorted}

1 0.006 0.006 1.403 1.403 leoAtFile.py:703(readAll)

4603 0.006 0.000 0.047 0.000 leoGlobals.py:6690(os_path_basename)

1 0.006 0.006 0.040 0.040 qt_gui.py:46(__init__)

794/141 0.006 0.000 2.087 0.015 <frozen importlib._bootstrap>:966(_find_and_load)

16628 0.006 0.000 0.024 0.000 leoNodes.py:1571(__get_b)

3137/2629 0.006 0.000 0.007 0.000 proxy_metaclass.py:77(__getattribute__)
1928 0.005 0.000 0.281 0.000 leoConfig.py:1898(visitNode)

167 0.005 0.000 0.047 0.000 leoGlobals.py:3711(readFileIntoString)

16628 0.005 0.000 0.018 0.000 leoNodes.py:649(bodyString)

7 0.005 0.001 0.058 0.008 leoKeys.py:2264(makeBindingsFromCommandsDict)

749 0.005 0.000 0.156 0.000 <frozen importlib._bootstrap>:870(_find_spec)

15370 0.005 0.000 0.334 0.000 re.py:231(compile)

8853 0.005 0.000 0.008 0.000 leoGlobals.py:4606(skip_line) # Much improved.

12677 0.005 0.000 0.007 0.000 leoNodes.py:45(check_gnx)
693 0.005 0.000 0.007 0.000 <frozen importlib._bootstrap_external>:430(_validate_bytecode_header)

1 0.005 0.005 0.005 0.005 qt_gui.py:879(getIconImage)

4267 0.005 0.000 0.055 0.000 leoNodes.py:2012(anyAtFileNodeName)

19 0.005 0.000 0.055 0.003 leoCommands.py:1181(setChanged)

693 0.005 0.000 0.194 0.000 <frozen importlib._bootstrap_external>:743(get_code)

4250 0.005 0.000 0.065 0.000 leoKeys.py:2913(registerCommand)

2 0.005 0.002 0.005 0.002 {built-in method minimumSizeHint}

13566 0.005 0.000 0.007 0.000 sre_parse.py:163(__getitem__)

171 0.005 0.000 0.026 0.000 leoExternalFiles.py:334(checksum)

1386 0.005 0.000 0.014 0.000 <frozen importlib._bootstrap_external>:263(cache_from_source)

6 0.005 0.001 0.005 0.001 leoFileCommands.py:2655(scanTnodes)

6570 0.005 0.000 0.012 0.000 <frozen importlib._bootstrap_external>:57(_path_join)

12956 0.005 0.000 0.013 0.000 enum.py:265(__call__)

84 0.005 0.000 0.005 0.000 {built-in method nt.listdir}

1034 0.005 0.000 0.008 0.000 <frozen importlib._bootstrap>:157(_get_module_lock)
80 0.005 0.000 0.007 0.000 qt_frame.py:4354(__init__)

1 0.004 0.004 0.078 0.078 backlink.py:116(fixIDs)

4265 0.004 0.000 0.008 0.000 leoConfig.py:1129(canonicalizeSettingName)

17694 0.004 0.000 0.004 0.000 leoGlobals.py:539(__hash__)

165 0.004 0.000 0.657 0.004 leoAtFile.py:464(read)

16834 0.004 0.000 0.004 0.000 {built-in method builtins.min}

6570 0.004 0.000 0.006 0.000 <frozen importlib._bootstrap_external>:59(<listcomp>)

17862 0.004 0.000 0.004 0.000 leoGlobals.py:2038(_checkKeyType)
82 0.004 0.000 0.008 0.000 <frozen importlib._bootstrap_external>:1067(_path_hooks)

1 0.004 0.004 0.063 0.063 nodetags.py:175(get_tagged_gnxes) 1 0.004 0.004 0.062 0.062 nodetags.py:140(initialize_taglist)

1928 0.004 0.000 0.016 0.000 leoConfig.py:713(parseHeadline)

23391 0.004 0.000 0.004 0.000 leoNodes.py:775(hasBack)

2 0.004 0.002 0.021 0.011 QNCalendarWidget.py:20(__init__)

1197/405 0.004 0.000 0.230 0.001 sre_parse.py:407(_parse_sub)

876 0.004 0.000 0.150 0.000 leoConfig.py:845(set)

35055 0.004 0.000 0.004 0.000 leoGlobals.py:4532(is_ws)
1324 0.004 0.000 0.019 0.000 leoKeys.py:2025(bindKey)

165 0.004 0.000 0.010 0.000 leoAtFile.py:5120(post_pass) 714 0.004 0.000 0.018 0.000 <frozen importlib._bootstrap>:504(_init_module_attrs)

6286 0.004 0.000 0.007 0.000 leoGlobals.py:458(write) 9902 0.003 0.000 0.021 0.000 editCommands.py:842(setIconList) 5428 0.003 0.000 0.021 0.000 mimetypes.py:243(enum_types)

6 0.003 0.001 0.110 0.018 leoCommands.py:1516(checkOutline)

Stats: g.isUnicode (before & after)#
145181 g.isUnicode:__init__,read_words,add_expanded_line,toUnicode

66369 g.isUnicode:__get_h,headString,headString,toUnicode 52902 g.isUnicode:get_UNL,__get_h,headString,headString 11400 g.isUnicode:munge,os_path_normpath,toUnicodeFileEncoding,toUnicode

8924 g.isUnicode:shortFileName,os_path_basename,toUnicodeFileEncoding,toUnicode 7744 g.isUnicode:get_directives_dict,__get_b,bodyString,bodyString 7488 g.isUnicode:<listcomp>,os_path_expanduser,toUnicodeFileEncoding,toUnicode 7449 g.isUnicode:anyAtFileNodeName,findAtFileName,headString,toUnicode 6986 g.isUnicode:v_element_visitor,v_element_visitor,v_element_visitor,v_element_visitor 6539 g.isUnicode:os_path_finalize_join,<listcomp>,os_path_expandExpression,toUnicode 5643 g.isUnicode:get_directives_dict,__get_h,headString,headString

4841 g.isUnicode:isAnyAtFileNode,isAnyAtFileNode,headString,toUnicode 4797 g.isUnicode:idle_check_commander,isAnyAtFileNode,isAnyAtFileNode,headString 4580 g.isUnicode:os_path_finalize_join,os_path_join,toUnicodeFileEncoding,toUnicode 4565 g.isUnicode:anyAtFileNodeName,findAtFileName,skip_id,toUnicode 4044 g.isUnicode:anyAtFileNodeName,anyAtFileNodeName,findAtFileName,headString 3405 g.isUnicode:isAnyAtFileNode,anyAtFileNodeName,findAtFileName,headString 2489 g.isUnicode:createAllButtons,__get_h,headString,headString 2280 g.isUnicode:parse,parse,feed,characters 2054 g.isUnicode:visitNode,__get_h,headString,headString 1866 g.isUnicode:putLine,putCodeLine,onl,os 1747 g.isUnicode:visitNode,parseHeadline,skip_id,toUnicode 1715 g.isUnicode:putBody,putLine,putCodeLine,os 1302 g.isUnicode:parseHeadline,__get_h,headString,headString

==== After 1

52902 g.isUnicode:get_UNL,__get_h,headString,headString

7459 g.isUnicode:get_directives_dict,__get_b,bodyString,bodyString 6986 g.isUnicode:v_element_visitor,v_element_visitor,v_element_visitor,v_element_visitor 5423 g.isUnicode:get_directives_dict,__get_h,headString,headString 3919 g.isUnicode:anyAtFileNodeName,anyAtFileNodeName,findAtFileName,headString 2489 g.isUnicode:createAllButtons,__get_h,headString,headString 2280 g.isUnicode:parse,parse,feed,characters 2132 g.isUnicode:idle_check_commander,isAnyAtFileNode,isAnyAtFileNode,headString 2054 g.isUnicode:visitNode,__get_h,headString,headString 1866 g.isUnicode:putLine,putCodeLine,onl,os 1715 g.isUnicode:putBody,putLine,putCodeLine,os 1550 g.isUnicode:isAnyAtFileNode,anyAtFileNodeName,findAtFileName,headString 1302 g.isUnicode:parseHeadline,__get_h,headString,headString

===== After 2

10 g._toUnicode:read,openFileForReading,readFileToUnicode,toUnicode

7 g._toUnicode:readAll,readOneAtCleanNode,read_at_clean_lines,toUnicode 6 g._toUnicode:openLeoFile,getLeoFile,readFile,toUnicode 5 g._toUnicode:read,read_into_root,readFileIntoString,toUnicode 3 g._toUnicode:read_into_root,readFileIntoString,getPythonEncodingFromString,toUnicode 2 g._toUnicode:__init__,__init__,read_words,toUnicode 1 g._toUnicode:createOutline,init_import,readFileIntoString,toUnicode

Stats: is_special: before (no change)#

584 g.is_special:readExternalFiles,readAll,isAtIgnoreNode,isAtIgnoreNode 474 g.is_special:putVnode,putVnode,isAtIgnoreNode,isAtIgnoreNode 134 g.is_special:onCreate,createAllButtons,isAtIgnoreNode,isAtIgnoreNode

43 g.is_special:putVnodes,putVnode,isAtIgnoreNode,isAtIgnoreNode 32 g.is_special:visitNode,doCommands,isAtIgnoreNode,isAtIgnoreNode

6 g.is_special:visitNode,doButtons,isAtIgnoreNode,isAtIgnoreNode 5 g.is_special:findReference,findReference,isAtIgnoreNode,isAtIgnoreNode

Stats: g.match_word: before & after#

# After s.bat.

# Yikes: createAllButtons takes a long time. 244179 g.match_word:createAllButtons,isAtIgnoreNode,isAtIgnoreNode,is_special

76017 g.match_word:doHandlersForTag,callTagHandler,onCreate,createAllButtons 16801 g.match_word:onCreate,createAllButtons,isAtIgnoreNode,isAtIgnoreNode

# Nothing else matters much… 7540 g.match_word:writeFromString,writeOpenFile,putBody,directiveKind4 2861 g.match_word:readAll,isAtIgnoreNode,isAtIgnoreNode,is_special 2572 g.match_word:putVnode,isAtIgnoreNode,isAtIgnoreNode,is_special 1824 g.match_word:fullPath,anyAtFileNodeName,anyAtFileNodeName,findAtFileName 1646 g.match_word:putLine,putAtOthersLine,putBody,directiveKind4 1089 g.match_word:isAnyAtFileNode,isAnyAtFileNode,anyAtFileNodeName,findAtFileName

===== After

7540 g.match_word:writeFromString,writeOpenFile,putBody,directiveKind4 1646 g.match_word:putLine,putAtOthersLine,putBody,directiveKind4 1645 g.match_word:fullPath,anyAtFileNodeName,anyAtFileNodeName,findAtFileName

Stats: p.ctor (no change will be made)#
# Called from get_directives_dict_list

76528 p.__init__:fullPath,get_directives_dict_list,self_and_parents,copy 31818 p.__init__:readAll,fullPath,get_directives_dict_list,copy

2196 p.__init__:idle_check_at_file_node,fullPath,get_directives_dict_list,copy

# p.generators…

30701 p.__init__:safe_all_positions,safeMoveToThreadNext,self_and_parents,copy 30158 p.__init__:fixIDs,all_unique_nodes,all_unique_positions,copy 22121 p.__init__:setChanged,all_unique_nodes,all_unique_positions,copy 24422 p.__init__:checkOutline,checkGnxs,safe_all_positions,copy 19398 p.__init__:readAll,fullPath,self_and_parents,copy 15079 p.__init__:finishCreate,setAllChapterNames,all_unique_positions,copy 14756 p.__init__:find_at_persistence_node,findNodeAnywhere,all_unique_positions,copy 17211 p.__init__:new,loadAllIcons,all_positions,copy 12537 p.__init__:readExternalFiles,restoreDescendentAttributes,all_unique_positions,copy 10726 p.__init__:getLeoFile,resolveTnodeLists,all_unique_positions,copy

9991 p.__init__:contractAllHeadlinesCommand,contractAllHeadlines,all_positions,copy 5008 p.__init__:set,get_UNL,self_and_parents,copy 4327 p.__init__:putVnodes,clearAllVisited,all_unique_positions,copy

# All others.
19898 p.__init__:set,get_UNL,getBack,copy

9315 p.__init__:doBool,set,get_UNL,copy 6745 p.__init__:doColor,set,get_UNL,copy 6004 p.__init__:doString,set,get_UNL,copy 1973 p.__init__:createSettingsDicts,traverse,visitNode,copy 1706 p.__init__:doData,set,get_UNL,copy 1563 p.__init__:doInt,set,get_UNL,copy 1531 p.__init__:eventFilter,__get_p,currentPosition,copy 1129 p.__init__:drawChildren,drawNode,rememberItem,copy 1120 p.__init__:visitNode,set,get_UNL,copy 1001 p.__init__:doFont,set,get_UNL,copy

Much faster reading of external files#

This branch incorporates Vitalije’s great new read code. This code reads external files (from @file nodes) almost exactly as fast as when using the cacher.

As a result, file caching is no longer needed, The –no-cache option is gone.

** Highlights of the fast-read branch **

  1. It includes the no-sax branch. That is, the fast-read branch contains new code for reading both external files and .leo files.

  2. Caching has been radically simplified:

  1. No file caching whatever is done. The cache contains only non-essential items, such as marked and expanded bits.

  2. ~/.leo/db now contains only two sub-folders: g_app_db and global_data. g_app_db corresponds to the old “global” folder. It contains the cached result of g.app.db. The global_data folder contains all expanded and marked bits, plus some other data. The keys are simply the full path names of each .leo file. This should be safe enough.

  1. Leo writes only a vestigial <globals> element in .leo files. This should be enough to allow old (Leo 4.5 and above) versions of Leo to read .leo files.

  2. Leo no longer writes expanded and marked bits to the root node of @file trees.

  3. As a result of 2, 3 and 4, all Leo files are essentially “fixed”. Their contents will change much less often than before. As a result, the c.fixed switch has been eliminated, along with the @bool fixedwindow setting.

  4. The g.enableDB switch has been eliminated. The –no-cache command-line argument has been deprecated.

Summary

Leo now works as if –no-cache were permanently in effect. In other words, Leo always recreates outlines directly from external files. This eliminates an important source of confusion.

Leo’s new read code is almost exactly as fast as reading cached data, a remarkable accomplishment.

Leo no longer pollutes .leo files with non-essential data, resulting in fewer diffs of .leo files.

Code

leo-editor/leo-editor#934

Added copy kwarg to generators#

This branch greatly reduces overhead during startup.

  1. All generators yielding positions now accept a “copy” kwarg.

    The default value is True, for compatibility with user scripts.

    When True, these generators yield copies of all positions.

    Leo’s core sets copy=False in several places, greatly reducing unnecessary positions.

  2. g.isUnicode and g.toUnicode are simpler and faster.

  3. Rewrote g.is_special, greatly reduced calls to g.match_words.

# get_UNL makes way too many copies.

11831 p.copy:visitNode,doBool,set,get_UNL

6827 p.copy:visitNode,doColor,set,get_UNL 9217 p.copy:doBool,set,get_UNL,getBack 6717 p.copy:visitNode,doString,set,get_UNL 4581 p.copy:doString,set,get_UNL,getBack 4287 p.copy:doColor,set,get_UNL,getBack 2470 p.copy:visitNode,doData,set,get_UNL 2089 p.copy:visitNode,doInt,set,get_UNL 1986 p.copy:doData,set,get_UNL,getBack 1673 p.copy:doInt,set,get_UNL,getBack 1668 p.copy:doBool,set,get_UNL,self_and_parents 1503 p.copy:doColor,set,get_UNL,self_and_parents 1477 p.copy:traverse,visitNode,set,get_UNL 1282 p.copy:doString,set,get_UNL,self_and_parents 1183 p.copy:visitNode,set,get_UNL,getBack 1001 p.copy:visitNode,doFont,set,get_UNL

# All others

6828 p.copy:readAll,fullPath,get_directives_dict_list,self_and_parents 4303 p.copy:putLeoOutline,putVnodes,clearAllVisited,all_unique_positions 4220 p.copy:checkGnxs,safe_all_positions,safeMoveToThreadNext,self_and_parents 4183 p.copy:getLeoFile,checkOutline,checkGnxs,safe_all_positions 4080 p.copy:openLeoFile,getLeoFile,resolveTnodeLists,all_unique_positions 3762 p.copy:readExternalFiles,readAll,fullPath,get_directives_dict_list 2372 p.copy:readExternalFiles,readAll,fullPath,self_and_parents 2054 p.copy:computeLocalSettings,createSettingsDicts,traverse,visitNode

# g.get_directive_dict_list

67470 p.copy:readAll,fullPath,get_directives_dict_list,self_and_parents 31172 p.copy:readExternalFiles,readAll,fullPath,get_directives_dict_list

# g.safeMoveToThreadNext

30497 p.copy:checkGnxs,safe_all_positions,safeMoveToThreadNext,self_and_parents

# c.checkGnxs

24119 p.copy:getLeoFile,checkOutline,checkGnxs,safe_all_positions

18974 p.copy:readExternalFiles,readAll,fullPath,self_and_parents 17110 p.copy:__init__,new,loadAllIcons,all_positions 15083 p.copy:finishOpen,finishCreate,setAllChapterNames,all_unique_positions 14756 p.copy:update_after_read_foreign_file,find_at_persistence_node,findNodeAnywhere,all_unique_positions 10423 p.copy:openLeoFile,getLeoFile,resolveTnodeLists,all_unique_positions

4327 p.copy:putLeoOutline,putVnodes,clearAllVisited,all_unique_positions 3983 p.copy:getLeoFile,readExternalFiles,restoreDescendentAttributes,all_unique_positions 3264 p.copy:idle_check_at_file_node,fullPath,get_directives_dict_list,self_and_parents 1973 p.copy:computeLocalSettings,createSettingsDicts,traverse,visitNode 1559 p.copy:openFileForReading,fullPath,get_directives_dict_list,self_and_parents 1464 p.copy:idle_check_commander,idle_check_at_file_node,fullPath,get_directives_dict_list

# get_UNL is not a problem

1264 p.copy:visitNode,doColor,set,get_UNL 1113 p.copy:visitNode,doBool,set,get_UNL 1050 p.copy:visitNode,doString,set,get_UNL

#

6828 p.copy:readAll,fullPath,get_directives_dict_list,self_and_parents 4303 p.copy:putLeoOutline,putVnodes,clearAllVisited,all_unique_positions 4220 p.copy:checkGnxs,safe_all_positions,safeMoveToThreadNext,self_and_parents 4183 p.copy:getLeoFile,checkOutline,checkGnxs,safe_all_positions 4080 p.copy:openLeoFile,getLeoFile,resolveTnodeLists,all_unique_positions 3762 p.copy:readExternalFiles,readAll,fullPath,get_directives_dict_list 2372 p.copy:readExternalFiles,readAll,fullPath,self_and_parents 2054 p.copy:computeLocalSettings,createSettingsDicts,traverse,visitNode

# p.get_UNL now creates the minimum number of copies.

1307 p.copy:visitNode,doBool,set,get_UNL 1270 p.copy:visitNode,doColor,set,get_UNL 1068 p.copy:visitNode,doString,set,get_UNL

# After changing p.safeMoveToThreadNext, g.get_directives_dict_list, c.checkGnxs.

4303 p.copy:putLeoOutline,putVnodes,clearAllVisited,all_unique_positions

4080 p.copy:openLeoFile,getLeoFile,resolveTnodeLists,all_unique_positions

# Change g.fullPath

3762 p.copy:readExternalFiles,readAll,fullPath,get_directives_dict_list 2372 p.copy:readExternalFiles,readAll,fullPath,self_and_parents 1881 p.copy:readAll,fullPath,get_directives_dict_list,self_and_parents

2054 p.copy:computeLocalSettings,createSettingsDicts,traverse,visitNode 1307 p.copy:visitNode,doBool,set,get_UNL 1270 p.copy:visitNode,doColor,set,get_UNL 1068 p.copy:visitNode,doString,set,get_UNL

2054 p.copy:computeLocalSettings,createSettingsDicts,traverse,visitNode

# These copies are essential.

1881 p.copy:readAll,fullPath,get_directives_dict_list,self_and_parents

# self_and_parents makes one copy, so this also is minimal.

Added g.app.c property#

This is the presently active commander, that is, g.app.log.c.

Removed “adjust” and “reassignIndices” kwargs#

This is an important simplification of the code.

Removed qtree.update_appearance*#
Improved Leo’s outline drawing code#

Leo now redraws the screen only once during startup.

Removed qtree.update_appearance and qtree.update_appearance_idle.

Features#

#871: A setting to position the icon bar#

leo-editor/leo-editor#871

In fact, this setting has existed for a long time.

#913: Show base classes in python importer#

leo-editor/leo-editor#913

#914: Fix jedi completion glitches#

leo-editor/leo-editor#914

#932: use “show” prefix for many commands#

leo-editor/leo-editor#932

Commands that DO use the printer:

print-body print-html print-node print-expanded-body print-expanded-html print-marked-bodies print-marked-html print-marked-nodes print-tree-bodies print-tree-html print-tree-nodes

Commands that DON’T use the printer:

gc-show-summary show-all-uas show-bindings show-buttons show-commands show-focus show-node-uas show-plugin-handlers show-plugins-info show-settings show-stats show-style-sheet

#949: Smart quotes#

leo-editor/leo-editor#949

The present code converts a straight quote (single or double) to an opening curly quote if the cursor is at the start of a line or if a blank or tab precedes the cursor. Otherwise, the code converts a straight quote (single or double) to a closing curly quote.

#953: better warnings about importing qt#

leo-editor/leo-editor#953

#961: curses gui#

leo-editor/leo-editor#961

Better tracing if the cursor gui fails to load.

#966: Better support for clojurescript#

leo-editor/leo-editor#966

Added –trace-drawing and –trace-startup#
Added .sty and .latex entries in extension_dict#
Added @nosearch to results of cff#
Added dump-clone-parents command#

This is for debugging only.

Added md_docer.py plugin#

https://groups.google.com/forum/#!topic/leo-editor/Nun7rRRhato

Added show-stats command & improved tracing#

This command just calls g.printStats, which prints the contents of g.app.statsDict.

Put the following snippet at the start of any function/method you wish to profile:

if not g.app.statsLockout:
    g.app.statsLockout = True
    try:
        d = g.app.statsDict
        key = 'g.isUnicode:' + g.callers()
        d [key] = d.get(key, 0) + 1
    finally:
        g.app.statsLockout = False

To see the stats, restart Leo, then do show-stats.

This pattern produces superb statistics that show how many times the callers of a routine called the routine. Here are before/after statistics for g.match_word:

# Yikes: createAllButtons takes a long time.

244179 g.match_word:createAllButtons,isAtIgnoreNode,isAtIgnoreNode,is_special
 76017 g.match_word:doHandlersForTag,callTagHandler,onCreate,createAllButtons
 16801 g.match_word:onCreate,createAllButtons,isAtIgnoreNode,isAtIgnoreNode

# Nothing else matters much...

7540 g.match_word:writeFromString,writeOpenFile,putBody,directiveKind4
2861 g.match_word:readAll,isAtIgnoreNode,isAtIgnoreNode,is_special
2572 g.match_word:putVnode,isAtIgnoreNode,isAtIgnoreNode,is_special
1824 g.match_word:fullPath,anyAtFileNodeName,anyAtFileNodeName,findAtFileName
1646 g.match_word:putLine,putAtOthersLine,putBody,directiveKind4
1089 g.match_word:isAnyAtFileNode,isAnyAtFileNode,anyAtFileNodeName,findAtFileName

# After improvements...

7540 g.match_word:writeFromString,writeOpenFile,putBody,directiveKind4
1646 g.match_word:putLine,putAtOthersLine,putBody,directiveKind4
1645 g.match_word:fullPath,anyAtFileNodeName,anyAtFileNodeName,findAtFileName
Leo ecognizes .latex and .sty as LaTeX files#

https://groups.google.com/forum/#!topic/leo-editor/09H5wX1QRxw

Added .latex and *.sty files, would automatically be recognized as LaTeX.

Removed –no-cache & –trace-cache#

Leo 5.5 release notes#

Leo 5.5 March 23, 2017

[Leo](https://leo-editor.github.io/leo-editor/) 5.5 is now available on [SourceForge](https://sourceforge.net/projects/leo/files/Leo/) and on [GitHub](leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](https://leo-editor.github.io/leo-editor/preface.html).

Simulating Leo’s features in Vim, Emacs or Eclipse is possible, just as it is possible to simulate Python in assembly language…

The highlights of Leo 5.5

  • Syntax coloring is 20x faster than before. The “big-text” hack is no longer needed.

  • Leo’s importers are now line/token oriented, allowing them to handle languages like javascript more robustly.

  • New perl and javascript importers.

  • Pylint now runs in the background.

  • Pyflakes can optionally check each file as it is written.

  • Greatly simplified argument-handling for interactive commands.

  • Documented how to do Test-Driven Development in Leo.

Links

Most important features#

Fixed huge performance bug in syntax coloring#

The horrible big text hack is no longer needed.

  • Fixes #273: Qt Bug involving large text nodes.

  • Completes #365: Use pyzo syntax coloring.

  • Revolutionizes Leo’s approach to Qt’s QSyntaxHighlighter class. Everything happens automatically. When changing nodes, Leo need only re-init the underlying jEdit colorizing code so that the proper language is colorized.

No need for any of the interface in the ColorizerMixin class. No need to “lock out” coloring: it happens automatically whenever Leo’s body pane changes! Heh. As I write this I see that colorizer.colorize is no longer ever called!

I don’t think I have ever misunderstood a class as badly as I have misunderstood QSyntaxHighlighter class. Set up and used properly, it is an amazing helper. To be fair, Leo uses this class in a very unusual manner. The mistake I made was subtle, and the Qt documents don’t warn against it.

The performance bug created by calling QSyntaxHighlighter explicitly caused a “series of unfortunate events” ;-) Seeing the speed pyzo’s pure python syntax colorer was the key breakthrough.

Optionally run pyflakes when saving files#

Enabled using @bool run-pyflakes-on-write = True

Greatly improved javascript and perl importers#

https://groups.google.com/d/msg/leo-editor/RDi2jffWjzI/K-mh4H5QBQAJ

leo-editor/leo-editor#332

The new javascript and perl importers know nothing about parsing. They know only about how to scan tokens accurately. The importers copy only entire lines from the text file to Leo nodes. As a result, the new importers much more reliable than previous importers.

Optionally colorize doc parts using rST#

New in Leo 5.5: optionally colorize doc parts using reStructuredText

Added @bool color-doc-parts-as-rest

The only changes were to match_doc_part and its restarter.

#371: execute-script supports multiple @language direcitves#

leo-editor/leo-editor#371

For example, execute-script will work on the following node:

@language rest
Comments...
@language python
print('hi')
@language md
More comments...
@language python
print('abc')

The new g.extractExecutableString function removes all lines that are in the range of @language rest/md/markdown. It truncates the script, with a warning, if it sees two “executable” @language directives, such as C and Python.

Note: Even if a node contains multiple executable languages, the user can select a range of lines to execute. All will be well, provided the selected text contains at most one executable language.

#334: Rewrote all of Leo’s importers#

leo-editor/leo-editor#334 This was a large project. See the issue tracker for extensive notes.

Full documentation is here: leo-editor/leo-editor

New, line-oriented scanning code in leo/importers/linescanner.py replaces old, character-oriented, code in leo/importers/basescanner.py.

The xml and html importers now regularize whitespace. xml and html are outliers because they have neither explicit brackets nor strict indentation rules.

#328: The pylint command now runs in the background#

Leo no longer hangs waiting for this command to finish. leo-editor/leo-editor#328

#311: Simplified Leo’s argument logic#

leo-editor/leo-editor#311

Here is the docstring for k.get1Arg, which also discusses k.getNextArg:

k.get1Arg: Handle the next character the user types when accumulating a user argument from the minibuffer. Ctrl-G will abort this processing at any time.

Commands should use k.get1Arg to get the first minibuffer argument and k.getNextArg to get all other arguments.

Before going into the many details, let’s look at some examples. This code will work in any class having a ‘c’ ivar bound to a commander.

Example 1: get one argument from the user:

@cmd(‘my-command’) def myCommand(self, event):

k = self.c.k k.setLabelBlue(‘prompt: ‘) k.get1Arg(event, handler=self.myCommand1)

def myCommand1(self, event):

k = self.c.k # k.arg contains the argument. # Finish the command. … # Reset the minibuffer. k.clearState() k.resetLabel() k.showStateAndMode()

Example 2: get two arguments from the user:

@cmd(‘my-command’) def myCommand(self, event):

k = self.c.k k.setLabelBlue(‘first prompt: ‘) k.get1Arg(event, handler=self.myCommand1)

def myCommand1(self, event):

k = self.c.k self.arg1 = k.arg k.setLabelBlue(‘second prompt: ‘) k.getNextArg(handler=self.myCommand2)

def myCommand2(self, event):

k = self.c.k # k.arg contains second argument. # Finish the command, using self.arg1 and k.arg. … # Reset the minibuffer. k.clearState() k.resetLabel() k.showStateAndMode()

k.get1Arg and k.getNextArg are a convenience methods. They simply pass their arguments to the get_arg method of the singleton GetArg instance. This docstring describes k.get1arg and k.getNextArg as if they were the corresponding methods of the GetArg class.

k.get1Arg is a state machine. Logically, states are tuples (kind, n, handler) though they aren’t represented that way. When the state machine in the GetArg class is active, the kind is ‘getArg’. This constant has special meaning to Leo’s key-handling code.

The arguments to k.get1Arg are as follows:

event: The event passed to the command.

handler=None, An executable. k.get1arg calls handler(event)

when the user completes the argument by typing <Return> or (sometimes) <tab>.

tabList=[]: A list of possible completions.

completion=True: True if completions are enabled.

oneCharacter=False: True if k.arg should be a single character.

stroke=None: The incoming key stroke.

useMinibuffer=True: True: put focus in the minibuffer while accumulating arguments.

False allows sort-lines, for example, to show the selection range.

Bugs#

#325: Simplify the organization of commands#

leo-editor/leo-editor#325

#340: finish (for 5.5) reload-settings#

leo-editor/leo-editor#340

Added reload-settings command. This does style-reload automatically.

#343: (unicode problems in file names)#

leo-editor/leo-editor#343 Exception creating path” error when evaluating a path with accents in a @clean expression

The fix was to g.os_path_expandExpression.

#344: @string view-rendered-default-kind not functional#

leo-editor/leo-editor#344

This setting was used: @string view-rendered-default-kind

  • Added “use_default” keyword arg to BaseColorizer.scanLanguageDirectives.

  • vr.get_kind sets use_default to False, and uses the setting by default.

#348: (CDATA errors)#

leo-editor/leo-editor#348 XML CDATA Sections not preserved on round-trip save

#350: themes not working as documented#

leo-editor/leo-editor#350

ssm.expand_css_constants no longer adds constants.

#352: Importer unit tests create both @clean and @file#

leo-editor/leo-editor#352 Importer unit tests create both @clean and @file

The fix was disappointingly simple: just init ic.treeType in ic.createOutline and ic.scannerUnitTest.

#367: goto-script problems#

leo-editor/leo-editor#367

createCommonButton now sets the gnx for AtButtonCallback.

QtIconBarClass.goto_command now completes the selection at idle time. There seems to be no way to do this in one step.

Note: ScriptingController.open_gnx uses g.openWithFileName to open settings files. So the focus problem is pretty strange.

#371: support multiple languages in scripts#

leo-editor/leo-editor#371

The fix was to extractExecutableString

#374: Leo can confuse directives with decorators#

leo-editor/leo-editor#374 This caused problems in the importers.

#375: improve jedit.setTag#

leo-editor/leo-editor#375

#380: New colorizer doesn’t update properly…#

leo-editor/leo-editor#380 New colorizing code doesn’t update properly after changing @language directives.

#381: (default importer encoding problems)#

leo-editor/leo-editor#381

Added g.getEncodingAt(p)

#387: New file is marked as changed#

leo-editor/leo-editor#387

The problem:

abbrev.init_tree_abbrev changes the outline’s changed indicator (*) during startup. Simply reversing this in c.new causes the * to flip back and forth.

The changes were a bit tricky:

  • init_tree_abbrev calls c.pasteOutline(…,redrawFlag=False)

  • pasteOutline calls c.setChanged(True, redrawFlag=redrawFlag)

  • c.new calls c.setChanged(False)

  • Added redrawFlag keyword arg to c.setChanged. When this is false, c.setChanged does not alter the outline’s changed indicator.

Suppressing the change indicator is a bit dangerous. It could be very confusing if the indicator gets out of sync with reality. But the fix should actually be safe enough, because only startup code is affected.

#388: wikiview plugin#

leo-editor/leo-editor#388

#389: syntax coloring changes#

leo-editor/leo-editor#389

See the checkin log for details.

#391: Read File Into Node” with empty file#

leo-editor/leo-editor#391

#392: @auto-rst file.txt: -rst ignored on read#

leo-editor/leo-editor#392

#395: beautify-node can hang#

leo-editor/leo-editor#395

#396: Show images in Leo’s body pane#

leo-editor/leo-editor#396

https://stackoverflow.com/questions/3254652/ several-ways-of-placing-an-image-in-a-qtextedit

#402: python’s input statement hangs Leo#

leo-editor/leo-editor#402

Added g.input_, but this is not a great solution.

#403: goto-global-line error#

leo-editor/leo-editor#403

The fix was to v.atFileNodeName. It must recognize @thin as an @file node.

#408: c.recursiveImport uncaught exception…#

c.recursiveImport uncaught exception on broken (linux) symlinks leo-editor/leo-editor#408

#409: urls no longer colored#

leo-editor/leo-editor#409

The fix was to restore disabled code in jedit.colorRangeWithTag.

#416: PageUp binding problem#

leo-editor/leo-editor#416

The fix, as expected, was to k.stroke2char.

#426: console registerCommand - Chapter_hoist plugin#

leo-editor/leo-editor#426

Added a kludge in dehoistCallback that satisfies k.registerCommand.

#427: multiple vnodes…#

leo-editor/leo-editor#427

Fixed #427: multiple vnodes with (same) gnx… All tests pass.

  • c.pasteOutline does not call c.checkOutline when tempOutline is True.

Also fixed several tree-drawing problems:

  • Refactored abbrev.init_tree_abbrev to suppress unwanted redraws.

  • Fixed an unrelated bug in abbrev.paste_tree. It must redraw the tree.

  • c.reloadSettingsHelper no longer redraws the tree.

#429: goto line number…#

leo-editor/leo-editor#429

  • goto.get_external_file_with_sentinels now calls the new g.composeScript.

  • Rewrote g.extractExecutableString. It now returns all lines under control of a given language.

#430: rst import…#

leo-editor/leo-editor#430 rst import: titles with different underline characters on same level.

#431: Simplify importer tables#

leo-editor/leo-editor#431

Create importer/writer tables only once, during startup. All tests pass. This resulted in a cascade of simplifications.

Moved ivars and methods from leoAtFile.py and leoImport.py into the LeoApp class: - Added atAutoWritersDict, writersDispatchDict, atAutoDict and classDispatchDict ivars. - Added createAllImporetersData and its two helpers. - Added scanner_for_at_auto and scanner_for_ext.

leoPersistence.py: - Moved ConvertController class to the attic. - Moved pd.convert_at_file_to_at_auto to the attic. - Moved pd.prepass & helper to the attic.

As a result, the prepass argument to the importers is no more.

leoTest.py: - All unit tests now restore the screen when done.

leo/plugins/linescanner.py: - Removed the prepass keyword arg and related logic from i.run.

plugins/qt_frame.py: - Added a disabled trace to createAtFileNode code, called from the drag/drop logic.

#434: Potential bug in settings#

leo-editor/leo-editor#434

Added a guard to fc.parse_leo_file. This is defensive coding.

Changed sf.copy_to_my_settings to reflect recent changes to p.getUnl.

Disabled compare_ast#

It suffers from mysterious bugs.

Fixed attribute error in To_Python.go#
Fixed bug in bracket matching#

A recent in doPlainChar change to handle #14 ruined bracket matching.

Fixed bug in rst3 command#

The proper place to init settings is in write_rst_tree. rst.rst3 simply inits the file count, n_written

Fixed crash after ! in tab completion#
File “c:leo.repoleo-editorleocoreleoKeys.py”, line 414, in auto_completer_state_handler

kind), color=’red’)

TypeError: putStatusLine() got an unexpected keyword argument ‘color’

Fixed crash in autocomplete (with backspace key?)#
Fixed crash in elisp importer#

It can now import demo-it.el.

Fixed date in About Leo dialog#
Fixed problem when ~/.leo/workbook.leo does not exist#

Changed LM.openEmptyWorkBook and LM.computeWorkbookFileName.

Fixed recursive import problems#

The new code uses the new importer code to clean nodes.

Fixed several importer bugs#
  • Passing parent=None to ic.createOutline puts the imported node as the last top-level node. Changed ic.create_top_node, ic.setDefaultDirectory and undo.createCommonBunch.

  • g.getEncodingAt now uses a BOM if it exists. No warning is given.

  • ic.scanUnknownFileType no longer adds @ignore. No idea why it ever did.

g.findRootWithPredicate preserves node order#

This was an irritating hangnail that affected, for example, the pylint command.

g.openUrlOnClick now catches all exceptions#

g.openUrlOnClick now catches all exception.

More generally, added @g.callback decorator, which does the same.

The pylint command now runs files in the expected order#

g.findRootsWithPredicate now preserves node order.

Code#

Added BackgroundProcessManager class#

https://groups.google.com/d/msg/leo-editor/kmj7wQq7qTk/5U9hSTswBQAJ

The singleton g.app.backgroundProcessManager instance of the BackgroundProcessManager (BPM) class handles all details of running separate processes in the background without blocking Leo.

The BPM manages a queue of background processes, and runs them one after another in the background. It registers a handler with the IdleTimeManager that checks to see if the presently running background process has completed. If so, it writes its output to the log and starts another background process in the queue.

Because only one background process from the queue is ever running, the background processes can write their output to Leo’s log without the output becoming intermixed.

You can kill all processes by calling BPM.kill(). That’s what kill-pylint does. You can add processes to the queue at any time. For example, you can rerun the pylint command while a background process is running.

The BackgroundProcessManager is completely safe: all of its code runs in the main process.

Added four new generators#

c.all_roots, c.all_unique_roots, p.nearest_roots, p.nearest_unique_roots (aka p.nearest)

Useful for finding nodes on which to run commands.

def nearest_roots(self, predicate=None):

‘’’ A generator yielding all the root positions “near” p1 = self that satisfy the given predicate. p.isAnyAtFileNode is the default predicate.

The search first proceeds up the p’s tree. If a root is found, this generator yields just that root.

Otherwise, the generator yields all nodes in p.subtree() that satisfy the predicate. Once a root is found, the generator skips its subtree. ‘’’

Added g.findRootWithPredicate#

Added g.findRootWithPredicate, an important helper. Used it to greatly rst.processTopTree, pyflakes.run, and pylint.run. This improves the rst3 command

Leo’s pyflakes and pylint commands can be applied to files that depend on the presently selected node. They first search down c.p’s tree, then up the tree, looking for @<file> nodes. If no nodes are found, and c.p is a clone, these commands expand the search to the entire tree, looking for an @<file> node that has c.p in its tree.

g.findRootWithPredicate now formalizes and regularizes this search process. For example:

def predicate(p):
    return p.isAnyAtFileNode() and p.h.strip().endswith('.py')

roots = g.findRootsWithPredicate(c, root, predicate)

I added this helper because the rst3 command was not as clever as the pylint and pyflakes commands in this regard. Now it is. It would have been unbearable to repeat the pylint/pyflakes code one more time…

Here is g.findRootWithPredicate:

def findRootsWithPredicate(c, root, predicate):
    '''
    Commands often want to find one or more **roots**, given a position p.
    A root is the position of any node matching a predicate.

    This function formalizes the search order used by the pylint, pyflakes and
    the rst3 commands, returning a list of zero or more found roots.
    '''
    roots = set()
    # 1. Search p's tree.
    for p in root.self_and_subtree():
        if predicate(p):
            roots.add(p.copy())
    if roots:
        return list(roots)
    # 2. Look up the tree.
    for p in root.parents():
        if predicate(p):
            return [p.copy()]
    # 3. Expand the search if root is a clone.
    clones = []
    for p in root.self_and_parents():
        if p.isCloned():
            clones.append(p.v)
    if clones:
        for p in c.all_positions():
            if predicate(p):
                # Match if any node in p's tree matches any clone.
                for p2 in p.self_and_subtree():
                    if p2.v in clones:
                        return [p.copy()]
    return []
Added IdleTimeManager#

https://groups.google.com/d/msg/leo-editor/hJWv-nL-9s0/2QbaGBgtBQAJ

leoApp.py now contains the IdleTimeManager (ITM) class, with a singleton instance, g.app.idleTimeManager. This class handles all details of running code at idle time, including running ‘idle’ hooks.

The new encapsulation has simplified code all over Leo:

  • ITM ivars replace several LeoApp ivars.

  • LM.load now calls g.app.idleTimeManager.start() to start idle-time processing, leaving all the details to the ITM class.

  • The g.idle time functions in leoGlobals.py now simply set g.app.idle_time_hooks_enabled. This is the only other remaining LeoApp ivar pertaining to idle-time processing.

  • To schedule code for running at idle time, code calls g.app.idleTimeManager.add_callback(callback).

Details

leoApp.py: - ITM.on_idle now handles idle-hooks. - Removed g.app.idle_timer. - ‘idle’ hooks called if and only if g.app.idle_time_hooks_enabled is True. - Only one timer is ever started by Leo: g.app.idle_time_manager_timer. - Removed call to g.enableIdleTimeHook in at the end of LM.doPostPluginsInit.

It is not needed: g.app.idle_time_hooks_enabled is True initially.

  • The enable/disable/toggle-idle-time-events commands now just set g.app.idle_time_hooks_enabled.

leoGlobals.py: - g.enable/disableIdleTimeHook now just set g.app.idle_time_hooks_enabled.

They remain for compatibility only.

  • g.idleTimeHookHandler is now a stub. It just prints a warning. The original has been moved to the attic (leoNotes.txt).

All generators yield copies of positions#

All of Leo’s generators yielding positions automatically yield copies of those positions. The following works as expected:

aList = [p for p in c.all_positions()]

There is no longer any need to do this:

aList = [p.copy() for p in c.all_positions()]

Of course, copied positions will typically become invalid when the outline changes, so some care is needed.

Created g.handleUnl#

Fixed a horrible bug in g.handleUrl that opened a file browser by mistake. All tests pass.

  • Add g.handleUnl, that can never open a browser.

  • g.recursiveUNLSearch selects the desired at idle time.

  • sf.find_setting no longer puts up a wonky dialog.

  • sf.find_setting calls g.handleUnl instead of g.handleUrl.

  • sf.copy_to_my_settings copies the settings tree only if it doesn’t exist.

Replaced c.nullPosition() by None#

Leo’s core code now uses None instead of c.nullPosition(). c.p can be None during startup, which necessitated a few new guards. As a result, the following are all valid tests:

if not p: # Correct, pre-Leo 5.5. if not p.v: # Correct, pre-Leo 5.5 if p is not None # Correct, Leo 5.5 and later. if p is None: # Correct, Leo 5.5 and later.

Now that these tests “just work”, there is no need to document them in the scripting tutorial.

Most changed methods are in the startup logic:

*.injectIvars c.redraw NullTree.edit_widget QtStatusLineClass.update

And a few others:

c.executeScriptHelper EditBodyTestCase.ctor

Rewrote FreeMindImporter class#

The new code works, and is much simpler than the old.

Simplified Leo’s read/write helpers#

An important simplification of the leoGlobals functions that read files into strings. All tests pass.

Most calls to g.readFileIntoString and g.readFileIntoEncodedString contain no keyword args.

  1. Removed the ‘mode’ and ‘raw’ keyword args from g.readFileIntoString.

    g.readFileIntoString is the most important helper. Simplifying it helps a lot.

  2. at.compareFiles calls g.readFileIntoEncodedString instead of g.readFileIntoString(raw=True)

  3. Removed keyword args with default values:
    • leoImport.py: Removed unnecessary encoding arg from call to readFileIntoString.

    • Removed unnecessary “silent” args in two call to g.readFileIntoEncodedString

Documentation#

Added new entries to the plugins documentation#

Slideshows, screencasts & screenshots

demo.py

Creates slides, screen shots and slide shows, replacing screencast.py, screenshots.py and slideshow.py

User Interface

bookmarks.py

Manages bookmarks using a separate pane.

dragdropgoodies

Dumps files dropped into Leo.

python_terminal.py

Embeds an python interpreter in Leo’s log pane.

QNCalendarWidgets.py

Adds a calendar widget.

richtext.py

Enables rich text using the CKEditor editor.

settings_finder.py

Adds the Edit Settings menu tree to the Settings menu.

systray.py

Adds Leo to the system tray.

wikiview.py

Hides/shows parts of urls in the body editor.

Files and nodes

jinjarender.py

Renders @jinja nodes.

leoOPML.py

Read and write .leo files in OPML.

notebook.py

Adds a QML notebook.

Commands and directives

codewisecompleter.py

Uses the ctags database to provide an autocompletion list.

ctagscompleter.py

Uses ctags to provide an autocompletion list.

ftp.py

Supports uploading of files via ftp.

gitarchive.py

Stores snapshots of outline in git.

leofeeds.py

Reads from rss, atom or other sources.

leomail.py

Sync local mailbox files over to Leo.

markup_inline.py

Adds commands that create bold, italic or underlined text.

nodediff.py

Provides commands to run text diffs on node bodies within Leo.

sftp.py

Adds @edit-like functionality for remote files over SFTP.

threadutil.py

Adds utilities for asynchronous operation of commands.

xml_edit.py

Adds commands for importing and exporting xml to and from Leo outlines.

Features#

#257: chapter-select-forward/back#

leo-editor/leo-editor#257

#349: Added –load-type=LOAD_TYPE command-line option#

leo-editor/leo-editor#349 Command line option to select type of @<file> node to when opening non-outline files

#356: Scripting docs for hew users#

The scripting tutorial contains a few more examples before jumping into the details.

#379: Removed many never-used commands#

leo-editor/leo-editor#379

  • Removed all abbrev-* commands except abbrev-kill-all and abbrev-list.

  • Removed all chapter-* commands except chapter-select and chapter-select-main.

    https://groups.google.com/d/msg/leo-editor/-mv2x_6TAdM/Bgntt7b9AgAJ

  • Removed all macro-* commands.

  • Removed all register-* commands.

  • Removed the following commands:

    advertised-undo digit-argument negative-argument number-command number-command-0 … number-command-9 universal-argument

Note: Leo 5.4 previously removed all buffer-* and register-* commands.

#438: Allow script abbreviations in headlines#
<Alt-X>99 is the same as <Alt-G>99#
Added decluttering of headlines#

Decluttering replaces @clean, @file, etc. by icons in headlines. This reduces screen space. The setting: @bool tree-declutter = True enables decluttering. The setting, @data tree-declutter-patterns should contain patterns like:

# remove @clean and use an icon
RULE ^@clean (.*)
REPLACE \1
ICON file_icons/file_clean.png

# show the last part of long filenames
RULE ^.{1,1000}([/\\])(.{25})
REPLACE …\1\2

# if the node name starts with 'peacock node DEMO', make a mess of it
RULE ^(peacock node DEMO)
REPLACE LOOK: \1
ICON Tango/16x16/emotes/face-grin.png
ICON Tango/16x16/emotes/face-wink.png
FG @solarized-magenta
BG white
FONT Times
PX 40
ITALIC 1
WEIGHT Bold
Added justify-toggle-auto and autojustify-on-at-start#

Here’s the commit message for 05df9ac

add @cmd justify-toggle-auto and @bool autojustify-on-at-start

The @int autojustify behavior is very useful for writing prose (not code) when you want text wrapped at a particular column with a real newline, not just visually wrapped at the window edge. To be usable it needs a command to toggle activation, and a setting to decide whether it’s on by default, this commit adds those.

The setting @int autojustify itself has been around for a while, I’d forgotten about it, I’ve been wanting this feature for years, made a failed attempt to add it once, but just (re)discovered the when I realized how it should be done, and found that it already was :-)

More discussion here: leo-editor/leo-editor#14

Added leo/Icons/transparent folders and icons#

Thanks to Tsuchi Noko for these.

Added open-themes-leo command and corresponding menu item#

It opens leo/config/themes.leo.

Added several new scripts and @button nodes to scripts.leo#

See The “What’s new in this file” node in scripts.leo for details.

leoDist.leo appears in the File menu#
Added reload-settings and reload-all-settings commands#
Rewrote leomail plugin#

The leomail plugin reads .mbox mail archive files into a tree of Leo nodes. This saves a lot of work.

Google “<your favorite mail client> archive to mbox” for instructions on generating .mbox files.

The new code contains the following improvements:

  1. It works with both Python 2 and 3. The old code could corrupt .leo files by including strings that the sax parser barfed on. The new code appears safe to use. The conversion involved tricky details in libraries, as well as the usual cursed bytes/string/unicode issues.

  2. The new code organizes messages by threads. Messages that start with “re:” become children of the node that started the thread.

  3. Better warning and informational messages, and a better docstring.

The markdown importer now regularizes sections#

https://groups.google.com/d/msg/leo-editor/8moMUEOOgWA/HE0cl-aADQAJ

Leo’s markdown importer converts all sections to use ‘#’ markup. The technical justification appears at the bottom of the page for #342. The rest of this post explains the change from a user’s point of view.

tl;dr: Converting all sections to ‘#’ markup is Leonine, simplest and best. Only existing .md files that Leo didn’t write could be changed. If such changes don’t work for you, just insert @ignore yourself when git or diff reports differences.

Imo, this change is fully justified:

  1. It is more Leonine.

When creating and changing .md files from within Leo, @auto-md works much more smoothly. Indeed, as I have just verified, converting an @nosent x.md file to @auto-md x.md “just works”.

There is absolutely no reason to use underlined sections when using Leo. The headlines proclaim the section structure far better than flat text of any kind, whether ### section name or underlined section names.

  1. Perfect import check should not wag the dog.

The markdown importer is one of the simplest of all. The possibility of dropping data seems remote. Requiring a typical perfect import check to pass would preclude regularizing section markup. It’s just that simple.

Furthermore, the existing unit tests for the markup importer do check imported section structure, albeit imperfectly That should suffice for now. In the unlikely event that real problems are reported, these after-the-fact unit tests can be improved.

Summary

Importing markdown files containing underlined sections could only pass typical perfect import checks if existing underlining were somehow retained. That’s a bad idea. Instead, Leo’s markdown importer now implicitly converts all sections to ‘#’ markup. In essence, the markup disappears from the outline, to be automagically reinserted when Leo writes the outline.

This new scheme can change existing .md files, but only files that Leo didn’t write. If that is inconvenient for you, just add @ignore yourself.

VR supports @jupyter#

https://groups.google.com/d/msg/leo-editor/L4EAfY7NJbw/NgSv5zSDEwAJ

This is buggy.

Settings and command-line options#

Settings:

  • @bool autojustify-on-at-start

  • @bool color-doc-parts-as-rest

  • @bool run-pyflakes-on-write

  • @bool tree-declutter = True

  • @data tree-declutter-patterns

Command-line options:

--load-type=LOAD_TYPE
--fail-fast             # sets failfast option in unit tests.

Leo 5.6 release notes#

Leo 5.6 September 25, 2017

[Leo](https://leo-editor.github.io/leo-editor/) 5.6 is now available on [SourceForge](https://sourceforge.net/projects/leo/files/Leo/) and on [GitHub](leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](https://leo-editor.github.io/leo-editor/preface.html).

Simulating Leo’s features in Vim, Emacs or Eclipse is possible, just as it is possible to simulate Python in assembly language…

The highlights of Leo 5.6

  • The cursesGui2.py plugin creates a console gui for Leo.

  • Added “Yes to All” and “No to All” buttons to file-changed dialog.

  • Improved how Leo switches between git branches.

  • Created outline-oriented git-diff command.

Links

major features#

For a list of all enhancements added in Leo 5.6, see this page: leo-editor/leo-editor#issues

#488: Created a console gui for Leo#

A new chapter in Leo’s documentation: https://leo-editor.github.io/leo-editor/console-gui.html

leo-editor/leo-editor#488

#501: git-diff command#

leo-editor/leo-editor#501

The new git-diff command shows the diffs between any uncommitted work and git’s HEAD in an outline. This is, by far, the best outline-oriented diff in Leo’s history. The command works for all kinds of external files.

Outline organization

This command creates a single tree as the last top-level node of the outline:

- git diff  # The single organizer node for the command
  - file A  # The organizer node for file A.
            # Body contains the text diff of the entire file.
    - Added # An organizer node for all added nodes, created only if necessary.
      - node 1 # A copy of the first added node.
      - node 2 # A copy of the second added node.
          ...
    - Deleted  # An organizer node for all deleted nodes, created only if necessary.
      - node 1 # A copy of the first deleted node.
          ...
    - Changed  # An organizer node for all changed nodes, created only if necessary.
      - node 1 # An organizer node for the changed node.
               #  Body contains the text diff of that node.
        - old: node1 # A copy of the old node.
        - new: node1 # A copy of the new node.

This command does not use git diff in any way. For example, moving a node affects only the overall diff in the organizer node for the file. Moved nodes do not otherwise appear in the diff.

Text diffs

Organizer nodes for files and changed nodes contain text diffs. Diffs look like this:

@language patch

--- HEAD
+++ uncommitted
@@ -553,8 +553,8 @@
             c1 = self.make_outline(fn, s1, self.rev1)
             c2 = self.make_outline(fn, s2, self.rev2)
             assert c1 and c2
-            for p in c1.all_positions():
-                print('%25s %s' % (p.gnx, p.h))
+            # for p in c1.all_positions():
+                # print('%25s %s' % (p.gnx, p.h))
             self.make_diff_outlines(fn, c1, c2)
             # try:
                 # c.disable_redraw()
@@ -578,6 +578,7 @@
...
@language python

Settings

leoSettings.leo contains new colorizer settings for @language patch.

Theory of operation

For each diffed file, this command uses a variant of the atFile read logic to create the corresponding outline in a hidden commander. Separate hidden commanders contain the “before” and “after” versions of the file. These outlines preserve gnx’s, so it is easy to create dicts of inserted, deleted and changed nodes. The command uses difflib (not git diff) to create all diffs, after the external file has been split into nodes.

#505: Leo switches between git branches properly#

leo-editor/leo-editor#505

The new code eliminates hidden time bombs when switching branches.

Changes to read/write code: - at.writeAll writes files at most once. - at.write updates cache. Previously only at.read updated the cache! - at.deleteUnvisitedNodes no longer creates resurrected nodes. - at.new_createThinChild4 always updates headlines. - at.terminateBody just sets v.tempRoots.

It no longer calls at.indicateNodeChanged.

  • fc.handleNodeConflicts reports changed headlines differently.

Changes to cacher code: - Added cacher.checkForChangedNodes. - Added tempRoots logic. - Added always_warn switch to cacher.reportIfNodeChanged.

Added “yes/no to all” buttons for externally changed file dialog#

Rev 9c94fec36d adds Yes / no to all on external file changes.

If you answer yes to all or no to all Leo remembers that answer for 3 seconds. As a result, another set of external changes will show the pop up again.

bugs#

For a list of all bugs fixed in Leo 5.6, see this page: leo-editor/leo-editor#issues

#541: Editor does not open when using pythonw#

leo-editor/leo-editor#541

#508: console gui: print-cmd-docstrings#

leo-editor/leo-editor#508

#504: console gui: console issues#

leo-editor/leo-editor#504

#317: Viewrendered pane loses live-render feature#

leo-editor/leo-editor#317

#385: Leo doesn’t remember new headlines after saves#

leo-editor/leo-editor#385

#386: colorize markdown properly#

leo-editor/leo-editor#386 All changes made to leo/modes/md.py

#438: Tree abbreviation placeholders in headlines…#

leo-editor/leo-editor#438

#449 & #470: Spontaneous node generation#

leo-editor/leo-editor#470

See also: leo-editor/leo-editor#449 The original fix was in i.run in linescanner.py.

#451: refresh-from-disk selects wrong node#

leo-editor/leo-editor#451 refresh-from-disk doesn’t always restore focus to the correct node

  • at.readOneAtAutoNode returns the new position.

  • c.refreshFromDisk selects that position.

#452: goto-global-lines can fail#

leo-editor/leo-editor#452

#453: Focus jumps to body when expanding abbrev in a headline#

leo-editor/leo-editor#453 Focus jumps to de body pane when expanding an abbreviation in a headline.

The fix was in find_place_holder. It should not set focus if no placeholder found.

#458: Chapters drop-down list is not automatically resized#

leo-editor/leo-editor#458 Set a Qt flag in tt.createControl.

#459: Missing end-of-line characters at the Log Pane#

Missing end-of-line characters at the Log Pane leo-editor/leo-editor#459

fc.handleNodeConflicts now prints a prominent warning in the log and console if it doesn’t create a recovered-nodes node.

Simplified signon logic and g.pr. - Removed app.signon_printed ivar. - Changed (slightly), the print statements in app.computeSignon. - Changed log message in app.setIDFromFile. - Changed (slightly), the log messages in app.writeWaitingLog. - Greatly simplified g.pr and codewise variant. They no longer queue messages. - Rewrote bridge.getLeoID() and app.setLeoID() without using sections.

#466: Moving a node can cause temporary coloring issues#

leo-editor/leo-editor#466

  • Added LeoHighlighter.force_rehighlight.

  • Rewrote ‘recolor’ command (c.force_recolor).

  • Rewrote c.recolor_now.

  • Added calls to c.recolor_now to c.moveOutline*.

Reverted leo_h.force_rehighlight.

​2017-04-28 06:34:10.

leoColorizer.py: - Inserted force_rehighlight

leoCommands.py: - Replaced c.updateSyntaxColor(p) with c.recolor_now(p) in 4 move commands. - Lines 4629, 4661, 4689, 4759, etc.

#471: UnicodeDecodeError in writeRecentFilesFileHelper#

UnicodeDecodeError in writeRecentFilesFileHelper leo-editor/leo-editor#471

The fix was in rf.writeRecentFilesFileHelper.

#472: @clean nodes stopped updating#

leo-editor/leo-editor#472

Solved: the checks are made only if @bool check_for_changed_external_files = True

Changed code in efc.on_idle and efc.idle_check_commander.

#476: (error in cacher.fileKey)#

leo-editor/leo-editor#476

#479: Preserve brython indentation…#

leo-editor/leo-editor#479 Preserve brython indentation when importing .html files

#481: The python importer optionally puts method decorators in headlines#

leo-editor/leo-editor#481

#487: g.IdleTime docstring#

leo-editor/leo-editor#487

#498: –session-restore option fails if no leo.session exists#

leo-editor/leo-editor#498

With a new installation of Leo there is no leo.session file. It is apparently created only after using the –session-save command line option.

If the –session-restore option is also used before that file is created, then Leo fails to open (splash screen displays, then nothing else happens).

#505: Leo’s read code must be rewritten#

leo-editor/leo-editor#505

This was the new-read branch.

The new code eliminates hidden time bombs when switching branches.

Changes to read/write code: - at.writeAll writes files at most once. - at.write updates cache. Previously only at.read updated the cache! - at.deleteUnvisitedNodes no longer creates resurrected nodes. - at.new_createThinChild4 always updates headlines. - at.terminateBody just sets v.tempRoots.

It no longer calls at.indicateNodeChanged.

  • fc.handleNodeConflicts reports changed headlines differently.

Changes to cacher code: - Added cacher.checkForChangedNodes. - Added tempRoots logic. - Added always_warn switch to cacher.reportIfNodeChanged.

#510: Improved how Leo handles settings#

leo-editor/leo-editor#510

No real changes were made. Plugins should not create bindings by calling k.registerCommand. Such bindings happen “too late” in the startup process to be over-ridden in settings files. Instead, plugins can define suggested bindings in leoSettings.leo.

Note: The mod_scripting plugins creates bindings from @button and @command nodes. Again, these are “late” bindings that can not be over-ridden in settings files. I don’t believe this is a big problem. The problem arises because Leo loads plugins after loading all outlines. It’s not a direct consequence of using settings files.

Leo now has two new command-line options. These provide more detail than the print-binding or show-settings commands, but only for a single setting or binding. Examples:

--trace-setting=http-port

# setting name

--trace-setting=cff

# command name

--trace-binding=shift-ctrl-f

# key binding

#516: Content of find tab can disappear#

leo-editor/leo-editor#516

#516: Content of find tab can disappear#

leo-editor/leo-editor#516

#522: cycle-editor-focus raises ValueError#

leo-editor/leo-editor#522

#529: help-for-settings and docs for @menu and @item in leoSettings.leo#

leo-editor/leo-editor#529

#537: Non-ascii characters in leo.core.commit_timestamp.json crashes Leo#

leo-editor/leo-editor#537

See also: How to make Unicode charset in cmd.exe by default? https://stackoverflow.com/questions/14109024

#62: Syntax @color settings don’t dereference#

leo-editor/leo-editor#62

Ensure that .leo/.leoRecentFiles.txt is closed#

leo-editor/leo-editor#497

Rewrote rf.createRecentFiles, rf.readRecentFilesFile and rf.writeRecentFilesFileHelper.

Fixed bug in k.computeInverseBindingDict#

The bug gave way too many bindings for the move-lines commands.

Fixed bug in tab completion#

ga.show_tab_list wasn’t showing commands without any shortcuts!

Fixed bugs re plugins registration#

Fixed plugins.registerOneHandler and plugins.registerOneExclusiveHandler

Fixed html import problem#

The unit test “@test xml non-ascii tags” failed on Python 2, but not Python 3.

The fix was in xml_i.scan_tag & helper

Fixed serious bug in c.checkFileTimeStamp#

It must return True if g.app.externalFilesController is None.

Fixed several problems with goto-global-line#
The pylint command now warns if pylint has not been installed#

The change was to pylint.run_pylint.

This removes a major source of confusion.

code#

#505: Leo’s read code must be rewritten#

leo-editor/leo-editor#505

The new code eliminates hidden time bombs when switching branches.

Changes to read/write code: - at.writeAll writes files at most once. - at.write updates cache. Previously only at.read updated the cache! - at.deleteUnvisitedNodes no longer creates resurrected nodes. - at.new_createThinChild4 always updates headlines. - at.terminateBody just sets v.tempRoots.

It no longer calls at.indicateNodeChanged.

  • fc.handleNodeConflicts reports changed headlines differently.

Changes to cacher code: - Added cacher.checkForChangedNodes. - Added tempRoots logic. - Added always_warn switch to cacher.reportIfNodeChanged.

#512: unit tests are failing for Terry#

leo-editor/leo-editor#512

#539: Redesigned Leo’s redraw code#

leo-editor/leo-editor#539

Redrawing the screen happens only as the result of an explicit call to c.redraw. In particular, neither c.selectPosition nor its helpers redraw the screen.

c.redraw_later() sets a flag requesting that c.outerUpdate call c.redraw if necessary. Any call to c.redraw resets this flag. cc.selectChapterForPosition calls c.redraw_later.

c.disable_redraw() sets a flag disabling all outline redraws. c.enable_redraw() re-enables redrawing. This is similar to the old begin_update/end_update scheme, but simpler and more explicit. Use this as follows:

try:

c.disable_redraw() # Code that might otherwise redraw the tree.

finally:

c.enable_redraw()

c.outerUpdate has been drastically simplified. It no longer handles requests for redraws, recoloring, bring-to-front or de-iconification. It now handles requests for delayed focus changes and delayed redraws. It also handles “childrenModified” and “contentModified” hooks.

Added ‘recursive’ keyword arg to recursive import API#

Added ‘recursive’ keyword arg to c.recursiveImport and RecursiveImportController ctor. Recursive is not the same as not one_file.

Added better checks in v.setBodyString & v.setHeadString#
Added g.Git functions#

leoGlobals.py the following functions and their helpers in the .Git subtree:

  • branch, commit = g.gitInfo(path = None)

  • date, build = g.jsonCommitInfo()

  • branch = g.gitBranchName(path = None)

  • commit = g.getCommitNumber(path = None)

The path should be a folder containing a .git subfolder. If the path is None, the leo-editor folder is used.

Leo’s cacher code will soon use the branch name returned by g.gitInfo() to ensure that switching git branches works properly.

As a happy side effect, these methods completely collapse the complexity of leoVersion.py.

Added gen_refs keyword arg to Importer ctor#

This makes explicit which importers actually generate section reference. At present, only the javascript importer sets this arg.

Added traces to c.doCommand to detect multiple redraws#

These traces detected nothing unusual and have been disabled.

Improved @auto write code#
  • Removed the allow_at_auto_section switch in leoAtFile.py.

  • When writing @auto files << handle line at s[i] >> in at.putBody now expands section references in @auto files if they are defined. Otherwise, lines containing undefined section references are written as plain code lines.

Removed atAuto switch from atFile class#

Ding dong, the switch is dead, the wicked old switch is dead.

20 years of lint removed from leoAtFile.py: https://groups.google.com/d/msg/leo-editor/o5GtCDCZDSo/KO__cZZ-AAAJ

Updated docs re #464#

leo-editor/leo-editor#464

Warning: The p.b and p.h setters and p.setDirty() are very expensive:

  • p.b = s calls c.setBodyString(p, s) which will recolor body text and update the node’s icon.

  • p.h = s calls c.setHeadString(p, s) which calls p.setDirty().

  • p.setDirty() changes the icons of all ancestor @file nodes.

In contrast, the corresponding p.v.b and p.v.b setters and p.v.setDirty() are extremely fast.

Usually, code should use the p.b and p.h setters and p.setDirty(), despite their cost, because they update Leo’s outline pane properly. Calling c.redraw() is not enough.

These performance gotchas become important for repetitive commands, like cff, replace-all and recursive import. In such situations, code should use p.v.b and p.v.h setters instead of p.b and p.h setters.

Use ‘with’ statement to simplify code#

Improved g.SherlockTracer.do_line, g.gitInfo, g.is_binary_external_file, g.log, g.readFileToUnicodeString.

commands#

#185: Added edit-recent-files and write-edited-recent-files commands#

leo-editor/leo-editor#185

The edit-recent-files command creates a new last top-level node containing a list of all recent files as they appear in the File:Recent File menu.

The write-edited-recent files command writes the body text node to leoRecentFiles.txt. The command assumes that the user has not changed the headline of the node created by the edit-recent-files command.

#456: replace-all command is much faster#

leo-editor/leo-editor#456

Made several changes to find.batchChange.

#482: Added toggle-auto-edit command#

leo-editor/leo-editor#482

This command is surprisingly useful. It toggles between a flattened view (@edit) and an outline view (@auto) of an external file containing no sentinels.

This command preserves the presently selected line when flattening/un-flattening the outline. You can run this command from any descendant of an @auto node.

@cmd(‘toggle-at-auto-at-edit’) def toggleAtAutoAtEdit(self, event):

‘’’Toggle between @auto and @edit, preserving insert point, etc.’’’ p = self.c.p if p.isAtEditNode():

self.toAtAuto(p) return

for p in p.self_and_parents():
if p.isAtAutoNode():

self.toAtEdit(p) return

g.es_print(‘Not in an @auto or @edit tree.’, color=’blue’)

efc.toAtAuto#
def toAtAuto(self, p):

‘’’Convert p from @edit to @auto.’’’ c = self.c # Change the headline. p.h = @auto’ + p.h[5:] # Compute the position of the present line within the file. w = c.frame.body.wrapper ins = w.getInsertPoint() row, col = g.convertPythonIndexToRowCol(p.b, ins) # Ignore preceding directive lines. directives = [z for z in g.splitLines(c.p.b)[:row] if g.isDirective(z)] row -= len(directives) row = max(0, row) # Reload the file, creating new nodes. c.selectPosition(p, enableRedrawFlag=False) c.refreshFromDisk() # Restore the line in the proper node. c.gotoCommands.find_file_line(row+1) p.setDirty() c.setChanged() c.redraw() c.bodyWantsFocus()

efc.toAtEdit#
def toAtEdit(self, p):

‘’’Convert p from @auto to @edit.’’’ c = self.c w = c.frame.body.wrapper p.h = @edit’ + p.h[5:] # Compute the position of the present line within the selected node c.p ins = w.getInsertPoint() row, col = g.convertPythonIndexToRowCol(c.p.b, ins) # Ignore directive lines. directives = [z for z in g.splitLines(c.p.b)[:row] if g.isDirective(z)] row -= len(directives) row = max(0, row) # Count preceding lines from p to c.p, again ignoring directives. for p2 in p.self_and_subtree():

if p2 == c.p:

break

lines = [z for z in g.splitLines(p2.b) if not g.isDirective(z)] row += len(lines)

# Reload the file into a single node. c.selectPosition(p, enableRedrawFlag=False) c.refreshFromDisk() # Restore the line in the proper node. ins = g.convertRowColToPythonIndex(p.b, row+1, 0) w.setInsertPoint(ins) p.setDirty() c.setChanged() c.redraw() c.bodyWantsFocus()

#495 and #496: jump/push commands#

leo-editor/leo-editor#495 Leo already supports the point and mark.

leo-editor/leo-editor#496

Added ec.pushCursor and ec.popCursor. Added ec.finishOfLine & ec.startOfLine & extend variants. Extended ec.moveWithinLineHelper.

beginning of line is before first character in line start of line is first nonwhite space text finish of line is last nonwhite space text end of line is after last character in line

navigating to these points is useful when using speech recognition and is frequently useful when creating macros to operate on text. Jump means you go to the location without remembering where you were. Push means remembering, in a stack, where you were and being able to return to that location with a pop command.

The push/pop model works well with speech recognition because you don’t have to give explicit navigation commands. You just go back to where you were.

#529: Added help-for-settings command#

leo-editor/leo-editor#529

Added goto-any-clone command#

Searches from c.p for any clone, not just a clone of c.p. Useful for eliminating all clones from a .leo file.

This command is different from goto-next-clone as follows:

  • goto-any-clone goes to the next clone, regardless of whether c.p is a clone.

  • goto-any-clone does not wrap. It prints a message when no clones remain.

Added listen-to-log and other commands#

How to debug npyscreen apps using two consoles: https://groups.google.com/forum/#!topic/npyscreen/nk2pjj71bok

The log-listen (aka listen-to-log) and kill-log-listen (aka, listen-log-kill) commands implement this logging cookbook recipe: https://docs.python.org/2/howto/logging-cookbook.html#sending-and-receiving-logging-events-across-a-network

The log-listen command creates a logging listener whose output goes to Leo’s console. The listener runs in a separate process so that Leo doesn’t hang.

Start the listener first, then start another process in another console. All logging output from the second process will be captured and displayed by the listener, provided that the second process includes a call to rootLogger.addHandler(socketHandler).

leo/external/log_broadcast.py contains example code. leo/plugins/cursesGui2.py uses this pattern to broadcast g.trace.

Added push-cursor and pop-cursor#

push-cursor Saves the location of the cursor, including node(position) on a stack. pop-cursor Restores the cursor position from the stack.

Added show-color-names command#
Added start-of-line/finish-line commands#

start-of-line Puts cursor at first non-blank character of the line. finish-line Puts the cursor at before the last non-blank character of the line.

The finish-line-extend-selection and start-of-line-extend-selection commands move the cursor and extend the selection range.

The finish-line command could put the cursor after the last non-blank character of the line, but that’s pretty much what end-of-line does.

clone-find commands report number of matches in root node#

Changed find.createCloneFindAllNodes and c.cloneFindMarkedHelper.

Improved indent-region and unindent-region commands#

https://groups.google.com/d/msg/leo-editor/SUnqs1_YbeI/DIv0EbtFCgAJ

The indent-region and unindent-region just move the insert point if there is no text selected.

Improved move-lines-up/down commands#

These commands (bound to ctrl-up/down by default) now work at the top or bottom of the body pane. The move-lines-up command inserts a new line below the moved line/lines when the lines are at the top of the body text. Similarly, the move-lines-down command inserts a line before the moved lines when at the bottom of the body text. Imo, this is a natural and useful.

valuescript plugin now supports vs-eval-block command#

importers#

#479: Revised xml/html importers#

leo-editor/leo-editor#479 Preserve brython indentation when importing .html files

The new code is simpler and handles dubious html syntax.

Added importer for the lua language#
Added tcl importer#

other features#

#446: Added vr-zoom command#

leo-editor/leo-editor#446

#448: Add abbreviations for commands#

leo-editor/leo-editor#448

If the expansion of an abbreviation is a command name, that command will be executed. Alas, this isn’t very useful: typing destroys selection ranges.

This took only a few lines of code in abbrev.expandAbbrev.

#478: Allow paste-retaining-clones across different .leo files#

leo-editor/leo-editor#478

#484: Improved Windows menu#

leo-editor/leo-editor#484

Added submenus to Windows menu. This significantly simplifies and clarifies the Windows menu.

#531: file timestamps#

leo-editor/leo-editor#531

Added new settings:

@bool log_show_save_time = False
@string log_timestamp_format = "%H%M%S"

Changed fc.putSavedMessage and at.replaceTargetFileIfDifferent.

Added git branch name to backed-up files#
Added leo_cloud and leo_cloud_server plugins#
Improved “Write Existing File?” dialog#

at.promptForDangerousWrite puts up a dialog with a clearer cancel button.

  • It says “Cancel (No To All)”.

  • Added cancelMessage keyword arg to x.promptForDangerousWrite.

  • Use keyword args in LeoFrame.promptForSave and ns_do_context.

Improved caching#

Rev b32259 transitions to a new caching scheme:

  1. All hashes now use the full path to the external file. Previously, the headline of @file nodes was typically used instead. Surely this might have caused silent problems.

  2. Leo’s hasher now includes the name of the present git branch in the hash. When switching git branches, this in essence disables hashing for all files changed in the previous branch.

Improved operation of command history#

The first UP-arrow to gives the previous command, the next up-arrow gives the next command, etc.

Indicate branch in Window title#

Changed g.computeWindowTitle.

VR renders LaTex (python 2 only)#

https://groups.google.com/d/msg/leo-editor/sBGJr_oHeyk/3eUjoBC0CQAJ

settings & command-line arguments#

#518: Added @bool report_unchanged_files#

leo-editor/leo-editor#518

@bool report_unchanged_files = True

Added –trace-focus command-line argument#
Added @bool color_trailing_whitespace & @color trailing_whitespace_color#

Defaults are:

@bool color_trailing_whitespace = True
@color trailing_whitespace_color = red
Added @bool log_show_save_time & @string log_timestamp_format#

Defaults are:

@bool log_show_save_time = False
@string log_timestamp_format = %H:%M:%S
Added @bool run_pyflakes_on_unchanged_files = True#
Added Ctrl-Shift-< and Ctrl-Shift-> bindings#

These are bound to indent/unindent-region and can be used when no text is selected.

Restored default: @bool check_for_changed_external_files = True#
Retired @bool allow_section_references_in_at_auto#

The disabled setting now contains this comment:

Note: This setting has been retired for the following reasons:

1. The new javascript importer always generate section references for non-trivial programs. As a result, the legacy value for this setting would cause the javascript importer to fail.

2. The new @auto write code writes expands section references if they exist. Otherwise, the write code writes the line as is, without any complaint. As a result, there should be no problem if an imported code contains something that looks like a section reference but isn’t.

screen_capture.py now enabled by default#

Leo 5.7 release notes#

Leo 5.7 final February 27, 2018

Leo 5.7 final, https://leo-editor.github.io/leo-editor/ is now available on [SourceForge](https://sourceforge.net/projects/leo/files/Leo/) and on [GitHub](leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](https://leo-editor.github.io/leo-editor/preface.html).

Simulating Leo’s features in Vim, Emacs or Eclipse is possible, just as it is possible to simulate Python in C or assembly language…

The highlights of Leo 5.7

  • pip install leo.

  • A debian package for Leo.

  • A web-based Leo Viewer, written by Joe Orr.

  • Added diff-leo-files and diff-and-open-leo-files commands. These create outline-oriented diffs for .leo files.

  • New reload-settings command.

  • Leo optionally shows user tips on startup.

  • Added a new Tips page to Leo’s documentation.

  • A visual widget for editing cvs tables.

  • Spell checking works without pyenchant

  • Improved the console_gui plugin.

  • Added live links from urls in the log pane.

  • Unit tests use a string gui, making them faster and more robust.

  • The line_numbering plugin shows line numbers in external files.

  • Improved the javascript importer.

  • Added a TreePad importer.

  • Added 6 new commands.

  • Dozens of bug fixes.

Links

Leo 5.7 Summary#

@nosearch

You can see all 5.7 issues by visiting: leo-editor/leo-editor#issues

Leo 5.7 Major features#

#417: reload-settings command#

leo-editor/leo-editor#417

#503: Use string/null gui for unit tests#

leo-editor/leo-editor#503

TM.doTests now runs all unit tests with string gui (StringTextWrapper class).

This has three advantages:

  1. The tests run much more quickly than before.

  2. Leo does no redraws during the tests.

  3. Clicks in the Leo window can now longer spoil running unit tests.

#562: A PyPi wheel for Leo#

leo-editor/leo-editor#562

#597: Show tips when Leo starts up#

leo-editor/leo-editor#597

#700: Spell checking works without pyenchant#

Leo uses the pyenchant spell checker if it has been installed.

Otherwise, Leo will use a pure python spell checker, provided that a spell dictionary exists at ~/.leo/main_spelling_dict.txt. You may download a compressed version of this dictionary from https://sourceforge.net/projects/leo/files/Miscellaneous/

Added a cvs table editing widget#

The edit-pane-csv command opens a CSV table editor pane. Very useful for editing CSV data in Leo.

Here is a demo: https://youtu.be/hca3x5SXNqs

Added Debian package for Leo#

I’m happy to announce first releases of Leo 5.0 as a debian/ubuntu packages

Please try my builds on your debian based environment:

On Ubuntu :
sudo add-apt-repository ppa:davy39/ppa
sudo apt-get update
sudo apt-get leo

On other Debian based system :
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys B84B2247
sudo add-apt-repository "https://ppa.launchpad.net/davy39/ppa/ubuntu utopic main"
sudo apt-get update
sudo apt-get leo

FYI, Debian no longer uses / supports add-apt-repository. It is my understanding that only ubuntu systems still support this. The procedure I used to successfully install Leo on Debian 8 was the following:

  1. I added the key as instructed above.

  2. I manually added the repository to my /etc/apt/sources.list

  3. the command to install leo I needed was: sudo apt-get install leo

The menu item was found under “Development” and Leo appears to be working just fine.

Added Outline-oriented diffs of .leo files#

The diff-leo-files command diffs arbitrarily many .leo files, two at a time. The diff-and-open-leo-files does the same, and addition opens the diffed files.

The CompareLeoOutlines class in leo/core/leoCompare.py allows scripts to generate outline-based diffs for arbitrarily many .leo files. Previously, only the git-diff command created outline-based diffs.

Here is an example script:

import leo.core.leoCompare as leoCompare
outlines = ['LeoDocs.leo', 'LeoDocs1.leo', 'LeoDocs2.leo']
paths = [g.os_path_finalize_join('~/compare', z) for z in outlines]
leoCompare.CompareLeoOutlines(c).diff_list_of_files(paths)

This script will present three sets of diffs, in a new top-level node whose nodes are as follows:

- outline diff
    Body: LeoDocs.leo, LeoDocs1.leo, LeoDocs2.leo
    - LeoDocs.leo, LeoDocs1.leo
      Body: the entire diff of LeoDocs.leo and LeoDocs1.leo
      - added
        copies of added nodes
      - deleted
        copies of deleted nodes
     - changed
        diff nodes for all changed nodes.
        Body: the diff of each node.
        - LeoDocs.leo: copy of old node
        - LeoDocs1: copy of new node
    - LeoDocs.leo, LeoDocs1.leo
      Ditto
    - LeoDocs1.leo, LeoDocs1.leo
      Ditto

Leo 5.7 Bugs fixed#

Fixed dozens of bugs. See: leo-editor/leo-editor#issues

Leo 5.7 b1: Bugs fixed#

leo-editor/leo-editor#327

leo-editor/leo-editor#362

leo-editor/leo-editor#384

leo-editor/leo-editor#489

leo-editor/leo-editor#493

leo-editor/leo-editor#509

Serious unfixable bugs: https://leo-editor.github.io/leo-editor/console-gui.html#unfixed-bugs

leo-editor/leo-editor#510

leo-editor/leo-editor#528

leo-editor/leo-editor#550

leo-editor/leo-editor#552

leo-editor/leo-editor#553

leo-editor/leo-editor#554

leo-editor/leo-editor#555

leo-editor/leo-editor#556

leo-editor/leo-editor#560

leo-editor/leo-editor#571

This only happens when clicking the link in the VR pane, and only with Python 2.

leo-editor/leo-editor#573

leo-editor/leo-editor#578

leo-editor/leo-editor#579

Added k.remove_conflicting_definitions.

leo-editor/leo-editor#585

leo-editor/leo-editor#586

leo-editor/leo-editor#591

leo-editor/leo-editor#593

leo-editor/leo-editor#595

leo-editor/leo-editor#600

leo-editor/leo-editor#603

leo-editor/leo-editor#604

leo-editor/leo-editor#627

leo-editor/leo-editor#630

leo-editor/leo-editor#634

leo-editor/leo-editor#638

leo-editor/leo-editor#639

leo-editor/leo-editor#640

leo-editor/leo-editor#641

leo-editor/leo-editor#645

leo-editor/leo-editor#648

leo-editor/leo-editor#649

leo-editor/leo-editor#651

leo-editor/leo-editor#652

leo-editor/leo-editor#653

leo-editor/leo-editor#654

leo-editor/leo-editor#656

leo-editor/leo-editor#657

leo-editor/leo-editor#658

The fix was in ni.compute_last_index.

leo-editor/leo-editor#659

leo-editor/leo-editor#661

leo-editor/leo-editor#718

The bug was in LM.computeWorkbookFileName. It’s fine to return the name if the file already exists.

The message came from readFileIntoString:

<module>,run,load,doPostPluginsInit,openEmptyWorkBook,loadLocalFile, openFileByName,initWrapperLeoFile,refreshFromDisk,readOneAtEditNode

Leo 5.7 final: Bugs fixed#

loadOnePlugin: can not load enabled plugin: leo.plugins.viewrendered leo-editor/leo-editor#702

Leo fails to load when pyenchant is not installed leo-editor/leo-editor#707

TypeError: coercing to Unicode: need string or buffer, NoneType found leo-editor/leo-editor#712

TypeError: expected str, bytes or os.PathLike object, not NoneType leo-editor/leo-editor#713

LeoBridge not explicitly closing the Leo-Editor file leaves the Leo-Editor file open leo-editor/leo-editor#716

setup.py broken when installing from zipball: execGitCommand not available leo-editor/leo-editor#720

replace-all can not be saved with crtl + s leo-editor/leo-editor#722

Recover more gracefully from user errors in abbreviations leo-editor/leo-editor#725

help-for-command crashes when vr2 plugin is active leo-editor/leo-editor#734

@rclick buttons not generating commands in work files leo-editor/leo-editor#739

Leo 5.7 Code improvements#

Leo 5.7 b1 Code improvements#

Let reformatting unit tests run in more environments leo-editor/leo-editor#577

In leoSettings.leo:

@int page_width = 80 @int tab_width = -4

In unitTest.leo:

pagewidth = 75: From myLeoSettings.leo tabwidth = -4: From leoSettings.leo

In unitTest.leo:

@pagewidth 40 @tabwidth 8

leo-editor/leo-editor#589

The @g.commander_command decorator injects ivars into the Commands class.

g.findNodeInChildren, g.findNodeInTree, and g.findNodeAnywhere now take an “exact” keyword argument. The default (True) ensures current behavior does not change.

All three methods first look for an exact match, regardless of the exact keyword, just as before. If no match is found, and exact is False, these methods then search again, matching if the given headline is a prefix of the headline of any node.

The signature of c.backup_helper is:

def backup_helper(self, base_dir=None, env_key='LEO_BACKUP', sub_dir=None):

c.backup_helper uses the LEO_BACKUP environment variable as the base of the save if it exists. Otherwise it uses the given base_dir directory. If given, the sub_dir path is applied to the base directory.

This method does careful error checking and reporting. The body text of the following four @button backup nodes are all just one line:

c.backup_helper(sub_dir='leoPy') # In leoPy.leo
c.backup_helper(sub_dir='ekr-projects') # In ekr-projects.leo
c.backup_helper(sub_dir='ekr') # In ekr.leo

Changing just the LEO_BACKUP environment value will change the destination of all these scripts.

g.callers(verbose=True) returns the callers on separate lines, displaying file name, line number and class name. This is especially useful for gui programming, where there may be many ‘display, ‘edit’, ‘redraw’ and ‘update’ methods. It’s also useful where you just don’t have any idea where a function or method resides.

For example, these traces, in BoxTitle.edit:

g.trace('===== (BoxTitle:%s) entry_widget: %s' % (
    self.__class__.__name__,
    self.entry_widget.__class__.__name__))
g.trace('CALLERS', g.callers(verbose=True))

Produce:

trace: edit ===== (BoxTitle:BoxTitleLog) entry_widget: LeoLog
trace: edit CALLERS
  line   32 apNPSApplication.py            LeoApp.__remove_argument_call_main
  line 2711 cursesGui2.py                  LeoApp.main
  line 1632 cursesGui2.py                  LeoCursesGui.run
  line   66 fm_form_edit_loop.py           LeoForm.edit

Each line shows the line number and file containing the function or method. All the above lines show methods.

This project makes major improvements to Leo’s redraw logic with virtually no effect on existing code. The highlights of the changes are as follows:

  1. Redrawing the screen happens only as the result of an explicit call to c.redraw. In particular, neither c.selectPosition nor its helpers redraw the screen immediately. However, cc.selectChapterForPosition ensures that a redraw happens eventually using…

  2. c.redraw_later() sets a flag requesting that c.outerUpdate call c.redraw if necessary. Any call to c.redraw resets this flag.

  3. c.disable_redraw() sets a flag disabling all outline redraws. c.enable_redraw() re-enables redrawing. Use these methods as follows:

    try:
        c.disable_redraw()
        # Code that might otherwise redraw the tree.
    finally:
        c.enable_redraw()
    

This pattern is essential in the new git-diff code. Lots of redraw code changed, but in similar and straightforward ways. In effect, the new code is exactly the same as the old unless c.disable_redraw() has been called, I do not expect problems here.

  1. c.outerUpdate has been drastically simplified. It now only handles requests for delayed focus changes (as before) and the new delayed redraws.

Note: cc.selectChapterForPosition calls c.redraw only if the chapter changes.

  • Added support for c.redraw_later, called from cc.selectChapterForPosition.

  • c.bringToFront now works without using c.outerUpdate.

  • c.widgetWantsFocusNow now just calls c.set_focus & clears c.requestedFocusWidget.

  • c.outerUpdate no longer handles recoloring or redrawing.

  • Replaced all calls to c.recolor_now by c.recolor.

  • Replaced all calls to redraw_now by redraw.

  • Removed all calls to body.forceFullRecolor.

  • Removed forceFullRecolorFlag.

  • Removed c.incrementalRecolorFlag.

  • c.selectPosition never calls c.redraw.

  • Removed c.requestRedrawFlag and c.outerUpdate never calls c.redraw.

fc.resolveArchivedPosition gives errors message only if there have been no read errors (at.errors == 0).

See https://groups.google.com/d/msg/leo-editor/RIwAHLAmq_0/s11zAcbECgAJ.

Leo 5.7 final code improvements#

Added g.execute_shell_commands_with_options.

Leo 5.7 Commands#

#632: check-conventions command#

Status

  1. This project does real checking, something that none of my type-related projects has ever done before. The cc.resolve* methods are simple and straightforward by the standards of tools like pylint and rope. Recent revs have cleaned up these methods a bit.

    From the start, the code has been able to detect violations of naming conventions that neither pylint nor pyflakes are ever going to find. Speed has always been good enough. On my machine the checker checks the 77 of Leo’s sources in about 5.5 seconds. Greater speed would be possible using a one-pass algorithm, but that is not necessary now.

  2. The “before and after” design/coding pattern is a spectacular success. It completely decouples the cc and cct classes. Neither is aware of each other in any way. In effect, before and after methods add to ast node visitors without changing those visitors in any way and without any knowledge of the node visitors.

  3. The present code is sound. It parses the code correctly, and visits nodes in the proper order.

    The initial prototype used regex patterns to do a quick, inaccurate, parse of the file. This strategy allowed me to focus on the cc.resolve* methods first, not later. Imo this was the only way I could have made the progress I did make.

    Recent revs have removed all regex patterns from the code. This could only be done once the cc.resolve methods were in place. Removing regex patterns makes parsing sound, which simplifies code downstream.

  4. The new cc.get_chain helper preprocesses chains like a.b.c or a.b().c or a.b[].c. This method is crucial, for several reasons:

  • It clarifies and simplifies various parts of the code.

  • It reveals the complexity of ast.Attribute trees.

  • It shows just where type inference or convention checking is likely to fail.

None of the benefits of cc.get_chain was obvious to me before creating it.

Summary

The cc command must be extended using @data settings and global patterns. It should also check keyword args.

The check-conventions command is a successful proof of concept:

  • It finds real problems quickly.

  • The code is sound. It parses code properly, and in the proper order.

  • Before and after methods collapse code complexity.

  • It will be easy for me to resume work on this project in future

As a result, this project is at a reasonable stopping point.

To do

  1. [Most important] At present, the check-conventions (cc) command only knows about Leo conventions. Instead, the command should used @data nodes to define conventions.

  2. [Important] The cc command should be able to check global naming conventions. For Leo, this would include the convention that self.c is a Commands object and that g is the leoGlobals module, etc.

  3. [Important] At present the cc command does not check keyword arguments to function calls.

4 [Maybe]
  • improve get_chain?
    • What percentage of chains can be resolved?

    • Use resolve_stack to bound recursion?

  • Add support for global patterns.

  • Support @data nodes.

  • check w, w.wrapper, w.widget?

Added clean-main-user-dict & clean-user-spell-dict#
Added count-children command#
Added demangle-recent-files#

Path demangling potentially alters the paths in the recent files list according to find/replace patterns in the @data path-demangle setting. For example:

REPLACE: .gnome-desktop WITH: My Desktop

The default setting specifies no patterns.

Added edit-pane-csv & edit-pane-test-open#
Added insert-as-first-child & insert-as-last-child commands#

These commands always add the new node as the first/last node of the preceding node, regardless of the setting @bool insert_new_nodes_at_end.

Added read/set/update-ref-file commands#

These commands make it easier to use Leo’s reference .leo files. From time to time, developers needs to open reference Leo file and copy its content to and from their personal file.

These commands use a separation node, a top-level node** whose headline is:

---begin-private-area---

The body of the separation node contains the .leo reference, a path to the reference .leo file. Everything above this node is the public part of the outline. Everything below this node is the private part of the outline.

set-reference-file selects the reference .leo file corresponding to the local .leo file. It creates the separation node if it doesn’t exists, changing the .leo reference as needed.

read-ref-file reads the public part of this outline from the reference .leo file given in the separation node. Warning: This command deletes all nodes above separation node, recreating them from the reference file.

update-ref-file saves public part of this outline to reference .leo file.

You would typically execute the read-ref-file command after any git pull that changes any reference .leo file. Similarly, you would typically execute the update-ref-file command before doing a git commit that changes a .leo file.

Added show-spell-info command#
The cff commands now sort their results#

Leo 5.7 Settings and command-line arguments#

Reinstated –trace-shutdown command-line argument#

This supports the already-existing g.app.trace_shutdown switch. Presumably –trace-shutdown was removed by mistake some time ago.

@bool show-tips#

When True, Leo shows User Tips in a dialog on startup.

Leo 5.7 Enhancements#

Added over two dozen enhancements. See leo-editor/leo-editor#issues

Leo 5.7 b1: Enhancements#

leo-editor/leo-editor#310

As a happy side effect, right clicking now always shows this popup. That’s because “New Outline” is always valid regardless of how many tabs there are and regardless of whether tabs have been detached.

leo-editor/leo-editor#327

This enhancement allows you to override bindings made in leoSettings.leo or myLeoSettings.leo by setting:

command-name = None

in the local .leo file, that is, outside of leoSettings.leo or myLeoSettings.leo. Important: binding:

do-nothing = <key>

does not work. That would eat <key> entirely. Instead, the new code calls k.handleUnboundKeys when it sees any key previously bound to command-name.

What I did: - k.masterKeyHandler handles k.killedBindings. - –trace-binding=BINDING works for bindings or command names. - Removed k.killBinding: it has no chance of working. - Added k.killedBindings, a list of command names for which bindings have been killed in local files. - ParserBaseClass.doShortcuts appends command names k.killedBindings. - Added c.config.isLocalSettingFile

leo-editor/leo-editor#414

leo-editor/leo-editor#417

leo-editor/leo-editor#428

leo-editor/leo-editor#503

leo-editor/leo-editor#510

leo-editor/leo-editor#523

leo-editor/leo-editor#529

leo-editor/leo-editor#552

leo-editor/leo-editor#577

leo-editor/leo-editor#583

leo-editor/leo-editor#584

leo-editor/leo-editor#587

leo-editor/leo-editor#589

leo-editor/leo-editor#596

leo-editor/leo-editor#597

leo-editor/leo-editor#602

leo-editor/leo-editor#613

leo-editor/leo-editor#635

leo-editor/leo-editor#655

leo-editor/leo-editor#674

Syntax coloring is based on C.

Changed qtree.declutter_node.

The code promotes replaces @others with the body text of the node’s child when the node has exactly one child. The singleton child becomes an organizer node without body text whose headline is ‘organizer’.

Later, the importer deletes organizer nodes after promoting their children. This is an iterative process, so that even more @others may be replaced later.

Leo 5.7 b2: Enhancements#

Leo uses the pyenchant spell checker if it has been installed.

Otherwise, Leo will use a pure python spell checker, provided that a spell dictionary exists at ~/.leo/main_spelling_dict.txt. You may download a compressed version of this dictionary from https://sourceforge.net/projects/leo/files/Miscellaneous/

The signature of c.backup_helper is:

def backup_helper(self, base_dir=None, env_key='LEO_BACKUP', sub_dir=None):

c.backup_helper uses the LEO_BACKUP environment variable as the base of the save if it exists. Otherwise it uses the given base_dir directory. If given, the sub_dir path is applied to the base directory.

This method does careful error checking and reporting. The body text of the following four @button backup nodes are all just one line:

c.backup_helper(sub_dir='leoPy') # In leoPy.leo
c.backup_helper(sub_dir='ekr-projects') # In ekr-projects.leo
c.backup_helper(sub_dir='ekr') # In ekr.leo

Changing just the LEO_BACKUP environment value will change the destination of all these scripts.

The diff-leo-files command diffs arbitrarily many .leo files, two at a time. The diff-and-open-leo-files does the same, and addition opens the diffed files.

The CompareLeoOutlines class in leo/core/leoCompare.py allows scripts to generate outline-based diffs for arbitrarily many .leo files. Previously, only the git-diff command created outline-based diffs.

Here is an example script:

import leo.core.leoCompare as leoCompare
outlines = ['LeoDocs.leo', 'LeoDocs1.leo', 'LeoDocs2.leo']
paths = [g.os_path_finalize_join('~/compare', z) for z in outlines]
leoCompare.CompareLeoOutlines(c).diff_list_of_files(paths)

This script will present three sets of diffs, in a new top-level node whose nodes are as follows:

- outline diff
    Body: LeoDocs.leo, LeoDocs1.leo, LeoDocs2.leo
    - LeoDocs.leo, LeoDocs1.leo
      Body: the entire diff of LeoDocs.leo and LeoDocs1.leo
      - added
        copies of added nodes
      - deleted
        copies of deleted nodes
     - changed
        diff nodes for all changed nodes.
        Body: the diff of each node.
        - LeoDocs.leo: copy of old node
        - LeoDocs1: copy of new node
    - LeoDocs.leo, LeoDocs1.leo
      Ditto
    - LeoDocs1.leo, LeoDocs1.leo
      Ditto
Leo 5.7 final: Enhancements#

Add mark/unmark-first-parents commands leo-editor/leo-editor#714

Predefine script_p and script_gnx values in Leo scripts leo-editor/leo-editor#736

Improved js_i.clean_headline. This method now applies various regex patterns to the headline to simplify the “summary” of the function, including => functions.

Leo 5.7 Plugins#

#488: Improved the console_gui plugin#

leo-editor/leo-editor#488 Docs: https://leo-editor.github.io/leo-editor/console-gui.html

The highlights of recent work:

  1. The label above the minibuffer now contains the present state. For example, after Ctrl-F the label is:

    Mini-buffer: Search:
    

indicating that a search string is expected.

  1. When selected, the tree pane highlights the ‘*’ line containing c.p.

  2. The status pane shows Find options after Ctrl-F and various toggle-find-* and set-find-* commands.

So it is now clear what is going on at all times. This clarity is more important than features!

  1. The minibuffer works with tab completion. Examples:

    run-a<tab>l<tab><return> executes run-all-unit-tests-locally. toggle-find-r<tab><return> executes toggle-find-regex-option. # Shows results in status area.

This is a huge step forward in power.

  1. Aha: the reason that all (enabled) unit tests work with the console gui is that the string representations of the body, tree and log (including headlines) are completely functional. True, the npyscreen views of same are weak and/or buggy, but that is a secondary matter.

For example, the Find commands probably work completely, even though the found text is not selected. Furthermore, there are workarounds. It is possible to select all lines containing the text selection, even though npyscreen does not support character selections.

Summary

The curses gui plugin is more functional and less confusing than before.

  • leo-c starts the test.

  • listen-to-log command to get message in THIS console.

  • Tab and Shift Tab switch panes.

  • F4 runs all unit tests.

    Ran 918 tests in 40.317s (failures=4, errors=1, skipped=25)

  • Improve console gui chapter:

Without redraws: 34.5 sec. With redraws: 58.7 sec.

#613: patch_python_colorizer.py plugin#

leo-editor/leo-editor#613

New leo_cloud.py plugin#

The new leo_cloud plugin allows subtrees within a .leo file to be stored in the cloud. It should be possible to support various cloud platforms, currently git is supported (i.e. you can use GitLab or GitHub or your own remote git server).

A leo_cloud subtree has a top node with a headline that starts with @leo_cloud’. The rest of the headline is ignored. The body of this top node is used to describe the cloud service. For example:

type: Git
remote: git@gitlab.com:tnbrown/leo_cloud_storage.git
local: ~/.leo/leo_cloud/gitlab_leo_cloud_storage
ID: shortcuts
read_on_load: ask
write_on_save: ask

The first three lines can be repeated with different IDs to store different subtrees at the same remote cloud location.

read_on_load: / write_on_save: can be yes, no, or ask. If it’s not one of those three, there’s a warning dialog.

There’s also a file system backend, which would look like this:

type: FileSystem
root: ~/DropBox/leo_cloud
ID: my_notes
read_on_load: ask
write_on_save: ask

The FileSystem backend was meant to be for development, but of course if you map it into a folder that is sync’ed externally, as shown above, it can serve as a cloud adapter too.

New line_numbering.py plugin#

This plugin shows real line numbers (as they are in external file) in the gutter.

Commands

line-numbering-toggle toggles whether this plugin has any effect.

toggle-line-numbering-root marks the presently selected node as fictive root for line numbering purposes.

Setting

Requires @bool use-gutter=True

Leo 5.7.1 Themes#

Leo 5.7.1 April 6, 2018

Leo 5.7.1, https://leo-editor.github.io/leo-editor/ is now available on [GitHub](leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 5.7.1

  • Improved support for themes, including the open-theme-file command.
    • Added –theme=<name> command-line option.

    • Added @string theme-name setting.

    • Leo warns if stylesheets contain undefined @-constants.

  • Replaced 5 vs-* commands by corresponding eval* commands.

  • Support @file x.md using html sentinels.

  • Allow @path in @<file> nodes, and optionally generate same in recursive imports.

  • Improved menus.

  • The usual minor bug fixes.

Links

Bugs#

is:issue milestone:5.7.1 is:closed https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A5.7.1+-label%3AWaiting+is%3Aclosed

#780: @tabwidth -2 in @data qt-gui-plugin-style-sheet crashes Leo#

leo-editor/leo-editor#780

#781: ViewRendered Plugin fails on Python 2.7 (Bad Import Statement)#

leo-editor/leo-editor#781

#792: python_console plugin doesn’t handle copy/paste properly#

leo-editor/leo-editor#792

#802: @color @image display in vr pane#

leo-editor/leo-editor#802

#808: Loading Images in Themes is Broken#

leo-editor/leo-editor#808

#809: Themes dialog doesn’t always start in leo/themes#

leo-editor/leo-editor#809

#812: g.glob_glob problems#

leo-editor/leo-editor#812 PickleShareDB.keys should definitely not call g.glob_glob.

#832: Leo crashes on non English systems#

leo-editor/leo-editor#832

#840: config.getData(foo) strips comments inconsistently#

leo-editor/leo-editor#840 Changed c.config.getData and gcm.getData.

#843: Cannot Open Any Non Leo File From Command Line#

leo-editor/leo-editor#843

Code#

Added add_path keyword argument to c.recursiveImport#

When True, adds @path directives to the root node of imported files.

Added g.backupGitIssues#
Added g.caller#
g.log is a synonym for g.es#

Commands#

#839: Replaced 5 vs-* commands with eval* commands#

leo-editor/leo-editor#839 The eval* commands are now in mod_scripting.py.

Added open-theme-file command#
Retired the ‘escape’ and ‘eval-expression’ commands#

They have been replaced by new eval- commands.

Features#

#467: Add setting for preferred directory#

leo-editor/leo-editor#467 @string initial-chooser-directory

#663: Regularize slashes and back slashes#

leo-editor/leo-editor#663

#748: Improve show-settings command#

leo-editor/leo-editor#748

#763: Use html comments to support @file x.md#

leo-editor/leo-editor#763

#766: Create Theme menu, etc.#

leo-editor/leo-editor#766

#784: Warn if stylesheet substitution leaves undefined @-constants#

leo-editor/leo-editor#784

Feature: Allow @path in body text#

Removed unnecessary check in g.get_directives_dict.

Won’t do: #822: Put outline tabs below the main window bar#

leo-editor/leo-editor#822

Settings & command-line arguments#

Command-line options:

  • Added –theme=<name>

  • Added –trace-themes

Settings:

  • Added @string theme-name

  • Added @string initial-chooser-directory Used by Ctrl-O (file-open-by-name)

Leo 5.7.2 Jupyter & Git#

May 7, 2018

Leo 5.7.2, https://leo-editor.github.io/leo-editor/ is now available on [GitHub](leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 5.7.2

  • Much improved support for Jupyter (.ipynb) files.

  • Fixed bugs that prevented switching between git branches easily.

  • Rewrote large parts of Leo’s key-handling code.

  • New command-line arguments to trace Leo’s code.

  • Removed about 20 unused settings.

  • The usual minor bug fixes.

Links

Bugs#

#757: MacOS: replace-then-find does not work in headlines#

leo-editor/leo-editor#757

#794: Clicking Find Tab should do exactly what pushing Ctrl-F does#

leo-editor/leo-editor#794

#848: Recent Files menu will break for foreign languages#

leo-editor/leo-editor#848

The first non-blank, non-comment line of the node @menu Recent Files can contain an alternate (translated) menu name.

You should not just change the headline of the node: it should remain unchanged. Indeed, the point of this item is that Leo has to know which item is the Recent Files item, so some other way was needed to specify an alternate name.

#862: paste-retaining-clones can corrupt the outline#

leo-editor/leo-editor#862

#863: Serious problems changing branches#

leo-editor/leo-editor#863

#877: Exception in the markdown importer#

leo-editor/leo-editor#877

#879: g.es can be too slow#

leo-editor/leo-editor#879

#880: Replace command does not set @<file> nodes dirty#

leo-editor/leo-editor#880

#884: Log pane does not handle leading whitespace properly#

leo-editor/leo-editor#884

Code#

#423: Simplify key handling with a better KeyStroke class#

leo-editor/leo-editor#423

Related issues:

Features#

#838: Better .ipynb importer/exporters#

leo-editor/leo-editor#838

@auto x.ipynb now “just works”.

  • I can change any cell in Jupyter and save the file. If the corresponding .leo file is running the new code appears in the @auto tree. Simple as that.

  • I can also change the @auto tree. The Jupyter web page will (I think) eventually reload automatically. Or I can reload the page myself. Simple as that.

It now feels Leonine to author in Leo (with all of Leo’s organizing capabilities) and then render or run code in Jupyter.

Other features:

When writing, Leo uses @language directives to determine cell type.

When reading, Leo indents nodes based on body lines of the form:

<h1…9>title</h1…9>

Such markup affects Jupyter rendering, but the Leo headline of the node can be anything you want.

Leo now generates markdown section markup automatically, based on outline level and headlines.

Leo handles organizer nodes in the outline.

#886: Add c.interactive1/2/3 methods#

leo-editor/leo-editor#886

Added insert-jupyter-toc and insert-markdown-toc commands#

The new insert-jupyter-toc and insert-markdown-toc commands produce a toc (table of contents) for in the selected node, at insert point of the body text. They replace any selected text.

These two commands are almost identical. They very only in the details of how they generate the url part of markdown links. See Note 2 below.

Tip: These commands produce a toc only for the selected node and it’s descendants, but that is not a real limitation. For example, you can produce a complete toc for an @auto .ipynb tree by executing the command in the @auto node itself, then cutting and pasting the toc into the first child of the @auto node.

Notes

  1. You must use the insert-jupyter-toc command inside .ipynb files. The Jupyter online notebook is picky about what links it will accept. In particular, case is important in url’s. You probably should use insert-markdown-toc for all other files.

  2. Both commands clean both parts of markdown links, that is, the [*] part and the (*) part. It’s not clear what characters can be allowed in general, but for now the rules are:

  1. Within [*] parts, all non alphanums are removed, except “:” and “-” and blanks.

  2. Same for (*) parts, except that blanks are converted to “-“.

  1. Similar logic is used in the exporter to clean section names.

The cleaning of markdown links is over-zealous, but it’s not clear exactly what characters are valid. In particular, html escapes will not work.

  1. These two commands are defined in Leo’s core. They are completely separate from the @auto (importer/export) logic.

Summary

These two commands are important tools. Please try them and report any problems or desired improvements.

I will be happy to allow more characters in markdown links, should you want them. Just let me know.

The insert-markdown-toc is a component of #767: Add markdown command similar to rst3 command.

Added new command-line arguments#

leo-editor/leo-editor#876

Leo’s –trace command-line arguments now allow users and devs to enable important traces without changing Leo’s sources in any way:

--trace-binding=KEY   trace commands bound to a key
--trace-coloring      trace syntax coloring
--trace-events        trace non-key events
--trace-focus         trace changes of focus
--trace-gnx           trace gnx logic
--trace-ipython       trace ipython bridge
--trace-keys          trace key events
--trace-plugins       trace imports of plugins
--trace-setting=NAME  trace where named setting is set
--trace-shutdown      trace shutdown logic
--trace-themes        trace theme init logic

The following command-line arguments are new:

--trace-coloring
--trace-events
--trace-gnx
--trace-keys
--trace-ipython
Removed unused settings#

The following settings are no longer used. They no longer appear in leoSettings.leo:

@bool gc_before_redraw = True @bool show_tree_stats = False @bool trace_bindings = False @bool trace_bindings_verbose = False @bool trace_color_parser = True @bool trace_colorizer = False @bool trace_doCommand = False @bool trace_f.set_focus = False @bool trace_focus = False @bool trace_g.app.gui.set_focus = False @bool trace_gc = False @bool trace_gc_calls = False @bool trace_gc_verbose = False @bool trace_key_event= False @bool trace_masterCommand = False @bool trace_masterFocusHandler = False @bool trace_masterKeyHandler = False @bool trace_minibuffer = False @bool trace_modes = False @bool trace_onBodyChanged = False @bool trace_plugins = False @bool trace_select = False @bool trace_status_line = False @bool trace_tree = False @bool trace_tree_alloc = False @bool trace_tree_edit = False @bool trace_tree_gc = False @bool trace_tree_redraw = False @bool verbose_trace_color_parser = False @string trace_bindings_filter = @string trace_bindings_pane_filter =

Leo 5.7.3 release notes#

May 28, 2018 Leo 5.7.3, https://leo-editor.github.io/leo-editor/ is now available on [GitHub](leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](https://leo-editor.github.io/leo-editor/preface.html).

The highlights of Leo 5.7.3

  • Added support for Jedi autocompletion.

  • Much improved python_terminal plugin.

  • Much improved recursive import script.

  • New leo_babel plugin.

  • Leo’s pylint command writes clickable links.

  • Smart searches for functions and methods.

  • Allow separate bindings for numeric keypad keys

  • Added easy-to-use diff-related wrappers for scripts.

  • Allow local overrides of all abbreviations.

  • Improved TypeScript importer.

  • The usual minor bug fixes.

Links

Bugs#

#841: Python importer does not always handle decorators properly#

leo-editor/leo-editor#841

#892: Crash in checkForChangedNodes#

leo-editor/leo-editor#892

#893: Python Console gets stuck on IndentationError#

leo-editor/leo-editor#893

A complete rewrite of the python_terminal plugin.

#901: The Windows Right-Menu key insert “Menu” into text#

leo-editor/leo-editor#901

Code#

#875: Rename json reader/writer plugins#

leo-editor/leo-editor#875

Removed most g.trace statements#

A mass cleanup of Leo’s code, removing many unused tracing statements.

Info items#

#909: How to use LaTeX with Leo#

leo-editor/leo-editor#909

#910: Summary of developer info items#

leo-editor/leo-editor#910

Features#

#309: Support Jedi autocompletion#

leo-editor/leo-editor#309

#868: Allow separate bindings for numeric keypad keys#

leo-editor/leo-editor#868

As usual, spellings are not significant. For example:

clone-find-all-flattened = Key_Pad+9
clone-find-all = keypad-PageUp
    # Same as keypad+pageup, etc. etc.
#904: Allow local overrides of abbreviations#

Allow local overrides of @data global-abbreviations & @outline-data tree-abbreviations leo-editor/leo-editor#904

#932: use show-prefix#

leo-editor/leo-editor#932

Commands that DO use the printer:

print-body print-html print-node print-expanded-body print-expanded-html print-marked-bodies print-marked-html print-marked-nodes print-tree-bodies print-tree-html print-tree-nodes

Commands that DON’T use the printer:

gc-show-summary show-all-uas show-bindings show-buttons show-commands show-focus show-node-uas show-plugin-handlers show-plugins-info show-settings show-stats show-style-sheet

Added leo_babel plugin#

For documentation, see the leo/plugins/leo_babel/doc folder.

Improved recursive import script#

The recursive import script now adds disambiguating headline comments as follows:

  • If a node is a descendant of a class node, the script prepends the class’s name:

    aClass.headline

  • Otherwise, the script appends the file name:

    headline (x.py)

This is a huge help when using the clone-find commands.

Improved typescript importer#
Removed settings#
  • Removed @bool trace_import.

  • Removed @bool trace_bind_key_exceptions.

Smart searches for functions and methods#

The find-def command is typically invoked by control-clicking a function name. This command now will search for possible alternative spellings of the name if no match is found initially:

  • If the original name contains an underscore, say x_y, the second search will be for the camelCase version, xY.

  • Otherwise, we assume the name may be camelCase, say xY, and we attempt to convert it to x_y.

A second search is attempted only if the converted name is different from the original. In particular, names starting with a leading underscore are never converted.

The new setting: @bool find-def-creates-clones (default False) controls whether a clone-find-flattened command is used to show all matching definitions. This setting has no effect when only one definition is found.