<?xml version="1.0" encoding="utf-8"?>
<!-- Created by Leo: https://leo-editor.github.io/leo-editor/leo_toc.html -->
<leo_file xmlns:leo="https://leo-editor.github.io/leo-editor/namespaces/leo-python-editor/1.1" >
<leo_header file_format="2"/>
<globals/>
<preferences/>
<find_panel_settings/>
<vnodes>
<v t="ekr.20050831195449"><vh>** Read me first **</vh></v>
<v t="ekr.20070610174018"><vh>Startup</vh>
<v t="rkeeney.20190823135126.4"><vh>@persistence</vh>
<v t="ekr.20240110034554.1"><vh>@data:@auto-md ../doc/demo.md</vh>
<v t="ekr.20240110034554.2"><vh>@gnxs</vh></v>
</v>
<v t="ekr.20240110034554.3"><vh>@data:@auto-md importers.md </vh>
<v t="ekr.20241206192042.1"><vh>@gnxs</vh></v>
</v>
<v t="ekr.20240303071512.1"><vh>@data:@auto-rst treecaching.txt</vh>
<v t="ekr.20240303071512.2"><vh>@gnxs</vh></v>
</v>
</v>
<v t="ekr.20050407144417"><vh>@settings</vh>
<v t="ekr.20150318043636.16"><vh>@bool check_outline_after_read = True</vh></v>
<v t="ekr.20150318043636.17"><vh>@bool check_outline_before_save = True</vh></v>
<v t="ekr.20141117065749.3"><vh>@bool wikiview-active = False</vh></v>
<v t="ekr.20111108052738.5507"><vh>@shortcuts</vh></v>
<v t="ekr.20130816100419.17299"><vh>@string target_language = rest</vh></v>
<v t="ekr.20150222035621.5"><vh>@bool body_pane_wraps = True</vh></v>
<v t="ekr.20230303070618.1"><vh>@data history-list</vh></v>
<v t="ekr.20100907092300.4440"><vh>Inkscape options</vh>
<v t="ekr.20100907092300.4441"><vh>@string inkscape-template = ../docs/inkscape-template.svg</vh></v>
<v t="ekr.20100907092300.4442"><vh>@string inkscape-bin = "c:\Program Files (x86)\Inkscape\inkscape.exe"</vh></v>
</v>
<v t="ekr.20101009114830.4724"><vh>File options</vh>
<v t="ekr.20080412124815.1"><vh>@bool fixedWindow = False</vh></v>
<v t="ekr.20101009114830.4723"><vh>@bool put_expansion_bits_in_leo_files = False</vh></v>
</v>
<v t="ekr.20230228100301.1"><vh>Find panel defaults</vh>
<v t="ekr.20230228100301.2"><vh>@bool ignore-case = True</vh></v>
<v t="ekr.20230228100301.3"><vh>@bool whole-word = False</vh></v>
</v>
<v t="ekr.20050407144342"><vh>http plugin</vh>
<v t="ekr.20050407144342.1"><vh>@bool http_active = False</vh></v>
<v t="ekr.20050407144342.2"><vh>@int  port = 8080</vh></v>
<v t="ekr.20050407144342.3"><vh>@string rst_http_attributename = rst_http_attribute</vh></v>
</v>
<v t="ekr.20050812123002"><vh>rst3 options</vh>
<v t="ekr.20131009050634.17658"><vh>@bool rst3_call_docutils = False</vh></v>
<v t="ekr.20131009050634.17610"><vh>@bool rst3_http_server_support = False</vh></v>
<v t="ekr.20131009050634.17622"><vh>@bool rst3_verbose = False</vh></v>
<v t="ekr.20131009050634.17623"><vh>@bool rst3_write_intermediate_file = True</vh></v>
<v t="ekr.20051202072010"><vh>@string rst3_default_path =</vh></v>
<v t="ekr.20050812123002.5"><vh>@string rst3_node_begin_marker = http-node-marker-</vh></v>
<v t="ekr.20131009050634.17616"><vh>@string rst3_stylesheet_path = ..\doc</vh></v>
<v t="ekr.20131027064821.18685"><vh>@string rst3_write_intermediate_extension = .txt</vh></v>
</v>
</v>
<v t="ekr.20131017051340.16847"><vh>Buttons</vh>
<v t="ekr.20230111163935.1"><vh>@button backup</vh></v>
<v t="ekr.20230110152344.1"><vh>@button find-bad-links</vh>
<v t="ekr.20230111171223.1"><vh>find_docs_links</vh></v>
<v t="ekr.20230110153304.1"><vh>find_outline_links</vh></v>
<v t="ekr.20230110153129.1"><vh>find_web_links</vh></v>
<v t="ekr.20230110153501.1"><vh>find_broken_links</vh></v>
</v>
<v t="ekr.20260605070320.1"><vh>@button make-sphinx</vh>
<v t="ekr.20260605070320.2"><vh>copy_files</vh></v>
<v t="ekr.20260605070320.3"><vh>copy_recursive</vh></v>
<v t="ekr.20260605070320.4"><vh>get_leo_version</vh></v>
<v t="ekr.20260605070320.5"><vh>git_status</vh></v>
<v t="ekr.20260605070320.6"><vh>make_html</vh></v>
<v t="ekr.20260605070320.7"><vh>patch_home_page</vh></v>
<v t="ekr.20260605070320.8"><vh>run</vh></v>
<v t="ekr.20260605070320.9"><vh>write_intermediate_files</vh></v>
</v>
<v t="ekr.20230110152349.1"><vh>@ignore disabled buttons</vh>
<v t="ekr.20111017085134.16158"><vh> Slideshow Buttons</vh>
<v t="ekr.20111017085134.16159"><vh>@@button copy-@screenshot-node</vh>
<v t="ekr.20111017085134.16160"><vh>@screenshot</vh>
<v t="ekr.20111017085134.16161"><vh>To Do List</vh>
<v t="ekr.20111017085134.16162"><vh>Urgent</vh></v>
<v t="ekr.20111017085134.16163"><vh>Important</vh></v>
<v t="ekr.20111017085134.16164"><vh>Soon</vh></v>
<v t="ekr.20111017085134.16165"><vh>Whenever</vh></v>
</v>
<v t="ekr.20111017085134.16166"><vh>Diary</vh>
<v t="ekr.20111017085134.16167"><vh>2009</vh>
<v t="ekr.20111017085134.16168"><vh>Jul 2009</vh></v>
<v t="ekr.20111017085134.16169"><vh>Aug 2009</vh></v>
<v t="ekr.20111017085134.16170"><vh>Sep 2009</vh></v>
<v t="ekr.20111017085134.16171"><vh>Oct 2009</vh></v>
<v t="ekr.20111017085134.16172"><vh>Nov 2009</vh></v>
<v t="ekr.20111017085134.16173"><vh>Dec 2009</vh></v>
</v>
<v t="ekr.20111017085134.16174"><vh>2010</vh></v>
</v>
</v>
<v t="ekr.20111017085134.16175"><vh>@select Urgent</vh></v>
<v t="ekr.20111017085134.16176"><vh>@@button ins-@slide-nodes</vh></v>
<v t="ekr.20111017085134.16177"><vh>@@button make-slide @key=Alt-8</vh></v>
<v t="ekr.20111017085134.16178"><vh>@@button make-slide-show @key=Alt-8</vh></v>
<v t="ekr.20111017085134.16179"><vh>@@button meld</vh>
<v t="ekr.20111017085134.16180"><vh>class MeldController</vh>
<v t="ekr.20111017085134.16181"><vh>utils</vh>
<v t="ekr.20111017085134.16182"><vh>finalize &amp; fix</vh></v>
<v t="ekr.20111017085134.16183"><vh>has_at_no_screenshot_node</vh></v>
<v t="ekr.20111017085134.16184"><vh>match</vh></v>
</v>
<v t="ekr.20111017085134.16185"><vh>run &amp; helpers</vh>
<v t="ekr.20111017085134.16186"><vh>adjust_slideshow &amp; helper</vh>
<v t="ekr.20111017085134.16187"><vh>adjust_slide_node &amp; helpers</vh>
<v t="ekr.20111017085134.16188"><vh>add_at_url_final_output_file</vh></v>
<v t="ekr.20111017085134.16189"><vh>add_image_directive</vh></v>
<v t="ekr.20111017085134.16190"><vh>delete_at_url_built_slide_node</vh></v>
</v>
</v>
<v t="ekr.20111017085134.16191"><vh>check &amp; helpers</vh>
<v t="ekr.20111017085134.16192"><vh>check_dir</vh></v>
<v t="ekr.20111017085134.16193"><vh>count_slide_nodes</vh></v>
</v>
<v t="ekr.20111017085134.16194"><vh>copy_files &amp; helper</vh>
<v t="ekr.20111017085134.16195"><vh>copy_file</vh></v>
</v>
<v t="ekr.20111017085134.16196"><vh>get_wink_screenshots</vh></v>
</v>
</v>
</v>
<v t="ekr.20111017085134.16197"><vh>@@button renumber nodes</vh></v>
</v>
<v t="ekr.20170212105226.1"><vh>@@button IntroSlides</vh>
<v t="ekr.20170212105226.2"><vh>&lt;&lt; imports &gt;&gt;</vh></v>
<v t="ekr.20170212105226.3"><vh>&lt;&lt; class IntroSlides &gt;&gt;</vh>
<v t="ekr.20170212105226.4"><vh>setup</vh></v>
<v t="ekr.20170212105226.5"><vh>setup_script</vh></v>
<v t="ekr.20170212105226.6"><vh>teardown</vh></v>
<v t="ekr.20170212105226.7"><vh>teardown_script</vh></v>
</v>
<v t="ekr.20170212105226.8"><vh>&lt;&lt; main &gt;&gt;</vh></v>
<v t="ekr.20170212105226.9"><vh>Leo's Main Window</vh>
<v t="ekr.20031218072017.2608"><vh>@@file leoApp.py</vh>
<v t="ekr.20120219194520.10463"><vh>&lt;&lt; imports &gt;&gt; (leoApp)</vh></v>
<v t="ekr.20161026122804.1"><vh>class IdleTimeManager</vh>
<v t="ekr.20161026125611.1"><vh>itm.add_callback</vh></v>
<v t="ekr.20161026124810.1"><vh>itm.on_idle</vh></v>
<v t="ekr.20161028034808.1"><vh>itm.start</vh></v>
</v>
<v t="ekr.20120209051836.10241"><vh>class LeoApp</vh>
<v t="ekr.20150509193643.1"><vh>app.Birth</vh>
<v t="ekr.20031218072017.1416"><vh>app.__init__ (helpers contain language dicts)</vh>
<v t="ekr.20161028035755.1"><vh>&lt;&lt; LeoApp: command-line arguments &gt;&gt;</vh></v>
<v t="ekr.20161028035835.1"><vh>&lt;&lt; LeoApp: Debugging &amp; statistics &gt;&gt;</vh></v>
<v t="ekr.20161028035902.1"><vh>&lt;&lt; LeoApp: error messages &gt;&gt;</vh></v>
<v t="ekr.20161028035924.1"><vh>&lt;&lt; LeoApp: global directories &gt;&gt;</vh></v>
<v t="ekr.20161028035956.1"><vh>&lt;&lt; LeoApp: global data &gt;&gt;</vh></v>
<v t="ekr.20161028040028.1"><vh>&lt;&lt; LeoApp: global controller/manager objects &gt;&gt;</vh></v>
<v t="ekr.20161028040054.1"><vh>&lt;&lt; LeoApp: global status vars &gt;&gt;</vh></v>
<v t="ekr.20161028040141.1"><vh>&lt;&lt; LeoApp: the global log &gt;&gt;</vh></v>
<v t="ekr.20161028040204.1"><vh>&lt;&lt; LeoApp: global types &gt;&gt;</vh></v>
<v t="ekr.20161028040229.1"><vh>&lt;&lt; LeoApp: plugins and event handlers &gt;&gt;</vh></v>
<v t="ekr.20161028040303.1"><vh>&lt;&lt; LeoApp: scripting ivars &gt;&gt;</vh></v>
<v t="ekr.20161028040330.1"><vh>&lt;&lt; LeoApp: unit testing ivars &gt;&gt;</vh></v>
<v t="ekr.20140729162415.18086"><vh>app.init_at_auto_names</vh></v>
<v t="ekr.20140729162415.18091"><vh>app.init_at_file_names</vh></v>
<v t="ekr.20031218072017.1417"><vh>app.define_global_constants</vh></v>
<v t="ekr.20141102043816.5"><vh>app.define_delegate_language_dict</vh></v>
<v t="ekr.20120522160137.9909"><vh>app.define_language_delims_dict</vh></v>
<v t="ekr.20120522160137.9910"><vh>app.define_language_extension_dict</vh></v>
<v t="ekr.20120522160137.9911"><vh>app.define_extension_dict</vh></v>
</v>
<v t="ekr.20150509193629.1"><vh>app.cmd (decorator)</vh></v>
</v>
<v t="ekr.20031218072017.2609"><vh>app.closeLeoWindow</vh></v>
<v t="ville.20090602181814.6219"><vh>app.commanders</vh></v>
<v t="ekr.20090717112235.6007"><vh>app.computeSignon</vh></v>
<v t="ekr.20100831090251.5838"><vh>app.createXGui</vh>
<v t="ekr.20100831090251.5840"><vh>app.createCursesGui</vh></v>
<v t="ekr.20090619065122.8593"><vh>app.createDefaultGui</vh></v>
<v t="ekr.20031218072017.1938"><vh>app.createNullGuiWithScript</vh></v>
<v t="ekr.20090202191501.1"><vh>app.createQtGui</vh></v>
<v t="ekr.20090126063121.3"><vh>app.createWxGui</vh></v>
</v>
<v t="ekr.20031218072017.2612"><vh>app.destroyAllOpenWithFiles</vh></v>
<v t="ekr.20031218072017.2615"><vh>app.destroyWindow</vh></v>
<v t="ekr.20031218072017.1732"><vh>app.finishQuit</vh></v>
<v t="ekr.20031218072017.2616"><vh>app.forceShutdown</vh></v>
<v t="ekr.20031218072017.2188"><vh>app.newCommander</vh></v>
<v t="ekr.20031218072017.2617"><vh>app.onQuit (enabled)</vh></v>
<v t="ekr.20120304065838.15588"><vh>app.selectLeoWindow</vh></v>
<v t="ville.20090620122043.6275"><vh>app.setGlobalDb</vh></v>
<v t="ekr.20031218072017.1978"><vh>app.setLeoID</vh>
<v t="ekr.20031218072017.1979"><vh>&lt;&lt; return if we can set leoID from sys.leoID&gt;&gt;</vh></v>
<v t="ekr.20031218072017.1980"><vh>&lt;&lt; return if we can set leoID from "leoID.txt" &gt;&gt;</vh></v>
<v t="ekr.20060211140947.1"><vh>&lt;&lt; return if we can set leoID from os.getenv('USER') &gt;&gt;</vh></v>
<v t="ekr.20031218072017.1981"><vh>&lt;&lt; put up a dialog requiring a valid id &gt;&gt;</vh></v>
<v t="ekr.20031218072017.1982"><vh>&lt;&lt; attempt to create leoID.txt &gt;&gt; (changed)</vh></v>
</v>
<v t="ekr.20031218072017.1847"><vh>app.setLog, lockLog, unlocklog</vh></v>
<v t="ekr.20031218072017.2619"><vh>app.writeWaitingLog</vh></v>
<v t="ekr.20120427064024.10068"><vh>app.Detecting already-open files</vh>
<v t="ekr.20120427064024.10064"><vh>app.checkForOpenFile</vh></v>
<v t="ekr.20120427064024.10066"><vh>app.forgetOpenFile</vh></v>
<v t="ekr.20120427064024.10065"><vh>app.rememberOpenFile</vh></v>
<v t="ekr.20150621062355.1"><vh>app.runAlreadyOpenDialog</vh></v>
</v>
</v>
<v t="ekr.20120209051836.10242"><vh>class LoadManager</vh>
<v t="ekr.20120214060149.15851"><vh> LM.ctor</vh></v>
<v t="ekr.20120211121736.10812"><vh>LM.Directory &amp; file utils</vh>
<v t="ekr.20120219154958.10481"><vh>LM.completeFileName</vh></v>
<v t="ekr.20120209051836.10372"><vh>LM.computeLeoSettingsPath</vh></v>
<v t="ekr.20120209051836.10373"><vh>LM.computeMyLeoSettingsPath</vh></v>
<v t="ekr.20120209051836.10252"><vh>LM.computeStandardDirectories &amp; helpers</vh>
<v t="ekr.20120209051836.10253"><vh>lm.computeGlobalConfigDir</vh></v>
<v t="ekr.20120209051836.10254"><vh>lm.computeHomeDir</vh></v>
<v t="ekr.20120209051836.10260"><vh>lm.computeHomeLeoDir</vh></v>
<v t="ekr.20120209051836.10255"><vh>lm.computeLeoDir</vh></v>
<v t="ekr.20120209051836.10256"><vh>lm.computeLoadDir</vh>
<v t="ekr.20120209051836.10257"><vh>&lt;&lt; resolve symlinks &gt;&gt;</vh></v>
</v>
<v t="ekr.20120213164030.10697"><vh>lm.computeMachineName</vh></v>
</v>
<v t="ekr.20120211121736.10772"><vh>LM.computeWorkbookFileName</vh></v>
<v t="ekr.20120219154958.10485"><vh>LM.reportDirectories</vh></v>
</v>
<v t="ekr.20120215062153.10740"><vh>LM.Settings</vh>
<v t="ekr.20120130101219.10182"><vh>lm.computeBindingLetter</vh></v>
<v t="ekr.20120223062418.10421"><vh>lm.computeLocalSettings</vh></v>
<v t="ekr.20121126202114.3"><vh>lm.createDefaultSettingsDicts</vh></v>
<v t="ekr.20120214165710.10726"><vh>lm.createSettingsDicts</vh></v>
<v t="ekr.20120223062418.10414"><vh>LM.getPreviousSettings</vh></v>
<v t="ekr.20120214132927.10723"><vh>lm.mergeShortcutsDicts &amp; helpers</vh>
<v t="ekr.20120311070142.9904"><vh>lm.checkForDuplicateShortcuts</vh></v>
<v t="ekr.20120214132927.10724"><vh>lm.invert</vh></v>
<v t="ekr.20120214132927.10725"><vh>lm.uninvert</vh></v>
</v>
<v t="ekr.20120222103014.10312"><vh>lm.openSettingsFile</vh></v>
<v t="ekr.20120213081706.10382"><vh>lm.readGlobalSettingsFiles</vh></v>
<v t="ekr.20120214165710.10838"><vh>lm.traceSettingsDict</vh></v>
<v t="ekr.20120214165710.10822"><vh>lm.traceShortcutsDict</vh></v>
</v>
<v t="ekr.20120219154958.10452"><vh>LM.load &amp; helpers</vh>
<v t="ekr.20150225133846.7"><vh>LM.doDiff</vh></v>
<v t="ekr.20120219154958.10477"><vh>LM.doPrePluginsInit &amp; helpers</vh>
<v t="ekr.20120219154958.10478"><vh>LM.createGui</vh></v>
<v t="ekr.20120219154958.10479"><vh>LM.createSpecialGui</vh></v>
<v t="ekr.20120219154958.10480"><vh>LM.adjustSysPath</vh></v>
<v t="ekr.20120219154958.10482"><vh>LM.getDefaultFile</vh></v>
<v t="ekr.20120219154958.10484"><vh>LM.initApp</vh></v>
<v t="ekr.20120219154958.10486"><vh>LM.scanOptions &amp; helper</vh>
<v t="ekr.20120219154958.10483"><vh>LM.computeFilesList</vh></v>
</v>
<v t="ekr.20160718072648.1"><vh>LM.setStdStreams</vh>
<v t="ekr.20160718091844.1"><vh>class LeoStdOut</vh>
<v t="ekr.20160718102306.1"><vh>LeoStdOut.write</vh></v>
</v>
</v>
</v>
<v t="ekr.20120219154958.10487"><vh>LM.doPostPluginsInit &amp; helpers</vh>
<v t="ekr.20120219154958.10488"><vh>LM.initFocusAndDraw</vh></v>
<v t="ekr.20120219154958.10489"><vh>LM.make_screen_shot</vh></v>
<v t="ekr.20131028155339.17098"><vh>LM.openEmptyWorkBook</vh></v>
</v>
<v t="ekr.20120219154958.10491"><vh>LM.isValidPython &amp; emergency (Tk) dialog class</vh>
<v t="ekr.20120219154958.10492"><vh>&lt;&lt; define emergency dialog class &gt;&gt;</vh>
<v t="ekr.20120219154958.10493"><vh>__init__ (emergencyDialog)</vh></v>
<v t="ekr.20120219154958.10494"><vh>createButtons</vh></v>
<v t="ekr.20120219154958.10495"><vh>createTopFrame</vh></v>
<v t="ekr.20120219154958.10496"><vh>okButton</vh></v>
<v t="ekr.20120219154958.10497"><vh>onKey</vh></v>
<v t="ekr.20120219154958.10498"><vh>run</vh></v>
</v>
</v>
<v t="ekr.20120223062418.10393"><vh>LM.loadLocalFile &amp; helper</vh>
<v t="ekr.20120223062418.10394"><vh>LM.openFileByName &amp; helpers</vh>
<v t="ekr.20120223062418.10405"><vh>LM.createMenu</vh></v>
<v t="ekr.20120223062418.10406"><vh>LM.findOpenFile</vh></v>
<v t="ekr.20120223062418.10407"><vh>LM.finishOpen</vh></v>
<v t="ekr.20120223062418.10408"><vh>LM.initWrapperLeoFile</vh></v>
<v t="ekr.20120223062418.10419"><vh>LM.isLeoFile &amp; LM.isZippedFile</vh></v>
<v t="ekr.20120224161905.10030"><vh>LM.openLeoOrZipFile</vh></v>
<v t="ekr.20120223062418.10416"><vh>LM.openLeoFile</vh></v>
<v t="ekr.20120223062418.10410"><vh>LM.openZipFile</vh></v>
<v t="ekr.20120223062418.10412"><vh>LM.readOpenedLeoFile</vh></v>
</v>
</v>
</v>
<v t="ekr.20160430063406.1"><vh>LM.revertCommander</vh></v>
</v>
<v t="ekr.20120223062418.10420"><vh>class PreviousSettings</vh></v>
<v t="ekr.20120225072226.10283"><vh>class RecentFilesManager</vh>
<v t="ekr.20041201080436"><vh>rf.appendToRecentFiles</vh></v>
<v t="ekr.20120225072226.10289"><vh>rf.cleanRecentFiles</vh></v>
<v t="ekr.20120225072226.10297"><vh>rf.clearRecentFiles</vh></v>
<v t="ekr.20120225072226.10301"><vh>rf.createRecentFilesMenuItems</vh></v>
<v t="ekr.20120225072226.10286"><vh>rf.getRecentFiles</vh></v>
<v t="ekr.20120225072226.10304"><vh>rf.getRecentFilesTable</vh></v>
<v t="ekr.20070224115832"><vh>rf.readRecentFiles &amp; helpers</vh>
<v t="ekr.20061010121944"><vh>rf.createRecentFiles</vh></v>
<v t="ekr.20050424115658"><vh>rf.readRecentFilesFile</vh></v>
</v>
<v t="ekr.20120225072226.10285"><vh>rf.sanitize</vh></v>
<v t="ekr.20120215072959.12478"><vh>rf.setRecentFiles</vh></v>
<v t="ekr.20120225072226.10293"><vh>rf.sortRecentFiles</vh></v>
<v t="ekr.20031218072017.2083"><vh>rf.updateRecentFiles</vh></v>
<v t="ekr.20050424114937.2"><vh>rf.writeRecentFilesFile &amp; helper</vh>
<v t="ekr.20050424131051"><vh>rf.writeRecentFilesFileHelper</vh></v>
</v>
</v>
<v t="ekr.20150514125218.1"><vh>Top-level-commands</vh>
<v t="ekr.20150514125218.2"><vh>ctrl-click-at-cursor</vh></v>
<v t="ekr.20150514125218.3"><vh>enable/disable/toggle-idle-time-events</vh></v>
<v t="ekr.20150514125218.4"><vh>join-leo-irc</vh></v>
<v t="ekr.20150514125218.5"><vh>open-url</vh></v>
<v t="ekr.20150514125218.6"><vh>open-url-under-cursor</vh></v>
</v>
</v>
<v t="ekr.20170213112231.1"><vh>New Node</vh></v>
<v t="ekr.20170212113230.1"><vh>@@test init method</vh></v>
<v t="ekr.20170212113214.1"><vh>@@suite plugins syntax</vh>
<v t="ekr.20170212113214.2"><vh>makePluginsTestSuite</vh></v>
<v t="ekr.20170212113214.3"><vh>class pluginTestCase</vh>
<v t="ekr.20170212113214.4"><vh>__init__</vh></v>
<v t="ekr.20170212113214.5"><vh>fail</vh></v>
<v t="ekr.20170212113214.6"><vh>runTest</vh></v>
<v t="ekr.20170212113214.7"><vh>setUp</vh></v>
<v t="ekr.20170212113214.8"><vh>shortDescription</vh></v>
</v>
<v t="ekr.20170212113214.9"><vh>class lastTestCase</vh></v>
</v>
</v>
<v t="ekr.20170212105226.10"><vh>intro-slides-script</vh>
<v t="ekr.20170212105226.11"><vh>Slide 1: Leo's main window</vh></v>
</v>
</v>
<v t="ekr.20111017085134.16199"><vh>@@button remove-built-slides</vh></v>
<v t="ekr.20111017085134.16200"><vh>@@button remove-final-output</vh></v>
<v t="ekr.20111017085134.16198"><vh>@@button remove-image-directives</vh></v>
</v>
<v t="ekr.20130803073926.17120"><vh>@@button clean-mail</vh></v>
<v t="ekr.20180125094702.1"><vh>@@button demo</vh>
<v t="ekr.20180125113535.1"><vh>&lt;&lt; utils &gt;&gt;</vh>
<v t="ekr.20180125101040.1"><vh>hightlight</vh></v>
<v t="ekr.20180125102041.1"><vh>unhighlight</vh></v>
<v t="ekr.20180125102554.1"><vh>update</vh></v>
<v t="ekr.20180125101033.1"><vh>wait</vh></v>
</v>
<v t="ekr.20180125113541.1"><vh>top-level</vh>
<v t="ekr.20180128052016.1"><vh>slides</vh>
<v t="ekr.20180128051013.1"><vh>panes</vh></v>
</v>
</v>
</v>
<v t="sps.20100708203040.19008"><vh>@@button generate-full-userguide</vh>
<v t="sps.20100708203040.19009"><vh>&lt;&lt; html manual &gt;&gt;</vh></v>
<v t="sps.20100708203040.19010"><vh>&lt;&lt; pdf manual &gt;&gt;</vh></v>
</v>
<v t="ville.20090705224948.5734"><vh>@@button generate-userguide</vh>
<v t="ville.20090705225609.5736"><vh>&lt;&lt; html manual &gt;&gt;</vh></v>
<v t="ville.20090705225609.5738"><vh>&lt;&lt; pdf manual &gt;&gt;</vh></v>
</v>
<v t="ekr.20161120074501.1"><vh>@@button make-md-heads</vh>
<v t="ekr.20161120075731.1"><vh>markup</vh></v>
</v>
<v t="ekr.20161204055040.1"><vh>@@button make-md-toc</vh>
<v t="ekr.20161204055436.1"><vh>run</vh></v>
<v t="ekr.20161204060843.1"><vh>mak_link</vh></v>
<v t="ekr.20161204055804.1"><vh>make_toc</vh></v>
</v>
<v t="ekr.20150314044011.7"><vh>@@button remove dups</vh></v>
</v>
</v>
<v t="ekr.20131017051340.16850"><vh>Scripts</vh>
<v t="ekr.20180523085905.1"><vh>Scripts that get GitHub issues</vh>
<v t="ekr.20180523085523.1"><vh>Script: get issues with given labels</vh></v>
<v t="ekr.20180125112540.1"><vh>Script: get closed issues</vh></v>
<v t="ekr.20180125112749.1"><vh>Script: get tips</vh></v>
</v>
<v t="ekr.20180523085918.1"><vh>All other scripts</vh>
<v t="ekr.20150313192232.12"><vh>Script: check all command names</vh></v>
<v t="ekr.20101111175617.5037"><vh>Script: get-plugin-docstrings</vh>
<v t="ekr.20101111175617.56915"><vh>class controller</vh>
<v t="ekr.20101112045055.13356"><vh>allowDir</vh></v>
<v t="ekr.20101112222250.5322"><vh>allowFile</vh></v>
<v t="ekr.20101112045055.13355"><vh>createDocs</vh></v>
<v t="ekr.20101112045055.13354"><vh>createSummary</vh></v>
<v t="ekr.20101111175617.14683"><vh>getDocString</vh></v>
<v t="ekr.20101112045055.13357"><vh>getFirstParagraph</vh></v>
<v t="ekr.20101111175617.24328"><vh>openPlugins</vh></v>
<v t="ekr.20101111175617.5787"><vh>run</vh></v>
</v>
</v>
<v t="ekr.20131013060803.16851"><vh>Script: generate position trace</vh></v>
<v t="ekr.20131030082936.17514"><vh>get-child-headlines</vh></v>
<v t="ekr.20170213143631.1"><vh>Script: Stand-alone slide</vh></v>
</v>
</v>
</v>
<v t="ekr.20210326081805.1"><vh>Archive</vh>
<v t="ekr.20180523093753.1"><vh>Backup of GitHub issues</vh>
<v t="ekr.20180523101625.1"><vh>GitHub LeoU issues</vh>
<v t="ekr.20180523101514.14"><vh>#816: Summary: Leo University</vh>
<v t="ekr.20180523101514.10"><vh>#527: LeoU: unit tests need not, and should not, depend on settings</vh></v>
<v t="ekr.20180523101514.9"><vh>#786: LeoU: Suggestions for theme developers</vh></v>
<v t="ekr.20180523101514.8"><vh>#817: LeoU: Think process, not knowledge</vh></v>
<v t="ekr.20180523101514.7"><vh>#818: LeoU: Use issues as an programming notebook</vh></v>
<v t="ekr.20180523101514.6"><vh>#836: LeoU: Leo's debugging tools</vh></v>
<v t="ekr.20180523101514.5"><vh>#837: LeoU: Running unit tests</vh></v>
<v t="ekr.20180523101514.13"><vh>#857: LeoU: How devs should use git branches</vh></v>
<v t="ekr.20180523101514.12"><vh>#859: LeoU: How to make complex changes to a code base</vh></v>
<v t="ekr.20180523101514.4"><vh>#890: LeoU: About Leo's Architecture</vh></v>
<v t="ekr.20180523101514.3"><vh>#891: LeoU: About Leo's Position and VNode classes</vh></v>
</v>
</v>
<v t="ekr.20180523095623.1"><vh>GitHub User issues</vh>
<v t="ekr.20180523095245.9"><vh>#908: Info: Summary of Leo's features</vh>
<v t="ekr.20180523095245.4"><vh>#770: Summary: explain Leo's features</vh></v>
</v>
<v t="ekr.20180523095245.8"><vh>#909: How to use LaTex with Leo</vh></v>
</v>
<v t="ekr.20180523095717.1"><vh>GitHub Dev issues</vh>
<v t="ekr.20180523101133.1"><vh>Dev summaries</vh>
<v t="ekr.20180523095245.20"><vh>#100: Summary: bugs re quicksearch plugin</vh></v>
<v t="ekr.20180523095245.18"><vh>#796: Summary: installation info items</vh></v>
<v t="ekr.20180523095245.17"><vh>#797: Summary: jupyter-related issues</vh></v>
<v t="ekr.20180523095245.16"><vh>#798: Summary: Terry's enhancements re Leo's Gui</vh></v>
<v t="ekr.20180523095245.3"><vh>#799: Summary: general info for Leo devs</vh></v>
<v t="ekr.20180523095245.2"><vh>#801: Summary: plans for 2018</vh></v>
<v t="ekr.20180523095245.1"><vh>#803: Summary: Themes items</vh></v>
<v t="ekr.20180523095245.7"><vh>#910: Summary of developer info items</vh>
<v t="ekr.20180523095243.24"><vh>#105: Index of old LaunchPad bugs re plugins</vh></v>
<v t="ekr.20180523095243.22"><vh>#324: How to install Anaconda</vh></v>
<v t="ekr.20180523095243.16"><vh>#681: Use the tools that Leo supports</vh></v>
<v t="ekr.20180523095243.15"><vh>#688: How to install miniconda on Windows 10</vh></v>
<v t="ekr.20180523095243.14"><vh>#699: How to install Anaconda3 on Windows</vh></v>
<v t="ekr.20180523095243.13"><vh>#701: How to install zerorpc on Windows</vh></v>
<v t="ekr.20180523095243.12"><vh>#703: How to install and run the hello world electron app on Windows</vh></v>
<v t="ekr.20180523095243.11"><vh>#710: How to Switch between Anaconda installations</vh></v>
<v t="ekr.20180523095243.8"><vh>#733: How to Install and run the leocljs demo</vh></v>
<v t="ekr.20180523095243.7"><vh>#735: How to Install and run LeoVue</vh></v>
<v t="ekr.20180523095243.6"><vh>#752: How to install eric6 on Windows</vh></v>
<v t="ekr.20180523095243.4"><vh>#755: How to build pyzo from sources</vh></v>
<v t="ekr.20180523095243.3"><vh>#872: Info: how Leo handles uA's</vh></v>
<v t="ekr.20180523095243.1"><vh>#906: Dubious major projects</vh></v>
</v>
</v>
<v t="ekr.20180523095925.1"><vh>Dev items</vh>
<v t="ekr.20180523095243.23"><vh>#322: Rewrite importers as they become needed</vh></v>
<v t="ekr.20180523095243.21"><vh>#355: Python 3 bug, now resolved, ruined Leo</vh></v>
<v t="ekr.20180523095243.20"><vh>#486: Workaround: Ctrl-) binding may not work on Windows 10</vh></v>
<v t="ekr.20180523095243.19"><vh>#517: leoConfig.ParserBaseClass methods should be revised</vh></v>
<v t="ekr.20180523095243.18"><vh>#551: How to make .leo files happy in git repository?</vh></v>
<v t="ekr.20180523095243.17"><vh>#636: Installing pyenchant fails for Windows 64 bit python</vh></v>
<v t="ekr.20180523095245.19"><vh>#665: Summary: support for org mode</vh></v>
<v t="ekr.20180523095245.5"><vh>#680: Summary: remove sclerotic features from Leo's code base</vh></v>
<v t="ekr.20180523095243.10"><vh>#715: Generating aspell dictionaries</vh></v>
<v t="ekr.20180523095243.9"><vh>#719: clean-recent-files does nothing by default</vh></v>
<v t="ekr.20180523095243.2"><vh>#883: Enhancement: make stand-alone trees of vnodes possible</vh></v>
<v t="ekr.20180523095245.11"><vh>#897: Support VS Code's FileSystemProviders</vh></v>
<v t="ekr.20180523095245.10"><vh>#907: Info: Borrow key features from other IDE's and editors</vh></v>
</v>
</v>
</v>
<v t="ekr.20101115152915.4937"><vh>Backup of wikipedia entry</vh></v>
<v t="ekr.20100122073254.11655"><vh>Writing new importers</vh></v>
</v>
<v t="matt.20200331213038.1"><vh>PyPi install caveat</vh></v>
<v t="ekr.20230121110345.1"><vh>Script files</vh>
<v t="ekr.20230121110340.1"><vh>@clean ../scripts/make-clean.cmd</vh></v>
<v t="ekr.20230121110533.1"><vh>@clean ../scripts/make-html.cmd</vh></v>
</v>
<v t="ekr.20100805171546.4412"><vh>Web pages</vh>
<v t="ekr.20090428133936.2"><vh>@edit html/conf.py</vh></v>
<v t="ekr.20241124083101.1"><vh>@edit _static/custom.css</vh></v>
<v t="ekr.20101112045055.5064"><vh>@file plugin_catalog.py</vh></v>
<v t="ekr.20131005214621.16088"><vh>Home pages</vh>
<v t="ekr.20230110155708.1"><vh>@file ../../docs/redirect_index.html</vh></v>
<v t="ekr.20100808060203.4273"><vh>@file ../../docs/index.html</vh></v>
</v>
</v>
<v t="ekr.20040414161647"><vh>Leo's Documentation</vh>
<v t="ekr.20170215081358.1"><vh> Table of contents</vh>
<v t="ekr.20170215075612.1"><vh>@rst html/leo_toc.html</vh></v>
</v>
<v t="ekr.20140216125129.16666"><vh>Additonal web pages</vh>
<v t="ekr.20131030184445.16582"><vh>@rst html/leoLinks.html</vh></v>
<v t="ekr.20090711120622.10447"><vh>@rst html/screen-shots.html</vh>
<v t="ekr.20170322084431.1"><vh>Leo's main window</vh></v>
<v t="ekr.20090811090022.14452"><vh>Leo's rendering pane</vh></v>
<v t="ekr.20170322084909.1"><vh>Using Leo to manage a PhD thesis</vh></v>
</v>
<v t="ekr.20131120115900.16329"><vh>@rst html/screencasts.html</vh></v>
<v t="ekr.20170130080532.1"><vh>@auto-md ../doc/demo.md</vh></v>
<v t="ekr.20161120073024.1"><vh>Technical docs on GitHub</vh>
<v t="ekr.20161120073038.1"><vh>@auto-md importers.md </vh></v>
</v>
<v t="ekr.20230120090521.1"><vh>Slides</vh></v>
</v>
<v t="ekr.20230121052337.1"><vh>Slides</vh>
<v t="ekr.20100821182153.4343"><vh>@rst html/slides.html</vh></v>
<v t="ekr.20230121060317.1"><vh>Slides: Clones and views</vh>
<v t="ekr.20230121054117.1"><vh>@rst html/slides/clones-and-views/clones-and-views.html</vh></v>
<v t="ekr.20230121060325.1"><vh>@rst html/slides/clones-and-views/slide-001.html</vh></v>
<v t="ekr.20230121060347.1"><vh>@rst html/slides/clones-and-views/slide-002.html</vh></v>
<v t="ekr.20230121164642.1"><vh>@rst html/slides/clones-and-views/slide-003.html</vh></v>
<v t="ekr.20230121165506.1"><vh>@rst html/slides/clones-and-views/slide-004.html</vh></v>
<v t="ekr.20230121165507.1"><vh>@rst html/slides/clones-and-views/slide-005.html</vh></v>
<v t="ekr.20230121165507.2"><vh>@rst html/slides/clones-and-views/slide-006.html</vh></v>
<v t="ekr.20230121165507.3"><vh>@rst html/slides/clones-and-views/slide-007.html</vh></v>
<v t="ekr.20230121165508.1"><vh>@rst html/slides/clones-and-views/slide-009.html</vh></v>
<v t="ekr.20230121165507.4"><vh>@rst html/slides/clones-and-views/slide-008.html</vh></v>
<v t="ekr.20230121165508.2"><vh>@rst html/slides/clones-and-views/slide-010.html</vh></v>
<v t="ekr.20230121165549.1"><vh>@rst html/slides/clones-and-views/slide-011.html</vh></v>
<v t="ekr.20230121165549.2"><vh>@rst html/slides/clones-and-views/slide-012.html</vh></v>
</v>
<v t="ekr.20230121061300.1"><vh>Slides: External files</vh>
<v t="ekr.20230121054859.1"><vh>@rst html/slides/external-files/external-files.html</vh></v>
<v t="ekr.20230122011127.1"><vh>@rst html/slides/external-files/slide-001.html</vh></v>
<v t="ekr.20230122011226.1"><vh>@rst html/slides/external-files/slide-002.html</vh></v>
<v t="ekr.20230122011227.1"><vh>@rst html/slides/external-files/slide-003.html</vh></v>
<v t="ekr.20230122011227.2"><vh>@rst html/slides/external-files/slide-004.html</vh></v>
<v t="ekr.20230122011227.3"><vh>@rst html/slides/external-files/slide-005.html</vh></v>
<v t="ekr.20230122011228.1"><vh>@rst html/slides/external-files/slide-006.html</vh></v>
<v t="ekr.20230122011228.2"><vh>@rst html/slides/external-files/slide-007.html</vh></v>
<v t="ekr.20230122011228.3"><vh>@rst html/slides/external-files/slide-008.html</vh></v>
<v t="ekr.20230122011228.4"><vh>@rst html/slides/external-files/slide-009.html</vh></v>
<v t="ekr.20230122011228.5"><vh>@rst html/slides/external-files/slide-010.html</vh></v>
<v t="ekr.20230122011229.1"><vh>@rst html/slides/external-files/slide-011.html</vh></v>
<v t="ekr.20230122011229.2"><vh>@rst html/slides/external-files/slide-012.html</vh></v>
<v t="ekr.20230122011229.3"><vh>@rst html/slides/external-files/slide-013.html</vh></v>
<v t="ekr.20230122011229.4"><vh>@rst html/slides/external-files/slide-014.html</vh></v>
<v t="ekr.20230122011229.5"><vh>@rst html/slides/external-files/slide-015.html</vh></v>
<v t="ekr.20230122011230.1"><vh>@rst html/slides/external-files/slide-016.html</vh></v>
<v t="ekr.20230122011230.2"><vh>@rst html/slides/external-files/slide-017.html</vh></v>
<v t="ekr.20230122011230.4"><vh>@rst html/slides/external-files/slide-019.html</vh></v>
<v t="ekr.20230122011230.5"><vh>@rst html/slides/external-files/slide-020.html</vh></v>
<v t="ekr.20230122011444.1"><vh>@rst html/slides/external-files/slide-021.html</vh></v>
<v t="ekr.20230122011445.1"><vh>@rst html/slides/external-files/slide-022.html</vh></v>
</v>
<v t="ekr.20230121061309.1"><vh>Slides: Leo's basics</vh>
<v t="ekr.20230121054950.1"><vh>@rst html/slides/basics/basics.html</vh></v>
<v t="ekr.20230121135204.1"><vh>@rst html/slides/basics/slide-002.html</vh></v>
<v t="ekr.20230121135205.1"><vh>@rst html/slides/basics/slide-003.html</vh></v>
<v t="ekr.20230121135205.2"><vh>@rst html/slides/basics/slide-004.html</vh></v>
<v t="ekr.20230121135205.3"><vh>@rst html/slides/basics/slide-005.html</vh></v>
<v t="ekr.20230121135206.1"><vh>@rst html/slides/basics/slide-006.html</vh></v>
<v t="ekr.20230121135206.2"><vh>@rst html/slides/basics/slide-007.html</vh></v>
<v t="ekr.20230121135206.3"><vh>@rst html/slides/basics/slide-008.html</vh></v>
<v t="ekr.20230121135206.4"><vh>@rst html/slides/basics/slide-009.html</vh></v>
<v t="ekr.20230121135206.5"><vh>@rst html/slides/basics/slide-010.html</vh></v>
<v t="ekr.20230121135312.2"><vh>@rst html/slides/basics/slide-011.html</vh></v>
<v t="ekr.20230121135312.3"><vh>@rst html/slides/basics/slide-012.html</vh></v>
<v t="ekr.20230121135312.4"><vh>@rst html/slides/basics/slide-013.html</vh></v>
<v t="ekr.20230121135312.5"><vh>@rst html/slides/basics/slide-014.html</vh></v>
<v t="ekr.20230121135312.6"><vh>@rst html/slides/basics/slide-015.html</vh></v>
<v t="ekr.20230121135312.7"><vh>@rst html/slides/basics/slide-016.html</vh></v>
<v t="ekr.20230121135312.8"><vh>@rst html/slides/basics/slide-017.html</vh></v>
<v t="ekr.20230121135312.9"><vh>@rst html/slides/basics/slide-018.html</vh></v>
<v t="ekr.20230121135312.10"><vh>@rst html/slides/basics/slide-019.html</vh></v>
<v t="ekr.20230121135312.11"><vh>@rst html/slides/basics/slide-020.html</vh></v>
<v t="ekr.20230121135448.2"><vh>@rst html/slides/basics/slide-021.html</vh></v>
<v t="ekr.20230121135448.3"><vh>@rst html/slides/basics/slide-022.html</vh></v>
<v t="ekr.20230121135448.4"><vh>@rst html/slides/basics/slide-023.html</vh></v>
<v t="ekr.20230121135448.5"><vh>@rst html/slides/basics/slide-024.html</vh></v>
<v t="ekr.20230121161822.1"><vh>@rst html/slides/basics/slide-025.html</vh></v>
</v>
<v t="ekr.20230121061335.1"><vh>Slides: Scripting</vh>
<v t="ekr.20230121055005.1"><vh>@rst html/slides/scripting-leo/scripting-leo.html</vh></v>
<v t="ekr.20230122081543.1"><vh>@rst html/slides/scripting-leo/slide-001.html</vh></v>
<v t="ekr.20230122081601.1"><vh>@rst html/slides/scripting-leo/slide-002.html</vh></v>
<v t="ekr.20230122081602.1"><vh>@rst html/slides/scripting-leo/slide-003.html</vh></v>
<v t="ekr.20230122081602.2"><vh>@rst html/slides/scripting-leo/slide-004.html</vh></v>
<v t="ekr.20230122081602.3"><vh>@rst html/slides/scripting-leo/slide-005.html</vh></v>
<v t="ekr.20230122081603.1"><vh>@rst html/slides/scripting-leo/slide-006.html</vh></v>
<v t="ekr.20230122081603.2"><vh>@rst html/slides/scripting-leo/slide-007.html</vh></v>
<v t="ekr.20230122081628.1"><vh>@rst html/slides/scripting-leo/slide-008.html</vh></v>
<v t="ekr.20230122081635.1"><vh>@rst html/slides/scripting-leo/slide-009.html</vh></v>
<v t="ekr.20230122081949.1"><vh>@rst html/slides/scripting-leo/slide-010.html</vh></v>
<v t="ekr.20230122081950.1"><vh>@rst html/slides/scripting-leo/slide-011.html</vh></v>
</v>
<v t="ekr.20230121061433.1"><vh>Slides: Minibuffer</vh>
<v t="ekr.20230121055019.1"><vh>@rst html/slides/minibuffer/minibuffer.html</vh></v>
<v t="ekr.20230122101310.1"><vh>@rst html/slides/minibuffer/slide-001.html</vh></v>
<v t="ekr.20230122101506.1"><vh>@rst html/slides/minibuffer/slide-002.html</vh></v>
<v t="ekr.20230122101506.2"><vh>@rst html/slides/minibuffer/slide-003.html</vh></v>
<v t="ekr.20230122101507.1"><vh>@rst html/slides/minibuffer/slide-004.html</vh></v>
<v t="ekr.20230122101507.2"><vh>@rst html/slides/minibuffer/slide-005.html</vh></v>
<v t="ekr.20230122101507.3"><vh>@rst html/slides/minibuffer/slide-006.html</vh></v>
<v t="ekr.20230122101507.4"><vh>@rst html/slides/minibuffer/slide-007.html</vh></v>
<v t="ekr.20230122101507.5"><vh>@rst html/slides/minibuffer/slide-008.html</vh></v>
<v t="ekr.20230122101508.1"><vh>@rst html/slides/minibuffer/slide-009.html</vh></v>
<v t="ekr.20230122101508.2"><vh>@rst html/slides/minibuffer/slide-010.html</vh></v>
<v t="ekr.20230122101508.3"><vh>@rst html/slides/minibuffer/slide-011.html</vh></v>
</v>
</v>
<v t="ekr.20131023151757.17122"><vh>Preliminaries</vh>
<v t="ekr.20131008041326.16079"><vh>@rst html/preliminaries.html</vh></v>
<v t="ekr.20131017174814.17479"><vh>@rst html/preface.html</vh></v>
<v t="ekr.20050831184021.4"><vh>@rst html/testimonials.html</vh>
<v t="ekr.20050830074815.1"><vh>Leo is revolutionary</vh></v>
<v t="ekr.20050830074815.2"><vh>Leo is a showcase Python application</vh></v>
<v t="ekr.20050830074815.3"><vh>Leo is fun, even addicting</vh></v>
<v t="ekr.20050830074815.4"><vh>Leo is a flexible, powerful IDE</vh></v>
<v t="ekr.20050830074815.5"><vh>Leo is a superb outliner</vh></v>
<v t="ekr.20050830074815.6"><vh>Leo is an excellent PIM</vh></v>
<v t="ekr.20050830074815.8"><vh>Leo is a superb documentation tool</vh></v>
<v t="ekr.20050830074815.9"><vh>Leo simplifies the understanding of complex systems</vh></v>
<v t="ekr.20050830074815.10"><vh>Leo is stable, well designed and well supported</vh></v>
<v t="ekr.20150326140024.1"><vh>Steve Zatz explains why @clean changes everything</vh></v>
<v t="ekr.20131023151757.17124"><vh>Quotes from Leo's developers</vh></v>
<v t="ekr.20050830074815.11"><vh>Longer quotes...</vh>
<v t="ekr.20050830074815.12"><vh> Speed Ream's slashdot article</vh></v>
<v t="ekr.20050830074815.13"><vh>Joe Orr</vh></v>
<v t="ekr.20050830074815.14"><vh>Dan Winkler</vh></v>
<v t="ekr.20050830074815.15"><vh>Dan Winkler 2</vh></v>
<v t="ekr.20050830074815.16"><vh>Dan Winkler 3</vh></v>
<v t="ekr.20131025044901.17144"><vh>Steve Litt</vh></v>
<v t="ekr.20141210095600.11"><vh>Dave Williams</vh></v>
<v t="ekr.20150923111606.1"><vh>John Lunzer</vh></v>
<v t="ekr.20170309071256.1"><vh>John Lunzer 2</vh></v>
<v t="ekr.20170618015524.1"><vh>Adrian Calvin</vh></v>
<v t="ekr.20200526090848.1"><vh>Satheesh Vattekkat</vh></v>
<v t="ekr.20220420153633.1"><vh>Thomas Passin</vh></v>
<v t="ekr.20241107122714.1"><vh>HaveF</vh></v>
</v>
<v t="ekr.20160304081437.7"><vh>Why Leo is noteworthy</vh>
<v t="ekr.20160304081437.8"><vh>Offray Luna Cárdenas</vh></v>
<v t="ekr.20160304081437.9"><vh>Speed's comments</vh></v>
</v>
<v t="ekr.20180226152739.1"><vh>How I discovered Leo</vh>
<v t="ekr.20180226152919.1"><vh>Terry Brown</vh></v>
<v t="ekr.20180303013046.1"><vh>Offray Vladimir Luna Cárdenas </vh></v>
<v t="ekr.20180226152847.1"><vh>Chris George</vh></v>
<v t="ekr.20180226152802.1"><vh>Satish Goda</vh></v>
<v t="ekr.20180303013437.1"><vh>David Szent-Györgyi</vh></v>
<v t="ekr.20180226152825.1"><vh>Rob Keeney</vh></v>
<v t="ekr.20180226152943.1"><vh>Kent Tenney</vh></v>
<v t="ekr.20180303013355.1"><vh>Matt Wilkie</vh></v>
</v>
</v>
<v t="ekr.20040414172218.4"><vh>@rst html/acknowledgements.html</vh>
<v t="ekr.20230119101059.1"><vh>@rst-no-head Opening quote</vh></v>
<v t="ekr.20230119101129.1"><vh>@rst-no-head Leo and More</vh></v>
<v t="ekr.20230119101215.1"><vh>@rst-no-head Leo's vips</vh></v>
<v t="ekr.20230119101405.1"><vh>@rst-no-head Contributors</vh></v>
<v t="ekr.20230119101501.1"><vh>@rst-no-head Plugin authores</vh></v>
<v t="ekr.20230119134825.1"><vh>@rst-no-head Licensing</vh></v>
</v>
<v t="ekr.20090221070927.1"><vh>@rst html/license.html</vh></v>
</v>
<v t="ekr.20131008041326.16092"><vh>Installing &amp; running Leo</vh>
<v t="ekr.20131015104133.16766"><vh>@rst html/getting-started.html</vh></v>
<v t="ekr.20131008041326.16094"><vh>@rst html/installing.html</vh>
<v t="ekr.20180130033527.1"><vh>Installing Leo from PyPi</vh></v>
<v t="ekr.20240302082146.1"><vh>Installing Leo from GitHub</vh></v>
<v t="ekr.20180126191031.1"><vh>Installing everything with Anaconda or Miniconda</vh></v>
<v t="ekr.20170206073747.9"><vh>Installing Leo on MacOs 10.7 (Lion) and later</vh></v>
</v>
<v t="ekr.20131008041326.16140"><vh>@rst html/running.html</vh>
<v t="ekr.20131008041326.16151"><vh>Running Leo</vh>
<v t="ekr.20131008041326.16152"><vh>Running Leo the first time</vh></v>
<v t="ekr.20131008041326.16153"><vh>Running Leo in batch mode</vh></v>
<v t="ekr.20131008041326.16154"><vh>Running Leo from a console window</vh></v>
<v t="ekr.20180226154417.1"><vh>Running Leo after pip install leo </vh></v>
<v t="ekr.20131008041326.16155"><vh>The .leo directory</vh></v>
</v>
<v t="ekr.20131008041326.16156"><vh>Leo's command-line options</vh></v>
<v t="ekr.20150323154836.1"><vh>Leo's workbook file</vh></v>
<v t="ekr.20141124094250.2"><vh>Using sessions</vh></v>
</v>
</v>
<v t="ekr.20050831195331.1"><vh>FAQ</vh>
<v t="ekr.20050830115714"><vh>@rst html\FAQ.html</vh>
<v t="ekr.20050830120007"><vh>@rst-no-head Links (FAQ)</vh></v>
<v t="ekr.20050830115714.1"><vh>Learning to use Leo</vh>
<v t="ekr.20161207052511.1"><vh>How can I learn Leo, or python, or anything</vh></v>
<v t="ekr.20050830115714.2"><vh>What's the best way to learn to use Leo?</vh></v>
<v t="ekr.20050830115714.7"><vh>When is using a section better than using a method?</vh></v>
</v>
<v t="ekr.20180529064813.1"><vh>Abbreviations</vh>
<v t="ekr.20170228104217.1"><vh>What are some useful abbreviations?</vh></v>
</v>
<v t="ekr.20180529064355.1"><vh>Clones</vh>
<v t="ekr.20150415110715.1"><vh>How can I eliminate clone wars?</vh></v>
<v t="ekr.20150415111217.1"><vh>How can I use clones to reorganize an outline?</vh></v>
<v t="ekr.20141108064630.8"><vh>How does EKR use clones?</vh></v>
<v t="ekr.20120229094652.15152"><vh>How does Leo handle clone conflicts?</vh></v>
<v t="ekr.20250317133518.1"><vh>How can Leonine scripts simulate half clones?</vh></v>
<v t="ekr.20060111192108"><vh>When is deleting a node dangerous?</vh></v>
<v t="ekr.20170228103914.1"><vh>When may I delete clones safely?</vh></v>
<v t="ekr.20110521135104.18151"><vh>Why doesn't Leo support cross-outline clones?</vh></v>
<v t="ekr.20150415105956.1"><vh>Why is Alt-N (goto-next-clone) important?</vh></v>
<v t="ekr.20050830115714.4"><vh>Why should I use clones?</vh></v>
</v>
<v t="ekr.20050830115714.26"><vh>Customizing Leo</vh>
<v t="ekr.20141108064630.18"><vh>How can I create a pane for matplotlib charts?</vh></v>
<v t="ekr.20190731085747.1"><vh>How can I customize settings for a particular external file?</vh></v>
<v t="ekr.20060915112109"><vh>How can I enable and disable support for psyco?</vh></v>
<v t="ekr.20190620113133.1"><vh>How can I modify an existing theme?</vh></v>
<v t="ekr.20141108064630.16"><vh>How can I put background images in the body pane?</vh></v>
<v t="ekr.20180529064307.1"><vh>How can I run code at startup?</vh></v>
<v t="ekr.20180619051649.1"><vh>How can I sync settings across .leo files?</vh></v>
<v t="ekr.20160304081437.3"><vh>How do I enable a theme .leo file?</vh></v>
<v t="ekr.20060805094325"><vh>How can I use Leo's legacy key bindings?</vh></v>
<v t="ekr.20050830120844"><vh>How do I add a new menu item from a plugin?</vh></v>
<v t="ekr.20110531155858.20564"><vh>How do I set selection colors and fonts?</vh></v>
<v t="ekr.20050830115714.30"><vh>How do I submit a plugin?</vh></v>
</v>
<v t="ekr.20180126190015.1"><vh>Excel</vh>
<v t="ekr.20050830115714.116"><vh>How can I show Leo files with Excel?</vh></v>
</v>
<v t="ekr.20050830115714.13"><vh>Files</vh>
<v t="ekr.20050830115714.24"><vh>Can @file trees contain material not in the external file?</vh></v>
<v t="shadow.20080825171547.9"><vh>How can I avoid getting long lines in external files?</vh></v>
<v t="ekr.20050830115714.113"><vh>How can I create a template .leo file?</vh></v>
<v t="ekr.20050830115714.18"><vh>How can I create Javascript comments?</vh></v>
<v t="ekr.20050830115714.19"><vh>How can I disable PHP comments?</vh></v>
<v t="felix.20251005130847.1"><vh>How can I export as a user-friendly HTML file?</vh></v>
<v t="ekr.20180212165141.1"><vh>How can I open special .leo files easily?</vh></v>
<v t="ekr.20141030042423.9"><vh>How can I specify the root directory of a thumb drive?</vh></v>
<v t="ekr.20050830115714.25"><vh>How can I use Leo with older C compilers</vh></v>
<v t="ekr.20050830115714.20"><vh>How can I use Leo with unsupported languages?</vh></v>
<v t="ekr.20050830115714.14"><vh>How do I inhibit sentinels in external files?</vh></v>
<v t="ekr.20050830115714.21"><vh>How do I make external files start with a shebang line?</vh></v>
<v t="ekr.20050830115714.16"><vh>How do I prevent Leo from expanding sections?</vh></v>
<v t="ekr.20060529053407"><vh>Why can't I use @ignore directives in @file trees?</vh></v>
</v>
<v t="ekr.20180126190053.1"><vh>Git</vh>
<v t="ekr.20130807203905.16526"><vh>How can I use git to check Leo's importers?</vh></v>
<v t="ekr.20160304081437.5"><vh>How can I use Leo with git?</vh></v>
<v t="ekr.20050830115714.12"><vh>How should I use Leo with git, etc.?</vh></v>
<v t="ekr.20180130105010.1"><vh>What is a reference .leo file?</vh></v>
<v t="ekr.20171027125705.1"><vh>Why do files sometimes change when switching branches?</vh></v>
</v>
<v t="ekr.20180529065538.1"><vh>Graphics</vh>
<v t="ekr.20050830115714.120"><vh>How can I display graphics in Leo?</vh></v>
<v t="ekr.20131122055946.16401"><vh>How can I make a screencast?</vh>
<v t="ekr.20131122055946.16402"><vh>Use a script to open your app</vh></v>
<v t="ekr.20131122055946.16403"><vh>Debug your workflow with short videos</vh></v>
<v t="ekr.20131122055946.16404"><vh>Emulate the screencast.com tutorials</vh></v>
<v t="ekr.20131122055946.16405"><vh>Record your first real take</vh></v>
<v t="ekr.20131122055946.16406"><vh>Edit your raw take</vh></v>
<v t="ekr.20131122055946.16407"><vh>Summary</vh></v>
<v t="ekr.20131129061821.16884"><vh>Additional tips</vh></v>
<v t="ekr.20131211054925.16388"><vh>Tips for improving audio</vh></v>
</v>
</v>
<v t="ekr.20180529065039.1"><vh>Importing files</vh>
<v t="ekr.20050830115714.74"><vh>How can I import many files at once?</vh></v>
</v>
<v t="ekr.20180126185857.1"><vh>LaTeX</vh>
<v t="ekr.20180124094454.1"><vh>How can I produce PDF output from LaTex input?</vh></v>
<v t="ekr.20120229094652.15148"><vh>How can I use BibTeX citations from Leo?</vh></v>
</v>
<v t="ekr.20180529062944.1"><vh>Markdown &amp; Sphinx</vh>
<v t="ekr.20180529063449.1"><vh>How can I create markdown files?</vh></v>
<v t="ekr.20180529064039.1"><vh>How can I create a markdown table of contents?</vh></v>
<v t="ekr.20180529062956.1"><vh>How can I use Markdown with Sphinx?</vh></v>
</v>
<v t="ekr.20141109053526.4"><vh>Scripting &amp; Testing</vh>
<v t="ekr.20141108064630.15"><vh>How can I create buttons with dropdown menus?</vh></v>
<v t="ekr.20120229094652.15099"><vh>How can I make commonly-used scripts widely accessible?</vh></v>
<v t="ekr.20160415031743.21"><vh>How can I organize large docstrings?</vh></v>
<v t="ekr.20190307095247.1"><vh>How can I run code in an external process?</vh></v>
<v t="ekr.20210607135729.1"><vh>How can I run scripts in languages other than python?</vh></v>
<v t="ekr.20160428105918.1"><vh>How can I run pylint outside of Leo?</vh></v>
<v t="ekr.20131115075142.16636"><vh>How can I test settings easily?</vh></v>
<v t="ekr.20141108064630.12"><vh>How can I use setuptools instead of .bat files?</vh></v>
<v t="ekr.20141108064630.13"><vh>How can scripts call functions from Leo's core?</vh></v>
<v t="ekr.20170612093902.1"><vh>How do I choose between @others and section references?</vh></v>
<v t="ekr.20141108064630.14"><vh>How to use leo to make mathematical notes?</vh></v>
<v t="ekr.20080527063511.1"><vh>What is an easy way to profile code?</vh></v>
</v>
<v t="ekr.20050830115714.76"><vh>Trouble shooting</vh>
<v t="ekr.20050830115714.115"><vh>Error messages from the rst3 plugin aren't helpful. What can I do?</vh></v>
<v t="ekr.20200213034654.1"><vh>How can I move Leo's window back on screen?</vh></v>
<v t="ekr.20050906090012"><vh>How can I run Leo from a console window?</vh></v>
<v t="ekr.20050830115714.77"><vh>How can I use Python's pdb debugger with Leo?</vh></v>
<v t="ekr.20090130144433.1"><vh>How do I get help?</vh></v>
<v t="ekr.20160123060917.1"><vh>How do I make Ctrl-Shift-0 work on Windows 8 or 10?</vh></v>
<v t="ekr.20090130144433.2"><vh>How do I report bugs?</vh></v>
<v t="ekr.20240818070101.1"><vh>How do I install PyQt6-WebEngine on linux?</vh></v>
<v t="ekr.20160318142213.1"><vh>I am having trouble installing Leo on MacOS. What should I do?</vh></v>
<v t="ekr.20070816092449"><vh>I can't run the LeoBridge module outside of leo/core.  What should I do?</vh></v>
<v t="ekr.20050830115714.17"><vh>I can't write Imported files.  What's going on?</vh></v>
<v t="ekr.20080813064908.2"><vh>My old .leo files won't load using Leo 4.5 or later. What should I do?</vh></v>
<v t="ekr.20060329101442"><vh>Nothing (or almost nothing) happens when I start Leo.  What should I do?</vh></v>
<v t="ekr.20070623145346.1"><vh>Running Python setup.py install from the leo directory doesn't work.  Why not?</vh></v>
<v t="ekr.20050830115714.117"><vh>The new Python decorator syntax causes problems.  What can I do?</vh></v>
<v t="ekr.20191002072123.1"><vh>Themes aren't working for me. What should I do?</vh></v>
<v t="ekr.20101026082911.5538"><vh>Why didn't Leo update my @clean outline as expected?</vh></v>
<v t="ekr.20120229094652.15130"><vh>Why do Qt windows disappear in my scripts?</vh></v>
<v t="ekr.20180212070758.1"><vh>Why isn't the Spell tab showing?</vh></v>
</v>
<v t="ekr.20071026055929"><vh>Unicode</vh>
<v t="ekr.20061021164213"><vh>I can not enter non-ascii characters.  What can I do?</vh></v>
<v t="ekr.20050830115714.9"><vh>Some characters in external files look funny. What can I do?</vh></v>
<v t="ekr.20060917130130"><vh>I get weird results when defining unicode strings in scripts.  What is going on?</vh></v>
<v t="ekr.20050830115714.10"><vh>Some characters are garbled when importing files. What can I do?</vh></v>
<v t="ekr.20071026055929.1"><vh>Python's print statement shows 'byte hash' for unicode characters.  What can I do?</vh></v>
</v>
<v t="ekr.20190802082825.1"><vh>Vim</vh>
<v t="ekr.20190622142940.1"><vh>How can I use Leo's bridge in vim?</vh></v>
</v>
<v t="ekr.20180529065351.1"><vh>Work flow</vh>
<v t="ekr.20150416100041.1"><vh>How can I organize data so I can find stuff later?</vh></v>
<v t="ekr.20120229094652.15124"><vh>How can I restore focus without using the mouse</vh></v>
<v t="ekr.20050830115714.119"><vh>How can I see two nodes at once?</vh></v>
<v t="ekr.20090706042206.14718"><vh>How can I use Leo cooperatively without sentinels?</vh></v>
<v t="ekr.20141109053526.8"><vh>How can I use the GTD workflow in Leo?</vh></v>
</v>
</v>
</v>
<v t="ekr.20091130111843.6787"><vh>Tutorials</vh>
<v t="ekr.20091130111843.6788"><vh>@rst html\tutorial.html</vh></v>
<v t="ekr.20131008041326.16203"><vh>@rst html\tutorial-basics.html</vh>
<v t="ekr.20131002055813.15973"><vh>Leo's main window</vh></v>
<v t="ekr.20170215105125.1"><vh>Commands</vh></v>
<v t="ekr.20170215031129.1"><vh>Outlines and clones</vh></v>
<v t="ekr.20131004064408.16020"><vh>Leo directives</vh></v>
<v t="ekr.20131003040744.18221"><vh>External files</vh>
<v t="ekr.20170314060847.1"><vh>\@file</vh></v>
<v t="ekr.20170314060926.1"><vh>Markup</vh></v>
<v t="ekr.20170314061000.1"><vh>\@clean</vh></v>
<v t="ekr.20170314061022.1"><vh>\@all</vh></v>
</v>
<v t="ekr.20131001100335.15940"><vh>Configuring Leo</vh></v>
<v t="ekr.20131009100732.19038"><vh>Plugins</vh></v>
<v t="ekr.20170215082032.1"><vh>Scripting basics</vh>
<v t="ekr.20170217093636.1"><vh>Scripting markup</vh></v>
<v t="ekr.20170217093639.1"><vh>c, g, and p</vh></v>
<v t="ekr.20170217093640.1"><vh>Accessing outline data</vh></v>
<v t="ekr.20170217093640.2"><vh>\@button and @command nodes</vh></v>
<v t="ekr.20170217093641.1"><vh>Autocompletion and calltips</vh></v>
</v>
<v t="ekr.20131005214621.16090"><vh>Summary</vh></v>
</v>
<v t="ekr.20131008041326.16222"><vh>@rst html\tutorial-pim.html</vh>
<v t="ekr.20131004073415.16044"><vh>Clones</vh></v>
<v t="ekr.20131018100353.16706"><vh>Clones create views</vh></v>
<v t="ekr.20131009100732.16760"><vh>Using abbreviations and templates</vh></v>
<v t="ekr.20131009100732.16737"><vh>Using URLs</vh></v>
<v t="ekr.20170312083548.1"><vh>Using Chapters</vh></v>
<v t="ekr.20131008041326.16066"><vh>Summary</vh></v>
</v>
<v t="ekr.20131008041326.16241"><vh>@rst html\tutorial-rst3.html</vh>
<v t="ekr.20131102044158.16488"><vh>Install docutils and (optional) sphinx</vh></v>
<v t="ekr.20131009100732.16748"><vh>Create the @rst node</vh></v>
<v t="ekr.20131027064821.17144"><vh>The output and intermediate files</vh></v>
<v t="ekr.20131009100732.16754"><vh>Choose docutils or sphinx</vh>
<v t="ekr.20131027064821.18689"><vh>Setting up conf.py for sphinx</vh></v>
</v>
<v t="ekr.20131009100732.16750"><vh>Put a title in the @rst node </vh></v>
<v t="ekr.20131024051649.17136"><vh>Start the chapter</vh></v>
<v t="ekr.20131024051649.17137"><vh>Create sections and subsections</vh></v>
<v t="ekr.20131009100732.16751"><vh>Write your document</vh></v>
<v t="ekr.20131009100732.16752"><vh>Run the rst3 command</vh></v>
<v t="ekr.20131028213522.17150"><vh>Other topics</vh>
<v t="ekr.20131009100732.16755"><vh>\@rst-no-head suppresses sections</vh></v>
<v t="ekr.20131025044901.17147"><vh>\@rst-ignore &amp; @rst-ignore-tree ignore text</vh></v>
<v t="ekr.20131025044901.17148"><vh>Inserting raw markup</vh></v>
<v t="ekr.20220129083216.1"><vh>Filtering contents</vh></v>
</v>
<v t="ekr.20131005214621.16128"><vh>Summary</vh></v>
<v t="ekr.20131009100732.16753"><vh>Further study</vh></v>
</v>
<v t="ekr.20040403171740"><vh>@rst html\tutorial-scripting.html</vh>
<v t="ekr.20131013060803.16852"><vh>Hello world</vh></v>
<v t="ekr.20170313111502.1"><vh>Create outline nodes</vh></v>
<v t="ekr.20170313111626.1"><vh>Generate an output file from nodes</vh></v>
<v t="ekr.20070120075236"><vh>Predefined symbols: c, g, and p</vh></v>
<v t="ekr.20131014050027.16801"><vh>Positions and vnodes</vh></v>
<v t="ekr.20131012060912.16775"><vh>Generators</vh></v>
<v t="ekr.20150312080344.12"><vh>wrappers vs. widgets</vh></v>
<v t="ekr.20131016021541.16893"><vh>Summary</vh></v>
<v t="ekr.20131017051340.16732"><vh>@rst-ignore-tree scripting examples</vh>
<v t="ekr.20131017051340.16733"><vh>An example outline</vh></v>
<v t="ekr.20131017051340.16735"><vh>Example position scripts</vh></v>
</v>
</v>
<v t="ekr.20180126061923.1"><vh>@rst html\tutorial-tips.html</vh>
<v t="ekr.20180126063015.1"><vh>The most important tips</vh>
<v t="ekr.20180126061429.16"><vh>You don't have to remember command names</vh></v>
<v t="ekr.20180126061429.15"><vh>Learn to use clones</vh></v>
</v>
<v t="ekr.20180126062746.1"><vh>Learning to use Leo</vh>
<v t="ekr.20180126061429.13"><vh>Leo's most important plugins</vh></v>
<v t="ekr.20180126061429.27"><vh>Move clones to the last top-level node</vh></v>
<v t="ekr.20180126061429.14"><vh>Put personal settings myLeoSettings.leo</vh></v>
<v t="ekr.20180126061429.25"><vh>Search for settings in leoSettings.leo</vh></v>
<v t="ekr.20180126061429.10"><vh>Use abbreviations</vh></v>
</v>
<v t="ekr.20180126062558.1"><vh>Useful commands and actions</vh>
<v t="ekr.20180126061429.7"><vh>The beautify command &amp; @nobeautify directive</vh></v>
<v t="ekr.20180126061429.22"><vh>The find-quick-selected command</vh></v>
<v t="ekr.20180126061429.23"><vh>The parse-body command</vh></v>
<v t="ekr.20180126061429.6"><vh>The pyflakes command</vh></v>
<v t="ekr.20180126061429.8"><vh>The pylint command</vh></v>
<v t="ekr.20180126061429.9"><vh>The rst3 command</vh></v>
<v t="ekr.20180126061429.24"><vh>The sort-siblings command</vh></v>
<v t="ekr.20180126061429.26"><vh>Use Alt-N (goto-next-clone) to find "primary" clones</vh></v>
<v t="ekr.20180126061429.18"><vh>Use cffm to gather outline nodes</vh></v>
<v t="ekr.20180126184230.1"><vh>Use Ctrl-P (repeat-complex-command) to avoid key bindings</vh></v>
</v>
<v t="ekr.20180126062701.1"><vh>Scripting tips</vh>
<v t="ekr.20180126061429.3"><vh>Clearing the Log window</vh></v>
<v t="ekr.20180126061429.19"><vh>g.callers() returns a list of callers</vh></v>
<v t="ekr.20180126061429.5"><vh>The @button make-md-toc script in LeoDocs.leo</vh></v>
<v t="ekr.20180126061429.12"><vh>Use @button nodes</vh></v>
<v t="ekr.20180126061429.2"><vh>Use a universal shortcut for your scripts</vh></v>
<v t="ekr.20180126061429.17"><vh>Use cff to gather nodes matching a pattern</vh></v>
<v t="ekr.20180126061429.21"><vh>Use g.pdb from the console</vh></v>
<v t="ekr.20180126061429.20"><vh>Use g.trace to debug scripts</vh></v>
<v t="ekr.20180126061429.4"><vh>Use section references sparingly</vh></v>
<v t="ekr.20220129091501.1"><vh>Use g.handleUnl to select nodes</vh></v>
</v>
</v>
</v>
<v t="ekr.20131008041326.16080"><vh>Users Guide</vh>
<v t="ekr.20230628032632.1"><vh>@rst html/clickablelinks.html</vh></v>
<v t="ekr.20131008041326.16082"><vh>@rst html/usersguide.html</vh></v>
<v t="ekr.20200909171301.1"><vh>@rst html/leomarkup.html</vh></v>
<v t="ekr.20050901101608.4"><vh>@rst html/customizing.html</vh>
<v t="EKR.20040524104904.140"><vh>Using settings</vh>
<v t="ekr.20090116130002.1"><vh>Configuration directories</vh></v>
<v t="ekr.20090116094356.2"><vh>Search order for settings files</vh></v>
<v t="ekr.20090116094356.3"><vh>Safe rules for local settings</vh></v>
<v t="ekr.20070317043727"><vh>Organizer nodes</vh></v>
<v t="ekr.20080411111008.1"><vh>\@ignore and \@if nodes</vh></v>
<v t="ekr.20070317043727.2"><vh>Simple settings nodes</vh></v>
<v t="ekr.20070317043727.3"><vh>Complex settings nodes</vh>
<v t="ekr.20090116094356.5"><vh>\@buttons</vh></v>
<v t="ekr.20090116094356.6"><vh>\@commands</vh></v>
<v t="ekr.20160428111506.1"><vh>\@command-history</vh></v>
<v t="ekr.20090116094356.7"><vh>\@data</vh></v>
<v t="ekr.20090116094356.8"><vh>\@enabled-plugins</vh></v>
<v t="ekr.20090116094356.11"><vh>\@font</vh></v>
<v t="ekr.20090116094356.10"><vh>\@menuat</vh></v>
<v t="ekr.20090116094356.9"><vh>\@menus</vh></v>
<v t="ekr.20090116094356.14"><vh>\@mode</vh></v>
<v t="ekr.20180224050255.1"><vh>\@rclick</vh></v>
<v t="ekr.20090116094356.13"><vh>\@recentfiles</vh></v>
<v t="ekr.20090116094356.12"><vh>\@shortcuts</vh></v>
</v>
</v>
<v t="ekr.20241112064750.1"><vh>Controlling syntax coloring</vh>
<v t="ekr.20190422181351.1"><vh>Color settings</vh></v>
<v t="ekr.20190422182440.1"><vh>Font settings</vh></v>
</v>
<v t="ekr.20210402080752.1"><vh>Customizing the rst3 command</vh></v>
<v t="ekr.20180404065846.1"><vh>Theme files</vh></v>
<v t="ekr.20060105214753"><vh>Input modes</vh></v>
<v t="ekr.20050306090601"><vh>uA's: extensible attribues of nodes</vh></v>
<v t="ekr.20170228112643.1"><vh>Decluttering headlines</vh>
<v t="ekr.20171122090736.1"><vh>Examples</vh></v>
<v t="ekr.20171122090711.1"><vh>Rule &amp; replacement lines</vh></v>
<v t="ekr.20171122090722.1"><vh>Style lines</vh></v>
</v>
<v t="ekr.20080310093038.4"><vh>Translating Leo's menus and messages</vh></v>
</v>
<v t="ekr.20050912125144.1"><vh>@rst html/plugins.html</vh>
<v t="ekr.20070814104719"><vh>Enabling plugins</vh></v>
<v t="ekr.20101113063552.9398"><vh>Summary</vh></v>
<v t="ekr.20101113063552.9528"><vh>Gui-independent plugins</vh>
<v t="ekr.20101113063552.9412"><vh>Commands &amp; directives</vh>
<v t="ekr.20101113063552.9413"><vh>add_directives.py</vh></v>
<v t="ekr.20101113063552.9414"><vh>bzr_qcommands.py</vh></v>
<v t="ekr.20170314091824.1"><vh>codewisecompleter.py</vh></v>
<v t="ekr.20170314091826.1"><vh>ctagscompleter.py</vh></v>
<v t="ekr.20101113063552.9415"><vh>empty_leo_file.py</vh></v>
<v t="ekr.20170314091927.1"><vh>ftp.py</vh></v>
<v t="ekr.20170314091958.1"><vh>gitarchive.py</vh></v>
<v t="ekr.20101113063552.9416"><vh>import_cisco_config.py</vh></v>
<v t="ekr.20101113063552.9417"><vh>initinclass.py</vh></v>
<v t="ekr.20170314092023.1"><vh>leofeeds.py</vh></v>
<v t="ekr.20170314092041.1"><vh>leomail.py</vh></v>
<v t="ekr.20101113063552.9418"><vh>leo_interface.py</vh></v>
<v t="ekr.20101113063552.9419"><vh>lineNumbers.py</vh></v>
<v t="ekr.20101113063552.9420"><vh>macros.py</vh></v>
<v t="ekr.20170314092107.1"><vh>markup_inline.py</vh></v>
<v t="ekr.20101113063552.9421"><vh>mod_autosave.py</vh></v>
<v t="ekr.20101113063552.9422"><vh>mod_read_dir_outline.py</vh></v>
<v t="ekr.20101113063552.9423"><vh>mod_timestamp.py</vh></v>
<v t="ekr.20101113063552.9798"><vh>nodeActions.py</vh></v>
<v t="ekr.20170314092126.1"><vh>nodediff.py</vh></v>
<v t="ekr.20101113063552.9425"><vh>outline_export.py</vh></v>
<v t="ekr.20101113063552.9426"><vh>paste_as_headlines.py</vh></v>
<v t="ekr.20101113063552.9428"><vh>quickMove.py</vh></v>
<v t="ekr.20101113063552.9429"><vh>setHomeDirectory.py</vh></v>
<v t="ekr.20170314092144.1"><vh>sftp.py</vh></v>
<v t="ekr.20170314092158.1"><vh>threadutil.py</vh></v>
<v t="ekr.20101113063552.9430"><vh>word_count.py</vh></v>
<v t="ekr.20170314092222.1"><vh>xml_edit</vh></v>
</v>
<v t="ekr.20101113063552.9431"><vh>Debugging</vh>
<v t="ekr.20101113063552.9432"><vh>debugger_pudb.py</vh></v>
<v t="ekr.20101113063552.9433"><vh>dump_globals.py</vh></v>
<v t="ekr.20101113063552.9434"><vh>enable_gc.py</vh></v>
<v t="ekr.20101113063552.9435"><vh>quit_leo.py</vh></v>
<v t="ekr.20101113063552.9436"><vh>trace_gc_plugin.py</vh></v>
<v t="ekr.20101113063552.9437"><vh>trace_keys.py</vh></v>
<v t="ekr.20101113063552.9438"><vh>trace_tags.py</vh></v>
</v>
<v t="ekr.20101113063552.9439"><vh>External programs</vh>
<v t="ekr.20101113063552.9442"><vh>open_shell.py</vh></v>
<v t="ekr.20101113063552.9443"><vh>tomboy_import.py</vh></v>
<v t="ekr.20101113063552.9444"><vh>vim.py</vh></v>
<v t="ekr.20101113063552.9445"><vh>xemacs.py</vh></v>
<v t="ekr.20101113063552.9446"><vh>word_export.py</vh></v>
</v>
<v t="ekr.20101113063552.9447"><vh>Files and nodes</vh>
<v t="ekr.20101113063552.9448"><vh>active_path.py</vh></v>
<v t="ekr.20101113063552.9449"><vh>at_folder.py</vh></v>
<v t="ekr.20101113063552.9450"><vh>at_produce.py</vh></v>
<v t="ekr.20101113063552.9451"><vh>at_view.py</vh></v>
<v t="ekr.20101113063552.9452"><vh>backlink.py</vh></v>
<v t="ekr.20101113063552.9453"><vh>datenodes.py</vh></v>
<v t="ekr.20101113063552.9454"><vh>expfolder.py</vh></v>
<v t="ekr.20101113063552.9455"><vh>FileActions.py</vh></v>
<v t="ekr.20101113063552.9456"><vh>geotag.py</vh></v>
<v t="ekr.20101113063552.9457"><vh>leocursor.py</vh></v>
<v t="ekr.20170314091526.1"><vh>leoOPML.py</vh></v>
<v t="felix.20251005132812.1"><vh>leo_to_html_outline_viewer.py</vh></v>
<v t="ekr.20101113063552.9458"><vh>mime.py</vh></v>
<v t="ekr.20101113063552.9459"><vh>multifile.py</vh></v>
<v t="ekr.20101113063552.9460"><vh>niceNosent.py</vh></v>
<v t="ekr.20170314091627.1"><vh>notebook.py</vh></v>
<v t="ekr.20101113063552.9461"><vh>read_only_nodes.py</vh></v>
<v t="ekr.20101113063552.9462"><vh>run_nodes.py</vh></v>
<v t="ekr.20101113063552.9464"><vh>startfile.py</vh></v>
<v t="ekr.20130815102041.15632"><vh>timestamp.py</vh></v>
<v t="ekr.20101113063552.9466"><vh>xsltWithNodes.py</vh></v>
</v>
<v t="ekr.20101113063552.9467"><vh>Scripting</vh>
<v t="ekr.20050912125735.363"><vh>dyna_menu</vh></v>
<v t="ekr.20101113063552.9468"><vh>leoscreen.py</vh></v>
<v t="ekr.20101113063552.9469"><vh>mod_scripting.py</vh></v>
<v t="ekr.20101113063552.9470"><vh>script_io_to_body.py</vh></v>
</v>
<v t="ekr.20101113063552.9471"><vh>Servers</vh>
<v t="ekr.20171018084145.1"><vh>leo_cloud.py</vh></v>
<v t="ekr.20101113063552.9472"><vh>leoremote.py</vh></v>
<v t="ekr.20101113063552.9473"><vh>mod_http.py</vh></v>
</v>
<v t="ekr.20101113063552.9474"><vh>Slideshows and screenshots</vh>
<v t="ekr.20170225081012.1"><vh>demo.py</vh></v>
<v t="ekr.20101113063552.9475"><vh>screenshots.py</vh></v>
<v t="ekr.20101113063552.9463"><vh>slideshow.py</vh></v>
</v>
<v t="ekr.20101113063552.9476"><vh>Text formatting</vh>
<v t="ekr.20101113063552.9477"><vh>bibtex.py</vh></v>
<v t="ekr.20101113063552.9478"><vh>dtest.py</vh></v>
<v t="ekr.20101113063552.9800"><vh>leo_to_html.py</vh></v>
<v t="ekr.20101113063552.9480"><vh>leo_to_rtf.py</vh></v>
</v>
<v t="ekr.20101113063552.9482"><vh>User interface</vh>
<v t="ekr.20101113063552.9484"><vh>chapter_hoist.py</vh></v>
<v t="ekr.20101113063552.9486"><vh>EditAttributes.py</vh></v>
<v t="ekr.20101113063552.9487"><vh>interact.py</vh></v>
<v t="ekr.20101113063552.9488"><vh>maximizeNewWindows.py</vh></v>
<v t="ekr.20101113063552.9489"><vh>mod_framesize.py</vh></v>
<v t="ekr.20101113063552.9794"><vh>plugins_menu.py</vh></v>
<v t="ekr.20101113063552.9491"><vh>redirect_to_log.py</vh></v>
<v t="ekr.20101113063552.9492"><vh>scripts_menu.py</vh></v>
<v t="ekr.20101113063552.9493"><vh>zenity_file_dialogs.py</vh></v>
</v>
</v>
<v t="ekr.20101113063552.9399"><vh>Qt only plugins</vh>
<v t="ekr.20101113063552.9400"><vh>attrib_edit.py</vh></v>
<v t="ekr.20141105055521.8"><vh>bigdash.py</vh></v>
<v t="ekr.20131009100732.19039"><vh>bookmarks.py</vh></v>
<v t="ekr.20101113063552.9401"><vh>colorize_headlines.py</vh></v>
<v t="ekr.20101113063552.9402"><vh>contextmenu.py</vh></v>
<v t="ekr.20170314090749.1"><vh>dragdropgoodies.py</vh></v>
<v t="ekr.20101113063552.9411"><vh>graphcanvas.py</vh></v>
<v t="ekr.20130815102041.15628"><vh>leomylyn.py</vh></v>
<v t="ekr.20141105055521.5"><vh>livecode.py</vh></v>
<v t="ekr.20101113063552.9403"><vh>nav_qt.py</vh></v>
<v t="ekr.20141105055521.6"><vh>nodetags.py</vh></v>
<v t="ekr.20130815102041.15618"><vh>printing.py</vh></v>
<v t="ekr.20101113063552.9404"><vh>projectwizard.py</vh></v>
<v t="ekr.20170314090824.1"><vh>python_terminal.py</vh></v>
<v t="ekr.20170314090914.1"><vh>QNCalendarWidgets</vh></v>
<v t="ekr.20101113063552.9405"><vh>quicksearch.py</vh></v>
<v t="ekr.20170314091002.1"><vh>richtext.py</vh></v>
<v t="ekr.20130815102041.15630"><vh>screen_capture.py</vh></v>
<v t="ekr.20130815102041.15631"><vh>screencast.py</vh></v>
<v t="ekr.20101113063552.9406"><vh>scrolledmessage.py</vh></v>
<v t="ekr.20170314091035.1"><vh>settings_finder.py</vh></v>
<v t="ekr.20101113063552.9407"><vh>spydershell.py</vh></v>
<v t="ekr.20101113063552.9408"><vh>stickynotes.py</vh></v>
<v t="ekr.20170314091127.1"><vh>systray.py</vh></v>
<v t="ekr.20101113063552.9409"><vh>todo.py</vh></v>
<v t="ekr.20101113063552.9410"><vh>viewrendered.py</vh></v>
<v t="ekr.20141105055521.7"><vh>viewrendered2.py</vh></v>
<v t="ekr.20170314091206.1"><vh>wikiview.py</vh></v>
</v>
</v>
<v t="ekr.20050901101608.2"><vh>@rst html/commands.html</vh>
<v t="ekr.20131001100335.15946"><vh>Executing commands from the minibuffer</vh>
<v t="ekr.20170312085351.1"><vh>Typing completion</vh></v>
<v t="ekr.20170312085434.1"><vh>Filename completion</vh></v>
</v>
<v t="ekr.20170215102815.1"><vh>Most important commands</vh>
<v t="ekr.20131004191204.16079"><vh>File operations &amp; sessions</vh></v>
<v t="ekr.20150315132217.3"><vh>Switching focus</vh></v>
<v t="ekr.20131002055813.19835"><vh>Outline commands</vh></v>
<v t="ekr.20131002055813.19036"><vh>Selecting outline nodes</vh></v>
<v t="ekr.20131002055813.19037"><vh>Moving the cursor</vh></v>
<v t="ekr.20131001100335.15938"><vh>Finding &amp; replacing text</vh></v>
<v t="ekr.20191004123555.1"><vh>Formatting text</vh></v>
<v t="ekr.20131002055813.19837"><vh>Undoing and redoing changes</vh></v>
<v t="ekr.20160428113347.1"><vh>Clone-find commands</vh></v>
<v t="ekr.20230105123159.1"><vh>Syncing @clean files</vh></v>
<v t="ekr.20131001100335.15947"><vh>Help commands</vh></v>
<v t="ekr.20190414191837.1"><vh>Debugger commands</vh></v>
</v>
<v t="ekr.20170215103337.1"><vh>All other commands</vh>
<v t="ekr.20160428110816.1"><vh>Clone-find commands</vh></v>
<v t="ekr.20150318110552.10"><vh>Debug commands</vh>
<v t="ekr.20161020064204.1"><vh>Running External debuggers</vh></v>
<v t="ekr.20161020064706.1"><vh>Printing settings and other data</vh></v>
<v t="ekr.20161020064436.1"><vh>Other debugging commands</vh></v>
</v>
<v t="ekr.20150318110552.18"><vh>Edit commands</vh>
<v t="ekr.20150318110552.21"><vh>Cutting, pasting and selecting text</vh></v>
<v t="ekr.20150318110552.22"><vh>Indenting body text</vh></v>
<v t="ekr.20150318110552.23"><vh>Adding and deleting comments in body text</vh></v>
<v t="ekr.20150323200607.1"><vh>Moving the cursor</vh></v>
<v t="ekr.20150318110552.24"><vh>Text formatting commands</vh></v>
<v t="ekr.20150318110552.25"><vh>Creating nodes from body text</vh></v>
<v t="ekr.20150318110552.26"><vh>Executing Python scripts in body text</vh></v>
<v t="ekr.20150318110552.20"><vh>Undoing changes</vh></v>
</v>
<v t="ekr.20150323185514.1"><vh>Emacs-like commands</vh>
<v t="ekr.20150318110552.74"><vh>Abbreviation commands</vh></v>
<v t="ekr.20150318110552.8"><vh>Cursor movement commands</vh></v>
<v t="ekr.20150323185921.1"><vh>Emacs text formatting</vh></v>
<v t="ekr.20150323103115.1"><vh>Rectangle commands</vh></v>
<v t="ekr.20150318110552.56"><vh>Scrolling the outline pane</vh></v>
<v t="ekr.20150323185611.1"><vh>Yank, kill &amp; delete commands</vh></v>
</v>
<v t="ekr.20150318110552.29"><vh>File commands</vh>
<v t="ekr.20150318110552.30"><vh>Loading, saving &amp; reverting files</vh></v>
<v t="ekr.20150318110552.31"><vh>Closing outlines &amp; quitting Leo</vh></v>
<v t="ekr.20150318110552.32"><vh>Importing &amp; exporting files</vh></v>
<v t="ekr.20150318110552.33"><vh>Using sessions</vh></v>
<v t="ekr.20150318110552.34"><vh>Communicating with external editors </vh></v>
<v t="ekr.20150318110552.35"><vh>Creating &amp; deleting directories &amp; files</vh></v>
<v t="ekr.20150318110552.36"><vh>Managing recent files</vh></v>
</v>
<v t="ekr.20150318110552.37"><vh>Help commands</vh></v>
<v t="ekr.20150323200950.1"><vh>Language conversion commands</vh></v>
<v t="ekr.20150318110552.38"><vh>Minibuffer commands</vh></v>
<v t="ekr.20150318110552.75"><vh>Miscellaneous commands</vh></v>
<v t="ekr.20150318110552.39"><vh>Mouseless Leo commands</vh>
<v t="ekr.20150318110552.40"><vh>Event simulation commands</vh></v>
<v t="ekr.20150318110552.41"><vh>Focus commands</vh></v>
<v t="ekr.20150318110552.42"><vh>Pane commands</vh></v>
</v>
<v t="ekr.20150318110552.43"><vh>Outline commands</vh>
<v t="ekr.20150318110552.44"><vh>Creating, cloning &amp; destroying nodes</vh></v>
<v t="ekr.20150318110552.45"><vh>Expanding &amp; contracting nodes</vh></v>
<v t="ekr.20150318110552.46"><vh>Editing headlines</vh></v>
<v t="ekr.20150318110552.47"><vh>Selecting nodes</vh></v>
<v t="ekr.20150318110552.48"><vh>Cutting, pasting &amp; deleting nodes</vh></v>
<v t="ekr.20150318110552.49"><vh>Moving &amp; reorganizing nodes</vh></v>
<v t="ekr.20150318110552.50"><vh>Converting between outlines and text</vh></v>
<v t="ekr.20150318110552.51"><vh>Dragging nodes</vh></v>
<v t="ekr.20150318110552.52"><vh>Marking nodes</vh></v>
<v t="ekr.20150318110552.53"><vh>Operations on marked nodes</vh></v>
<v t="ekr.20150318110552.54"><vh>Comparing outlines</vh></v>
<v t="ekr.20150318110552.55"><vh>Using Chapters</vh></v>
</v>
<v t="ekr.20150318110552.79"><vh>Plugins commands</vh></v>
<v t="ekr.20150318110552.57"><vh>Search &amp; spell commands</vh>
<v t="ekr.20150318110552.59"><vh>Basic searches</vh></v>
<v t="ekr.20150318110552.60"><vh>Incremental find commands</vh></v>
<v t="ekr.20150318110552.61"><vh>Word search and regex search commands</vh></v>
<v t="ekr.20150318110552.62"><vh>Check boxes and their commands</vh></v>
<v t="ekr.20150318110552.63"><vh>Radio buttons and their commands </vh></v>
<v t="ekr.20150318110552.64"><vh>Spell commands</vh></v>
</v>
<v t="ekr.20150318110552.65"><vh>Settings commands</vh></v>
<v t="ekr.20150603161559.1"><vh>Code beautification commands</vh>
<v t="ekr.20230124061650.1"><vh>Comparison with Black</vh></v>
<v t="ekr.20150603115243.1"><vh>Beautifier directives</vh></v>
<v t="ekr.20150603115400.1"><vh>Stand-alone beautifier</vh></v>
</v>
<v t="ekr.20150318110552.66"><vh>Window-related commands</vh></v>
<v t="ekr.20150318110552.87"><vh>Vim mode commands</vh></v>
</v>
<v t="ekr.20150323161357.1"><vh>Key Reference</vh>
<v t="ekr.20150323161357.2"><vh>Selecting outline nodes</vh></v>
<v t="ekr.20150323161357.3"><vh>Moving outline nodes</vh></v>
<v t="ekr.20150323161357.4"><vh>Moving the cursor</vh></v>
</v>
<v t="ekr.20150323102918.1"><vh>@rst-ignore Undocumented commands</vh></v>
</v>
<v t="ekr.20131009065148.31758"><vh>@rst html/directives.html</vh>
<v t="ekr.20100806170836.4392"><vh>\@&lt;file&gt; and \@path directives</vh>
<v t="ekr.20100806170836.4393"><vh>\@asis &lt;path&gt;</vh></v>
<v t="ekr.20100806170836.4396"><vh>\@auto &lt;path&gt;</vh>
<v t="ekr.20160410045234.1"><vh>\@auto sanity checks</vh></v>
</v>
<v t="ekr.20100806170836.4399"><vh>\@clean &lt;path&gt;</vh></v>
<v t="ekr.20100806170836.4395"><vh>\@edit &lt;path&gt;</vh></v>
<v t="ekr.20100806170836.4403"><vh>\@file &lt;path&gt; (aka @thin)</vh></v>
<v t="ekr.20160410044518.1"><vh>\@nosent &lt;path&gt;</vh></v>
<v t="ekr.20100806170836.4402"><vh>\@shadow &lt;path&gt; (deprecated)</vh></v>
<v t="ekr.20231013091132.1"><vh>\@path &lt;path&gt;</vh></v>
</v>
<v t="ekr.20100806170836.4411"><vh>\@all and \@others</vh></v>
<v t="ekr.20250729083112.1"><vh>\@leo directives</vh></v>
<v t="ekr.20100806170836.4398"><vh>Syntax coloring directives</vh></v>
<v t="ekr.20100806170836.4408"><vh>Dangerous directives</vh></v>
<v t="ekr.20100804133903.7262"><vh>All other directives</vh></v>
</v>
</v>
<v t="ekr.20101025080245.5798"><vh>Leo and Other Programs</vh>
<v t="ekr.20131008041326.16100"><vh>@rst html/leoandotherprograms.html</vh></v>
<v t="mhw.20191008134016.1"><vh>Leo and Asiidoc</vh>
<v t="mhw.20191008134029.1"><vh>@rst html/leoandasciidoc.html</vh></v>
</v>
<v t="ekr.20061025065357"><vh>Leo and Emacs</vh>
<v t="ekr.20061025065357.1"><vh>@rst html\emacs.html</vh>
<v t="ekr.20170315072706.1"><vh>Leo vs org mode</vh></v>
<v t="ekr.20140720203932.17747"><vh>Using org-mode (.org) files in Leo</vh></v>
<v t="ekr.20061025081359"><vh>Controlling Leo from Emacs using Pymacs</vh></v>
<v t="ekr.20061025070825.1"><vh>Functions in leoPymacs.py</vh></v>
<v t="ekr.20061025142434"><vh>The minibuffer</vh></v>
</v>
</v>
<v t="TL.20080804095315.1"><vh>Leo and Vim</vh>
<v t="TL.20080804095315.2"><vh>@rst html\vimBindings.html</vh>
<v t="ekr.20140810085801.18230"><vh>Using Leo's native vim mode</vh>
<v t="ekr.20140810153947.6747"><vh>Supported commands</vh></v>
<v t="ekr.20140810153947.6752"><vh>Differences from the real vim</vh></v>
<v t="ekr.20140810153947.6749"><vh>Abbreviations</vh></v>
<v t="ekr.20140810153947.6750"><vh>Colon commands</vh></v>
<v t="ekr.20140810153947.6751"><vh>Settings</vh></v>
</v>
<v t="ekr.20140720203932.17748"><vh>Using vimoutline (.otl) files in Leo</vh></v>
<v t="ekr.20140810085801.18231"><vh>Using stand-alone vim bindings</vh>
<v t="TL.20080804095315.4"><vh>Installing vim bindings</vh></v>
<v t="TL.20080804095315.5"><vh>General commands</vh></v>
<v t="TL.20080804095315.6"><vh>Body pane commands</vh></v>
<v t="TL.20080804095315.7"><vh>Outline commands</vh></v>
<v t="TL.20080804095315.8"><vh>Commands not supported</vh></v>
<v t="TL.20080804095315.9"><vh>Avoiding changes to 'tag' files</vh></v>
</v>
</v>
</v>
<v t="ekr.20241027051721.1"><vh>Leo and Jupyter Notebooks</vh>
<v t="ekr.20241027051739.1"><vh>@rst html\jupyternotebooks.html</vh>
<v t="ekr.20241107063856.1"><vh>Creating and populating @jupytext trees</vh></v>
<v t="ekr.20241105100428.1"><vh>Reading @jupytext trees</vh></v>
<v t="ekr.20241107070438.1"><vh>Editing @jupytext trees</vh></v>
<v t="ekr.20241107062843.1"><vh>Writing @jupytext trees</vh></v>
<v t="ekr.20241105103314.1"><vh>Settings</vh></v>
<v t="ekr.20241107080948.1"><vh>Extended comments about @jupytext</vh></v>
</v>
</v>
<v t="ekr.20070317033759"><vh>Embedding Leo with the leoBridge module</vh>
<v t="ekr.20070317033759.1"><vh>@rst html\leoBridge.html</vh>
<v t="ekr.20070317033759.3"><vh>Overview</vh></v>
<v t="ekr.20071210094621"><vh>Running leoBridge from within Leo</vh></v>
</v>
</v>
<v t="ekr.20210824081721.1"><vh>Leo's websocket server</vh>
<v t="ekr.20210824081815.1"><vh>@rst html/leoserver.html</vh>
<v t="ekr.20210825021830.1"><vh>The communication protocol</vh>
<v t="felix.20260601125039.1"><vh>Authentication</vh></v>
<v t="felix.20260601132011.1"><vh>Secure Websockets</vh></v>
<v t="ekr.20210824083951.1"><vh>Requests</vh></v>
<v t="ekr.20210824085857.1"><vh>Responses</vh></v>
<v t="felix.20210825222316.1"><vh>Async messages</vh></v>
</v>
<v t="felix.20210902210559.1"><vh>The main server loop</vh></v>
<v t="ekr.20210825021904.1"><vh>Compatibility and extensibility</vh></v>
<v t="felix.20210825213137.1"><vh>Multiple concurrent connections</vh></v>
<v t="felix.20210826001302.1"><vh>Command line arguments</vh></v>
<v t="felix.20210902210710.1"><vh>Acknowledgments</vh></v>
</v>
</v>
</v>
<v t="ekr.20101025080245.5799"><vh>Advanced Topics</vh>
<v t="ekr.20131008041326.16099"><vh>@rst html/intermediatetopics.html</vh></v>
<v t="ekr.20060612102055"><vh>Writing Plugins</vh>
<v t="ekr.20060612103240"><vh>@rst html\writingPlugins.html</vh>
<v t="ekr.20131008041326.16053"><vh>About Plugins</vh></v>
<v t="EKR.20040524104904.224"><vh>Important security warnings</vh></v>
<v t="peckj.20130813123907.6841"><vh>Documenting plugins</vh></v>
<v t="ekr.20131012191145.16789"><vh>c ivars &amp; properties</vh></v>
<v t="ekr.20050903074833"><vh>Handling events</vh>
<v t="ekr.20050903074833.1"><vh>Summary of event handlers</vh></v>
</v>
<v t="EKR.20040524104904.240"><vh>Support for unit testing</vh></v>
</v>
</v>
<v t="ekr.20060527105211"><vh>Debugging with Leo</vh>
<v t="ekr.20060527105617"><vh>@rst html\debuggers.html</vh>
<v t="ekr.20070116062405"><vh>Using g.trace and g.pdb</vh></v>
<v t="ekr.20060527112801"><vh>Settings for winpdb</vh></v>
<v t="ekr.20070115172724"><vh>Debugging scripts with winpdb</vh>
<v t="ekr.20070115172724.1"><vh>The debug command</vh>
<v t="ekr.20070115172724.3"><vh>The execute-script command with explicit debugger breaks</vh></v>
</v>
</v>
</v>
</v>
<v t="ekr.20131015104133.16763"><vh>A scripting miscellany</vh>
<v t="ekr.20131015091948.16784"><vh>@rst html\scripting-miscellany.html</vh>
<v t="ekr.20131014053720.16816"><vh>\@button example</vh></v>
<v t="ekr.20150817125512.1"><vh>Comparing two similar outlines</vh></v>
<v t="tom.20230107235603.1"><vh>Converting Body Text To Title Case</vh></v>
<v t="ekr.20110531155858.20563"><vh>Creating minimal outlines</vh></v>
<v t="ekr.20111115063523.13619"><vh>Creating Qt Windows from Leo scripts</vh></v>
<v t="ekr.20161014050133.1"><vh>Cutting and pasting text</vh></v>
<v t="ekr.20071026183116"><vh>g.app.gui.run* methods run dialogs</vh></v>
<v t="ekr.20040403173920.19"><vh>Getting commander preferences</vh></v>
<v t="ekr.20050907094633"><vh>Getting configuration settings</vh></v>
<v t="ekr.20080922124033.1"><vh>Getting interactive input in scripts and commands</vh></v>
<v t="ekr.20080109074102"><vh>Inserting and deleting icons</vh></v>
<v t="ekr.20040403173920.18"><vh>Invoking commands from scripts</vh></v>
<v t="ekr.20050417072710.1"><vh>Making operations undoable</vh></v>
<v t="ekr.20100506062734.11593"><vh>Modifying plugins with @script scripts</vh></v>
<v t="ekr.20090223065025.3"><vh>Modifying the body pane directly</vh></v>
<v t="ekr.20070122093626"><vh>Recovering vnodes</vh></v>
<v t="ekr.20150318043636.14"><vh>Recursive import script</vh></v>
<v t="ekr.20120317130339.8282"><vh>Retaining pointers to Qt windows</vh></v>
<v t="ekr.20150323102036.1"><vh>Running code at idle time</vh></v>
<v t="ekr.20161029072351.1"><vh>Running code in separate processes</vh>
<v t="ekr.20180226151003.1"><vh>Using subprocess.popen</vh>
<v t="ekr.20180226155008.1"><vh>Call subprocess.popen directly</vh></v>
<v t="ekr.20180226155010.1"><vh>Call g.execute_shell_commands</vh></v>
<v t="ekr.20180226155010.2"><vh>Call g.execute_shell_commands_with_options</vh></v>
</v>
<v t="ekr.20180226153353.1"><vh>Using g.app.backgroundProcessManager</vh></v>
<v t="ekr.20190307093145.1"><vh>Using g.execute_shell_commands</vh></v>
</v>
<v t="ekr.20040403173920.24"><vh>Running Leo in batch mode</vh></v>
<v t="ekr.20180827103758.1"><vh>Using @pyplot and matplotlib</vh>
<v t="ekr.20180827104847.1"><vh>Overview</vh></v>
<v t="ekr.20180827105047.1"><vh>Displaying images externally</vh></v>
</v>
<v t="ekr.20081205084002.2"><vh>Working with directives</vh></v>
<v t="ekr.20131012060912.16788"><vh>Writing g.es output to other tabs</vh></v>
<v t="ekr.20190608092106.1"><vh>Writing clickable links to the Log tab</vh></v>
</v>
</v>
<v t="ekr.20131008041326.16178"><vh>Exploring Leo's Code Base</vh>
<v t="ekr.20131009065148.31760"><vh>@rst html/theory.html</vh>
<v t="ekr.20131011050613.16868"><vh>How to explore Leo's sources</vh>
<v t="ekr.20131012060912.16768"><vh>Finding commands</vh></v>
<v t="ekr.20131011050613.16870"><vh>Finding key-handling code</vh></v>
<v t="ekr.20131011050613.16871"><vh>Finding redraw and refocus code</vh></v>
<v t="ekr.20150323111053.1"><vh>Finding all uses of a symbol</vh></v>
<v t="ekr.20131011050613.16862"><vh>Debugging with g.trace, g.callers &amp; g.pdb</vh></v>
</v>
<v t="ekr.20131011050613.16860"><vh>The design of Leo's classes</vh></v>
<v t="ekr.20131011050613.16876"><vh>Fragile methods</vh></v>
<v t="ekr.20131011050613.16866"><vh>Read long comments with caution</vh></v>
<v t="ekr.20131011050613.16815"><vh>Startup</vh></v>
<v t="EKR.20040524104904.268"><vh>Unicode</vh></v>
<v t="ekr.20131012060912.16770"><vh>Why key handling is complex</vh></v>
<v t="ekr.20150311123850.39"><vh>Leo must have sentinels, even without clones</vh></v>
<v t="ekr.20150417041505.1"><vh>Setting focus</vh></v>
</v>
</v>
<v t="ekr.20140810085801.18216"><vh>Vim Mode Theory of Operation</vh>
<v t="ekr.20140810085801.18232"><vh>@rst html/vim-theory.html</vh>
<v t="ekr.20140810085801.18217"><vh>The big picture</vh></v>
<v t="ekr.20140811083910.18246"><vh>A simple key handler</vh></v>
<v t="ekr.20140810085801.18221"><vh>A more complex key handler</vh>
<v t="ekr.20140810085801.18222"><vh>vim_d</vh></v>
<v t="ekr.20140810085801.18223"><vh>vim_d2</vh></v>
<v t="ekr.20140810085801.18224"><vh>vim_d3</vh></v>
<v t="ekr.20140810085801.18225"><vh>vis_d</vh></v>
</v>
<v t="ekr.20140810085801.18226"><vh>Code level details</vh>
<v t="ekr.20140810085801.18227"><vh>Initialization</vh></v>
<v t="ekr.20140810085801.18228"><vh>Dispatchers</vh></v>
<v t="ekr.20140810085801.18218"><vh>About key handlers</vh></v>
<v t="ekr.20140810085801.18219"><vh>Ivars for key handlers</vh></v>
<v t="ekr.20150312080344.14"><vh>Handling tabs</vh></v>
<v t="ekr.20140810085801.18220"><vh>API's for key handlers</vh></v>
<v t="ekr.20140810085801.18229"><vh>vc.return_value and internal error checking</vh></v>
</v>
</v>
</v>
<v t="ekr.20131019035402.17557"><vh>The Leonine world</vh>
<v t="ekr.20131019035402.17573"><vh>@rst html\leonine-world.html</vh></v>
</v>
<v t="ekr.20180505114327.1"><vh>Leo University</vh>
<v t="ekr.20180509042555.1"><vh>@rst html\leo-university.html</vh>
<v t="ekr.20180505114327.5"><vh>Lesson 1: Think process, not knowledge</vh></v>
<v t="ekr.20180505114327.7"><vh>Lesson 2: Learn Leo's debugging tools</vh></v>
<v t="ekr.20180505114327.8"><vh>Lesson 3: Running unit tests</vh></v>
<v t="ekr.20180505114327.6"><vh>Lesson 4: Use issues as an programming notebook</vh></v>
<v t="ekr.20180505114327.9"><vh>Lesson 5: c.recursiveImport imports files recursively</vh></v>
<v t="ekr.20180505114327.10"><vh>Lesson 6: How devs should use git branches</vh></v>
<v t="ekr.20180505114327.11"><vh>Lesson 7: How to make complex changes to a code base</vh></v>
<v t="ekr.20180505114327.3"><vh>LeoU: Suggestions for theme developers</vh></v>
<v t="ekr.20180505141445.1"><vh>LeoU: About Leo's architecture</vh></v>
<v t="ekr.20180505114327.12"><vh>LeoU: About Leo's Position and VNode classes</vh></v>
</v>
</v>
</v>
<v t="ekr.20131008041326.16091"><vh>Cheat Sheet</vh>
<v t="ekr.20131007143750.16070"><vh>@rst html\cheatsheet.html</vh>
<v t="ekr.20131019061259.16693"><vh>Key bindings</vh>
<v t="ekr.20131015035606.16778"><vh>Selecting outline nodes</vh></v>
<v t="ekr.20131015035606.16800"><vh>Moving outline nodes</vh></v>
<v t="ekr.20131015035606.16780"><vh>Moving the cursor</vh></v>
</v>
<v t="ekr.20181015144118.7"><vh>Executing minibuffer commands</vh></v>
<v t="ekr.20131015035606.16801"><vh>Frequently used commands</vh></v>
<v t="ekr.20160428104050.1"><vh>Gathering find commands</vh></v>
<v t="ekr.20131015035606.16786"><vh>Leo directives</vh></v>
<v t="ekr.20131015035606.16788"><vh>Settings</vh></v>
<v t="ekr.20131031101712.16486"><vh>Node types</vh></v>
<v t="ekr.20131016103844.16730"><vh>Notable Plugins</vh></v>
<v t="ekr.20131015035606.16799"><vh>External files (@&lt;file&gt; nodes)</vh></v>
<v t="ekr.20160410103017.1"><vh>Sections</vh></v>
<v t="ekr.20131007143750.16074"><vh>Scripting</vh>
<v t="ekr.20131019061259.16686"><vh>Pre-defined symbols</vh></v>
<v t="ekr.20170315020214.1"><vh>LeoApp class</vh></v>
<v t="ekr.20131019061259.16688"><vh>Commands class</vh></v>
<v t="ekr.20190101093224.1"><vh>Undoing commands</vh>
<v t="ekr.20190101093224.2"><vh>Undoably changing body text</vh></v>
<v t="ekr.20190101093224.3"><vh>Undoably changing multiple nodes</vh></v>
</v>
<v t="ekr.20131019061259.16690"><vh>VNode class</vh></v>
<v t="ekr.20131019061259.16691"><vh>Position class</vh></v>
<v t="ekr.20131019061259.16692"><vh>leo.core.leoGlobals module</vh></v>
<v t="ekr.20170403185500.1"><vh>Performance</vh></v>
<v t="ekr.20181015144118.25"><vh>Prompting for command arguments</vh>
<v t="ekr.20181015144118.26"><vh>Example 1: Prompt for one arg</vh></v>
<v t="ekr.20181015144118.27"><vh>Example 2: Prompt for 2 args</vh></v>
<v t="ekr.20181015144118.28"><vh>Example 3: Prompt for 3 args</vh></v>
</v>
<v t="ekr.20181015144118.29"><vh>Naming conventions in Leo's core</vh>
<v t="ekr.20181015144118.30"><vh>Official ivars</vh></v>
</v>
<v t="ekr.20181015144118.31"><vh>Widgets and wrappers</vh></v>
</v>
<v t="ekr.20131028213522.17138"><vh>Command-line options</vh></v>
<v t="ekr.20181015144118.33"><vh>Learning to be a Leo developer</vh>
<v t="ekr.20181015144118.34"><vh>Code academy</vh>
<v t="ekr.20181015144118.35"><vh>CA: uA's</vh></v>
<v t="ekr.20181015144118.36"><vh>CA: icons</vh></v>
<v t="ekr.20181015144118.37"><vh>CA: using git</vh></v>
<v t="ekr.20181015144118.38"><vh>CA: finding nodes with c.cloneFindByPredicate</vh></v>
</v>
<v t="ekr.20181015144118.39"><vh>Leo University</vh></v>
<v t="ekr.20181015144118.40"><vh>Architecture</vh></v>
</v>
<v t="ekr.20230716051446.1"><vh>Clickable links</vh></v>
</v>
</v>
<v t="ekr.20230123101622.1"><vh>More TOC links</vh>
<v t="ekr.20230123101657.1"><vh>@rst html/toc-more-links.html</vh></v>
</v>
<v t="ekr.20150312080344.67"><vh>History of Leo</vh>
<v t="ekr.20150312080344.68"><vh>@rst html/history.html</vh>
<v t="ekr.20230909063921.1"><vh>The Early Days</vh>
<v t="ekr.20050902105852"><vh>1995: Beginnings</vh></v>
<v t="ekr.20050902105852.1"><vh>1996: Breakthroughs</vh></v>
<v t="ekr.20050902105852.2"><vh>1996-1998: Apple and YellowBox</vh></v>
<v t="ekr.20050902105852.3"><vh>1999-2001: Borland C++</vh></v>
<v t="ekr.20050902105852.4"><vh>2001: Discovering Python</vh></v>
<v t="ekr.20050902105852.6"><vh>2001: Putting sentinel lines in external files</vh>
<v t="EKR.20040524104904.248"><vh>Overview</vh></v>
<v t="EKR.20040524104904.249"><vh>First steps</vh></v>
<v t="EKR.20040524104904.250"><vh>A prototype: simplified noweb</vh></v>
<v t="EKR.20040524104904.251"><vh>Avoiding error notifications</vh></v>
<v t="EKR.20040524104904.252"><vh>The write code</vh></v>
<v t="EKR.20040524104904.253"><vh>The read code</vh></v>
<v t="EKR.20040524104904.254"><vh>The load/save code</vh></v>
<v t="EKR.20040524104904.255"><vh>Attributes, mirroring and dummy nodes</vh></v>
<v t="EKR.20040524104904.256"><vh>Clones</vh></v>
<v t="EKR.20040524104904.257"><vh>Error recovery, at last</vh></v>
</v>
<v t="ekr.20050902105852.7"><vh>2002: Untangling @file is easy!</vh></v>
<v t="ekr.20050902105852.8"><vh>2002: Leo 3.x: Continuous improvement</vh></v>
<v t="ekr.20050902105852.5"><vh>2003: SourceForge: new energy</vh></v>
<v t="ekr.20050902105852.9"><vh>2003: 4.0: New read logic eliminates read errors, eliminated child indices</vh></v>
<v t="ekr.20050902105852.10"><vh>2004: 4.1: The debut of gnx's</vh></v>
<v t="ekr.20050902105852.11"><vh>2004: 4.2: generators, uA's the end of sync problems, shared tnodes</vh></v>
<v t="ekr.20050902105852.12"><vh>2005: 4.3: @settings trees, plugins manager, predefined c, g, p</vh></v>
<v t="ekr.20060629083935"><vh>2006: 4.4: The minibuffer, key bindings autocompletion, multiple log panes</vh></v>
</v>
<v t="ekr.20230909063947.1"><vh>Later developments</vh>
<v t="ekr.20080315115427.568"><vh>2006-2008: 4.4.x: Hundreds of improvements</vh></v>
<v t="ekr.20101025080245.6086"><vh>2009: 4.6: Qt gui, @edit, @auto-rst</vh></v>
<v t="ekr.20101025080245.6087"><vh>2010: 4.7: The one node world &amp; Python 3k</vh></v>
<v t="ekr.20101025080245.6089"><vh>2010: 4.8: New sentinels &amp; recovery nodes</vh></v>
<v t="ekr.20131008041326.16253"><vh>2011: 4.9: The end of Tk, autocompleter, vr pane</vh></v>
<v t="ekr.20150312013449.4"><vh>2014: 5.0 Vim mode, plays well with others</vh></v>
<v t="ekr.20150220200101.2"><vh>2015: 5.1 @clean</vh>
<v t="ekr.20230909073504.2"><vh>Steve Zatz: in praise of @clean</vh></v>
<v t="ekr.20230909073504.3"><vh>EKR: Why @clean is so important</vh></v>
</v>
<v t="ekr.20230908140206.569"><vh>2016-2018: 5.2 through 5.9: precursors to LeoInteg</vh></v>
<v t="ekr.20230908152641.1"><vh>2019-2023: Leo 6.0 through 6.7: LeoInteg</vh></v>
<v t="ekr.20250727055239.1"><vh>2024 onward: Leo 6.8: Easy layouts, @jupytext, @leo</vh></v>
</v>
</v>
</v>
<v t="ekr.20050831184021.5"><vh>Appendices &amp; glossary</vh>
<v t="ekr.20131008041326.16341"><vh>@rst html/appendices.html</vh>
<v t="EKR.20040524104904.357"><vh>Format of .leo files</vh></v>
<v t="ekr.20060921064744.1"><vh>Format of external files</vh></v>
<v t="ekr.20190414193500.1"><vh>The Leonine way to refactor code</vh></v>
<v t="ekr.20241112030815.1"><vh>Leo's Colorizer: Theory of Operation</vh>
<v t="ekr.20241112094914.1"><vh>Components of the jedit class</vh></v>
<v t="ekr.20241112044810.1"><vh>The big challenge</vh></v>
<v t="ekr.20241112111533.1"><vh>About states and restarters</vh></v>
<v t="ekr.20060430220749"><vh>Mode files</vh></v>
</v>
<v t="ekr.20200807105709.1"><vh>leoAst.py</vh>
<v t="ekr.20200807111156.1"><vh>Running leoAst.py</vh>
<v t="ekr.20200807110628.1"><vh>Running leoAst.py from the command line</vh></v>
<v t="ekr.20200107142458.1"><vh>Running the code python programmatically</vh></v>
<v t="ekr.20200107143607.1"><vh>Running unit tests and coverage tests programmatically</vh></v>
</v>
<v t="ekr.20191118115949.1"><vh>TokenOrder classes: Theory of operation</vh>
<v t="ekr.20191206062224.1"><vh>Token-order classes</vh></v>
<v t="ekr.20200113232354.1"><vh>Other classes</vh></v>
<v t="ekr.20200113234440.1"><vh>Significant vs insignificant tokens</vh></v>
<v t="ekr.20191206063508.1"><vh>Helping TOG visitors</vh></v>
<v t="ekr.20191206064645.1"><vh>Syncing tokens</vh></v>
<v t="ekr.20200107105607.1"><vh>Figures of merit</vh></v>
</v>
<v t="ekr.20200807105737.1"><vh>Maintaining leoAst.py</vh></v>
</v>
<v t="EKR.20040524104904.354"><vh>Unicode reference</vh></v>
<v t="ekr.20120319170934.6109"><vh>Valid URL's</vh></v>
<v t="ekr.20150210062226.4"><vh>The Mulder/Ream update algorithm</vh>
<v t="ekr.20150220145456.4"><vh>What the algorithm does</vh></v>
<v t="ekr.20080730212711.52"><vh>Guesses don't matter</vh></v>
<v t="ekr.20150210062226.5"><vh>Background of the code</vh></v>
<v t="ekr.20150211131925.9"><vh>Aha: the x.sentinels array</vh></v>
<v t="ekr.20150210062226.6"><vh>Strategy &amp; proof of correctness</vh></v>
<v t="ekr.20150210062226.7"><vh>Summary</vh></v>
</v>
<v t="ekr.20050901084134"><vh>Why I like Python</vh>
<v t="ekr.20050901092232.2"><vh>Clarity</vh></v>
<v t="ekr.20050901092232.3"><vh>Power</vh></v>
<v t="ekr.20050901092232.4"><vh>Safety</vh></v>
<v t="ekr.20050901092232.5"><vh>Speed</vh></v>
<v t="ekr.20050901092232.6"><vh>Conclusions</vh></v>
</v>
</v>
<v t="ekr.20091111112709.6672"><vh>@rst html/glossary.html</vh>
<v t="ekr.20100804133903.7250"><vh>\@</vh></v>
<v t="ekr.20100804133903.7251"><vh>A - C</vh></v>
<v t="ekr.20100804133903.7252"><vh>D - G</vh></v>
<v t="ekr.20100804133903.7253"><vh>H - L</vh></v>
<v t="ekr.20100804133903.7254"><vh>M - O</vh></v>
<v t="ekr.20100804133903.7255"><vh>P - R</vh></v>
<v t="ekr.20100804133903.7256"><vh>S - Z</vh></v>
</v>
</v>
<v t="ekr.20060620094033"><vh>What's New...</vh>
<v t="ekr.20101025080245.5791"><vh>@rst html/what-is-new.html</vh>
<v t="ekr.20071116062917.2"><vh>@rst-no-head links</vh></v>
<v t="ekr.20260531063902.1"><vh>What's new in Leo 6.8.9</vh></v>
<v t="ekr.20251204122149.1"><vh>What's new in Leo 6.8.8</vh></v>
<v t="ekr.20250830050946.1"><vh>What's new in Leo 6.8.7</vh></v>
<v t="ekr.20250728124612.1"><vh>What's new in Leo 6.8.6</vh></v>
<v t="ekr.20250626165619.1"><vh>What's new in Leo 6.8.5</vh></v>
<v t="ekr.20250422050813.2"><vh>What's new in Leo 6.8.4</vh></v>
<v t="ekr.20241126091611.1"><vh>What's new in Leo 6.8.3</vh></v>
<v t="ekr.20240828095959.1"><vh>What's new in Leo 6.8.2</vh></v>
<v t="ekr.20240527101024.1"><vh>What's new in Leo 6.8.0</vh></v>
<v t="ekr.20240527100956.1"><vh>What's new in Leo 6.7</vh>
<v t="ekr.20240222121346.1"><vh>What's new in Leo 6.7.8</vh></v>
<v t="ekr.20240118094134.1"><vh>What's new in Leo 6.7.7</vh></v>
<v t="ekr.20231126120048.1"><vh>What's new in Leo 6.7.6</vh></v>
<v t="ekr.20230901233844.1"><vh>What's new in Leo 6.7.5</vh></v>
<v t="ekr.20230709070852.1"><vh>What's new in Leo 6.7.4</vh></v>
<v t="ekr.20230409053106.1"><vh>What's new in Leo 6.7.3</vh></v>
<v t="ekr.20230111160833.1"><vh>What's new in Leo 6.7.2</vh></v>
<v t="ekr.20221018092915.1"><vh>What's new in Leo 6.7.1</vh></v>
<v t="ekr.20220912154542.1"><vh>What's new in Leo 6.7.0</vh></v>
</v>
<v t="ekr.20221108064449.1"><vh>What's new in Leo 6.6 and earlier</vh>
<v t="ekr.20220831093321.1"><vh>What's new in Leo 6.6.4</vh></v>
<v t="ekr.20220719064316.1"><vh>What's new in Leo 6.6.3</vh></v>
<v t="ekr.20220523145755.1"><vh>What's new in Leo 6.6.2</vh></v>
<v t="ekr.20220427143133.1"><vh>What's new in Leo 6.6.1</vh></v>
<v t="ekr.20211105051309.1"><vh>What's new in Leo 6.6</vh></v>
<v t="ekr.20210921103230.1"><vh>What's new in Leo 6.5</vh></v>
<v t="ekr.20210405104357.1"><vh>What's new in Leo 6.4</vh></v>
<v t="ekr.20201017061850.1"><vh>What's new in Leo 6.3</vh></v>
<v t="ekr.20200313060126.1"><vh>What's new in Leo 6.2</vh></v>
<v t="ekr.20191003051240.1"><vh>What's new in Leo 6.1</vh></v>
<v t="ekr.20190616175854.1"><vh>What's new in Leo 6.0</vh></v>
</v>
<v t="ekr.20221108064344.1"><vh>What's new in Leo 5.x</vh>
<v t="ekr.20190122044116.1"><vh>What's new in Leo 5.9</vh></v>
<v t="ekr.20180821154658.1"><vh>What's new in Leo 5.8</vh></v>
<v t="ekr.20180527084307.1"><vh>What's new in Leo 5.7.3</vh></v>
<v t="ekr.20180427130312.1"><vh>What's new in Leo 5.7.2</vh></v>
<v t="ekr.20180404015558.1"><vh>What's new in Leo 5.7.1</vh>
<v t="ekr.20180411071648.1"><vh>Features</vh></v>
<v t="ekr.20180411071733.1"><vh>Settings</vh></v>
</v>
<v t="ekr.20180125034531.1"><vh>What's new in Leo 5.7</vh>
<v t="ekr.20180126002550.1"><vh>Highlights</vh></v>
<v t="ekr.20180126002657.1"><vh>Code</vh></v>
<v t="ekr.20180126003100.1"><vh>Commands</vh></v>
<v t="ekr.20180126003454.1"><vh>Enhancements</vh></v>
<v t="ekr.20180126003617.1"><vh>Plugins</vh></v>
<v t="ekr.20180126003420.1"><vh>Settings &amp; command-line arguments</vh></v>
</v>
<v t="ekr.20170911082347.1"><vh>What's new in Leo 5.6</vh>
<v t="ekr.20170911082432.2"><vh>Highlights</vh>
<v t="ekr.20170911082432.3"><vh>#488: Created a console gui for Leo</vh></v>
<v t="ekr.20170911082432.4"><vh>#501: git-diff command</vh></v>
<v t="ekr.20170911082432.5"><vh>#505: Leo switches between git branches properly</vh></v>
<v t="ekr.20170911082432.6"><vh>Added "yes/no to all" buttons for externally changed file dialog</vh></v>
</v>
<v t="ekr.20170911082432.53"><vh>Code</vh></v>
<v t="ekr.20170911082432.66"><vh>Commands</vh></v>
<v t="ekr.20170911082432.88"><vh>Other features</vh></v>
<v t="ekr.20170911082432.101"><vh>Settings &amp; command-line arguments</vh></v>
</v>
<v t="ekr.20170123090814.1"><vh>What's new in Leo 5.5</vh>
<v t="ekr.20170123090841.2"><vh>Highlights</vh></v>
<v t="ekr.20170123090841.6"><vh>Created new @button scripts</vh></v>
<v t="ekr.20170123090841.22"><vh>Code</vh></v>
<v t="ekr.20170123090841.26"><vh>Features</vh></v>
<v t="ekr.20170316061456.1"><vh>Settings</vh></v>
<v t="ekr.20170316063618.1"><vh>Command-line options</vh></v>
</v>
<v t="ekr.20161014053105.1"><vh>What's new in Leo 5.4</vh>
<v t="ekr.20161014053127.1"><vh>Highlights</vh></v>
<v t="ekr.20161014053707.1"><vh>Commands</vh></v>
<v t="ekr.20161014054015.1"><vh>Other features</vh></v>
<v t="ekr.20161014054147.1"><vh>Settings</vh></v>
</v>
<v t="ekr.20160417112500.1"><vh>What's new in Leo 5.3</vh>
<v t="ekr.20160417112511.1"><vh>Highlights</vh></v>
<v t="ekr.20160417112540.32"><vh>Commands</vh></v>
<v t="ekr.20160417112540.33"><vh>Plugins</vh></v>
</v>
<v t="ekr.20160310062634.1"><vh>What's new in Leo 5.2</vh>
<v t="ekr.20160310062651.1"><vh>Highlights</vh></v>
<v t="ekr.20160310063235.1"><vh>Commands &amp; directives</vh></v>
<v t="ekr.20160310064208.5"><vh>Features</vh></v>
<v t="ekr.20160310064208.18"><vh>Plugins &amp; scripts</vh></v>
<v t="ekr.20160310064208.24"><vh>Settings</vh></v>
</v>
<v t="ekr.20150212182032.4"><vh>What's new in Leo 5.1</vh>
<v t="ekr.20150312080344.33"><vh>Highlights</vh></v>
<v t="ekr.20160310060817.1"><vh>Commands &amp; settings</vh></v>
<v t="ekr.20150311123850.41"><vh>Features</vh></v>
<v t="ekr.20150311123850.56"><vh>Why @clean is so important</vh></v>
<v t="ekr.20150220115528.4"><vh>The Mulder/Ream update algorithm</vh></v>
</v>
<v t="ekr.20141105050314.25"><vh>What's new in Leo 5.0</vh>
<v t="ekr.20150312080344.31"><vh>Highlights</vh></v>
<v t="ekr.20141105052052.2"><vh>Commands</vh></v>
<v t="ekr.20141105050314.163"><vh>Features</vh>
<v t="ekr.20150312080344.20"><vh>A plugable architecture for @auto nodes</vh></v>
</v>
<v t="ekr.20141105050314.181"><vh>Plugins</vh></v>
<v t="ekr.20141105050314.197"><vh>Settings</vh></v>
</v>
</v>
<v t="ekr.20180404015644.1"><vh>What's new in Leo 4.x</vh>
<v t="ekr.20131019190351.16664"><vh>What's new in Leo 4.11</vh>
<v t="ekr.20150312080344.32"><vh>Highlights</vh></v>
<v t="ekr.20131019190351.16947"><vh>Commands</vh></v>
<v t="ekr.20131019190351.16975"><vh>Features</vh></v>
<v t="ekr.20131019190351.16990"><vh>Plugins</vh></v>
<v t="ekr.20131019190351.17002"><vh>Scripts in scripts.leo</vh></v>
<v t="ekr.20131019190351.17004"><vh>Settings</vh></v>
</v>
<v t="ekr.20120320153011.6055"><vh>What's new in Leo 4.10</vh>
<v t="ekr.20150312080344.63"><vh>Highlights</vh></v>
<v t="ekr.20150312080344.65"><vh>Commands</vh></v>
<v t="ekr.20150312080344.66"><vh>Classes</vh></v>
<v t="ekr.20120320153011.8400"><vh>Features</vh></v>
</v>
<v t="ekr.20110601105631.19349"><vh>What's new in Leo 4.9</vh>
<v t="ekr.20150312080344.59"><vh>Highlights</vh></v>
<v t="ekr.20150312080344.61"><vh>Commands</vh></v>
<v t="ekr.20150312080344.60"><vh>Features</vh></v>
</v>
<v t="ekr.20101025080245.5805"><vh>What's new in Leo 4.8</vh>
<v t="ekr.20150312080344.56"><vh>Highlights</vh></v>
<v t="ekr.20150312080344.58"><vh>Commands</vh></v>
<v t="ekr.20150312080344.57"><vh>Features</vh></v>
</v>
<v t="ekr.20100129054823.11924"><vh>What's new in Leo 4.7</vh>
<v t="ekr.20150312080344.55"><vh>Highlights</vh></v>
<v t="ekr.20100129054823.11931"><vh>Command-line options</vh></v>
<v t="ekr.20100211221936.7098"><vh>Commands</vh></v>
</v>
<v t="ekr.20090324145450.20"><vh>What's new in Leo 4.6</vh>
<v t="ekr.20150312080344.52"><vh>Highlights</vh></v>
<v t="ekr.20090324145450.40"><vh>Commands</vh></v>
<v t="ekr.20150312080344.53"><vh>Features</vh></v>
</v>
<v t="ekr.20080806211440.185"><vh>What's new in Leo 4.5</vh>
<v t="ekr.20080806211440.188"><vh>Highlights</vh></v>
</v>
<v t="ekr.20080314081157.127"><vh>What's new in Leo 4.4.8</vh>
<v t="ekr.20150312080344.50"><vh>Highlights</vh></v>
</v>
<v t="ekr.20150312080344.47"><vh>What's new in Leo 4.4.7</vh>
<v t="ekr.20150312080344.48"><vh>Highlights</vh></v>
</v>
<v t="ekr.20071217093444"><vh>What's new in Leo 4.4.6</vh>
<v t="ekr.20150312080344.46"><vh>Highlights</vh></v>
</v>
<v t="ekr.20071116062917"><vh>What's new in Leo 4.4.5</vh>
<v t="ekr.20150312080344.45"><vh>Highlights</vh></v>
<v t="ekr.20071116062917.18"><vh>Commands</vh></v>
<v t="ekr.20071116062917.3"><vh>Features</vh></v>
</v>
<v t="ekr.20070809145744"><vh>What's new in Leo 4.4.4</vh>
<v t="ekr.20150312080344.37"><vh>Highlights</vh></v>
<v t="ekr.20070809145744.4"><vh>Commands</vh></v>
<v t="ekr.20070809145744.5"><vh>Features</vh></v>
</v>
<v t="ekr.20070513113903"><vh>What's new in Leo 4.4.3</vh>
<v t="ekr.20150312080344.36"><vh>Highlights</vh></v>
</v>
<v t="ekr.20060928172457"><vh>What's new in Leo 4.4.2</vh>
<v t="ekr.20060929043325"><vh>Highlights</vh></v>
<v t="ekr.20061009111417.18"><vh>Commands</vh></v>
<v t="ekr.20060928172457.4"><vh>Features</vh></v>
<v t="ekr.20060928172457.5"><vh>Plugins</vh></v>
<v t="ekr.20061009111417.11"><vh>Settings</vh></v>
</v>
<v t="ekr.20060620094033.1"><vh>What's new in Leo 4.4.1</vh>
<v t="ekr.20150312080344.35"><vh>Highlights</vh></v>
<v t="ekr.20060620130636"><vh>Commands</vh></v>
<v t="ekr.20060620095949.15"><vh>Features</vh></v>
<v t="ekr.20060620130943"><vh>Plugins</vh></v>
<v t="ekr.20060620095949.25"><vh>Settings</vh></v>
</v>
<v t="ekr.20060620094033.2"><vh>What's new in Leo 4.4</vh>
<v t="ekr.20150312080344.34"><vh>Highlights</vh></v>
<v t="ekr.20070622212132"><vh>Commands</vh></v>
<v t="ekr.20060620133820.16"><vh>Features</vh></v>
<v t="ekr.20060620140130"><vh>Plugins</vh></v>
<v t="ekr.20060620140228"><vh>Settings</vh></v>
</v>
</v>
</v>
</v>
<v t="ekr.20180125034510.1"><vh>Release Notes</vh>
<v t="ekr.20250422050948.1"><vh>Leo 6.8.x release notes</vh>
<v t="ekr.20260531063735.1"><vh>Leo 6.8.9 release notes</vh></v>
<v t="ekr.20251204122305.1"><vh>Leo 6.8.8 release notes</vh></v>
<v t="ekr.20250830050853.1"><vh>Leo 6.8.7 release notes</vh></v>
<v t="ekr.20250728123954.1"><vh>Leo 6.8.6 release notes</vh></v>
<v t="ekr.20250626165415.1"><vh>Leo 6.8.5 release notes</vh></v>
<v t="ekr.20250422050813.3"><vh>Leo 6.8.4 release notes</vh></v>
<v t="ekr.20241126091524.1"><vh>Leo 6.8.3 release notes</vh></v>
<v t="ekr.20240527100702.1"><vh>Leo 6.8.0 release notes</vh></v>
</v>
<v t="ekr.20240724062137.1"><vh>Leo 6.7.x release notes</vh>
<v t="ekr.20240222121215.1"><vh>Leo 6.7.8 release notes</vh></v>
<v t="ekr.20240118094108.1"><vh>Leo 6.7.7 release notes</vh></v>
<v t="ekr.20231126121710.1"><vh>Leo 6.7.6 release notes </vh></v>
<v t="ekr.20230901233131.1"><vh>Leo 6.7.5 release notes</vh></v>
<v t="ekr.20230703101804.1"><vh>Leo 6.7.4 release notes</vh></v>
<v t="ekr.20230409052507.1"><vh>Leo 6.7.3 release notes</vh></v>
<v t="ekr.20230110152131.1"><vh>Leo 6.7.2 release notes</vh></v>
<v t="ekr.20221018092737.1"><vh>Leo 6.7.1 release notes</vh></v>
</v>
<v t="ekr.20230110152214.1"><vh>Leo 6.x release notes</vh>
<v t="ekr.20220704113115.1"><vh>Leo 6.6.3 release notes</vh></v>
<v t="ekr.20220523084825.1"><vh>Leo 6.6.2 release nodes</vh></v>
<v t="ekr.20220401072939.1"><vh>Leo 6.6.1 release notes</vh></v>
<v t="ekr.20211105051031.1"><vh>Leo 6.6 release notes</vh></v>
<v t="ekr.20210921102613.1"><vh>Leo 6.5 release notes</vh>
<v t="ekr.20210921102613.13"><vh>6.5: Commands</vh></v>
<v t="ekr.20210921102613.20"><vh>6.5: Features</vh></v>
<v t="ekr.20210921102613.40"><vh>6.5: Settings</vh></v>
<v t="ekr.20211014165743.1"><vh>6.5: Testing</vh></v>
</v>
<v t="ekr.20210405104422.1"><vh>Leo 6.4 release notes</vh>
<v t="ekr.20210405104614.1"><vh>6.4: Bugs</vh></v>
<v t="ekr.20210405104619.1"><vh>6.4: Code</vh>
<v t="ekr.20210405100137.468"><vh>#1413: New undo pattern</vh></v>
<v t="ekr.20210606081234.1"><vh>#1715: Add execute-general-script</vh></v>
<v t="ekr.20210405100137.563"><vh>#1721: Remove most calls to c.setBody/HeadString</vh></v>
<v t="ekr.20210405100137.1058"><vh>#1806: Rewrite leoFind.py, with unit tests</vh></v>
<v t="ekr.20210710040014.2"><vh>#1944: Annotations &amp; stub files</vh></v>
<v t="ekr.20210823181157.1"><vh>#1973 and #2005: Support Qt6</vh></v>
<v t="ekr.20210717092635.918"><vh>#2005: Add more qt imports</vh></v>
<v t="ekr.20210718082823.2"><vh>#2081: Use sys.excepthook, not @g.callback</vh></v>
<v t="ekr.20210802163908.31"><vh>#2103: stubs for leoGlobals.py</vh></v>
</v>
<v t="ekr.20210405104753.1"><vh>6.4: Commands</vh>
<v t="ekr.20210606081234.1"></v>
<v t="ekr.20210405100137.787"><vh>#1754: reformat-paragraph</vh></v>
<v t="ekr.20210405100137.1340"><vh>#1831 &amp; #2049: mypy command</vh></v>
<v t="ekr.20210405100137.1396"><vh>#1841: copy-gnx</vh></v>
<v t="ekr.20210528082736.11"><vh>#1955: improve extract command</vh></v>
<v t="ekr.20210405100137.1798"><vh>PR #1849: reload-settings now changes all settings</vh></v>
</v>
<v t="ekr.20210405110053.1"><vh>6.4: Major features</vh>
<v t="ekr.20210405100137.2"><vh>#0442: json: .leojs files</vh></v>
<v t="ekr.20210528083510.1"><vh>#1672: Remove support for Qt docks</vh></v>
<v t="ekr.20210606081234.1"></v>
<v t="ekr.20210405100137.912"><vh>#1768: Change cursor in command mode</vh></v>
<v t="ekr.20210405100137.915"><vh>#1772: Add git-diff-pr command</vh></v>
<v t="ekr.20210405100137.931"><vh>#1781: Leonine diffs of .leo files</vh></v>
<v t="ekr.20210405100137.1062"><vh>#1813: Add leoserver.py and leoclient.py</vh></v>
<v t="ekr.20210405100137.1345"><vh>#1832: Retire @root and convert-at-root command</vh></v>
<v t="ekr.20210528083337.1"><vh>#1846: Support pyQt6</vh></v>
<v t="ekr.20210405100137.1743"><vh>#1867: Simplify rst3</vh></v>
</v>
<v t="ekr.20210405110145.1"><vh>6.4: Other features</vh>
<v t="ekr.20210405100137.456"><vh>#1240: Alert for changed .leo file</vh></v>
<v t="ekr.20210405100137.923"><vh>#1780: Improve support for backup scripts</vh></v>
<v t="ekr.20210405100137.946"><vh>#1792: Improve themes for newbies</vh></v>
<v t="ekr.20210405100137.955"><vh>#1798: Better error reports</vh></v>
<v t="ekr.20210405100137.1061"><vh>#1808: Pylint checks last file by default</vh></v>
<v t="ekr.20210405100137.1384"><vh>#1840: one-shot headline-only</vh></v>
<v t="ekr.20210710163244.2"><vh>#2023: make find-all links clickable</vh></v>
<v t="ekr.20210710040931.1"><vh>Add leo/scripts/wax_off.py</vh></v>
</v>
<v t="ekr.20210405104825.1"><vh>6.4: Settings &amp; command-line options</vh></v>
</v>
<v t="ekr.20201014052236.1"><vh>Leo 6.3 release notes</vh>
<v t="ekr.20201014052236.5"><vh>6.3: Bugs</vh></v>
<v t="ekr.20201014052236.2"><vh>6.3: Code</vh></v>
<v t="ekr.20201014052236.3"><vh>6.3: Commands</vh></v>
<v t="ekr.20201015152218.1"><vh>6.3: Importers</vh></v>
<v t="ekr.20201014052236.4"><vh>6.3: Features</vh></v>
<v t="ekr.20201014052236.6"><vh>6.3: Settings and command-line options</vh></v>
<v t="ekr.20201015122734.1"><vh>6.3: Plugins</vh></v>
</v>
<v t="ekr.20200225075435.1"><vh>Leo 6.2 release notes</vh>
<v t="ekr.20200313052138.1"><vh>6.2: Code</vh></v>
<v t="ekr.20200313054557.1"><vh>6.2: Commands</vh></v>
<v t="ekr.20200313051859.1"><vh>6.2: Features</vh></v>
<v t="ekr.20200313051926.1"><vh>6.2: Bugs</vh></v>
<v t="ekr.20200313053803.1"><vh>6.2: Settings and command-line options</vh></v>
</v>
<v t="ekr.20191003050703.1"><vh>Leo 6.1 release notes</vh>
<v t="ekr.20191003050703.3"><vh>6.1: Major features</vh>
<v t="ekr.20191003060551.1"><vh>#1093: pyzo_in_leo plugin</vh></v>
<v t="ekr.20191003061844.1"><vh>#1315: The history_tracer plugin animates git commits</vh></v>
<v t="ekr.20191004072604.1"><vh>Support for asciidoc and asciidoctor</vh></v>
<v t="ekr.20191007104843.1"><vh>Support for pandoc, including @language pandoc</vh></v>
<v t="ekr.20191003055249.1"><vh>Support for black</vh></v>
<v t="ekr.20191026191805.1"><vh>Support for sphinx</vh></v>
</v>
<v t="ekr.20191003050703.6"><vh>6.1: Bugs</vh>
<v t="ekr.20191003052014.1"><vh>Minor bugs</vh></v>
<v t="ekr.20191003051510.1696"><vh>#1338: {{ conflicts</vh></v>
</v>
<v t="ekr.20191003051809.1"><vh>6.1: Code features</vh></v>
<v t="ekr.20191003050703.11"><vh>6.1: Features</vh></v>
<v t="ekr.20191003050703.15"><vh>6.1: Settings, directives, command-line arguments</vh>
<v t="ekr.20191003051510.14"><vh>#1263: --window-spot</vh></v>
<v t="ekr.20191003051510.1274"><vh>#1289: --global-docks</vh></v>
<v t="ekr.20191003051510.1626"><vh>#1306: @nopyflakes</vh></v>
</v>
</v>
<v t="ekr.20191003062919.1"><vh>Leo 6.0 release notes</vh>
<v t="ekr.20191003062919.2"><vh>Acknowledgements</vh></v>
<v t="ekr.20191003062919.3"><vh>6.0: Major features</vh>
<v t="ekr.20191003062919.4"><vh>Leo requires python 3</vh></v>
<v t="ekr.20191003062919.5"><vh>Leo uses a dock-based gui by default</vh></v>
</v>
<v t="ekr.20191003062919.6"><vh>6.0: Bugs</vh>
<v t="ekr.20191003062919.7"><vh>Bugs related to transition to python 3</vh></v>
<v t="ekr.20191003062919.8"><vh>Bugs related to Qt docks</vh></v>
<v t="ekr.20191003062919.9"><vh>Fixes to LeoWapp</vh></v>
<v t="ekr.20191003062919.10"><vh>Other bugs</vh></v>
</v>
<v t="ekr.20191003062919.11"><vh>6.0: Features</vh>
<v t="ekr.20191003062919.12"><vh>New and improved commands</vh></v>
<v t="ekr.20191003062919.13"><vh>Code features</vh></v>
<v t="ekr.20191003062919.14"><vh>Other features</vh></v>
</v>
<v t="ekr.20191003062919.15"><vh>6.0: Settings and command-line arguments</vh></v>
</v>
</v>
<v t="ekr.20230110152240.1"><vh>Leo 5.x release notes</vh>
<v t="ekr.20190117143933.1"><vh>Leo 5.9 release notes</vh>
<v t="ekr.20190119065631.1"><vh>5.9: Bugs fixed</vh>
<v t="ekr.20190117143942.673"><vh>#0804: ~= in style sheets</vh></v>
<v t="ekr.20190123075604.1"><vh>#0981: &amp; #977: File syncing</vh></v>
<v t="ekr.20190117143942.957"><vh>#0998: Fix recursive import problems</vh></v>
<v t="ekr.20190117143942.2"><vh>#1002: self.assertEqual in a @test node is not comparing lists properly</vh></v>
<v t="ekr.20190117143942.394"><vh>#1007: console gui doesn't load</vh></v>
<v t="ekr.20190412074507.6"><vh>#1018: marks</vh></v>
<v t="ekr.20190118222654.1"><vh>#1021: Fixed add-editor</vh></v>
<v t="ekr.20190117143942.395"><vh>#1023: Marked and expansion bits no longer affect .leo files</vh></v>
<v t="ekr.20190117143942.403"><vh>#1032: importers should not clean blank lines</vh></v>
<v t="ekr.20190117143942.438"><vh>#1033: No @path directive added for empty imported files</vh></v>
<v t="ekr.20190117143942.450"><vh>#1036: and #1046: strip control chars before reading .leo files</vh></v>
<v t="ekr.20190118222624.1"><vh>#1048: &amp; #1037: trailing blank lines</vh></v>
<v t="ekr.20190117143942.633"><vh>#1049: crash kills Leo</vh></v>
<v t="ekr.20190117143942.647"><vh>#1051: eliminate ui interface refs</vh></v>
<v t="ekr.20190117143942.650"><vh>#1053: Unwanted @shadow message on saves</vh></v>
<v t="ekr.20190118085508.1"><vh>#1056: Column numbers in the status line do not work</vh></v>
<v t="ekr.20190117143942.976"><vh>#1057: Unwanted loadOnePlugin messages on startup</vh></v>
<v t="ekr.20190118222636.1"><vh>#1059: cycle-tab-focus exception</vh></v>
<v t="ekr.20190123075859.1"><vh>#1065: refresh-from-disk</vh></v>
<v t="ekr.20190412074507.3"><vh>#1098: crash in json scanner</vh></v>
<v t="ekr.20190424063410.2"><vh>#1100: changes to external files</vh></v>
<v t="ekr.20190412074507.26"><vh>#1111: Read minimal .leo files without crashing</vh></v>
<v t="ekr.20190412074507.50"><vh>#1113: @language lisp crash w/ pygments</vh></v>
<v t="ekr.20190412074507.52"><vh>#1114: bigdash does not load</vh></v>
<v t="ekr.20190424063410.37"><vh>#1116: Crash in viewrendered plugin</vh></v>
<v t="ekr.20190424063410.38"><vh>#1118: Crash in console gui</vh></v>
</v>
<v t="ekr.20190119070017.1"><vh>5.9: Features</vh>
<v t="ekr.20190117143942.654"><vh>#0525: Nested @clean</vh></v>
<v t="ekr.20190325062650.1"><vh>#0568 &amp; #1102: pygments syntax coloring</vh></v>
<v t="ekr.20190117143942.672"><vh>#0672: Leo uses TravisCI</vh></v>
<v t="ekr.20190117143942.681"><vh>#0915: Leo debugger</vh></v>
<v t="ekr.20190122041941.1"><vh>#0926: Organize @outline-data tree-abbreviations</vh></v>
<v t="ekr.20190117143942.29"><vh>#1005: LeoWapp: Leo in a browser</vh></v>
<v t="ekr.20190117143942.399"><vh>#1031, #1050 and #1003: Better error recovery</vh></v>
<v t="ekr.20190122042300.1"><vh>#1047: Tree Window Resizes on Paste Node</vh></v>
<v t="ekr.20190327105147.364"><vh>#1081: @asis</vh></v>
<v t="ekr.20190327105525.1"><vh>#1085: The py3 branch</vh></v>
<v t="ekr.20190412074507.4"><vh>#1090: --script path</vh></v>
<v t="ekr.20190412074507.11"><vh>#1107: Automatic sessions</vh></v>
<v t="ekr.20190327105503.1"><vh>Added g.get_files_in_directory</vh></v>
<v t="ekr.20190327105000.1"><vh>Added promote-headline command</vh></v>
<v t="ekr.20190123122138.1"><vh>Retired the head-to-prev node and tail-to-next-node commands </vh></v>
</v>
<v t="ekr.20190414193153.1"><vh>5.9: Code</vh>
<v t="ekr.20190117143942.463"><vh>#1040: Simplify atFile.write code</vh></v>
<v t="ekr.20190414193128.1"><vh>Added leo/core/leoFastRedraw.py</vh></v>
<v t="ekr.20190327105249.1"><vh>Created py3 branch, for Leo 6.0</vh></v>
</v>
<v t="ekr.20190119071258.1"><vh>5.9: Settings &amp; command-line arguments</vh></v>
</v>
<v t="ekr.20180930062351.1"><vh>Leo 5.8 release notes</vh>
<v t="ekr.20180930062351.2"><vh>Bugs</vh>
<v t="ekr.20180930062351.3"><vh>Fixed in b1</vh>
<v t="ekr.20180930062351.4"><vh>#841: Python importer does not always handle decorators properly</vh></v>
<v t="ekr.20180930062351.5"><vh>#893: Python Console gets stuck on IndentationError</vh></v>
<v t="ekr.20180930062351.6"><vh>#917: System keys on Microsoft keyboard insert unwanted text</vh></v>
<v t="ekr.20180930062351.7"><vh>#922: text following @others is ignored</vh></v>
<v t="ekr.20180930062351.8"><vh>#933: Leo clears the user's clipboard on first time startup</vh></v>
<v t="ekr.20180930062351.9"><vh>#936: hang on sesson start</vh></v>
<v t="ekr.20180930062351.10"><vh>#938: New code breakes tree abbreviations </vh></v>
<v t="ekr.20180930062351.11"><vh>#940: Crashes in stickynotes.py</vh></v>
<v t="ekr.20180930062351.12"><vh>#943: Error in reload-all-settings</vh></v>
<v t="ekr.20180930062351.13"><vh>#947: replace-all</vh></v>
<v t="ekr.20180930062351.14"><vh>#956: syntax error</vh></v>
<v t="ekr.20180930062351.15"><vh>#967: Cross-bile backlink errors</vh></v>
<v t="ekr.20180930062351.16"><vh>backup script saves/restores cwd</vh></v>
<v t="ekr.20180930062351.17"><vh>Fixed crasher in LeoQtLog.linkClicked</vh></v>
<v t="ekr.20180930062351.18"><vh>Fixed problems with git-diff command</vh></v>
<v t="ekr.20180930062351.19"><vh>git-diff now works outside of leo-editor folder</vh></v>
</v>
<v t="ekr.20180930062351.20"><vh>Fixed in b2</vh>
<v t="ekr.20180930062351.21"><vh>#969: Chapter button</vh></v>
<v t="ekr.20180930062351.22"><vh>#970: Crash opening mal-formed .leo files</vh></v>
</v>
</v>
<v t="ekr.20180930062351.23"><vh>Code</vh>
<v t="ekr.20180930062351.24"><vh>#296: private plugin directories</vh></v>
<v t="ekr.20180930062351.25"><vh>#924: Improved performance of at.readAll</vh>
<v t="ekr.20180930062351.26"><vh>Stats...</vh>
<v t="ekr.20180930062351.27"><vh>CProfile: .leo FAST = False</vh></v>
<v t="ekr.20180930062351.28"><vh>cProfile: .leo FAST = True</vh>
<v t="ekr.20180930062351.29"><vh>originals</vh></v>
</v>
<v t="ekr.20180930062351.30"><vh>cProfile, with FAST = True (much improved)</vh></v>
<v t="ekr.20180930062351.31"><vh>Stats: g.isUnicode (before &amp; after)</vh></v>
<v t="ekr.20180930062351.32"><vh>Stats: is_special: before (no change)</vh></v>
<v t="ekr.20180930062351.33"><vh>Stats: g.match_word: before &amp; after</vh></v>
<v t="ekr.20180930062351.34"><vh>Stats: p.ctor (no change will be made)</vh></v>
</v>
</v>
<v t="ekr.20180930062351.35"><vh>Much faster reading of external files</vh></v>
<v t="ekr.20180930062351.36"><vh>Added copy kwarg to generators</vh>
<v t="ekr.20180930062351.37"><vh>Stats: p.copy (before)</vh></v>
<v t="ekr.20180930062351.38"><vh>Stats: p.copy (after, with s.bat)</vh></v>
<v t="ekr.20180930062351.39"><vh>Stats: p.copy (after changing p.get_UNL)</vh></v>
<v t="ekr.20180930062351.40"><vh>Stats: p.copy (after2)</vh></v>
<v t="ekr.20180930062351.41"><vh>Stats: p.copy (after 3)</vh></v>
</v>
<v t="ekr.20180930062538.1"><vh>Added g.app.c property</vh></v>
<v t="ekr.20180930062351.42"><vh>Removed "adjust" and "reassignIndices" kwargs</vh></v>
<v t="ekr.20180930062351.43"><vh>Removed qtree.update_appearance*</vh></v>
<v t="ekr.20180930062351.44"><vh>Improved Leo's outline drawing code</vh></v>
</v>
<v t="ekr.20180930062351.45"><vh>Features</vh>
<v t="ekr.20180930062351.46"><vh>#871: A setting to position the icon bar </vh></v>
<v t="ekr.20180930062351.47"><vh>#913: Show base classes in python importer</vh></v>
<v t="ekr.20180930062351.48"><vh>#914: Fix jedi completion glitches</vh></v>
<v t="ekr.20180930062351.49"><vh>#932: use "show" prefix for many commands</vh></v>
<v t="ekr.20180930062351.50"><vh>#949: Smart quotes</vh></v>
<v t="ekr.20180930062351.51"><vh>#953: better warnings about importing qt</vh></v>
<v t="ekr.20180930062351.52"><vh>#961: curses gui</vh></v>
<v t="ekr.20180930062351.53"><vh>#966: Better support for clojurescript</vh></v>
<v t="ekr.20180930062351.54"><vh>Added --trace-drawing and --trace-startup</vh></v>
<v t="ekr.20180930062351.55"><vh>Added .sty and .latex entries in extension_dict</vh></v>
<v t="ekr.20180930062351.56"><vh>Added @nosearch to results of cff</vh></v>
<v t="ekr.20180930062351.57"><vh>Added dump-clone-parents command</vh></v>
<v t="ekr.20180930062351.58"><vh>Added md_docer.py plugin</vh></v>
<v t="ekr.20180930062351.59"><vh>Added show-stats command &amp; improved tracing</vh></v>
<v t="ekr.20180930062351.60"><vh>Leo ecognizes .latex and .sty as LaTeX files</vh></v>
<v t="ekr.20180930062351.61"><vh>Removed --no-cache &amp; --trace-cache</vh></v>
</v>
</v>
<v t="ekr.20170123085934.1"><vh>Leo 5.5 release notes</vh>
<v t="ekr.20170123090348.1"><vh>Most important features</vh>
<v t="ekr.20170123084701.1"><vh>Fixed huge performance bug in syntax coloring</vh></v>
<v t="ekr.20170123084609.24"><vh>Optionally run pyflakes when saving files</vh></v>
<v t="ekr.20170124034150.1"><vh>Greatly improved javascript and perl importers</vh></v>
<v t="ekr.20170205185641.2"><vh>Optionally colorize doc parts using rST</vh></v>
<v t="ekr.20170124014606.1"><vh>#371: execute-script supports multiple @language direcitves</vh></v>
<v t="ekr.20170124020217.1"><vh>#334: Rewrote all of Leo's importers</vh></v>
<v t="ekr.20170123084609.26"><vh>#328: The pylint command now runs in the background</vh></v>
<v t="ekr.20170124024347.1"><vh>#311: Simplified Leo's argument logic</vh></v>
</v>
<v t="ekr.20170123084609.8"><vh>Bugs</vh>
<v t="ekr.20170123084609.14"><vh>#325: Simplify the organization of commands</vh></v>
<v t="ekr.20170228101933.21"><vh>#340: finish (for 5.5) reload-settings</vh></v>
<v t="ekr.20170228101933.2"><vh>#343: (unicode problems in file names)</vh></v>
<v t="ekr.20170228101933.50"><vh>#344: @string view-rendered-default-kind not functional</vh></v>
<v t="ekr.20170123084609.17"><vh>#348: (CDATA errors)</vh></v>
<v t="ekr.20170308145129.169"><vh>#350: themes not working as documented</vh></v>
<v t="ekr.20170308145129.59"><vh>#352: Importer unit tests create both @clean and @file</vh></v>
<v t="ekr.20170205185641.4"><vh>#367: goto-script problems</vh></v>
<v t="ekr.20170205185641.5"><vh>#371: support multiple languages in scripts</vh></v>
<v t="ekr.20170124015707.1"><vh>#374: Leo can confuse directives with decorators</vh></v>
<v t="ekr.20170205185641.6"><vh>#375: improve jedit.setTag</vh></v>
<v t="ekr.20170205185641.7"><vh>#380: New colorizer doesn't update properly...</vh></v>
<v t="ekr.20170228101933.17"><vh>#381: (default importer encoding problems)</vh></v>
<v t="ekr.20170205185641.8"><vh>#387: New file is marked as changed</vh></v>
<v t="ekr.20170205185641.9"><vh>#388: wikiview plugin</vh></v>
<v t="ekr.20170205185641.10"><vh>#389: syntax coloring changes</vh></v>
<v t="ekr.20170228101933.14"><vh>#391: Read File Into Node" with empty file</vh></v>
<v t="ekr.20170205190147.1"><vh>#392: @auto-rst file.txt: -rst ignored on read</vh></v>
<v t="ekr.20170205185641.11"><vh>#395: beautify-node can hang</vh></v>
<v t="ekr.20170205185641.12"><vh>#396: Show images in Leo's body pane </vh></v>
<v t="ekr.20170206095132.1"><vh>#402: python's input statement hangs Leo</vh></v>
<v t="ekr.20170228101933.19"><vh>#403: goto-global-line error</vh></v>
<v t="ekr.20170228101933.9"><vh>#408: c.recursiveImport uncaught exception...</vh></v>
<v t="ekr.20170228101933.8"><vh>#409: urls no longer colored</vh></v>
<v t="ekr.20170308145129.2"><vh>#416: PageUp binding problem</vh></v>
<v t="ekr.20170228101933.51"><vh>#426: console registerCommand - Chapter_hoist plugin</vh></v>
<v t="ekr.20170228101933.49"><vh>#427: multiple vnodes...</vh></v>
<v t="ekr.20170228101933.52"><vh>#429: goto line number...</vh></v>
<v t="ekr.20170303051729.1"><vh>#430: rst import...</vh></v>
<v t="ekr.20170308145129.32"><vh>#431: Simplify importer tables</vh></v>
<v t="ekr.20170308145129.13"><vh>#434: Potential bug in settings</vh></v>
<v t="ekr.20170228101933.15"><vh>Disabled compare_ast</vh></v>
<v t="ekr.20170123084609.13"><vh>Fixed attribute error in To_Python.go</vh></v>
<v t="ekr.20170123084609.9"><vh>Fixed bug in bracket matching</vh></v>
<v t="ekr.20170228101933.6"><vh>Fixed bug in rst3 command</vh></v>
<v t="ekr.20170123084609.12"><vh>Fixed crash after ! in tab completion</vh></v>
<v t="ekr.20170123084609.16"><vh>Fixed crash in autocomplete (with backspace key?)</vh></v>
<v t="ekr.20170205201047.1"><vh>Fixed crash in elisp importer</vh></v>
<v t="ekr.20170123084609.11"><vh>Fixed date in About Leo dialog</vh></v>
<v t="ekr.20170228101933.3"><vh>Fixed problem when ~/.leo/workbook.leo does not exist</vh></v>
<v t="ekr.20170308145129.141"><vh>Fixed recursive import problems</vh></v>
<v t="ekr.20170228101933.16"><vh>Fixed several importer bugs</vh></v>
<v t="ekr.20170303063731.1"><vh>g.findRootWithPredicate preserves node order</vh></v>
<v t="ekr.20170228101933.7"><vh>g.openUrlOnClick now catches all exceptions</vh></v>
<v t="ekr.20170308145129.132"><vh>The pylint command now runs files in the expected order</vh></v>
</v>
<v t="ekr.20170123084609.18"><vh>Code</vh>
<v t="ekr.20170123084609.20"><vh>Added BackgroundProcessManager class</vh></v>
<v t="ekr.20170123084609.28"><vh>Added four new generators</vh></v>
<v t="ekr.20170228101933.10"><vh>Added g.findRootWithPredicate</vh></v>
<v t="ekr.20170123084609.19"><vh>Added IdleTimeManager</vh></v>
<v t="ekr.20170219074525.1"><vh>All generators yield copies of positions</vh></v>
<v t="ekr.20170228101933.12"><vh>Created g.handleUnl</vh></v>
<v t="ekr.20170219074554.1"><vh>Replaced c.nullPosition() by None</vh></v>
<v t="ekr.20170228101933.13"><vh>Rewrote FreeMindImporter class</vh></v>
<v t="ekr.20170228101933.18"><vh>Simplified Leo's read/write helpers</vh></v>
</v>
<v t="ekr.20170225082023.1"><vh>Documentation</vh>
<v t="ekr.20170225035122.1"><vh>Added new entries to the plugins documentation</vh></v>
</v>
<v t="ekr.20170123084609.22"><vh>Features</vh>
<v t="ekr.20170205185641.3"><vh>#257: chapter-select-forward/back</vh></v>
<v t="ekr.20170228112247.1"><vh>#349: Added --load-type=LOAD_TYPE command-line option</vh></v>
<v t="ekr.20170203060220.1"><vh>#356: Scripting docs for hew users</vh></v>
<v t="ekr.20170123152852.1"><vh>#379: Removed many never-used commands</vh></v>
<v t="ekr.20170123084609.29"><vh>#438: Allow script abbreviations in headlines</vh></v>
<v t="ekr.20170123084609.27"><vh>&lt;Alt-X&gt;99 is the same as &lt;Alt-G&gt;99</vh></v>
<v t="ekr.20170313152439.1"><vh>Added decluttering of headlines</vh></v>
<v t="ekr.20170228125816.1"><vh>Added justify-toggle-auto and autojustify-on-at-start</vh></v>
<v t="ekr.20170311055647.1"><vh>Added leo/Icons/transparent folders and icons</vh></v>
<v t="ekr.20170303113742.1"><vh>Added open-themes-leo command and corresponding menu item</vh></v>
<v t="ekr.20170313151821.1"><vh>Added several new scripts and @button nodes to scripts.leo</vh></v>
<v t="ekr.20170123084609.25"><vh>leoDist.leo appears in the File menu</vh></v>
<v t="ekr.20170228104028.1"><vh>New unl:// links replace file:// syntax</vh></v>
<v t="ekr.20170228101933.20"><vh>re: Make UNL links active</vh></v>
<v t="ekr.20170228104123.1"><vh>Added reload-settings and reload-all-settings commands</vh></v>
<v t="ekr.20170228182610.1"><vh>Rewrote leomail plugin</vh></v>
<v t="ekr.20170123084609.30"><vh>The markdown importer now regularizes sections</vh></v>
<v t="ekr.20170228124856.1"><vh>VR supports @jupyter</vh></v>
</v>
<v t="ekr.20170316061434.1"><vh>Settings and command-line options</vh></v>
</v>
<v t="ekr.20170608071626.1"><vh>Leo 5.6 release notes</vh>
<v t="ekr.20170707034853.2"><vh>major features</vh>
<v t="ekr.20170707034853.3"><vh>#488: Created a console gui for Leo</vh></v>
<v t="ekr.20170822100152.1"><vh>#501: git-diff command</vh></v>
<v t="ekr.20170707034853.5"><vh>#505: Leo switches between git branches properly</vh></v>
<v t="ekr.20170707034853.4"><vh>Added "yes/no to all" buttons for externally changed file dialog</vh></v>
</v>
<v t="ekr.20170707034853.6"><vh>bugs</vh>
<v t="ekr.20170913102052.1"><vh>#541: Editor does not open when using pythonw</vh></v>
<v t="ekr.20170906040849.1"><vh>#508: console gui: print-cmd-docstrings</vh></v>
<v t="ekr.20170906040814.1"><vh>#504: console gui: console issues</vh></v>
<v t="ekr.20170804155454.4"><vh>#317: Viewrendered pane loses live-render feature</vh></v>
<v t="ekr.20170707034853.7"><vh>#385: Leo doesn't remember new headlines after saves</vh></v>
<v t="ekr.20170707034853.8"><vh>#386: colorize markdown properly</vh></v>
<v t="ekr.20170707034853.9"><vh>#438: Tree abbreviation placeholders in headlines...</vh></v>
<v t="ekr.20170707034853.10"><vh>#449 &amp; #470: Spontaneous node generation</vh></v>
<v t="ekr.20170707034853.11"><vh>#451: refresh-from-disk selects wrong node</vh></v>
<v t="ekr.20170707034853.12"><vh>#452: goto-global-lines can fail</vh></v>
<v t="ekr.20170707034853.13"><vh>#453: Focus jumps to body when expanding abbrev in a headline</vh></v>
<v t="ekr.20170804153108.154"><vh>#457: wrap around search</vh></v>
<v t="ekr.20170707034853.14"><vh>#458: Chapters drop-down list is not automatically resized</vh></v>
<v t="ekr.20170707034853.15"><vh>#459: Missing end-of-line characters at the Log Pane </vh></v>
<v t="ekr.20170707034853.16"><vh>#466: Moving a node can cause temporary coloring issues</vh></v>
<v t="ekr.20170707034853.17"><vh>#471: UnicodeDecodeError in writeRecentFilesFileHelper</vh></v>
<v t="ekr.20170707034853.18"><vh>#472: @clean nodes stopped updating</vh></v>
<v t="ekr.20170804155454.5"><vh>#473: nav_qt buttons do not reload if file is re-opened</vh></v>
<v t="ekr.20170707034853.19"><vh>#476: (error in cacher.fileKey)</vh></v>
<v t="ekr.20170707034853.20"><vh>#479: Preserve brython indentation...</vh></v>
<v t="ekr.20170707034853.21"><vh>#481: The python importer optionally puts method decorators in headlines</vh></v>
<v t="ekr.20170707034853.22"><vh>#487: g.IdleTime docstring</vh></v>
<v t="ekr.20170707034853.23"><vh>#498: --session-restore option fails if no leo.session exists</vh></v>
<v t="ekr.20170804155454.6"><vh>#505: Leo's read code must be rewritten</vh></v>
<v t="ekr.20170707034853.24"><vh>#510: Improved how Leo handles settings</vh></v>
<v t="ekr.20170804153108.184"><vh>#516: Content of find tab can disappear</vh></v>
<v t="ekr.20170804155454.7"><vh>#516: Content of find tab can disappear</vh></v>
<v t="ekr.20170804153108.198"><vh>#522: cycle-editor-focus raises ValueError</vh></v>
<v t="ekr.20170804153108.135"><vh>#526: @persistence doesn't retain tags and links (uA's)</vh></v>
<v t="ekr.20170823100047.1"><vh>#528: @menuat duplicates menus when myLeoSettings is opened</vh></v>
<v t="ekr.20170823100152.1"><vh>#529: help-for-settings and docs for @menu and @item in leoSettings.leo </vh></v>
<v t="ekr.20170804155213.1"><vh>#537: Non-ascii characters in leo.core.commit_timestamp.json crashes Leo</vh></v>
<v t="ekr.20170804155454.3"><vh>#62: Syntax @color settings don't dereference</vh></v>
<v t="ekr.20170707034853.25"><vh>Ensure that .leo/.leoRecentFiles.txt is closed</vh></v>
<v t="ekr.20170707034853.26"><vh>Fixed bug in k.computeInverseBindingDict</vh></v>
<v t="ekr.20170707034853.27"><vh>Fixed bug in tab completion</vh></v>
<v t="ekr.20170707034853.28"><vh>Fixed bugs re plugins registration</vh></v>
<v t="ekr.20170707034853.29"><vh>Fixed html import problem</vh></v>
<v t="ekr.20170707034853.30"><vh>Fixed serious bug in c.checkFileTimeStamp</vh></v>
<v t="ekr.20170707034853.31"><vh>Fixed several problems with goto-global-line</vh></v>
<v t="ekr.20170707034853.32"><vh>The pylint command now warns if pylint has not been installed</vh></v>
</v>
<v t="ekr.20170707034853.33"><vh>code</vh>
<v t="ekr.20170804153108.4"><vh>#505: Leo's read code must be rewritten</vh></v>
<v t="ekr.20170804153108.166"><vh>#512: unit tests are failing for Terry</vh></v>
<v t="ekr.20170808083130.1"><vh>#539: Redesigned Leo's redraw code</vh></v>
<v t="ekr.20170707034853.34"><vh>Added 'recursive' keyword arg to recursive import API</vh></v>
<v t="ekr.20170707034853.35"><vh>Added better checks in v.setBodyString &amp; v.setHeadString</vh></v>
<v t="ekr.20170707034853.36"><vh>Added g.Git functions</vh></v>
<v t="ekr.20170707034853.37"><vh>Added gen_refs keyword arg to Importer ctor</vh></v>
<v t="ekr.20170707034853.38"><vh>Added traces to c.doCommand to detect multiple redraws</vh></v>
<v t="ekr.20170707034853.39"><vh>Improved @auto write code</vh></v>
<v t="ekr.20170707034853.40"><vh>Removed atAuto switch from atFile class</vh></v>
<v t="ekr.20170707034853.41"><vh>Updated docs re #464</vh></v>
<v t="ekr.20170707034853.42"><vh>Use 'with' statement to simplify code</vh></v>
</v>
<v t="ekr.20170707034853.43"><vh>commands</vh>
<v t="ekr.20170707034853.44"><vh>#185: Added edit-recent-files and write-edited-recent-files commands</vh></v>
<v t="ekr.20170707034853.55"><vh>#456: replace-all command is much faster</vh></v>
<v t="ekr.20170707034853.48"><vh>#482: Added toggle-auto-edit command</vh>
<v t="ekr.20170707034853.49"><vh>efc.toggleAtAutoAtEdit &amp; helpers</vh>
<v t="ekr.20170707034853.50"><vh>efc.toAtAuto</vh></v>
<v t="ekr.20170707034853.51"><vh>efc.toAtEdit</vh></v>
</v>
</v>
<v t="ekr.20170804153108.157"><vh>#495 and #496: jump/push commands</vh></v>
<v t="ekr.20170823085504.1"><vh>#529: Added help-for-settings command</vh></v>
<v t="ekr.20170707034853.45"><vh>Added goto-any-clone command</vh></v>
<v t="ekr.20170707034853.46"><vh>Added listen-to-log and other commands</vh></v>
<v t="ekr.20170708002743.1"><vh>Added push-cursor and pop-cursor</vh></v>
<v t="ekr.20170707034853.47"><vh>Added show-color-names command</vh></v>
<v t="ekr.20170708002922.1"><vh>Added start-of-line/finish-line commands</vh></v>
<v t="ekr.20170707034853.52"><vh>clone-find commands report number of matches in root node</vh></v>
<v t="ekr.20170707034853.53"><vh>Improved indent-region and unindent-region commands</vh></v>
<v t="ekr.20170707034853.54"><vh>Improved move-lines-up/down commands</vh></v>
<v t="ekr.20170707034853.73"><vh>valuescript plugin now supports vs-eval-block command</vh></v>
</v>
<v t="ekr.20170707034853.56"><vh>importers</vh>
<v t="ekr.20170707034853.59"><vh>#479: Revised xml/html importers</vh></v>
<v t="ekr.20170707034853.57"><vh>Added importer for the lua language</vh></v>
<v t="ekr.20170707034853.58"><vh>Added tcl importer</vh></v>
</v>
<v t="ekr.20170707034853.60"><vh>other features</vh>
<v t="ekr.20170804155454.10"><vh>#446: Added vr-zoom command</vh></v>
<v t="ekr.20170707034853.61"><vh>#448: Add abbreviations for commands</vh></v>
<v t="ekr.20170707034853.62"><vh>#478: Allow paste-retaining-clones across different .leo files</vh></v>
<v t="ekr.20170707034853.63"><vh>#484: Improved Windows menu</vh></v>
<v t="ekr.20170804155454.11"><vh>#531: file timestamps</vh></v>
<v t="ekr.20170707034853.64"><vh>Added  git branch name to backed-up files</vh></v>
<v t="ekr.20170925084456.1"><vh>Added leo_cloud and leo_cloud_server plugins</vh></v>
<v t="ekr.20170707034853.65"><vh>Improved "Write Existing File?" dialog</vh></v>
<v t="ekr.20170707034853.66"><vh>Improved caching</vh></v>
<v t="ekr.20170707034853.67"><vh>Improved operation of command history</vh></v>
<v t="ekr.20170707034853.68"><vh>Indicate branch in Window title</vh></v>
<v t="ekr.20170707034853.70"><vh>VR renders LaTex (python 2 only)</vh></v>
</v>
<v t="ekr.20170707034853.74"><vh>settings &amp; command-line arguments</vh>
<v t="ekr.20170707034853.75"><vh>#518: Added @bool report_unchanged_files</vh></v>
<v t="ekr.20170707034853.76"><vh>Added --trace-focus command-line argument</vh></v>
<v t="ekr.20170804155454.9"><vh>Added @bool color_trailing_whitespace &amp; @color trailing_whitespace_color</vh></v>
<v t="ekr.20170804154716.1"><vh>Added @bool log_show_save_time &amp; @string log_timestamp_format</vh></v>
<v t="ekr.20170707034853.77"><vh>Added @bool run_pyflakes_on_unchanged_files = True</vh></v>
<v t="ekr.20170707034853.78"><vh>Added Ctrl-Shift-&lt; and Ctrl-Shift-&gt; bindings</vh></v>
<v t="ekr.20170707034853.79"><vh>Restored default: @bool check_for_changed_external_files = True</vh></v>
<v t="ekr.20170707034853.80"><vh>Retired @bool allow_section_references_in_at_auto</vh></v>
<v t="ekr.20170707034853.72"><vh>screen_capture.py now enabled by default</vh></v>
</v>
</v>
<v t="ekr.20180125034327.1"><vh>Leo 5.7 release notes</vh>
<v t="ekr.20180125032239.1"><vh>Leo 5.7 Summary</vh></v>
<v t="ekr.20180125041229.1"><vh>Leo 5.7 Major features</vh>
<v t="ekr.20180124100450.49"><vh>#417: reload-settings command</vh></v>
<v t="ekr.20180124100450.168"><vh>#503: Use string/null gui for unit tests</vh></v>
<v t="ekr.20180130055320.1"><vh>#562: A PyPi wheel for Leo</vh></v>
<v t="ekr.20180124100450.906"><vh>#597: Show tips when Leo starts up</vh></v>
<v t="ekr.20180124100450.913"><vh>#635: Link to nodes from log pane</vh></v>
<v t="ekr.20180212070925.1"><vh>#700: Spell checking works without pyenchant</vh></v>
<v t="ekr.20180212163926.1"><vh>Added a cvs table editing widget</vh></v>
<v t="ekr.20180124121851.1"><vh>Added Debian package for Leo</vh></v>
<v t="ekr.20180212065030.1"><vh>Added Outline-oriented diffs of .leo files</vh></v>
</v>
<v t="ekr.20180125034637.1"><vh>Leo 5.7 Bugs fixed</vh>
<v t="ekr.20180226091747.1"><vh>Leo 5.7 b1: Bugs fixed</vh>
<v t="ekr.20180125235811.3"><vh>#327: Create a way to unbind bindings in leoSettings.leo</vh></v>
<v t="ekr.20180125235811.2"><vh>#362: default_path within @rst-options honoured or ignored depending on the node where rst3 command is executed</vh></v>
<v t="ekr.20180125235811.1"><vh>#384: open files with very long path</vh></v>
<v t="ekr.20180125235810.9"><vh>#489: wikiview plugin docs / patterns / function</vh></v>
<v t="ekr.20180125235810.8"><vh>#493: Leo GUI window not repositioning properly with changing monitor configuration</vh></v>
<v t="ekr.20180125235810.7"><vh>#509: Fix console gui problems</vh></v>
<v t="ekr.20180125235810.6"><vh>#510: Improve how Leo handles settings</vh></v>
<v t="ekr.20180124100450.328"><vh>#528: @menuat duplicates menus when myLeoSettings is opened</vh></v>
<v t="ekr.20180125235810.5"><vh>#550: Refresh from disk not working for @shadow nodes</vh></v>
<v t="ekr.20180125235810.4"><vh>#552: @clean is not compatible with org mode files</vh></v>
<v t="ekr.20180125235810.3"><vh>#553: leo crashes using iPython bridge</vh></v>
<v t="ekr.20180125235810.2"><vh>#554: ipython leo window blank (Not Responding)</vh></v>
<v t="ekr.20180125235810.1"><vh>#555: @path exception</vh></v>
<v t="ekr.20180124100450.360"><vh>#556: AttributeError: 'LeoApp' object has no attribute 'cacher'</vh></v>
<v t="ekr.20180125235809.31"><vh>#560: simulateCommand: no command for &lt;command-defined-by-plugin&gt;</vh></v>
<v t="ekr.20180124100450.367"><vh>#571: Hyperlink click does not launch the page</vh></v>
<v t="ekr.20180125235809.29"><vh>#573: leoDist: some external files missing when installed by pip</vh></v>
<v t="ekr.20180125235809.28"><vh>#578: Support for org-mode tags on import</vh></v>
<v t="ekr.20180125235809.27"><vh>#579: Key bindings don't take for commands defined in plugins</vh></v>
<v t="ekr.20180125235809.26"><vh>#585: css syntax coloring (@language css)</vh></v>
<v t="ekr.20180125235809.25"><vh>#586: Pip install fails on gitDescribe --&gt; need to distinguish Dev and User installs</vh></v>
<v t="ekr.20180125235809.24"><vh>#591: LEP will strip HTML from HTML nodes</vh></v>
<v t="ekr.20180125235809.23"><vh>#593: File --&gt; RecentFiles can not work</vh></v>
<v t="ekr.20180125235809.22"><vh>#595: The dark theme is broken on Windows</vh></v>
<v t="ekr.20180125235809.21"><vh>#600: `insert-child` worked same as `insert-node`</vh></v>
<v t="ekr.20180125235809.20"><vh>#603: Missing files when installing Leo from PyPI using "pip install leo"</vh></v>
<v t="ekr.20180125235809.19"><vh>#604: Missing files when installing Leo from PyPI using "pip install leo[develop]"</vh></v>
<v t="ekr.20180125235809.18"><vh>#627: cft error</vh></v>
<v t="ekr.20180125235809.17"><vh>#630: Do we need both rst-ignore-tree and rst-ignore?</vh></v>
<v t="ekr.20180125235809.16"><vh>#634: Hard crash in quicksearch when using regular expressions</vh></v>
<v t="ekr.20180125235809.15"><vh>#638: gui console mode broken on Linux py2.7 </vh></v>
<v t="ekr.20180125235809.14"><vh>#639: Javascript importer should use @others everywhere</vh></v>
<v t="ekr.20180125235809.13"><vh>#640: .org importer fails for leading introduction lines</vh></v>
<v t="ekr.20180125235809.12"><vh>#641: invalid syntax after git pull</vh></v>
<v t="ekr.20180125235809.11"><vh>#645: TabImporter fails on files with both tabs and spaces</vh></v>
<v t="ekr.20180125235809.10"><vh>#648: pyflakes warnings should not prevent script execution</vh></v>
<v t="ekr.20180125235809.9"><vh>#649: Leo only evaluates one path expression in @path &amp; @&lt;file&gt; paths</vh></v>
<v t="ekr.20180125235809.8"><vh>#651: Javascript importer fails for leo.js</vh></v>
<v t="ekr.20180125235809.7"><vh>#652: leovue/src/components/viewgrid.js dos not import perfectly</vh></v>
<v t="ekr.20180125235809.6"><vh>#653: Javascript importer crashes on jqterm.js</vh></v>
<v t="ekr.20180125235809.5"><vh>#654: Undoer class problem</vh></v>
<v t="ekr.20180125235809.4"><vh>#656: @buttons defined in local myLeoSettings.leo not appearing in work files</vh></v>
<v t="ekr.20180125235809.3"><vh>#657: @rclick button-name not working if under @buttons node</vh></v>
<v t="ekr.20180201101506.1"><vh>#658: duplicate gnx problem</vh></v>
<v t="ekr.20180127092625.1"><vh>#659: --session-restore causes failure on first launch</vh></v>
<v t="ekr.20180128101447.1"><vh>#661: leoBridge scripts should not update the recent files list</vh></v>
<v t="ekr.20180216043451.7"><vh>#718: @command-x = binding crashes Leo</vh></v>
<v t="ekr.20180124100450.728"><vh>Fixed can not open message in leoBridge test</vh></v>
</v>
<v t="ekr.20180226032107.1"><vh>Leo 5.7 final: Bugs fixed</vh></v>
</v>
<v t="ekr.20180125035840.1"><vh>Leo 5.7 Code improvements</vh>
<v t="ekr.20180226150731.1"><vh>Leo 5.7 b1 Code improvements</vh>
<v t="ekr.20180124100450.369"><vh>#577: reformatting unit tests...</vh></v>
<v t="ekr.20180124100450.427"><vh>#589 @g.commander_command</vh></v>
<v t="ekr.20180128112939.1"><vh>Added "exact" keyword arg to g.findNode* functions</vh></v>
<v t="ekr.20180126003014.1"><vh>Added @button get-issues to LeoDocs.leo</vh></v>
<v t="ekr.20180124120513.1"><vh>Added backup-repo script in leoPy.leo</vh></v>
<v t="ekr.20180212065845.1"><vh>Added c.backup_helper</vh></v>
<v t="ekr.20180126060924.1"><vh>Added g.getGitIssues</vh></v>
<v t="ekr.20180124100450.1030"><vh>Added p.promote</vh></v>
<v t="ekr.20180126060940.1"><vh>Added top-level make_tip_nodes in leoTips.py</vh></v>
<v t="ekr.20180124100440.5"><vh>Added verbose option to g.callers()</vh></v>
<v t="ekr.20180124121124.1"><vh>Improved Leo read/write code in leoAtFile.py</vh></v>
<v t="ekr.20180124100440.3"><vh>New redraw code</vh></v>
<v t="ekr.20180216063833.1"><vh>Suppress warnings in fc.resolveArchivedPosition</vh></v>
</v>
<v t="ekr.20180226150747.1"><vh>Leo 5.7 final code improvements</vh></v>
</v>
<v t="ekr.20180125042412.1"><vh>Leo 5.7 Commands</vh>
<v t="ekr.20180124100450.839"><vh>#632: check-conventions command</vh></v>
<v t="ekr.20180211112158.1"><vh>Added clean-main-user-dict &amp; clean-user-spell-dict</vh></v>
<v t="ekr.20180201041411.1"><vh>Added count-children command</vh></v>
<v t="ekr.20180216044139.1"><vh>Added demangle-recent-files</vh></v>
<v t="ekr.20180212164854.1"><vh>Added edit-pane-csv &amp; edit-pane-test-open</vh></v>
<v t="ekr.20180124124409.1"><vh>Added insert-as-first-child &amp; insert-as-last-child commands</vh></v>
<v t="ekr.20180130092843.1"><vh>Added read/set/update-ref-file commands</vh></v>
<v t="ekr.20180212071157.1"><vh>Added show-spell-info command</vh></v>
<v t="ekr.20180124100450.797"><vh>The cff commands now sort their results</vh></v>
</v>
<v t="ekr.20180126001345.1"><vh>Leo 5.7 Settings and command-line arguments</vh>
<v t="ekr.20180124100450.803"><vh>Reinstated --trace-shutdown command-line argument</vh></v>
<v t="ekr.20180126063712.1"><vh>@bool show-tips</vh></v>
</v>
<v t="ekr.20180124100450.1"><vh>Leo 5.7 Enhancements</vh>
<v t="ekr.20180226091936.1"><vh>Leo 5.7 b1: Enhancements</vh>
<v t="ekr.20180125235816.1"><vh>#310: Create new file in right-click in file tab in UI</vh></v>
<v t="ekr.20180124100450.3"><vh>#327: Create a way to unbind bindings in leoSettings.leo</vh></v>
<v t="ekr.20180125235814.18"><vh>#414: Add p.drawer, p.results, etc.</vh></v>
<v t="ekr.20180125235814.17"><vh>#417: Complete reload-settings</vh></v>
<v t="ekr.20180125235814.16"><vh>#428: Code review: tree redrawing logic</vh></v>
<v t="ekr.20180125235814.15"><vh>#503: Use string/null gui for unit tests</vh></v>
<v t="ekr.20180125235814.14"><vh>#510: Improve how Leo handles settings</vh></v>
<v t="ekr.20180125235814.13"><vh>#523: Check *all* scripts with pyflakes</vh></v>
<v t="ekr.20180124100450.357"><vh>#529: Improved documentation</vh></v>
<v t="ekr.20180125235814.12"><vh>#552: @clean is not compatible with org mode files</vh></v>
<v t="ekr.20180125235814.11"><vh>#577: Let reformatting unit tests run in more environments</vh></v>
<v t="ekr.20180125235814.10"><vh>#583: Remove top-level docs folder</vh></v>
<v t="ekr.20180125235814.9"><vh>#584: Clean up the worst pep8 offenses</vh></v>
<v t="ekr.20180125235814.8"><vh>#587: Dynamic display of node attributes (headline tags)</vh></v>
<v t="ekr.20180125235814.7"><vh>#589: Use @g.commander_command to define commands in Commands class</vh></v>
<v t="ekr.20180125235814.6"><vh>#596: Use @ifplatform to create platform-specific settings in leoSettings.leo</vh></v>
<v t="ekr.20180125235814.5"><vh>#597: Show tips when Leo starts up</vh></v>
<v t="ekr.20180125235814.4"><vh>#602: Add ability to modify spell-check dictionary</vh></v>
<v t="ekr.20180125235814.3"><vh>#613: Support patching of Leo's colorizer tables</vh></v>
<v t="ekr.20180125235814.2"><vh>#635: Link to nodes from log</vh></v>
<v t="ekr.20180125235814.1"><vh>#655: The js importer could remove @others when a node has only one child</vh></v>
<v t="ekr.20180202061934.1"><vh>#674: Add a treepad importer</vh></v>
<v t="ekr.20180216082220.1"><vh>Added limited support for .rs (rust files)</vh></v>
<v t="ekr.20180124100450.704"><vh>Added HEAD, TAIL, REST declutter replacement "patterns"</vh></v>
<v t="ekr.20180124124532.1"><vh>Improved javascript importer</vh></v>
</v>
<v t="ekr.20180212070807.1"><vh>Leo 5.7 b2: Enhancements</vh>
<v t="ekr.20180212070925.1"></v>
<v t="ekr.20180212065845.1"></v>
<v t="ekr.20180211112158.1"></v>
<v t="ekr.20180212065030.1"></v>
<v t="ekr.20180212071157.1"></v>
</v>
<v t="ekr.20180226092312.1"><vh>Leo 5.7 final: Enhancements</vh></v>
</v>
<v t="ekr.20180125041723.1"><vh>Leo 5.7 Plugins</vh>
<v t="ekr.20180124100450.126"><vh>#488: Improved the console_gui plugin</vh></v>
<v t="ekr.20180124100450.888"><vh>#613: patch_python_colorizer.py plugin</vh></v>
<v t="ekr.20180124100440.6"><vh>New leo_cloud.py plugin</vh></v>
<v t="ekr.20180124122055.1"><vh>New line_numbering.py plugin</vh></v>
</v>
</v>
<v t="ekr.20180404015249.1"><vh>Leo 5.7.1 Themes</vh>
<v t="ekr.20180404020342.1"><vh>Bugs</vh>
<v t="ekr.20180404015841.6"><vh>#780: @tabwidth -2 in @data qt-gui-plugin-style-sheet crashes Leo</vh></v>
<v t="ekr.20180404022106.1"><vh>#781: ViewRendered Plugin fails on Python 2.7 (Bad Import Statement)</vh></v>
<v t="ekr.20180404015841.7"><vh>#783: print- commands fail under pythonw</vh></v>
<v t="ekr.20180404015841.8"><vh>#788: Fix theme-related bugs</vh></v>
<v t="ekr.20180404021814.1"><vh>#792: python_console plugin doesn't handle copy/paste properly</vh></v>
<v t="ekr.20180404021737.1"><vh>#802: @color @image display in vr pane</vh></v>
<v t="ekr.20180404015841.9"><vh>#808: Loading Images in Themes is Broken</vh></v>
<v t="ekr.20180404021630.1"><vh>#809: Themes dialog doesn't always start in leo/themes</vh></v>
<v t="ekr.20180404015841.10"><vh>#812: g.glob_glob problems</vh></v>
<v t="ekr.20180404021543.1"><vh>#832: Leo crashes on non English systems</vh></v>
<v t="ekr.20180404015841.11"><vh>#840: config.getData(foo) strips comments inconsistently</vh></v>
<v t="ekr.20180404015841.12"><vh>#843: Cannot Open Any Non Leo File From Command Line</vh></v>
</v>
<v t="ekr.20180404020244.1"><vh>Code</vh>
<v t="ekr.20180404172529.1"><vh>Added add_path keyword argument to c.recursiveImport</vh></v>
<v t="ekr.20180404015841.13"><vh>Added g.backupGitIssues</vh></v>
<v t="ekr.20180404020037.1"><vh>Added g.caller</vh></v>
<v t="ekr.20180404015841.15"><vh>g.log is a synonym for g.es</vh></v>
</v>
<v t="ekr.20180404021227.1"><vh>Commands</vh>
<v t="ekr.20180404021236.1"><vh>#839: Replaced 5 vs-* commands with eval* commands</vh></v>
<v t="ekr.20180404070940.1"><vh>Added open-theme-file command</vh></v>
<v t="ekr.20180404015841.17"><vh>Retired the 'escape' and 'eval-expression' commands</vh></v>
</v>
<v t="ekr.20180404020226.1"><vh>Features</vh>
<v t="ekr.20180404015923.1"><vh>#467: Add setting for preferred directory</vh></v>
<v t="ekr.20180404015841.2"><vh>#663: Regularize slashes and back slashes</vh></v>
<v t="ekr.20180404015841.3"><vh>#748: Improve show-settings command</vh></v>
<v t="ekr.20180404015841.4"><vh>#763: Use html comments to support @file x.md</vh></v>
<v t="ekr.20180404015841.5"><vh>#766: Create Theme menu, etc.</vh></v>
<v t="ekr.20180404021847.1"><vh>#784: Warn if stylesheet substitution leaves undefined @-constants</vh></v>
<v t="ekr.20180404015841.14"><vh>Feature: Allow @path in body text</vh></v>
<v t="ekr.20180404015841.18"><vh>Won't do: #822: Put outline tabs below the main window bar</vh></v>
</v>
<v t="ekr.20180404063924.1"><vh>Settings &amp; command-line arguments</vh></v>
</v>
<v t="ekr.20180411070654.1"><vh>Leo 5.7.2 Jupyter &amp; Git</vh>
<v t="ekr.20180411150947.1"><vh>Bugs</vh>
<v t="ekr.20180411150950.1"><vh>#757: MacOS: replace-then-find does not work in headlines</vh></v>
<v t="ekr.20180411105215.1"><vh>#794: Clicking Find Tab should do exactly what pushing Ctrl-F does</vh></v>
<v t="ekr.20180505114332.5"><vh>#848: Recent Files menu will break for foreign languages</vh></v>
<v t="ekr.20180505114332.8"><vh>#862: paste-retaining-clones can corrupt the outline</vh></v>
<v t="ekr.20180505114332.9"><vh>#863: Serious problems changing branches</vh></v>
<v t="ekr.20180505114332.13"><vh>#877: Exception in the markdown importer</vh></v>
<v t="ekr.20180505114332.14"><vh>#879: g.es can be too slow</vh></v>
<v t="ekr.20180505114332.15"><vh>#880: Replace command does not set @&lt;file&gt; nodes dirty</vh></v>
<v t="ekr.20180505114332.17"><vh>#884: Log pane does not handle leading whitespace properly</vh></v>
</v>
<v t="ekr.20180427130017.1"><vh>Code</vh>
<v t="ekr.20180505114332.2"><vh>#423: Simplify key handling with a better KeyStroke class</vh></v>
</v>
<v t="ekr.20180411073507.1"><vh>Features</vh>
<v t="ekr.20180411102234.1"><vh>#838: Better .ipynb importer/exporters</vh></v>
<v t="ekr.20180505114332.18"><vh>#886: Add c.interactive1/2/3 methods</vh></v>
<v t="ekr.20180501163005.1"><vh>Added insert-jupyter-toc and insert-markdown-toc commands</vh></v>
<v t="ekr.20180427125919.1"><vh>Added new command-line arguments</vh></v>
<v t="ekr.20180427130028.1"><vh>Removed unused settings</vh></v>
</v>
</v>
<v t="ekr.20180509122406.1"><vh>Leo 5.7.3 release notes</vh>
<v t="ekr.20180509123013.1"><vh>Bugs</vh>
<v t="ekr.20180526131124.1"><vh>#841: Python importer does not always handle decorators properly </vh></v>
<v t="ekr.20180509123007.1"><vh>#892: Crash in checkForChangedNodes</vh></v>
<v t="ekr.20180526130745.1"><vh>#893: Python Console gets stuck on IndentationError </vh></v>
<v t="ekr.20180511062809.1"><vh>#901: The Windows Right-Menu key insert "Menu" into text</vh></v>
</v>
<v t="ekr.20180509125836.1"><vh>Code</vh>
<v t="ekr.20180509125839.1"><vh>#875: Rename json reader/writer plugins</vh></v>
<v t="ekr.20180522101756.1"><vh>BackgroundProcessManager supports clickable links</vh></v>
<v t="ekr.20180527084114.1"><vh>Removed most g.trace statements</vh></v>
</v>
<v t="ekr.20180523053906.1"><vh>Info items</vh>
<v t="ekr.20180523053913.1"><vh>#909: How to use LaTeX with Leo</vh></v>
<v t="ekr.20180523063338.1"><vh>#910: Summary of developer info items</vh></v>
</v>
<v t="ekr.20180509123018.1"><vh>Features</vh>
<v t="ekr.20180526213056.1"><vh>#309: Support Jedi autocompletion</vh></v>
<v t="ekr.20180525211530.1"><vh>#738: Links in Tips dialogs are now clickable</vh></v>
<v t="ekr.20180511101509.1"><vh>#868: Allow separate bindings for numeric keypad keys</vh></v>
<v t="ekr.20180522121943.1"><vh>#904: Allow local overrides of abbreviations</vh></v>
<v t="ekr.20180702171546.1"><vh>#932: use show-prefix</vh></v>
<v t="ekr.20180509122603.1"><vh>Added diff-related wrappers</vh></v>
<v t="ekr.20180509122901.1"><vh>Added leo_babel plugin</vh></v>
<v t="ekr.20180524104432.1"><vh>Improved recursive import script</vh></v>
<v t="ekr.20180526131023.1"><vh>Improved typescript importer</vh></v>
<v t="ekr.20180522101650.1"><vh>pylint creates clickable links</vh></v>
<v t="ekr.20180510093733.1"><vh>Removed settings</vh></v>
<v t="ekr.20180511061629.1"><vh>Smart searches for functions and methods</vh></v>
</v>
</v>
</v>
</v>
</v>
<v t="ekr.20260531063902.1"></v>
<v t="ekr.20260531063735.1"></v>
</vnodes>
<tnodes>
<t tx="EKR.20040524104904.140">Leo stores options in **@settings trees**, outlines whose headline is ``@settings``. When opening a .leo file, Leo looks for ``@settings`` trees not only in the outline being opened but also in various ``leoSettings.leo`` files. This scheme allows for the following kinds of settings:

- Per-installation or per-machine settings.
- Per-user settings.
- Per-folder settings.
- Per-file settings.

There are four kinds of settings files:

1. **Default settings files**, named **leoSettings.leo**. Although they can be used in other ways, they typically contain default settings.

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

3. **Machine settings files**, named **&lt;prefix&gt;myLeoSettings.leo**, where **prefix** comes from os.getenv('HOSTNAME')or os.getenv('COMPUTERNAME').

4. **Theme files**. These are .leo files containing stylesheets and other appearance-related settings.

The following sections describe the kinds of nodes in ``@settings`` trees.
</t>
<t tx="EKR.20040524104904.224">Naively using plugins can expose you and your .leo files to malicious attacks. The fundamental principles are::

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

and::

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

Stephen Schaefer summarizes the danger this way::

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

In other words::

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

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

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

    # Warning: extremely dangerous code

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

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

.. code-block:: python

    badNode = c.p
    for p in c.all_positions():
        # &lt;&lt; change `rexec` to `exec` in p's body &gt;&gt;
    # &lt;&lt; delete badNode &gt;&gt;
    # &lt;&lt; clear the undo stack &gt;&gt;

This script will introduce a security hole the .leo file without doing anything prohibited by rexec, and without leaving any traces of the perpetrating script behind. The damage will become permanent *outside* this script when the user saves the .leo file.
</t>
<t tx="EKR.20040524104904.240">If a plugin has a function at the outer (module) level called unitTest, Leo's unit tests will call that function.

So it would be good if writers of plugins would create such a unitTest function. To indicate a failure the unitTest can just throw an exception. Leo's plugins test suite takes care of the rest.
</t>
<t tx="EKR.20040524104904.248">The following sections describe the complexities that were involved in designing Leo's simple-looking mechanisms. They give a pseudo-chronological list of the major Aha's involved in creating Leo2. These Aha's form the real design and theory of operation of Leo. 

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

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

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

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

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

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

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

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

"We can use the following convention to determine where putDocPart has inserted line breaks: A line in a doc part is followed by an inserted newline if and only if the newline is preceded by whitespace. This is an elegant convention, and is essentially invisible to the user. Tangle outputs words until the line would become too long, and then it inserts a newline. To preserve all whitespace, tangle always includes the whitespace that terminates a word on the same line as the word itself. Therefore, split lines always end in whitespace. To make this convention work, tangle only has to delete the trailing whitespace of all lines that are followed by a 'real' newline."
</t>
<t tx="EKR.20040524104904.253">After the write code was working I turned my attention to the read (untangle) code. Leo's Untangle command is the most complex and difficult code I have ever written. Imagine my surprise when I realized that the Leo2 read code is essentially trivial! Indeed, the Leo2 untangle code is like an assembler. The read code scans lines of a external files looking for "opcodes", that is, sentinel lines, and executes some simple code for each separate opcode. The heart of this code is the scanText routine in atFile.cpp.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

This ends the original history of Leo2. In fact, it took quite a while before Leo recovered properly from all errors. I finally saw that .leo files should duplicate all information in external files. This allows a .leo file to be used a single backup file and allows maximal error recovery in all situations. It took several months to stamp out several subtle bugs involving clones that caused spurious read errors. Such errors undermine confidence in Leo and can cause disastrous reversions. See my diary entries for January 2002 in leo.py for details.
</t>
<t tx="EKR.20040524104904.268">Leo's grand strategy for handling text is as follows:

1. Internally, Leo uses unicode objects for all text.

2. When reading files or user input, Leo converts all plain (encoded)
   strings to unicode.

3. When reading or writing files, Leo converts unicode strings to encoded
   strings.

To make this strategy work, Leo must know the encoding used for external files. This is why Leo supports the @encoding directive and various encoding-related settings.

The g.toUnicode and g.toEncodedString functions convert to and from unicode. These methods catch all unicode-related exceptions.

The g.u function should be used *only* to convert from the Qt string type (a wrapper for a unicode string) to unicode. Do not use g.u instead of g.toUnicode.
</t>
<t tx="EKR.20040524104904.354">Leo uses unicode internally for all strings.

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

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

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

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

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

        default_derived_file_encoding = UTF-8 
        new_leo_file_encoding = UTF-8 

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

4. The @encoding directive specifies the encoding used in a external file. You can't mix encodings in a single external file.
</t>
<t tx="EKR.20040524104904.357">.. _`Writing plugins`:   writingPlugins.html

Here are the XML elements that may appear in Leo files:

``&lt;?xml&gt;``
    Leo files start with the following line::

        &lt;?xml version="1.0" encoding="UTF-8"?&gt;

``&lt;?xml-stylesheet&gt;``
    This element is optional.  For example::

        &lt;?xml-stylesheet ekr_stylesheet?&gt;

``&lt;leo_file&gt;``
    This element opens an element that contains the entire file.
    ``&lt;/leo_file&gt;`` ends the file.

``&lt;leo_header&gt;`` 
    This element specifies version information and other information
    that affects how Leo parses the file.  For example::

        &lt;leo_header file_format="2"/&gt;

    The ``file_format`` attribute gives the 'major' format number.
    It is ``"2"`` for all newer versions of Leo.

``&lt;globals&gt;``, ``&lt;preferences&gt;``, ``&lt;find_panel_settings&gt;`` and ``&lt;clone_windows&gt;``
    These elements are vestigial. |br|
    Modern versions of Leo ignore them when reading outlines and write
    empty elements when writing outlines.

``&lt;vnodes&gt;``
    A single ``&lt;vnodes&gt;`` element contains nested ``&lt;v&gt;`` elements.
    ``&lt;v&gt;`` elements correspond to vnodes.
    The nesting of ``&lt;v&gt;`` elements indicates outline structure in the obvious way.

``&lt;v&gt;``
    This element represents a single vnode and has the following form::

        &lt;v...&gt;&lt;vh&gt;sss&lt;/vh&gt; (zero or more nested v elements) &lt;/v&gt;

    The ``&lt;vh&gt;`` element specifies the headline text.
    sss is the headline text encoded with the usual XML escapes.
    As shown above, a ``&lt;v&gt;`` element may contain nested ``&lt;v&gt;`` elements.
    Zero or more of the following attributes may appear in &lt;v&gt; elements::

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

    The ``t="Tnnn"`` attribute specifies the &lt;t&gt; element associated with a &lt;v&gt; element.
    The ``a="xxx"`` attribute specifies vnode attributes.
    ``xxx`` denotes one or more upper-case letters whose meanings are as follows::

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

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

..  The tnode list existed from Leo 4.0 until Leo 4.7. Leo 4.7 removed the tnode list.

    -   Plugins and scripts may add attributes to &lt;v&gt; and &lt;t&gt; elements.
        See `Writing plugins`_ for details.

``&lt;tnodes&gt;``
    A single ``&lt;tnodes&gt;`` element contains a non-nested list of ``&lt;t&gt;`` elements.

``&lt;t&gt;``
    This element represents the body text of the corresponding &lt;v&gt; element.
    It has this form::

        &lt;t tx="&lt;gnx&gt;"&gt;sss&lt;/t&gt;

    The ``tx`` attribute is required.
    The ``t`` attribute of ``&lt;v&gt;`` elements refer to this ``tx`` attribute.
    ``sss`` is the body text encoded with the usual XML escapes.

    **New in 4.0**: Plugins and scripts may add attributes to ``&lt;v&gt;`` and ``&lt;t&gt;``
    elements. See `Writing plugins`_ for details.
</t>
<t tx="TL.20080804095315.1"></t>
<t tx="TL.20080804095315.2">###################
Using Vim with Leo
###################

This chapter discusses these topics:

- How to enable and use Leo's new vim-emulation mode.
- How to import and export vim's .otl files.
- How to install and use stand-alone vim-like bindings.

.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="TL.20080804095315.4">Place a copy of the "@keys Vim bindings" node and its sub-nodes, located in the leoSettings.leo file, under the "@settings" node in the myLeoSettings.leo file

The same procedure is performed to update to a new version.

Note: Place any local customized key bindings in a separate "@keys My Vi" node in the myLeoSettings.leo file to prevent them from being overwritten when updating to a new version.
</t>
<t tx="TL.20080804095315.5">The following commands are always available.

State change commands::

    i           Change state to insert from command state
    Esc         Change state to command from insert state
    Ctrl-[      Same as ESC

Save/Exit/Quite commands::

    :e          Revert
    :w&lt;return&gt;  Save '.leo' file
    :wq&lt;return&gt; Save '.leo' file and quit Leo
    :q&lt;return&gt;  Quit Leo   (Leo will prompt if file not saved)
    ZZ          Save leo file and exit

Undo/Redo commands::

    u           Undo previous command
    Ctrl-r      Redo previous command


Search options::

    Ctrl-/      Prompt for option to change
                Options:
                    a   Search all nodes (also &lt;cr&gt; key)
                    h   Toggle headline search
                    b   Toggle body search
                    m   Toggle marking of nodes (specify sub-option)
                        f   Toggle marking of nodes with found text
                        c   Toggle marking of nodes with changed text
                            (only supported with 'Alt-/', 'Alt-p')
                    r   Toggle regex matches
                        ('/' key turns off regex. 'n' key uses regex if turned on)

    Note: Whether a search is limited to node's body or the node's sub-outline
          is determined by which pane has focus when search text specified.
          (See "Find text commands:" sub-sections in Outline/Body Pane sections)

Miscellaneous commands::

    Tab         Toggle focus between Outline and Body pane
    =           Simulate double-click on current node's icon box
    Alt-G       Go to specified line number (relative to external file)
    Ctrl-:      Enter Leo's command line
</t>
<t tx="TL.20080804095315.6">Move cursor commands::

    h           Go back 1 character
       LtArrow  Mapped to "h" for convenience
    j           Go down 1 line
       DnArrow  Mapped to "j" for convenience
    k           Go up 1 line
       UpArrow  Mapped to "k" for convenience
    l           Go forward 1 character
       RtArrow  Mapped to "l" for convenience

    w           Go to beginning of next word
       W        Mapped to "w" until "stop after blank characters" supported
    b           Go to beginning of current/previous word
       B        Mapped to "b" until "stop at blank character" supported
    e           Go to end of current/next word
       E        Mapped to "e" until "stop at blank character" supported

    Note: Move by word commands stop at non-alpha characters

    |           Goto beginning of current line
    ^           Go to 1st non-blank character on current line
    $           Goto end of current line

    %           Go to matching bracket

    (           Go to beginning of current sentence
    )           Go to beginning of next sentence
    {           Go to beginning of current paragraph
    }           Go to beginning of next paragraph

    gg          Go to the first line (Cursor at column 1)
    G           Go to the last line  (Cursor at column 1)

Mark commands::

    m&lt;label&gt;    Assign cursor location to a single character label
    `&lt;label&gt;    Go to location associated with label

      Note: Only character count is tracked. Any inserts or deletes will change mark.
          Mark's are not node specific; `&lt;label&gt; will go to location in current node.

Select commands::

    Ctrl-v      Toggle text select mode (Vim's "visual" mode)
       V        Mapped to 'Ctrl-v' for convenience (Should toggle line select)

Insert/substitute commands::

    a           Insert at cursor
    i           Mapped to "a" until "cursor on a character" supported
    A           Insert at end of line
    I           Insert at first non-space
    o           Open new line below current line
    O           Open new line above current line
    R           Overwrite text
    s           Substitute character (Delete character, enter insert state)
    S           Substitute line (Delete line, enter insert state)

Change commands::

    C           Change to end of line
    cc          Change all of current line
    cw          Change to end of word
    cb          Change to beginning of word
    c)          Delete to end of sentence
    c(          Delete to beginning of sentence
    c}          Delete to end of paragraph
    c{          Delete to beginning of paragraph
    c%          Change from current bracket type its matching bracket type
    ct&lt;char&gt;    Selects forward to &lt;char&gt; (follow with 'i' to change selection)
    cT&lt;char&gt;    Selects backward to &lt;char&gt; (follow with 'i' to change selection)
    c&lt;cr&gt;       Change selected text

Delete commands::

    x           Delete next character
    delete      Delete next character
    D           Delete to the end of the current line
    dd          Delete current line
    dw          Delete to end of word
    db          Delete to beginning of word
    d)          Delete to end of sentence
    d(          Delete to beginning of sentence
    d}          Delete to end of paragraph
    d{          Delete to start of paragraph
    d%          Delete from current bracket type to its apposing bracket
    dt&lt;ch&gt;      Delete to character (not limited to current line)
    d&lt;cr&gt;       Delete selected text

    J           Join next line to end of current line (deletes carriage return)

Yank text commands::

    Y           Yank to end of line
    yy          Yank line
    yw          Yank to beginning of next word
    yb          Yank to beginning of current word
    y)          Yank to end of sentence
    y(          Yank to beginning of sentence
    y}          Yank to end of paragraph
    y{          Yank to beginning of paragraph
    y%          Yank from current bracket type to its opposing bracket
    yt&lt;char&gt;    Select forward to &lt;char&gt;  (use 'y&lt;cr&gt;' to yank selection)
    yT&lt;char&gt;    Select backward to &lt;char&gt; (use 'y&lt;cr&gt;' to yank selection)
    y&lt;cr&gt;       Yank selected text (Vim uses 'y' in visual mode)

Find character commands::

    f           Find next occurrence of user specified character
    F           Find previous occurrence of user specified character

Find text commands::

    /           Search forward within current node's body text
    ?           Search backward within current node's body text
    n           Find next (same scope, same direction)
    N           Find next (same scope, other direction)

    Note: See "Search options" in General Commands section to change options.

Replace [and find next] commands::

    Commands using Paste buffer (clipboard)
    P           Paste text before cursor.
    p           Mapped to "P" until character based cursor supported.
    Ctrl-p      Paste then find next match
                Note: Use 'pn' instead of 'Ctrl-p' in headlines (Leo limitation)
                      Command will continue to paste when match no longer found.

    Commands prompting for replace string
    Note: Scope and direction taken from last use of '/','?' or 'Ctrl-/'(scope only)
    Alt-/       Prompt for search &amp; replace string
    Alt-p       Replace then search (use after Alt-/)
                Note: Works in headlines and body panes.
                      Doesn't paste unless last search found a match.

Indent/Unindent line commands::

    &gt;&gt;          Indent the current line
    &gt;)          Indent to the end of sentence
    &gt;(          Indent to the beginning of sentence
    &gt;}          Indent to the end of paragraph
    &gt;{          Indent to the beginning of paragraph
    &gt;g          Indent to the start of buffer
    &gt;G          Indent to the end of buffer

    &lt;&gt;          Unindent the current line
    &lt;)          Unindent to the end of sentence
    &lt;(          Unindent to the beginning of sentence
    &lt;}          Unindent to the end of paragraph
    &lt;{          Unindent to the beginning of paragraph
    &lt;g          Unindent to the start of buffer
    &lt;G          Unindent to the end of buffer

Format commands::

    gqap        Split long line into separate lines
    gwap        Split long line into separate lines
    gqq         Split long line into separate lines
    gww         Split long line into separate lines

    Note: 'gwap' and 'gww' should not move cursor but do.

Scroll commands::

    Ctrl-b      Scroll text up by pane's height
    Ctrl-f      Scroll text down by pane's height
       Ctrl-y   Mapped to Ctrl-b until scroll up one line is supported
       Ctrl-e   Mapped to Ctrl-f until scroll down one line is supported
       Ctrl-u   Mapped to Ctrl-b until scroll up half a pane height is supported
       Ctrl-d   Mapped to Ctrl-f until scroll down half a pane height is supported

Window commands::

    Ctrl-w s    Open another view into current node's body (Vim: Split window)
       Ctrl-w n Mapped to "Ctrl-w s" (Vim: New buffer in split window)
    Ctrl-w w    Switch to next view (Vim: Go to up/left window w/wrapping)
       Ctrl-w p Mapped to "Ctrl-w w" (Vim: Cycle through windows)
       Ctrl-w k Mapped to "Ctrl-w w" (Vim: Go to window above current window)
       Ctrl-w j Mapped to "Ctrl-w w" (Vim: Go to window below current window)
    Ctrl-w c    Close current view in body pane (Vim: Close current window)
       Ctrl-w q Mapped to "Ctrl-w c" (Vim: Quit current window)

Node commands::

    Go to another node while focus remains in the body pane.
    Ctrl-j      Go to next visible node
    Ctrl-k      Go to previous visible node
    Ctrl-h      Hide sub-nodes or, if hidden, go up 1 level
    Ctrl-l      Display sub-nodes or, if displayed, go down 1 level
       Ctrl-DnArrow    Mapped to "Ctrl-j" for convenience
       Ctrl-UpArrow    Mapped to "Ctrl-k" for convenience
       Ctrl-LtArrow    Mapped to "Ctrl-h" for convenience
       Ctrl-RtArrow    Mapped to "Ctrl-l" for convenience
</t>
<t tx="TL.20080804095315.7">The following commands are supported when in a headline's command mode.

State change commands::

    Ctrl-i      Change state to command from grayed state
    return      Change state to command from insert state
    Ctrl-]      Change state to grayed from command state

Cursor movement commands::

    h           Go to previous character
       LtArrow  Mapped to 'h' for convenience
    l           Go to next character
       RtArrow  Mapped to "l" for convenience

    Note: 'j' and 'k' will scroll the buffer contents up and down;
          leaving the focus in the outline pane.

    w           Go to beginning of next word
       W        Mapped to "w" until "stop after blank characters" supported
    b           Go to beginning of current/previous word
       B        Mapped to "b" until "stop at blank character" supported
    e           Go to end of current/next word
       E        Mapped to "e" until "stop at blank character" supported

    Note: Move by word commands stop at non-alpha characters

    |           Go to beginning of line
    ^           Go to beginning of line
    $           Go to end of line

    %           Go to matching bracket

Edit commands::

    x           Delete next character
    delete      Delete next character
    dd          kill-line

    s           Select current character

    v           Toggle text select mode (issue cursor movement commands)
    y&lt;return&gt;   Yank selected text

    C           Select to end of line (follow with 'i' to change text)
    cc          Delete line (follow with 'i' to change text)

    D           Select to end of line (follow with 'x' to delete text)
    dd          Delete line

    Y           Select to end of line (follow with 'y&lt;return&gt;' to yank text)
    yy          Select line (follow with 'y&lt;return&gt;' to yank text)

Find character commands::

    f           Find next occurrence of user specified character
    F           Find previous occurrence of user specified character

Find text commands::

    /           Search forward within current node and its subnodes
    n           Find next (same scope, same direction)
    N           Find next (same scope, other direction)

    Note: See "Search options" section above to change options using 'Ctrl-/'

Replace [and find next] commands::

    Commands that use Paste buffer (clipboard)
    Note: Paste-then-search command not possible in headlines (Use 'pn')
    P           Paste text before cursor.
    p           Mapped to "P" until character based cursor supported.

    Commands that prompt for the replace string
    Alt-/       Prompt for search &amp; replace string
    Alt-p       Replace then search (use after Alt-/)
                Note: Works in headlines and body panes.
                      Doesn't paste unless last search found a match.

Node edit commands::

    o           Insert node after current node

    Ctrl-x      Delete current node
    Ctrl-c      Yank current node
    Ctrl-v      Paste current node

Node goto commands::

    G           Go to the outline's last node
    gg          Go to the outline's first node

    Ctrl-j      Go to next visible node
    Ctrl-k      Go to previous visible node
    Ctrl-h      Hide sub-nodes or, if hidden, go up 1 level
    Ctrl-l      Display sub-nodes or, if displayed, go down 1 level

       DnArrow  Mapped to "Ctrl-j" for convenience
       UpArrow  Mapped to "Ctrl-k" for convenience

       Ctrl-DnArrow Mapped to "Ctrl-j" for convenience
       Ctrl-UpArrow Mapped to "Ctrl-k" for convenience
       Ctrl-LtArrow Mapped to "Ctrl-h" for convenience
       Ctrl-RtArrow Mapped to "Ctrl-l" for convenience

Node move commands::

    Ctrl-Shift-k    Move node down
    Ctrl-Shift-h    Move node left
    Ctrl-Shift-l    Move node right
    Ctrl-Shift-j    Move node up

       Ctrl-Shift-DnArrow    Mapped to "Ctrl-Shift-k" for convenience
       Ctrl-Shift-LtArrow    Mapped to "Ctrl-Shift-h" for convenience
       Ctrl-Shift-RtArrow    Mapped to "Ctrl-Shift-l" for convenience
       Ctrl-Shift-UpArrow    Mapped to "Ctrl-Shift-j" for convenience

Node mark commands::

    m           Toggle node mark
    Ctrl-m      Go to next marked node
    Alt-m       Clear all marked nodes

Outline scroll commands::

   Ctrl-y       Scroll outline up one line
   Ctrl-e       scroll outline down one line
   Ctrl-u       Scroll outline up one half page
   Ctrl-d       scroll outline down one half page
   Ctrl-b       Scroll outline up one page
   Ctrl-f       scroll outline down one page

</t>
<t tx="TL.20080804095315.8">Notable missing editing commands::

    t&lt;char&gt;     Move cursor to character before specified character
    r           Replace a single character with a single character
    0           Go to 1st column in current line (Use '|' instead)
    bksp        Move one character to the left
    ~           Toggle character's case
    .           Repeat last editing command
    ;           Repeat last cursor movement command
    &lt;n&gt;&lt;cmd&gt;    Perform command 'n' number of times
    &lt;cmd&gt;&lt;n&gt;&lt;object&gt;    Perform the command on the n'th or up to the n'th object

Notable missing body pane commands::

    &lt;num&gt;G      Go to specified line number
    z&lt;movement&gt; Slide buffer to put current line at top/middle/bottom of pane
    '&lt;command&gt;  Go to line of last edit, jump, ...
    `&lt;command&gt;  Go to character of last edit, jump, ...
</t>
<t tx="TL.20080804095315.9">If you use the open-with command to open a node text in Vim and your Vim's "tag" file refers to external files then there is a risk that a external file that is initially displayed via the "tag" command" in Vim is accidentally edited and saved from the external Vim editor while your Leo session still contains the external file's original text that may later recreate the original external file during a Leo save operation (overwriting the changes saved from the Vim editor).

To prevent this problem, modifications to external files can be avoided by using Vim's "modeline" feature to disable editing of external files.

Vim's "modeline" feature scans each loaded buffer for text at the top or bottom of the file containing " vim:" followed by a series of Vim options. The text is usually embedded within a comment. The following example prevents modifications to a buffer in a Python file::

    # vim:noma (A space is required between the '#' and "vim:noma")

If this line is placed in a separate Leo node at the top or bottom of the list of nodes under a external file node (ex: @file) then any external file saved and then later loaded into Vim will, by default, not be modifiable. If a derived file does need to be edited then modifications can be re-enabled on a file-by-file basis by issuing Vim's ":ma" command while viewing the derived file.

The number of lines that Vim checks at the top and bottom of the buffer is configurable. The following Vim command must be placed in the vimrc file to allow for Leo's trailing sentinel lines::

    set modelines=8

Issue the ":help modeline" command within Vim for the more information about modelines.
</t>
<t tx="ekr.20031218072017.1416">def __init__(self):
    '''
    Ctor for LeoApp class. These ivars are Leo's global vars.

    leoGlobals.py contains global switches to be set by hand.
    '''
    &lt;&lt; LeoApp: command-line arguments &gt;&gt;
    &lt;&lt; LeoApp: Debugging &amp; statistics &gt;&gt;
    &lt;&lt; LeoApp: error messages &gt;&gt;
    &lt;&lt; LeoApp: global directories &gt;&gt;
    &lt;&lt; LeoApp: global data &gt;&gt;
    &lt;&lt; LeoApp: global controller/manager objects &gt;&gt;
    &lt;&lt; LeoApp: global status vars &gt;&gt;
    &lt;&lt; LeoApp: the global log &gt;&gt;
    &lt;&lt; LeoApp: global types &gt;&gt;
    &lt;&lt; LeoApp: plugins and event handlers &gt;&gt;
    &lt;&lt; LeoApp: scripting ivars &gt;&gt;
    &lt;&lt; LeoApp: unit testing ivars &gt;&gt;
    # Define all global data.
    self.init_at_auto_names()
    self.init_at_file_names()
    self.define_global_constants()
    self.define_language_delims_dict()
    self.define_language_extension_dict()
    self.define_extension_dict()
    self.define_delegate_language_dict()
</t>
<t tx="ekr.20031218072017.1417">def define_global_constants(self):
    # self.prolog_string = "&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;"
    self.prolog_prefix_string = "&lt;?xml version=\"1.0\" encoding="
    self.prolog_postfix_string = "?&gt;"
    self.prolog_namespace_string = 'xmlns:leo="http://edreamleo.org/namespaces/leo-python-editor/1.1"'
</t>
<t tx="ekr.20031218072017.1732">def finishQuit(self):
    # forceShutdown may already have fired the "end1" hook.
    trace = self.trace_shutdown and not g.unitTesting
    if trace: print('finishQuit')
    if not g.app.killed:
        g.doHook("end1")
    if g.app.ipk:
        g.app.ipk.cleanup_consoles()
    self.destroyAllOpenWithFiles()
    # if trace: print('app.finishQuit: setting g.app.killed: %s' % g.callers())
    g.app.killed = True
        # Disable all further hooks and events.
        # Alas, "idle" events can still be called
        # even after the following code.
    if g.app.gui:
        g.app.gui.destroySelf()
            # Calls qtApp.quit()
</t>
<t tx="ekr.20031218072017.1847">def setLog(self, log):
    """set the frame to which log messages will go"""
    # print("app.setLog: %s %s" % (log, g.callers()))
    # print("app.setLog: %s" % log)
    if not self.logIsLocked:
        self.log = log

def lockLog(self):
    """Disable changes to the log"""
    # print("app.lockLog:")
    self.logIsLocked = True

def unlockLog(self):
    """Enable changes to the log"""
    # print("app.unlockLog:")
    self.logIsLocked = False
</t>
<t tx="ekr.20031218072017.1938">def createNullGuiWithScript(self, script=None):
    app = self
    app.batchMode = True
    app.gui = g.app.nullGui
    app.gui.setScript(script)
</t>
<t tx="ekr.20031218072017.1978">def setLeoID(self, verbose=True):
    tag = ".leoID.txt"
    homeLeoDir = g.app.homeLeoDir
    globalConfigDir = g.app.globalConfigDir
    loadDir = g.app.loadDir
    verbose = not g.app.unitTesting
    &lt;&lt; return if we can set leoID from sys.leoID &gt;&gt;
    &lt;&lt; return if we can set leoID from "leoID.txt" &gt;&gt;
    &lt;&lt; return if we can set leoID from os.getenv('USER') &gt;&gt;
    &lt;&lt; put up a dialog requiring a valid id &gt;&gt;
    &lt;&lt; attempt to create leoID.txt &gt;&gt;
</t>
<t tx="ekr.20031218072017.1979"># This would be set by in Python's sitecustomize.py file.
# Use hasattr &amp; getattr to suppress pylint warning.
# Use a "non-constant" attribute to suppress another warning!
nonConstantAttr = "leoID"
if hasattr(sys, nonConstantAttr):
    g.app.leoID = getattr(sys, nonConstantAttr)
    if verbose and not g.app.silentMode and not g.app.unitTesting:
        g.red("leoID=", g.app.leoID, spaces=False)
    # Careful: periods in the id field of a gnx will corrupt the .leo file!
    g.app.leoID = g.app.leoID.replace('.', '-')
    return
else:
    g.app.leoID = None
</t>
<t tx="ekr.20031218072017.1980">for theDir in (homeLeoDir, globalConfigDir, loadDir):
    # N.B. We would use the _working_ directory if theDir is None!
    if theDir:
        try:
            fn = g.os_path_join(theDir, tag)
            f = open(fn, 'r')
            s = f.readline()
            f.close()
            if s and len(s) &gt; 0:
                g.app.leoID = s.strip()
                # Careful: periods in the id field of a gnx
                # will corrupt the .leo file!
                g.app.leoID = g.app.leoID.replace('.', '-')
                if verbose and not g.app.silentMode and not g.app.unitTesting:
                    g.red('leoID=', g.app.leoID, ' (in ', theDir, ')', spaces=False)
                return
            elif verbose and not g.app.unitTesting:
                g.red('empty ', tag, ' (in ', theDir, ')', spaces=False)
        except IOError:
            g.app.leoID = None
        except Exception:
            g.app.leoID = None
            g.error('unexpected exception in app.setLeoID')
            g.es_exception()
</t>
<t tx="ekr.20031218072017.1981"># 2011/06/13: Don't put up a splash screen.
# It would obscure the coming dialog.
g.app.use_splash_screen = False
# New in 4.1: get an id for gnx's.  Plugins may set g.app.leoID.
if g.app.gui is None:
    # Create the Qt gui if it exists.
    g.app.createDefaultGui(fileName='g.app.setLeoId', verbose=True)
if g.app.gui is None: # Neither gui could be created: this should never happen.
    g.es_debug("Please enter LeoID (e.g. your username, 'johndoe'...)")
    # pylint: disable=no-member
    f = builtins.input if g.isPython3 else builtins.raw_input
        # Suppress pyflakes complaint.
    leoid = f('LeoID: ')
else:
    leoid = g.app.gui.runAskLeoIDDialog()
# Bug fix: 2/6/05: put result in g.app.leoID.
g.app.leoID = leoid
# Careful: periods in the id field of a gnx will corrupt the .leo file!
g.app.leoID = g.app.leoID.replace('.', '-')
# g.trace(g.app.leoID)
g.blue('leoID=', repr(g.app.leoID), spaces=False)
</t>
<t tx="ekr.20031218072017.1982">for theDir in (homeLeoDir, globalConfigDir, loadDir):
    # N.B. We would use the _working_ directory if theDir is None!
    if theDir:
        try:
            fn = g.os_path_join(theDir, tag)
            f = open(fn, 'w')
            s = g.app.leoID
            if not g.isPython3: # 2010/08/27
                s = g.toEncodedString(s, encoding='utf-8', reportErrors=True)
            f.write(s)
            f.close()
            if g.os_path_exists(fn):
                g.error('', tag, 'created in', theDir)
                return
        except IOError:
            pass
        g.error('can not create', tag, 'in', theDir)
</t>
<t tx="ekr.20031218072017.2083">def updateRecentFiles(self, fileName):
    """Create the RecentFiles menu.  May be called with Null fileName."""
    rf = self
    if g.app.unitTesting: return

    def munge(name):
        return g.os_path_finalize(name or '').lower()

    def munge2(name):
        return g.os_path_finalize_join(g.app.loadDir, name or '')
    # Update the recent files list in all windows.

    if fileName:
        for frame in g.app.windowList:
            # Remove all versions of the file name.
            for name in rf.recentFiles:
                if (munge(fileName) == munge(name) or
                    munge2(fileName) == munge2(name)
                ):
                    rf.recentFiles.remove(name)
            rf.recentFiles.insert(0, fileName)
            # Recreate the Recent Files menu.
            rf.createRecentFilesMenuItems(frame.c)
    else:
        for frame in g.app.windowList:
            rf.createRecentFilesMenuItems(frame.c)
</t>
<t tx="ekr.20031218072017.2188">def newCommander(self, fileName, relativeFileName=None, gui=None, previousSettings=None):
    """Create a commander and its view frame for the Leo main window."""
    trace = (False or g.trace_startup) and not g.unitTesting
    if trace: g.es_debug(repr(fileName), repr(relativeFileName))
    # Create the commander and its subcommanders.
    # This takes about 3/4 sec when called by the leoBridge module.
    import leo.core.leoCommands as leoCommands
    return leoCommands.Commands(fileName, relativeFileName, gui, previousSettings)
</t>
<t tx="ekr.20031218072017.2608">@first # -*- coding: utf-8 -*-
&lt;&lt; imports &gt;&gt;
@others
@language python
@tabwidth -4
@pagewidth 70
</t>
<t tx="ekr.20031218072017.2609">def closeLeoWindow(self, frame, new_c=None, finish_quit=True):
    """
    Attempt to close a Leo window.

    Return False if the user veto's the close.

    finish_quit - usually True, close Leo when last file closes, but
                  False when closing an already-open-elsewhere file
                  during initial load, so UI remains for files
                  further along the command line.
    """
    trace = self.trace_shutdown and not g.unitTesting
    if trace: print('closeLeoWindow: %s' % frame.c.shortFileName())
    c = frame.c
    c.endEditing() # Commit any open edits.
    if c.promptingForClose:
        # There is already a dialog open asking what to do.
        return False
    g.app.recentFilesManager.writeRecentFilesFile(c)
        # Make sure .leoRecentFiles.txt is written.
    if c.changed:
        c.promptingForClose = True
        veto = frame.promptForSave()
        c.promptingForClose = False
        if veto: return False
    g.app.setLog(None) # no log until we reactive a window.
    g.doHook("close-frame", c=c)
        # This may remove frame from the window list.
    if frame in g.app.windowList:
        g.app.destroyWindow(frame)
        g.app.windowList.remove(frame)
    else:
        # Fix bug https://github.com/leo-editor/leo-editor/issues/69
        g.app.forgetOpenFile(fn=c.fileName(), force=True)
    if g.app.windowList:
        c2 = new_c or g.app.windowList[0].c
        g.app.selectLeoWindow(c2)
    elif finish_quit and not g.app.unitTesting:
        g.app.finishQuit()
    return True # The window has been closed.
</t>
<t tx="ekr.20031218072017.2612">def destroyAllOpenWithFiles(self):
    '''Remove temp files created with the Open With command.'''
    trace = self.trace_shutdown and not g.unitTesting
    if trace: print('destroyAllOpenWithFiles')
    if g.app.externalFilesController:
        g.app.externalFilesController.shut_down()
        g.app.externalFilesController = None
</t>
<t tx="ekr.20031218072017.2615">def destroyWindow(self, frame):
    '''Destroy all ivars in a Leo frame.'''
    trace = self.trace_shutdown and not g.unitTesting
    if trace: print('destroyWindow:  %s' % frame.c.shortFileName())
    if g.app.externalFilesController:
        g.app.externalFilesController.destroy_frame(frame)
    if frame in g.app.windowList:
        # print('destroyWindow', (g.app.windowList)
        g.app.forgetOpenFile(frame.c.fileName())
    # force the window to go away now.
    # Important: this also destroys all the objects of the commander.
    frame.destroySelf()
</t>
<t tx="ekr.20031218072017.2616">def forceShutdown(self):
    """
    Forces an immediate shutdown of Leo at any time.

    In particular, may be called from plugins during startup.
    """
    trace = self.trace_shutdown and not g.unitTesting
    if trace: print('forceShutdown')
    # Wait until everything is quiet before really quitting.
    if trace: print('forceShutdown: before end1')
    g.doHook("end1")
    if trace: print('forceShutdown: after end1')
    self.log = None # Disable writeWaitingLog
    self.killed = True # Disable all further hooks.
    for w in self.windowList[:]:
        if trace: print('forceShutdown: %s' % w)
        self.destroyWindow(w)
    if trace: print('before finishQuit')
    self.finishQuit()
</t>
<t tx="ekr.20031218072017.2617">@cmd('exit-leo')
def onQuit(self, event=None):
    '''Exit Leo, prompting to save unsaved outlines first.'''
    trace = self.trace_shutdown and not g.unitTesting
    if trace: print('onQuit: %s' % g.callers())
    g.app.quitting = True
    if g.app.save_session and g.app.sessionManager:
        g.app.sessionManager.save_snapshot()
    while g.app.windowList:
        w = g.app.windowList[0]
        if not g.app.closeLeoWindow(w):
            break
    if g.app.windowList:
        g.app.quitting = False # If we get here the quit has been disabled.
</t>
<t tx="ekr.20031218072017.2619">def writeWaitingLog(self, c):
    '''Write all waiting lines to the log.'''
    trace = False
    app = self
    if trace:
        # Do not call g.es, g.es_print, g.pr or g.trace here!
        print('***** writeWaitingLog: silent: %s c: %s' % (
            app.silentMode, c and c.shortFileName() or '&lt;no c&gt;'))
        # print('***** %s' % g.callers(8))
        # print('***** writeWaitingLog: %s' % ''.join(app.printWaiting))
        # import sys ; print('writeWaitingLog: argv',sys.argv)
    if not c or not c.exists:
        return
    if g.unitTesting:
        app.printWaiting = []
        app.logWaiting = []
        g.app.setLog(None) # Prepare to requeue for other commanders.
        return
    table = [
        ('Leo Log Window', 'red'),
        (app.signon, None),
        (app.signon1, None),
        (app.signon2, None)
    ]
    table.reverse()
    c.setLog()
    app.logInited = True # Prevent recursive call.
    if not app.signon_printed:
        app.signon_printed = True
        if not app.silentMode:
            print('')
            print('** isPython3: %s' % g.isPython3)
            if not g.enableDB:
                print('** caching disabled')
            print(app.signon)
            if app.signon1:
                print(app.signon1)
            print(app.signon2)
    if not app.silentMode:
        for s in app.printWaiting:
            print(s)
    app.printWaiting = []
    if not app.silentMode:
        for s, color in table:
            if s:
                app.logWaiting.insert(0, (s + '\n', color),)
        for s, color in app.logWaiting:
            g.es('', s, color=color, newline=0)
                # The caller must write the newlines.
        if hasattr(c.frame.log, 'scrollToEnd'):
            g.app.gui.runAtIdle(c.frame.log.scrollToEnd)
    app.logWaiting = []
    # Essential when opening multiple files...
    g.app.setLog(None)
</t>
<t tx="ekr.20040403171740">.. |---| unicode:: U+02015 .. for quotes
   :trim:

#############################
Writing Leo scripts in Python
#############################

This chapter tells how to write **Leo scripts**, Python scripts run from any Leo node. This chapter is intended for those fairly comfortable with Python scripting. If you are not, please study the excellent `Python Tutorial &lt;https://docs.python.org/2/tutorial/&gt;`_. Jacob Peck has written a more `informal scripting tutorial &lt;https://blog.suspended-chord.info/2014/01/28/intro-to-leo-scripting/&gt;`_.

Three predefined symbols, **c**, **g**, and **p** give Leo scripts easy access to all the data in the outline. These symbols also allow Leo scripts to execute any code in Leo's own codebase.

**Positions** and **vnodes** are the foundation of Leo scripting. leo/core/leoNodes.py defines the corresponding Position and VNode classes. These classes provide access to all outline data and allow Leo scripts to create and change outlines.

.. _`Leo's cheat sheet`: cheatsheet.html
.. _`scripting portion`: cheatsheet.html#scripting

**Further study**: The `scripting portion`_ of `Leo's cheat sheet`_ contains more information about scripting.

.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="ekr.20040403173920.18">You can invoke minibuffer commands by name.  For example:

.. code-block:: python

    c.executeMinibufferCommand('open-outline')
    # or
    c.doCommandByName('open-outline')

This will return the value returned from the command.

Commands created with @command and @button nodes can return values as well. Since top-level return statements aren't allowed in scripts executed with exec, you can define a global variable named **result**, and Leo will return its value:

.. code-block:: python

    global result
    result = 42
</t>
<t tx="ekr.20040403173920.19">Each commander sets ivars corresponding to settings.

Scripts can get the following ivars of the Commands class:

.. code-block:: python

    ivars = (
        'output_doc_flag',
        'page_width',
        'tab_width',
        'target_language',
        'use_header_flag',
    )
    print("Prefs ivars...\n",color="purple")
    for ivar in ivars:
        print(getattr(c,ivar))

If your script sets c.tab_width it should call f.setTabWidth to redraw the screen:

.. code-block:: python

    c.tab_width = -4    # Change this and see what happens.
    c.frame.setTabWidth(c.tab_width)
</t>
<t tx="ekr.20040403173920.24">On startup, Leo looks for two arguments of the form::

    --script scriptFile

If found, Leo enters batch mode. In batch mode Leo does not show any windows. Leo assumes the scriptFile contains a Python script and executes the contents of that file using Leo's Execute Script command. By default, Leo sends all output to the console window. Scripts in the scriptFile may disable or enable this output by calling app.log.disable or app.log.enable

Scripts in the scriptFile may execute any of Leo's commands except the Edit Body and Edit Headline commands. Those commands require interaction with the user. For example, the following batch script reads a Leo file and prints all the headlines in that file:

.. code-block:: python

    path = g.os_path_finalize_join(g.app.loadDir,'..','test','test.leo')
    assert g.os_path_exists(path),path

    g.app.log.disable() # disable reading messages while opening the file
    c2 = g.openWithFileName(path)
    g.app.log.enable() # re-enable the log.

    for p in c2.all_positions():
        g.es(g.toEncodedString(p.h,"utf-8"))
</t>
<t tx="ekr.20040414161647">@pagewidth 70
@tabwidth -4

These are the sources for Leo's users guide.

They contain restructured text markup for the sphinx tool. See::

    https://www.sphinx-doc.org
    https://docutils.sourceforge.net/rst.html
    https://docutils.sourceforge.net/docs/user/rst/quickstart.html

To generate these docs:

    `git checkout gh-pages`
    Click the `make-sphinx` button
    `git commit -m "log message"`
    `git push`
</t>
<t tx="ekr.20040414172218.4">
################
Acknowledgements
################

.. |br| raw:: html

   &lt;br /&gt;

</t>
<t tx="ekr.20041201080436">def appendToRecentFiles(self, files):
    rf = self
    files = [theFile.strip() for theFile in files]

    def munge(name):
        return g.os_path_normpath(name or '').lower()

    for name in files:
        # Remove all variants of name.
        for name2 in rf.recentFiles[:]:
            if munge(name) == munge(name2):
                rf.recentFiles.remove(name2)
        rf.recentFiles.append(name)
</t>
<t tx="ekr.20050306090601">.. index::
    pair:uA; Reference

Leo's .leo file format is extensible. The basis for extending .leo files are the v.unknownAttributes ivars of vnodes, also know as **user attributes**, uA's for short. Leo translates between uA's and xml attributes in the corresponding &lt;v&gt; elements in .leo files. Plugins may also use v.tempAttributes ivars to hold temporary information that will *not* be written to the .leo file. These two ivars are called **attribute ivars**.

Attribute ivars must be Python dictionaries, whose keys are names of plugins and whose values are *other* dictionaries, called **inner dictionaries**, for exclusive use of each plugin.

The v.u Python property allows plugins to get and set v.unknownAttributes easily:

.. code-block:: python

    d = v.u # gets uA (the outer dict) for v
    v.u = d # sets uA (the outer dict) for v

For example:

.. code-block:: python

    plugin_name = 'xyzzy'
    d = v.u # Get the outer dict.
    inner_d = d.get(plugin_name,{}) # Get the inner dict.
    inner_d ['duration']= 5
    inner_d ['notes'] "This is a note."
    d [plugin_name] = inner_d
    v.u = d

No corresponding Python properties exist for v.tempAttributes, so the corresponding example would be:

.. code-block:: python

    plugin_name = 'xyzzy'
    # Get the outer dict.
    if hasattr(p.v,'tempAttributes'): d = p.v.tempAttributes
    else: d = {}
    inner_d = d.get(plugin_name,{}) # Get the inner dict.
    inner_d ['duration'] = 5
    inner_d ['notes'] = "This is a note."
    d [plugin_name] = inner_d
    p.v.tempAttributes = d

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

**Note**: Leo does *not* pickle members of inner dictionaries whose name (key) starts with str\_. The values of such members should be a Python string. This convention allows strings to appear in .leo files in a more readable format.

Here is how Leo associates uA's with ``&lt;v&gt;`` elements in ``.leo`` files:

- **Native xml attributes** are the attributes of ``&lt;v&gt;`` elements that are known (treated specially) by Leo's read/write code. The native attributes of ``&lt;v&gt;`` elements are ``a``, ``t``, ``vtag``, ``tnodeList``, ``marks``, ``expanded``, and ``descendentTnodeUnknownAttributes``. All other attributes of ``&lt;v&gt;`` and ``&lt;t&gt;`` elements are **foreign xml attributes**.

- When reading a ``.leo`` file, Leo will create v.unknownAttributes ivars for any vnode whose corresponding ``&lt;v&gt;`` or ``&lt;t&gt;`` element contains a foreign xml attribute.

- When writing a ``.leo`` file, Leo will write foreign xml attributes in ``&lt;v&gt;`` elements if the corresponding vnode contains an unknownAttributes ivar.

- Leo performs the usual xml escapes on these strings when reading or writing the unknownAttributes ivars.
</t>
<t tx="ekr.20050407144342"></t>
<t tx="ekr.20050407144342.1"></t>
<t tx="ekr.20050407144342.2"></t>
<t tx="ekr.20050407144342.3"></t>
<t tx="ekr.20050407144417"></t>
<t tx="ekr.20050417072710.1">Plugins and scripts should call ``u.beforeX`` and ``u.afterX`` methods to describe the operation that is being performed. **Note**: u is shorthand for ``c.undoer``. Most ``u.beforeX`` methods return undoData that the client code merely passes to the corresponding u.afterX method. This data contains the 'before' snapshot. The ``u.afterX`` methods then create a bead containing both the 'before' and 'after' snapshots.

``u.beforeChangeGroup`` and ``u.afterChangeGroup`` allow multiple calls to ``u.beforeX`` and ``u.afterX`` methods to be treated as a single undoable entry. See the code for the Replace All, Sort, Promote and Demote commands for examples. The ``u.beforeChangeGroup`` and ``u.afterChangeGroup`` methods substantially reduce the number of ``u.beforeX`` and ``afterX`` methods needed.

Plugins and scripts may define their own ``u.beforeX`` and ``u.afterX`` methods. Indeed,        ``u.afterX`` merely needs to set the ``bunch.undoHelper`` and ``bunch.redoHelper`` ivars to the methods used to undo and redo the operation. See the code for the various ``u.beforeX`` and ``u.afterX`` methods for guidance.

See the section &lt;&lt; How Leo implements unlimited undo &gt;&gt; in ``leoUndo.py`` for more details. In general, the best way to see how to implement undo is to see how Leo's core calls the ``u.beforeX`` and ``afterX`` methods.
</t>
<t tx="ekr.20050424114937.2">def writeRecentFilesFile(self, c, force=False):
    '''
    Write the appropriate .leoRecentFiles.txt file.

    Write a message if force is True, or if it hasn't been written yet.

    '''
    tag = '.leoRecentFiles.txt'
    rf = self
    if g.app.unitTesting:
        return
    localFileName = c.fileName()
    if localFileName:
        localPath, junk = g.os_path_split(localFileName)
    else:
        localPath = None
    written = False
    seen = []
    for path in (localPath, g.app.globalConfigDir, g.app.homeLeoDir):
        if path:
            fileName = g.os_path_join(path, tag)
            if g.os_path_exists(fileName) and not fileName.lower() in seen:
                seen.append(fileName.lower())
                ok = rf.writeRecentFilesFileHelper(fileName)
                if force or not rf.recentFileMessageWritten:
                    if ok:
                        if not g.app.silentMode:
                            g.pr('wrote recent file: %s' % fileName)
                        written = True
                    else:
                        g.error('failed to write recent file: %s' % (fileName))
                # Bug fix: Leo 4.4.6: write *all* recent files.
    if written:
        rf.recentFileMessageWritten = True
    else:
        # Attempt to create .leoRecentFiles.txt in the user's home directory.
        if g.app.homeLeoDir:
            fileName = g.os_path_finalize_join(g.app.homeLeoDir, tag)
            if not g.os_path_exists(fileName):
                g.red('creating: %s' % (fileName))
            rf.writeRecentFilesFileHelper(fileName)
</t>
<t tx="ekr.20050424115658">def readRecentFilesFile(self, path):
    trace = False and not g.unitTesting
    rf = self
    fileName = g.os_path_join(path, '.leoRecentFiles.txt')
    ok = g.os_path_exists(fileName)
    if ok:
        try:
            if g.isPython3:
                f = open(fileName, encoding='utf-8', mode='r')
            else:
                f = open(fileName, 'r')
        except IOError:
            g.trace('can not open', fileName)
            return False
        if trace: g.trace(('reading %s' % fileName))
        lines = f.readlines()
        if lines and rf.sanitize(lines[0]) == 'readonly':
            lines = lines[1:]
        if lines:
            lines = [g.toUnicode(g.os_path_normpath(line)) for line in lines]
            rf.appendToRecentFiles(lines)
    return ok
</t>
<t tx="ekr.20050424131051">def writeRecentFilesFileHelper(self, fileName):
    # Don't update the file if it begins with read-only.
    trace = False and not g.unitTesting
    rf = self
    theFile = None
    try:
        theFile = open(fileName)
        lines = theFile.readlines()
        if lines and rf.sanitize(lines[0]) == 'readonly':
            if trace: g.trace('read-only: %s' % fileName)
            return False
    except IOError:
        # The user may have erased a file.  Not an error.
        pass
    finally:
        if theFile: theFile.close()
    theFile = None
    try:
        if g.isPython3:
            theFile = open(fileName, encoding='utf-8', mode='w')
        else:
            theFile = open(fileName, mode='w')
        if rf.recentFiles:
            s = '\n'.join(rf.recentFiles)
        else:
            s = '\n'
        if not g.isPython3:
            s = g.toEncodedString(s, reportErrors=True)
        theFile.write(s)
    except IOError:
        # The user may have erased a file.  Not an error.
        g.error('error writing', fileName)
        g.es_exception()
        theFile = None
    except Exception:
        g.error('unexpected exception writing', fileName)
        g.es_exception()
        theFile = None
        if g.unitTesting: raise
    finally:
        if theFile:
            theFile.close()
    return bool(theFile)
</t>
<t tx="ekr.20050812123002">.. Important: These options are for Sphinx.</t>
<t tx="ekr.20050812123002.5"></t>
<t tx="ekr.20050830074815.1">"I am using Leo since a few weeks and I brim over with enthusiasm for it. I think it is the most amazing software since the invention of the spreadsheet."---Anon.

"We who use Leo know that it is a breakthrough tool and a whole new way of writing code."---Joe Orr

"I am a huge fan of Leo. I think it's quite possibly the most revolutionary programming tool I have ever used and it (along with the Python language) has utterly changed my view of programming (indeed of writing) forever."---Shakeeb Alireza

"Thank you very much for Leo. I think my way of working with data will change forever... I am certain [Leo] will be a revolution. The revolution is as important as the change from sequential linear organization of a book into a web-like hyperlinked pages. The main concept that impress me is that the source listing isn't the main focus any more. You focus on the non-linear, hierarchical, collapsible outline of the source code."---Korakot Chaovavanich

"Leo is a quantum leap for me in terms of how many projects I can manage and how much information I can find and organize and store in a useful way."---Dan Winkler

"Wow, wow, and wow...I finally understand how to use clones and I realized that this is exactly how I want to organize my information. Multiple views on my data, fully interlinkable just like my thoughts."---Anon

"Edward... you've come up with perhaps the most powerful new concept in code manipulation since VI and Emacs."---David McNab

"Leo is...a revolutionary step in the right direction for programming."---Brian Takita

Leo makes managing long, complex code bases many many times more easy and feasible than anything else I've tried. Leo also makes trying experimental code way easier than anything else (e.g., running a script to test out some programming issue).  So hard to capture the flavor of all that!

"I use Leo every day, all the time, for non-programming things. I don't see how I could replace it if it somehow vanished."---Thomas Passin

</t>
<t tx="ekr.20050830074815.10">"I am extremely impressed at how stable and useful Leo appears to be."---Marcus
A. Martin

"Leo is amazingly stable. Docs are often weak with Open Source Software. Not so Leo: Leo is unusually well documented."---F. Geiger

"Leo is unimaginably useful and I always find new things it already knows(!) how to do. Indeed I am amazed by the never-ending resources and patience Edward is putting into it and its users community. Excellent."---Gil Shwartz

I feel strongly that Ed Ream, our ever-patient, ever-productive Leo architect deserves a nomination [for the ActiveState OpenSource Award.] Among other reasons, for:

- Delivering the first usable visual literate programming tool.
- Adding a vast abundance of new features.
- Making possible a previously unimaginable amount of leverage in code editing.
- Eliminating vast amounts of menial programming labour.
- Tirelessly and patiently supporting users, and catering to a wide range of feature requests.---David McNab
</t>
<t tx="ekr.20050830074815.11"></t>
<t tx="ekr.20050830074815.12">.. _`slashdot`: https://slashdot.org/comments.pl?sid=38848&amp;amp;cid=4171478

August 28, 2002, on `slashdot`_.

Hello, my full name is David Speed Ream. I am known as Speed to friends and enemies alike, but I gladly answer to David or most any other handle. I am an unabashed and biased fan of Leo, the fact that it was written by my brother Edward only slightly coloring my already colored glasses. I have been testing and using Leo in software production for over 4 years. My company currently has over 50,000 lines of code in over 100 source files that are written using Leo.

My comments are from two points of view, the first being software project manager for a complicated, multi-module software product, and the second being as a production line coder. For me, Leo’s greatest and only real drawback is the learning curve. This learning curve can be shallow if all that is required is that someone code using Leo. However, in our company we allocate 40 to 80 hours *on top* of the normal coding load for someone to come up to speed on Leo. The ROI (return on investment) is calculated by me to be on the order of 3 months. So if I hire a consultant for less than 3 months, I don’t teach him Leo, even though all source code in our company must reside in Leo files for the reasons I won’t go into now.

I consider that my coders are 15 to 30 percent more efficient in their daily operations than my competition’s people. This indefensible claim of mine is based on the changes in my productivity as Leo grew from a test document production tool to the primary production method for all our assembly, c and cpp source code.

Personally, I hate to deal with documentation when I write code, except:

1) When I am first sitting down to solve a new problem. Then the documentation becomes quite long-winded and pontificatory, as if I were the only one on earth smart enough to solve the problem - or

2) When I come back to code I or someone else has written and find the documentation insufficient to understand the code without study (seems to be most of the time).

So I do not require my engineers or myself to do a great job of documentation, nor do I use Leo for that purpose. Rather, it is Leo’s outlining and organizing ability, and Leo’s ability to create source files from within the outline that give me what I think is a tremendous competitive advantage. Each of my company’s products run on all versions of windows from Win 3.1 to XP. In our flagship software piece, there are ten main modules, and each module is maintained by one single Leo file. In the CODEC module, one Leo file named compress.leo organizes and creates seven .asm files, forty-four .c files, twenty .h files, two .def files, four .mak files, etc. etc. etc. This one file can be checked out from source code control and given to an engineer for the addition of a new feature.

In it are contained all the known issues for the CODEC, each issue arranged in its own clone section. One clone section groups together every routine, variable or type definition that must change between different versions of Windows. These sections could be from six different c source files, two assembly files, and eight .h files. Another clone section groups together those sections relating to memory problems, which change according to the memory configuration and TSR configuration (or lack thereof) on the target machine. Another clone section groups sections that fail (or don’t fail) if the routine in question was accidentally run during the dreaded ‘interrupt time’. Another clone section is a section containing clones, each of which is named after the major bug that was fixed when the engineer who fixed the bug grouped a bunch of routines, definitions, etc. together to fix the bug.

None of the above clone sections was ‘designed’ into the document. Just the opposite happens. When the codec was first written, there was just a single Leo file with a bunch of sections for each c routine or assembly module. As the product grew and was tested on various platforms, each failure of the module was organized into clones each time a failure was fixed. This is what I call “SELF DOCUMENTING CODE”. This has nothing to do with me sitting and documenting anything. Its just that the STRUCTURE of a bug fix (or product enhancement) lives on long after the coding is done, as long as no one is foolish enough to delete the cloned sections that ‘DOCUMENT’ what happened.

In actual practice, this organizational ‘history’ is so powerful that I can’t begin to describe it. A ‘REVERSE LEARNING CURVE’ happens when an engineer gets a Leo file that already has the ‘interrupt time sensitive’ routines grouped together by the last unfortunate soul who had to work on them. There may not be any more written documentation, but the knowledge contained in the structure can be breathtaking. It is certainly time saving. I find this particularly true in my own case. Often I’ll look at some code that seems totally unfamiliar and think ‘what idiot wrote this crap’. Then I’ll look at the version control comments and realize that I wrote the crap. Then for sure I know the documentation is non-existent, but the clones I used to develop it are still there, and they always serve to refresh my memory in an indescribable way.

Enough of this commentary, I just looked at the clock. Best wishes to anyone willing to try Leo for a week. I hope you will be glad you did.
</t>
<t tx="ekr.20050830074815.13">The Word outlines are very useful. But Leo makes Word look like a clunky toy.

#1 Reason would probably be clone nodes. One node can point to another. Another way of putting this is is that a leaf can be on more than one tree. For example, suppose you have a list of recipes. You simultaneously put a single recipe under multiple categories or even multiple hierarchies. You could put "3 bean enchilada" simultaneously under Recipes-Mexican and Food-Gas. Another example would be, if you are a biologist trying to decide under which genus to put a new species, you could put the species under two simultaneously. In effect, you can build a 3-D tree.


#2 Reason would probably be that Leo outlines can be embedded in external text files. So, a Leo outline is more than an outline, it is a meta-structure that can be added to another text without changing that text, but rather providing an external road map to the text. Microsoft Word has a text (xml) version with a commenting convention, so Leo can even be used to add outlines into Word docs, although it isn't set up to do that now.

I may not have made #2 very clear, but it is actually a very useful feature. It takes some getting used to before one sees all of the possibilities tho. One way to think of it is that Leo allows you to throw external documents into your outline, and yet the external document remains independent and can still be edited separately.

Some other cool things about Leo which Word doesn't feature:
1. Pure xml output that is easy to transform into other formats (next version of Word will have true XML format, but not as easy to work with). One consequence of this is that Leo files can be transformed pretty easily to web pages with their outlining capability intact.
2. Easy to add features since is programmed in Python and open source. Maybe your average user can't start hacking on it, but a surprising amount can be tacked on...
3. Free, opensource, multi-platform
4. Leo is scriptable with Python. It should be possible to build a Tickler into Leo using Python scripting, for example.
</t>
<t tx="ekr.20050830074815.14">First of all, kudos to you for the excellent progress you've been making with Leo. I upgraded today after about three months of using and older version and I was thrilled to see all the great improvements that have happened so fast. I especially love the ability to go to next clone. I think you're really showing what open source can do and your current trajectory puts you on track to kick Emacs into the dustbin of computing history.

So today I copied all my data (personal information manager and project management stuff) out of my old outliner (ThoughtManager, which syncs with and runs on the Palm) and put it into Leo. It took me hours to do it and then to rearrange it the way I really wanted it. But having the ability to make clones and have different ways to view my data is, as you know, fabulous. In my case, for personal information and project management things, I used the flexibility of clones to allow me to see my data in several different views: 1) by project, the logical hierarchical breakdown by topic, 2) by person, so whenever I'm talking to someone I can easily see all the pending items related to them which may be spread over multiple projects, 3) by priority, so I can see what needs to get done sooner and what can wait for later and, 4) a special case of priority called "Today" for the things I'm going to focus on in the coming hours.

Now here's why I don't miss the ability of my old outliner to sync the entire outline with the Palm. It turns out the main thing I really want in the Palm is the top category "Today" so all I have to do is have Leo flatten that one heading into a text file (and it kindly remembers the name and directory of the file I used last time) and then I'm done because I've told the Palm Hotsync manager that that file should be sent to Palm memo pad every time I sync. The Palm Hotsync manager does a nice job of sending a text file to the Palm memo pad and even breaks the file up into multiple memo records if it's too big to fit in just one. So that gives me enough to be able to browse (or full text search) the small amount of data that I really want right inside my Palm (which is also my cell phone). Quick and dirty but it works.

For times when I want my whole outline with me, Leo wins again because thanks to its cross platform nature I can take my whole outline with me on my Mac iBook, even though I usually edit it on a Windows PC (which is the only kind of machine my old outliner would run on). Quite frankly, although my old outliner was able to shoehorn the whole thing into my palm/cellphone, it was a pain to access it on the small screen and slow processor. Now when I anticipate I'll need the whole thing, for example when I'm going to a meeting, I can put it on my Mac iBook (under X and Fink for now until Python can do it native under Aqua) and have real, full access to it all.

I think now in addition to being great for programming Leo is also a great PIM. Being able to flatten a strategically chosen portion of the outline into a known file name that the Palm sync manager has been told to send to the Palm on every sync does the trick for me. I wonder if you would consider something like an @flatten directive so I can have that done automatically for me every time I save my outline? For now it's up to me to flatten the node I want manually, although once I've done that the transfer to the Palm is automatic.

You're my hero! Thank you so much.
</t>
<t tx="ekr.20050830074815.15">Another day, another breakthrough using Leo--now I realize Leo is the best URL bookmark manager there is.  No more bookmarks menus or favorites lists inside the browser for me.  With the @url directive I can just double click on the URL to open it in my browser.  Leo lets me arrange the URLs in a hierarchy (or multiple hierarchies), attach notes to them, save clippings of things I read on the sites.  It's sooo much better than anything the browsers have built in and it lets me easily use different browsers on different platforms and different machines (try that with the browsers' built-in bookmark managers).

When using Leo as a project manager and personal information manager as I do I can heavily annotate every task and project with helpful and relevant URLs.  And since URLs can be of the file:// form, they're not just for web pages or HTML documents;  I can link to any file on my disk of any type to be opened by any program.

Leo is a quantum leap for me in terms of how many projects I can manage and how much information I can find and organize and store in a useful way.  I'm a data-mining army of one now and the web is my playground. Every time I find a web page that has interesting links to others, those links get stored in my Leo outline too, right where I can find them and make practical use of them.  I can easily accept dozens of valuable links every day and integrate them into what I'm doing in a way that I'm confidant they won't get lost or forgotten.  Before I always used to get bogged down by the difficulty of managing bookmarks inside the browser.  But now I'm no longer the victim of information overload buried in the knowledge landslide of the Internet;  instead I'm the professional strip miner with the world's biggest bulldozer.  I eagerly plunge into mountains of data and emerge with all the valuable information nuggets neatly stored and organized.  And my storehouse of knowledge is a flexible thing where I can reorganize and prioritize and massage the data to my heart's content as I learn more about it and decide to use it in different ways for different purposes.  It's the difference between the pick axe and the steam shovel for me.
</t>
<t tx="ekr.20050830074815.16">This year my accountant is getting a beautiful printout generated by LaTeX and Leo. I have a complicated tax situation this year, but I got it all laid out and organized in Leo. Then I had each of the nodes that had something my accountant needs to see write the data out to a file in the form a LaTeX table.

Sometimes a row of a table would have a result that was calculated by adding up a list of numbers. For that I used the modern day equivalent of an adding machine paper tape--I stored a lisp s-expression in a Leo comment. I like s-expressions for this because once I put the opening "(+" on one line and the closing ")" on another line, I can fill in additional numbers just by typing them and can even annotate them with comments. So in the middle of generating a LaTeX file I might have something like this::

    @
    (+
    1165.26 1823.70 ; May 2002
    123.38 ; June 2002
    13.50 ; July 2002
    13.21 ; October 2002
    55.25 ; November 2002
    )
    @c

That's an annotated record of how I arrived at the number the accountant will actually see. I can just paste it into any lisp or scheme interpreter and get the total. Adding additional numbers is easy.

For next year, I think I might take this a step further. What I did this year is good for adding up numbers to get a total for one row of a LaTeX table. But it turns out I'd also like some more processing done on those tables (which I had to do by hand this time--I'd like the rows sorted in reverse order by magnitude (so that the big numbers jump out at you from the start of the tables) and I'd like a total of all the rows in the table. So I think next year, instead of having an s-expression that computes the total of one row for me, I think I'll use s-expressions that generate whole tables, formatted for LaTex, from the underlying data. So I'm thinking next year my s-expressions might look more like this::

    @
    (table "Widget Related Expenses"
        ("widget insurance" (+
                        1165.26 1823.70 ; May 2002
                        123.38 ; June 2002
                        13.50 ; July 2002
                        13.21 ; October 2002
                        55.25 ; November 2002
                      ))
         ("widget shipping" (+
                        472.15 651.94 ; May 2002
                        54 ; June 2002
                       ))
         ("widget cleaning" (+
                        165.26 183.70 ; May 2002
                        123.38 ; June 2002
                        13.50 ; July 2002
                        13.21 ; October 2002
                        55.25 ; November 2002
                       ))
    )
    @c

The job of that "table" function would be to return the LaTeX code needed to display a table with the category names and values, sorted descending by magnitude, with the total displayed. It's sort of a poor man's way of doing a spreadsheet inside Leo and then making it look great using LaTeX. The idea would be as I wanted to add more data, I'd add it to the s-expression and then reevaluate the whole thing by pasting it into a lisp interpreter and then copying the result back into the same Leo node for LaTeX to process.---Dan
</t>
<t tx="ekr.20050830074815.2">"Thanks for a wonderful program – everybody should be using it! It blows the socks off that Java Mind mapping software that won project of the month a while back on sourceforge!"---Derick van Niekerk.

"A few years back I would have said Zope was #1 Python showcase, but I agree 100% that Leo is tops now."---Jason Cunliffe

"Leo is the most interesting Python project I know of...I see lots of stuff posted on the Daily Python page, but I usually yawn and come over to this forum to see what's cooking."---Anon

"What an original synthesis of different ideas, why can't other Open Source projects change the way I think?"---Anon
</t>
<t tx="ekr.20050830074815.3">"When first I opened Leo, it was out of curiosity. But having used it...I'll never go back. They'll have to pry Leo out of my cold, dead fingers! Seriously, it should be renamed 'Crack Cocaine' because it's that addictive. I'm ready to start a 12-Step group."---Travers A. Hough

"I feel addicted to programming again...in fact [Leo] has resurrected a dead project of mine :) The Outline has proven most liberating in terms of testing ideas out."---Anon

"I have been absolutely seduced by Leo over the past few days. I tell you, I can not put it down. I feel like a kid with a shiny new bike...I'm already bursting with new ways I'd like to use the tool in the future."---Lyn Adams Headley

Thanks for the great work--I love Leo!!!---Josef Dalcolmo

Leo has simplified updating and creating new scripts and .bats keeping similar information in the same place. there is almost an addictive withdrawal effect when I can complete an operation in so much less time with Leo &amp; python than I had become used to.---Anon

Leo is my Favorites Mind Capsule ;-)

- she can contain all kinds of my Works (novel, code, slides, documents...)
- and she can magic record my chaos mind in same time and same place and NOT Disturb my working...
- luvin Leo, make me freedom with chaos mind and structuring work export!
- all my Slides is make with rst2s5
- write rst in Leo
- usage CLI tools generate html slides
- easy, geek, and freedom!--- 周琦 (Zoom.Quiet)
</t>
<t tx="ekr.20050830074815.4">"[Leo] should either replace or greatly augment the development tools that I use."---Zak Greant

"Leo is a marriage of outlining and programming. Pure genius. The main reason I am impressed with this tool is that it doesn't affect your choice of tools. You can use whatever IDE for whatever language and switch back and forth between Leo and it."---Austin King

"Leo is the best IDE that I have had the pleasure to use. I have been using it now for about 2--3 months. It has totally changed not only the way that I program, but also the way that I store and organize all of the information that I need for the job that I do."---Ian Mulvany

"I only have one week of Leo experience but I already know it will be my default IDE/project manager...people complain about the lack of a project manager for the free/standard Python IDE's like Idle. Leo clearly solves that problem and in a way that commercial tools can't touch."---Marshall Parsons

"I have been using Leo for about 3 weeks and I hardly use my other programming editor anymore...I find it easy and enjoyable to use. I plan to adopt it as my presentation tool for code reviews."---Jim Vickroy

"I'm absolutely astounded by the power of such a simple idea! It works great and I can immediately see the benefits of using Leo in place of the standard flat file editor."---Tom Lee

"I think you're really showing what open source can do and your current trajectory puts you on track to kick Emacs into the dustbin of computing history."---Dan Winkler
</t>
<t tx="ekr.20050830074815.5">"Word outlines are very useful. But Leo makes Word look like a clunky toy."---Joe Orr

"Leo is an interactive editor for organizing text fragments hierarchically and sequentially into one or more files and hierarchical folders, without arbitrary limits on the number and size of text fragments and the depth of the hierarchy..."---Alex Abacus

"Leo reminds me a great deal of things I loved when I used Userland's Frontier (an outlining cms with a native oodb) - but Frontier wasn't hackable enough for me, and it wasn't oriented towards coding..., and you couldn't round-trip rendered pages (big Leo win). This is really a super tool - in a matter of days I've started to use it on all my projects and I still haven't figured out how I lived without it."---John Sequeira

"Leo is EXACTLY the kind of outliner I was looking for--fantastic job!"---Steve Allen

"Leo creates living documents. Ideas can be organized and reorganized gradually and then inserted into the appropriate place in a project. Outlines become fluid, allowing infinite depth and by using clones of nodes, arbitrary levels of complexity...[Other] outliners impose structure on documents...Leo is different. Instead of imposing structure, it allows you to impose your own infrastructure, and then be as creative as you want. This brings the necessary chaos of creativity to heel when it is time to produce the document. The node structure creates ultimate flexibility when it comes to ordering scenes in chapter. Say good-bye to copy and paste and hello to drag and drop."---Chris George.
</t>
<t tx="ekr.20050830074815.6">"If you are like me, you have a kind of knowledge base with infos gathered over time. And you have projects, where you use some of those infos. Now, with conventional outliners you begin to double these infos, because you want to have the infos needed for the project with your project. With Leo you can do this too, but if you change text in one place IT IS UPDATED IN THE OTHER PLACE TOO! This is a feature I did not see with any other outliner (and I tried a few). Amazing! Leo directly supports the way I work!"---F. Geiger

"Another day, another breakthrough using Leo--now I realize Leo is the best URL bookmark manager there is. No more bookmarks menus or favorites lists inside the browser for me. With the @url directive I can just double click on the URL to open it in my browser. Leo lets me arrange the URLs in a hierarchy (or multiple hierarchies), attach notes to them, save clippings of things I read on the sites. It's sooo much better than anything the browsers have built in and it lets me easily use different browsers on different platforms and different machines (try that with the browsers' built-in bookmark managers)."---Dan Winkler

"I am an amateur photographer. I use plain old 35mm. film for my pictures. Over the weekend, I used Leo to organize my lists of pictures. It is quite helpful--I can have separate nodes for pictures I have enlarged, as well as pictures I have submitted to our local camera club. Thanks!"---Rich Reis

"Cloning is pure genius!... Leo's cloning facility, allows me to create several views on the CFA course material. My main view follows the prescribed study guide. Another view is organized like the textbooks. Yet another gives me a glossary of terms. And when I'm done, I'll have some nice libraries...I can re-use later in other projects."---Michael Manti

Despite I am no programmer, I have been using Leo for some years now as my "Intelligent PIM" - I organize my (complex) life with Leo. Many thanks to Edward and others for the great application -- vili &lt;viljem.tisnikar@gmail.com&gt;

I had used Leo for a long time as a PIM to track my work, but moved to emacs org mode for a period of time because of its explicit agenda and work tracking capabilities. But I went back to Leo because it seems more flexible when it comes to viewing various aspects of a project. For some recent performance data collection work, under one outline are the theory behind the project, the code (generation) for the project, the project web page (generated from an @rst node tree),  and project deployment (little more than clicking a button). One can change focus from one aspect to another very quickly and use clones to really drill down into an area (for me it's typically the code) when needed. Leo is an impressive tool, and I have only scratched the surface--Robert Shanley.

I am a manager, physicist and perhaps an electrical engineer. I use several different editors all the time, for different reasons, like vim and scite sometime  emacs. I use Leo on complex projects, involving many files. I have small python and Lua scripts, Lua tables, plain text files, many LaTeX files, CSV files, Markdown files, lots of PDF's for reference, spreadsheets, todo lists. I write documentation, write simple tools to help with business and scientific calculations. I do this all in a company with 20 people, working in small teams.

I use Leo as a project manager. It glues together all kind of stuff, allows me to do some jobs with a little script, and interfaces well with others. Some other tools may be better for some other things and I use other tools too, but I keep coming back to Leo for much of my work. Leo manages to be generic enough to co-exist well with other tools and bring all these different files together.--Josef Dalcomo.

For many years I have been looking for a program for working with information in the broadest sense of the word. Basically, these are the tasks of information analysis and transformation, literature reviews, writing texts and PIM. For a long time I have been using Mindmaps based solutions. For example, freeplane. However, I definitely lacked flexibility. Scripting those was painful!

When I found LEO it solved all my problems. Initially, I lacked the number of buttons on the icon bar, but I solved this problem [as] I previously wrote to the google group. Also I needed to have multiple icons when decluttering. Now everything is enough, I really like the flexibility of LEO. It's like an off-road car that you can modify on your own to suit your needs. I also really like the possibility of interleaved data and scripts to model my workflow.

Thank you very much for your work!.--Luka Golibrodo</t>
<t tx="ekr.20050830074815.8">"I've written documentation in WordPerfect, Ventura, Word, PageMaker, and FrameMaker and even though they create wonderfully looking and useful documents, they've never been able to do what I've been looking for. HTML, compiled help files, and later PDF came closer, but still not there...I think I've found it in Leo, a way to make a "living" document. A document built out of discrete parts that can be re-organized on the fly to meet the needs of a varying audience...I've already started converting the IT Procedures manual from Open Office to Leo because I know it's going to be much more useful to me and anyone else...just the possibility of keeping system maintenance scripts in the IT manual is mind boggling."---David Nichols

"With the help of the rst2 plugin, [Leo is] the best outliner I have yet encountered for writing the early stages of academic papers."

"A Leo file is an ideal documentation tool, collecting the assorted readme.txt files, the comments from the source files...as well as the config files themselves."---Kent Tenney
</t>
<t tx="ekr.20050830074815.9">"Just as structured programming reveals and disciplines the flow control of a program, [Leo] allows the designer to reveal and discipline structure at many layers simultaneously: data structures, object structure, entity-relationship structure, client-server structure, design pattern structure, temporal structure, project management structure, and any other structure relevant to the system."---Steven P. Schaefer

"A funny observation with Leo is that when I 'Leo-ise' other people's code, Leo makes the code's structure so transparent that design faults become very quickly apparent. For example, maintenance pain caused by lack of factorization."---David McNab

"Leo is a powerful tool for organizing text into tree structures, and for just generally attacking a number of problems from a tree-based perspective."---Joe Orr

"I found this blog entry by someone (a talented former coworker of mine actually) complaining about some poorly written code she had to maintain: https://snippy.ceejbot.com/wiki/show/start/2003/01/29/001 She said: 'You'd need a bulldozer to start refactoring it.' That was my cue to write a long message explaining that there is indeed such a bulldozer and it's called Leo. (You can see my message there as a reply to her original posting.) I gave her my recipe for how to get someone else's messy, scary code into Leo and how to break it down into manageable chunks."---Dan Winkler

"Ed, you continue to push the envelope. The amazing thing is that the footprint isn't doubling every few months like it would be in another designer's hands. Adding features by removing constraints, hot refactoring while adding unit tests. Forget the book. I would pay to see the movie."
</t>
<t tx="ekr.20050830115714">####
FAQ
####

This is Leo's Frequently Asked Questions document.

.. index:: FAQ

.. contents:: Contents
    :depth: 4
    :local:

</t>
<t tx="ekr.20050830115714.1"></t>
<t tx="ekr.20050830115714.10">The encoding used in the file being imported doesn't match the encoding in effect for Leo. Use the @encoding directive_ in an ancestor of the node_ selected when doing the Import command_ to specify the encoding of file to be imported.
</t>
<t tx="ekr.20050830115714.113">**Question**: It would be nice if Leo could open empty files. I tend to be "document oriented" rather than "application oriented" in my thinking and prefer "create empty file at location -&gt; open it with program" to "start program -&gt; create new file -&gt; save it at location".

**Answer** by Paul Paterson: If you are on Windows 98/2000/XP then the procedure is as follows...

1. Start Leo
2. Click New
3. Click Save as...
4. Save the file as "c:\\windows\\shellnew\\leofile.leo" (or c:\\winnt for 2000/XP)
5. Open regedit "start...run...regedit"
6. Open HKEY_CLASSES_ROOT and find the ".leo" extension type
7. Go New ... Key from the context menu 
8. Call the new key ShellNew 
9. Select the new key, right-click, choose New...String Value from the context menu
10. Call it FileName 
11. Double-click on the string, and modify it to be the filename of the leofile.leo file you created, including the extension
12. Exit the registry editor and restart Windows Explorer (you may need to reboot on Windows 98)

Now you should have a New:Leo File option in Explorer. This creates a duplicate of the file you saved. This can be useful because you could make a template Leo file containing some standard nodes_ that you always have and then save this.
</t>
<t tx="ekr.20050830115714.115">For the most part, docutils_ does a good job of reporting errors. docutils_ prints a message to the console and inserts an unmistakable error message in the generated .html file. **Important**: On Windows it is helpful to `run Leo in a console`_.

However, in some cases, docutils_ crashes instead of properly reporting the problem. There are several workarounds:

1.  The crashes I have seen arise from the following bug in docutils. **Hyperlinks in image:: markup must be lower case**.  This will work::

        .. .. |back| image:: arrow_lt.gif
            :target: faq_

    This will **crash**::

        .. .. |back| image:: arrow_lt.gif
            :target: FAQ_

    So avoid this crash by making sure to use lower case targets in ':target:' markup.

2.  You can change the docutils_ source slightly so that it prints a traceback when it crashes. (The rst3 plugin should be able to do this, but I haven't figured out how yet.) It's easy enough to do this:

- Find the file core.py in top-level docutils folder. Typically this folder will be in Python's site-packages folder.

- Open core.py in some editor other than Leo.

- Find the method called report_Exceptions.

- Insert the following lines at the very start of this method::

        print 'EKR: added traceback'
        import traceback ; traceback.print_exc()

This will cause a traceback whenever docutils_ crashes. I have found that such tracebacks are generally enough to locate the general area of the problem. **Note**: These tracebacks go to the console window, so you should `run Leo in a console`_.

3.  As a last resort, you can isolate syntax errors by reducing your input files until they work again, then adding sections until you get a crash. This is easy enough to do (when using the rst3 plugin) by change a headline 'x' to @rst-ignore-tree x.
</t>
<t tx="ekr.20050830115714.116">.. From: https://sourceforge.net/forum/message.php?msg_id=3240374

Using Leo's File-Export-Flatten Outline commands creates a MORE style outline which places all Leo body sections on the left margin. The headlines_ are indented with tabs which Excel will read as a tab delimited format. Once inside Excel there are benefits.

1. The most obvious benefit inside Excel is that the body sections (Excel first column) can be selected easily and highlighted with a different font color. This makes the MORE format very readable. Save a copy of your sheet as HTML and now you have a web page with the body sections highlighted.

2. It is possible to hide columns in Excel. Hiding the first column leaves just the headlines showing.

3. Formulas based on searching for a string can do calculations in Excel. For example if a heading "Current Assets" appears on level 4 then the body formula::

        =INDEX(A:A,MATCH("Current Assets",D:D,0)+1)

will retrieve it. The +1 after match looks down one row below the matched headline. The trick is to place all your headlines in quotes because Excel will see + "Current Assets" from the MORE outline. When Excel tries without the quotes it thinks it is a range name and displays a #N/A error instead of the headline. Also you must place a child node_ below to get the + sign instead of a - sign which would give a MORE headline of -"Current assets" , also is an error.

I think there is some interesting possibility here because of the enforcement of Leo body text being always in the first column. The Leo outline provides additional reference to organizing the problem not typical of spreadsheet models. Beyond scripting in Python, Excel is good at doing interrelated calculations and detecting problems like circular references. In Excel Tools-Options-General is a setting for r1c1 format which then shows numbers instead of letters for column references. Using this would allow entries like this in the leo body::

    1000
    3500
    =R[-1]C+R[-2]C

In Excel you would see 4500 below those two numbers. This is completely independent of where the block of three cells exists on the sheet.
</t>
<t tx="ekr.20050830115714.117">This syntax file hack works well enough to work with Leo '@' markup::

    syn region leoComment start="^@\\s*" end="^@c\\s*$"
    syn match   pythonDecorator	"@\\S\\S+" display nextgroup=pythonFunction skipwhite
</t>
<t tx="ekr.20050830115714.119">By Rich Ries. I often rework C code that's already been "Leo-ized"--the first pass was quick and dirty to get it going. When I do subsequent passes, I wind up with subnodes that are out of order with the sequence found in the main node_. It's not a big deal, but I like 'em ordered. With just one editor pane, clicking on the node_ to move would switch focus to that node_. I'd then need to re-focus on the main node_. A minor nuisance, but it does slow you down.

My solution is to open a second editor with its focus on the main node_. Switch to the other editor, and, referring to the first editor pane, move the nodes as you like. The second editor's pane will change focus to the node_ you're moving, but the first editor will stay focused on the main node_. It's a lot easier to do than to describe!
</t>
<t tx="ekr.20050830115714.12">.. _`reference .leo files`: FAQ.html#what-is-a-reference-leo-file

Use @clean or @auto unless everyone in your work group uses Leo.  In that case, using @file is best.  Use local copies of `reference .leo files`_ instead of the reference files themselves.
</t>
<t tx="ekr.20050830115714.120">One way is to link directly to the media file from a Leo node_ (with @url) and write a script button to wrap all URL-nodes under the current node_ in a single HTML page. Then, you can view your media in two ways:

- Individually. You can directly click on the @url link to display the media in the browser (assuming you have your MIME/filetype associations set up correctly for your browser).

- In a group. You can click on a script button (you have to code this yourself, very simple) which should collect all @url nodes_ under the current node_ and dynamically generate a HTML page displaying either links to or embedded versions of the media (using the HTML trick described above to invoke the browser). This way, you can create collections of @url nodes under a single node_ (like a bookmark folder), and press a single button to view the @url collection as a single entity in the browser (with all browser capabilities like displaying the media).

You could probably generalize this idea of "collect all @url nodes under current node_ and display as HTML in browser" into a general-purpose plugin. However, the plugin would have to be somewhat smart in mapping a link to its corresponding HTML code (e.g. an image link gets mapped to an &lt;img&gt; HTML tag, a link to a Flash file gets mapped to an &lt;embed&gt; tag, etc).
</t>
<t tx="ekr.20050830115714.13"></t>
<t tx="ekr.20050830115714.14">.. _`Mulder/Ream update algorithm`: appendices.html#the-mulder-ream-update-algorithm

Use @clean trees. Files derived from @clean trees contain no sentinels_. However, Leo can update @clean trees from changes made to the corresponding external file.  The `Mulder/Ream update algorithm`_ makes this magic happen.
</t>
<t tx="ekr.20050830115714.16">Use @asis trees. Files derived from @asis trees contain no sentinels. Leo creates the external file simply by writing all body text in outline order. Leo can't update the outline unless the external file contains sentinels, so Leo does not update @asis trees automatically when you change the external file in an external editor.
</t>
<t tx="ekr.20050830115714.17">The import commands insert @ignore directives_ in the top-level node_. Leo does this so that you won't accidentally overwrite your files after importing them. Change the filename following @file (or @file) as desired, then remove the @ignore directive_. Saving the outline will then create the external file.
</t>
<t tx="ekr.20050830115714.18">**Question**: I'm writing a Windows Script Component, which is an XML file with a CData section containing javascript. I can get the XML as I want it by using @language html, but how can I get the tangling comments inside the CData section to be java-style comments rather than html ones?

**Answer**: In @file trees you use the @delims directive to change comment delimiters. For example::

    @delims /* */ 
    Javascript stuff 
    @delims &lt;-- --&gt; 
    HTML stuff

**Important**: Leo can not revert to previous delimiters automatically; you must change back to previous delimiters using another @delims directive_.
</t>
<t tx="ekr.20050830115714.19">By Zvi Boshernitzan: I was having trouble disabling '&lt;?php' with comments (and couldn't override the comment character for the start of the page). Finally, I found a solution that worked, using php's heredoc string syntax::

    @first &lt;?php
    @first $comment = &lt;&lt;&lt;EOD
    EOD;

    // php code goes here.
    echo "boogie";

    $comment2 = &lt;&lt;&lt;EOD
    @last EOD;
    @last ?&gt;

or::

    @first &lt;?php
    @first /*
    */

    echo "hi";

    @delims /* */
    @last ?&gt;
</t>
<t tx="ekr.20050830115714.2">First, read `Leo's tutorials`_. This will be enough to get you started if you just want to use Leo as an outliner_. If you intend to use Leo for programming, read the `scripting tutorial`_, then look at Leo's source code in the file LeoPy.leo. Spend 5 or 10 minutes browsing through the outline. Don't worry about details; just look for the following common usage patterns:

- The (Projects) tree shows how to use clones to represent tasks.

- Study @file leoNodes.py. It shows how to define more than one class in single file.

- Most other files show how to use a single @others directive to define one class.

- Most methods are defined using @others, *not* section definition nodes.
</t>
<t tx="ekr.20050830115714.20">The @first directive_ is the key to output usable code in unsupported languages. For example, to use Leo with the Basic language, use the following::

    @first $IFDEF LEOHEADER
    @delims '
    @c
    $ENDIF

So this would enable a basic compiler to "jump" over the "true" Leo-header-lines. Like this::

    $IFDEF LEOHEADER &lt;-conditional compilation directive 
    #@+leo-ver=4 &lt;-these lines not compiled
    #@+node:@file QParser005.INC
    #@@first
    #@delims ' 
    '@@c
    $ENDIF &lt;-... Until here!
    &lt;rest of derived code file ... &gt;

This changes the comment symbol the apostrophe, making comments parseable by a BASIC (or other language.)
</t>
<t tx="ekr.20050830115714.21">Use the @first directive_ in @file or @clean trees. The @first directive puts lines at the very start of files derived from @file. For example, the body text of @file spam.py might be::

    @first #! /usr/bin/env python

The body text of @file foo.pl might be::

    @first #/usr/bin/perl

\@first directives must be the *very first* lines of @file nodes. More than one @first directive may exist, like this::

    @first #! /usr/bin/env python
    @first # more comments.
</t>
<t tx="ekr.20050830115714.24">No. Everything in an @file trees must be part of the external file: orphan and @ignore nodes are invalid in @file trees. This restriction should not be troublesome. For example, you can organize your outline like this::

    + myClass
    ..+ ignored stuff
    ..+ @file myClass

(As usual, + denotes a headline.) So you simply create a new node_, called myClass, that holds your @file trees and stuff you don't want in the @file trees.
</t>
<t tx="ekr.20050830115714.25">By Rich Ries. Some older C compilers don't understand the "//" comment symbol, so using @language C won't work. Moreover, the following does not always work either::

    @comment /* */

This generates the following sentinel line::

    /*@@comment /* */*/

in the output file, and not all C compilers allow nested comments, so the last \*\/ generates an error. The solution is to use::

    #if 0
    @comment /* */
    #endif

Leo is happy: it recognizes the @comment directive_. The C compiler is happy: the C preprocessor strips out the offending line before the C compiler gets it.
</t>
<t tx="ekr.20050830115714.26"></t>
<t tx="ekr.20050830115714.30">You have two options: 

- Get git write access, and add the @file file to the plugins directory.

- Just send the @file file to me at edreamleo@gmail.com.
</t>
<t tx="ekr.20050830115714.4">You will lose much of Leo's power if you don't use clones. See `Clones`_ and `Views`_ for full details.
</t>
<t tx="ekr.20050830115714.7">Use methods for any code that is used (called or referenced) more than once.

Sections_ are convenient in the following circumstances:

- When you want to refer to snippets of code the can not be turned into methods. For example, many plugins start with the code like this::

    &lt;&lt; docstring &gt;&gt;
    &lt;&lt; imports &gt;&gt;
    &lt;&lt; version history &gt;&gt;
    &lt;&lt; globals &gt;&gt;

    None of these sections could be replaced by methods.

- When you want to refer to a snippet of code that shares local variables with the enclosing code. This is surprisingly easy and safe to do, *provided* the section is used only in one place. `Section names`_ in such contexts can be clearer than method names.  For example::

    &lt;&lt; init ivars for writing &gt;&gt;

In short, I create sections when convenient, and convert them to functions or methods if they need to be used in several places.
</t>
<t tx="ekr.20050830115714.74">The Import Files dialog allows you to select multiple files provided you are running Python 2.3 or above. There is also an importFiles script in LeoPy.leo.  You can use that script as follows::

    import leo.core.leoImport as leoImport
    leoImport.importFiles(aDirectory, ".py")

This will import all .py files from aDirectory, which should be a full path to a particular directory. You could use ".c" to import all .c files, etc.
</t>
<t tx="ekr.20050830115714.76"></t>
<t tx="ekr.20050830115714.77">Just `run Leo in a console`_. At the point you want to drop into the debugger, execute this line::

    g.pdb()

All output from pdb goes to stdout, which is the console window. It would be good to create a subclass of pdb.Pdb that uses Leo's log pane rather than a console window, but I haven't done that. It could be done easily enough in a plugin...

**Important**: I recommend using g.trace instead of pdb.  For example::

    g.trace(x)

prints the name of the function or method containing the trace, and the value of
x. g.callers is often useful in combination with g.trace. g.callers(5)
returns the last 5 entries of the call stack. For example::

    g.trace(x,g.callers(5))

Used this way, g.trace shows you patterns that will be invisible using pdb.
</t>
<t tx="ekr.20050830115714.9">Internally, Leo represents all strings as unicode. Leo translates from a particular encoding to Unicode_ when reading .leo files or external files. Leo translates from Unicode_ to a particular encoding when writing external files. You may see strange looking characters if your text editor is expecting a different encoding. The encoding used in any external file is shown in the #@+leo sentinel line like this::

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

**Exception**: the encoding is UTF-8 if no -encoding= field exists. You can also use the @encoding directive_ to set the encoding for individual external files. If no @encoding directive_ is in effect, Leo uses the following settings_ to translate to and from unicode:

default_derived_file_encoding
    The encoding used for external files if no @encoding directive_ is in effect.
    This setting also controls the encoding of files that Leo writes.
    The default is UTF-8 (case not important).

new_leo_file_encoding
    The encoding specified in the following line of new .leo files::

        &lt;?xml version="1.0" encoding="UTF-8"&gt;

    The default is UTF-8 (upper case for compatibility for old versions of Leo).
</t>
<t tx="ekr.20050830120007">.. Links used in this document...

.. External links

.. _docutils:           https://docutils.sourceforge.net/
.. _`git repository`:   https://github.com/leo-editor/leo-editor
.. _unicode:            https://www.unicode.org/

.. Glossary
.. _directive:              glossary.html#directive
.. _directives:             glossary.html#directives
.. _`external file`:        glossary.html#external-file
.. _`external files`:       glossary.html#external-files
.. _headline:               glossary.html#headline
.. _headlines:              glossary.html#headlines
.. _node:                   glossary.html#node
.. _nodes:                  glossary.html#nodes
.. _outliner:               glossary.html#outliner
.. _sections:               glossary.html#sections
.. _`section name`:         glossary.html#section-name
.. _`section names`:        glossary.html#section-names
.. _sentinels:              glossary.html#sentinels
.. _`sentinel line`:        glossary.html#sentinel
.. _`sentinel lines`:       glossary.html#sentinel
.. _setting:                glossary.html#setting
.. _settings:               glossary.html#settings

.. FAQ
.. _`How to install Leo on Windows`:    installing.html#installing-leo-on-windows
.. _`run Leo in a console`:             running.html#running-leo-from-a-console-window

.. Tutorial
.. _`scripting tutorial`:   tutorial-scripting.html
.. _`Leo's tutorials`:      tutorial.html
.. _`Clones`:               tutorial-pim.html#clones
.. _`Views`:                tutorial-pim.html#views

.. Other local references
.. _command:                commands.html
.. _`History of Leo`:       appendices.html#history-of-leo
.. _`Leo 4.0: Eliminating error 'recovery'`: appendices.html#leo-4-0-eliminating-error-recovery

</t>
<t tx="ekr.20050830120844">c.frame.menu.createMenuItemsFromTable will append items to the end of an existing menu. For example, the following script will add a new item at the end of the 'File' menu::

    def callback(*args,**keys):
        g.trace()

    table = (("Test1",None,callback),)

    c.frame.menu.createMenuItemsFromTable('File',table)

Plugins can do anything with menus using c.frame.menu.getMenu. For example, here is a script that adds a Test menu item after the 'Open With' menu item in the File menu::

    def callback(*args,**keys):
        g.trace()

    fileMenu = c.frame.menu.getMenu('File')

# 3 is the position in the menu.  Other kinds of indices are possible::

    fileMenu.insert(3,'command',label='Test2',command=callback)
</t>
<t tx="ekr.20050831184021.4">.. |---| unicode:: U+02015 .. for quotes
   :trim:

################################
What People are Saying about Leo
################################

.. |br| raw:: html

   &lt;br /&gt;

.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="ekr.20050831184021.5"></t>
<t tx="ekr.20050831195331.1"></t>
<t tx="ekr.20050831195449">For instruction about installing Leo see:
https://leo-editor.github.io/leo-editor/installing.html

For everything a beginner needs to know about Leo see:
https://leo-editor.github.io/leo-editor/tutorial.html

For help, please ask questions at:
http://groups.google.com/group/leo-editor
</t>
<t tx="ekr.20050901084134">I wrote this soon after discovering Python in 2001. The conclusions are still valid today.

I've known for a while that Python was interesting; I attended a Python conference last year and added Python support to Leo. But last week I got that Python is something truly remarkable. I wanted to convert Leo from wxWindows to wxPython, so I began work on c2py, a Python script that would help convert from C++ syntax to Python. While doing so, I had an Aha experience. Python is more than an incremental improvement over Smalltalk or C++ or objective-C; it is "something completely different". The rest of this post tries to explain this difference.
</t>
<t tx="ekr.20050901092232.2">What struck me first as I converted C++ code to Python is how much less blah, blah, blah there is in Python. No braces, no stupid semicolons and most importantly, *no declarations*. No more pointless distinctions between const, char \*, char const \*, char \* and wxString. No more wondering whether a variable should be signed, unsigned, short or long.

Declarations add clutter, declarations are never obviously right and declarations don't prevent memory allocation tragedies. Declarations also hinder prototyping. In C++, if I change the type of something I must change all related declarations; this can be a huge and dangerous task. With Python, I can change the type of an object without changing the code at all! It's no accident that Leo's new log pane was created first in Python.

Functions returning tuples are a "minor" feature with a huge impact on code clarity. No more passing pointers to data, no more defining (and allocating and deallocating) temporary structs to hold multiple values.

.. _`pylint`: https://pylint.pycqa.org/en/latest/

Python can't check declarations because there aren't any. However, there is a really nifty tool called `pylint`_ that does many of the checks typically done by compilers.
</t>
<t tx="ekr.20050901092232.3">Python is much more powerful than C++, not because Python has more features, but because Python needs *less* features. Some examples:

- Python does everything that the C++ Standard Template Library (STL) does, without any of the blah, blah, blah needed by STL. No fuss, no muss, no code bloat.

- Python's slicing mechanism is very powerful and applies to any sequence (string, list or tuple). Python's string library does more with far less functions because slices replace many functions typically found in other string libraries.

- Writing dict = {} creates a dictionary (hash table). Hash tables can contain anything, including lists and other hash tables.

- Python's special functions,  __init__, __del__, __repr__, __cmp__, etc. are an elegant way to handle any special need that might arise.
</t>
<t tx="ekr.20050901092232.4">Before using Python I never fully realized how difficult and dangerous memory allocation is in C++. Try doing:

.. code-block::

    aList[i:j] = list(aString)

in C.  You will write about 20 lines of C code. Any error in this code will create a memory allocation crash or leak.

Python is fundamentally safe. C++ is fundamentally unsafe. When I am using Python I am free from worry and anxiety. When I am using C++ I must be constantly "on guard." A momentary lapse can create a hard-to-find pointer bug. With Python, almost nothing serious can ever go wrong, so I can work late at night, or after a beer. The Python debugger is always available. If an exception occurs, the debugger/interpreter tells me just what went wrong. I don't have to plan a debugging strategy! Finally, Python recovers from exceptions, so Leo can keep right on going even after a crash!
</t>
<t tx="ekr.20050901092232.5">Python has almost all the speed of C. Other interpretive environments such as icon and Smalltalk have clarity, power and safety similar to Python. What makes Python unique is its seamless way of making C code look like Python code. Python executes at essentially the speed of C code because most Python modules are written in C. The overhead in calling such modules is negligible. Moreover, if code is too slow, one can always create a C module to do the job.

In fact, Python encourages optimization by moving to higher levels of expression. For example, Leo's Open command reads an XML file. If this command is too slow I can use Python's XML parser module. This will speed up Leo while at the same time raising the level of the code.
</t>
<t tx="ekr.20050901092232.6">Little of Python is completely new. What stands out is the superb engineering judgment evident in Python's design. Python is extremely powerful, yet small, simple and elegant. Python allows me to express my intentions clearly and at the highest possible level.

The only hope of making Leo all it can be is to use the best possible tools. I believe Python will allow me to add, at long last, the new features that Leo should have.

Edward K. Ream, October 25, 2001.  P.S., September, 2005:

Four years of experience have only added to my admiration for Python. Leo could
not possibly be what it is today without Python.
</t>
<t tx="ekr.20050901101608.2">########################
Leo's Commands Reference
########################

This chapter lists almost all of Leo's commands. It starts with a discussion of the Emacs-like minibuffer.

.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="ekr.20050901101608.4">################
Customizing Leo
################

This chapter discusses how to customize Leo using the plugins and other means. See `Using settings`_ for a description of how to change Leo's settings.

.. contents:: Contents
    :depth: 2
    :local:
</t>
<t tx="ekr.20050902105852">Leo grew out of my efforts to use Donald Knuth's "CWEB system of Structured documentation." I had known of literate programming since the mid 1980's, but I never understood how to make it work for me. In November 1995 I started thinking about programming in earnest. Over the holidays I mused about making programs more understandable. </t>
<t tx="ekr.20050902105852.1">In January 1996 the fog of confusion suddenly cleared. I summarized my thinking with the phrase, **web are outlines in disguise**. I suspected that outline views were the key to programming, but many details remained obscure.

March 5, 1996, is the most important date in Leo's history. While returning from a day of skiing, I discussed my thoughts with Rebecca. During that conversation I realized that I could use the MORE outliner as a prototype for a "programming outliner." I immediately started work on my first outlined program. It quickly became apparent that outlines work: all my old problems with programming vanished. The @others directive dates from this day. I realized that MORE's outlines could form the basis for Leo's screen design. Rather than opening body text within the outline, as MORE does, I decided to use a separate body pane.

I hacked a translator called M2C which allowed me to use MORE to write real code. I would write code in MORE, copy the text to the clipboard in MORE format, then run M2C, which would convert the outline into C code. This process was useful, if clumsy. I called the language used in the outline SWEB, for simplified CWEB. Much later Leo started supporting the noweb language.
</t>
<t tx="ekr.20050902105852.10">Leo 4.1, February 20, 2004.

This release reorganized the code base to support gui's other than tkinter.

Leo first used gnx's (global node indices) as a foolproof way of associating nodes in .leo files with nodes in external files. At the time, there was still intense discussions about protecting the logical consistency of outlines. @thin was later to solve all those problems, but nobody knew that then.
</t>
<t tx="ekr.20050902105852.11">Leo 4.2, September 20, 2004.

This is one of the most significant dates in Leo's history. There were so many significant changes that it is hard to remember what Leo was like before it.

Leo 4.2 eliminated worries about consistency of outlines and external files: Leo recreates all essential information from @thin files, so *there is nothing left in the .leo file to get out of sync*. Thin external files use gnx's extensively. This simplifies the file format and makes thin external files more cvs friendly.

Leo 4.2 forms the **great divide** in Leo's internal data structures. Before 4.2, Leo every node in the outline had its own vnode. This was a big performance problem: clone operations had to traverse the entire outline!

4.2 represents clones by sharing subtrees. Kent Tenney and Bernhard Mulder made absolutely crucial contributions. Kent pointed out that it is a tnode, not a vnode that must form the root of the shared data. Bernhard showed that iterators avoid creating huge numbers of positions.


- Add ``@all``, ``@test`` and ``@suite``.
- Add ``mod_scripting`` plugin.
- Add new generators.</t>
<t tx="ekr.20050902105852.12">Leo 4.3 (May 23, 2005) and Leo 4.3.3 (September 17, 2005):

Leo 4.3 introduced settings files. These files replaced config.txt and made settings completely extensible and flexible. This release also introduced the ill-fated settings pane. It was soon retired because it inhibited development.

- Add the ``PluginsManager`` plugin. Thank you Paul Patterson!
- Predefine ``c``, ``g`` and ``p`` in scripts and ``@test`` nodes
- Add the ``rst3`` plugin.
</t>
<t tx="ekr.20050902105852.2">Throughout 1996 I created a version of Leo on the Macintosh in plain C and the native Mac Toolbox. This was a poor choice; I wasted a huge amount of time programming with these primitive tools. However, this effort convinced me that Leo was a great way to program.

Late in 1997 I wrote a Print command to typeset an outline. Printing (Weaving) is supposedly a key feature of literate programming. Imagine my surprise when I realized that such a "beautiful" program listing was almost unintelligible; all the structure inherent in the outline was lost! I saw clearly that typesetting, no matter how well done, is no substitute for explicit structure.

In 1998 I created a version of Leo using Apple's YellowBox environment. Alas, Apple broke its promises to Apple developers. I had to start again.
</t>
<t tx="ekr.20050902105852.3">In May of 1999 I began work on the Borland version of Leo for Windows. Borland C++ was much better than CodeWarrior C, but it was still C++. Still, the Borland Delphi classes were a pleasure to use and free of bugs. I redesigned Leo's file format for the Windows version of Leo; the Yellow Box file format was a binary format that requires the Yellow Box runtime.

There are two significant problems with the Borland version of Leo. First, it works only on Windows. Second, it can never be Open software, because it uses Borland's Delphi classes and a commercial syntax coloring component.

This version of Leo was the first version to use xml as the format of .leo files. Marc-Antoine Parent urged me to use XML and patiently explained how to use XML properly. </t>
<t tx="ekr.20050902105852.4">I attended the Python conference in early 2001. In May of 2000 I began work on a wxWindows version of Leo. The wxWindows project failed in a useful way. While adding python scripting, I became familiar with Python and its internals.

I started to 'get' Python in September 2001. In October of 2001 I began work on leo.py, based on Tk. The rewrite took only two months! leo.py 0.05 alpha went out the door on December 17, 2001.

I wrote the white papers around this time. Python solved *all* my programming problems. I was no longer anxious while programming; it simply isn't possible to create hard-to-find bugs in Python.</t>
<t tx="ekr.20050902105852.5">I registered the Leo project on SourceForge on March 10, 2003. Leo started a new life shortly thereafter. Prior to SourceForge my interest in Leo had been waning.
</t>
<t tx="ekr.20050902105852.6">In the summer of 2001 I began to consider using sentinel lines in external files. Previously I had thought that outline structure must be 'protected' by remaining inside .leo files. Accepting the possibility that sentinels might be corrupted opened vast new design possibilities. In retrospect, problems with sentinels almost never happen, but that wasn't obvious at the time! The result of this design was known then as Leo2. That terminology is extinct. I think of this version as the first version to support @file and automatic tangling and untangling.

</t>
<t tx="ekr.20050902105852.7">The biggest surprise in Leo's history was the realization it is **much** easier to untangle files derived from @file. Indeed, the old tangle code created all sorts of problems that just disappear when using @file. The new Python version of Leo became fully operational in early 2002. It was probably about this time that I chose noweb as Leo's preferred markup language. My decision not to support noweb's escape sequences made Leo's read code much more robust.
</t>
<t tx="ekr.20050902105852.8">I spent 2002 taking advantages of Python's tremendous power and safety. Many improvements were at last easy enough to do:

- Leo 3.2: Add nested ``@others`` directives.
- Leo 3.3: Add unicode support.
- Leo 3.7: Add ``@first`` and ``@last`` directives.
- Leo 3.8: Add ``@asis`` and ``@nosent`` directives.
- Leo 3.9: Add incremental syntax coloring and incremental undo.
</t>
<t tx="ekr.20050902105852.9">4.0 final: October 17, 2003.

In late 2002 and throughout 2003 I worked on an entirely new file format. 

Version 4.0 is a major advance in Leo's error handling. Using 4.0 is much safer than all previous versions. The new read code makes no changes to the outline until it is known that no read errors have occurred.

This was a time of intense design work trying to improve error recovery scheme used while reading external files. In the summer of 2003 I realized that orphan and @ignore'd nodes must be prohibited in @file trees. With this restriction, Leo could finally recreate @file trees in outlines using **only** the information in external files. This made the read code much more robust, and eliminated all the previous unworkable error recovery schemes. At last Leo was on a completely firm foundation.

Leo's read code now writes a message to the log pane whenever it sees that the body text in the external file does not match the body text in the outline. These messages do not indicate errors, only that the body text has been changed outside of Leo.

Leo's read code now warns if any non-empty node is unvisited. This check, and the check that headlines match pretty much guarantees that out-of-sync outlines will generate errors. Thus, there is no need a gnx timestamp in @+leo sentinels!

- Add support for uA's.
- Eliminate child indices, extraneous blank lines and @body sentinels.
- Eliminate @node sentinels.
- Add ``@nl`` and ``@nonl`` sentinels.
- Read errors leave the outline completely unchanged.
</t>
<t tx="ekr.20050903074833">Plugins and other scripts can register event handlers (also known as hooks):

.. code-block:: python

    leoPlugins.registerHandler("after-create-leo-frame",onCreate)
    leoPlugins.registerHandler("idle", on_idle) 
    leoPlugins.registerHandler(("start2","open2","command2"), create_open_with_menu) 

As shown above, a plugin may register one or more event handlers with a single call to leoPlugins.registerHandler. Once a hook is registered, Leo will call the registered function' at the named **hook time**. For example:

.. code-block:: python

    leoPlugins.registerHandler("idle", on_idle)

causes Leo to call on_idle at "idle" time.

Event handlers must have the following signature:

.. code-block:: python

    def myHook (tag, keywords):
        whatever

- tag is the name of the hook (a string).
- keywords is a Python dictionary containing additional information. The following section describes the contents of the keywords dictionary in detail.

**Important**: hooks should get the proper commander this way:

.. code-block:: python

    c = keywords.get('c')
</t>
<t tx="ekr.20050903074833.1">The following table tells about each event handler: its name, when it is called,
and the additional arguments passed to the hook in the keywords dictionary.
For some kind of hooks, Leo will skip its own normal processing if the hook
returns anything *other* than None. The table indicates such hooks with 'yes' in
the 'Stop?' column.

**Note**:

- The `v`, `old_v` and `new_v` keys below are *deprecated*. They contain *positions*, not vnodes.
- The `new_c` key is also *deprecated*. Use the `c` key instead.

@nowrap
.. No longer used events...
.. 'after-redraw-outline'                  end of tree.redraw       c (note 6)
.. 'redraw-entire-outline'         yes     start of tree.redraw     c (note 6)
.. 'scan-directives'                       in scanDirectives        c,p,v,s,old_dict,dict,pluginsList (note 10)

.. No longer used notes...
..   6.  These hooks are useful for testing.
..  10. g.scanDirectives calls 'scan-directives' hook.
..      g.scanDirectives returns a dictionary, say d.
..      d.get('pluginsList') is an a list of tuples (d,v,s,k) where:
..      - d is the spelling of the @directive, without the leading @.
..      - v is the vnode containing the directive, _not_ the original vnode.
..      - s[k:] is a string containing whatever follows the @directive.
..  k has already been moved past any whitespace that follows the @directive.
..  See the add_directives plugins directive for a complete example of how to use this hook.


============================== ======== =================================== =============================
Event name (tag argument)      Stop?    When called                         Keys in keywords dict
============================== ======== =================================== =============================
'after-auto'                            after each @auto file loaded        c,p (note 13)
'after-create-leo-frame'                after creating any frame            c
'after-edit'                            after each @edit file loaded        c
'after-reading-external-file'           after reading each external file    c,p
'after-reload-settings'                 after 'reload-settings' command     c
'before-create-leo-frame'               before frame.finishCreate           c
'before-writing-external-file'          before writing each external file   c,p
'bodyclick1'                    yes     before normal click in body         c,p,v,event
'bodyclick2'                            after normal click in body          c,p,v,event
'bodydclick1'                   yes     before double click in body         c,p,v,event
'bodydclick2'                           after  double click in body         c,p,v,event
'bodykey1'                      yes     before body keystrokes              c,p,v,ch,oldSel,undoType
'bodykey2'                              after  body keystrokes              c,p,v,ch,oldSel,undoType
'bodyrclick1'                   yes     before right click in body          c,p,v,event
'bodyrclick2'                           after  right click in body          c,p,v,event
'boxclick1'                     yes     before click in +- box              c,p,v,event
'boxclick2'                             after  click in +- box              c,p,v,event
'clear-all-marks'                       after clear-all-marks command       c,p,v
'clear-mark'                            when mark is set                    c,p,v
'close-frame'                           in app.closeLeoWindow               c (note 11)
'color-optional-markup'         yes *   (note 7)                            colorer,p,v,s,i,j,colortag (note 7)
'command1'                      yes     before each command                 c,p,v,label (note 2)
'command2'                              after  each command                 c,p,v,label (note 2)
'create-optional-menus'                 (note 8)                            c (note 8)
'create-node'                           after inserting a node              c,p
'create-popup-menu-items'               in tree.OnPopup                     c,p,v,event (new)
'draw-outline-box'              yes     when drawing +- box                 tree,p,v,x,y
'draw-outline-icon'             yes     when drawing icon                   tree,p,v,x,y
'draw-outline-node'             yes     when drawing node                   tree,p,v,x,y
'draw-outline-text-box'         yes     when drawing headline               tree,p,v,x,y
'drag1'                         yes     before start of drag                c,p,v,event
'drag2'                                 after  start of drag                c,p,v,event
'dragging1'                     yes     before continuing to drag           c,p,v,event
'dragging2'                             after  continuing to drag           c,p,v,event
'enable-popup-menu-items'               in tree.OnPopup                     c,p,v,event
'end1'                                  start of app.quit()                 None
'enddrag1'                      yes     before end of drag                  c,p,v,event
'enddrag2'                              after  end of drag                  c,p,v,event
'headclick1'                    yes     before normal click in headline     c,p,v,event
'headclick2'                            after  normal click in headline     c,p,v,event
'headrclick1'                   yes     before right click in headline      c,p,v,event
'headrclick2'                           after  right click in headline      c,p,v,event
'headkey1'                      yes     before headline keystrokes          c,p,v,ch (note 12)
'headkey2'                              after  headline keystrokes          c,p,v,ch (note 12)
'hoist-changed'                         whenever the hoist stack changes    c
'iconclick1'                    yes     before single click in icon box     c,p,v,event (note 15)
'iconclick2'                            after  single click in icon box     c,p,v,event (note 15)
'iconrclick1'                   yes     before right click in icon box      c,p,v,event (note 15)
'iconrclick2'                           after  right click in icon box      c,p,v,event (note 15)
'icondclick1'                   yes     before double click in icon box     c,p,v,event (note 15)
'icondclick2'                           after  double click in icon box     c,p,v,event (note 15)
'idle'                                  periodically (at idle time)         c
'init-color-markup'                     (note 7)                            colorer,p,v (note 7)
'menu1'                         yes     before creating menus               c,p,v (note 3)
'menu2'                         yes     during creating menus               c,p,v (note 3)
'menu-update'                   yes     before updating menus               c,p,v
'new'                                   start of New command                c,old_c,new_c (note 9)
'open1'                                 before opening any file             c,old_c,new_c,fileName (note 4)
'open2'                                 after  opening any file             c,old_c,new_c,fileName (note 4)
'openwith1'                     yes     before Open With command            c,p,v,d (note 14)
'openwith2'                             after  Open With command            c,p,v,(note 14)
'recentfiles1'                  yes     before Recent Files command         c,p,v,fileName
'recentfiles2'                          after  Recent Files command         c,p,v,fileName
'save1'                         yes     before any Save command             c,p,v,fileName
'save2'                                 after  any Save command             c,p,v,fileName
'select1'                       yes     before selecting a position         c,new_p,old_p,new_v,old_v
'select2'                               after  selecting a position         c,new_p,old_p,new_v,old_v
'select3'                               after  selecting a position         c,new_p,old_p,new_v,old_v
'set-mark'                              when a mark is set                  c,p,v
'show-popup-menu'                       in tree.OnPopup                     c,p,v,event
'start1'                                after app.finishCreate()            None
'start2'                                after opening first Leo window      c,p,v,fileName
'unselect1'                     yes     before unselecting a vnode          c,new_p,old_p,new_v,old_v
'unselect2'                             after  unselecting a vnode          c,new_p,old_p,new_v, old_v
'\@url1'                        yes     before double-click @url node       c,p,v,url (note 5)
'\@url2'                                after  double-click @url node       c,p,v(note 5)
============================== ======== =================================== =============================

**Notes**:

1.  'activate' and 'deactivate' hooks have been removed because they do not work as expected.

2.  'commands' hooks: The label entry in the keywords dict contains the
    'canonicalized' form of the command, that is, the lowercase name of the command
    with all non-alphabetic characters removed.
    Commands hooks now set the label for undo and redo commands 'undo' and 'redo'
    rather than 'cantundo' and 'cantredo'.

3.  'menu1' hook: Setting g.app.realMenuNameDict in this hook is an easy way of
    translating menu names to other languages. **Note**: the 'new' names created this
    way affect only the actual spelling of the menu items, they do *not* affect how
    you specify shortcuts settings, nor do they affect the 'official'
    command names passed in g.app.commandName. For example::

        app().realMenuNameDict['Open...'] = 'Ouvre'.

4.  'open1' and 'open2' hooks: These are called with a keywords dict containing the following entries:

    - c:          The commander of the newly opened window.
    - old_c:      The commander of the previously open window.
    - new_c:      (deprecated: use 'c' instead) The commander of the newly opened window.
    - fileName:   The name of the file being opened.

    You can use old_c.p and c.p to get the current position in the old and new windows.
    Leo calls the 'open1' and 'open2' hooks only if the file is not already open. Leo
    will also call the 'open1' and 'open2' hooks if: a) a file is opened using the
    Recent Files menu and b) the file is not already open.

5.  '@url1' and '@url2' hooks are only executed if the 'icondclick1' hook returns None.

6.  Obsolete note.

7.  These hooks allow plugins to parse and handle markup within doc parts,
    comments and Python ''' strings. Note that these hooks are *not* called in
    Python ''' strings. See the color_markup plugin for a complete example of how to
    use these hooks.

8.  Leo calls the 'create-optional-menus' hook when creating menus. This hook need
    only create new menus in the correct order, without worrying about the placement
    of the menus in the menu bar. See the plugins_menu and scripts_menu plugins for
    examples of how to use this hook.

9.  The New command calls 'new'.
    The 'new_c' key is deprecated.  Use the 'c' key instead.

10. Obsolete note.

11. g.app.closeLeoWindow calls the 'close-frame' hook just before
    removing the window from g.app.windowList. The hook code may remove the window
    from app.windowList to prevent g.app.closeLeoWindow from destroying the window.

12. New in Leo 6.4: Leo calls the 'headkey1' and 'headkey2' when the headline has *actually* changed.

13. p is the new node (position) containing '@auto filename.ext'

14. The d argument to the open-with event handlers is a python
    dictionary whose keys are all the tags specified by the user in the body of the
    @openwith node.

The following events can *only* be called be called by minibuffer commands:

========================== ======== =====================
Event name (tag argument)  Stop?    Keys in keywords dict
========================== ======== =====================
'iconclick1'               yes      c,p,v,event (note 15)
'iconrclick1'              yes      c,p,v,event (note 15)
'iconrclick2'                       c,p,v,event (note 15)
'icondclick1'              yes      c,p,v,event (note 15)
'icondclick2'                       c,p,v,event (note 15)
========================== ======== =====================

15. The only way to trigger these event is with the following minibuffer commands::

                click-icon-box
                ctrl-click-icon
                double-click-headline
        Ctrl+F3 double-click-icon-box
                right-click-headline
                right-click-icon

16. The following links are supported by plugins, not Leo itself:

============================== ======== =================================== ===========
'hypercclick1'                  yes     before control click in hyperlink   c,p,v,event
'hypercclick2'                          after  control click in hyperlink   c,p,v,event
'hyperenter1'                   yes     before entering hyperlink           c,p,v,event
'hyperenter2'                           after  entering hyperlink           c,p,v,event
'hyperleave1'                   yes     before leaving  hyperlink           c,p,v,event
'hyperleave2'                           after  leaving  hyperlink           c,p,v,event
============================== ======== =================================== ===========</t>
<t tx="ekr.20050906090012">Leo (and other programs) often send more detailed error messages to stderr, the output stream that goes to the console window. In Linux and MacOS environments, python programs normally execute with the console window visible. On Windows, can run Leo with the console window visible by associating .leo files with python.exe *not* pythonw.exe.
</t>
<t tx="ekr.20050907094633">Settings may be different for each commander.

The c.config class has the following getters::

    c.config.getBool(settingName,default=None)
    c.config.getColor(settingName)
    c.config.getDirectory(settingName)
    c.config.getFloat(settingName)
    c.config.getInt(settingName)
    c.config.getLanguage(settingName)
    c.config.getRatio(settingName)
    c.config.getShortcut(settingName)
    c.config.getString(settingName)

These methods return None if no setting exists.

The getBool 'default' argument to getBool specifies the value to be returned if the setting does not exist.
</t>
<t tx="ekr.20050912125144.1">#######
Plugins
#######

This chapter discusses Leo's plugins. The plugins found in LeoPyRef.leo are part of Leo's official distribution. The next chapter, `Writing Plugins &lt;writingPlugins.html&gt;`_, tells how to write plugins.

The scripting plugin (mod_scripting.py) deserves special mention. This plugin lets you create **script buttons** in a matter of seconds. See `Using @button nodes &lt;tutorial-scripting#using-button-nodes&gt;`_. Script buttons are extraordinarily useful.

.. contents:: Contents
    :depth: 5
    :local:

</t>
<t tx="ekr.20050912125735.363">The dyna_menu plugin is a remarkable body of work by 'e'. This plugin creates a dyna_menu menu from which you can execute commands. You may download the latest version at: https://rclick.netfirms.com/dyna_menu.py.html
</t>
<t tx="ekr.20051202072010"></t>
<t tx="ekr.20060105214753">Leo now allows you to specify input modes. You enter mode x with the ``enter-x-mode`` command. The purpose of a mode is to create different bindings for keys within a mode. Often plain keys are useful in input modes.

You can specify modes with ``@mode`` nodes in ``leoSettings.leo``. ``@mode`` nodes work just like ``@shortcuts`` nodes, but in addition they have the side effect of creating the ``enter-&lt;mode name&gt;-mode`` command.

Notes:

- You can exit any mode using the ``keyboard-quit`` (``Control-g``) command. This is the **only** binding that is automatically created in each mode. All other bindings must be specified in the ``@mode`` node. In particular, the bindings specified in ``@shortcuts`` nodes are **not** in effect in mode (again, except for the ``keyboard-quit`` binding).

- Leo supports something akin to tab completion within modes: if you type a key that isn't bound in a mode a 'Mode' tab will appear in the log pane. This tab shows all the keys that you can type and the commands to which they are bound. The ``mode-help`` command does the same thing.

- ``@shortcuts`` nodes specify the bindings for what might be called the 'top-level' mode. These are the bindings in effect when no internal state is present, for example, just after executing the ``keyboard-quit`` command.

- The top_level_unbound_key_action setting determines what happens to unbound keys in the top-level mode. Leo ignores unbound keys in all other modes. The possibilities are 'insert', 'replace' and 'ignore'.

- The ``set-insert-mode``, ``set-overwrite-mode`` and ``set-ignore-mode`` commands alter what happens to unbound keys in the top-level mode.

- If the ``@mode`` headline contains ``::``, everything following the ``::`` is the mode prompt. For example::

    @mode abc :: xyz

Creates the ``enter-abc-mode`` command, but the prompt for the command is ``xyz``.

With all these options it should be possible to emulate the keyboard behavior of any other editor.
</t>
<t tx="ekr.20060111192108">A **dangerous** delete is a deletion of a node so that all the data in the node is deleted *everywhere* in an outline. The data is gone, to be retrieved only via undo or via backups. It may not be obvious which deletes are dangerous in an outline containing clones. Happily, there is a very simple rule of thumb::

    Deleting a non-cloned node is *always* dangerous.
    Deleting a cloned node is *never* dangerous.

We could also consider a delete to be dangerous **if it results in a node being omitted from an external file.** This can happen as follows. Suppose we have the following outline (As usual, A' indicates that A is marked with a clone mark)::

    - @file spam.py
        - A'
            - B
    - Projects
        - A'
            - B

Now suppose we clone B, and move the clone so the tree looks like this::

    - @file spam.py
        - A'
            - B'
    - Projects
        - A'
            - B'
        - B'

If (maybe much later), we eliminate B' as a child of A will get::

    - @file spam.py
        - A'
    - Projects
        - A'
        - B

B has not been destroyed, but B is gone from @file spam.py! So in this sense deleting a clone node can also be called dangerous.
</t>
<t tx="ekr.20060211140947.1">try:
    theId = os.getenv('USER')
    if theId:
        if verbose and not g.app.unitTesting:
            g.blue("setting leoID from os.getenv('USER'):",
                repr(theId))
        g.app.leoID = theId
        # Careful: periods in the id field of a gnx
        # will corrupt the .leo file!
        g.app.leoID = g.app.leoID.replace('.', '-')
        return
except Exception:
    pass
</t>
<t tx="ekr.20060329101442">Missing modules can cause installation problems. If the installer doesn't work (or puts up a dialog containing no text), you may install Leo from the .zip file as described at `How to install Leo on Windows`_. However you are installing Leo, be sure to `run Leo in a console`_. because as a last resort Leo prints error messages to the console.
</t>
<t tx="ekr.20060430220749">.. _jEdit: https://www.jedit.org/

The `jEdit`_ editor drives its syntax colorer using ``.xml`` files. Leo uses ``.py`` files instead.

Long ago, Leo's ``jEdit2Py`` script created the python **mode files** in the ``leo/modes`` directory.

Roughly speaking, there is one mode file for every language that Leo can colorize. Over the years, Leo's devs have modified several of these mode files by hand.

``init`` sets ``jedit.rulesDict`` from the mode file for the language in effect. Keys are **lead-in characters**; values are lists of **rule functions** (**rules** for short). Each mode file defines its own rulesDict and rules.

``mainLoop(s)`` uses the rulesDict to retrieve a list of zero or more rules to be used when scanning s. It's that simple.

Legacy mode files could collaborate using the ``delegate`` keyword, but that scheme was (and is) clumsy.

Leo 6.8.3 added ``leo/modes/jupytext.py``, a new mode file for ``@language jupytext``. This mode file introduced a new style of collaboration. The mode files for the jupytext, python and markdown languages collaborate *directly* using modifications of *existing* rules in ``python.py`` and ``md.py``.
</t>
<t tx="ekr.20060527105211"></t>
<t tx="ekr.20060527105617">##################
Debugging with Leo
##################

This chapter discusses debugging Python scripts with Leo.
Be aware of the distinction between **Leo-specific** scripts and **general** scripts.
Leo-specific scripts access data in the Leo outline in which they are contained;
general scripts do not.

.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="ekr.20060527112801">The following settings in leoSettings.leo control debugger operation. The settings shown here will be assumed to be in effect throughout this chapter::

    @string debugger_kind = winpdb

This setting controls what debugger the 'Debug Script' script button uses. Eventually this setting will control what debugger the debug command uses. At present the only valid value is 'winpdb'::

    @bool write_script_file = True

True: The execute script command writes the script to be executed to a file, then executes the script using Python's execFile function. The script_file_path setting specifies the path to this file. False (legacy): The execute script command uses Python's exec command to execute the script.

::

    @string script_file_path = ../test/scriptFile.py

The path to the file to be written by the execute-script command. Notes:

- This setting has effect only if the write_script_file setting is True.
- Use / as the path delimiter, regardless of platform.
- The default path is ../test/scriptFile.py if no path is given.
- The path starts at g.app.loadDir, so for example ../test/scriptFile.py is equivalent to leo/test/scriptFile.py.
- The filename should end in .py.

::

    @string debugger_path = None

</t>
<t tx="ekr.20060529053407">``@ignore`` can only be used in the root node of @file trees. It tells Leo
to ignore the tree.

The ``@ignore`` directive can not be used elsewhere in @file trees because
of the way Leo recreates outlines from external files. This is an
absolutely crucial restriction and will never go away. For details, see the
entry for 2003 in the `History of Leo`_.

There are several workaround, as shown in LeoPy.leo:

- keep notes in the outline outside of any external file.
- Use ``@all`` to gather notes in a external file, as in done in @file
  leoProjects.txt.
</t>
<t tx="ekr.20060612102055">.. Most of this has nothing to do with *writing* plugins.</t>
<t tx="ekr.20060612103240">###############
Writing Plugins
###############

.. _`Scripting Leo with Python`: tutorial-scripting.html

Plugins modify how Leo works. With plugins you can give Leo new commands,
modify how existing commands work, or change any other aspect of Leo's look
and feel.

leoPyRef.leo contains all of Leo's official plugins. Studying this file is
a good way to learn how to write plugins.

Writing plugins is like writing any other Leo script.  See
`Scripting Leo with Python`_. In particular:

1. Plugins can use any of Leo's source code simply by importing any module
   defined in leoPy.leo.

2. Plugins can register event handlers just like any other Leo script. For full
   details, see the section called `Handling Events`_ later in this chapter.

The rest of this chapters discusses topics related specifically to plugins.

.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="ekr.20060620094033"></t>
<t tx="ekr.20060620094033.1"></t>
<t tx="ekr.20060620094033.2"></t>
<t tx="ekr.20060620095949.15">::

    Leo matching brackets
    \1, \2, etc. replacements are valid in regex searches
    \n and \t are valid in plain searches
    The shortcut for the replace-string command changes
    from the find command to the replace command
</t>
<t tx="ekr.20060620095949.25">::

    @abbrev settings
    @font settings
    Commands can be executed on entry to a mode
    Bindings that are active only in command, enter and insert key states

    New Settings:

        @bool autoindent_in_nocolor_mode
        @bool flash_matching_brackets
        @bool idle_redraw
        @bool trace_bind_key_exceptions
        @bool warn_about_redefined_shortcuts
        @color flash_brackets_background_color
        @color flash_brackets_foreground_color
        @int flash-brackets-delay
        @int flash_brackets_count
        @string close_flash_brackets
        @string open_flash_brackets
        @string editor_orientation
</t>
<t tx="ekr.20060620130636">::

    cycle-focus
    debug
    find-character
    find-word
    help-for-command
    hide-invisibles 
    isearch-with-present-options
    open-users-guide
    python-help
    run-unit-test
    scroll-outline-left
    scroll-outline-right
    toggle-autocompleter
    toggle-calltips
    toggle-invisibles
</t>
<t tx="ekr.20060620130943">::

   Added slideshow.py
   mod_scripting.py creates a press-x-button commands
</t>
<t tx="ekr.20060620133820.16">::

    Added script to update new copies of leoSetttings.leo from previous copies
    Made all edit command undoable
    Added colorizing support for Lua language
    Autocompletion and calltips
    Leo remembers the previous open directory
    User input modes
    Installed many standard bindings to leoSettings.leo
    Added support for @mode nodes
    Added modes/\*.xml to distribution
    Allow multiple key bindings to the same command
    Moved all scripts into scripts.leo
    Bound &lt;Return&gt; to end-edit-headline
    Created scripts.leo and unitTest.leo
    The tabbed log
    The Find tab replaces the old Find panel</t>
<t tx="ekr.20060620140130">::

    Changed path to stylesheet in the rst3 plugin
    Fixed crasher in Word (and other) plugins
    Fixed problem with labels plugin

    Added the following commands for the groupoperations plugin:

        group-operations-clear-marked
        group-operations-mark-for-copy
        group-operations-mark-for-move
        group-operations-mark-for-clone
        group-operations-mark-target
        group-operations-operate-on-marked
        group-operations-transfer

    The scripting plugin now supports shortcuts in @button nodes:

        @button name @key=shortcut

    The scripting plugin now supports @command nodes:

        @command name @key=shortcut
</t>
<t tx="ekr.20060620140228">::

    New settings features:

        Per-pane bindings: command-name ! pane = shortcut
        Spelling settings replace the settings in spellpyx.ini
            @shortcuts nodes

    New settings:

        @bool allow_idle_time_hook
        @bool autocomplete-brackets
        @bool gc_before_redraw
        @bool minibufferSearchesShowFindTab
        @bool show_only_find_tab_options
        @bool show_tree_stats
        @bool trace_autocompleter
        @bool trace_bindings
        @bool trace_doCommand
        @bool trace_f.set_focus
        @bool trace_focus
        @bool trace_g.app.gui.set_focus
        @bool trace_gc
        @bool trace_gc_calls
        @bool trace_gc_verbose
        @bool trace_key_event
        @bool trace_masterClickHandler
        @bool trace_masterCommand
        @bool trace_masterFocusHandler
        @bool trace_masterKeyHandler
        @bool trace_minibuffer
        @bool trace_modes
        @bool trace_redraw_now
        @bool trace_select
        @bool trace_status_line
        @bool trace_tree
        @bool trace_tree_alloc
        @bool trace_tree_edit
        @bool useCmdMenu
        @bool useMinibuffer
        @bool use_syntax_coloring
        @color body_text_selection_background_color
        @color body_text_selection_foreground_color
        @color log_pane_Find_tab_background_color
        @color log_pane_Spell_tab_background_color, etc.
        @int max_undo_stack_size,
        @string trace_bindings_filter
        @string trace_bindings_pane_filter
</t>
<t tx="ekr.20060629083935">Leo 4.4, May 11, 2006:

Leo 4.4 completed a year-long effort to incorporate an Emacs-style minibuffer and related commands into Leo. Leo 4.4 also featured many improvements in how keys are bound to commands, including per-pane bindings and user-defined key-binding modes. These features allow users to emulate Emacs, Vim, or any other editor. They also make it easy to use Leo without a mouse.

This release created many Emacs-like commands, including cursor and screen movement, basic character, word and paragraph manipulation, and commands to manipulate buffers, the kill ring, regions and rectangles. Much of the work started with a prototype by LeoUser (B.H).

- The **New World Order**: drawing happens immediately, not at idle time.
- The **Newer World Order**: c.endUpdate is equivalent to ``c.redraw_now``.
- Add a tabbed log pane.
- Add autocompletion and calltips.

Development on long-delayed projects accelerated after 4.4.</t>
<t tx="ekr.20060805094325">You can 'revert' to old key bindings as follows:

1. Open leoSettings.leo.

2. Find the node 'Keyboard shortcuts'.

3. Disable the old bindings by moving the node '@keys EKR bindings: Emacs keys + modes' so that it is a child of the node: '@ignore Unused key bindings'.

4. Notice that there are two child nodes of the node '@ignore Unused key bindings' that refer to legacy key bindings:

   - '@keys Legacy Leo shortcuts with important Emacs bindings'

   - '@keys Legacy Leo bindings'.

5. Move **one** of these two legacy nodes up one level so that it is a child of the node 'Keyboard shortcuts'. It should **not** be a child of the node '@ignore Unused key bindings'.
</t>
<t tx="ekr.20060915112109">Find the @file leoApp.py node in leoPy.leo. In the ctor for the LeoApp class set self.use_psyco to True or False. You will find this ctor in the node::

    Code--&gt;Core classes...--&gt;@file leoApp.py--&gt;app.__init__

Note that this ivar can not be set using settings in leoSettings.leo because Leo uses g.app.use_psyco before processing configuration settings.
</t>
<t tx="ekr.20060917130130">Add the following as the *very first line* of your scripts::

    @first # -*- coding: utf-8 -*-

Without this line, constructs such as::

    u = u'a-(2 unicode characters here)-z'
    u = 'a-(2 unicode characters here)-z'

will not work when executed with Leo's execute script command. Indeed, the Execute Script command creates the script by writing the tree containing the script to a string. This is done using Leo's write logic, and this logic converts the unicode input to a utf-8 encoded string. So *all non-ascii characters* get converted to their equivalent in the utf-8 encoding. Call these encoding &lt;e1&gt; and &lt;e2&gt;. In effect the script becomes::

    u = u'a-&lt;e1&gt;-&lt;e2&gt;-z'
    u = 'a-&lt;e2&gt;-&lt;e&gt;-z'

which is certainly *not* what the script writer intended! Rather than defining strings using actual characters, Instead, one should use the equivalent escape sequences. For example::

    u = u'a-\\u0233-\\u8ce2-z'
    u = 'a-\\u0233-\\u8ce2-z'
</t>
<t tx="ekr.20060921064744.1">.. _`sentinel lines`: glossary.html#sentinel-lines

This section describes Leo's `sentinel lines`_, comment used in external files.

.. index:: gnx

External files created by ``@file`` use gnx's in ``@+node`` sentinels. Such gnx's permanently and uniquely identify nodes. Gnx's have the form::

    id.yyyymmddhhmmss
    id.yyyymmddhhmmss.n

The second form is used if two gnx's would otherwise be identical.

- ``id`` is a string unique to a developer, e.g., a git id.
- ``yyyymmddhhmmss`` is the node's creation date.
- ``n`` is an integer.

Closing sentinels are required for section references and the ``@all`` and ``@others`` directives, collectively known as **embedding constructs.** Proof: These constructs do not terminate the node in which they appear. Without a closing sentinel there would be no way to know where the construct ended and the following lines of the enclosing node began.

Here are the sentinels used by modern versions of Leo, in alphabetical order.

``@&lt;&lt;``
    Sentinels of the form ``@&lt;&lt;section_name&gt;&gt;`` represent section references.

    If the reference does not end the line, the sentinel line ending the
    expansion is followed by the remainder of the reference line. This
    allows the Read code to recreate the reference line exactly.

``@@``
    This sentinel represents any line starting with ``@`` in body text
    except ``@&lt;whitespace&gt;``, ``@doc`` and ``@others``.
    Examples::

      @@nocolor
      @@pagewidth 80
      @@tabwidth -4
      @@c

.. ``@afterref``
..     Marks non-whitespace text appearing after a section references.
..     As of Leo 6.6, Leo no longer *writes* afterref sentinels.
..     However, Leo will always *read* such sentinels correctly.

``@+all`` and ``-all``
    These sentinels mark the range of``@all`` directives.

``@at`` and ``@doc``
    These sentinels mark the range of ``@doc`` parts.

..  Leo 5.7.4. retired the **trailing whitespace convention**:
..      A line in a doc part is followed by an inserted newline
..      if and only if the newline if preceded by whitespace.
..  To make this convention work, Leo's old write code deleted the trailing
..  whitespace of all lines that are followed by a "real" newline.

.. ``@+body`` ``and @-body`` **(Leo 3.x only)**
..    These sentinels marked the range of body text.

``@@delims``
    This sentinel marks the range of an ``@delims`` directive.  |br|
    The range continues until the next ``@delims`` directive.
    
    Adding, deleting or changing ``@@delim`` *sentinels* will destroy Leo's
    ability to read the external file.
    
    Mistakes in using the ``@delims`` *directives* have no effect on Leo,
    though such mistakes will thoroughly mess up a external file as far as
    compilers, HTML renderers, etc. are concerned.

``@@section-delims``
    This sentinel represents the ``@section-delims`` directive. |br|
    Such must appear in the root ``@&lt;file&gt;`` node.

``@+leo``
    This sentinel marks the start of any external file.  |br|
    This sentinel has the form::

        &lt;opening_delim&gt;@leo&lt;closing_delim&gt;

    The read code uses single-line comments if ``&lt;closing_delim&gt;`` is empty.  |br|
    The write code generates single-line comments if possible.

    The ``@+leo`` sentinel contains other information. For example::

        &lt;opening_delim&gt;@leo-ver=4-thin&lt;closing_delim&gt;

``@-leo``
    This sentinel marks the end of the Leo file. |br|
    Nothing but whitespace should follow this directive.

..  @+middle and @-middle: Created in Leo 4.0, removed in Leo 5.3.
..      These sentinels marked a range of nodes.
..      These sentinels were a **mistake**. See:
..      https://github.com/leo-editor/leo-editor/issues/132

``@+node``
    This sentinel marks the start of a node::

        @+node:gnx:&lt;headline&gt;
        
    Nodes continue until the next ``@+node``, ``at-all`` or ``at-others`` sentinel.

.. ``@nl`` and ``@nonl``: Leo 3.x only
..      These sentinels inserted or suppressed newlines in the outline.
..      Modern versions of Leo do not write ``@nonl`` or ``@nl``.
..      As a result, body text always ends with at least one newline.

``@+others`` and ``@-others``
    These sentinels mark the range of an ``@others`` directive.     

``@verbatim``
    This sentinel indicates that the next line of the external file is not
    a sentinel. This escape convention allows body text to contain lines
    that would otherwise be considered sentinel lines.

..  @@verbatimAfterRef 
..      Old versions of Leo generated @verbatimAfterRef when a comment
..      following a section reference would otherwise be treated as a sentinel.
</t>
<t tx="ekr.20060928172457"></t>
<t tx="ekr.20060928172457.4">::

    Leo can be called from Emacs: See the `Leo and Emacs` chapter
    Added support for middle-button paste
    Writing .leo files is about twice as fast as before
    Integrated sax with read logic
    Much faster navigation through the outline using Alt-arrow keys
    When focus is in the outline pane, you can move to headlines by
    typing the first letter of headlines
    The find command now closes nodes
    Leo is easier to use without using a mouse
</t>
<t tx="ekr.20060928172457.5">::

    Improved mod_scripting.py:

        Creates a command for every button
        The Script Button button creates the press-script-button-button command

    New plugins:

        leo_to_html.py
        leo_to_rtf.py
        paste_as_headlines.py
        slideshow.py
        word_count.py
</t>
<t tx="ekr.20060929043325">::

    Leo 4.4.2.1 final released October 29, 2006
    The 'big reorg': vnode and tnode classes are independent of Leo's core
    Support for ZODB in the vnode and tnode classes
    The find command closes nodes behind it
</t>
<t tx="ekr.20061009111417.11">::

    @bool collapse_nodes_during_finds
    @bool insert_new_nodes_at_end
    @bool sparse_move_outline_left
</t>
<t tx="ekr.20061009111417.18">::

    extend-to-line
    extend-to-paragraph
    extend-to-sentence
    forward-end-word
    forward-end-word-extend-selection
</t>
<t tx="ekr.20061010121944">def createRecentFiles(self):
    '''Try to create .leoRecentFiles.txt in
    - the users home directory first,
    - Leo's config directory second.'''
    for theDir in (g.app.homeLeoDir, g.app.globalConfigDir):
        if theDir:
            try:
                fn = g.os_path_join(theDir, '.leoRecentFiles.txt')
                f = open(fn, 'w')
                f.close()
                g.red('created', fn)
                return
            except Exception:
                g.error('can not create', fn)
                g.es_exception()
</t>
<t tx="ekr.20061021164213">Set @bool ignore_unbound_non_ascii_keys = False in LeoSettings.leo or myLeoSettings.leo.
</t>
<t tx="ekr.20061025065357"></t>
<t tx="ekr.20061025065357.1">#################################
Leo and Emacs, including org mode
#################################

This chapter several topics relating to the Emacs editor.

.. contents:: Contents
    :depth: 2
    :local:

</t>
<t tx="ekr.20061025070825.1">The leoPymacs module is intended to be called from Emacs using pymacs.  It contains the following top-level functions:

- get_app()

  Returns the hidden app created by the leoPymacs.init function.

- dump(anyPythonObject)

  Returns str(repr(anyPythonObject)).

- get_g()

  Returns the leoGlobals module of the hidden app created by the leoPymacs.init function.

- get_script_result()

  Returns g.app.scriptResult, where g.app is the hidden app.

- init()
  Calls leo.run(pymacs=True) to create a hidden Leo application.
  Later calls to open can open hidden Leo outlines that can be accessed via runScript.

- open(fileName)

  Opens the .leo file given by fileName. fileName must be the full
  path to a .leo file. Returns the commander of the open Leo outline,
  or None if the outline could not be opened.

- run_script(c,script,p=None)

  Executes a script in the context of a commander c returned by the leoPymacs.open.
  c may be None, in which case a dummy commander is created in which to run the script.
  In the executed script, p is set to c.p if no p argument is specified.
  Returns g.app.scriptResult, where g.app is the hidden app.
</t>
<t tx="ekr.20061025081359">.. _`pymacs`:   https://pymacs.progiciels-bpi.ca/index.html
.. _`elisp`:    https://en.wikipedia.org/wiki/Emacs_Lisp
.. _`Emacs`:    https://www.xemacs.org/

Leo's leoPymacs module is a simple 'server' for the `pymacs`_ package. Using pymacs and leoPymacs, `elisp`_ scripts in `Emacs`_ can open .leo files and execute *Python* scripts as if they were executed inside Leo. In particular, such scripts can use Leo's predefined c, g and p variables. Thus, *Python* scripts running in Emacs can:

- Open any .leo file. 
- Access any part of the outline. 
- Change any part of the outline, including external files, 
- Save .leo files.
- Execute *any* Leo script.

In short, you can now do from Emacs anything that you can do with Leo scripting inside Leo.

Here are step-by-step instructions for executing Python scripts in Emacs:

**Step 1. Install pymacs** 

A note about two-way communication between Python and lisp scripts: Python
scripts can call the Pymacs.lisp function *only* if the Python script was
invoked from emacs. Otherwise, calling ``Pymacs.lisp`` will hang the process
making the call. For example, executing the following script as an ordinary
Leo script will hang Leo:

.. code-block:: python

    from Pymacs import lisp
    print lisp("""2+2""") # Hangs

**Step 2. Load leoPymacs, creating a hidden Leo application**

From inside Emacs, you load Leo's leoPymacs module as follows::

    (pymacs-load "leoPymacs" "leo-")

The call to pymacs-load is similar to this Python code:

.. code-block:: python

    import leoPymacs as leo-'

``pymacs-load`` defines the elisp function
``leo-x`` for every top-level function ``x`` in ``leoPymacs.py``, namely::

    leo-dump
    leo-get-app
    leo-get-g
    leo-get-script-result
    leo-init
    leo-open
    leo-run-script

Each of these creates a **hidden Leo application** that can load, change or
save ``.leo`` files. This hidden application can also execute Leonine
scripts.

This hidden Leo application uses Leo's "null" gui. Leo commands and Leo
scripts that use Leo's "qt" gui will not work as expected.

``pymacs-load`` works like a Python reload, so you can redefine
``leoPymacs.py`` while Emacs is running. However, calling ``pymacs-load``
creates a *new* Leo application, so typically you would want to call
pymacs-load only once per Emacs session. Like this::

    (setq reload nil) ; change nil to t to force a reload.

    (if (or reload (not (boundp 'leoPymacs)))
        (setq leoPymacs (pymacs-load "leoPymacs" "leo-"))
        (message "leoPymacs already loaded")
    )

**Step 3. open .leo files from emacs**

We can now open a ``.leo`` file as follows::

    (setq c (leo-open fileName))

This call binds the elisp ``c`` variable to the newly-opened Leo commander.
``fileName`` should be the full path to a .leo file. The ``c`` argument may
be ``nil``. If so, ``leo-run-script`` creates a **dummy commander** for the
script. For example, the following script calls ``g.os_path_join`` and
``g.os_path_abspath``::

    (setq script "g.app.scriptResult =
        g.os_path_abspath(g.os_path_join(
            g.app.loadDir,'..','test','ut.leo'))"
    )

    (setq fileName (leo-run-script nil script))

``leo-run-script`` returns the value of ``g.app.scriptResult``. As shown
above, Python scripts return their results by setting
``g.app.scriptResult``. elisp scripts may get ``g.app.scriptResult``
using ``leo-script-result``.

**Step 4. Execute Leonine scripts from emacs**

From emacs we can execute a Python script **as if** it were executed in an
open Leo outline. Suppose aLeoScript is an **elisp** string containing a
Leo (Python) script. We can execute that script in the hidden Leo
application as follows::

    (leo-run-script c aLeoScript)

For example::

    (setq c (leo-open fileName)
    (csetq script "print 'c',c,'h',c.p.h")
    (leo-run-script c script)

Putting this all together, we get::

    ; Step 1: load leoPymacs if it has not already been loaded.
    (setq reload nil)
    (if (or reload (not (boundp 'leoPymacs)))
        (setq leoPymacs (pymacs-load "leoPymacs" "leo-"))
        (message "leoPymacs already loaded")
    )

    ; Step 2: compute the path to leo/test/ut.leo using a Leo script.
    (setq script
        "g.app.scriptResult = g.os_path_abspath(
            g.os_path_join(g.app.loadDir,'..','test','ut.leo'))"
    )
    (setq fileName (leo-run-script nil script))

    ; Step 3: execute a script in ut.leo.
    (setq c (leo-open fileName))
    (setq script "print 'c',c.shortFileName() ,'current:',c.p.h")
    (leo-run-script c script)
</t>
<t tx="ekr.20061025142434">Leo's mini-buffer is a text area at the bottom of the body pane. You use Leo's minibuffer like the Emacs mini-buffer to invoke commands by their so-called *long name*. The following commands affect the minibuffer:

- **full-command**: (default shortcut: Alt-x) Puts the focus in the minibuffer. Type a full command name, then hit &lt;Return&gt; to execute the command. Tab completion works, but not yet for file names.

- **quick-command-mode**: (default shortcut: Alt-x) Like Emacs Control-C. This mode is defined in leoSettings.leo. It is useful for commonly-used commands.

- **universal-argument**: (default shortcut: Alt-u) Like Emacs Ctrl-u. Adds a repeat count for later command. Ctrl-u 999 a adds 999 a's.

- **keyboard-quit**: (default shortcut: Ctrl-g) Exits any minibuffer mode and puts the focus in the body pane.

For example, to print a list of all commands type Alt-X show-commands &lt;Return&gt;.
</t>
<t tx="ekr.20070115172724">.. _`embedded winpdb`: https://www.digitalpeers.com/pythondebugger/embedded.htm
.. _`winpdb`: https://www.digitalpeers.com/pythondebugger/

The following three section discuss three ways of debugging scripts with `winpdb`_. The first two sections tell how to debug general scripts; the last section tells how to debug Leo-specific scripts.

winpdb_ and its documentation have been improved recently. For more details, see the `embedded winpdb`_ docs. The discussion of embedded debugging may have been written specifically with Leo in mind.
</t>
<t tx="ekr.20070115172724.1">This way of debugging can only be used for general scripts, not leo-specific scripts. The debug command writes the script to scriptFile.py and invokes winpdb. winpdb opens and is already 'attached' to the script to be debugged. You can single-step as you like. Leo continues to run, but killing the debugger will also kill Leo.
</t>
<t tx="ekr.20070115172724.3">This way of debugging scripts allows winpdb to debug scripts that use c, g and p. A bit more work is needed because winpdb does not start automatically. Here are step-by step instructions:

1. Insert the following two lines of code at the start of the script to be debugged:

    .. code-block:: python

        import rpdb2
        rpdb2.start_embedded_debugger('go',fAllowUnencrypted=True)

2. Execute Leo's execute-script command (*not* the debug command). Leo will appear to hang: start_embedded_debugger is waiting for *another* copy of winpdb to 'attach' to the script's process. The default timeout is 5 minutes, after which an exception gets thrown.

3. Start winpdb explicitly by executing something like the following in a console::

    python /Python26/Scripts/_winpdb.py -t

   The -t option tells winpdb that no encoding of password is necessary.
   The password is specified in the call to rpdb2.start_embedded_debugger in your script.
   In our example, the password is 'go'.

4. Use winpdb's File:Attach command to attach winpdb to Leo. Specify the password as 'go' and you will see the scriptFile.py containing your entire script. You can now execute or single-step through the script. To repeat, c, g and p are defined, so you can debug any script this way.
</t>
<t tx="ekr.20070116062405">.. _`FAQ`:                  FAQ.html#how-can-i-use-python-s-pdb-debugger-with-leo
.. _`pdb`:                  https://docs.python.org/3/library/pdb.html
.. _`run Leo in a console`: installing.html#running-leo-from-a-console-window
.. _`work flow`:            FAQ.html#how-can-i-use-leo-to-develop-leo-itself

Inserting g.trace statements in my Python code is usually my first debugging choice. The g.trace statement prints the name of the function in which the call to g.trace occurs, followed by the value of its arguments. The output of the g.trace goes to the console, so you must `run Leo in a console`_ to use g.trace.

Inserting and deleting g.trace statements is fast, provided that your `work flow`_ makes it easy to restart the program under test. As a result, using g.trace statements is similar to setting tracepoints in a debugger, with the advantage that (disabled) tracepoints remain in the source code for future use. You will find many examples of using g.trace throughout Leo's source code.

My second choice is using g.pdb to set breakpoints for the `pdb`_ debugger. Pdb uses the console for all interaction, so you must `run Leo in a console`_. See the `FAQ`_ for a discussion of both g.trace and g.pdb.
</t>
<t tx="ekr.20070120075236">.. index::
    pair: Predefined Symbols; Tutorial

The execute-script command predefines the symbols c, g, and p.

c is the **commander** of the outline containing the script. Commanders are instances of the Commands class, defined in leoCommands.py. Commanders provide access to all outline data *and* all of Leo's source code.

g is Leo's **leo.core.leoGlobals** containing many useful functions, including g.es.

p is the **position** of the presently selected node. Positions represent nodes at a particular location of an outline. Because of clones, the *same* node may appear at multiple positions in an outline. **c.p** is the outline's presently selected position.
</t>
<t tx="ekr.20070122093626">Positions become invalid whenever the outline changes. 

This script finds a position p2 having the same vnode as an invalid position p:

.. code-block:: python

    if not c.positionExists(p):
        for p2 in c.all_positions():
            if p2.v == p.v: # found
                c.selectPosition(p2)
        else:
            print('position no longer exists')
</t>
<t tx="ekr.20070224115832">def readRecentFiles(self, localConfigFile):
    '''Read all .leoRecentFiles.txt files.'''
    # The order of files in this list affects the order of the recent files list.
    rf = self
    seen = []
    localConfigPath = g.os_path_dirname(localConfigFile)
    for path in (
        g.app.homeLeoDir,
        g.app.globalConfigDir,
        localConfigPath,
    ):
        if path:
            path = g.os_path_realpath(g.os_path_finalize(path))
        if path and path not in seen:
            ok = rf.readRecentFilesFile(path)
            if ok: seen.append(path)
    if not seen and rf.write_recent_files_as_needed:
        rf.createRecentFiles()
</t>
<t tx="ekr.20070317033759"></t>
<t tx="ekr.20070317033759.1">#######################################
Embedding Leo with the leoBridge module
#######################################

The leoBridge module allows complete access to all aspects of Leo from other
Python programs running independently of Leo. Let us call such a program a
**host** program. Using the leoBridge module, host programs can get access to:

- all of Leo's source code,
- the contents of any .leo file,
- the commander of any .leo file.

.. contents:: Contents
    :depth: 2
    :local:


</t>
<t tx="ekr.20070317033759.3">Host programs may use the leoBridge module as follows:

.. code-block:: python

    import leo.core.leoBridge as leoBridge

    controller = leoBridge.controller(gui='nullGui',
        loadPlugins=True,  # True: attempt to load plugins.
        readSettings=True, # True: read standard settings files.
        silent=False,      # True: don't print signon messages.
        verbose=False)     # True: print informational messages.

    g = controller.globals()
    c = controller.openLeoFile(path)

Let us look at these statements in detail. The first two statements import the leoBridge module and create a **bridge controller**. In effect, these statements embed an invisible copy of Leo into the host program. This embedded copy of Leo uses a null gui, which simulates all aspects of Leo's normal gui code without creating any screen objects.

The statement:

.. code-block:: python

    g = controller.globals()

provides access to Leo's leoGlobals module, and properly inits globals such as g.app, g.app.gui, etc. *Host programs should not import leoGlobals directly*, because doing so would not init the g.app object properly.

The statement:

.. code-block:: python

    c = controller.openLeoFile(path)

invisibly opens the .leo file given by the path argument. This call returns a completely standard Leo commander, properly inited. This is the big payoff from the leoBridge module: the host program gets instant access to c.config.getBool, etc.
</t>
<t tx="ekr.20070317043727">Organizer nodes have headlines that do no start with ``@``. Organizer nodes may be inserted freely without changing the meaning of an ``@setting`` tree.
</t>
<t tx="ekr.20070317043727.2">Simple settings nodes have headlines of the form ``@&lt;type&gt; name = val``.
These settings set the value of name to val, with the indicated type::

    &lt;type&gt;          Valid values
    ------          ------------
    @bool           True, False, 0, 1
    @color          A Qt color name or value, such as 'red' or 'xf2fddff'   
                    (without the quotes)
    @directory      A path to a directory
    @float          A floating point number of the form nn.ff.
    @int            An integer
    @ints[list]     An integer (must be one of the ints in the list).
                    Example: @ints meaningOfLife[0,42,666]=42
    @keys[name]     Gives a name to a set of bindings.
                    (For the Check Bindings script in leoSettings.leo.)
    @path           A path to a directory or file
    @ratio          A floating point number between 0.0 and 1.0, inclusive.
    @string         A string
    @strings[list]  A string (must be one of the strings in the list).
                    Example: @strings tk_relief['flat','groove','raised']='groove'

**Note**: For a list of Tk color specifiers see:

- https://www.tcl.tk/man/tcl8.4/TkCmd/colors.htm
- https://www.tcl.tk/man/tcl8.4/TkLib/GetColor.htm

**Important**: you can use the ``show-colors`` command to guide you in making these settings.
</t>
<t tx="ekr.20070317043727.3">Complex settings nodes have headlines of the form ``@&lt;type&gt; description``::

    @&lt;type&gt;             Valid values
    -------             ------------
    @buttons            Child @button nodes create global buttons.
    @commands           Child @command nodes create global buttons.
    @command-history    Body is a list of commands pre-loaded into history list.
    @data               Body is a list of strings, one per line.
    @enabled-plugins    Body is a list of enabled plugins.
    @font               Body is a font description.
    @menus              Child @menu and @item nodes create menus and menu items.
    @menuat             Child @menu and @item nodes modify menu trees
                        created by @menus.
    @mode [name]        Body is a list of shortcut specifiers.
    @recentfiles        Body is a list of file paths.
    @shortcuts          Body is a list of shortcut specifies.

Complex nodes specify settings in their body text.
See the following sections for details.
</t>
<t tx="ekr.20070513113903"></t>
<t tx="ekr.20070610174018">This section contains settings for this file.

It also contains other information of little interest to most Leo users.</t>
<t tx="ekr.20070622212132">::

    activate-cmds-menu
    activate-edit-menu
    activate-file-menu
    activate-help-menu
    activate-outline-menu
    activate-plugins-menu
    activate-window-menu
    add-space-to-lines
    add-tab-to-lines
    clean-lines
    clear-selected-text
    click-click-box
    click-headline
    click-icon-box
    clone-find-all
    contract-and-go-right
    contract-body-pane
    contract-log-pane
    contract-outline-pane
    contract-pane
    double-click-headline
    double-click-icon-box
    dump-all-objects
    dump-new-objects
    expand-body-pane
    expand-log-pane
    expand-outline-pane
    expand-pane
    find-again
    find-all
    find-tab-find command
    find-tab-find-previous
    free-text-widgets
    fully-expand-body-pane
    fully-expand-log-pane
    fully-expand-outline-pane
    fully-expand-pane
    goto-first-sibling
    goto-global-line
    goto-last-sibling
    help
    help-for-command
    hide-body-pane
    hide-find-tab
    hide-log-pane
    hide-minibuffer
    hide-outline-pane
    hide-pane,
    open-find-tab
    open-find-tab
    open-outline-by-name (uses filename completion)
    open-spell-tab
    show-bindings
    show-commands    re-search-backward
    re-search-forward
    remove-space-from-lines
    remove-tab-from-lines
    replace-string
    run-unit-test
    scroll-down
    scroll-down-extend-selection
    scroll-outline-down-line
    scroll-outline-down-page 
    scroll-outline-up-line
    scroll-outline-up-page
    scroll-up
    scroll-up-extend-selection
    search-backward
    search-forward
    search-with-present-options
    set-find-everywhere
    set-find-node-only
    set-find-suboutline-only
    show-colors
    show-fonts
    show-minibuffer
    show-search-options
    simulate-begin-drag
    simulate-end-drag
    toggle-find-ignore-case-option
    toggle-find-in-body-option,
    toggle-find-in-headline-option
    toggle-find-mark-changes-option
    toggle-find-mark-finds-option
    toggle-find-regex-option
    toggle-find-reverse-option
    toggle-find-word-option and
    toggle-find-wrap-around-option
    toggle-mini-buffer
    verbose-dump-objects
    word-search-backward
    word-search-forward
</t>
<t tx="ekr.20070623145346.1">Leo's setup.py script is intended only to create source distributions. It can't be used to install Leo because Leo is not a Python package.
</t>
<t tx="ekr.20070809145744"></t>
<t tx="ekr.20070809145744.4">::

    check-derived-file
    check-leo-file
    compare-leo-outlines
    insert-child
    read-at-auto-nodes
    read-file-into-node
    write-at-auto-nodes
    write-dirty-at-auto-nodes
    write-file-from-node
</t>
<t tx="ekr.20070809145744.5">::

    @buttons trees
    @menus trees
    Added 'clear-all-marks' hook
    Added graphed.py plugin
</t>
<t tx="ekr.20070814104719">You enable or disable plugins using ``@enabled-plugins`` nodes in leoSettings files (``leoSettings.leo``, ``myLeoSettings.leo`` or the ``.leo`` file being loaded). See `Specifying settings &lt;customizing.html#specifying-settings&gt;`_ for full details of settings files.

The body text of the ``@enabled-plugins`` node contains a list of enabled plugins. Notes:

Leo attempts to load all plugins every time an ``@enabled-plugins`` node is seen. If the plugin has already been loaded, Leo silently ignores the request to re-enable the plugin. Leo never attempts to disable a plugin while processing enabled plugin strings. Thus, plugins enabled in an ``@enabled-plugins`` node in ``leoSettings.leo`` *will* be enabled regardless of the contents of any other ``@enabled-plugins`` node.

You can enable plugins by file name or by module name:
- Leo looks in the leo/plugins directory for names ending in .py.
- Leo uses imports a module directly for names that do *not* end in .py, so you can load plugins from any path on PYTHONPATH, including paths given in sitecustomize.py.

g.app.gui.getEnabledPlugins contains the last processed ``@enabled-plugins`` node.
</t>
<t tx="ekr.20070816092449">Question and answer from plumloco.

Add the equivalent of::

    import sys 
    leocore = "path/to/leo/core" 
    if leocore not in sys.path: sys.path.append(leocore) 
    import leo.core.leoBridge as leoBridge

at the head of each file that uses leoBridge.

The problem is not importing leoBridge itself but (if I use 'from leo.core') the importing of plugins, who get a different leoGlobals from leoBridge, without g.app etc, and so do not work if they rely on dynamic values in g.etc.

&gt; Why can't you simply add leo/core to sys.path in sitecustomize.py?

Putting leo/core on the python path as you suggest would put forty python modules in the global module namespace for all python programs when I want just one. Also, I have a safe working copy of leo and a cvs/testing version. I would wish to test any programs against the testing version while using the working version, but both /core directories can't be exposed at the same time.

&gt; Do you need plugins while running from the leoBridge? 

Afraid so, at least the rst3 plugin. The solution I am using now is to place::

    sys.modules['leoGlobals'] = leoGlobals  

in leoBridge after import leo.core.leoGlobals as leoGlobals

This allows my scripts to be portable over the several computers/platforms I need to use them on, and makes testing scripts against multiple leo versions easy. It does mean that my scripts are not portable to other leo users but that is not likely to be a problem.
</t>
<t tx="ekr.20071026055929"></t>
<t tx="ekr.20071026055929.1">First, you must change Python's default encoding to something other than 'ascii'.  To do this, put the following in your sitecustomize.py file in Python's Lib folder::

    import sys 
    sys.setdefaultencoding('utf-8') # 'iso-8859-1' is another choice.

You must restart Python after doing this: sys.setdefaultencoding can not be called after Python starts up.

Leo's g.es_print and g.pr functions attempts to convert incoming arguments to unicode using the default encoding. For example, the following Leo script shows various ways of printing La Peña properly::

    @first # -*- coding: utf-8 -*-

    import sys
    e = sys.getdefaultencoding()
    print 'encoding',e
    table = (
        'La Peña',
        unicode('La Peña','utf-8'),
        u'La Peña',
        u'La Pe\\xf1a',
    )

    for s in table:
        print type(s)
        g.es_print('g.es_print',s)
        if type(s) != type(u'a'):
            s = unicode(s,e)
        print 'print     ',s
        print 'repr(s)   ',repr(s)

For still more details, see: https://www.diveintopython.org/xml_processing/unicode.html
</t>
<t tx="ekr.20071026183116">Scripts can invoke various dialogs using the following methods of the g.app.gui object.

Here is a partial list. Use typing completion to get the full list:

.. code-block:: python

    g.app.gui.runAskOkCancelNumberDialog(c,title,message)
    g.app.gui.runAskOkCancelStringDialog(c,title,message)
    g.app.gui.runAskOkDialog(c,title,message=None,text='Ok')
    g.app.gui.runAskYesNoCancelDialog(c,title,message=None,
        yesMessage='Yes',noMessage='No',defaultButton='Yes')
    g.app.gui.runAskYesNoDialog(c,title,message=None)

The values returned are in ('ok','yes','no','cancel'), as indicated by the method names. Some dialogs also return strings or numbers, again as indicated by their names.

Scripts can run File Open and Save dialogs with these methods:

.. code-block:: python

    g.app.gui.runOpenFileDialog(title,filetypes,defaultextension)
    g.app.gui.runOpenFilesDialog(title,filetypes,defaultextension)
    g.app.gui.runSaveFileDialog(initialfile,title,filetypes,defaultextension)

For details about how to use these file dialogs, look for examples in Leo's own source code. The runOpenFilesDialog returns a list of file names.
</t>
<t tx="ekr.20071116062917"></t>
<t tx="ekr.20071116062917.18">::

    delete-all-icons
    delete-first-icon
    delete-last-icon
    delete-node-icons
    insert-icon
    reverse-sort-lines
    reverse-sort-lines-ignoring-case
    sort-lines-ignoring-case
    toggle-collapse_nodes_during_finds
</t>
<t tx="ekr.20071116062917.2">.. Links used in this document.
.. _`leoBridge`:            leoBridge.html
.. _`debugging with Leo`:   debuggers.html
.. _`Using @shadow`:        atShadow.html
.. _`Python's gettext`:     https://docs.python.org/lib/module-gettext.html
.. _Emacs:                  https://www.xemacs.org/
.. _pymacs:                 https://pymacs.progiciels-bpi.ca/index.html
.. _`Leo and Emacs`:        emacs.html


</t>
<t tx="ekr.20071116062917.3">::

    Created unitTest.leo
    The rst3 plugin now supports @rst-preformat nodes
</t>
<t tx="ekr.20071210094621">This following is adapted from Terry Brown's entry in Leo's wiki.

You can not just run leoBridge from Leo, because the leoBridge module is designed to run a separate copy of Leo. However, it is possible to run leoBridge from a separate process. That turned out to be more, um, interesting than anticipated, so I'm recording the results here.

The idea is that script A running in Leo (i.e. in a regular GUI Leo session) calls script B through subprocess.Popen(), script B uses LeoBridge to do something (parse unloaded Leo files), and returns the result to script A. Passing the result back via the clipboard seemed like a possibility, but XWindows clipboard madness being what it is, that didn't seem to work.

First trick, calling script B from script A:

.. code-block:: python

    import subprocess
    p = subprocess.Popen(('python',
        path_to_script_B,
        parameter_for_script_B,),
        stdout=subprocess.PIPE,
        env={'PYTHONPATH': g.app.loadDir,'USER': g.app.leoID},
    )
    p.wait()

Setting PYTHONPATH in the environment seemed like the easiest way to let script B find leoBridge.py (which it needs to import).  But by setting the env parameter you limit script B's environment to be **only** PYTHONPATH, which causes leoBridge to fail because, in unix at least, it depends on USER in the environment.  So you need to pass that through, too.

Now, because passing stuff back on the clipboard seems unreliable, at least in XWindows, script B passes results back to script A via stdout (print), but there's some Leo initialization chatter you want to avoid.  So put a sentinel, 'START_CLIPBOARD', in the output, and collect it like this:

.. code-block:: python

    response = p.stdout.readlines()
    while response and 'START_CLIPBOARD' not in response[0]:
        del response[0]
    del response[0]  # delete the sentinel as well
    response = ''.join(response)

This is the basic mechanism.  What I *actually* wanted to do was have script B generate a branch of nodes and pass that back to script A for insertion in the tree script A is running in.  That's relatively easy if you use:

.. code-block:: python

    c.setCurrentPosition(pos_of_branch_to_return)
    c.copyOutline()
    print '&lt;!-- START_CLIPBOARD --&gt;'
    print g.app.gui.getTextFromClipboard()
    print '&lt;!-- END_CLIPBOARD --&gt;'

at the end of script B. Back in script A, after you've rebuilt
`response` as shown above, do:

.. code-block:: python

    g.app.gui.replaceClipboardWith(response)
    c.pasteOutline()
</t>
<t tx="ekr.20071217093444"></t>
<t tx="ekr.20080109074102">You can add an icon to the presently selected node with c.editCommands.insertIconFromFile(path). path is an absolute path or a path relative to the leo/Icons folder. A relative path is recommended if you plan to use the icons on machines with different directory structures.

For example:

.. code-block:: python

    path = 'rt_arrow_disabled.gif' 
    c.editCommands.insertIconFromFile(path) 

Scripts can delete icons from the presently selected node using the following methods:

.. code-block:: python

    c.editCommands.deleteFirstIcon() 
    c.editCommands.deleteLastIcon() 
    c.editCommands.deleteNodeIcons() 
</t>
<t tx="ekr.20080310093038.4">.. _gettext: https://docs.python.org/lib/module-gettext.html

It is easy to translate Leo's menu strings: simply create an ``@menus`` tree in ``leoSettings.leo`` or ``myLeoSettings.leo`` that contains the translated menu names.

**New in Leo 4.4.8**: Leo now contains support for translating messages sent to Leo's log:

- Rather than using an ``_`` function to denote strings to be translated, Leo's g.es and g.es_print functions translate "odd" (first, third, fifth) arguments, leaving "even" arguments untranslated. Keyword arguments, color, newline, etc. are never translated.

- All calls to ``g.es`` and ``g.es_print`` in Leo's core follow this convention.

- ``g.translateString`` does the actual translation using Python's `gettext`_ module.

- You can use the script in the node ``@button print g.es stats`` in ``scripts.leo`` to create catalogs of all scripts that need to be translated. Such catalogs are used by Python's ``gettext`` module. (This script was also used to check that the proper arguments to ``g.es`` and ``g.es_print`` were translated.)
</t>
<t tx="ekr.20080314081157.127"></t>
<t tx="ekr.20080315115427.568">This series of releases featured hundreds of improvements.

Leo 4.4.1 (August 30, 2006) and Leo 4.4.2.1 (October 29, 2006):

- Add a new colorizer controlled by jEdit language description files.
- Add the ``leoPymacs`` module, allowing Leonine scripts within Emacs.

Leo 4.4.3 (June 26, 2006) and Leo 4.4.3.1 (July 3, 2006):

- The **big reorg** made the vnode and tnode classes completely independent of the rest of Leo.
- Add chapters, the ``leoBridge`` module, and spell checking.

Leo 4.4.4 (November 2, 2007): Add ``@auto``, ``menus`` and ``buttons``.

Leo 4.4.7 (February 18, 2008): Add the ``ipython`` plugin, a collaboration between EKR and Ville M. Vainio.

Leo 4.4.8 (April 6, 2008): Host Leo's forum on Google Groups.
</t>
<t tx="ekr.20080411111008.1">Leo ignores any subtree of an ``@settings`` tree whose headline starts with ``@ignore``.

You can use several other kinds of nodes to cause Leo to ignore parts of an ``@settings`` tree:

- ``@ifenv &lt;list of environments&gt;``

True if sys.env matches any of given list of environments.

- ``@ifplatform &lt;platform&gt;``

True if sys.platform matches the give platform name.

- ``@ifhostname &lt;host&gt;``

True if os.getenv('HOSTNAME') or os.getenv('COMPUTERNAME') matches the given host.

- ``@ifhostname !&lt;host&gt;``

True if ``@ifhostname &lt;host&gt;`` *doesn't* match.
</t>
<t tx="ekr.20080412124815.1"></t>
<t tx="ekr.20080527063511.1">I had a need to figure out why a part of some python code I had written was taking too long. I pulled the code into Leo and the relevant part of the outline looked something like this::

    + Main module
    -- Generate cryptographic key
    -- Hashing algorithm

etc. So I cloned just the segment I wanted to profile and pulled it under a new section::

    + Main module
    -- [clone] Generate cryptographic key
    -- Hashing algorithm

    + Profiling Experiment
    -- [clone] Generate cryptographic key

And in the body of the "Profiling experiment", I used this code::

    code_under_here = """
    @others
    """

    from timeit import Timer
    t = Timer("print my_key_generator()", code_under_here)
    print t.timeit(number = 10)

And then I hit Control-B to execute the Profiling Experiment body. This let me make adjustments to the code in the clone body and keep hitting Control-B to execute the code with the timeit module to see immediately if what I had done was making a difference.

The great thing about this was that I just used the Leo @others construct to create a wrapper around the code and did not need to litter my code with debug or profiling statements.---Kayvan
</t>
<t tx="ekr.20080730212711.52">There are several boundary cases that the update algorithm can not resolve.
For example, if a line is inserted between nodes, the algorithm can not
determine whether the line should be inserted at the end of one node or the
start of the next node. Let us call such lines **ambiguous lines**.

The algorithm *guesses* that ambiguous lines belongs at the end of a node
rather than at the start of the next node. This is usually what is
wanted--we usually insert lines at the end of a node.

Happily, **guesses don't matter**, for the following reasons:

1. The external file that results from writing the @clean x tree will be
   the same as the updated external file *no matter where* ambiguous lines
   are placed. In other words, the update algorithm is **sound**.

2. Leo reports nodes that were changed when reading any external file. The
   user can review changes to @clean and @file trees in the same way.

3. The user can permanently correct any mistaken guess. Guesses only happen
   for *newly inserted or changed* lines. Moving an ambiguous line to the
   following node will not change the external file. As a result, the
   next time Leo reads the file the line will be placed in the correct node!

This proves that @shadow and @clean are easy and safe to use. The
remaining sections of this document discuss code-level details.

</t>
<t tx="ekr.20080806211440.185"></t>
<t tx="ekr.20080806211440.188">::

    Leo 4.5 final released September 2, 2008
    @shadow
    Improved Leo's key-binding code
    Improved support for vim bindings
    Allow v.uA's in @file and @shadow nodes
    Sax-based parser for .leo files
    Unified nodes
    Reorganized Leo's drawing and focus code:
    Removed calls to c.beginUpdate and c.endUpdate
</t>
<t tx="ekr.20080813064908.2">In version 4.5, Leo changed to using a sax parser for .leo files. This can cause problems if your .leo file contains invalid characters. Bugs in previous versions of Leo permitted these bad characters to appear.

The sax parser complains that these characters are not valid in .xml files. Remove these invalid characters as follows:

1. `run Leo in a console`_, and load the .leo file. Near the bottom of the error message you will see a line like::

    SAXParseException: &lt;unknown&gt;:123:25: not well-formed (invalid token)

This line reports a bad character at character 25 of line 123.

2. Open the .leo file in an external editor. The Scite editor, https://www.scintilla.org/SciTE.html, is a good choice because it clearly shows non-printing characters. Remove the invalid character, save the .leo file.

Repeat steps 1 and 2 until all invalid characters are gone.
</t>
<t tx="ekr.20080922124033.1">k.get1Arg handles the next character the user types when accumulating a user argument from the minibuffer.  k.get1Arg handles details such as tab completion, backspacing, Ctrl-G etc.

Commands should use k.get1Arg to get the first minibuffer argument and k.getNextArg to get all other arguments.

k.get1Arg is a state machine. It has to be because it's almost always waiting for the user to type the next character. The handle keyword arg specifies the next state in the machine.

The following examples will work in any class having a 'c' ivar bound to a commander.

Example 1: get one argument from the user:

.. code-block:: python

    @cmd('my-command')
    def myCommand(self, event):
        """State 0"""
        k = self.c.k
        k.setLabelBlue('prompt: ')
        k.get1Arg(event, handler=self.myCommand1)

    def myCommand1(self, event):
        """State 1"""
        k = self.c.k
        # ----&gt; 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:

.. code-block:: python

    @cmd('my-command')
    def myCommand(self, event):
        """State 0"""
        k = self.c.k
        k.setLabelBlue('first prompt: ')
        k.get1Arg(event, handler=self.myCommand1)

    def myCommand1(self, event):
        """State 1"""
        k = self.c.k
        self.arg1 = k.arg
        k.setLabelBlue('second prompt: ')
        k.getNextArg(handler=self.myCommand2)

    def myCommand2(self, event):
        """State 2"""
        k = self.c.k
        # -----&gt; k.arg contains second argument.
        # Finish the command, using self.arg1 and k.arg.
        ...
        # Reset the minibuffer.
        k.clearState()
        k.resetLabel()
        k.showStateAndMode()

**Summary**

- The handler keyword argument to k.get1Arg and k.getNextArg specifies the next state in the state machine.

- k.get1Arg contains many optional keyword arguments. See its docstring for details.
</t>
<t tx="ekr.20081205084002.2">@language rest

New in Leo 6.8.4: Scripts can easily determine what directives are in effect at a position `p` using the following **directive getters**:

@language python
.. code-block:: python

    # All getters look for the given directive in p and its ancestors.
    encoding: str = c.getEncoding(p)
    path: str = c.getPath(p)  # A full, absolute path, using *all* ancestor @path directives.
    language: str = c.getLanguage(p)  # The nearest *unambiguous* @language directive.
    line_ending: str = c.getLineEnding(p)
    tab_width: int = c.getTabWidth(p)
    wrap_flag: bool = c.getWrap(p)
    
@language rest
**Leo 6.8.4 deprecates c.scanAllDirectives(p)**

c.scanAllDirectives returns a Python dictionary whose keys are directive names and whose values are the value in effect at position p. For example:

@language python
.. code-block:: python

    # Same as c.getPath(p)
    d = c.scanAllDirectives(p)
    d.get('path')
</t>
<t tx="ekr.20090116094356.10">``@menuat`` modifies the menu tree created by ``@menus``. This allows settings in ``myLeoSettings.leo`` to change menus without copying the entire menu tree from ``leoSettings.leo``. This ensures you don’t miss out when new things are added in the ``@menus`` in ``leoSettings.leo``, as you would if you replaced the ``@menus`` in ``leoSettings.leo`` with one in ``myLeoSettings.leo``.

``@menuat`` should occur in a ``@settings`` tree, but not as a descendant of a ``@menus`` tree. Its children are ``@menu`` and ``@item`` nodes as for the ``@menu`` setting.

The ``@menuat`` setting has 2-3 parameters in its head text::

    @menuat &lt;path&gt; &lt;action&gt; [clipboard]

The path argument specifies a **target** in the menu tree as defined by ``@menus`` and modified by earlier ``@menuat`` settings. The path takes the form::

    /entry1/entry2/entry3

Each entry is the **cleaned** name of a menu or item. Cleaned names are a name with all text except a-z and 0-9 removed and upper case letters converted to lower case. For example, specify::

    Outline-&gt;Move-&gt;Move Down

as::

     /outline/move/movedown

The action argument specifies what the menu item does. There are 5 available actions:

- **before**: Insert items and sub menus immediately before the target.
- **after**:  Insert items and sub menus immediately after the target.
- **append**: Append items and sub menus at the end of the target menu or item.
- **cut**:    Remove the target from the menu tree and save it to an internal clipboard.
- **copy**:   Copy the target to an internal clipboard. Descendants of the ``@menuat`` setting are ignored.

The cut and copy arguments ignore descendants of the ``@menuat`` setting .

The optional clipboard argument modifies the action of the before, after, and append actions. By default these actions insert the menus and items supplied as descendants of the ``@menuat`` setting. If you specify “clipboard” (without the quotes) as the source, the contents of the clipboard from a previous cut or copy action will be used instead.
</t>
<t tx="ekr.20090116094356.11">The body text contains a list of settings for a font.  For example::

    body_text_font_family = Courier New
    body_text_font_size = None
    body_text_font_slant = None
    body_text_font_weight = None

*Note*: you can use the ``show-fonts`` command to guide you in making these settings.

</t>
<t tx="ekr.20090116094356.12">The body text contains a list of shortcut specifiers.
</t>
<t tx="ekr.20090116094356.13">The body text contains a list of paths of recently opened files, one path per line. Leo writes the list of recent files to ``.leoRecentFiles.txt`` in Leo's config directory, again one file per line.
</t>
<t tx="ekr.20090116094356.14">Leo allows you to specify input modes. You enter mode x with the ``enter-x-mode`` command. The purpose of a mode is to create different bindings for keys within a mode. Often plain keys are useful in input modes.

You can specify modes with ``@mode`` nodes in ``leoSettings.leo``. ``@mode`` nodes work just like ``@shortcuts`` nodes, but in addition they have the side effect of creating the enter-&lt;mode name&gt;-mode command.

The form of this node is::

    @mode &lt;mode name&gt;

The body text contains a list of shortcut specifiers. ``@mode`` nodes work just like ``@shortcuts`` nodes, but in addition they have the side effect of creating the ``enter-&lt;mode name&gt;-mode`` command.

Notes:

- You can exit any mode using the ``keyboard-quit`` (``Control-g``) command. This is the **only** binding that is automatically created in each mode. All other bindings must be specified in the ``@mode`` node. In particular, the bindings specified in ``@shortcuts`` nodes are **not** in effect in mode (again, except for the ``keyboard-quit`` binding).

- Leo supports something akin to tab completion within modes: if you type a key that isn't bound in a mode a 'Mode' tab will appear in the log pane. This tab shows all the keys that you can type and the commands to which they are bound. The ``mode-help`` command does the same thing.

- ``@shortcuts`` nodes specify the bindings for what might be called the 'top-level' mode. These are the bindings in effect when no internal state is present, for example, just after executing the ``keyboard-quit`` command.

- The ``top_level_unbound_key_action`` setting determines what happens to unbound keys in the top-level mode. Leo ignores unbound keys in all other modes. The possibilities are 'insert', 'replace' and 'ignore'.

- The ``set-insert-mode``, ``set-overwrite-mode`` and ``set-ignore-mode`` commands alter what happens to unbound keys in the top-level mode.

- If the ``@mode`` headline contains ``::``, everything following the ``::`` is the mode prompt. For example::

    @mode abc :: xyz

Creates the ``enter-abc-mode`` command, but the prompt for the command is ``xyz``.

With all these options it should be possible to emulate the keyboard behavior of any other editor.
</t>
<t tx="ekr.20090116094356.2">When reading a .leo file, Leo looks for settings in default settings files first, then settings in personal settings files, and finally settings in local settings files.  The exact search order is:

.. Can't mix list and literal blocks.

**First**: Default settings files::

   configDir/leoSettings.leo
   homeDir/leoSettings.leo
   localDir/leoSettings.leo

**Second**: Personal settings files::

   configDir/myLeoSettings.leo
   homeDir/myLeoSettings.leo
   homeDir/&lt;machine-name&gt;LeoSettings.leo (note capitalization)
   localDir/myLeoSettings.leo

**Last**: Local settings files: the file being loaded.

Settings that appear later in this list override settings that appear earlier in this list.  This happens on a setting-by-setting basis, *not* on a file-by-file basis.  In other words, each individual setting overrides only the *corresponding* setting in previously-read files.  Reading a setting file does *not* reset all previous settings. Note that the same file might appear several times in the search list. Leo detects such duplicate file names and only loads each settings file once. Leo remembers all the settings in settings files and does not reread those settings when reading another .leo file.

**Caution**: This search order offers almost too much flexibility. This can be confusing, even for power users. It's important to choose the "simplest configuration scheme that could possibly work".  Something like:

- Use a single ``leoSettings.leo`` file for installation-wide defaults.
- Use a single ``myLeoSettings.leo`` files for personal defaults.
- Use local settings sparingly.

*Note*: it is good style to limit settings placed in ``myLeoSettings.leo`` to those settings that differ from default settings.
</t>
<t tx="ekr.20090116094356.3">You should use special care when placing default or personal settings files in **local** directories, that is, directories other than homeDir, configDir or machineDir. In particular, the value of localDir can change when Leo reads additional files. This can result in Leo finding new default and personal settings files. The values of these newly-read settings files will, as always, override any previously-read settings.

Let us say that a setting is **volatile** if it is different from a default setting. Let us say that settings file A.leo **covers** settings file if B.leo if all volatile settings in B.leo occur in A.leo. With these definitions, the **safe rule** for placing settings files in local directories is::

   Settings files in local directories should
   cover all other settings files.

Following this rule will ensure that the per-directory defaults specified in the local settings file will take precedence over all previously-read default and personal settings files. Ignore this principle at your peril.
</t>
<t tx="ekr.20090116094356.5">An ``@buttons`` tree in a settings file defines global buttons that are created in the icon area of all .leo files. All ``@button`` nodes in the ``@commands`` tree create global buttons. All ``@button`` nodes outside the commands tree create buttons local to the settings file.
</t>
<t tx="ekr.20090116094356.6">An ``@commands`` tree in a settings file defines global commands. All ``@command`` nodes in the ``@commands`` tree create global commands. All ``@command`` nodes outside the ``@commands`` tree create commands local to the settings file.
</t>
<t tx="ekr.20090116094356.7">The body text contains a list of strings, one per line. Lines starting with ``#`` are ignored.
</t>
<t tx="ekr.20090116094356.8">The body text of the ``@enabled-plugins`` node contains a list of enabled plugins, one per line. Comment lines starting with '#' are ignored. Leo loads plugins in the order they appear. **Important**: Leo handles ``@enabled-plugins`` nodes a differently from other kinds of settings. To avoid confusion, **please read the following carefully**.

As always, Leo looks for ``@enabled-plugins`` nodes in settings files in the order specified by `Search order for settings files`_. Leo will enable all plugins found in the ``@enabled-plugins`` node it finds *last* in the search order. Leo does *not* enable plugins found in any other ``@enabled-plugins`` node. In particular, **you can not specify a list of default plugins by placing that list in a settings file that appears early in the search list**. Instead, the last ``@enabled-plugins`` node found in the search list specifies all and *only* the plugins that will be enabled.

Let us distinguish two different situations. First, what Leo does when loading a file, say ``x.leo``. Second, what Leo does when loading a second file, say ``y.leo``, *from* ``x.leo``. When loading the first .leo file, Leo enables plugins from the
``@enabled-plugins`` node it finds *last* in the search order. But after plugins
have *already* been loaded and enabled, there is no way to disable previously
loaded-and-enabled plugins. But local settings files can enable additional
plugins.

To avoid confusion, I highly recommend following another kind of safe rule. We say that an ``@enabled-plugin`` node in file ``A.leo`` **covers** an ``@enabled-plugin`` node in file ``B.leo`` if all plugins specified in B's ``@enabled-plugins`` node appear A's ``@enabled-plugins`` node. The safe rule for plugins is::

  @enabled-plugin nodes in settings files in local directories
  should cover @enabled-plugins nodes in all other settings files.
</t>
<t tx="ekr.20090116094356.9">Leo creates its menus from the ``@menu``, ``@item`` and ``@popup`` nodes in the ``@menus`` tree. Within ``@menus`` trees, ``@menu`` nodes create menus and ``@item`` nodes create menu items.

The menu name always follows ``@menu``. If the menu name is 'Plugins', Leo will create the Plugins menu and populate the menu by calling the ``create-optional-menus`` hook. This creates the Plugins menu as usual. Nested ``@menu`` nodes define submenus.

The command name follows ``@item``. If the body text of an ``@item`` node exists, this body text is the menu name. Otherwise, the menu name is the command name. However, if the command name starts with a ``*``, hyphens are removed from the menu name. Menu names and command names may contain a single ampersand (``&amp;``). If present, the following character is underlined in the name. If the command name in an ``@item`` node is just a hyphen (``-``), the item represents a menu separator.

``@popup &lt;widget-name&gt;`` creates a popup menu for use by the contextmenu.py plugin. The children of this node should be ``@menu`` and ``@item`` nodes, used as with ``@menus``.
</t>
<t tx="ekr.20090116130002.1">Settings files can be found in the following directories:

- **homeDir**, the ``HOME/.leo`` directory. HOME is given by Python's HOME environment variable, or by ``os.expanduser('~')`` if no HOME environment variable exists.

- **configDir**, Leo's configuration directory: ``leo/config``.

- **machineDir**, the ``HOME/.leo/MACHINE`` directory. MACHINE is given by Python's ``HOSTNAME`` environment variable, or by Python's ``COMPUTERNAME`` environment variable if there is no ``HOSTNAME`` variable, or by the value returned by ``socket.gethostname()`` if neither environment variable exists.

- **localDir**, the directory containing the .leo file being loaded.

Leo reports in the Log pane window on startup and when opening .leo files what HOME dir is used and which settings files are read.</t>
<t tx="ekr.20090126063121.3">def createWxGui(self, fileName='', verbose=False):
    # Do NOT omit fileName param: it is used in plugin code.
    """A convenience routines for plugins to create the wx gui class."""
    app = self
    app.pluginsController.loadOnePlugin('leo.plugins.wxGui', verbose=verbose)
    if fileName and verbose:
        print('wxGui created in %s' % fileName)
</t>
<t tx="ekr.20090130144433.1">All questions are welcome at https://groups.google.com/group/leo-editor
</t>
<t tx="ekr.20090130144433.2">Please consider *asking for help* at https://groups.google.com/group/leo-editor before filing bug reports.

Please report bugs at https://bugs.launchpad.net/leo-editor

When reporting a bug, please include *all* of the following:

- The version of Leo used.
- The version of Python used.
- The platform or platforms used: Linux, Windows, MacOS.
- A clear description of the problem.
- Information sufficient to recreate the problem.

It's polite to make the bug report self contained, so that six weeks later somebody will be able to understand the report as it stands.
</t>
<t tx="ekr.20090202191501.1">def createQtGui(self, fileName='', verbose=False):
    # Do NOT omit fileName param: it is used in plugin code.
    """A convenience routines for plugins to create the Qt gui class."""
    app = self
    try:
        from leo.core.leoQt import Qt
        import leo.plugins.qt_gui as qt_gui
    except ImportError:
        Qt = None
    if Qt:
        qt_gui.init()
        if app.gui and fileName and verbose:
            print('Qt Gui created in %s' % fileName)
    else:
        print('createQtGui: can not create Qt gui.')
</t>
<t tx="ekr.20090221070927.1">#################
Leo's MIT license
#################

All parts of Leo are distributed under the following copyright. This is intended to be the same as the MIT license, namely that Leo is absolutely free, even for commercial use, including resale. There is no GNU-like "copyleft" restriction. This license is compatible with the GPL.

**Copyright 1997-2026 by Edward K. Ream. All Rights Reserved.**

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

**THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.**

################
Other Copyrights
################

.. _`Tribal Lion`: https://www.dreamstime.com/royalty-free-stock-photos-tribal-lion-image3490018
.. _`dreamstime.com`: https://www.dreamstime.com

Portions of Leo's pygments interface use code from the Jupyter qtconsole package.

These parts are are clearly marked in Leo's code as follows:

    Copyright (c) Jupyter Development Team.
    Distributed under the terms of the Modified BSD License.

Leo's `Tribal Lion`_ Logo is Copyright (c) by `dreamstime.com`_ and is used by permission.</t>
<t tx="ekr.20090223065025.3">Let:

.. code-block:: python

    w = c.frame.body.wrapper  # Leo's body pane.

Scripts can get or change the context of the body as follows:

.. code-block:: python

    w.appendText(s)                     # Append s to end of body text.
    w.delete(i,j=None)                  # Delete characters from i to j.
    w.deleteTextSelection()             # Delete the selected text, if any.
    s = w.get(i,j=None)                 # Return the text from i to j.
    s = w.getAllText                    # Return the entire body text.
    i = w.getInsertPoint()              # Return the location of the cursor.
    s = w.getSelectedText()             # Return the selected text, if any.
    i,j = w.getSelectionRange (sort=True) # Return the range of selected text.
    w.setAllText(s)                     # Set the entire body text to s.
    w.setSelectionRange(i,j,insert=None) # Select the text.

**Notes**:

- These are only the most commonly-used methods. For more information, consult Leo's source code.

- i and j are zero-based indices into the the text. When j is not specified, it defaults to i. When the sort parameter is in effect, getSelectionRange ensures i &lt;= j.

- color is a Tk color name, even when using the Gt gui.
</t>
<t tx="ekr.20090324145450.20"></t>
<t tx="ekr.20090324145450.40">::

    back-to-home
    open-quickstart-leo
    pdb
</t>
<t tx="ekr.20090619065122.8593">def createDefaultGui(self, fileName='', verbose=False):
    """A convenience routines for plugins to create the default gui class."""
    app = self
    argName = app.guiArgName
    if g.in_bridge:
        # print('createDefaultGui: g.in_bridge: %s' % g.in_bridge)
        return # The bridge will create the gui later.
    if app.gui:
        return # This method can be called twice if we had to get .leoID.txt.
    if argName in ('qt', 'qttabs'): # 2011/06/15.
        app.createQtGui(fileName, verbose=verbose)
    elif argName == 'null':
        g.app.gui = g.app.nullGui
    elif argName == 'curses':
        app.createCursesGui()
    if not app.gui:
        print('createDefaultGui: Leo requires Qt to be installed.')
</t>
<t tx="ekr.20090706042206.14718">Most people will find using @clean trees to be most useful. Use @auto-rst, @auto-vimoutline or @auto-org when using rST, vimoutline or Emacs org mode files.
</t>
<t tx="ekr.20090711120622.10447">################
Leo screen shots
################

Here are some example screen shots.  The images are reduced in size.
Click on the screen shots to see an enlarged image.

.. contents:: Contents
    :depth: 2
    :local:
</t>
<t tx="ekr.20090717112235.6007">def computeSignon(self):
    app = self
    import leo.core.leoVersion as leoVersion
    build, date = leoVersion.build, leoVersion.date
    git_info = leoVersion.git_info
    guiVersion = app.gui and app.gui.getFullVersion() or 'no gui!'
    leoVer = leoVersion.version
    n1, n2, n3, junk, junk = sys.version_info
    if sys.platform.startswith('win'):
        sysVersion = 'Windows '
        try:
            # v = os.sys.getwindowsversion()
            # sysVersion += ', '.join([str(z) for z in v])
            # peckj 20140416: determine true OS architecture
            # the following code should return the proper architecture
            # regardless of whether or not the python architecture matches
            # the OS architecture (i.e. python 32-bit on windows 64-bit will return 64-bit)
            v = platform.win32_ver()
            release, winbuild, sp, ptype = v
            true_platform = os.environ['PROCESSOR_ARCHITECTURE']
            try:
                true_platform = os.environ['PROCESSOR_ARCHITEw6432']
            except KeyError:
                pass
            sysVersion = 'Windows %s %s (build %s) %s' % (release, true_platform, winbuild, sp)
        except Exception:
            pass
    else: sysVersion = sys.platform
    branch = git_info.get('branch', None)
    commit = git_info.get('commit', None)
    if branch is None or commit is None:
        app.signon1 = 'Not running from a git repo'
    else:
        app.signon1 = 'Git repo info: branch = %s, commit = %s' % (
            branch, commit)
    app.signon = 'Leo %s' % leoVer
    if build:
        app.signon += ', build '+build
    if date:
        app.signon += ', '+date
    app.signon2 = 'Python %s.%s.%s, %s\n%s' % (
        n1, n2, n3, guiVersion, sysVersion)
</t>
<t tx="ekr.20090811090022.14452">The following screenshots show Leo's rendering pane.

.. _`reStructuredText`: https://docutils.sourceforge.io/rst.html

This pane can render `reStructuredText`_:

.. image:: screen-shots/render-rst.png
   :scale: 40%
   :alt: Rendering Pane

The rendering pane can render svg pictures, including animated pictures.
Here we see an .svg file included by reference:

.. image:: screen-shots/render-svg-movie.png
   :scale: 40%
   :alt: SVG Reference

The rendering pane can also render svg sources contained in the body pane:

.. image:: screen-shots/render-svg-sources.png
   :scale: 40%
   :alt: SVG Source

The rendering pane can show pictures, music and movies.
Here we see Leo's splash screen:

.. image:: screen-shots/render-splash-screen.png
    :scale: 40%
    :alt: Splash Screen
</t>
<t tx="ekr.20091111112709.6672">#########
Glossary
#########

.. |br| raw:: html

   &lt;br /&gt;

.. Links
.. _`Customizing Leo`:              customizing.html
.. _`git repository`:               https://github.com/leo-editor/leo-editor
.. _`Writing plugins and hooks`:    writingPlugins.html
.. _`Leo's reference`:              directives.html
.. _`leo's tutorial`:               tutorial.html

This is a short glossary of important terms in Leo's world. For more information about terms, look in the index for links to discussions in other places, especially in `Leo's Tutorial`_ and `Leo's Reference`_.

.. .. glossary::
..    :sorted:

.. contents:: Contents
    :depth: 2
    :local:</t>
<t tx="ekr.20091130111843.6787"></t>
<t tx="ekr.20091130111843.6788">.. |---| unicode:: U+02015 .. for quotes
   :trim:

###############
Leo's Tutorials
###############

.. index:: Leo's tutorial

.. _`Python`: https://www.python.org/


Leo is a full-featured outliner. Unique features make Leo a powerful IDE, Personal Information Manager, and scripting environment. The first three tutorials are for everyone:

.. toctree::
    :maxdepth: 1

    tutorial-basics
    tutorial-pim
    tutorial-rst3

The last tutorial is for programmers:

.. toctree::
    :maxdepth: 1

    tutorial-scripting

And finally, here is a list of helpful tips:

.. toctree::
    :maxdepth: 1

    tutorial-tips

Ask for help at `leo-editor &lt;https://groups.google.com/forum/#!forum/leo-editor&gt;`_.

</t>
<t tx="ekr.20100122073254.11655">This section describes the process of creating an importer for a new language. There are a set of "importers" in leoImport.py, all based on the baseScannerClass class. You can define your own importer by creating a subclass. This shouldn't be too difficult: baseScannerClass is supposed to do almost all the work. With luck, your subclass might be very simple, as with class cScanner.

**Important** As I write this, I realize that I remember very little about the code, but I do remember its general organization and the process of creating a new importer. The following should be all you need to write any importer.

This base class has three main parts:

1. The "parser" that recognizes where nodes begin and end.

2. The "code generator" the actually creates the imported nodes.

3. Checking code that ensures that the imported code is equivalent to the original code.

You should never have to change the code generators or the checking code. Confine your attention to the parser.

The parser thinks it is looking for classes, and within classes, method definitions.  Your job is to tell the parser how to do this. Let's look at part of the ctor for baseScannerClass for clues::

   # May be overridden in subclasses.
   self.anonymousClasses = [] # For Delphi Pascal interfaces.
   self.blockCommentDelim1 = None
   self.blockCommentDelim2 = None
   self.blockCommentDelim1_2 = None
   self.blockCommentDelim2_2 = None
   self.blockDelim1 = '{'
   self.blockDelim2 = '}'
   self.blockDelim2Cruft = [] # Stuff that can follow .blockDelim2.
   self.classTags = ['class',] # tags that start a tag.
   self.functionTags = []
   self.hasClasses = True
   self.hasFunctions = True
   self.lineCommentDelim = None
   self.lineCommentDelim2 = None
   self.outerBlockDelim1 = None
   self.outerBlockDelim2 = None
   self.outerBlockEndsDecls = True
   self.sigHeadExtraTokens = [] # Extra tokens valid in head of signature.
   self.sigFailTokens = []
       # A list of strings that abort a signature when seen in a tail.
       # For example, ';' and '=' in C.
   self.strict = False # True if leading whitespace is very significant.

Yes, this looks like gibberish. I do *not* remember what all these things do in detail, although obviously the names mean something. What I *do* remember is that these ivars control the operation of the startsFunction and startsClass methods and their helpers (especially startsHelper) and the methods that call them, scan and scanHelper. Most of these methods have a trace var that will enable tracing during importing.

So the strategy is simple: study startsHelper in detail, set the ivars above to make startsHelper do what you want, and trace until things work as you want.

There is one more detail. Sometimes the ivars above are not sufficient to get the job done. In that case, subclasses will override various methods of the parser, but *not* the code generator. If indentation is important, you will want to look at the Python importer. Notice that it overrides skipCodeBlock, called by startsHelper.

That's about it. It would be pointless to give you more details, because those details would lead you *away* from the process you need to follow. Having said that, feel free to ask further questions. I'll be glad to answer them.
</t>
<t tx="ekr.20100129054823.11924"></t>
<t tx="ekr.20100129054823.11931">::

    --debug
    --version
</t>
<t tx="ekr.20100211221936.7098">::

    clear-all-caches
    clear-cache
</t>
<t tx="ekr.20100506062734.11593">The mod_scripting plugin runs @scripts before plugin initiation is complete. Thus, such scripts can not directly modify plugins. Instead, a script can create an event handler for the after-create-leo-frame that will modify the plugin.

For example, the following modifies the cleo.py plugin after Leo has completed loading it:

.. code-block:: python

    def prikey(self, v):
        try:
            pa = int(self.getat(v, 'priority'))
        except ValueError:
            pa = -1

        if pa == 24:
            pa = -1
        if pa == 10:
            pa = -2

        return pa

    import types
    from leo.core import leoPlugins

    def on_create(tag, keywords):
        c.cleo.prikey = types.MethodType(prikey, c.cleo, c.cleo.__class__)

    leoPlugins.registerHandler("after-create-leo-frame",on_create)

Attempting to modify c.cleo.prikey immediately in the @script gives an AttributeError as c has no .cleo when the @script is executed. Deferring it by using registerHandler() avoids the problem.
</t>
<t tx="ekr.20100804133903.7250">.. index::
    pair: @; Glossary

``@``
    Starts a doc part. Doc parts continue until an ``@c`` or ``@code``
    directive or the end of the body text.

.. index::
    pair: ``@@ convention for headlines``; Glossary

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

.. index::
    pair: ``@&lt;file&gt; node``; Glossary

``@&lt;file&gt; node``
    A node whose headline starts with ``@asis``, ``@auto``, ``@clean``,
    ``@edit``, ``@file``, ``@shadow``, ``@thin``.
    
    We often refer to outline nodes by the directives they contain. For
    example, an ``@file`` node is a node whose headline starts with
    ``@file``.

.. index::
    pair: ``@all``; Glossary

``@all``
    Copies the body text of all nodes in an @file tree to the external file.

.. index::
    pair: @asis; Glossary

``@asis &lt;filename&gt;``
    Creates an external file containing no Leo sentinels directly from the ``@asis`` tree.

.. index::
    pair: ``@auto``; Glossary

``@auto &lt;filename&gt;``
    Imports an external file into the Leo outline, splitting the file into
    nodes if an importer exists for the give filetype.

.. index::
    pair: ``@c``; Glossary
    pair: ``@code``; Glossary

``@c and @code``
    Ends a doc part and starts a code part.

.. index::
    pair: ``@chapter``; Glossary

``@chapter``
    An ``@chapter`` tree represents a chapter.

.. index::
    pair: ``@color``; Glossary

.. index::
    pair: ``@clean``; Glossary

``@clean``
    Creates an external file without sentinels. |br|
    Section references and the ``@all`` and ``@others`` directives are valid in ``@clean`` trees.

``@color``
    Enables syntax coloring in a node and its descendants until the next
    ``@nocolor`` directive.

.. index::
    pair: ``@comment``; Glossary

``@comment``
    Sets the comment delimiters in ``@thin``, ``@file`` and ``@shadow`` files.

.. index::
    pair: ``@delims``; Glossary

``@delims``
  Sets the comment delimiters in ``@thin``, ``@file`` and ``@shadow`` files.

.. index::
    pair: ``@edit``; Glossary

``@edit &lt;filename&gt;``
    Reads an entire external file into a single node.

.. index::
    pair: ``@encoding``; Glossary

``@encoding &lt;encoding&gt;``
    Specifies the Unicode encoding for an external file.

.. index::
    pair: ``@file``; Glossary

``@file &lt;filename&gt;``
    Creates an external file containing sentinels.
    
    When writing ``@file`` trees, Leo expands section references and ``@all`` and
    ``@others`` directives.

.. index::
    pair: ``@first``; Glossary

``@first &lt;text&gt;``
    This directive inserts a line at the *very start* of an external file,
    before the first sentinel.

    The ``@first`` directive must appear at the *very start* of body text. For example::

	    @first #! /usr/bin/env python

.. index::
    pair: ``@killcolor``; Glossary

``@killcolor``
    Completely disables syntax coloring in a node, regardless of other directives.

.. index::
    pair: ``@language``; Glossary

``@language &lt;language name&gt;``
    Specifies the source language, which affects syntax coloring and the
    comments delimiters used in external files and syntax coloring.

.. index::
    pair: ``@last``; Glossary

``@last &lt;text&gt;``
    Allows you to place lines at the very end of external files, after the last sentinel.

    This directive must appear at the *very end* of body text. For example::

        @first &lt;?php
        ...
        @last ?&gt;

.. index::
    pair: ``@lineending``; Glossary

``@lineending cr/lf/nl/crlf``
    Sets the line endings for external files.

.. index::
    pair: ``@nocolor``; Glossary

``@nocolor``
    Disables syntax coloring in a node and its descendants until the next ``@color``
    directive.

.. index::
    pair: ``@nocolor-node``; Glossary

``@nocolor-node``
    Completely disables coloring for one node. Descendant nodes are not affected.

.. index::
    pair: ``@nosent``; Glossary

``@nosent``
    Creates external files without sentinels. Unlike ``@clean``, ``@nosent`` trees
    are never updated from from external files.

.. index::
    pair: ``@nowrap``; Glossary

``@nowrap``
    Disables line wrapping the Leo's body pane.

.. index::
    pair: ``@others``; Glossary

``@others``
    Copies the body text of all nodes *except* section definition nodes in an
    ``@file`` tree to the corresponding external file.

.. index::
    pair: ``@pagewidth``; Glossary

``@pagewidth &lt;n&gt;``
   Sets the page width used by the reformat-paragraph command.
   This directive also controls how ``@doc`` parts are broken into lines.

.. index::
    ..  pair: ``@path``; Glossary

``@path &lt;path&gt;``
    Sets the path prefix for relative filenames for descendant ``@&lt;file&gt;`` directives.

.. index::
    pair: ``@tabwidth``; Glossary

``@tabwidth &lt;n&gt;``
    Sets the width of tabs. Negative tab widths cause Leo to convert tabs to
    spaces.

.. index::
    pair: ``@thin``; Glossary

``@thin &lt;filename&gt;``
    A synonym for ``@file``.

.. index::
    pair: ``@wrap``; Glossary

``@wrap``
    Enables line wrapping in Leo's body pane.
</t>
<t tx="ekr.20100804133903.7251">.. index::
    pair: Body pane; Glossary

Body pane
    The pane containing the body text of the currently selected headline in the
    outline pane.

.. index::
    pair: Body text; Glossary

Body text
    The text in the body pane. That is, the contents of a node.

.. index::
    pair: Body text box; Glossary

Body text box
    A small blue box in the icon box indicating that the node contains body
    text.

.. index::
    pair: Child; Glossary

Child
    The direct descendant of a node.

.. index::
    pair: Clone; Glossary

Clone
    A copy of a tree that changes whenever the original changes.
    The original and all clones are treated equally:
    no special status is given to the "original" node.

.. index::
    pair: Clone arrow; Glossary

Clone arrow
    A small red arrow in the icon box indicating that the node is a clone.

.. index::
    pair: Code part; Glossary

Code part
    A part of a section definition that contains code. Code parts start with ``@c``
    or ``@code`` directives and continue until the next doc part.

.. index::
    pair: Contract; Glossary

Contract
    To hide all descendants of a node.
</t>
<t tx="ekr.20100804133903.7252">.. index::
    pair: Demote; Glossary

Demote
    To move all siblings that follow a node so that they become children of the node.

.. index::
    pair: Descendant; Glossary

Descendant
    An offspring of a node.  That is, a child, grandchild, etc. of a node.

.. index::
    pair: Directive; Glossary

Directive
    A keyword, preceded by an ``@`` sign, in body text that controls Leo's
    operation. The keyword is empty for the ``@`` directive.

.. index::
    pair: Dirty Node; Glossary

Dirty Node
    A node whose headline or body text has changed.

.. index::
    pair: Doc part; Glossary

Doc part
    A part of a section definition that contains comments. Doc parts start with
    ``@`` and continue until the ``@c`` directive or the end of the body text.

.. index::
    pair: Escape convention; Glossary

.. _`noweb`: https://www.cs.tufts.edu/~nr/noweb/

Escape convention
    A convention for representing sequences of characters that would otherwise
    have special meaning.
    
    **Important**: Within any ``@&lt;file&gt;`` node, any line containing matched
    ``&lt;&lt;`` and ``&gt;&gt;`` characters is a section reference. To use ``&lt;&lt;`` and
    ``&gt;&gt;`` as ordinary characters, place them on separate lines.

.. index::
    pair: Expand; Glossary

Expand
    To make the children of a node visible.

.. index::
    pair: External file; Glossary

External file
    A file outside of Leo that is connected to Leo by an ``@&lt;file&gt;`` node.

.. index::
    pair: gnx; Glossary
    pair: Global Node Index; Glossary

.. _`format of external files`: appendices.html#format-of-external-files

Gnx (Global Node Index)
    A unique, immutable string permanently associated with each vnode.
    See `format of external files`_.

.. index::
    pair: Grandchild; Glossary

Grandchild
    The child of a child of a node.
</t>
<t tx="ekr.20100804133903.7253">.. index::
    pair: Headline; Glossary

Headline
    The headline text of a node.  The part of the node visible in the outline pane.

.. index::
    pair: Hoist; Glossary
    pair: Dehoist; Glossary

Hoist &amp; dehoist
    Hoisting a node redraws the screen that node and its descendants becomes the
    only visible part of the outline. Leo prevents the you from moving nodes
    outside the hoisted outline. Dehoisting a node restores the outline.
    Multiple hoists may be in effect: each dehoist undoes the effect of the
    immediately preceding hoist.

.. index::
    pair: Icon box; Glossary

Icon box
    An icon just to the left of headline text of a node indicating whether the
    node is cloned, marked or dirty, and indicating whether the node contains
    body text.

.. index::
    pair: Log pane; Glossary

Log Pane
    The part of Leo's main window that shows informational messages from Leo. It
    also contains the Find tab, the Spell tab, the autocompletion tab.
</t>
<t tx="ekr.20100804133903.7254">.. index::
    pair: Mark; Glossary

Mark
    A red vertical line in the icon box of a node.

.. index::
    pair: Node; Glossary

Node
    The organizational unit of an outline. The combination of headline text and
    body text. Sometimes used as a synonym for tree.

.. index::
    pair: Offspring; Glossary

Offspring
    A synonym for the descendants of a node.
    The children, grandchildren, etc. of a node.

.. index::
    pair: Organizer node; Glossary

Organizer node
    A node containing no body text. Organizing nodes may appear anywhere in an
    ``@file`` tree; they do not affect the external file in any way. In particular,
    organizing nodes do not affect indentation in external files.

.. index::
    pair: Orphan node; Glossary

Orphan node
    A node that would not be copied to a external file. Orphan nodes can
    arise because an ``@file`` tree has no ``@others`` or ``@all``
    directives. Sections that are defined but not used also create orphan
    nodes.

    Leo issues a warning when attempting to write an ``@file`` tree
    containing orphan nodes, and does not save the external file. No
    information is lost; Leo saves the information in the ``@file`` tree in
    the .leo file. Leo will load the ``@file`` tree from the .leo file the
    next time Leo opens the .leo file.

.. index::
    pair: Outline; Glossary

Outline
    A node and its descendants. A tree. All the nodes of a ``.leo`` file.

.. index::
    pair: Outline order; Glossary

Outline order
    The order that nodes appear on the screen when all nodes are expanded.

.. index::
    pair: Outline pane; Glossary

Outline pane
    The pane containing a visual representation of the entire outline, or a part
    of the outline if the outline is hoisted.
</t>
<t tx="ekr.20100804133903.7255">.. index::
    pair: Parent; Glossary

Parent
    The node that directly contains a node.

.. index::
    pair: Plugin; Glossary

Plugin
    A way to modify and extend Leo without changing Leo's core code.
    See `Writing plugins and hooks`_.

.. index::
    pair: Promote; Glossary

Promote
    To move all children of a node in an outline so that they become siblings of
    the node.

.. index::
    pair: FAQ; Glossary

Reference .leo file
    ``leoeditor/leo/core/LeoPyRef.leo``
    
    This file should change only when adding new external files to Leo.
    Developers should use a local copy of LeoPyRef.leo (usually called
    ``leoPy.leo``) for their own work.

.. index::
    pair: reStructuredText; Glossary
    pair: rST; Glossary

.. _`rST primer`: https://docutils.sourceforge.net/docs/user/rst/quickstart.html


reStructuredText (rST)
    A markup language for creating .html, or LaTeX output files. See the `rST primer`_.

.. index::
    pair: Root; Glossary

Root
    The first node of a .leo file, outline, suboutline or @&lt;file&gt; tree.
</t>
<t tx="ekr.20100804133903.7256">.. index::
    pair: Section; Glossary

Section
    A fragment of text that can be incorporated into external files.

.. index::
    pair: Section definition; Glossary

Section definition
    The body text of a section definition node.

.. index::
    pair: Section definition node; Glossary

Section definition node
    A node whose headline starts with a section name and whose body text defines
    a section.

.. index::
    pair: Section name; Glossary

Section name
    A name between ``&lt;&lt;`` and ``&gt;&gt;``. Section names may contain any character
    except newlines and ``&gt;&gt;``.

.. index::
    pair: Section reference; Glossary

Section reference
    A section name appearing in a code part. When writing to an external file,
    Leo replaces all references by their definitions.

.. index::
    pair: Sentinel; Glossary
    pair: Sentinel Lines; Glossary

Sentinel
    Comment lines in external files used to represent Leo's outline structure.
    Such lines start with an @ following the opening comment delimiter.
    Sentinels embed outline structure into external files.

    **Do not alter sentinel lines**. Doing so can corrupt the outline structure.

.. index::
    pair: Setting; Glossary

Settings
    Plugins and other parts of Leo can get options from ``@settings`` trees,
    outlines whose headline is ``@settings``.

    When opening a .leo file, Leo looks for ``@settings`` trees in the
    outline being opened and also in various leoSettings.leo files.

    ``@settings`` trees allow plugins to get options without any further
    support from Leo's core code. For a full discussion of ``@settings``
    trees, see `Customizing Leo`_.

.. index::
    pair: Sibling; Glossary

Sibling
    Nodes with the same parent. Siblings of the root node have the hidden root
    node as their parent.

.. index::
    pair: Target language; Glossary

Target language
    The language used to syntax color text. This determines the default comment
    delimiters used when writing external files.

.. index::
    pair: Tree; Glossary

Tree
    An outline. A node and its descendants.

.. index::
    pair: Underindented Line; Glossary

Underindented line
    A line of body text that is indented less then the starting line of the
    class, method or function in which it appears. Leo outlines can not
    represent such lines exactly: every line in an external file will have at
    least the indentation of any unindented line of the corresponding node in
    the outline.

.. index::
    pair: uA; Glossary

.. _`extensible attributes`: customizing.html#adding-extensible-attributes-to-nodes-and-leo-files

uA
    uA's (User Attributes) are persistent Python dicts that allows scripts
    and plugins to associate additional data with each node. See
    `extensible attributes`_.

.. index::
    pair: View node; Glossary

View node
    A node that represents a view of an outline. View nodes are typically
    ordinary, non-cloned nodes that contain cloned descendant nodes. The cloned
    descendant nodes comprise most of the data of the view. Other non-cloned
    nodes may add additional information to the view.
</t>
<t tx="ekr.20100804133903.7262">
This section is a reference guide for all other Leo directives, organized alphabetically.

Unless otherwise noted, all directives listed are valid only in body text, and they must start at the leftmost column of the node.

.. glossary::
     :sorted:

.. index::
    pair: @; Reference
.. index::
    pair: @doc; Reference
.. index::
    pair: Doc part; Reference

``@ and @doc``

    These directives start a doc part. ``@doc`` is a synonym for ``@``. Doc parts
    continue until an ``@c`` directive or the end of the body text. For example::

        @ This is a comment in a doc part.
        Doc parts can span multiple lines.
        The next line ends the doc part
        @c

    When writing external files, Leo writes doc parts as comments.

    Leo does not recognize ``@`` or ``@doc`` in ``@asis`` trees or when the ``@all`` or
    ``@delims`` directives are in effect.

.. index::
    pair: @c; Reference
.. index::
    pair: @code; Reference

``@c and @code``

    Ends any doc part and starts a code part.

    ``@code`` is a deprecated synonym for ``@c``.

    Leo does not recognize this directive in ``@asis`` trees.

.. index::
    pair: @chapter; Reference

.. _`Using Chapters`: commands.html#using-chapters

 ``@chapter``

    An ``@chapter`` tree represents a chapter. For full details, see `Using Chapters`_.

    These directives must appear in the node's headline.

.. index::
    pair: @encoding; Reference

``@encoding &lt;encoding&gt;``

    Specifies the Unicode encoding for an external file. For example::

        @encoding iso-8859-1

    When reading external files, the encoding given must match the encoding
    actually used in the external file or "byte hash" will result.

.. index::
    pair: @first; Reference

``@first &lt;text&gt;``

    Places lines at the very start of an external file, before any Leo
    sentinels. ``@first`` lines must be the *very first* lines in an ``@&lt;file&gt;`` node.
    More then one ``@first`` lines may appear.

    This creates two first lines, a shebang line and a Python encoding line::

        @first #! /usr/bin/env python
        @first # -*- coding: utf-8 -*-

    Here is a perl example::

        @first #!/bin/sh -- # perl, to stop looping
        @first eval 'exec /usr/bin/perl -w -S $0 ${1+"$@"}'
        @first     if 0;

``@ignore``

    Tells Leo to ignore the subtree in which it appears.

    In the body text of most top-level @&lt;file&gt; nodes, the ``@ignore`` directive
    causes Leo not to write the tree. However, Leo ignores ``@ignore`` directives
    in ``@asis`` trees.

    Plugins and other parts of Leo sometimes ``@ignore`` for their own purposes. For
    example, Leo's unit testing commands will ignore trees containing ``@ignore``.
    In such cases, the ``@ignore`` directive may appear in the headline or body
    text.

.. index::
    pair: @language; Reference

..  # A script to generate the list of languages
..  import glob
..  dir_ = g.os_path_finalize_join(g.app.loadDir, '..', 'modes')
..  aList = sorted(glob.glob('%s/*.py' % dir_))
..  s = ', '.join([g.shortFileName(z)[: -3] for z in aList])
..  g.es(s)

``@language &lt;language name&gt;``

    Specifies the language in effect, including comment delimiters.
    If no ``@language`` directive is in effect, Leo uses the defaults specified
    by the ``@string target-language`` setting.

    A node may contain multiple ``@language`` directives.

    The valid language names include the following: actionscript, ada95, ahk, antlr, apacheconf, apdl, applescript, asciidoc, asp, aspect_j, assembly_macro32, assembly_mcs51, assembly_parrot, assembly_r2000, assembly_x86, awk, b, batch, bbj, bcel, bibtex, c, chill, clojure, cobol, coldfusion, cplusplus, csharp, css, cython, d, dart, doxygen, eiffel, embperl, erlang, factor, forth, fortran, fortran90, foxpro, gettext, groovy, haskell, haxe, html, i4gl, icon, idl, inform, ini, inno_setup, interlist, io, java, javascript, jhtml, jmk, jsp, kivy, latex, lilypond, lisp, lotos, lua, mail, makefile, maple, matlab, md, ml, modula3, moin, mqsc, netrexx, nqc, nsi, nsis2, objective_c, objectrexx, occam, omnimark, pascal, patch, perl, php, phpsection, pike, pl1, plain, plsql, pop11, postscript, povray, powerdynamo, prolog, pseudoplain, psp, ptl, pvwave, pyrex, python, r, rebol, redcode, rest, rhtml, rib, rpmspec, rtf, ruby, rview, sas, scala, scheme, sdl_pr, sgml, shell, shellscript, shtml, smalltalk, smi_mib, splus, sqr, squidconf, ssharp, swig, tcl, tex, texinfo, text, tpl, tsql, uscript, vbscript, velocity, verilog, vhdl, xml, xsl, yaml, zpt.

    **Note**: Shell files have comments that start with #.

    Case is ignored in the language names. For example, the following are
    equivalent::

        @language html
        @language HTML

    The ``@language`` directive also controls syntax coloring. For language x, the
    file leo/modes/x.py describes how to colorize the language. To see the
    languages presently supported, look in the leo/modes directory. There are
    over 100 such languages.

.. index::
    pair: @last; Reference

``@last &lt;text&gt;``

    Places lines at the very end of external files.

    This directive must occur at the *very end* of top-level @&lt;file&gt; nodes. More
    than one ``@last`` directive may exist. For example::

        @first &lt;?php
        ...
        @last ?&gt;

    Leo does not recognize ``@last`` directive in ``@asis`` trees.

.. index::
    pair: @lineending; Reference

``@lineending cr/lf/nl/crlf``

    Sets the line endings for external files.
    This directive overrides the ``@string output_newline`` setting.

    The valid forms of the ``@lineending`` directive are:

    ========================   ======================================================
    \@lineending nl            The default, Linux.
    ------------------------   ------------------------------------------------------
    \@lineending cr            Mac
    ------------------------   ------------------------------------------------------
    \@lineending crlf          Windows
    ------------------------   ------------------------------------------------------
    \@lineending lf            Same as 'nl', not recommended
    ------------------------   ------------------------------------------------------
    \@lineending platform      Same as platform value for output_newline setting.
    ========================   ======================================================

.. index::
    pair: @nowrap; Reference

``@nowrap``

    Disables line wrapping the Leo's body pane.

    Only the first ``@wrap`` or ``@nowrap`` directive in a node has any effect.

    ``@nowrap`` may appear in either headlines or body text.

.. index::
    pair: @pagewidth; Reference

``@pagewidth &lt;n&gt;``

   Sets the page width used by the ``reformat-paragraph`` command.
   This directive also controls how ``@doc`` parts are broken into lines.
   &lt;n&gt; should be a positive integer.  For example::


      @pagewidth 100

  The ``@pagewidth`` directive overrides the ``@int page_width`` setting.

.. index::
    pair: @persistence; Reference

``@persistence``

    With ``@clean`` and ``@file``, Leo can preserve **persistent data**,
    each node's **gnx** (global node index) **uA**, (user attributes).

    By default, Leo's importers preserve neither gnx's nor uA's. However,
    if an outline contains an ``@persistence`` node, Leo will save data in
    the ``@persistence`` tree that allows Leo to recover gnx's and uA's
    when re-reading ``@auto`` files. This allows clone links and uA's
    to persist.

    ``@persistence`` is an optional feature. The stored data is akin to
    bookmarks. The data can "break" (become inaccessible) if the structure
    (including class/method/function names) changes. However, the data will
    typically break infrequently. To disable this feature, just delete an
    existing ``@persistence`` node or change ``@persistence`` to
    ``@@persistence``.

.. index::
    pair: @tabwidth; Reference
.. index::
    pair: Negative tab width; Reference

``@tabwidth &lt;n&gt;``

  Sets the width of tabs.
  Negative tab widths cause Leo to convert tabs to spaces.

.. index::
    pair: @wrap; Reference

``@wrap``

    Enables line wrapping in Leo's body pane.

    Only the first ``@wrap`` or ``@nowrap`` directive in a node has any effect.

    ``@wrap`` may appear in either headlines or body text.
</t>
<t tx="ekr.20100805171546.4412">This section contains files used to generate Leo's web site,
including Leo's home page.
</t>
<t tx="ekr.20100806170836.4392">.. From directives reference

.. index::
    pair: @&lt;file&gt;; Reference

This section discusses the @&lt;file&gt; directives. These directives create or import external files.

``@&lt;file&gt;`` nodes create external files::

    @asis &lt;filename&gt;        write only, no sentinels, exact line endings
    @auto &lt;filename&gt;        recommended
    @clean &lt;filename&gt;       recommended
    @edit &lt;filename&gt;        @edit node contains entire file
    @file &lt;filename&gt;        recommended
    @nosent &lt;filename&gt;      write only, no sentinels

**Note**: ``@file``, ``@clean`` and ``@auto`` are the recommended ways of creating external files. ``@asis`` and ``@nosent`` are for special occasions.

**Note**: All these directive must appear in headlines.

The following table compares the various ways of creating external files. Later sections provide more details::

                             Sections &amp;   File data in
    @&lt;file&gt; kind  Sentinels?  @others?    .leo file?    Notes             
    ------------  ---------- -----------  ------------  -----
    @asis            no         no           yes
    @auto            no         yes          no         1, 2
    @auto-xx         no         yes          no         1, 2
    @clean           no         yes          yes     
    @edit            no         no           no    
    @file            yes        yes          no
    @nosent          no         yes          yes

**Note 1**: ``@auto`` nodes read files using language-specific importers.
By default, the file's extension determines the importer::

    Extensions                  Importer
    ----------                  --------
    .c, .cc, .c++, .cpp,.cxx    C
    .cs', .c#'                  C Sharp
    .el                         Elisp
    .h, .h++                    C
    .html, .htm                 HTML
    .ini                        Config file
    .ipynb                      Jupyter notebook
    .java                       Java
    .js                         JavaScript
    .md                         Markdown
    .org                        Org Mode
    .otl                        Vim outline
    .pas                        Pascal
    .php                        PHP
    .py, .pyi, .pyw             Python
    .rest, .rst                 reStructuredText
    .ts                         TypeScript
    .xml                        XML

**Note 2**: You can also specify importers *explicitly* as follows::

    @auto-xxx           Importer
    ---------           --------
    @auto-ctext         ctext
    @auto-markdown      markdown
    @auto-md            markdown
    @auto-org           org-mode
    @auto-org-mode      org-mode
    @auto-otl           vimoutline
    @auto-vim-outline   vimoutline      
    @auto-rst           reStructuredText

**Important**: The importers/exporters for markdown, org-mode, reStructuredText and vimoutline files automatically generate section heading of the appropriate level. Body text of the top-level ``@auto`` node is ignored.
</t>
<t tx="ekr.20100806170836.4393">.. index::
    pair: @asis; Reference

The ``@asis`` directive creates an external file without sentinels and without any expansions.

Use this directive only when you must have complete control over every character of the external file. When writing ``@asis`` nodes, writes the body text of all nodes in outline order. Leo writes the body text *as is*, without recognizing section definitions, without expanding section references, and without treating directives specially in any way. In particular, Leo copies all directives, including ``@`` or ``@c`` directives, to the external file as text. **Warning**: Because the external file contains no sentinels, ``@asis`` trees can not be updated from changes made outside of Leo. If you want this capability, use ``@clean`` instead.

.. index::
    pair: @@ convention in @asis trees; Reference

**The @@ convention**: Within ``@asis`` trees only, if a headline starts with @@, Leo writes everything in the headline following the @@ just before the corresponding body text.

Files created from ``@asis`` trees contain *nothing* not contained in body text (or
@@ headlines). In particular, if body text does not end in a newline, the first
line from the next node will concatenated to the last line of the preceding node.

Within ``@asis`` trees, Leo writes no sentinels to the external file, so Leo can not update the outline using changes to the external file. When reading .leo files, Leo does *not* read external files created from ``@asis`` nodes. Instead, all data in an ``@asis`` tree is stored in the .leo file.

Within ``@asis`` trees, Leo recognizes the ``@ignore`` directive only in the *ancestors* of ``@asis`` nodes. This allows you to use the ``@ignore`` directive to prevent Leo from writing ``@asis`` trees.

**Note**: ``@file-asis`` and ``@silent`` are deprecated synonyms for ``@asis``.
</t>
<t tx="ekr.20100806170836.4395">.. index::
    pair: @edit; Reference

The ``@edit`` directive imports an external file into a single node.

When reading ``@edit`` nodes, Leo reads the entire file into the ``@edit`` node. Lines
that look like sentinels will be read just as they are.

When writing ``@edit`` nodes, ``@edit`` nodes must not have children and section
references and ``@others`` are not allowed.
</t>
<t tx="ekr.20100806170836.4396">.. index::
    pair: @auto; Reference

The ``@auto`` directive imports an external file into a tree of nodes.

``@auto`` trees allow people to use Leo in collaborative environments without using sentinels in external files. Even without sentinels, ``@auto`` trees can change when the corresponding external file changes outside of Leo.

.. index::
    pair: Importer; Reference

``@auto`` nodes read files using language-specific importers.
By default, the file's extension determines the importer::

    Extensions                  Importer
    ----------                  --------
    .c, .cc, .c++, .cpp,.cxx    C
    .cs', .c#'                  C Sharp
    .el                         Elisp
    .h, .h++                    C
    .html, .htm                 HTML
    .ini                        Config file
    .ipynb                      Jupyter notebook
    .java                       Java
    .js                         JavaScript
    .md                         Markdown
    .org                        Org Mode
    .otl                        Vim outline
    .pas                        Pascal
    .php                        PHP
    .py, .pyi, .pyw             Python
    .rest, .rst                 reStructuredText
    .ts                         TypeScript
    .xml                        XML

You can also specify importers *explicitly* as follows::

    @auto-xxx           Importer            Notes
    ---------           --------            -----
    @auto-ctext         ctext           
    @auto-markdown      markdown            1, 2
    @auto-md            markdown            1, 2
    @auto-org           org-mode            1, 3
    @auto-org-mode      org-mode            1, 3
    @auto-otl           vimoutline          1, 4
    @auto-vim-outline   vimoutline          1, 4      
    @auto-rst           reStructuredText    1, 5

.. _`org-mode`:         https://en.wikipedia.org/wiki/Org-mode
.. _`Emacs`:            emacs.html#using-org-mode-org-files-in-leo
.. _`markdown`:         https://en.wikipedia.org/wiki/Markdown
.. _`reStructuredText`: https://docutils.sourceforge.net/rst.html
.. _`vim outline`:      https://www.vim.org/scripts/script.php?script_id=3515
.. _`vim`:              vimBindings.html#using-vimoutline-otl-files-in-leo

**Note 1**: The importers/exporters for markdown, org-mode, reStructuredText and vimoutline files automatically generate section heading of the appropriate level. Body text of the top-level ``@auto`` node is ignored.

**Note 2**: See the official `Markdown`_ documentation.

**Note 3**: See Leo's `Emacs`_ documentation and Emacs's `org-mode`_ documentation.

**Note 4**: See Leo's `vim`_ documentation and Vim's `vim outline`_ documentation.

**Note 5**: See the `reStructuredText`_ documentation.
</t>
<t tx="ekr.20100806170836.4398">The ``@color``, ``@killcolor``, ``@nocolor`` and ``@nocolor-node`` directives control how
Leo colors text in the body pane.

.. index::
    pair: Ambiguous node; Reference

These directives typically affect the node in which they appear and all descendant nodes. Exception: an **ambiguous node**, a node containing both ``@color`` and ``@nocolor`` directives, has no effect on how Leo colors text in descendant nodes.

.. glossary::
    :sorted:

.. index::
    pair: @color; Reference

``@color``

    Enables syntax coloring until the next ``@nocolor`` directive.

.. index::
    pair: @killcolor; Reference

``@killcolor``

    Disables syntax coloring in a node, overriding all ``@color``, ``@nocolor`` or
    ``@nocolor-node`` directives in the same node.

.. index::
    pair: @nocolor; Reference

``@nocolor``

    Disables syntax coloring until the next ``@nocolor`` directive.

.. index::
    pair: @nocolor-node; Reference

``@nocolor-node``

    Disables coloring for only the node containing it. The ``@nocolor-node``
    directive overrides the ``@color`` and ``@nocolor`` directives within the same
    node.
</t>
<t tx="ekr.20100806170836.4399">.. _`Mulder/Ream update algorithm`: appendices.html#the-mulder-ream-update-algorithm
.. _`Scripting miscellany`: scripting-miscellany.html
.. _`check-nodes`: commands.html#syncing-clean-files

.. index::
    pair: @clean; Reference

The ``@clean &lt;filename&gt;`` creates an external file without sentinel lines.
``@clean`` trees will probably be the most convenient way of creating and
accessing external files for most people.

When writing an ``@clean`` tree, Leo expands section references, ``@all`` and
``@others`` directives, but Leo writes no sentinels to the external file.

When reading an ``@clean`` tree, Leo propagates changes from the external file
to the ``@clean`` tree using the `Mulder/Ream update algorithm`_.

**Note**: The ``@bool force_newlines_in_at_nosent_bodies`` setting controls whether
Leo writes a trailing newline if non-empty body text does not end in a newline.
The default is True.

**Note**: The `check-nodes`_ command helps sync ``@clean`` trees when
collaborating with others.</t>
<t tx="ekr.20100806170836.4402">.. index::
    pair: @shadow; Reference
    pair: Private file; Reference
    pair: Public file; Reference

**Important**: As of Leo 5.1, ``@shadow`` is **deprecated** Use ``@clean`` instead. ``@clean`` is faster than ``@shadow`` and requires no hidden files.

The ``@shadow`` directive creates *two* external files, a **public** file without sentinels, and a **private** file containing sentinels.

.. _`Mulder/Ream update algorithm`: appendices.html#the-mulder-ream-update-algorithm

When reading an ``@shadow`` node, Leo uses the `Mulder/Ream update algorithm`_ to compare the public and private files, then updates the outline based on changes to the *public* file.

Leo can do an initial import of ``@shadow`` trees by parsing the corresponding public file, exactly as is done for ``@auto`` nodes.
</t>
<t tx="ekr.20100806170836.4403">.. index::
    pair: @file; Reference
    pair: @thin; Reference

The ``@file`` directive creates an external file containing sentinels. When writing
@file trees, Leo expands section references and ``@all`` and ``@others`` directives.

When reading external files created by ``@file``, the sentinels allow Leo to
recreate all aspects of the outline. In particular, Leo can update the
outline based on changes made to the file by another editor. 

**Important**: ``@file`` is the recommended way to create and edit most
files. In particular, using ``@file`` nodes is **highly recommended**
when sharing external files in a collaborative environment. The ``@all``
directivive is designed for "catch-all" files, like todo.txt or
notes.txt or whatever. Such files are assumed to contain a random
collection of nodes, so there is no language in effect and no real
comment delimiters.

The ``@thin`` directive is a synonym for ``@file``.

Prior to Leo 4.7, ``@file`` worked differently from ``@thin``. This should not be
a problem: Leo 4.7 can read all external files written by Leo 4.6.
</t>
<t tx="ekr.20100806170836.4408">These directives alter how Leo represents data in external files. They are **dangerous**--mistakes in using these sentinels can make it impossible for Leo to read the resulting external file. Use them with care!

Nevertheless, these sentinels can be useful in special situations.

.. glossary::
    :sorted:

.. index::
    pair: @comment; Reference

``@comment &lt;1, 2 or three comment delims&gt;``

    Sets the comment delimiters in ``@file`` and ``@shadow`` files.
    **Important**: Use ``@comment`` for unusual situations only. In most cases, you
    should use the ``@language`` directive to set comment delimiters.

    The ``@comment`` directive may be followed by one, two or three delimiters,
    separated by whitespace. If one delimiter is given, it sets the delimiter
    used by single-line comments. If two delimiters are given, they set the
    block comment delimiter. If three delimiters are given, the first sets the
    single-line-comment delimiter, and the others set the block-comment
    delimiters.

    Within these delimiters, underscores represent a significant space, and
    double underscores represent a newline. Examples::

        @comment REM_
        @comment __=pod__ __=cut__

    The second line sets PerlPod comment delimiters.

    **Warning**: the ``@comment`` and ``@delims`` directives **must not** appear in
    the same node. Doing so may create a file that Leo can not read.

    **Note**: ``@language`` and ``@comment`` may appear in the same node, provided
    that ``@comment`` appears *after* the ``@language`` directive: ``@comment`` overrides
    ``@language``.

    The ``@comment`` directive must precede the first section name or ``@c``
    directive.

    There are situations where using ``@delims`` or ``@comment`` is not
    avoidable or impractical to add new language definition, and including
    it causes the resulting file to be invalid. In place of delimiter
    definition, use ``@0x`` + delimiter encoded in hexadecimal. The
    hexadecimal part must be acceptable input to binascii.unhexlify(),
    otherwise whole directive will be ignored. Use
    binascii.hexlify('my-delimiter') to generate it. Decoded delimiters are
    not checked for validity (such as, UTF-8) and whether they do not clash
    with Leo format (like newline or NUL characters)!

    Example::

        @comment @0x3c212d2d2120 @0x202d2d3e

    for GenshiXML is the same definition as:: 

        @comment &lt;!--!_ _--&gt;

    but the latter would cause XML parsing error on the ``@comment`` line.

.. index::
    pair: @delims; Reference

``@delims &lt;1 or 2 comment delims&gt;``

    Sets comment delimiters in external files containing sentinel lines.

    The ``@delims`` directive requires one or two delimiters, separated by
    whitespace. If one delimiter is present it sets the single-line-comment
    delimiter. If two delimiters are present they set block comment delimiters.

    This directive is often used to place Javascript text inside XML or HTML
    files. Like this:
    
    .. code-block:: python

        @delims /* */
        Javascript stuff
        @delims &lt;-- --&gt;
        HTML stuff

    **Warning**: you **must** change back to previous delimiters using another
    ``@delims`` directive. Failure to change back to the previous delimiters will
    thoroughly corrupt the external file as far as compilers, HTML renderers,
    etc. are concerned. Leo does not do this automatically at the end of a node.

    **Warning**: the ``@comment`` and ``@delims`` directives **must not** appear in
    the same node. Doing so may create a file that Leo can not read.

    **Note**: The ``@delims`` directive can not be used to change the comment
    strings at the start of the external file, that is, the comment strings for
    the ``@+leo sentinel`` and the initial ``@+body`` and ``@+node`` sentinels.
</t>
<t tx="ekr.20100806170836.4411">These control how Leo places text when writing external files. They are two of the most important directives in Leo.

.. glossary::
    :sorted:

.. index::
    pair: @all; Reference

``@all``

    Copies *all* descendant nodes to the external file. Use ``@all`` to place
    unrelated data in an external file.

    The ``@all`` directive is valid only in the body of ``@file`` trees.

    Within the range of an ``@all`` directive, Leo ignores the ``@others`` directive
    and section references, so Leo will not complain about orphan nodes.

    The ``@all`` directivive is designed for "catch-all" files, like
    todo.txt or notes.txt or whatever. Such files are assumed to
    contain a random collection of nodes, so there is no language in
    effect and no real comment delimiters.

.. index::
    pair: @others; Reference

``@others``

    Writes the body text of all unnamed descendant into the external file, in
    outline order.

    Whitespace appearing before ``@others`` directive adds to the indentation of
    all nodes added by the ``@others`` directive.

    A single node may contain only one ``@others`` directive, but descendant nodes
    may have other ``@others`` directives.
</t>
<t tx="ekr.20100821182153.4343">.. This file must be located in the leo/doc/html.

######
Slides
######

This is the front page for various slide shows about Leo.

.. toctree::
    :maxdepth: 1

    slides/clones-and-views/clones-and-views
    slides/external-files/external-files
    slides/basics/basics
    slides/scripting-leo/scripting-leo
    slides/minibuffer/minibuffer
</t>
<t tx="ekr.20100831090251.5838"></t>
<t tx="ekr.20100831090251.5840">def createCursesGui(self, fileName='', verbose=False):
    app = self
    app.pluginsController.loadOnePlugin('leo.plugins.cursesGui', verbose=verbose)
</t>
<t tx="ekr.20100907092300.4440"></t>
<t tx="ekr.20100907092300.4441">Path to inkscape template file
</t>
<t tx="ekr.20100907092300.4442">Path to Inkscape executable
</t>
<t tx="ekr.20101009114830.4723">@nocolor-node

Formerly, this had to be on because the expansion bits
of @screenshot trees were significant.

Happily, this is no longer true.

True (recommended):
    Write "E" attribute bits in &lt;v&gt; elements.
    Leo outlines will record the expansion state of all nodes.

False:
    (Good for files like unitTest.leo)
    Suppress "E" attribute bits in &lt;v&gt; elements.
    Only the ancestors of the presently selected node will
    be expanded when Leo opens an outline.
</t>
<t tx="ekr.20101009114830.4724"></t>
<t tx="ekr.20101025080245.5791">##################
What's New in Leo
##################

.. contents:: Contents
    :depth: 0
    :local:
</t>
<t tx="ekr.20101025080245.5798"></t>
<t tx="ekr.20101025080245.5799"></t>
<t tx="ekr.20101025080245.5805"></t>
<t tx="ekr.20101025080245.6086">Leo 4.6 (July 15, 2009) and Leo 4.6.1 (July 30, 2009):

- Use Qt by default.
- Add ``@auto-rst`` and ``@edit``.
</t>
<t tx="ekr.20101025080245.6087">Leo 4.7: February 23, 2010. Leo 4.7.1: February 26, 2010.

Leo 4.7 accomplishes something I long thought to be impossible: the unification of vnodes and tnodes. tnodes no longer exist: vnodes contain all data. The Aha that made this possible is that iterators and positions allow a single node to appear in more than one place in a tree traversal.

This was one of the most significant developments in Leo's history. At last the endless confusion between vnodes and tnodes is gone. At the most fundamental level, Leo's data structures are as simple as possible. This makes them as general and as powerful as possible!

- A single code base runs on both Python 2 and 3.
- Leo automatically converts from old-style to new-style sentinels.
</t>
<t tx="ekr.20101025080245.6089">Leo 4.8 (November 26, 2010):

This release simplified Leo's sentinels as much as possible. This version also added "Resurrected" and "Recovered" nodes. These nodes protect against data loss, and also implicitly warn when unusual data-changing events occur. Creating this scheme was yet another chapter in the epic saga of error recovery in Leo.</t>
<t tx="ekr.20101026082911.5538">The update algorithm guarantees *only* that writing an updated @clean outline will generate the updated **public** file.  **Ambiguous lines** could be placed either at the end of one node or the beginning of the following nodes. The update algorithm *guesses* that such lines should be placed at the end of the previous node.

Happily, guesses are not serious. Once you move an ambiguous node and save the Leo file, the update algorithm will not have to guess where the line belongs the next time Leo reads the @clean files.
</t>
<t tx="ekr.20101111175617.14683">def getDocString(self, p):
    '''Return the docstring of the @&lt;file&gt; node p.'''
    trace = False
    if trace: g.trace('='*20)
    for p2 in p.self_and_subtree():
        s = p2.b
        if trace: g.trace(p2.h)
        for tag in ("'''",'"""'):
            i = s.find(tag)
            if i &gt; -1:
                j = s.find(tag,i+3)
                if j &gt; -1:
                    if trace: g.trace('**found**',p2.h,'\n',s)
                    return s[i+3:j]
    else:
        return ''
</t>
<t tx="ekr.20101111175617.24328">def openLeoPlugins(self):
    # Plugins are now found in leoPy.leo.
    fn = g.os_path_finalize_join(g.app.loadDir,'..','plugins','leoPy.leo')
    c = g.openWithFileName(fn, old_c=self.c, gui=None,)
    if not c:
        g.error('can not open leoPy.leo')
    return c
</t>
<t tx="ekr.20101111175617.5037">'''
Creates an outline containing most docstrings from Leo's plugins.

Some docstrings are suppressed.
'''

@others
controller(c).run()
@language python
</t>
<t tx="ekr.20101111175617.56915">class controller:

    def __init__ (self,c):
        self.c = c

    @others
</t>
<t tx="ekr.20101111175617.5787">def run(self):
    c = self.c
    new_c = self.openLeoPlugins()
    if not new_c: return
    # Create the top-level output node.
    output = c.p.insertAfter()
    output.h = 'get-docstrings-output'
    output.b = '@language rest\n'
    # Scan the descendants of the Plugins node.
    root = g.findNodeAnywhere(new_c,'Plugins')
    if root:
        self.createSummary(output,root)
        self.createDocs(output,root)
        g.app.selectLeoWindow(c)
        c.redraw()
    else:
        g.error('no Plugins node')
</t>
<t tx="ekr.20101112045055.13354">def createSummary (self,output,root):

    summary = output.insertAsLastChild()
    summary.h = 'Summary'
    result = []
    for p in root.children():
        if self.allowDir(p):
            for p2 in p.subtree():
                if self.allowFile(p2):
                    h = p2.anyAtFileNodeName()
                    s = self.getDocString(p2)
                    s = self.getFirstParagraph(s).rstrip()
                    if s:
                        if not s.endswith('.'): s = s + '.'
                        result.append('%s\n%s\n\n' % (h,s))
    # Sort by plugin name, ignoring case.
    def lower(s): return s.lower()
    result.sort(key=lower)
    summary.b = ''.join(result)
</t>
<t tx="ekr.20101112045055.13355">def createDocs (self,output,root):

    trace = False
    for p in root.children():
        if self.allowDir(p):
            if trace: print('\n**',p.h)
            child = output.insertAsLastChild()
            child.h = p.h
            for p2 in p.subtree():
                if self.allowFile(p2):
                    h = p2.anyAtFileNodeName()
                    s = self.getDocString(p2)
                    if trace: print('%5s %s' % (len(s),h))
                    child2 = child.insertAsLastChild()
                    child2.h = h
                    child2.b = "%s\n\n" % s.strip()
</t>
<t tx="ekr.20101112045055.13356">def allowDir (self,p):

    '''Return True if we should allow scan of directory p.'''

    aList = (
        # Suppressed directories.
        'Examples','Experimental',
        'Dyna plugins by e',
        'Gui plugins','Testing',
    )
    return p.h not in aList and not p.h.startswith('  ')
</t>
<t tx="ekr.20101112045055.13357">def getFirstParagraph (self,s):

    lines =  g.splitLines(s.strip())
    if not lines: return ''
    result = []
    for s in lines:
        if s.strip():
            result.append('   '+s)
        else:
            break
    return ''.join(result)
</t>
<t tx="ekr.20101112222250.5322">def allowFile (self,p):

    '''Return True if we should allow scan of a file at p.'''

    aList = (
        # Suppressed files.
        # '@file bookmarks.py',
        '@file rst3.py',            # Replaced by core rst3 command.
        '@file stickynotes_plus.py', # Experimental version of stickynotes
        '@file testnode.py',        # Replaced by @edit.
        # These all depend on old plugins_manager.py.
        '@file autotrees.py', 
        '@file old_plugin_manager.py',
        '@file leoupdate.py',
        # These are used only by autotrees.py.
        r'@file trees\doc.py',
        r'@file trees\news.py',
        r'@file trees\remote.py',
        r'@file trees\rss.py',
        r'@file trees\test.py',
    )
    return p.h not in aList and p.isAnyAtFileNode() and p.h.endswith('.py')
</t>
<t tx="ekr.20101113063552.9398">.. Complete as of Leo 5.5.

``active_path.py``
    Synchronizes ``@path`` nodes with folders.
``bookmarks.py``
    Manages bookmarks using a separate pane.
``add_directives.py``
    Allows users to define new directives.
``at_folder.py``
    Synchronizes ``@folder`` nodes with folders.
``at_produce.py``
    Executes commands in nodes whose body text starts with ``@produce``.
``at_view.py``
    Adds support for ``@clip``, ``@view`` and ``@strip`` nodes.
``attrib_edit.py``
    Edits user attributes in a Qt frame.
``backlink.py``
    Allows arbitrary links between nodes.
``bibtex.py``
    Manages BibTeX files with Leo.
``bigdash.py``
    Creates a global search window.
``bookmarks.py``
    Manages bookmarks using a separate pane.
``bzr_qcommands.py``
    Adds a context menu to each node containing all the commands in the bzr Qt
    interface. Bzr is invoked based on the path of the current node.
``chapter_hoist.py``
    Creates hoist buttons.
``codewisecompleter.py``
    Uses the ctags database to provide an autocompletion list.
``colorize_headlines.py``
    Manipulates appearance of individual tree widget items.
``contextmenu.py``
    Defines various useful actions for context menus (Qt only).
``ctagscompleter.py``
    Uses ctags to provide an autocompletion list.
``datenodes.py``
    Allows users to insert headlines containing dates.
``debugger_pudb.py``
    Makes g.pdb() enter the Pudb debugger instead of pdb.
``demo.py``
    Creates slides or interactive demos.
``dragdropgoodies``
    Dumps files dropped into Leo.
``dtest.py``
    Sends code to the doctest module and reports the result.
``dragdropgoodies``
    Dumps files dropped into Leo.
``dump_globals.py``
    Dumps Python globals at startup.
``EditAttributes.py``
    Lets the user associate text with a specific node.
``empty_leo_file.py``
    Allows Leo to open any empty file as a minimal .leo file.
``enable_gc.py``
    Enables debugging and tracing for Python's garbage collector.
``expfolder.py``
    Adds ``@expfolder`` nodes that represent folders in the file system.
``FileActions.py``
    Defines actions taken when double-clicking on ``@&lt;file&gt;`` nodes and
    supports ``@file-ref`` nodes.
``ftp.py``
    Supports uploading of files via ftp.
``geotag.py``
    Tags nodes with latitude and longitude.
``gitarchive.py``
    Stores snapshots of outline in git.
``graphcanvas.py``
    Adds a graph layout for nodes in a tab.
    Requires Qt and the backlink.py plugin.
``import_cisco_config.py``
    Allows the user to import Cisco configuration files.
``initinclass.py``
    Modifies the Python ``@auto`` importer so that the importer
    puts the ``__init__`` method (ctor) into the body of the class node.
``interact.py``
    Adds buttons so Leo can interact with command line environments.
``leofeeds.py``
    Reads from rss, atom or other sources.
``leo_interface.py``
    Allows the user to browse XML documents in Leo.
``leo_pdf.py``
    This NOT a Leo plugin: this is a docutils writer for .pdf files.
``leo_to_html.py``
    Converts a leo outline to an html web page.
``leo_to_html_outline_viewer.py``
    Converts a leo outline to a self-contained HTML interactive outline viewer.
``leo_to_rtf.py``
    Outputs a Leo outline as a numbered list to an RTF file. The RTF file can be
    loaded into Microsoft Word and formatted as a proper outline.
``leocursor.py``
    Creates a LeoCursor object that can walk around a Leo outline and decode
    attributes from nodes.
``leofeeds.py``
    Reads from rss, atom or other sources.

.. Not a plugin: leofts.py.

``leomail.py``
    Sync local mailbox files over to Leo.
``leomylyn.py``
    Provides a "Mylyn" like experience for Leo.
``leoOPML.py``
    Read and write ``.leo`` files in OPML.
``leoremote.py``
    Remote control for Leo.
``leoscreen.py``
    Allows interaction with shell apps via screen.
``lineNumbers.py``
    Adds #line directives in perl and perlpod programs.   
``livecode.py``
    Creates a live code-evaluation pane.
``macros.py``
    Creates new nodes containing parameterized section references.
``markup_inline.py``
    Adds commands that create bold, italic or underlined text.
``maximizeNewWindows.py``
    Maximizes all new windows.
``mime.py``
    Opens files with their default platform program.
``mod_autosave.py``
    Autosaves the Leo outline every so often.
``mod_framesize.py``
    Sets a hard coded frame size.
``mod_http.py``
    An http plugin for Leo, based on AsyncHttpServer.py.
``mod_read_dir_outline.py``
    Allows Leo to read a complete directory tree into a Leo outline. Converts
    directories into headlines and puts the list of file names into bodies.
``mod_scripting.py``
    Creates script buttons and ``@button``, ``@command``, ``@plugin`` and ``@script`` nodes.
``mod_timestamp.py``
    Timestamps all save operations to show when they occur.
``multifile.py``
    Allows Leo to write a file to multiple locations.
``nav_qt.py``
    Adds "Back" and "Forward" buttons (Qt only).
``niceNosent.py``
    Ensures that all descendants of ``@file-nosent nodes`` end
    with exactly one newline, replaces all tabs with spaces, and
    adds a newline before class and functions in the derived file.
``nodeActions.py``
    Allows the definition of double-click actions.
``nodediff.py``
    Provides commands to run text diffs on node bodies within Leo.
``nodeTags.py``
    Provides node tagging capabilities to Leo.
``nodewatch.py``
    Adds scriptable ``@nodewatch`` nodes.
``notebook.py``
    Adds a QML notebook.
``open_shell.py``
    Creates an 'Extensions' menu containing two commands:
    Open Console Window and Open Explorer.
``outline_export.py``
    Modifies the way exported outlines are written.
``paste_as_headlines.py``
    Creates new headlines from clipboard text.
``plugins_menu.py``
    Creates a Plugins menu and adds all actives plugins to it.  
``projectwizard.py``
    Creates a wizard that creates ``@auto`` nodes.
``python_terminal.py``
    Embeds an python interpreter in Leo's log pane.
``QNCalendarWidgets.py``
    Adds a calendar widget.
``quickMove.py``
    Creates buttons to move nodes quickly to other nodes.
``quicksearch.py``
    Adds a fast-to-use search widget, like the "Find in files" feature of many editors.
``quit_leo.py``
    Shows how to force Leo to quit.
``read_only_nodes.py``
    Creates and updates ``@read-only`` nodes.
``redirect_to_log.py``
    Sends all output to the log pane.
``richtext.py``
    Enables rich text using the `CKEditor &lt;https://ckeditor.com/&gt;`_ editor.
``rss.py``
    Adds rss reader features to Leo.
``run_nodes.py``
    Runs a program and interface Leos through its input/output/error streams.   
``screen_capture.py``
    Supports taking screen shots.
``screenshots.py``
    Creates stand-alone slideshows containing screenshots.
``script_io_to_body.py``
    Sends output from the Execute Script command to the end of the body pane.
``scripts_menu.py``
    Creates a Scripts menu for LeoPy.leo.
``setHomeDirectory.py``
    Sets g.app.homeDir to a hard-coded path.
``sftp.py``
    Adds ``@edit``-like functionality for remote files over SFTP.
``slideshow.py``
    Support slideshows in Leo outlines.
``spydershell.py``
    Launches the spyder environment with access to Leo instance.
    See https://packages.python.org/spyder/.
``startfile.py``
    Launches (starts) a file given by a headline when double-clicking the icon.
``stickynotes.py``
    Adds simple "sticky notes" feature (popout editors) for Qt gui.
``systray.py``
    Adds Leo to the system tray.
``threadutil.py``
    Adds utilities for asynchronous operation of commands.
``timestamp.py``
    Manages attributes containing node creation/modification/viewed times.
``todo.py``
    Provides to-do list and simple task management for leo (Qt only).
``tomboy_import.py``
    Allows imports of notes created in Tomboy / gnote.
``trace_gc_plugin.py``
    Traces changes to Leo's objects at idle time.
``trace_keys.py``
    Traces keystrokes in the outline and body panes.
``trace_tags.py``
    Traces most common hooks, but not key, drag or idle hooks.
``viewrendered.py``
    Creates a window for *live* rendering of rst, html, etc.
    This plugin uses docutils, https://docutils.sourceforge.net/,
    to do the rendering, so installing docutils is recommended.
    Supports ``@graphics-script``, ``@image``, ``@html``, ``@movie`` and ``@svg`` nodes.
``viewrendered3.py``
    An alternate/enhanced version of viewrendered.py.
``vim.py``
    Enables two-way communication with VIM.
``wikiview.py``
    Hides/shows parts of urls in the body editor.
``word_count.py``
    Counts characters, words, lines, and paragraphs in the body pane.
``word_export.py``
    Adds the ``Plugins\:Word Export\:Export`` menu item to format and export
    the selected outline to a Word document, starting Word if necessary.
``xemacs.py``
    Allows you to edit nodes in emacs/xemacs.
``xml_edit.py``
    Adds commands for importing and exporting xml to and from Leo outlines.
``xsltWithNodes.py``
    Adds the Outline:XSLT menu containing XSLT-related commands.
``zenity_file_dialogs.py``
    Replaces Leo's file dialogs on Linux with external
    calls to the zenity gtk dialog package.
</t>
<t tx="ekr.20101113063552.9399"></t>
<t tx="ekr.20101113063552.9400">Edits user attributes in a Qt frame.

This plugin creates a frame for editing attributes similar to::

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

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

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

v.u mode
  These attributes are stored in the "unknownAttributes" (uA) data for
  each node, accessed via v.u.

Field:
  Attributes are lines starting (no whitespace) with "AttributeName:" in
  the body text.

@Child
  Attributes are the head strings of child nodes when the head string
  starts with '@AttributeName' where the first letter (second character)
  must be capitalized.

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

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

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

        Field:
        @Child
        # v.u mode

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

attrib-edit-manage
    Select which attributes, from all attributes seen so
    far in this outline, to include on the current node.

attrib-edit-scan
    Scan the entire outline for attributes so ``attrib-edit-manage``
    has the complete list.

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

        addressbook First

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

    As a convenience, entering a path like::

        todo metadata created|creator|revised

    would create::

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


**Technical details**

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

- In addition to ``v.u['addressbook']['_edit']['first']``, paths like ``v.u['addressbook']['_edit']['_int']['age']`` may be used to identify type, although currently there's no difference in the edit widget.

- In the future the plugin may allow other plugins to register to provide attribute path information, instead of just scanning for ['_edit'] entries in v.u.

- Currently there's no sorting of the attributes in "v.u mode", which is a problem for some applications.  It's unclear where the desired order would be stored, without even more repetition in v.u.  When other plugins can register to manipulate the attribute list each plugin could address this, with unordered presentation in the absence of the client plugin.

- There's code to have the editor appear in a tab instead of its own area under the body editor, but (a) this is always being buried by output in the log window, and (b) there's a bug which leaves some (harmless) ghost widgets in the background.  Enable by ``@setting`` ``attrib_edit_placement`` to 'tab'.
</t>
<t tx="ekr.20101113063552.9401">Manipulates appearance of individual tree widget items.

This plugin is mostly an example of how to change the appearance of headlines. As such, it does a relatively mundane chore of highlighting ``@thin``, ``@auto``, ``@shadow`` nodes in bold.
</t>
<t tx="ekr.20101113063552.9402">Defines various useful actions for context menus (Qt only).

Examples are:

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

Here's an example on how to implement your own context menu items in your plugins:

.. code-block:: python

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

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

        def nextclone_rclick_cb():
            c.goToNextClone()

        # 'menu' is a QMenu instance that was created by Leo 
        # in response to right click on tree item

        action = menu.addAction("Go to clone")
        action.connect(action, QtCore.SIGNAL("triggered()"), nextclone_rclick_cb)

And call this in your plugin *once*:

.. code-block:: python

    g.tree_popup_handlers.append(nextclone_rclick)
</t>
<t tx="ekr.20101113063552.9403">Adds "Back" and "Forward" buttons (Qt only).

Creates "back" and "forward" buttons on button bar. These navigate
the node history.

This plugin does not need specific setup. If the plugin is loaded, the buttons 
will be available. The buttons use the icon specified in the active Qt style

</t>
<t tx="ekr.20101113063552.9404">Creates a wizard that creates ``@auto`` nodes.

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

</t>
<t tx="ekr.20101113063552.9405">Adds a fast-to-use search widget, like the "Find in files" feature of many editors.

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

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

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

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

</t>
<t tx="ekr.20101113063552.9406">Provides a Scrolled Message Dialog service for Qt.

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

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

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

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

The plugin is invoked like this:

.. code-block:: python

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

or:

.. code-block:: python

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

All parameters are optional except ``c``.

**Parameters**

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

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

label:
    The text to appear in a label above the display. If it is '', the label is hidden.

title:
    The title to appear on the window or dock.

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

    Flags can be combined, for example, 'rst html' causes the message
    to be interpreted as rst and displayed as html.
</t>
<t tx="ekr.20101113063552.9407">Launches the spyder environment with access to Leo instance.
See https://packages.python.org/spyder/

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

</t>
<t tx="ekr.20101113063552.9408">Adds simple "sticky notes" feature (popout editors) for Qt gui.

Adds the following (``Alt-X``) commands:

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

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

Encrypted mode requires the python-crypto module.

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

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

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

</t>
<t tx="ekr.20101113063552.9409">Provides to-do list and simple task management for leo (Qt only).

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

For more documentation see: https://leo.zwiki.org/tododoc.

</t>
<t tx="ekr.20101113063552.9410">Creates a window for *live* rendering of rst, html, etc.  Qt only.
Supports ``@graphics-script``, ``@image``, ``@html``, ``@movie`` and ``@svg`` nodes.

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

    Heading
    -------

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

and::

    &lt;h1&gt;Heading&lt;h1&gt;

    &lt;tt&gt;This&lt;/tt&gt; is &lt;b&gt;really&lt;/b&gt; a line of text.

will look something like:

**Heading**

`This` is **really** a line of text.
</t>
<t tx="ekr.20101113063552.9411">Adds a graph layout for nodes in a tab. Requires Qt and the backlink.py plugin.

</t>
<t tx="ekr.20101113063552.9412"></t>
<t tx="ekr.20101113063552.9413">Allows users to define new directives.</t>
<t tx="ekr.20101113063552.9414">Adds a context menu to each node containing all the commands in the bzr Qt interface. Bzr is invoked based on the path of the current node. **Requires contextmenu.py.**

</t>
<t tx="ekr.20101113063552.9415">Allows Leo to open any empty file as a minimal .leo file.

</t>
<t tx="ekr.20101113063552.9416">Allows the user to import Cisco configuration files.

Adds the "File:Import:Import Cisco Configuration" menu item. The plugin will:

1)  Create a new node, under the current node, where the configuration will be written. This node will typically have references to several sections (see below).

2)  Create sections (child nodes) for the indented blocks present in the original config file. These child nodes will have sub-nodes grouping similar blocks (e.g. there will be an 'interface' child node, with as many sub-nodes as there are real interfaces in the configuration file).

3)  Create sections for the custom keywords specified in the customBlocks[] list in importCiscoConfig(). You can modify this list to specify different keywords. DO NOT put keywords that are followed by indented blocks (these are taken care of by point 2 above). The negated form of the keywords (for example, if the keyword is 'service', the negated form is 'no service') is also included in the sections.

4)  Not display consecutive empty comment lines (lines with only a '!').

All created sections are alphabetically ordered.

</t>
<t tx="ekr.20101113063552.9417">Modifies the Python ``@auto`` importer so that the importer puts the ``__init__`` method (ctor) into the body of the class node.

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

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

</t>
<t tx="ekr.20101113063552.9418">Allows the user to browse XML documents in Leo.

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

..  class file represents the whole leo file.
..  class leo_node has a headline and body text.

..  If you encounter the first of a set of clones, create a leo_node. If you
..  encounter the same set of clones later, create a leo_clone node and refer back
..  to the first element.

</t>
<t tx="ekr.20101113063552.9419">Adds #line directives in perl and perlpod programs.

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

</t>
<t tx="ekr.20101113063552.9420">Creates new nodes containing parameterized section reference.

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

To see this in action, do the following:

0. **Important**: in the examples below, type &lt;&lt; instead of &lt; &lt; and
   type &gt;&gt; instead of &gt; &gt;.  Docstrings can not contain section references!

1. Create a node called 'Parameterized Nodes', with a sub-node called  &lt; &lt; Meow \&gt;\&gt;.
   The body of &lt; &lt; Meow &gt; &gt; should have the text::

        I mmmm sooo happy I could  &lt; &lt; 1$  &gt; &gt;.
        But I don't know if I have all the  &lt; &lt; 2$  &gt; &gt;
        money in the world.

2. In a node called A, type::

        &lt; &lt; meow( purrrrrr, zzooot )  &gt; &gt;
        (leave the cursor at the end of the line)

3. In a node called B, type::

         &lt; &lt; meow ( spit or puke, blinking  )  &gt; &gt;
        (leave the cursor at the end of the line)

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

5. Go to Outline and select Parameterize Section Reference.

The plugin searches the outline, goes to level one and finds a Node with the Headline, "Parameterized Nodes". It looks for nodes under that headline with the the headline &lt;\&lt; meow &gt;\&gt;. It then creates this node structure under Node A::

        &lt; &lt; meow ( purrrrrr, zzooot ) &gt; &gt;
            &lt; &lt;2$&gt; &gt;
            &lt; &lt;1$&gt; &gt;

6. Examine the new subnodes of Node A:  

        &lt; &lt; meow ( purrrrrr, zzooot ) &gt; &gt; contains the body text of the &lt; &lt; meow &gt; &gt; node.
        &lt; &lt; 1$ &gt; &gt; contains the word purrrrrr.
        &lt; &lt; 2$ &gt; &gt; contains the word zzooot.

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

Go to Outline Menu and select Parameterize Section Reference command.

8. Examine the new subnodes of Node B.

It's a lot easier to use than to explain!
</t>
<t tx="ekr.20101113063552.9421">Autosaves the Leo outline every so often.

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

    @int mod_autosave_interval = 300

This plugin is active only if::

    @bool mod_autosave_active = True

</t>
<t tx="ekr.20101113063552.9422">Allows Leo to read a complete directory tree into a Leo outline. Converts directories into headlines and puts the list of file names into bodies.

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

Feedback on this plugin can be sent to::

    Frédéric Momméja
    &lt;frederic [point] mommeja [at] laposte [point] net&gt;

</t>
<t tx="ekr.20101113063552.9423">Timestamps all save operations to show when they occur.

</t>
<t tx="ekr.20101113063552.9425">Modifies the way exported outlines are written.

</t>
<t tx="ekr.20101113063552.9426">Creates new headlines from clipboard text.

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

</t>
<t tx="ekr.20101113063552.9428">Creates buttons to move nodes quickly to other nodes.

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

Adds `Move/Clone/Copy To Last Child Button` and `Move/Clone/Copy To First Child Button`, `Link To/From` and `Jump To` commands to the Move sub-menu on the Outline menu, and each node's context menu, if the `contextmenu` plugin is enabled.

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

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

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

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

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

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

  Goto Target
    takes you to the target node (like a `Jump` button).
  Make Permanent
    makes the button permanent, it will reappear
    when the file is saved / closed / re-opened.
  Set Parent
    allows you to move buttons to sub-menu items of other
    `quickMove` buttons.  This implicitly makes the moved button
    permanent.  It also causes the moved button to lose its context menu.
  Remove Button
    comes from the `mod_scripting` plugin, and just
    removes the button for the rest of the current session.

Set Parent Notes
  `Set Parent` doesn't allow you to do anything with `quickMove` you couldn't
  do with a long strip of separate buttons, but it collects quickMove buttons
  as sub-menu items of one quickMove button, saving a lot of toolbar space.

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

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

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

  Create somewhere in your outline a node called `Tags`. Use the quickMove menu
  to make it a `Jump To` button, and use its context menu to make it permanent.
  Clicking on it will jump you to your tag list. Now create a node under the
  `Tags` node for each tag you want. The node's name will be the tag name, and
  can be changed later. Then use the quickMove menu to make each of these nodes
  a `Link To` button, and then use the context menu on the button to set its
  parent to your `Tags` button. It becomes a sub-menu item of the `Tags` button.

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

</t>
<t tx="ekr.20101113063552.9429">Sets g.app.homeDir to a hard-coded path.

</t>
<t tx="ekr.20101113063552.9430">Counts characters, words, lines, and paragraphs in the body pane.

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

</t>
<t tx="ekr.20101113063552.9431"></t>
<t tx="ekr.20101113063552.9432">Makes ``g.pdb()`` enter the Pudb debugger instead of pdb.

Pudb is a full-screen Python debugger: https://pypi.python.org/pypi/pudb
</t>
<t tx="ekr.20101113063552.9433">Dumps Python globals at startup.

</t>
<t tx="ekr.20101113063552.9434">Enables debugging and tracing for Python's garbage collector.

</t>
<t tx="ekr.20101113063552.9435">Shows how to force Leo to quit.

</t>
<t tx="ekr.20101113063552.9436">Traces changes to Leo's objects at idle time.

</t>
<t tx="ekr.20101113063552.9437">Traces keystrokes in the outline and body panes.

</t>
<t tx="ekr.20101113063552.9438">Traces most common hooks, but not key, drag or idle hooks.

</t>
<t tx="ekr.20101113063552.9439"></t>
<t tx="ekr.20101113063552.9442">Creates an 'Extensions' menu containing two commands: Open Console Window and Open Explorer.

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

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

Please submit bugs / feature requests to etaekema@earthlink.net

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

</t>
<t tx="ekr.20101113063552.9443">Allows imports of notes created in Tomboy / gnote.

Usage:

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

</t>
<t tx="ekr.20101113063552.9444">Enables two-way communication with gvim (recommended) or vim. with the following commands:

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

``vim-open-node``
    Opens the selected node in vim. Leo will update the node in the outline
    when you save the file in vim.
</t>
<t tx="ekr.20101113063552.9445">Allows you to edit nodes in emacs/xemacs.

Depending on your preference, selecting or double-clicking a node will pass the body text of that node to emacs. You may edit the node in the emacs buffer and changes will appear in Leo.

</t>
<t tx="ekr.20101113063552.9446">Adds the Plugins\:Word Export\:Export menu item to format and export the selected outline to a Word document, starting Word if necessary.

</t>
<t tx="ekr.20101113063552.9447"></t>
<t tx="ekr.20101113063552.9448">Synchronizes ``@path`` nodes with folders.

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

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

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

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

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

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

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

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

There are commands on the Plugins active_path submenu:

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

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

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

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

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

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

    @language rest # AUTOLOADED DOCSTRING

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

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

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

active_path is a rewrite of the at_directory plugin to use ``@path`` directives (which influence ``@auto`` and other ``@file`` type directives), and to handle sub-folders more automatically.
</t>
<t tx="ekr.20101113063552.9449">Synchronizes ``@folder`` nodes with folders.

If a node is named ``@folder &lt;path_to_folder&gt;``, the content (filenames) of the folder and the children of that node will be sync. Whenever a new file is put there, a new node will appear on top of the children list (with mark). So that I can put my description (i.e. annotation) as the content of that node. In this way, I can find any files much easier from leo.

Moreover, I add another feature to allow you to group files(in leo) into children of another group. This will help when there are many files in that folder. You can logically group it in leo (or even clone it to many groups), while keep every files in a flat/single directory on your computer.

</t>
<t tx="ekr.20101113063552.9450">Executes commands in nodes whose body text starts with ``@produce``.

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

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

    @produce echo hi

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

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

Whatever follows ``@produce`` is executed as a command.

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

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

This plugin is not intended as a replacement for make or Ant, but as a simple substitute when that machinery is overkill.
</t>
<t tx="ekr.20101113063552.9451">Adds support for ``@clip``, ``@view`` and ``@strip`` nodes.

- Selecting a headline containing ``@clip`` appends the contents of the clipboard to
  the end of the body pane.

- Double clicking the icon box of a node whose headline contains
  ``@view &lt;path-to-file&gt;`` places the contents of the file in the body pane.

- Double clicking the icon box of a node whose headline contains
  ``@strip &lt;path-to-file&gt;`` places the contents of the file in the body pane, with all
  sentinels removed.

This plugin also accumulates the effect of all ``@path`` nodes.

</t>
<t tx="ekr.20101113063552.9452">Allows arbitrary links between nodes.

</t>
<t tx="ekr.20101113063552.9453">Allows users to insert headlines containing dates.

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

There are options to omit Saturdays and Sundays.

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

    @bool suppress-datenodes-menus
    @bool suppress-all-plugins-menus

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

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

</t>
<t tx="ekr.20101113063552.9454">Adds ``@expfolder`` nodes that represent folders in the file system.

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

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

For the ``@text`` and ``@expfolder`` nodes to interact correctly, the textnode plugin must load before the expfolder plugin. This can be set using the Plugin Manager's Plugin Load Order pane.
</t>
<t tx="ekr.20101113063552.9455">Defines actions taken when double-clicking on ``@&lt;file&gt;`` nodes and supports ``@file-ref`` nodes.

Double-clicking any kind of ``@&lt;file&gt;`` node writes out the file if changes have been made since the last save, and then runs a script on it, which is retrieved from the outline.

Scripts are located in a node whose headline is FileActions. This node can be anywhere in the outline. If there is more than one such node, the first one in outline order is used.

The children of that node are expected to contain a file pattern in the headline and the script to be executed in the body. The file name is matched against the patterns (which are Unix-style shell patterns), and the first matching node is selected. If the filename is a path, only the last item is matched.

Execution of the scripts is similar to the "Execute Script" command in Leo. The main difference is that the namespace in which the scripts are run contains these elements:

- 'c' and 'g' and 'p': as in the regular execute script command.

- 'filename': the filename from the ``@file`` directive.

- 'shellScriptInWindow', a utility function that runs a shell script in an external windows, thus permitting programs to be called that require user interaction

File actions are implemented for all kinds ``@&lt;file&gt;`` nodes. There is also a new node type ``@file-ref`` for referring to files purely for the purpose of file actions, Leo does not do anything with or to such files.
</t>
<t tx="ekr.20101113063552.9456">Tags nodes with latitude and longitude.

</t>
<t tx="ekr.20101113063552.9457">Creates a LeoCursor object that can walk around a Leo outline and decode attributes from nodes.

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

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

</t>
<t tx="ekr.20101113063552.9458">Opens files with their default platform program.

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

    @mime foodir/document.pdf

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

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

Where '%s' is replaced with the full pathname.

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

Use ``@url`` for opening either URLs or Uniform Node Locators in "\*.leo" files and use ``@mime`` nodes for opening files on the local file system.

For other sys.platform's, add an elif case to the section "guess file association handler" and either define a default _mime_open_cmd string, where "%s" will be replaced with the filename, or define a function taking the filename string as its only argument and set as open_func.
</t>
<t tx="ekr.20101113063552.9459">Allows Leo to write a file to multiple locations.

This plugin acts as a post-write mechanism, a file must be written to the file system for it to work. At this point it is not a replacement for ``@path`` or an absolute path, it works in tandem with them.

To use, place ``@multipath`` at the start of a line in the root node or an ancestor of the node. The format is (On Unix-like systems)::

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

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

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

It will places copy of the written file in each of these directories.

There is an additional directive that simplifies common paths, it is called
@multiprefix. By typing ``@multiprefix`` with a path following it, before a
@multipath directive you set the beginning of the paths in the ``@multipath``
directive. For example::

    #@multiprefix /leo #@multipath /plugins 

or::

    #@multiprefix /leo/
    #@multipath plugins: fungus : drain

copies a file to /leo/plugins /leo/fungus /leo/drain.

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

The ``@multiprefix`` stays in effect for the entire tree until reset with another
@multiprefix directive. ``@multipath`` is cumulative, in that for each ``@multipath`` in
an ancestor a copy of the file is created. These directives must at the beginning of the line and by themselves.

</t>
<t tx="ekr.20101113063552.9460">Ensures that all descendants of ``@file-nosent`` nodes end with exactly one newline, replaces all tabs with spaces, and adds a newline before class and functions in the derived file.

</t>
<t tx="ekr.20101113063552.9461">Creates and updates ``@read-only`` nodes.

Here's my first attempt at customizing leo. I wanted to have the ability to import files in "read-only" mode, that is, in a mode where files could only be read by leo (not tangled), and also kept in sync with the content on the drive.

The reason for this is for example that I have external programs that generate resource files. I want these files to be part of a leo outline, but I don't want leo to tangle or in any way modify them. At the same time, I want them to be up-to-date in the leo outline.

So I coded the directive plugin. It has the following characteristics:

- It reads the specified file and puts it into the node content.

- If the ``@read-only`` directive was in the leo outline already, and the file content on disk has changed from what is stored in the outline, it marks the node as changed and prints a "changed" message to the log window; if, on the other hand, the file content has _not_ changed, the file is simply read and the node is not marked as changed.

- When you write a ``@read-only`` directive, the file content is added to the node immediately, i.e. as soon as you press Enter (no need to call a menu entry to import the content).

- If you want to refresh/update the content of the file, just edit the headline and press Enter. The file is reloaded, and if in the meantime it has changed, a "change" message is sent to the log window.

- The body text of a ``@read-only`` file cannot be modified in leo.

The syntax to access files in ``@read-only`` via ftp/http is the following::

    @read-only https://www.ietf.org/rfc/rfc0791.txt
    @read-only ftp://ftp.someserver.org/filepath

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

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

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

Davide Salomoni

</t>
<t tx="ekr.20101113063552.9462">Runs a program and interface Leos through its input/output/error streams.

Double clicking the icon box whose headlines are ``@run &lt;cmd args&gt;`` will execute the command. There are several other features, including ``@arg`` and ``@input`` nodes.

The run_nodes.py plugin introduce two new nodes that transform leo into a terminal. It was mostly intended to run compilers and debuggers while having the possibility to send messages to the program.

Double clicking on the icon of an node whose headline is ``@run &lt;command&gt; &lt;args&gt;`` will launch &lt;command&gt; with the given arguments. It will also mark the node. # Terminates the argument list. ``@run # &lt;comment&gt;`` is also valid.

@in nodes are used to send input to the running process. Double clicking on
the icon of an ``@in &lt;message&gt;`` node will append a newline to ``&lt;message&gt;`` and write it to the program, no matter where the node is placed. If no ``@run`` node is active, nothing happens.

The body text of every child, in which the headlines do not begin with '@run' or '@in', will be appended to &lt;command&gt;, allowing you to add an unlimited number of arguments to &lt;command&gt;.

The output of the program is written in the log pane (Error output in red). When the program exit the node is set unmarked and the return value is displayed... When the enter key is pressed in the body pane of an active ``@run`` node the content of it body pane is written to the program and then emptied ready for another line of input. If the node have ``@run`` nodes in its descendants, they will be launched successively. (Unless one returned an exit code other than 0, then it will stop there)

By Alexis Gendron Paquette. Please send comments to the Leo forums.
</t>
<t tx="ekr.20101113063552.9463">Support slideshows in Leo outlines.

This plugin defines four new commands:

- ``next-slide-show``:  move to the start of the next slide show,
  or the first slide show if no slide show has been seen yet.
- ``prev-slide-show``:  move to the start of the previous slide show,
  or the first slide show if no slide show has been seen yet.
- ``next-slide``: move to the next slide of a present slide show.
- ``prev-slide``: move to the previous slide of the present slide show.

Slides shows consist of a root ``@slideshow`` node with descendant ``@slide`` nodes. ``@slide`` nodes may be organized via non-@slide nodes that do not appear in the slideshow.

All these commands ignore ``@ignore`` trees.

</t>
<t tx="ekr.20101113063552.9464">Launches (starts) a file given by a headline when double-clicking the icon.

This plugin ignores headlines starting with an ``@``. Uses the ``@folder`` path if the headline is under an ``@folder`` headline. Otherwise the path is relative to the Leo file.
</t>
<t tx="ekr.20101113063552.9466">Adds the Outline:XSLT menu containing XSLT-related commands.

This menu contains the following items:

- Set StyleSheet Node:
    - Selects the current node as the xsl stylesheet the plugin will use.

- Process Node with Stylesheet Node:
    - Processes the current node as an xml document,
      resolving section references and Leo directives.
    - Creates a sibling containing the results.

Requires 4Suite 1.0a3 or better, downloadable from https://4Suite.org.

</t>
<t tx="ekr.20101113063552.9467"></t>
<t tx="ekr.20101113063552.9468">Allows interaction with shell apps via screen.

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

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

**Commands**

leoscreen-run-text
  Send the text selected in Leo's body text to the shell app.
  Selects the next line for your convenience.

leoscreen-get-line
  Insert a line of the last result from the shell into Leo's body text
  at the current insert point.  Lines are pulled one at a time starting
  from the end of the output.  Can be used repeatedly to get the
  output you want into Leo.

leoscreen-get-all
  Insert all of the last result from the shell into Leo's body text
  at the current insert point.

leoscreen-get-note
  Insert all of the last result from the shell into a new child node of
  the current node.

leoscreen-show-all
  Show the output from the last result from the shell in a temporary
  read only window. **Important**: The output is not stored.

leoscreen-show-note
  Insert all of the last result from the shell into a new child node of
  the current node and display that node a a stickynote (requires stickynote
  plugin).

leoscreen-next
  Switch screen session to next window.

leoscreen-prev
  Switch screen session to preceding window.

leoscreen-other
  Switch screen session to last window displayed.

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

      c.leo_screen.get_line_prefix = '#'

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

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

**Settings**

leoscreen_prefix
  Prepended to output pulled in to Leo. The substring SPACE in this
  setting will be replaced with a space character, to allow for trailing
  spaces.

leoscreen_time_fmt
  time.strftime format for note type output headings.

**Theory of operation**

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

**Example SQL setup**

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

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

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

**Implementation note**: screen behaves differently if screen -X is executed with the same stdout as the target screen, vs. a different stdout. Although stdout is ignored, Popen() needs to ensure it's not just inherited.
</t>
<t tx="ekr.20101113063552.9469">Creates script buttons and ``@button``, ``@command``, ``@plugin`` and ``@script`` nodes.

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

The 'Run Script' button is simply another way of doing the Execute Script command: it executes the selected text of the presently selected node, or the entire text if no text is selected.

The 'Script Button' button creates *another* button in the icon area every time you push it. The name of the button is the headline of the presently selected node. Hitting this *newly created* button executes the button's script.

For example, to run a script on any part of an outline do the following:

1.  Select the node containing the script.
2.  Press the scriptButton button.  This will create a new button.
3.  Select the node on which you want to run the script.
4.  Push the *new* button.

That's all.

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

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

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

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

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

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

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

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

- ``@button`` nodes create script buttons.
- ``@command`` nodes create minibuffer commands.
- ``@plugin`` nodes cause plugins to be loaded.
- ``@script`` nodes cause a script to be executed when opening a .leo file.

Such nodes may be security risks. This plugin scans for such nodes only if the corresponding atButtonNodes, atPluginNodes, and atScriptNodes constants are set to True in this plugin.

You can specify the following options in ``leoSettings.leo``.  See the node:
@settings--&gt;Plugins--&gt;scripting plugin.  Recommended defaults are shown::

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

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

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

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

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

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

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

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

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

``@button name @key=shortcut``

    Binds the shortcut to the script in the script button. The button's name is
    'name', but you can see the full headline in the status line when you move the
    mouse over the button.

``@command name @key=shortcut``

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

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

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

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

will set sys.argv to [u'a',u'b',u'c']
</t>
<t tx="ekr.20101113063552.9470">Sends output from the Execute Script command to the end of the body pane.

</t>
<t tx="ekr.20101113063552.9471"></t>
<t tx="ekr.20101113063552.9472">Remote control for Leo.

Example client:

.. code-block:: python

    from leo.external import lproto
    import os


    addr = open(os.path.expanduser('~/.leo/leoserv_sockname')).read()
    print("will connect to",addr)
    pc  = lproto.LProtoClient(addr)
    pc.send("""
        g.es("hello world from remote") 
        c = g.app.commanders()[0]
    """)

    # note how c persists between calls
    pc.send("""c.k.simulateCommand('stickynote')""")
</t>
<t tx="ekr.20101113063552.9473">A minimal http plugin for Leo, based on AsyncHttpServer.py.

Use this plugin is as follows:

1. Start Leo with the plugin enabled. You will see a purple message that says something like::

    http serving enabled on port 8130...

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

You will see a a "top" level page containing one link for every open .leo file. Start clicking :-)

You can use the browser's refresh button to update the top-level view in the browser after you have opened or closed files.

To enable this plugin put this into your file::

    @settings
    @bool http_active = True
    @int  port = 8130
    @string rst_http_attributename = 'rst_http_attribute'

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

</t>
<t tx="ekr.20101113063552.9474"></t>
<t tx="ekr.20101113063552.9475">Creates stand-alone slideshows containing screenshots.

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

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

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

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

**Prerequisites**

Inkscape (Required)
  An SVG editor: https://www.inkscape.org/
  Allows the user to edit screenshots.
  Required to create final output (PNG) files.

PIL (Optional but highly recommended)
  The Python Imaging Library,
  https://pypi.org/project/pillow/

Wink (Optional)
  A program that creates slideshows and slides.
  https://www.debugmode.com/wink/

**Summary**

``@slideshow &lt;slideshow-name&gt;``
  Creates the folder:
  &lt;sphinx_path&gt;/slides/&lt;slideshow-name&gt;

``@slide &lt;ignored text&gt;``
  Creates slide-&lt;slide-number&gt;.html
  (in the sphinx _build directory).
  **Note**: the plugin skips any ``@slide`` nodes
  with empty body text.

``@screenshot``
  Specifies the contents of the screenshot.

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

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

``@url built slide``
  Contains the absolute path to the final slide in
  the _build/html subfolder of the slideshow
  folder. If present, this ``@url`` node completely
  disables rebuilding the slide.

``@url screenshot``
  Contains the absolute path to the original
  screenshot file. If present, this ``@url`` node
  inhibits taking the screenshot.

``@url working file``
  Contains the absolute path to the working file.
  If present, this ``@url`` node disables taking the
  screenshot, creating the working file. The final
  output file will be regenerated if the working
  file is newer than the final output file.

``@url final output file``
  Contains the absolute path to the final output
  file.

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

    @url screenshot
    @url working file
    @url built slide

**Making slides**

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

1. Create a slide.

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

2. (Optional) Create a screenshot.

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

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

  Taking a screenshot involves the following steps:

  A. Create the **target outline**: ``screenshot-setup.leo``.

    The target outline contains consists of all
    the children (and their descendants) of the
    ``@screenshot`` node.

  B. Create the **screenshot**, a bitmap (PNG) file.

    The slide commands take a screen shot of the
    target outline. The ``@pause`` option opens the
    target outline but does *not* take the
    screenshot. The user must take the screenshot
    manually. For more details, see the the
    options section below.

  C. Convert the screenshot file to a **work file**.

    The work file is an SVG (Scalable Vector
    Graphics) file: https://www.w3.org/Graphics/SVG/.

  D. (Optional) Edit the work file.

    If the ``@slide`` node has a child ``@edit`` node, the
    plugin opens Inkscape so that the user can
    edit the work file.

  E. Render the **final output file**.

    The plugin calls Inkscape non-interactively to
    render the final output file (a PNG image)
    from the work file. If the Python Imaging
    Library (PIL) is available, this step will use
    PIL to improve the quality of the final output
    file.

3. Build the slide using Sphinx.

  After making all files, the plugins runs Sphinx
  by running 'make html' in the slideshow folder.
  This command creates the final .html files in the
  _build/html subfolder of the slideshow folder.

4. Create url nodes.

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

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

**Options and settings**

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

**Global options nodes**

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

``@sphinx_path = &lt;path&gt;``
  This directory contains the slides directory,
  and the following files: 'conf.py', 'Makefile' and 'make.bat'.

``@screenshot_height = &lt;int&gt;``
  The height in pixels of screenshots.

``@screenshot_width = &lt;int&gt;``
  The height in pixels of screenshots.

``@template_fn = &lt;path&gt;``
  The absolute path to ``inkscape-template.svg``.

``@title = &lt;any text&gt;``
  The title to use for one slide or the entire
  slideshow.

``@title_pattern = &lt;pattern&gt;``
  The pattern used to generate patterns for one
  slide or the entire slideshow. The title is
  computed as follows::

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

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

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

``@verbose = True/False``
  True (or true or 1):  generate informational message.
  False (or false or 0): suppress informational messages.

``@wink_path = &lt;path&gt;``
  This path contains screenshots created by wink.
  This is used only by the ``meld-slides`` command.

**Local options nodes**

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

``@callout &lt;any text&gt;``
  Generates a text callout in the working .svg file.
  An ``@slide`` node may have several ``@callout`` children.

``@edit = True/False``
  If True (or true or 1) the plugin enters
  Inkscape interactively after taking a
  screenshot.

``@markers = &lt;list of integers&gt;``
  Generates 'numbered balls' in the working .svg file.

``@pause = True/False``
  If True (or true or 1) the user must take the
  screenshot manually. Otherwise, the plugin takes
  the screenshot automatically.

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

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

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

``@screenshot``
  The root of a tree that becomes the entire
  contents of screenshot. No screenshot is taken
  if this node does not exist.

``@select &lt;headline&gt;``
  Causes the given headline in the ``@screenshot``
  outline to be selected before taking the screenshot.

**Settings**

``@string screenshot-bin = &lt;path to inkscape.exe&gt;``
  The full path to the Inkscape program.   

**File names**

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

    slide-n.html.txt:   the slide's rST source.
    screenshot-n.png:   the original screenshot.
    screenshot-n.svg:   the working file.
    slide-n.png:        the final output file.
    _build/html/slide-n.html: the final slide.
</t>
<t tx="ekr.20101113063552.9476"></t>
<t tx="ekr.20101113063552.9477">Manages BibTeX files with Leo.

Create a bibliographic database by putting '@bibtex filename' in a headline. Entries are added as nodes, with '@entrytype key' as the headline, and the contents of the entry in body text. The plugin will automatically insert a template for the entry in the body pane when a new entry is created (hooked to pressing enter when typing the headline text). The templates are defined in dictionary 'templates' in the \&lt;\&lt;globals\&gt;\&gt; section, by default containing all required fields for every entry.

The file is written by double-clicking the node. Thus the following outline::

    -@bibtex biblio.bib
     +@book key
      author = {P. D. James},
      year = 1999

will be written in the file 'biblio.bib' as::

    @book{key,
    author = {P. D. James},
    year= 1999}

Strings are defined in ``@string`` nodes and they can contain multiple entries. All ``@string`` nodes are written at the start of the file. Thus the following outline::

    -@bibtext biblio.bib
     +@string
      j1 = {Journal1}
     +@article AUj1
      author = {P. D. James},
      journal = j1
     +@string
      j2 = {Journal2}
      j3 = {Journal3}

Will be written as::

    @string{j1 = {Journal1}}
    @string{j2 = {Journal2}}
    @string{j3 = {Journal3}}

    @article{AUj1,
    author = {P. D. James},
    journal = j1}

No error checking is made on the syntax. The entries can be organized under nodes --- if the headline doesn't start with '@', the headline and body text are ignored, but the child nodes are parsed as usual.

BibTeX files can be imported by creating an empty node with '@bibtex filename' in the headline. Double-clicking it will read the file 'filename' and parse it into a ``@bibtex`` tree. No syntax checking is made, 'filename' is expected to be a valid BibTeX file.
</t>
<t tx="ekr.20101113063552.9478">Sends code to the doctest module and reports the result.

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

    Alt-X dtest

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

From Wikipedia::

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

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

https://tinyurl.com/pxhlq - Jim Fulton's presentation::

    Literate Testing:
    Automated Testing with doctest
</t>
<t tx="ekr.20101113063552.9480">Outputs a Leo outline as a numbered list to an RTF file. The RTF file can be loaded into Microsoft Word and formatted as a proper outline.

If this plug-in loads properly, you should have an "Outline to Microsoft RTF" option added to your File &gt; Export... menu in Leo.

Settings such as outputting just the headlines (vs. headlines &amp; body text) and whether to include or ignore the contents of ``@file`` nodes are stored in the rtf_export.ini file in your Leo\plugins folder.

The default export path is also stored in the INI file. By default, it's set to c:\ so you may need to modify it depending on your system.
</t>
<t tx="ekr.20101113063552.9482"></t>
<t tx="ekr.20101113063552.9484">Creates hoist buttons.

This plugin puts two buttons in the icon area: a button called 'Save Hoist' and a button called 'Dehoist'. The 'Save Hoist' button hoists the presently selected node and creates a button which can later rehoist the same node. The 'Dehoist' button performs one level of dehoisting

Requires at least version 0.19 of mod_scripting.

</t>
<t tx="ekr.20101113063552.9486">Lets the user to associate text with a specific node.

Summon it by pressing button-2 or button-3 on an icon Box in the outline. This will create an attribute editor where the user can add, remove and edit attributes. Since attributes use the underlying tnode, clones will share the attributes of one another.

</t>
<t tx="ekr.20101113063552.9487">Adds buttons so Leo can interact with command line environments.

:20100226: see also leoscreen.py for a simpler approach.

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

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

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

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

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

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

Requires `pexpect` module.
</t>
<t tx="ekr.20101113063552.9488">Maximizes all new windows.

</t>
<t tx="ekr.20101113063552.9489">Sets a hard coded frame size.

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

</t>
<t tx="ekr.20101113063552.9491">Sends all output to the log pane.

</t>
<t tx="ekr.20101113063552.9492">Creates a Scripts menu for LeoPy.leo.

</t>
<t tx="ekr.20101113063552.9493">Replaces the gui file dialogs on Linux with external calls to the zenity gtk dialog package.

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

Despite this, some Linux users might prefer it to the gui dialogs.
</t>
<t tx="ekr.20101113063552.9528"></t>
<t tx="ekr.20101113063552.9794">Creates a Plugins menu and adds all actives plugins to it.

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

**INI files and the Properties Dialog**

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

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

**Special Methods**

Certain methods defined at the top level are considered special.

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

applyConfiguration

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

**Special Variable Names**

Some names defined at the top level have special significance.

__plugin_name__
    This will be used to define the name of the plugin and will be used
    as a label for its menu entry.

__plugin_priority__
    Plugins can also attempt to select the order they will appear in the menu by
    defining a __plugin_priority__. The menu will be created with the highest
    priority items first. This behavior is not guaranteed since other plugins
    can define any priority. This priority does not affect the order of calling
    handlers.
    To change the order select a number outside the range 0-200 since this range
    is used internally for sorting alphabetically. Properties and INI files.
</t>
<t tx="ekr.20101113063552.9798">Allows the definition of double-click actions.

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

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

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

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

**Configuration**

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

@bool nodeActions_save_atFile_nodes = False

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

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

@int nodeActions_message_level = 1

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

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

**Patterns**

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

    *           matches everything
    ?           matches any single character
    [&lt;seq&gt;]     matches any character in &lt;seq&gt;
    [!&lt;seq&gt;]    matches any character **not** in &lt;seq&gt;

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

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

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

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

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

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

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

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

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

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

**Pattern directives**

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

:[X]:
  Use python's regular expression type patterns instead of the Unix
  shell-style pattern syntax.

  For example, the following patterns will match the same headline string::

     Unix shell-style pattern:
        @files *.py

     Regular Expression pattern:
        ^@files .*\.py$ [X]

:[V]:
  Matching the pattern will not block the double-click event from
  being passed to the remaining patterns.
  The "V" represents a down arrow that symbolizes the passing of the event
  to the next pattern below it.

  For example, adding the "[V]" directive to the "@files \*_test.py" in
  the Patterns section above, changes its script from being 'an
  alternate to' to being 'a pre-processor for' the "@files \*.py" script::

     +- nodeActions
        |
        +- @files *_test.py [V]
        |
        +- @files *.py

:[&gt;]:
  Matching the pattern will not block the double-click event from being
  passed to other plugins.
  The "&gt;" represents a right arrow that
  symbolizes the passing of the event to the next plugin.

  If the headline matched more than one headline,
  the double-click event will be passed to the next plugin if the
  directive is associated with any of the matched patterns.

The directive(s) for a pattern must be contained within a single set of brackets, separated from the pattern by a space, with or without a comma separator.  For example, the following specifies all three directives::

  ^@files .*\.py$ [X,V&gt;]


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

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

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

     g.os.system('"Start /b ' + pClicked.bodyString() + '"')
</t>
<t tx="ekr.20101113063552.9800">Converts a leo outline to an html web page.

This plugin takes an outline stored in Leo and converts it to html which is then either saved in a file or shown in a browser. It is based on the original leoToHTML 1.0 plugin by Dan Rahmel which had bullet list code by Mike Crowe.

The outline can be represented as a bullet list, a numbered list or using html &lt;h?&gt; type headings. Optionally, the body text may be included in the output.

If desired, only the current node will be included in the output rather than the entire outline.

An xhtml header may be included in the output, in which case the code will be valid XHTML 1.0 Strict.

The plugin is fully scriptable as all its functionality is available through a Leo_to_HTML object which can be imported and used in scripts.

**Menu items and @settings**

If this plugin loads properly, the following menu items should appear in your File &gt; Export... menu in Leo::

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

*Unless* the following appears in an ``@setting`` tree::

    @bool leo_to_html_no_menus = True

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

**Commands**

Several commands will also be made available

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

The following commands will start a browser showing the html.

show-html
  will show the outline according to current settings.

show-html-*
  will show the outline using bullet type '*' which can be
  **number**, **bullet** or **head**.

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

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

**Properties**

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

exportpath:
    The path to the folder where you want to store the generated html file.
    Default: c:\\

flagjustheadlines:
    Default: 'Yes' to include only headlines in the output.

flagignorefiles:
    Default: 'Yes' to ignore ``@file`` nodes.

use_xhtml:
    Yes to include xhtml doctype declarations and make the file valid XHTML 1.0 Strict.
    Otherwise only a simple &lt;html&gt; tag is used although the output will be xhtml
    compliant otherwise. Default: Yes

bullet_type:
    If this is 'bullet' then the output will be in the form of a bulleted list.
    If this is 'number' then the output will be in the form of a numbered list.
    If this is 'heading' then the output will use &lt;h?&gt; style headers.

    Anything else will result in &lt;h?&gt; type tags being used where '?' will be a
    digit starting at 1 and increasing up to a maximum of six depending on depth
    of nesting. Default: number

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

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

**Configuration**

At present, the file leo/plugins/leo_to_html.ini contains configuration settings. In particular, the default export path, "c:\" must be changed for \*nix systems.
</t>
<t tx="ekr.20101115152915.4937">{{Infobox software
| name = Leo: Leonine Editor with Outlines
| developer = Edward K. Ream, et al.
| size = ~9 MB
| programming_language = [[Python (programming language)|Python]]
| operating_system = [[Cross-platform]]
| genre = [[Text editor]], [[Outliner]], [[Integrated development environment|IDE]]
| license = [[MIT License|MIT]]
| website = {{URL|https://leo-editor.github.io/leo-editor/}}
}}

'''Leo''' is an [[open-source software|open-source]]  [[text editor]]/[[outliner]] that features  clones (virtual copies of outline nodes) as a central tool of organization, navigation, customization and scripting.

==Languages==
Leo can manipulate text or code in any human or computer programming language (e.g., Python, C, C++, Java), as Leo is a language-independent or "adaptable LPE" ([[literate programming]] environment).&lt;ref&gt;{{cite journal|last1=Pieterse|first1=Vreda|last2=Kourie|first2=Derrick G.|last3=Boake|first3=Andrew|title=A Case for Contemporary Literate Programming|journal=SAICSIT '04: Proceedings|date=2004|pages=111–118|url=http://espresso.cs.up.ac.za/publications/vpieterse_etal_saicsit.pdf|archiveurl=http://dl.acm.org/citation.cfm?id=1035054 |archivedate=2004|publisher=South African Institute for Computer Scientists and Information Technologists|location=Republic of South Africa}} Table 2: "Some Adaptable LPEs", p. 113. Same authors' abridged version in book form: {{cite book|editor1-last=Eckstein|editor1-first=Jutta|editor2-last=Baumeister|editor2-first=Hubert|title=Extreme Programming and Agile Processes in Software Engineering|chapter-url=https://archive.org/details/springer_10.1007-b98150|publisher=Springer-Verlag|location=Berlin; Heidelberg; New York |isbn=3-540-22137-9|pages=250–253|chapter=Literate Programming to Enhance Agile Methods|date=June 2004}} Table 2: "Some Language Independent LPEs", p. 251&lt;/ref&gt; Syntax highlighting is provided for many different programming languages.&lt;ref name=NordicJComp /&gt; Leo is written in [[Python (programming language)|Python]] and can be extended with plugins written in Python. The GUI uses the [[Qt (toolkit)|Qt]] toolkit; the syntax-aware editor is based on [[Scintilla (software)|Scintilla]]. Leo outlines are stored as [[XML]] files.

==Trees, clones and views==
Leo's foremost functionality, in addition to text editing, is that of an [[outliner]], with a "vast range of convenience features for structuring and managing outlines" both by drag-and-drop via GUI and by keyboard commands.&lt;ref name=NordicJComp&gt;{{cite journal|last1=Vestdam|first1=Thomas|last2=Nørmark|first2=Kurt|title=Maintaining Program Understanding - Issues, Tools, and Future Directions|journal=Nordic Journal of Computing|date=September 2004|volume=11|issue=3|pages=303–320|url=http://people.cs.aau.dk/~normark/elucidative-programming/papers/issues_tools_future.pdf|accessdate=18 November 2014|location=Finland|issn=1236-6064 |archiveurl=http://dl.acm.org/citation.cfm?id=1080584 |archivedate=2004}} Leo discussed on pp. 12-13 of author's copy of published article.&lt;/ref&gt; Leo's outline pane shows a [[tree (data structure)|tree]] of data nodes. Nodes contain headlines, body text, and other information. Headlines naturally serve as descriptions of the body text. For example, @file nodes are nodes whose headline starts with @file. Leo trees are in fact [[directed acyclic graph]]s; nodes may have more than one parent. Leo calls such nodes '''clones'''. Clones appear in several places in the outline pane. '''Views''' are simply nodes whose children contain clones. A single outline may contain arbitrarily many views of the nodes contained therein.

==External files==
'''@file nodes''' represent '''external files''', files on the computer's file system other than the outline file. When saving an outline Leo automatically writes all changed @file trees back to the external files. Comments, called '''sentinel lines''', in external files represent the outline structure. When Leo reads an outline, these comments allow Leo to recreate @file trees using only the data in the external file. '''@auto nodes''' and '''@clean nodes''' represent external files without using sentinel comments. When reading @auto nodes, Leo uses the program structure of the ''external file'' to create the @auto tree. When reading @clean nodes, Leo uses the structure of the ''outline'' to create the @clean tree.

==Scripting==
Leo's outline or hierarchical structure is distinct from the web of interleaved program and documentation "chunks" associated with classic [[literate programming]] tools.&lt;ref name=PalmerHillenbrand&gt;{{cite book|last1=Palmer|first1=James Dean|last2=Hillenbrand|first2=Eddie|title=OOPSLA '09: Proceedings of the 24th ACM SIGPLAN Conference Companion on Object Oriented Programming Systems Languages and Applications|date=2009|publisher=ACM|location=New York|pages=1007–1014|chapter=Reimagining Literate Programming |doi=10.1145/1639950.1640072|quote=A few literate programming systems have taken a much different tack based on novel user interfaces. Edward Ream’s literate editor, Leo, uses visual outlines that allow users to attach metadata and descriptions to program descriptions and data. Unfortunately, truly literate programs may break Leo’s hierarchical outline based paradigm.|isbn=9781605587684|s2cid=17591332 }} (p. 1009)&lt;/ref&gt;&lt;ref name="Swaine"&gt;{{cite journal|last1=Swaine|first1=Michael|title=Programming Paradigms|journal=Dr. Dobb's Journal|date=July 1998|url=http://www.drdobbs.com/programming-paradigms/184410614 |archiveurl=https://web.archive.org/web/20160415194559/http://www.drdobbs.com/programming-paradigms/184410614 |archivedate=2016-04-15 |url-status=live}}Compares early version of LEO with [[Donald Knuth]]'s [[WEB]].&lt;/ref&gt; The body text of any Leo node may contain a '''Leo script''', a Python script executed in the context of a Leo outline. A simple [[API]] gives Leo scripts full access to all data in loaded outlines, as well as full access to Leo's own source code. The API includes Python [[iterators]] that allow scripts to traverse outlines easily. Scripts may be composed of any tree of nodes. A [[markup language]] similar to [[noweb]] tells Leo how to create scripts from (parts of) an outline. Headlines control and guide scripts. For example, '''@button nodes''' create user-defined commands.  Leo executes the script of an @button node in the context of any other outline node.

==References==
{{Reflist}}

==External links==
{{Portal|Free and open-source software}}
*{{official website|https://leo-editor.github.io/leo-editor/}}
*{{github|leo-editor}}
*{{cite web | title=LeoVue, A web-based version of Leo, by Joe Orr | url=https://kaleguy.github.io/leovue}}
*{{cite web | title=LeoInteg, A VSCode extension that integrates Leo, by Félix Malboeuf | website=[[GitHub]]| url=https://github.com/boltex/leointeg}}
*{{cite web | title=LeoJS | website=[[GitHub]]| url=https://github.com/boltex/leojs}}
*{{cite web | title=Literate Programming and Leo | publisher = [[Slashdot]] | date=2002-08-28 | url=http://developers.slashdot.org/article.pl?sid=02/08/28/1655207 }}
*{{cite web | author=James Tauber | title=Using the Leo Outliner as a PIM | date=2004-05-15 |url=http://jtauber.com/blog/2004/05/15/using_the_leo_outliner_as_a_pim/ | author-link=James Tauber }}

[[Category:Outliners]]
[[Category:Literate programming]]
[[Category:Free software programmed in Python]]
[[Category:Free text editors]]
[[Category:Code navigation tools]]
[[Category:Software that uses Qt]]
[[Category:Software that uses Scintilla]]
[[Category:Software using the MIT license]]
</t>
<t tx="ekr.20110521135104.18151">Any outline (.leo file) may contain clones that appear in multiple external files defined *within* that outline. There is no problem with such **intra-outline clones**.

In contrast, **cross-outline clones** are clones that appear in more than one outline.  Leo's paste-retaining-clones command makes it possible for two outlines to contain nodes with the same gnx. Conceivably, both outlines could use those clones in the *same* external file!

Leo will never encourage cross-outline clones, because such clones are inherently dangerous. Indeed, neither outline would have full responsibility for its own data. 

Indeed, the shared clones would be subject to the well-known multiple-update problem. Suppose the two outlines were open simultaneously, and each outline changed the shared clones in different ways. Whichever outline changed the data last would "win." The changes in the other outline would be lost forever!

In short, Leo will never support features that encourage cross-outline clones.</t>
<t tx="ekr.20110531155858.20563">The following script will create a minimal Leo outline:

.. code-block:: python

    if 1:
        # Create a visible frame.
        c2 = g.app.newCommander(fileName=None)
    else:
        # Create an invisible frame.
        c2 = g.app.newCommander(fileName=None,gui=g.app.nullGui)

    c2.frame.createFirstTreeNode()
    c2.redraw()

    # Test that the script works.
    for p in c2.all_positions():
        g.es(p.h)
</t>
<t tx="ekr.20110531155858.20564">See the node ``@data qt-gui-plugin-style-sheet`` in your theme file or ``myLeoSettings.leo``.
</t>
<t tx="ekr.20110601105631.19349">
</t>
<t tx="ekr.20111017085134.16158"></t>
<t tx="ekr.20111017085134.16159">'''
Copy the @screenshot node (a child of this node)
to all @slide nodes under p, (an @slideshow node),
that do not contain an @screenshot node.
'''

error = None
# Find this node:
h = '@button copy-@screenshot-node'
p2 = g.findNodeAnywhere(c,h)
if not p2:
    error = 'Can not find',p.h
# Find the @screenshot tree and the optional @select node.
if not error:
    select,template = None,None
    for child in p2.children():
        if g.match_word(child.h,0,'@screenshot'):
            template = child.copy()
        if g.match_word(child.h,0,'@select'):
            select = child.copy()
    if not template:
        error = 'No template @slideshow node in %s' % p2.h
if not error:
    if not g.match_word(p.h,0,'@slideshow'):
        error = 'not an @slideshow node',p.h
if error:
    g.error(error)
else:
    c.selectPosition(template)
    c.copyOutline()
    changed = False
    b = c.undoer.beforeChangeTree(p)
    for child in p.children():
        if not g.match_word(child.h,0,'@slide'):
            continue
        for grandChild in child.children():
            if g.match_word(grandChild.h,0,'@screenshot'):
                break
        else:
            changed = True
            p3 = child.insertAsLastChild()
            c.selectPosition(p3)
            c.pasteOutline()
            g.note('copied @screenshot to %s' % child.h)
            if select:
                c.selectPosition(p3)
                p4 = child.insertAsLastChild()
                p4.h = select.h
                g.note('copied %s to %s' % (select.h,child.h))
            c.selectPosition(p3)
            c.deleteOutline(p3)
            child.contract()
    if changed:
        c.undoer.afterChangeTree(p,'copy-@screenshot',b)
    c.redraw()
</t>
<t tx="ekr.20111017085134.16160"></t>
<t tx="ekr.20111017085134.16161">My to-do list.
</t>
<t tx="ekr.20111017085134.16162">1. Make Leo tutorials.  The world is waiting.
2. Pay phone bill or the world will never know.
</t>
<t tx="ekr.20111017085134.16163"></t>
<t tx="ekr.20111017085134.16164"></t>
<t tx="ekr.20111017085134.16165"></t>
<t tx="ekr.20111017085134.16166"></t>
<t tx="ekr.20111017085134.16167">@language rest

This is my diary.
</t>
<t tx="ekr.20111017085134.16168">July 1
    Started writing in my diary.
July 2
    Wrote another sentence in my diary.
July 3
    Keeping my diary very regularly.
July 5
    Oops...Yesterday I forgot to write in my diary.
</t>
<t tx="ekr.20111017085134.16169"></t>
<t tx="ekr.20111017085134.16170"></t>
<t tx="ekr.20111017085134.16171"></t>
<t tx="ekr.20111017085134.16172"></t>
<t tx="ekr.20111017085134.16173"></t>
<t tx="ekr.20111017085134.16174"></t>
<t tx="ekr.20111017085134.16175"></t>
<t tx="ekr.20111017085134.16176">'''Create @slide nodes under p, an @slideshow node.'''

n = 23 # Number of last slide to be created.

existing = [z.copy().h for z in p.children() 
    if g.match_word(z.h,0,'@slide')]

if g.match_word(p.h,0,'@slideshow'):
    b = c.undoer.beforeChangeTree(p)
    changed = False
    for n in range(1,n+1):
        h = '@slide %03d' % n
        if h not in existing:
            changed = True
            child = p.insertAsLastChild()
            child.h = h
            g.note('created %s' % h)
    if changed:
        c.undoer.afterChangeTree(p,'ins-@slide-nodes',b)
    else:
        g.note('no @slide nodes inserted')
    c.redraw()
else:
    g.error('not an @slideshow node',p.h)
</t>
<t tx="ekr.20111017085134.16177">m = g.loadOnePlugin('screenshots')
m.make_slide_command(event={'c':c})
</t>
<t tx="ekr.20111017085134.16178">m = g.loadOnePlugin('screenshots')
m.make_slide_show_command(event={'c':c})
</t>
<t tx="ekr.20111017085134.16179">'''Meld Wink slides into an @slideshow folder.

   Copy screenshot files from the wink_dir to slideshow_dir, numbering
   the destination files to reflect "holes" created by @no-screenshot
   nodes.

   This script carefully checks that the number of screenshot files
   matches the number of screenshots referenced by the @slide nodes.
   No copying takes place if the numbers are not as expected.'''

@language python

import glob
import os
import shutil

slideshow_dir = 'C:/leo.repo/trunk/leo/doc/html/slides/leo-basics-step-by-step'

wink_dir = 'C:/leo.repo/trunk/leo/doc/html/slides/leo-basics-step-by-step/_files'
    # The directory containing the wink screenshots.
    # This will usually be &lt;slideshow_dir&gt;/_files.
    # **Important** You generate these screenshots using Wink's 
    # Export As Html command (!)

@others

mc = MeldController(c,p,slideshow_dir,wink_dir)
mc.run()
</t>
<t tx="ekr.20111017085134.16180">class MeldController:

    def __init__ (self,c,p,slideshow_dir,wink_dir):

        self.c = c
        self.slideshow_dir = slideshow_dir
        self.slideshow_node = p
        self.wink_dir = wink_dir

    @others
</t>
<t tx="ekr.20111017085134.16181"></t>
<t tx="ekr.20111017085134.16182">def fix (self,fn):
    return os.path.normcase(fn).replace('\\','/')

def finalize (self,fn):
    return self.fix(g.os_path_finalize_join(self.slideshow_dir,fn))
</t>
<t tx="ekr.20111017085134.16183">def has_at_no_screenshot_node (self,p):

    for p in p.children():
        if self.match(p,'@no-screenshot'):
            return True
    else:
        return False
</t>
<t tx="ekr.20111017085134.16184">def match (self,p,pattern):

    '''Return True if p.h matches the pattern.'''

    return g.match_word(p.h,0,pattern)
</t>
<t tx="ekr.20111017085134.16185">def run (self):

    print('='*20)

    aList = self.get_wink_screenshots()
    if not aList:
        return

    if not self.check(aList):
        return

    # Pass 1: copy files for @slide nodes w/o @no-screenshot nodes.
    self.copy_files(aList)

    # Pass 2: adjust children of @slide nodes.
    self.adjust_slideshow()

    print('meld done')
</t>
<t tx="ekr.20111017085134.16186">def adjust_slideshow(self):

    '''Adjust all @slide nodes in the slideshow.'''

    # Traverse the tree as in the screenshot plugin.
    # That is, ignore @ignore trees and nested @slide nodes.
    # This ensures that the slide number, n, is correct.
    p = self.slideshow_node
    after = p.nodeAfterTree()
    p = p.firstChild()
    n = 1
    while p and p != after:
        if self.match(p,'@slide'):
            self.adjust_slide_node(p,n)
            n += 1
            p.moveToNodeAfterTree()
        elif self.match(p,'@ignore'):
            p.moveToNodeAfterTree()
        else:
            p.moveToThreadNext()
</t>
<t tx="ekr.20111017085134.16187">def adjust_slide_node (self,p,slide_number):

    '''Adjust p, an @slide node.'''

    trace = True

    # Delete the first "@url built slide" node.
    self.delete_at_url_built_slide_node(p)

    # Do nothing more if there is an @no-screenshot node.
    if self.has_at_no_screenshot_node(p):
        return

    # Add or update the "@url final output file" node.
    p2 = self.add_at_url_final_output_file(p,slide_number)

    # Add the .. image:: directive.
    self.add_image_directive(p,slide_number)
</t>
<t tx="ekr.20111017085134.16188">def add_at_url_final_output_file (self,p,slide_number):

    '''Create or update the "@url final output file" node.'''

    trace = True
    tag ='@url final output file'

    for child in p.children():
        if self.match(child,tag):
            p2 = child ; break
    else:
        if trace: g.es('add %s' % tag)
        p2 = p.insertAsLastChild()
        p2.h = tag

    p2.b = self.finalize(
        'slide-%03d.png' % (slide_number))

    return p2
</t>
<t tx="ekr.20111017085134.16189">def add_image_directive (self,p,slide_number):

    '''Add an image directive in p if it is not there.'''

    s = '.. image:: slide-%03d.png' % (slide_number)

    if p.b.find(s) == -1:
        p.b = p.b.rstrip() + '\n\n%s\n\n' % (s)
</t>
<t tx="ekr.20111017085134.16190">def delete_at_url_built_slide_node (self,p):

    '''Delete any "@url built slide" node in p's children.'''

    trace = True
    tag = '@url built slide'

    for child in p.children():
        if self.match(child,tag):
            if trace: g.es('del %s in %s' % (tag,p.h))
            child.doDelete()
            break
</t>
<t tx="ekr.20111017085134.16191">def check (self,aList):

    '''
    Check that len(aList) matches the number of @slide nodes in the
    slideshow. Don't count @slide nodes containing an @no-screenshot node.
    '''

    p = self.slideshow_node
    n1 = len(aList)
    n2,n3 = self.count_slide_nodes()

    if not self.check_dir(self.wink_dir):
        return False
    if not self.check_dir(self.slideshow_dir):
        return False
    if not self.match(p,'@slideshow'):
        return g.error('not a @slideshow node: %s',p.h)

    if n1 != (n2-n3):
        return g.error(
            '%s wink slides\n'
            '%s @slide nodes\n'
            '%s @no_screenshot nodes' % (
                n1,n2,n3))

    return True
</t>
<t tx="ekr.20111017085134.16192">def check_dir (self,theDir):

    if not g.os_path_exists(theDir):
        return g.error('not found: %s' % (theDir))

    if not g.os_path_isdir(theDir):
        return g.error('not a directory: %s' % (theDir))

    return True
</t>
<t tx="ekr.20111017085134.16193">def count_slide_nodes (self):

    '''Return n1,n2

    n1 is the total number of @slide nodes in the @slideshow tree.
    n2 is number of @slide nodes containing an @no-slideshow child.
    '''

    p = self.slideshow_node
    after = p.nodeAfterTree()
    p = p.firstChild()
    n1,n2 = 0,0
    while p and p != after:
        if self.match(p,'@slide'):
            n1 += 1
            if self.has_at_no_screenshot_node(p):
                n2 += 1
            p.moveToNodeAfterTree()
        elif self.match(p,'@ignore'):
            p.moveToNodeAfterTree()
        else:
            p.moveToThreadNext()

    g.trace(n1,n2)
    return n1,n2
</t>
<t tx="ekr.20111017085134.16194">def copy_files (self,aList):

    '''Copy files from the wink_dir to slideshow_dir,
    numbering the destination files to reflect "holes"
    created by @no-screenshot nodes.'''

    # Traverse the tree as in the screenshot plugin.
    # That is, ignore @ignore trees and nested @slide nodes.
    # This ensures that the slide number, n, is correct.
    p = self.slideshow_node
    after = p.nodeAfterTree()
    p = p.firstChild()
    wink_n = 0 # Wink screenshot numbers start at 0.
    slide_n = 1 # Slide numbers start at 1.
    while p and p != after:
        if self.match(p,'@slide'):
            if not self.has_at_no_screenshot_node(p):
                self.copy_file(aList,slide_n,wink_n)
                wink_n += 1
            slide_n += 1
            p.moveToNodeAfterTree()
        elif self.match(p,'@ignore'):
            p.moveToNodeAfterTree()
        else:
            p.moveToThreadNext()
</t>
<t tx="ekr.20111017085134.16195">def copy_file (self,aList,slide_n,wink_n):

    trace = True

    if wink_n &gt;= len(aList):
        return g.trace('can not happen: '
            'len(aList): %s, n: %s' % (
                len(aList),wink_n))

    fn_src = aList[wink_n]
    fn_dst = 'slide-%03d.png' % (slide_n)

    if trace:
        g.trace('%7s -&gt; %s' % (g.shortFileName(fn_src),fn_dst))

    shutil.copyfile(fn_src,fn_dst)
</t>
<t tx="ekr.20111017085134.16196">def get_wink_screenshots (self):

    '''Return the properly sorted list of wink screenshots.'''

    trace = False

    aList = glob.glob(self.wink_dir + '/*.png')

    def key(s):
        path,ext = g.os_path_splitext(s)
        junk,n = g.os_path_split(path)
        n = n.strip()
        if n.isdigit():
            return int(n)
        else:
            g.error('bad wink screenshot: %s' % (s))
            raise KeyError

    aList.sort(key=key) # Essential.

    if trace:
        for z in aList:
            print(z)

    return aList
</t>
<t tx="ekr.20111017085134.16197">'''Renumber @slide nodes under p, an @slideshow node.'''

if g.match_word(p.h,0,'@slideshow'):
    n = 1
    for child in p.children():
        if g.match(child.h,0,'@slide'):
            child.h = '@slide %03d' % n
            n += 1
    c.redraw()
else:
    g.error('not an @slideshow node',p.h)
</t>
<t tx="ekr.20111017085134.16198">@language python

changed = 0
b = c.undoer.beforeChangeTree(p)

for child in p.children():
    s = child.b
    i = s.find('.. image::')
    if i &gt; -1:
        i,j = g.getLine(s,i)
        child.b = s[:i] + s[j+1:]
        # g.es(child.h)
        changed += 1

if changed:
    g.es('changed %s nodes' % changed)
    c.undoer.afterChangeTree(p,'remove-image-directives',b)

</t>
<t tx="ekr.20111017085134.16199">@language python

changed = 0
b = c.undoer.beforeChangeTree(p)
for child in p.children():
    for child2 in child.children():
        if g.match_word(child2.h,0,'@url built slide'):
            child2.doDelete()
            changed += 1
            break

if changed:
    g.es('deleted %s nodes' % (changed))
    c.undoer.afterChangeTree(p,'remove-@url-built-slide',b)
    c.redraw()
</t>
<t tx="ekr.20111017085134.16200">@language python

changed = 0
b = c.undoer.beforeChangeTree(p)
for child in p.children():
    for child2 in child.children():
        if g.match_word(child2.h,0,'@url final output file'):
            child2.doDelete()
            changed += 1
            break

if changed:
    g.es('deleted %s nodes' % (changed))
    c.undoer.afterChangeTree(p,'remove-@url-final-output',b)
    c.redraw()
</t>
<t tx="ekr.20111108052738.5507">run-marked-unit-tests-externally = Alt-4
run-all-unit-tests-externally = Alt-5
</t>
<t tx="ekr.20111115063523.13619">The following puts up a test window when run as a Leo script:

.. code-block:: python

    from PyQt5 import QtGui
    w = QtGui.QWidget()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Simple test')
    w.show()
    c.my_test = w # &lt;-- Keep a reference to the window!

**Important**: Something like the last line is essential. Without it, the window would immediately disappear after being created.  The assignment:

.. code-block:: python

    c.my_test = w

creates a permanent reference to the window so the window won't be garbage collected after the Leo script exits.

</t>
<t tx="ekr.20120130101219.10182">def computeBindingLetter(self, kind):
    # lm = self
    if not kind:
        return 'D'
    table = (
        ('M', 'myLeoSettings.leo'),
        (' ', 'leoSettings.leo'),
        ('F', '.leo'),
    )
    for letter, kind2 in table:
        if kind.lower().endswith(kind2.lower()):
            return letter
    return 'D' if kind.find('mode') == -1 else '@'
</t>
<t tx="ekr.20120209051836.10241">class LeoApp(object):
    """A class representing the Leo application itself.

    Ivars of this class are Leo's global variables."""
    @others
</t>
<t tx="ekr.20120209051836.10242">class LoadManager(object):
    '''A class to manage loading .leo files, including configuration files.'''
    @others
</t>
<t tx="ekr.20120209051836.10252">def computeStandardDirectories(self):
    '''Compute the locations of standard directories and
    set the corresponding ivars.'''
    lm = self
    g.app.loadDir = lm.computeLoadDir()
    g.app.leoDir = lm.computeLeoDir()
    g.app.homeDir = lm.computeHomeDir()
    g.app.homeLeoDir = lm.computeHomeLeoDir()
    g.app.globalConfigDir = lm.computeGlobalConfigDir()
    g.app.extensionsDir = g.os_path_finalize_join(g.app.loadDir, '..', 'extensions')
    g.app.testDir = g.os_path_finalize_join(g.app.loadDir, '..', 'test')
</t>
<t tx="ekr.20120209051836.10253">def computeGlobalConfigDir(self):
    # lm = self
    # To avoid pylint complaints that sys.leo_config_directory does not exist.
    leo_config_dir = (
        hasattr(sys, 'leo_config_directory') and
        getattr(sys, 'leo_config_directory') or None)
    if leo_config_dir:
        theDir = leo_config_dir
    else:
        theDir = g.os_path_join(g.app.loadDir, "..", "config")
    if theDir:
        theDir = g.os_path_finalize(theDir)
    if (
        not theDir or
        not g.os_path_exists(theDir) or
        not g.os_path_isdir(theDir)
    ):
        theDir = None
    return theDir
</t>
<t tx="ekr.20120209051836.10254">def computeHomeDir(self):
    """Returns the user's home directory."""
    home = os.path.expanduser("~")
        # Windows searches the HOME, HOMEPATH and HOMEDRIVE
        # environment vars, then gives up.
    if home and len(home) &gt; 1 and home[0] == '%' and home[-1] == '%':
        # Get the indirect reference to the true home.
        home = os.getenv(home[1: -1], default=None)
    if home:
        # Important: This returns the _working_ directory if home is None!
        # This was the source of the 4.3 .leoID.txt problems.
        home = g.os_path_finalize(home)
        if (
            not g.os_path_exists(home) or
            not g.os_path_isdir(home)
        ):
            home = None
    # g.trace(home)
    return home
</t>
<t tx="ekr.20120209051836.10255">def computeLeoDir(self):
    # lm = self
    loadDir = g.app.loadDir
    return g.os_path_dirname(loadDir)
        # We don't want the result in sys.path
</t>
<t tx="ekr.20120209051836.10256">def computeLoadDir(self):
    """Returns the directory containing leo.py."""
    import sys
    try:
        # Fix a hangnail: on Windows the drive letter returned by
        # __file__ is randomly upper or lower case!
        # The made for an ugly recent files list.
        path = g.__file__ # was leo.__file__
        # g.trace(repr(path))
        if path:
            # Possible fix for bug 735938:
            # Do the following only if path exists.
            &lt;&lt; resolve symlinks &gt;&gt;
            if sys.platform == 'win32':
                if len(path) &gt; 2 and path[1] == ':':
                    # Convert the drive name to upper case.
                    path = path[0].upper() + path[1:]
            path = g.os_path_finalize(path)
            loadDir = g.os_path_dirname(path)
        else: loadDir = None
        if (
            not loadDir or
            not g.os_path_exists(loadDir) or
            not g.os_path_isdir(loadDir)
        ):
            loadDir = os.getcwd()
            # From Marc-Antoine Parent.
            if loadDir.endswith("Contents/Resources"):
                loadDir += "/leo/plugins"
            else:
                g.pr("Exception getting load directory")
        loadDir = g.os_path_finalize(loadDir)
        # g.trace(loadDir)
        return loadDir
    except Exception:
        print("Exception getting load directory")
        raise
</t>
<t tx="ekr.20120209051836.10257">if path.endswith('pyc'):
    srcfile = path[: -1]
    if os.path.islink(srcfile):
        path = os.path.realpath(srcfile)
</t>
<t tx="ekr.20120209051836.10260">def computeHomeLeoDir(self):
    # lm = self
    homeLeoDir = g.os_path_finalize_join(g.app.homeDir, '.leo')
    if not g.os_path_exists(homeLeoDir):
        g.makeAllNonExistentDirectories(homeLeoDir, force=True)
    return homeLeoDir
</t>
<t tx="ekr.20120209051836.10372">def computeLeoSettingsPath(self):
    '''Return the full path to leoSettings.leo.'''
    trace = False
    # lm = self
    join = g.os_path_finalize_join
    settings_fn = 'leoSettings.leo'
    table = (
        # First, leoSettings.leo in the home directories.
        join(g.app.homeDir, settings_fn),
        join(g.app.homeLeoDir, settings_fn),
        # Last, leoSettings.leo in leo/config directory.
        join(g.app.globalConfigDir, settings_fn)
    )
    for path in table:
        if trace: print('computeLeoSettingsPath', g.os_path_exists(path), repr(path))
        if g.os_path_exists(path):
            break
    else:
        path = None
    return path
</t>
<t tx="ekr.20120209051836.10373">def computeMyLeoSettingsPath(self):
    '''
    Return the full path to myLeoSettings.leo.

    The "footnote": Get the local directory from lm.files[0]
    '''
    trace = False
    lm = self
    join = g.os_path_finalize_join
    settings_fn = 'myLeoSettings.leo'
    # This seems pointless: we need a machine *directory*.
    # For now, however, we'll keep the existing code as is.
    machine_fn = lm.computeMachineName() + settings_fn
    # First, compute the directory of the first loaded file.
    # All entries in lm.files are full, absolute paths.
    localDir = g.os_path_dirname(lm.files[0]) if lm.files else None
    table = (
        # First, myLeoSettings.leo in the local directory
        join(localDir, settings_fn),
        # Next, myLeoSettings.leo in the home directories.
        join(g.app.homeDir, settings_fn),
        join(g.app.homeLeoDir, settings_fn),
        # Next, &lt;machine-name&gt;myLeoSettings.leo in the home directories.
        join(g.app.homeDir, machine_fn),
        join(g.app.homeLeoDir, machine_fn),
        # Last, leoSettings.leo in leo/config directory.
        join(g.app.globalConfigDir, settings_fn),
    )
    for path in table:
        if trace: print('computeMyLeoSettingsPath', g.os_path_exists(path), repr(path))
        if g.os_path_exists(path):
            break
    else:
        path = None
    return path
</t>
<t tx="ekr.20120211121736.10772">def computeWorkbookFileName(self):
    # lm = self
    # Get the name of the workbook.
    fn = g.app.config.getString(setting='default_leo_file')
        # The default is ~/.leo/workbook.leo
    if not fn and g.app.debug:
        g.es_debug("FAILED g.app.config.getString(setting='default_leo_file')")
        fn = g.os_path_finalize('~/.leo/workbook.leo')
    fn = g.os_path_finalize(fn)
    if not fn: return
    if g.os_path_exists(fn):
        return fn
    elif g.os_path_isabs(fn):
        # Create the file.
        g.error('Using default leo file name:\n%s' % (fn))
        return fn
    else:
        # It's too risky to open a default file if it is relative.
        return None
</t>
<t tx="ekr.20120211121736.10812"></t>
<t tx="ekr.20120213081706.10382">def readGlobalSettingsFiles(self):
    '''Read leoSettings.leo and myLeoSettings.leo using a null gui.'''
    trace = (False or g.trace_startup) and not g.unitTesting
    verbose = False
    lm = self
    if trace: g.es_debug()
    # Open the standard settings files with a nullGui.
    # Important: their commanders do not exist outside this method!
    paths = [lm.computeLeoSettingsPath(), lm.computeMyLeoSettingsPath()]
    old_commanders = g.app.commanders()
    commanders = [lm.openSettingsFile(path) for path in paths]
    commanders = [z for z in commanders if z]
    settings_d, shortcuts_d = lm.createDefaultSettingsDicts()
    for c in commanders:
        settings_d, shortcuts_d = lm.computeLocalSettings(
            c, settings_d, shortcuts_d, localFlag=False)
    # Adjust the name.
    shortcuts_d.setName('lm.globalShortcutsDict')
    if trace:
        if verbose:
            for c in commanders:
                print(c)
        lm.traceSettingsDict(settings_d, verbose)
        lm.traceShortcutsDict(shortcuts_d, verbose)
    lm.globalSettingsDict = settings_d
    lm.globalShortcutsDict = shortcuts_d
    # Clear the cache entries for the commanders.
    # This allows this method to be called outside the startup logic.
    for c in commanders:
        if c not in old_commanders:
            g.app.forgetOpenFile(c.fileName())
</t>
<t tx="ekr.20120213164030.10697">def computeMachineName(self):
    '''Return the name of the current machine, i.e, HOSTNAME.'''
    # This is prepended to leoSettings.leo or myLeoSettings.leo
    # to give the machine-specific setting name.
    # How can this be worth doing??
    try:
        import os
        name = os.getenv('HOSTNAME')
        if not name:
            name = os.getenv('COMPUTERNAME')
        if not name:
            import socket
            name = socket.gethostname()
    except Exception:
        name = ''
    # g.trace(name)
    return name
</t>
<t tx="ekr.20120214060149.15851">def __init__(self):
    trace = (False or g.trace_startup) and not g.unitTesting
    if trace: g.es_debug('(LoadManager)')
    # Global settings &amp; shortcuts dicts.
    # The are the defaults for computing settings and shortcuts for all loaded files.
    self.globalSettingsDict = None
        # A g.TypedDict containing the merger of default settings,
        # settings in leoSettings.leo and settings in myLeoSettings.leo
    self.globalShortcutsDict = None
        # A g.TypedDictOfLists containing the merger of shortcuts in
        # leoSettings.leo and settings in myLeoSettings.leo.
    # LoadManager ivars corresponding to user options....
    self.files = []
        # List of files to be loaded.
    self.options = {}
        # Dictionary of user options. Keys are option names.
    self.old_argv = []
        # A copy of sys.argv for debugging.
    self.more_cmdline_files = False
        # True when more files remain on the command line to be
        # loaded.  If the user is answering "No" to each file as Leo asks
        # "file already open, open again", this must be False for
        # a complete exit to be appropriate (finish_quit=True param for
        # closeLeoWindow())
    if 0: # use lm.options.get instead.
        self.script = None # The fileName of a script, or None.
        self.script_name = None
        self.script_path = None
        self.script_path_w = None
        self.screenshot_fn = None
        self.selectHeadline = None
        self.versionFlag = False
        self.windowFlag = False
        self.windowSize = None
    # Ivars of *other* classes corresponding to command-line arguments...
        # g.app.batchMode           Set in createNullGuiWithScript
        # g.app.gui = None          The gui class.
        # g.app.guiArgName          The gui name given in --gui option.
        # g.app.qt_use_tabs
        # g.app.silentMode
        # g.app.start_fullscreen
        # g.app.start_maximized    .
        # g.app.start_minimized
        # g.app.useIpython
        # g.app.use_splash_screen
        # g.enableDB                --no-cache
</t>
<t tx="ekr.20120214132927.10723">def mergeShortcutsDicts(self, c, old_d, new_d):
    '''Create a new dict by overriding all shortcuts in old_d by shortcuts in new_d.

    Both old_d and new_d remain unchanged.'''
    trace = False and not g.unitTesting
    lm = self
    if not old_d: return new_d
    if not new_d: return old_d
    if trace:
        new_n, old_n = len(list(new_d.keys())), len(list(old_d.keys()))
        g.trace('new %4s %s %s' % (new_n, id(new_d), new_d.name()))
        g.trace('old %4s %s %s' % (old_n, id(old_d), old_d.name()))
    inverted_old_d = lm.invert(old_d)
    inverted_new_d = lm.invert(new_d)
    # Fix bug 951921: check for duplicate shortcuts only in the new file.
    lm.checkForDuplicateShortcuts(c, inverted_new_d)
    inverted_old_d.update(inverted_new_d) # Updates inverted_old_d in place.
    result = lm.uninvert(inverted_old_d)
    return result
</t>
<t tx="ekr.20120214132927.10724">def invert(self, d):
    '''Invert a shortcut dict whose keys are command names,
    returning a dict whose keys are strokes.'''
    trace = False and not g.unitTesting; verbose = True
    if trace: g.trace('*' * 40, d.name())
    result = g.TypedDictOfLists(
        name='inverted %s' % d.name(),
        keyType=g.KeyStroke,
        valType=g.ShortcutInfo)
    for commandName in d.keys():
        for si in d.get(commandName, []):
            # This assert can fail if there is an exception in the ShortcutInfo ctor.
            assert isinstance(si, g.ShortcutInfo), si
            stroke = si.stroke # This is canonicalized.
            si.commandName = commandName # Add info.
            assert stroke
            if trace and verbose:
                g.trace('%40s %s' % (commandName, stroke))
            result.add(stroke, si)
    if trace: g.trace('returns  %4s %s %s' % (
        len(list(result.keys())), id(d), result.name()))
    return result
</t>
<t tx="ekr.20120214132927.10725">def uninvert(self, d):
    '''Uninvert an inverted shortcut dict whose keys are strokes,
    returning a dict whose keys are command names.'''
    trace = False and not g.unitTesting; verbose = True
    if trace and verbose: g.trace('*' * 40)
    assert d.keyType == g.KeyStroke, d.keyType
    result = g.TypedDictOfLists(
        name='uninverted %s' % d.name(),
        keyType=type('commandName'),
        valType=g.ShortcutInfo)
    for stroke in d.keys():
        for si in d.get(stroke, []):
            assert isinstance(si, g.ShortcutInfo), si
            commandName = si.commandName
            if trace and verbose:
                g.trace('uninvert %20s %s' % (stroke, commandName))
            assert commandName
            result.add(commandName, si)
    if trace: g.trace('returns %4s %s %s' % (
        len(list(result.keys())), id(d), result.name()))
    return result
</t>
<t tx="ekr.20120214165710.10726">def createSettingsDicts(self, c, localFlag):
    import leo.core.leoConfig as leoConfig
    parser = leoConfig.SettingsTreeParser(c, localFlag)
        # returns the *raw* shortcutsDict, not a *merged* shortcuts dict.
    shortcutsDict, settingsDict = parser.traverse()
    return shortcutsDict, settingsDict
</t>
<t tx="ekr.20120214165710.10822">def traceShortcutsDict(self, d, verbose=False):
    if verbose:
        print(d)
        for key in sorted(list(d.keys())):
            val = d.get(key)
            # print('%20s %s' % (key,val.dump()))
            print('%35s %s' % (key, [z.stroke for z in val]))
        if d: print('')
    else:
        print(d)
</t>
<t tx="ekr.20120214165710.10838">def traceSettingsDict(self, d, verbose=False):
    if verbose:
        print(d)
        for key in sorted(list(d.keys())):
            gs = d.get(key)
            print('%35s %17s %s' % (key, g.shortFileName(gs.path), gs.val))
        if d: print('')
    else:
        print(d)
</t>
<t tx="ekr.20120215062153.10740"></t>
<t tx="ekr.20120215072959.12478">def setRecentFiles(self, files):
    '''Update the recent files list.'''
    rf = self
    rf.appendToRecentFiles(files)
</t>
<t tx="ekr.20120219154958.10452">def load(self, fileName=None, pymacs=None):
    '''Load the indicated file'''
    lm = self
    # Phase 1: before loading plugins.
    # Scan options, set directories and read settings.
    if not lm.isValidPython(): return
    lm.doPrePluginsInit(fileName, pymacs)
        # sets lm.options and lm.files
    if lm.options.get('version'):
        print(g.app.signon)
        return
    if not g.app.gui:
        return
    # Phase 2: load plugins: the gui has already been set.
    g.doHook("start1")
    if g.app.killed: return
    g.app.idleTimeManager.start()
    # Phase 3: after loading plugins. Create one or more frames.
    ok = lm.doPostPluginsInit()
    if ok and g.app.diff:
        lm.doDiff()
    if ok:
        g.es('') # Clears horizontal scrolling in the log pane.
        g.app.gui.runMainLoop()
        # For scripts, the gui is a nullGui.
        # and the gui.setScript has already been called.
</t>
<t tx="ekr.20120219154958.10477">def doPrePluginsInit(self, fileName, pymacs):
    ''' Scan options, set directories and read settings.'''
    # trace = False
    lm = self
    lm.computeStandardDirectories()
    lm.adjustSysPath()
    # Scan the options as early as possible.
    lm.options = options = lm.scanOptions(fileName, pymacs)
        # also sets lm.files.
    if options.get('version'):
        g.app.computeSignon()
        return
    script = options.get('script')
    verbose = script is None
    # Init the app.
    lm.initApp(verbose)
    lm.reportDirectories(verbose)
    # Read settings *after* setting g.app.config and *before* opening plugins.
    # This means if-gui has effect only in per-file settings.
    lm.readGlobalSettingsFiles()
        # reads only standard settings files, using a null gui.
        # uses lm.files[0] to compute the local directory
        # that might contain myLeoSettings.leo.
    # Read the recent files file.
    localConfigFile = lm.files[0] if lm.files else None
    g.app.recentFilesManager.readRecentFiles(localConfigFile)
    g.app.setGlobalDb()
    # Create the gui after reading options and settings.
    lm.createGui(pymacs)
    # We can't print the signon until we know the gui.
    g.app.computeSignon() # Set app.signon/signon2 for commanders.
</t>
<t tx="ekr.20120219154958.10478">def createGui(self, pymacs):
    trace = (False or g.trace_startup) and not g.unitTesting
    if trace: g.es_debug()
    lm = self
    gui_option = lm.options.get('gui')
    windowFlag = lm.options.get('windowFlag')
    script = lm.options.get('script')
    if g.app.gui:
        if g.app.gui == g.app.nullGui:
            g.app.gui = None # Enable g.app.createDefaultGui
            g.app.createDefaultGui(__file__)
        else:
            # This can happen when launching Leo from IPython.
            g.trace('g.app.gui', g.app.gui)
    elif gui_option is None:
        if script and not windowFlag:
            # Always use null gui for scripts.
            g.app.createNullGuiWithScript(script)
        else:
            g.app.createDefaultGui(__file__)
    else:
        lm.createSpecialGui(gui_option, pymacs, script, windowFlag)
</t>
<t tx="ekr.20120219154958.10479">def createSpecialGui(self, gui, pymacs, script, windowFlag):
    # lm = self
    if pymacs:
        g.app.createNullGuiWithScript(script=None)
    elif script:
        if windowFlag:
            g.app.createDefaultGui()
            g.app.gui.setScript(script=script)
            sys.args = []
        else:
            g.app.createNullGuiWithScript(script=script)
    else:
        # assert g.app.guiArgName
        g.app.createDefaultGui()
</t>
<t tx="ekr.20120219154958.10480">def adjustSysPath(self):
    '''Adjust sys.path to enable imports as usual with Leo.

    This method is no longer needed:

        1. g.importModule will import from the
           'external' or 'extensions' folders as needed
           without altering sys.path.

        2.  Plugins now do fully qualified imports.
    '''
    pass
</t>
<t tx="ekr.20120219154958.10481">def completeFileName(self, fileName):
    fileName = g.toUnicode(fileName)
    fileName = g.os_path_finalize(fileName)
    # 2011/10/12: don't add .leo to *any* file.
    return fileName
</t>
<t tx="ekr.20120219154958.10482">def getDefaultFile(self):
    # Get the name of the workbook.
    fn = g.app.config.getString('default_leo_file')
    fn = g.os_path_finalize(fn)
    if not fn: return
    # g.trace(g.os_path_exists(fn),fn)
    if g.os_path_exists(fn):
        return fn
    elif g.os_path_isabs(fn):
        # Create the file.
        g.error('Using default leo file name:\n%s' % (fn))
        return fn
    else:
        # It's too risky to open a default file if it is relative.
        return None
</t>
<t tx="ekr.20120219154958.10483">def computeFilesList(self, fileName):
    lm = self
    files = []
    if fileName:
        files.append(fileName)
    for arg in sys.argv[1:]:
        if arg and not arg.startswith('-'):
            files.append(arg)
    result = []
    for z in files:
        # Fix #245: wrong: result.extend(glob.glob(lm.completeFileName(z)))
        aList = glob.glob(lm.completeFileName(z))
        if aList:
            result.extend(aList)
        else:
            result.append(z)
    return result
</t>
<t tx="ekr.20120219154958.10484">def initApp(self, verbose):
    trace = (False or g.trace_startup) and not g.unitTesting
    if trace: g.es_debug()
    assert g.app.loadManager
    import leo.core.leoBackground as leoBackground
    import leo.core.leoConfig as leoConfig
    import leo.core.leoNodes as leoNodes
    import leo.core.leoPlugins as leoPlugins
    import leo.core.leoSessions as leoSessions
    # Import leoIPython only if requested.  The import is quite slow.
    self.setStdStreams()
    if g.app.useIpython:
        import leo.core.leoIPython as leoIPython
            # This launches the IPython Qt Console.  It *is* required.
        assert leoIPython # suppress pyflakes/flake8 warning.
    # Make sure we call the new leoPlugins.init top-level function.
    leoPlugins.init()
    # Force the user to set g.app.leoID.
    g.app.setLeoID(verbose=verbose)
    # Create early classes *after* doing plugins.init()
    g.app.idleTimeManager = IdleTimeManager()
    g.app.backgroundProcessManager = leoBackground.BackgroundProcessManager()
    g.app.externalFilesController = leoExternalFiles.ExternalFilesController()
    g.app.recentFilesManager = RecentFilesManager()
    g.app.config = leoConfig.GlobalConfigManager()
    g.app.nodeIndices = leoNodes.NodeIndices(g.app.leoID)
    g.app.sessionManager = leoSessions.SessionManager()
    # Complete the plugins class last.
    g.app.pluginsController.finishCreate()
</t>
<t tx="ekr.20120219154958.10485">def reportDirectories(self, verbose):
    '''Report directories.'''
    if not verbose: return
    if 1: # old
        for kind, theDir in (
            ("load", g.app.loadDir),
            ("global config", g.app.globalConfigDir),
            ("home", g.app.homeDir),
        ):
            # g.blue calls g.es_print, and that's annoying.
            g.es("%s dir:" % (kind), theDir, color='blue')
    else:
        aList = (
            'homeDir', 'homeLeoDir',
            'leoDir', 'loadDir',
            'extensionsDir', 'globalConfigDir')
        for ivar in aList:
            val = getattr(g.app, ivar)
            g.trace('%20s' % (ivar), val)
</t>
<t tx="ekr.20120219154958.10486">def scanOptions(self, fileName, pymacs):
    '''Handle all options, remove them from sys.argv and set lm.options.'''
    trace = False
    lm = self
    # print('scanOptions',sys.argv)
    lm.old_argv = sys.argv[:]
    # Note: this automatically implements the --help option.
    usage = "usage: launchLeo.py [options] file1, file2, ..."
    parser = optparse.OptionParser(usage=usage)
    add = parser.add_option
    add('--debug', action='store_true',
        help='enable debug mode')
    add('--diff', action='store_true', dest='diff',
        help='use Leo as an external git diff')
    add('--fullscreen', action='store_true',
        help='start fullscreen')
    add('--ipython', action='store_true', dest='use_ipython',
        help='enable ipython support')
    add('--gui',
        help='gui to use (qt/qttabs)')
    add('--load-type', dest='load_type',
        help='@&lt;file&gt; type for loading non-outlines from command line')
    add('--maximized', action='store_true',
        help='start maximized')
    add('--minimized', action='store_true',
        help='start minimized')
    add('--no-cache', action='store_true', dest='no_cache',
        help='disable reading of cached files')
    add('--no-plugins', action='store_true', dest='no_plugins',
        help='disable all plugins')
    add('--no-splash', action='store_true', dest='no_splash_screen',
        help='disable the splash screen')
    add('--screen-shot', dest='screenshot_fn',
        help='take a screen shot and then exit')
    add('--script', dest='script',
        help='execute a script and then exit')
    add('--script-window', dest='script_window',
        help='open a window for scripts')
    add('--select', dest='select',
        help='headline or gnx of node to select')
    add('--silent', action='store_true', dest='silent',
        help='disable all log messages')
    add('--trace-plugins', action='store_true', dest='trace_plugins',
        help='trace imports of plugins')
    add('-v', '--version', action='store_true', dest='version',
        help='print version number and exit')
    add('--window-size', dest='window_size',
        help='initial window size (height x width)')
    # Parse the options, and remove them from sys.argv.
    options, args = parser.parse_args()
    sys.argv = [sys.argv[0]]; sys.argv.extend(args)
    if trace:
        # print('scanOptions:',sys.argv)
        g.trace('options', options)
    # Handle the args...
    # --debug
    g.app.debug = options.debug
    # if g.app.debug: g.trace_startup = True
    # --git-diff
    if options.diff:
        g.app.diff = options.diff
    # --gui
    gui = options.gui
    if gui:
        gui = gui.lower()
        if gui == 'qttabs':
            g.app.qt_use_tabs = True
        elif gui in ('curses', 'qt', 'null'):
            g.app.qt_use_tabs = False
        else:
            print('scanOptions: unknown gui: %s.  Using qt gui' % gui)
            gui = 'qt'
            g.app.qt_use_tabs = False
    elif sys.platform == 'darwin':
        gui = 'qt'
        g.app.qt_use_tabs = False
    else:
        gui = 'qttabs'
        g.app.qt_use_tabs = True
    assert gui
    g.app.guiArgName = gui
    # --load-type
    load_type = options.load_type
    if load_type:
        load_type = load_type.lower()
    else:
        load_type = 'edit'
    load_type = '@' + load_type
    # --ipython
    g.app.useIpython = options.use_ipython
    if trace: g.trace('g.app.useIpython', g.app.useIpython)
    # --fullscreen
    # --minimized
    # --maximized
    g.app.start_fullscreen = options.fullscreen
    g.app.start_maximized = options.maximized
    g.app.start_minimized = options.minimized
    # --no-cache
    if options.no_cache:
        if trace: print('scanOptions: disabling caching')
        g.enableDB = False
    # --no-plugins
    if options.no_plugins:
        if trace: print('scanOptions: disabling plugins')
        g.app.enablePlugins = False
    # --no-splash: --minimized disables the splash screen
    g.app.use_splash_screen = (
        not options.no_splash_screen and
        not options.minimized)
    # --screen-shot=fn
    screenshot_fn = options.screenshot_fn
    if screenshot_fn:
        screenshot_fn = screenshot_fn.strip('"')
        if trace: print('scanOptions: screenshot_fn', screenshot_fn)
    # --script
    script_path = options.script
    script_path_w = options.script_window
    if script_path and script_path_w:
        parser.error('--script and script-window are mutually exclusive')
    script_name = script_path or script_path_w
    if script_name:
        script_name = g.os_path_finalize_join(g.app.loadDir, script_name)
        script, e = g.readFileIntoString(script_name, kind='script:')
        # print('script_name',repr(script_name))
    else:
        script = None
        # if trace: print('scanOptions: no script')
    # --select
    select = options.select
    if select:
        select = select.strip('"')
        if trace: print('scanOptions: select', repr(select))
    # --silent
    g.app.silentMode = options.silent
    # print('scanOptions: silentMode',g.app.silentMode)
    # --trace-plugins
    g.app.trace_plugins = options.trace_plugins
    # --version: print the version and exit.
    versionFlag = options.version
    # --window-size
    windowSize = options.window_size
    if windowSize:
        if trace: print('windowSize', repr(windowSize))
        try:
            h, w = windowSize.split('x')
            windowSize = int(h), int(w)
        except ValueError:
            windowSize = None
            g.trace('bad --window-size:', windowSize)
    # Compute lm.files
    lm.files = lm.computeFilesList(fileName)
    # if options.debug:
    #    g.es_debug('lm.files',lm.files)
    # Post-process the options.
    if pymacs:
        script = None
        windowFlag = None
    # Compute the return values.
    windowFlag = script and script_path_w
    d = {
        'gui': gui,
        'load_type': load_type,
        'screenshot_fn': screenshot_fn,
        'script': script,
        'select': select,
        'version': versionFlag,
        'windowFlag': windowFlag,
        'windowSize': windowSize,
    }
    if trace: g.trace(d)
    return d
</t>
<t tx="ekr.20120219154958.10487">def doPostPluginsInit(self):
    '''Create a Leo window for each file in the lm.files list.'''
    # Clear g.app.initing _before_ creating commanders.
    lm = self
    g.app.initing = False # "idle" hooks may now call g.app.forceShutdown.
    # Create the main frame.  Show it and all queued messages.
    c = c1 = None
    if lm.files:
        for n, fn in enumerate(lm.files):
            lm.more_cmdline_files = n &lt; len(lm.files) - 1
            c = lm.loadLocalFile(fn, gui=g.app.gui, old_c=None)
                # Returns None if the file is open in another instance of Leo.
            if not c1: c1 = c
    if g.app.restore_session:
        m = g.app.sessionManager
        if m:
            aList = m.load_snapshot()
            if aList:
                m.load_session(c1, aList)
                c = c1 = g.app.windowList[0].c
    if not c1 or not g.app.windowList:
        c1 = lm.openEmptyWorkBook()
    # Fix bug #199.
    g.app.runAlreadyOpenDialog(c1)
    # Put the focus in the first-opened file.
    fileName = lm.files[0] if lm.files else None
    c = c1
    # For qttabs gui, select the first-loaded tab.
    if hasattr(g.app.gui, 'frameFactory'):
        factory = g.app.gui.frameFactory
        if factory and hasattr(factory, 'setTabForCommander'):
            factory.setTabForCommander(c)
    if not c:
        return False # Force an immediate exit.
    # Fix bug 844953: tell Unity which menu to use.
    if c: c.enableMenuBar()
    # Do the final inits.
    g.app.logInited = True
    g.app.initComplete = True
    if c: c.setLog()
    # print('doPostPluginsInit: ***** set log')
    p = c and c.p or None
    g.doHook("start2", c=c, p=p, v=p, fileName=fileName)
    if c: lm.initFocusAndDraw(c, fileName)
    screenshot_fn = lm.options.get('screenshot_fn')
    if screenshot_fn:
        lm.make_screen_shot(screenshot_fn)
        return False # Force an immediate exit.
    else:
        return True
</t>
<t tx="ekr.20120219154958.10488">def initFocusAndDraw(self, c, fileName):

    def init_focus_handler(timer, c=c, p=c.p):
        '''Idle-time handler for initFocusAndDraw'''
        c.initialFocusHelper()
        c.outerUpdate()
        timer.stop()

    # This must happen after the code in getLeoFile.
    timer = g.IdleTime(init_focus_handler, delay=0.1, tag='getLeoFile')
    if timer:
        timer.start()
    else:
        # Default code.
        c.selectPosition(c.p)
        c.initialFocusHelper()
        c.k.showStateAndMode()
        c.outerUpdate()
</t>
<t tx="ekr.20120219154958.10489">def make_screen_shot(self, fn):
    '''Create a screenshot of the present Leo outline and save it to path.'''
    # g.trace('runLeo.py',fn)
    if g.app.gui.guiName() == 'qt':
        m = g.loadOnePlugin('screenshots')
        m.make_screen_shot(fn)
</t>
<t tx="ekr.20120219154958.10491">def isValidPython(self):
    if sys.platform == 'cli':
        return True
    minimum_python_version = '2.6'
    message = """\
Leo requires Python %s or higher.
You may download Python from
http://python.org/download/
""" % minimum_python_version
    try:
        version = '.'.join([str(sys.version_info[i]) for i in (0, 1, 2)])
        ok = g.CheckVersion(version, minimum_python_version)
        if not ok:
            print(message)
            try:
                # g.app.gui does not exist yet.
                import Tkinter as Tk
                &lt;&lt; define emergency dialog class &gt;&gt;
                d = EmergencyDialog(
                    title='Python Version Error',
                    message=message)
                d.run()
            except Exception:
                pass
        return ok
    except Exception:
        print("isValidPython: unexpected exception: g.CheckVersion")
        traceback.print_exc()
        return 0
</t>
<t tx="ekr.20120219154958.10492">class EmergencyDialog(object):
    """A class that creates an Tkinter dialog with a single OK button."""
    @others
</t>
<t tx="ekr.20120219154958.10493">def __init__(self, title, message):
    """Constructor for the leoTkinterDialog class."""
    self.answer = None # Value returned from run()
    self.title = title
    self.message = message
    self.buttonsFrame = None # Frame to hold typical dialog buttons.
    self.defaultButtonCommand = None
        # Command to call when user closes the window
        # by clicking the close box.
    self.frame = None # The outermost frame.
    self.root = None # Created in createTopFrame.
    self.top = None # The toplevel Tk widget.
    self.createTopFrame()
    buttons = {"text": "OK", "command": self.okButton, "default": True},
        # Singleton tuple.
    self.createButtons(buttons)
    self.top.bind("&lt;Key&gt;", self.onKey)
</t>
<t tx="ekr.20120219154958.10494">def createButtons(self, buttons):
    """Create a row of buttons.

    buttons is a list of dictionaries containing
    the properties of each button."""
    assert(self.frame)
    self.buttonsFrame = f = Tk.Frame(self.top)
    f.pack(side="top", padx=30)
    # Buttons is a list of dictionaries, with an empty dictionary
    # at the end if there is only one entry.
    buttonList = []
    for d in buttons:
        text = d.get("text", "&lt;missing button name&gt;")
        isDefault = d.get("default", False)
        underline = d.get("underline", 0)
        command = d.get("command", None)
        bd = 4 if isDefault else 2
        b = Tk.Button(f, width=6, text=text, bd=bd,
            underline=underline, command=command)
        b.pack(side="left", padx=5, pady=10)
        buttonList.append(b)
        if isDefault and command:
            self.defaultButtonCommand = command
    return buttonList
</t>
<t tx="ekr.20120219154958.10495">def createTopFrame(self):
    """Create the Tk.Toplevel widget for a leoTkinterDialog."""
    self.root = Tk.Tk()
    self.top = Tk.Toplevel(self.root)
    self.top.title(self.title)
    self.root.withdraw()
    self.frame = Tk.Frame(self.top)
    self.frame.pack(side="top", expand=1, fill="both")
    label = Tk.Label(self.frame, text=message, bg='white')
    label.pack(pady=10)
</t>
<t tx="ekr.20120219154958.10496">def okButton(self):
    """Do default click action in ok button."""
    self.top.destroy()
    self.top = None
</t>
<t tx="ekr.20120219154958.10497">def onKey(self, event):
    """Handle Key events in askOk dialogs."""
    self.okButton()
    return # (for Tk) "break"
</t>
<t tx="ekr.20120219154958.10498">def run(self):
    """Run the modal emergency dialog."""
    self.top.geometry("%dx%d%+d%+d" % (300, 200, 50, 50))
    self.top.lift()
    self.top.grab_set() # Make the dialog a modal dialog.
    self.root.wait_window(self.top)
</t>
<t tx="ekr.20120219194520.10463">import leo.core.leoGlobals as g
import leo.core.leoExternalFiles as leoExternalFiles
try:
    import builtins # Python 3
except ImportError:
    import __builtin__ as builtins # Python 2.
import glob
import os
import optparse
import string
import sys
# import time
import traceback
import zipfile
import platform
if g.isPython3:
    import io
    StringIO = io.StringIO
else:
    import cStringIO
    StringIO = cStringIO.StringIO
</t>
<t tx="ekr.20120222103014.10312">def openSettingsFile(self, fn):
    '''
    Open a settings file with a null gui.  Return the commander.

    The caller must init the c.config object.
    '''
    lm = self
    if not fn: return None
    giveMessage = (
        not g.app.unitTesting and
        not g.app.silentMode and
        not g.app.batchMode)
        # and not g.app.inBridge

    def message(s):
        # This occurs early in startup, so use the following.
        if not giveMessage: return
        if not g.isPython3:
            s = g.toEncodedString(s, 'ascii')
        g.blue(s)

    theFile = lm.openLeoOrZipFile(fn)
    if theFile:
        message('reading settings in %s' % (fn))
    # Changing g.app.gui here is a major hack.  It is necessary.
    oldGui = g.app.gui
    g.app.gui = g.app.nullGui
    c = g.app.newCommander(fn)
    frame = c.frame
    frame.log.enable(False)
    g.app.lockLog()
    g.app.openingSettingsFile = True
    try:
        ok = c.fileCommands.openLeoFile(theFile, fn,
            readAtFileNodesFlag=False, silent=True)
                # closes theFile.
    finally:
        g.app.openingSettingsFile = False
    g.app.unlockLog()
    c.openDirectory = frame.openDirectory = g.os_path_dirname(fn)
    g.app.gui = oldGui
    return ok and c or None
</t>
<t tx="ekr.20120223062418.10393">def loadLocalFile(self, fn, gui, old_c):
    '''Completely read a file, creating the corresponding outline.

    1. If fn is an existing .leo file (possibly zipped), read it twice:
    the first time with a NullGui to discover settings,
    the second time with the requested gui to create the outline.

    2. If fn is an external file:
    get settings from the leoSettings.leo and myLeoSetting.leo, then
    create a "wrapper" outline containing an @file node for the external file.

    3. If fn is empty:
    get settings from the leoSettings.leo and myLeoSetting.leo or default settings,
    or open an empty outline.
    '''
    trace = (False or g.trace_startup) and not g.unitTesting
    if trace: g.es_debug(fn)
    lm = self
    # Step 0: Return if the file is already open.
    fn = g.os_path_finalize(fn)
    if fn:
        c = lm.findOpenFile(fn)
        if c:
            if trace: g.trace('Already open: %s' % (fn))
            return c
    # Step 1: get the previous settings.
    # For .leo files (and zipped .leo files) this pre-reads the file in a null gui.
    # Otherwise, get settings from leoSettings.leo, myLeoSettings.leo, or default settings.
    previousSettings = lm.getPreviousSettings(fn)
    # Step 2: open the outline in the requested gui.
    # For .leo files (and zipped .leo file) this opens the file a second time.
    c = lm.openFileByName(fn, gui, old_c, previousSettings)
    return c
</t>
<t tx="ekr.20120223062418.10394">def openFileByName(self, fn, gui, old_c, previousSettings):
    '''Read the local file whose full path is fn using the given gui.
    fn may be a Leo file (including .leo or zipped file) or an external file.

    This is not a pre-read: the previousSettings always exist and
    the commander created here persists until the user closes the outline.

    Reads the entire outline if fn exists and is a .leo file or zipped file.
    Creates an empty outline if fn is a non-existent Leo file.
    Creates an wrapper outline if fn is an external file, existing or not.
    '''
    trace = (False or g.trace_startup) and not g.unitTesting
    if trace: g.es_debug(g.shortFileName(fn))
    lm = self
    # Disable the log.
    g.app.setLog(None)
    g.app.lockLog()
    # Create the a commander for the .leo file.
    # Important.  The settings don't matter for pre-reads!
    # For second read, the settings for the file are *exactly* previousSettings.
    c = g.app.newCommander(fileName=fn, gui=gui,
        previousSettings=previousSettings)
    assert c
    # Open the file, if possible.
    g.doHook('open0')
    theFile = lm.openLeoOrZipFile(fn)
    # Enable the log.
    g.app.unlockLog()
    c.frame.log.enable(True)
    # Phase 2: Create the outline.
    g.doHook("open1", old_c=None, c=c, new_c=c, fileName=fn)
    if theFile:
        readAtFileNodesFlag = bool(previousSettings)
        # The log is not set properly here.
        ok = lm.readOpenedLeoFile(c, fn, readAtFileNodesFlag, theFile)
            # Call c.fileCommands.openLeoFile to read the .leo file.
        if not ok: return None
    else:
        # Create a wrapper .leo file if:
        # a) fn is a .leo file that does not exist or
        # b) fn is an external file, existing or not.
        lm.initWrapperLeoFile(c, fn)
    g.doHook("open2", old_c=None, c=c, new_c=c, fileName=fn)
    # Phase 3: Complete the initialization.
    g.app.writeWaitingLog(c)
    c.setLog()
    lm.createMenu(c, fn)
    lm.finishOpen(c)
    return c
</t>
<t tx="ekr.20120223062418.10405">def createMenu(self, c, fn=None):
    # lm = self
    # Create the menu as late as possible so it can use user commands.
    if not g.doHook("menu1", c=c, p=c.p, v=c.p):
        c.frame.menu.createMenuBar(c.frame)
        g.app.recentFilesManager.updateRecentFiles(fn)
        g.doHook("menu2", c=c, p=c.p, v=c.p)
        g.doHook("after-create-leo-frame", c=c)
        g.doHook("after-create-leo-frame2", c=c)
        # Fix bug 844953: tell Unity which menu to use.
        c.enableMenuBar()
</t>
<t tx="ekr.20120223062418.10406">def findOpenFile(self, fn):
    # lm = self

    def munge(name):
        return g.os_path_normpath(name or '').lower()

    for frame in g.app.windowList:
        c = frame.c
        if g.os_path_realpath(munge(fn)) == g.os_path_realpath(munge(c.mFileName)):
            # don't frame.bringToFront(), it breaks --minimize
            c.setLog()
            # 2011/11/21: selecting the new tab ensures focus is set.
            master = hasattr(frame.top, 'leo_master') and frame.top.leo_master
            if master: # frame.top.leo_master is a TabbedTopLevel.
                master.select(frame.c)
            c.outerUpdate()
            return c
    return None
</t>
<t tx="ekr.20120223062418.10407">def finishOpen(self, c):
    # lm = self
    k = c.k
    assert k
    # New in Leo 4.6: provide an official way for very late initialization.
    c.frame.tree.initAfterLoad()
    c.initAfterLoad()
    c.redraw()
    # chapterController.finishCreate must be called after the first real redraw
    # because it requires a valid value for c.rootPosition().
    if c.chapterController: c.chapterController.finishCreate()
    if k: k.setDefaultInputState()
    c.initialFocusHelper()
    if k: k.showStateAndMode()
    c.frame.initCompleteHint()
    c.outerUpdate()
        # Honor focus requests.
        # This fixes bug 181: Focus remains in previous file
        # https://github.com/leo-editor/leo-editor/issues/181
</t>
<t tx="ekr.20120223062418.10408">def initWrapperLeoFile(self, c, fn):
    '''
    Create an empty file if the external fn is empty.

    Otherwise, create an @edit or @file node for the external file.
    '''
    # lm = self
    # Use the config params to set the size and location of the window.
    frame = c.frame
    frame.setInitialWindowGeometry()
    frame.deiconify()
    frame.lift()
    frame.resizePanesToRatio(frame.ratio, frame.secondary_ratio)
        # Resize the _new_ frame.
    if not g.os_path_exists(fn):
        p = c.rootPosition()
        # Create an empty @edit node unless fn is an .leo file.
        p.h = g.shortFileName(fn) if fn.endswith('.leo') else '@edit %s' % fn
        c.selectPosition(p)
    elif c.looksLikeDerivedFile(fn):
        # 2011/10/10: Create an @file node.
        p = c.importCommands.importDerivedFiles(parent=c.rootPosition(),
            paths=[fn], command=None) # Not undoable.
        if p and p.hasBack():
            p.back().doDelete()
            p = c.rootPosition()
        if not p: return None
    else:
        # Create an @&lt;file&gt; node.
        p = c.rootPosition()
        if p:
            load_type = self.options['load_type']
            p.setHeadString('%s %s' % (load_type,fn))
            c.refreshFromDisk()
            c.selectPosition(p)

    # Fix critical bug 1184855: data loss with command line 'leo somefile.ext'
    # Fix smallish bug 1226816 Command line "leo xxx.leo" creates file xxx.leo.leo.
    c.mFileName = fn if fn.endswith('.leo') else '%s.leo' % (fn)
    c.wrappedFileName = fn
    c.frame.title = c.computeWindowTitle(c.mFileName)
    c.frame.setTitle(c.frame.title)
    # chapterController.finishCreate must be called after the first real redraw
    # because it requires a valid value for c.rootPosition().
    if c.config.getBool('use_chapters') and c.chapterController:
        c.chapterController.finishCreate()
    frame.c.clearChanged()
        # Mark the outline clean.
        # This makes it easy to open non-Leo files for quick study.
    return c
</t>
<t tx="ekr.20120223062418.10410">def openZipFile(self, fn):
    # lm = self
    try:
        theFile = zipfile.ZipFile(fn, 'r')
        if not theFile: return None
        # Read the file into an StringIO file.
        aList = theFile.namelist()
        name = aList and len(aList) == 1 and aList[0]
        if not name: return None
        s = theFile.read(name)
        if g.isPython3: s = g.ue(s, 'utf-8')
        return StringIO(s)
    except IOError:
        # Do not use string + here: it will fail for non-ascii strings!
        if not g.unitTesting:
            g.error("can not open:", fn)
        return None
</t>
<t tx="ekr.20120223062418.10412">def readOpenedLeoFile(self, c, fn, readAtFileNodesFlag, theFile):
    # New in Leo 4.10: The open1 event does not allow an override of the init logic.
    assert theFile
    # lm = self
    ok = c.fileCommands.openLeoFile(theFile, fn,
        readAtFileNodesFlag=readAtFileNodesFlag)
            # closes file.
    if ok:
        if not c.openDirectory:
            theDir = c.os_path_finalize(g.os_path_dirname(fn))
            c.openDirectory = c.frame.openDirectory = theDir
    else:
        g.app.closeLeoWindow(c.frame, finish_quit=self.more_cmdline_files is False)
    return ok
</t>
<t tx="ekr.20120223062418.10414">def getPreviousSettings(self, fn):
    '''
    Return the settings in effect for fn. Typically, this involves
    pre-reading fn.
    '''
    lm = self
    settingsName = 'settings dict for %s' % g.shortFileName(fn)
    shortcutsName = 'shortcuts dict for %s' % g.shortFileName(fn)
    # A special case: settings in leoSettings.leo do *not* override
    # the global settings, that is, settings in myLeoSettings.leo.
    isLeoSettings = g.shortFileName(fn).lower() == 'leosettings.leo'
    exists = g.os_path_exists(fn)
    if fn and exists and lm.isLeoFile(fn) and not isLeoSettings:
        # Open the file using a null gui.
        try:
            g.app.preReadFlag = True
            c = lm.openSettingsFile(fn)
        finally:
            g.app.preReadFlag = False
        # Merge the settings from c into *copies* of the global dicts.
        d1, d2 = lm.computeLocalSettings(c,
            lm.globalSettingsDict, lm.globalShortcutsDict, localFlag=True)
                # d1 and d2 are copies.
        d1.setName(settingsName)
        d2.setName(shortcutsName)
    else:
        # Get the settings from the globals settings dicts.
        d1 = lm.globalSettingsDict.copy(settingsName)
        d2 = lm.globalShortcutsDict.copy(shortcutsName)
    return PreviousSettings(d1, d2)
</t>
<t tx="ekr.20120223062418.10416">def openLeoFile(self, fn):
    # lm = self
    try:
        theFile = open(fn, 'rb')
        return theFile
    except IOError:
        # Do not use string + here: it will fail for non-ascii strings!
        if not g.unitTesting:
            g.error("can not open:", fn)
        return None
</t>
<t tx="ekr.20120223062418.10419">def isLeoFile(self, fn):
    return fn and (zipfile.is_zipfile(fn) or fn.endswith('.leo'))

def isZippedFile(self, fn):
    return fn and zipfile.is_zipfile(fn)
</t>
<t tx="ekr.20120223062418.10420">class PreviousSettings(object):
    '''A class holding the settings and shortcuts dictionaries
    that are computed in the first pass when loading local
    files and passed to the second pass.'''

    def __init__(self, settingsDict, shortcutsDict):
        assert g.isTypedDict(settingsDict)
        assert g.isTypedDictOfLists(shortcutsDict)
        self.settingsDict = settingsDict
        self.shortcutsDict = shortcutsDict

    def __repr__(self):
        return '&lt;PreviousSettings\n%s\n%s\n&gt;' % (
            self.settingsDict, self.shortcutsDict)

    __str__ = __repr__
</t>
<t tx="ekr.20120223062418.10421">def computeLocalSettings(self, c, settings_d, shortcuts_d, localFlag):
    '''Merge the settings dicts from c's outline into *new copies of*
    settings_d and shortcuts_d.'''
    trace = (False or g.trace_startup) and not g.unitTesting
    if trace: g.es_debug('%s\n%s\n%s' % (
        c.shortFileName(), settings_d, shortcuts_d))
    lm = self
    shortcuts_d2, settings_d2 = lm.createSettingsDicts(c, localFlag)
    assert shortcuts_d
    assert settings_d
    if settings_d2:
        settings_d = settings_d.copy()
        settings_d.update(settings_d2)
    if shortcuts_d2:
        shortcuts_d = lm.mergeShortcutsDicts(c, shortcuts_d, shortcuts_d2)
    return settings_d, shortcuts_d
</t>
<t tx="ekr.20120224161905.10030">def openLeoOrZipFile(self, fn):
    lm = self
    zipped = lm.isZippedFile(fn)
    if lm.isLeoFile(fn) and g.os_path_exists(fn):
        if zipped:
            theFile = lm.openZipFile(fn)
        else:
            theFile = lm.openLeoFile(fn)
    else:
        theFile = None
    return theFile
</t>
<t tx="ekr.20120225072226.10283">class RecentFilesManager(object):
    '''A class to manipulate leoRecentFiles.txt.'''

    def __init__(self):
        self.groupedMenus = []
            # Set in rf.createRecentFilesMenuItems.
        self.recentFiles = []
            # List of g.Bunches describing .leoRecentFiles.txt files.
        self.recentFileMessageWritten = False
            # To suppress all but the first message.
        self.write_recent_files_as_needed = False
            # Will be set later.
    @others
</t>
<t tx="ekr.20120225072226.10285">def sanitize(self, name):
    '''Return a sanitized file name.'''
    if name is None:
        return None
    name = name.lower()
    for ch in ('-', '_', ' ', '\n'):
        name = name.replace(ch, '')
    return name or None
</t>
<t tx="ekr.20120225072226.10286">def getRecentFiles(self):
    # Fix #299: Leo loads a deleted file.
    self.recentFiles = [z for z in self.recentFiles
        if g.os_path_exists(z)]
    # g.trace('\n'.join([z for z in self.recentFiles]))
    return self.recentFiles
</t>
<t tx="ekr.20120225072226.10289">def cleanRecentFiles(self, c):
    '''Remove items from the recent files list that are no longer valid.'''
    rf = self
    dat = c.config.getData('path-demangle')
    if not dat:
        g.es('No @data path-demangle setting')
        return
    changes = []
    replace = None
    for line in dat:
        text = line.strip()
        if text.startswith('REPLACE: '):
            replace = text.split(None, 1)[1].strip()
        if text.startswith('WITH:') and replace is not None:
            with_ = text[5:].strip()
            changes.append((replace, with_))
            g.es('%s -&gt; %s' % changes[-1])
    orig = [z for z in rf.recentFiles if z.startswith("/")]
    rf.recentFiles = []
    for i in orig:
        t = i
        for change in changes:
            t = t.replace(*change)
        rf.updateRecentFiles(t)
    rf.writeRecentFilesFile(c, force=True)
        # Force the write message.
</t>
<t tx="ekr.20120225072226.10293">def sortRecentFiles(self, c):
    '''Sort the recent files list.'''
    rf = self
    aList = rf.recentFiles
    aList.sort(key=lambda s: g.os_path_basename(s).lower())
    aList.reverse()
    rf.recentFiles = []
    for z in aList:
        rf.updateRecentFiles(z)
    rf.writeRecentFilesFile(c, force=True)
        # Force the write message.
</t>
<t tx="ekr.20120225072226.10297">def clearRecentFiles(self, c):
    """Clear the recent files list, then add the present file."""
    rf = self; u = c.undoer; menu = c.frame.menu
    bunch = u.beforeClearRecentFiles()
    recentFilesMenu = menu.getMenu("Recent Files...")
    menu.deleteRecentFilesMenuItems(recentFilesMenu)
    rf.recentFiles = [c.fileName()]
    for frame in g.app.windowList:
        rf.createRecentFilesMenuItems(frame.c)
    u.afterClearRecentFiles(bunch)
    # Write the file immediately.
    rf.writeRecentFilesFile(c, force=True)
        # Force the write message.
</t>
<t tx="ekr.20120225072226.10301">def createRecentFilesMenuItems(self, c):
    rf = self
    menu = c.frame.menu
    recentFilesMenu = menu.getMenu("Recent Files...")
    if not recentFilesMenu and not g.unitTesting:
        # g.trace('Recent Files Menu does not exist',g.callers())
        return
    # Delete all previous entries.
    menu.deleteRecentFilesMenuItems(recentFilesMenu)
    # Create the permanent (static) menu entries.
    table = rf.getRecentFilesTable()
    menu.createMenuEntries(recentFilesMenu, table)
    # Create all the other entries (a maximum of 36).
    accel_ch = string.digits + string.ascii_uppercase # Not a unicode problem.
    i = 0
    n = len(accel_ch)
    # see if we're grouping when files occur in more than one place
    rf_group = c.config.getBool("recent_files_group")
    rf_always = c.config.getBool("recent_files_group_always")
    groupedEntries = rf_group or rf_always
    if groupedEntries: # if so, make dict of groups
        dirCount = {}
        for fileName in rf.getRecentFiles()[: n]:
            dirName, baseName = g.os_path_split(fileName)
            if baseName not in dirCount:
                dirCount[baseName] = {'dirs': [], 'entry': None}
            dirCount[baseName]['dirs'].append(dirName)
    for name in rf.getRecentFiles()[: n]:
        # pylint: disable=cell-var-from-loop
        if name.strip() == "":
            continue # happens with empty list/new file

        def recentFilesCallback(event=None, c=c, name=name):
            c.openRecentFile(name)

        if groupedEntries:
            dirName, baseName = g.os_path_split(name)
            entry = dirCount[baseName]
            if len(entry['dirs']) &gt; 1 or rf_always: # sub menus
                if entry['entry'] is None:
                    entry['entry'] = menu.createNewMenu(baseName, "Recent Files...")
                    # acts as a flag for the need to create the menu
                c.add_command(menu.getMenu(baseName), label=dirName,
                    command=recentFilesCallback, underline=0)
            else: # single occurrence, no submenu
                c.add_command(recentFilesMenu, label=baseName,
                    command=recentFilesCallback, underline=0)
        else: # original behavior
            label = "%s %s" % (accel_ch[i], g.computeWindowTitle(name))
            c.add_command(recentFilesMenu, label=label,
                command=recentFilesCallback, underline=0)
        i += 1
    if groupedEntries: # store so we can delete them later
        rf.groupedMenus = [z for z in dirCount
            if dirCount[z]['entry'] is not None]
</t>
<t tx="ekr.20120225072226.10304">def getRecentFilesTable(self):
    return (
        "*clear-recent-files",
        "*clean-recent-files",
        "*sort-recent-files",
        # ("-",None,None),
    )
</t>
<t tx="ekr.20120229094652.15099">Put @command nodes as children of an @commands node in myLeoSettings.leo. This makes the @command nodes available to all opened .leo files.

Using @command rather than @button means that there is never any need to disable scripts. There is no need for @button. To see the list of your @command nodes, type::

    &lt;alt-x&gt;@c&lt;tab&gt;

Similarly to see the list of your @button nodes, type::

    &lt;alt-x&gt;@b&lt;tab&gt;
</t>
<t tx="ekr.20120229094652.15124">It sometimes happens that the focus gets left in a Leo widget that doesn't support Leo's key bindings. You would think that you would have to use the mouse to click in, say, the body pane so that you can use Leo's key bindings again.

But you don't have to do that.  Instead, use Alt-tab once to change away from Leo, and then use Alt-tab again to change back to Leo.  When you do this, Leo puts focus in the body pane and you are all set.
</t>
<t tx="ekr.20120229094652.15130">@pagewidth 75

Q. When I run the following script I see a window appear and then immediately disappear::

    from leo.core.leoQt import QtWidgets, QtCore
    w = QtWidgets.QWidget()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Simple test')
    w.show()

What's going on?

A. When the script exits the sole reference to the window, w, ceases to exist, so the window is destroyed (garbage collected). To keep the window open, add the following code as the last line to keep the reference alive::

    g.app.scriptsDict['my-script_w'] = w

This reference will persist until the next time you run the execute-script. If you want something even more permanent, you can do something like::

    g.app.my_script_w = w
</t>
<t tx="ekr.20120229094652.15148">.. _`this posting about BibTeX citations`: https://groups.google.com/group/leo-editor/browse_thread/thread/d36d76174dcd6786/9c2a298049f4f01c

.. _`raw-data`: https://docutils.sourceforge.net/docs/ref/rst/directives.html#raw-data-pass-through

When using LaTeX and BibTeX, I would like to use inside of Leo a kind of LaTeX-inline-markup, that after generation of the RsT file through Sphinx as well as after running of "make latex", generate a LaTeX file containing the citation call of the form \cite{CITBook001} as described in a file \*.bib. Is there a way to have Leo/Sphinx/RsT generate the inline raw latex syntax?

Use the docutils `raw-data`_ syntax. Examples::

    .. role:: raw-role(raw)
      :format: html latex
    .. raw:: latex
      \bibliographystyle{acm}
      \bibliography{myBibliography}

For more details, see `this posting about BibTeX citations`_.
</t>
<t tx="ekr.20120229094652.15152">Some people seem to think that it is difficult to understand how Leo handles "clone wars": differing values for a cloned nodes that appear in several external files. That's not true. The rule is::

    **The last clone that Leo reads wins.**

That is, for any cloned node C, Leo takes the value of C.h and C.b to be the values specified by the last copy that Leo reads.

There is only one complication::

    **Leo reads the entire outline before reading any external files.**

Thus, if C appears in x.leo, y.py and z.py, Leo will choose the value for C in x.py or y.py, depending on which @&lt;file&gt; node appears later in the outline.

**Note**: Whenever Leo detects multiple values for C when opening an outline, Leo creates a "Recovered nodes" tree. This tree contains all the various values for C, nicely formatted so that it is easy to determine where the differences are.

</t>
<t tx="ekr.20120304065838.15588">def selectLeoWindow(self, c):
    trace = False and not g.unitTesting
    if trace: g.trace(c.frame.title)
    frame = c.frame
    frame.deiconify()
    frame.lift()
    c.setLog()
    master = hasattr(frame.top, 'leo_master') and frame.top.leo_master
    if master: # 2011/11/21: selecting the new tab ensures focus is set.
        # frame.top.leo_master is a TabbedTopLevel.
        master.select(c)
    if 1: # 2016/04/09
        c.initialFocusHelper()
    else:
        c.bodyWantsFocus()
    c.outerUpdate()
</t>
<t tx="ekr.20120311070142.9904">def checkForDuplicateShortcuts(self, c, d):
    '''Check for duplicates in an "inverted" dictionary d
    whose keys are strokes and whose values are lists of ShortcutInfo nodes.

    Duplicates happen only if panes conflict.
    '''
    # lm = self
    # Fix bug 951921: check for duplicate shortcuts only in the new file.
    for ks in sorted(list(d.keys())):
        conflict, panes = False, ['all']
        aList = d.get(ks)
        aList2 = [si for si in aList if not si.pane.startswith('mode')]
        if len(aList) &gt; 1:
            for si in aList2:
                if si.pane in panes:
                    conflict = True; break
                else:
                    panes.append(si.pane)
        if conflict:
            g.es_print('conflicting key bindings in %s' % (c.shortFileName()))
            for si in aList2:
                g.es_print('%6s %s %s' % (si.pane, si.stroke.s, si.commandName))
</t>
<t tx="ekr.20120317130339.8282">@pagewidth 75

The following script won't work as intended:

    from PyQt5 import QtGui
    w = QtGui.QWidget()
    w.resize(250, 150)
    w.move(300, 300)
    w.setWindowTitle('Simple test')
    w.show()

When the script exits the sole reference to the window, w, ceases to exist, so the window is destroyed (garbage collected). To keep the window open, add the following code as the last line to keep the reference alive:

.. code-block:: python

    g.app.scriptsDict['my-script_w'] = w

Note that this reference will persist until the next time you run the execute-script. If you want something even more permanent, you can do something like:

.. code-block:: python

    g.app.my_script_w = w
</t>
<t tx="ekr.20120319170934.6109">Leo checks that the URL is valid before attempting to open it. A valid URL is:

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

That is, a comma, hyphen and open curly brace may not be the last character.

URL's in Leo should contain no spaces: use %20 to indicate spaces.

You may use any type of URL that your browser supports: http, mailto, ftp, file, etc.
</t>
<t tx="ekr.20120320153011.6055">
</t>
<t tx="ekr.20120320153011.8400">::

    Tab completion now shows all @command &amp; @button nodes
    Leo can highlight the pane containing the focus
    The bigdash plugin searches across multiple files
    The new quick edit/save mode makes Leo work like SciTe
</t>
<t tx="ekr.20120427064024.10064">def checkForOpenFile(self, c, fn):
    '''Warn if fn is already open and add fn to already_open_files list.'''
    d, tag = g.app.db, 'open-leo-files'
    if g.app.reverting:
        # Fix #302: revert to saved doesn't reset external file change monitoring
        g.app.already_open_files = []
    if d is None or g.app.unitTesting or g.app.batchMode or g.app.reverting:
        return
    aList = g.app.db.get(tag) or []
    if fn in aList:
        # The file may be open in another copy of Leo, or not:
        # another Leo may have been killed prematurely.
        # Put the file on the global list.
        # A dialog will warn the user such files later.
        if fn not in g.app.already_open_files:
            g.es('may be open in another Leo:', color='red')
            g.es(fn)
            g.app.already_open_files.append(fn)
    else:
        g.app.rememberOpenFile(fn)
</t>
<t tx="ekr.20120427064024.10065">def rememberOpenFile(self, fn):
    trace = False and not g.unitTesting
    d, tag = g.app.db, 'open-leo-files'
    if d is None or g.app.unitTesting or g.app.batchMode or g.app.reverting:
        pass
    elif g.app.preReadFlag:
        pass
    else:
        aList = d.get(tag) or []
        # It's proper to add duplicates to this list.
        aList.append(fn)
        if trace:
            # Trace doesn't work well while initing.
            print('rememberOpenFile:added: %s' % (fn))
            for z in aList:
                print('  %s' % (z))
        d[tag] = aList
</t>
<t tx="ekr.20120427064024.10066">def forgetOpenFile(self, fn, force=False):
    '''Forget the open file, so that is no longer considered open.'''
    trace = self.trace_shutdown and not g.unitTesting
    d, tag = g.app.db, 'open-leo-files'
    if not d or not fn:
        # Fix https://github.com/leo-editor/leo-editor/issues/69
        return
    if not force and (d is None or g.app.unitTesting or g.app.batchMode or g.app.reverting):
        return
    aList = d.get(tag) or []
    if fn in aList:
        aList.remove(fn)
        if trace:
            print('forgetOpenFile: %s' % g.shortFileName(fn))
            # for z in aList:
            #    print('  %s' % (z))
        d[tag] = aList
    else:
        if trace: print('forgetOpenFile: did not remove: %s' % (fn))
</t>
<t tx="ekr.20120427064024.10068"></t>
<t tx="ekr.20120522160137.9909">@nobeautify

def define_language_delims_dict(self):

    self.language_delims_dict = {
        # Internally, lower case is used for all language names.
        # Keys are languages, values are 1,2 or 3-tuples of delims.
        "actionscript"       : "// /* */", # jason 2003-07-03
        "ada"                : "--",
        "ada95"              : "--",
        "ahk"                : ";",
        "antlr"              : "// /* */",
        "apacheconf"         : "#",
        "apdl"               : "!",
        "applescript"        : "-- (* *)",
        "asp"                : "&lt;!-- --&gt;",
        "aspect_j"           : "// /* */",
        "assembly_macro32"   : ";",
        "assembly_mcs51"     : ";",
        "assembly_parrot"    : "#",
        "assembly_r2000"     : "#",
        "assembly_x86"       : ";",
        "autohotkey"         : "; /* */", # TL - AutoHotkey language
        "awk"                : "#",
        "b"                  : "// /* */",
        "batch"              : "REM_", # Use the REM hack.
        "bbj"                : "/* */",
        "bcel"               : "// /* */",
        "bibtex"             : "%",
        "c"                  : "// /* */", # C, C++ or objective C.
        "chill"              : "/* */",
        "clojure"            : ";", # 2013/09/25: Fix bug 879338.
        "cobol"              : "*",
        "coldfusion"         : "&lt;!-- --&gt;",
        "coffeescript"       : "#", # 2016/02/26.
        "config"             : "#", # Leo 4.5.1
        "cplusplus"          : "// /* */",
        "cpp"                : "// /* */",# C++.
        "csharp"             : "// /* */", # C#
        "css"                : "/* */", # 4/1/04
        "cweb"               : "@q@ @&gt;", # Use the "cweb hack"
        "cython"             : "#",
        "d"                  : "// /* */",
        "dart"               : "// /* */", # Leo 5.0.
        "doxygen"            : "#",
        "eiffel"             : "--",
        "elisp"              : ";",
        "erlang"             : "%",
        "factor"             : "!_ ( )", # Use the rem hack.
        "forth"              : "\\_ _(_ _)", # Use the "REM hack"
        "fortran"            : "C",
        "fortran90"          : "!",
        "foxpro"             : "&amp;&amp;",
        "gettext"            : "# ",
        "groovy"             : "// /* */",
        "handlebars"         : "&lt;!-- --&gt;", # McNab: delegate to html.
        "haskell"            : "--_ {-_ _-}",
        "haxe"               : "// /* */",
        "hbs"                : "&lt;!-- --&gt;", # McNab: delegate to html.
        "html"               : "&lt;!-- --&gt;",
        "i4gl"               : "-- { }",
        "icon"               : "#",
        "idl"                : "// /* */",
        "inform"             : "!",
        "ini"                : ";",
        "inno_setup"         : ";",
        "interlis"           : "/* */",
        "io"                 : "// */",
        "java"               : "// /* */",
        "javascript"         : "// /* */", # EKR: 2011/11/12: For javascript import test.
        "javaserverpage"     : "&lt;%-- --%&gt;", # EKR: 2011/11/25 (See also, jsp)
        "jhtml"              : "&lt;!-- --&gt;",
        "jmk"                : "#",
        "jsp"                : "&lt;%-- --%&gt;",
        "kivy"               : "#", # PeckJ 2014/05/05
        "kshell"             : "#", # Leo 4.5.1.
        "latex"              : "%",
        "less"               : "/* */", # NcNab: delegate to css.
        "lilypond"           : "% %{ %}",
        "lisp"               : ";", # EKR: 2010/09/29
        "lotos"              : "(* *)",
        "lua"                : "--", # ddm 13/02/06
        "mail"               : "&gt;",
        "makefile"           : "#",
        "maple"              : "//",
        "markdown"           : "", # EKR, 2016/11/25
        "matlab"             : "%", # EKR: 2011/10/21
        "md"                 : "&lt;!-- --&gt;", # PeckJ: 2013/02/08
        "ml"                 : "(* *)",
        "modula3"            : "(* *)",
        "moin"               : "##",
        "mqsc"               : "*",
        "netrexx"            : "-- /* */",
        "noweb"              : "%", # EKR: 2009-01-30. Use Latex for doc chunks.
        "nqc"                : "// /* */",
        "nsi"                : ";", # EKR: 2010/10/27
        "nsis2"              : ";",
        "objective_c"        : "// /* */",
        "objectrexx"         : "-- /* */",
        "occam"              : "--",
        "omnimark"           : ";",
        "pascal"             : "// { }",
        "perl"               : "#",
        "perlpod"            : "# __=pod__ __=cut__", # 9/25/02: The perlpod hack.
        "php"                : "// /* */", # 6/23/07: was "//",
        "pike"               : "// /* */",
        "pl1"                : "/* */",
        "plain"              : "#", # We must pick something.
        "plsql"              : "-- /* */", # SQL scripts qt02537 2005-05-27
        "pop11"              : ";;; /* */",
        "postscript"         : "%",
        "povray"             : "// /* */",
        "powerdynamo"        : "// &lt;!-- --&gt;",
        "prolog"             : "% /* */",
        "psp"                : "&lt;!-- --&gt;",
        "ptl"                : "#",
        "pvwave"             : ";",
        "pyrex"              : "#",
        "python"             : "#",
        "r"                  : "#",
        "rapidq"             : "'",
        "rebol"              : ";",
        "redcode"            : ";",
        "rest"               : ".._",
        "rhtml"              : "&lt;%# %&gt;",
        "rib"                : "#",
        "rpmspec"            : "#",
        "rst"                : ".._",
        "ruby"               : "#", # thyrsus 2008-11-05
        "rview"              : "// /* */",
        "sas"                : "* /* */",
        "scala"              : "// /* */",
        "scheme"             : "; #| |#",
        "sdl_pr"             : "/* */",
        "sgml"               : "&lt;!-- --&gt;",
        "shell"              : "#",     # shell scripts
        "shellscript"        : "#",
        "shtml"              : "&lt;!-- --&gt;",
        "smalltalk"          : '" "', # Comments are enclosed in double quotes(!!)
        "smi_mib"            : "--",
        "splus"              : "#",
        "sqr"                : "!",
        "squidconf"          : "#",
        "ssharp"             : "#",
        "swig"               : "// /* */",
        "tcl"                : "#",
        "tcltk"              : "#",
        "tex"                : "%", # Bug fix: 2008-1-30: Fixed Mark Edginton's bug.
        "text"               : "#", # We must pick something.
        "texinfo"            : "@c",
        "tpl"                : "&lt;!-- --&gt;",
        "tsql"               : "-- /* */",
        "typescript"         : "// /* */", # For typescript import test.
        "unknown"            : "#", # Set when @comment is seen.
        "unknown_language"   : '#--unknown-language--', # For unknown extensions in @shadow files.
        "uscript"            : "// /* */",
        "vbscript"           : "'",
        "velocity"           : "## #* *#",
        "verilog"            : "// /* */",
        "vhdl"               : "--",
        "vim"                : "\"",
        "vimoutline"         : "#", # TL 8/25/08 Vim's outline plugin
        "xml"                : "&lt;!-- --&gt;",
        "xsl"                : "&lt;!-- --&gt;",
        "xslt"               : "&lt;!-- --&gt;",
        "yaml"               : "#",
        "zpt"                : "&lt;!-- --&gt;",

        # These aren't real languages, or have no delims...
        # "cvs_commit"         : "",
        # "dsssl"              : "; &lt;!-- --&gt;",
        # "embperl"            : "&lt;!-- --&gt;",  # Internal colorizing state.
        # "freemarker"         : "",
        # "hex"                : "",
        # "jcl"                : "",
        # "patch"              : "",
        # "phpsection"         : "&lt;!-- --&gt;",  # Internal colorizing state.
        # "props"              : "#",         # Unknown language.
        # "pseudoplain"        : "",
        # "relax_ng_compact"   : "#",         # An xml schema.
        # "rtf"                : "",
        # "svn_commit"         : "",
    }
</t>
<t tx="ekr.20120522160137.9910">@nobeautify

def define_language_extension_dict(self):

    # Used only by g.app.externalFilesController.get_ext.

    # Keys are languages, values are extensions.
    self.language_extension_dict = {
        "actionscript"  : "as", # jason 2003-07-03
        "ada"           : "ada",
        "ada95"         : "ada",
        "ahk"           : "ahk",
        "antlr"         : "g",
        "apacheconf"    : "conf",
        "apdl"          : "apdl",
        "applescript"   : "scpt",
        "asp"           : "asp",
        "aspect_j"      : "aj",
        "autohotkey"    : "ahk", # TL - AutoHotkey language
        "awk"           : "awk",
        "b"             : "b",
        "batch"         : "bat", # Leo 4.5.1.
        "bbj"           : "bbj",
        "bcel"          : "bcel",
        "bibtex"        : "bib",
        "c"             : "c",
        "chill"         : "ch",  # Only one extension is valid: .c186, .c286
        "clojure"       : "clj", # 2013/09/25: Fix bug 879338.
        "cobol"         : "cbl", # Only one extension is valid: .cob
        "coldfusion"    : "cfm",
        "coffeescript"  : "coffee",
        "config"        : "cfg",
        "cplusplus"     : "c++",
        "cpp"           : "cpp",
        "css"           : "css", # 4/1/04
        "cweb"          : "w",
        "cython"        : "pyx", # Only one extension is valid at present: .pyi, .pyd.
        "d"             : "d",
        "dart"          : "dart",
        "eiffel"        : "e",
        "elisp"         : "el",
        "erlang"        : "erl",
        "factor"        : "factor",
        "forth"         : "forth",
        "fortran"       : "f",
        "fortran90"     : "f90",
        "foxpro"        : "prg",
        "gettext"       : "po",
        "groovy"        : "groovy",
        "haskell"       : "hs",
        "haxe"          : "hx",
        "html"          : "html",
        "i4gl"          : "i4gl",
        "icon"          : "icn",
        "idl"           : "idl",
        "inform"        : "inf",
        "ini"           : "ini",
        "inno_setup"    : "iss",
        "io"            : "io",
        "java"          : "java",
        "javascript"    : "js", # EKR: 2011/11/12: For javascript import test.
        "javaserverpage": "jsp", # EKR: 2011/11/25
        "jhtml"         : "jhtml",
        "jmk"           : "jmk",
        "jsp"           : "jsp",
        "kivy"          : "kv", # PeckJ 2014/05/05
        "kshell"        : "ksh", # Leo 4.5.1.
        "latex"         : "tex", # 1/8/04
        "lilypond"      : "ly",
        "lua"           : "lua", # ddm 13/02/06
        "mail"          : "eml",
        "makefile"      : "mak",
        "maple"         : "mpl",
        "matlab"        : "m",
        "md"            : "md", # PeckJ: 2013/02/07
        "ml"            : "ml",
        "modula3"       : "mod",
        "moin"          : "wiki",
        "mqsc"          : "mqsc",
        "noweb"         : "nw",
        "nqc"           : "nqc",
        "nsi"           : "nsi", # EKR: 2010/10/27
        "nsis2"         : "nsi",
        "objective_c"   : "mm", # Only one extension is valid: .m
        "objectrexx"    : "rex",
        "occam"         : "occ",
        "omnimark"      : "xom",
        "pascal"        : "p",
        "perl"          : "pl",
        "perlpod"       : "pod",
        "php"           : "php",
        "pike"          : "pike",
        "pl1"           : "pl1",
        "plain"         : "txt",
        "plsql"         : "sql", # qt02537 2005-05-27
        # "pop11"       : "p", # Conflicts with pascal.
        "postscript"    : "ps",
        "povray"        : "pov",
        "prolog"        : "pro",
        "psp"           : "psp",
        "ptl"           : "ptl",
        "pyrex"         : "pyx",
        "python"        : "py",
        "r"             : "r",
        "rapidq"        : "bas", # fil 2004-march-11
        "rebol"         : "r", # jason 2003-07-03
        "rhtml"         : "rhtml",
        "rib"           : "rib",
        "rst"           : "rest",
        "ruby"          : "rb", # thyrsus 2008-11-05
        "sas"           : "sas",
        "scala"         : "scala",
        "scheme"        : "scm",
        "sgml"          : "sgml",
        "shell"         : "sh", # DS 4/1/04
        "shellscript"   : "bash",
        "shtml"         : "ssi", # Only one extension is valid: .shtml
        "smalltalk"     : "sm",
        "splus"         : "splus",
        "sqr"           : "sqr",
        "ssharp"        : "ss",
        "swig"          : "i",
        "tcl"           : "tcl",
        "tcltk"         : "tcl",
        "tex"           : "tex",
        "texinfo"       : "info",
        "text"          : "txt",
        "tpl"           : "tpl",
        "tsql"          : "sql", # A guess.
        "typescript"    : "ts",
        "unknown"       : "txt", # Set when @comment is seen.
        "uscript"       : "uc",
        "vbscript"      : "vbs",
        "velocity"      : "vtl",
        "verilog"       : "v",
        "vhdl"          : "vhd", # Only one extension is valid: .vhdl
        "vim"           : "vim",
        "vimoutline"    : "otl", # TL 8/25/08 Vim's outline plugin
        "xml"           : "xml",
        "xsl"           : "xsl",
        "xslt"          : "xsl",
        "yaml"          : "yaml",
        "zpt"           : "zpt",
    }

    # These aren't real languages, or have no delims...
        # cvs_commit, dsssl, embperl, freemarker, hex, jcl,
        # patch, phpsection, progress, props, pseudoplain,
        # relax_ng_compact, rtf, svn_commit.

    # These have extensions which conflict with other languages.
        # assembly_macro32: .asm or .a
        # assembly_mcs51:   .asm or .a
        # assembly_parrot:  .asm or .a
        # assembly_r2000:   .asm or .a
        # assembly_x86:     .asm or .a
        # squidconf:        .conf
        # rpmspec:          .rpm
</t>
<t tx="ekr.20120522160137.9911">@nobeautify

def define_extension_dict(self):

    # Keys are extensions, values are languages
    self.extension_dict = {
        # "ada":    "ada",
        "ada":      "ada95", # modes/ada95.py exists.
        "ahk":      "autohotkey",
        "aj":       "aspect_j",
        "apdl":     "apdl",
        "as":       "actionscript", # jason 2003-07-03
        "asp":      "asp",
        "awk":      "awk",
        "b":        "b",
        "bas":      "rapidq", # fil 2004-march-11
        "bash":     "shellscript",
        "bat":      "batch",
        "bbj":      "bbj",
        "bcel":     "bcel",
        "bib":      "bibtex",
        "c":        "c",
        "c++":      "cplusplus",
        "cbl":      "cobol", # Only one extension is valid: .cob
        "cfg":      "config",
        "cfm":      "coldfusion",
        "clj":      "clojure", # 2013/09/25: Fix bug 879338.
        "ch":       "chill", # Other extensions, .c186,.c286
        "coffee":   "coffeescript",
        "conf":     "apacheconf",
        "cpp":      "cpp",
        "css":      "css",
        "d":        "d",
        "dart":     "dart",
        "e":        "eiffel",
        "el":       "elisp",
        "eml":      "mail",
        "erl":      "erlang",
        "f":        "fortran",
        "f90":      "fortran90",
        "factor":   "factor",
        "forth":    "forth",
        "g":        "antlr",
        "groovy":   "groovy",
        "h":        "c", # 2012/05/23.
        "handlebars": "html", # McNab.
        "hbs":      "html", # McNab.
        "hs":       "haskell",
        "html":     "html",
        "hx":       "haxe",
        "i":        "swig",
        "i4gl":     "i4gl",
        "icn":      "icon",
        "idl":      "idl",
        "inf":      "inform",
        "info":     "texinfo",
        "ini":      "ini",
        "io":       "io",
        "iss":      "inno_setup",
        "java":     "java",
        "jhtml":    "jhtml",
        "jmk":      "jmk",
        "js":       "javascript", # For javascript import test.
        "jsp":      "javaserverpage",
        # "jsp":      "jsp",
        "ksh":      "kshell",
        "kv":       "kivy", # PeckJ 2014/05/05
        "less":     "css", # McNab
        "lua":      "lua", # ddm 13/02/06
        "ly":       "lilypond",
        "m":        "matlab",
        "mak":      "makefile",
        "md":       "md", # PeckJ 2013/02/07
        "ml":       "ml",
        "mm":       "objective_c", # Only one extension is valid: .m
        "mod":      "modula3",
        "mpl":      "maple",
        "mqsc":     "mqsc",
        "nqc":      "nqc",
        "nsi":      "nsi", # EKR: 2010/10/27
        # "nsi":      "nsis2",
        "nw":       "noweb",
        "occ":      "occam",
        "otl":      "vimoutline", # TL 8/25/08 Vim's outline plugin
        "p":        "pascal",
        # "p":      "pop11", # Conflicts with pascal.
        "php":      "php",
        "pike":     "pike",
        "pl":       "perl",
        "pl1":      "pl1",
        "po":       "gettext",
        "pod":      "perlpod",
        "pov":      "povray",
        "prg":      "foxpro",
        "pro":      "prolog",
        "ps":       "postscript",
        "psp":      "psp",
        "ptl":      "ptl",
        "py":       "python",
        "pyx":      "cython", # Other extensions, .pyd,.pyi
        # "pyx":    "pyrex",
        # "r":      "r", # modes/r.py does not exist.
        "r":        "rebol", # jason 2003-07-03
        "rb":       "ruby", # thyrsus 2008-11-05
        "rest":     "rst",
        "rex":      "objectrexx",
        "rhtml":    "rhtml",
        "rib":      "rib",
        "sas":      "sas",
        "scala":    "scala",
        "scm":      "scheme",
        "scpt":     "applescript",
        "sgml":     "sgml",
        "sh":       "shell", # DS 4/1/04. modes/shell.py exists.
        "shtml":    "shtml",
        "sm":       "smalltalk",
        "splus":    "splus",
        "sql":      "plsql", # qt02537 2005-05-27
        "sqr":      "sqr",
        "ss":       "ssharp",
        "ssi":      "shtml",
        "tcl":      "tcl", # modes/tcl.py exists.
        # "tcl":    "tcltk",
        "tex":      "latex",
        # "tex":      "tex",
        "tpl":      "tpl",
        "ts":       "typescript",
        "txt":      "plain",
        # "txt":      "text",
        # "txt":      "unknown", # Set when @comment is seen.
        "uc":       "uscript",
        "v":        "verilog",
        "vbs":      "vbscript",
        "vhd":      "vhdl",
        "vhdl":     "vhdl",
        "vim":      "vim",
        "vtl":      "velocity",
        "w":        "cweb",
        "wiki":     "moin",
        "xml":      "xml",
        "xom":      "omnimark",
        "xsl":      "xsl",
        "yaml":     "yaml",
        "zpt":      "zpt",
    }

    # These aren't real languages, or have no delims...
        # cvs_commit, dsssl, embperl, freemarker, hex, jcl,
        # patch, phpsection, progress, props, pseudoplain,
        # relax_ng_compact, rtf, svn_commit.

    # These have extensions which conflict with other languages.
        # assembly_macro32: .asm or .a
        # assembly_mcs51:   .asm or .a
        # assembly_parrot:  .asm or .a
        # assembly_r2000:   .asm or .a
        # assembly_x86:     .asm or .a
        # squidconf:        .conf
        # rpmspec:          .rpm

    # Extra language extensions, used to associate extensions with mode files.
    # Used by importCommands.languageForExtension.
    # Keys are extensions, values are corresponding mode file (without .py)
    # A value of 'none' is a signal to unit tests that no extension file exists.
    self.extra_extension_dict = {
        'pod'   : 'perl',
        'unknown_language': 'none',
        'w'     : 'none', # cweb
    }
</t>
<t tx="ekr.20121126202114.3">def createDefaultSettingsDicts(self):
    '''Create lm.globalSettingsDict &amp; lm.globalShortcutsDict.'''
    settings_d = g.app.config.defaultsDict
    assert isinstance(settings_d, g.TypedDict), settings_d
    settings_d.setName('lm.globalSettingsDict')
    shortcuts_d = g.TypedDictOfLists(
        name='lm.globalShortcutsDict',
        keyType=type('s'), valType=g.ShortcutInfo)
    return settings_d, shortcuts_d
</t>
<t tx="ekr.20130803073926.17120">target = '-- \nYou received this message because'
target = '--=20\nYou received this message because'
while p:
    s = p.b
    i = s.find(target)
    if i &gt; -1:
        p.b = s[:i]
        g.es(p.h)
    p.moveToThreadNext()
</t>
<t tx="ekr.20130807203905.16526">When I study a program, I like to import it into Leo. I have several scripts that do this: some create @auto nodes; others create @file nodes. Whatever the method used, the import process has the potential to change many files. Usually, I just change @auto and @file to @@auto or @@file, so that any changes I make while studying the code won't affect the originals.

But this "safety first" approach means that I can't actually use Leo to insert tracing statements (or for any other changes.) Happily, there is a way to import "live" code into Leo safely::

   Create a git repository for the code before importing it

The Aha is to create the repository *wherever the code is*, including,
say, python/Lib/site-packages.

- git diff ensures that import hasn't significantly altered the code,

This is exactly what I need:  I can make changes to important tools *safely* within Leo.
</t>
<t tx="ekr.20130815102041.15618">This plugin supports printing using the Qt GUI.
Written by Jacob M. Peck.
</t>
<t tx="ekr.20130815102041.15628">By Ville M. Vainio
See: https://en.wikipedia.org/wiki/Mylyn

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

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

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

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

Mylyn was a nice boost back in the eclipse days, it could work for Leo too. My main motivation right now was to demonstrate the signals with something that is much simpler than using them in qmlnotebook.
</t>
<t tx="ekr.20130815102041.15630">By Terry Brown.

screen_capture now captures an image immediately, screen_capture_5sec waits
five seconds, so you can position the pointer, open menus etc. The only
feedback is in the console, as messages in the log would be distracting in
the captured image.</t>
<t tx="ekr.20130815102041.15631">Screencasts promise to be easy to be *much* easier to create than slideshows, while also being more interesting, informative and flashy.  It is *so* much easier to write a screencast script than it is to lay out a slide, take a screenshot, and then manage resulting slide.

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

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

Screencasts may be the long-awaited tools that will allow me to show Leo in action so that other will finally be able to understand it easily.
</t>
<t tx="ekr.20130815102041.15632">By Kent Tenney

The timestamp plugin manages the following node attributes:

- str_ctime: creation time
- str_mtime: time node was last modified
- str_atime: time node contents were last viewed
</t>
<t tx="ekr.20130816100419.17299">The default language if no @language or @comment is in effect.

Valid values are (case is ignored):

actionscript,c,csharp,css,cweb,elisp,html,java,latex,
pascal,perl,perlpod,php,plain,plsql,python,rapidq,rebol,shell,tcltk.</t>
<t tx="ekr.20131001100335.15938">This section explains how to use Leo's standard search/replace commands.
**Note**: you can also use the Nav Tab (in the Log pane) to search for text.

``Ctrl-F (start-search)`` shows the Find Tab and puts the focus in the text box labeled ``Find:``.

**Aside**: You can select radio buttons and toggle check boxes in the Find Tab with ``Ctrl-Alt keys``. The capitalized words of the radio buttons or check boxes indicate which key to use.  For example, ``Ctrl-Alt-X (toggle-find-regex-option)`` toggles the ``regeXp`` checkbox.

After typing ``Ctrl-F``, type the search string, say ``def``, in the text box.

Start the find command by typing ``&lt;Return&gt;``.

But suppose you want to replace ``def`` with ``foo``, instead of just finding ``def``.

Just type ``&lt;Tab&gt;`` before typing ``&lt;Return&gt;``. Focus shifts to the text box labeled ``Replace:``.

Finally, type ``&lt;Return&gt;`` to start the ``find-next`` command. When Leo finds the next instance of ``def``, it will select it.

You may now type any command.  The following are most useful:

- ``Ctrl-minus (replace-then-find)`` replaces the selected text.
- ``F3 (find-next)`` continues searching without making a replacement.
- ``F2 (find-previous)`` continues the search in reverse.
- ``Ctrl-G (keyboard-quit)`` ends the search.
</t>
<t tx="ekr.20131001100335.15940">.. index::
    pair: leoSettings.leo; Tutorial
    pair: Global Settings; Tutorial
    pair: myLeoSettings.leo; Tutorial
    pair: Personal Settings; Tutorial
    pair: Local Settings; Tutorial
    pair: Configuration file; Tutorial

Leo uses outlines for just about *everything*, including configuring Leo:

- **leo/config/leoSettings.leo** contains Leo's default **global settings**. Don't change this file unless you are one of Leo's developers.

- **~/myLeoSettings.leo** contains your **personal settings**. Leo will create this file automatically if it doesn't exist when using the *Settings &gt;&gt; Open myLeoSettings* menu item. Settings in myLeoSettings.leo override (or add to) the default settings in leoSettings.leo.

- Any other .leo file may also contain **local settings**. Local settings apply only to that file and override all other settings.

**Settings nodes** specify settings.  These nodes *must* be descendants of an **@settings** node. Moving a settings node out from the @settings tree disables the setting. Headlines start with @ followed by a type, and possibly a value.  Here are some examples, with body text shown indented from headlines::

    @bool vim_mode = False

    @color flash_brackets_background_color = red

    @data global-abbreviations
        # Body text contains abbreviations.
        date;;={|{x=time.strftime("%Y/%m/%d")}|}
        trace;;=trace = &lt;|bool|&gt; and not g.unitTesting
        al;;=@language
        alh;;=@language html\n
        alj;;=@language javascript\n
        alm;;=@language md\n
        alp;;=@language python\n
        alr;;=@language rest\n@wrap\n
        nc;;=@nocolor\n
        ncn;;=@nocolor-node\n

    @string script_file_path = ../test/scriptFile.py

    @enabled-plugins
        # a list of enabled plugins
        plugins_menu.py
        free_layout.py
        mod_scripting.py
        backlink.py
        bigdash.py
        bookmarks.py
        contextmenu.py

    @shortcuts
        # body text contains personal key bindings
        file-open-by-name   = Ctrl-O
        save-all            = Ctrl-S

.. _`configuration guide`: customizing.html

For more information, see Leo's `configuration guide`_.
</t>
<t tx="ekr.20131001100335.15946">Leo’s minibuffer appears at the bottom of Leo’s main window. You use the minibuffer to execute commands by name, and also to accumulate arguments to commands.

Every Leo command has a **command name**. In this document, keystrokes that invoke a command will be followed by the command name in parentheses. For example, ``Ctrl-S (save-file)`` saves a Leo file.

**Very Important**: Leo has hundreds of commands, but because of tab completion you do not have to remember, or even *know about* any of them.  Feel free to ignore commands that you don't use. The following prefixes help find commands by name:: 

    clone-find  clone-find commands
    file-       file commands
    find-       find commands
    isearch-    incremental search commands
    leo-        open .leo files
    open-       open files or url's
    print-      print commands
    rectangle-  rectangle commands
    sort-       sort commands
    toggle-     toggle settings commands

Here are the commands that pertain to executing commands:

``Alt-X (full-command)``
    Executes any other command by typing its full name.

``Ctrl-P (repeat-complex-command``
    Repeats the last command entered by name in the minibuffer.

When in the minibuffer, the following keys are treated in special ways:

``&lt;Return&gt;``
    Executes the command.

``&lt;Tab&gt;``
    Shows all valid completions.

``&lt;BackSpace&gt;``
    Shows more completions.

``Ctrl-G``
    Exits the minibuffer and puts focus in the body pane.

``UpArrow``
    Moves backward through command history. The first ``UpArrow`` is the same as ``Ctrl-P``.

``DownArrow``
    Moves forward through command history.
</t>
<t tx="ekr.20131001100335.15947">``F1 (help)``
    Shows a help message appears in the viewrendered pane. ``Alt-0`` (``vr-toggle``) hides or shows this pane.
``F11 (help-for-command)``
    Shows the documentation for any Leo command. ``F11`` prompts for the name of a Leo command in the minibuffer. Use tab completion to see the list of all commands that start with a given prefix.
``F12 (help-for-python)``
    Shows the documentation from Python's help system. Typing completion is not available: type the full name of any Python module, class, function or statement.

These commands clarify which settings are in effect, and where they came from::

    show-bindings
    show-settings

These commands discuss special topics::

    help-for-abbreviations
    help-for-autocompletion
    help-for-bindings
    help-for-creating-external-files
    help-for-debugging-commands
    help-for-drag-and-drop
    help-for-dynamic-abbreviations
    help-for-find-commands
    help-for-minibuffer
    help-for-regular-expressions
    help-for-scripting


</t>
<t tx="ekr.20131002055813.15973">Here is a screenshot of Leo's main window:

.. image:: screen-shots/leo-workbook.png
   :alt: Screenshot

.. index::
    pair: Body pane; Tutorial
    pair: Expansion box; Tutorial
    pair: Icon area; Tutorial
    pair: Log pane; Tutorial
    pair: Main Window; Tutorial
    pair: Outline pane; Tutorial
    pair: Status line; Tutorial

Leo's main window consists of an **icon area** just below the menus, an **outline pane** at the top left, a **log pane** at the top right, a **body pane** at the bottom left, and an optional **viewrendered pane** at the bottom right. The **minibuffer** and **status line** lie at the bottom of the main window.

The log pane contains several tabs:

- The **Log tab** shows messages from Leo.
- The **Find tab** shows the status of Leo's Find/Replace commands.

Other tabs may also appear in the log pane:

- The **Spell tab** controls Leo's spell-checking.
- The **Completion tab** shows available typing completions.

.. index::
    pair: Icon box; Tutorial
    pair: Node; Tutorial
    pair: Headline; Tutorial
    pair: Body text; Tutorial

Leo stores all data in **nodes**. Nodes have **headlines** (shown in the outline pane) and **body text**. The body pane shows the body text of the **presently selected node**, the node whose headline is selected in the outline pane.  Headlines have an **icon box** indicating a node's status. For example, the icon box has a red border when the node has been changed.

</t>
<t tx="ekr.20131002055813.19036">You may select, expand and contract outline nodes with the mouse as usual, but using arrow keys is *highly recommended*. When focus is in the outline pane, *plain* arrows keys change the selected node:

``Right-arrow (expand-and-go-right)``
    Expands a node or selects its first child.
``Left-arrow (contract-or-go-left)``
    Contracts a node if its children are visible, and selects the node's parent otherwise.
``Up-arrow (goto-prev-visible)``
    Selects the previous *visible* outline node.
``Down-arrow (goto-next-visible)``
    Selects the next *visible* outline node.

Regardless of focus, ``Alt-arrow`` select outline nodes:

``Alt-Home (goto-first-visible-node)``
    Selects the first outline node and collapses all nodes.
``Alt-End (goto-last-visible-node)``
    Selects the last *visible* outline node and collapses all nodes except the node and its ancestors.
``Alt-arrow keys``
    Select the outline pane, and then act just like the plain arrow keys when the outline pane has focus.
</t>
<t tx="ekr.20131002055813.19037">When focus is in any of Leo's text panes (body pane, log pane, headlines), Leo works like most text editors:

- ``Plain arrow`` keys move the cursor up, down, left or right.
- ``Ctrl-LeftArrow`` and ``Ctrl-RightArrow`` move the cursor by words.
- ``Home`` and ``End`` move the cursor to the beginning or end of a line.
- ``Ctrl-Home`` moves the cursor to the beginning of the body text.
- ``Ctrl-End`` moves the cursor to the end of the body text.
- ``PageDown`` and ``PageUp`` move the cursor up or down one page.

**Note**: As usual, adding the ``Shift`` key modifier to any of the keys above moves the cursor and extends the selected text.
</t>
<t tx="ekr.20131002055813.19835">``Ctrl-I or Insert (insert-node)``
    Inserts a new node into the outline.
``Ctrl-H (edit-headline)``
    Begins editing the headline of the selected node.
``Return``
    When focus is in the outline pane, ``&lt;Return&gt;`` ends editing ``(end-edit-headline)`` or switches focus to the body pane.
``Ctrl-Shift-C (copy-node)``
    Copies the outline and all it's descendants, placing the node on the clipboard.
``Ctrl-Shift-X (cut-node)``
    Cuts the outline and all its descendants, placing the node on the clipboard.
``Ctrl-Shift-V (paste-node)``
    Pastes a node (and its descendants) from the clipboard after the presently selected node.
``Ctrl-M (mark)``
    Toggles the mark on a node. Marked nodes have a vertical red bar in their icon area.
``Ctrl-} (demote)``
    Makes all following siblings of a node children of the node.
``Ctrl-{ (promote)``
    Makes all the children of a node siblings of the node.
</t>
<t tx="ekr.20131002055813.19837">Leo has unlimited undo--Leo remembers *all* changes you make to outline structure or the contents of any node since you restarted Leo.

``Ctrl-Z (undo)``
    Undoes the last change. Another ``Ctrl-Z`` undoes the previous change, etc.
``Ctrl-Shift-Z (redo)``
    Undoes the effect of the last undo, etc.

The first two entries of the ``Edit`` menu show what the next undo or redo operation will be.
</t>
<t tx="ekr.20131003040744.18221">Leo outlines can refer to **external files**, files on your file system. Leo quickly loads the files when opening Leo outlines. The following sections discuss only the basics.  See `Leo's Reference Guide &lt;directives.html&gt;`_ for full details.
</t>
<t tx="ekr.20131004064408.16020">.. index::
   pair: Directive; Tutorial

Leo **directives** control Leo's operations. Directives start with ``@`` in the leftmost column of body text. Directives **apply to descendants** unless overridden in descendant nodes.

.. index::
    pair: @color; Tutorial
    pair: @nocolor; Tutorial
    pair: @nocolor-node; Tutorial

The **@color**, **@nocolor**, and **@nocolor-node** directives control syntax coloring. **Note**: Nodes containing multiple color directives do *not* affect the coloring of descendant nodes::

    @color
    @nocolor
    @nocolor-node

.. index::
    pair: @language; Tutorial

The **@language** directive tells which language is in effect::

    @language python
    @language c
    @language rest # restructured text
    @language plain # plain text: no syntax coloring.

.. index::
    pair: @pagewidth; Tutorial
    pair: @tabwidth; Tutorial
    pair: Negative tab width; Tutorial

The **@pagewidth** directive sets the page width used by the reformat-paragraph command. The **@tabwidth** directive controls tabbing. Negative tab widths (recommended for Python) convert tabs to spaces::

    @pagewidth 100
    @tabwidth -4
    @tabwidth 8

.. index::
    pair: @wrap; Tutorial
    pair: @nowrap; Tutorial

The **@wrap** and **@nowrap** enable or disable line wrapping in the body pane::

    @nowrap
    @wrap

The **@first** directive ensures that lines appear at the very start of an external file. See the next section. Multiple @first directives are allowed. These directives must be the *very first* lines of body text::

    @first # -*- coding: utf-8 -*-
    @first #! /usr/bin/env python

.. _`directives reference page`: directives.html

Leo has many other directives, described in the `directives reference page`_.

</t>
<t tx="ekr.20131004073415.16044">.. index::
    pair: Clone; Tutorial

A **clone** is a node that appears in more than one place in a Leo outline. A small red arrow in the icon box marks each clone. All clones of a node are actually *the same node*:

- Any change to one clone affects all clones.
- Inserting, moving, or deleting any child of a clone will change all other clones on the screen.


``Ctrl-` (clone-node)``
    Clones node A. The shortcut is a grave accent, *not* a single quote.  This character is often on the same keyboard key as the tilde ``~`` character.

Please take a few moments to experiment with clones:

- Create a node whose headline is A.
- Clone node A with the ``clone-node`` command.
- Type some text into the body of A.
- All clones of A now have the same body.
- Insert a node, say B, as a child of any of the A nodes.
- Notice that *all* the A nodes now have a B child.
- See what happens if you clone B.
- See what happens if you insert, delete or move nodes that are children of A.
- When you delete a node's penultimate clone, the node is no longer a clone.
</t>
<t tx="ekr.20131004191204.16079">Here are Leo's basic file commands:

``Ctrl-N (new)``
    Creates a new outline in a new tab.
``Ctrl-O (open-outline)``
    Opens an existing .leo file.
``Ctrl-S (save-file)``
    Saves the outline.
``Ctrl-Q (exit-leo)``
    Exits Leo.  Leo will prompt you to save any unsaved outlines.

A **session** specifies a list of .leo files that Leo opens automatically when Leo first starts.  Leo will reload the last session provided that command-line arguments *don't* contain any file names.
</t>
<t tx="ekr.20131005214621.16088"></t>
<t tx="ekr.20131005214621.16090">Leo is a full-featured outliner with the following special features:

- Directives control how Leo works.
- ``@file`` and ``@clean`` nodes create external files.
- ``myLeoSettings.leo`` specifies your personal settings.
- Plugins extend Leo. ``@enabled-plugins`` settings nodes enable plugins.

For programmers:

- Leo has an easy-to-use scripting API, giving full access to all data in the outline.
- ``@button`` and ``@command`` nodes define scripts that can be applied to *other* nodes.
- Alt-1 enables autocompletion.

.. _`ask for help`: https://groups.google.com/forum/#!forum/leo-editor
.. _`Leo's Command Reference`: commands.html

Leo has hundreds of commands, described in `Leo's Command Reference`_. Please feel free to `ask for help`_ at any time.
</t>
<t tx="ekr.20131005214621.16128">- The rst3 command converts an @rst tree to an output file and an intermediate file.

- docutils uses the output file; sphinx uses the intermediate file.

- Settings starting with "rst3" control how the rst3 command works.

- Within @rst trees, headlines become rST sections.

- Sections levels in the generated rST correspond to outline levels in Leo.

- You reorganize your rST documents just by reorganizing the corresponding @rst tree.

- The rst3 command works acts on the nearest ancestor @rst node, if any, or on all descendant @rst nodes.

- ``@rst-no-head`` nodes insert text (or markup) without an rST headline.

- The rst3 command ignores @rst-ignore nodes and @rst-ignore-tree trees.

- The ``@button make-sphinx`` node in LeoDocs.leo calls sphinx automatically.

- CheatSheet.leo contains an expanded version of the example used in this tutorial. |br|
  You can open CheatSheet.leo from Leo's help menu.

  </t>
<t tx="ekr.20131007143750.16070">#################
Leo's Cheat Sheet
#################

This Cheat Sheet contains a summary of many of Leo's important features.
**Important**: The easiest way to find documentation is to search LeoDocs.leo.

.. contents:: Contents
    :depth: 4
    :local:
</t>
<t tx="ekr.20131007143750.16074">This section lists the ivars (instance variables), properties, functions and methods most commonly used in Leo scripts.

**Very important**: use Alt-1 (toggle-autocompleter) and Alt-2 (toggle-calltips) to recreate these lists as you type.
</t>
<t tx="ekr.20131008041326.16053">A plugin is a Python file in Leo's plugins folder.

Every plugin should have a top-level init function that returns True if the plugin has been initialized properly. The init function typically:

1. Registers an onCreate event handler, called when Leo creates a new window.
2. Calls g.plugin_signon(__name__)

For example:

.. code-block:: python

    def init():
        if &lt;&lt; all imports successful &gt;&gt;:
            g.registerHandler('after-create-leo-frame',onCreate)
            g.plugin_signon(__name__)
            return True
        else:
            return False

Plugins do *not* have automatic access to c, g and p.

Plugins define g by importing it:

.. code-block:: python

    import leo.core.leoGlobals as g

Plugins gain access to c using event handlers:

.. code-block:: python

    controllers = {}

    def init():
        g.registerHandler('after-create-leo-frame',onCreate)
        return True

    def onCreate (tag, keys):
        global controllers
        c = keys.get('c')
        if c:
            hash = c.hash()
            if hash not in controllers.keys():
                controllers(hash) = PluginController(c)

    def eventHander(tag,keys):
        global controllers
        c = keys.get('c')
        if c:
            controller = controllers.get(c.hash())
            controller.handleEvent()

Some plugins inject ivars into the Commands class rather than using a global controllers dict:

.. code-block:: python

    def onCreate (tag, keys):
        c = keys.get('c')
        if c:
            c.my_plugin_controller = ControllerClass(c)

    def eventHander(tag,keys):
        c = keys.get('c')
        if c:
            c.my_plugin_controller.handleEvent()

Once c is determined, the presently selected position is simply c.p.
</t>
<t tx="ekr.20131008041326.16066">Clones are nodes appearing in multiple places in the outline.

- Changes to one clone affect all other clones.
- All clones of a node are *exactly the same node*.

Views allow multiple views of data to exist in a single outline.

- A view is simply a collection of nodes.
- View focus attention on tasks and reduce searching for nodes.

Leo expands abbreviations as you type.

- Abbreviations range from simple shortcuts to multi-line templates containing fields.
- Type ``,,`` to move to the next field.
- Abbreviations can also insert the result of executing code.

Ctrl-left-clicking any URL opens the URL.

@chapter trees denote chapters. Activating a chapter shows only the nodes in that chapter.
</t>
<t tx="ekr.20131008041326.16079">#############
Preliminaries
#############

.. Use maxdepth 1 to emphasize top-level entries.

.. toctree::
   :maxdepth: 1

   preface
   testimonials
   acknowledgements
   license

</t>
<t tx="ekr.20131008041326.16080">.. Do *not* nest any @rst nodes.</t>
<t tx="ekr.20131008041326.16082">.. |---| unicode:: U+02015
   :trim:

#################
Leo's Users Guide
#################

.. _`Leo Tutorial`: tutorial.html

This is Leo's Users Guide. It covers additional material not covered in the
`Leo Tutorial`_.

.. toctree::
   :maxdepth: 2

   clickablelinks
   leomarkup
   customizing
   plugins
   commands
   directives

..  rstplugin3

</t>
<t tx="ekr.20131008041326.16091"></t>
<t tx="ekr.20131008041326.16092"></t>
<t tx="ekr.20131008041326.16094">##############
Installing Leo
##############

.. index:: Installing Leo

.. _`Leo's help forum`: https://groups.google.com/group/leo-editor


This chapter tells how to install and run Leo on Windows, Linux and MacOS.

The short summary:

1. Install Python 3.9 or later, including pip.

2. Install Leo (including all of Leo's dependencies) from either from PyPi or GitHub:

   - From PyPi::
   
        pip install leo

   - From GitHub::

        git clone https://github.com/leo-editor/leo-editor.git
        cd leo-editor
        pip install -r requirements.txt

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

.. contents:: Contents
    :depth: 4
    :local:
</t>
<t tx="ekr.20131008041326.16099">###################
Advanced Topics
###################

.. toctree::
   :maxdepth: 2

   writingPlugins
   debuggers

.. toctree::
   :maxdepth: 1

   scripting-miscellany
   theory
   vim-theory
   leonine-world
   leo-university

.. atShadow</t>
<t tx="ekr.20131008041326.16100">######################
Leo and Other Programs
######################

.. toctree::
   :maxdepth: 2

   jupyternotebooks
   leoandasciidoc
   emacs
   vimBindings
   leoBridge
   leoserver
</t>
<t tx="ekr.20131008041326.16140">###########
Running Leo
###########

.. index:: Running Leo

This chapter tells how to run Leo and discusses Leo's command-line options.

.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="ekr.20131008041326.16151">You can run Leo from a Python interpreter as follows::

    import leo
    leo.run() # runs Leo, opening a new outline or,
    leo.run(fileName=aFileName) # runs Leo, opening the given file name.

Another way to run Leo is as follows::

    cd &lt;path-to-launchLeo.py&gt;
    python launchLeo.py %*

Here are some tips that may make running Leo easier:

**Linux**

The following shell script will allow you to open foo.leo files by typing leo foo::

    #!/bin/sh 
    python &lt;leopath&gt;launchLeo.py $1

where &lt;leopath&gt; is the path to the directory containing the leo directory. 

**Windows**

You can associate Leo with .leo files using a batch file. Put the
following .bat file in c:\\Windows::

    &lt;path-to-python&gt;/python &lt;path-to-leo&gt;/launchLeo.py %*

Here &lt;path-to-leo&gt; is the path to the directory *containing* the leo directory,
that is, the directory containing launchLeo.py.
</t>
<t tx="ekr.20131008041326.16152">The first time you start Leo, a dialog will ask you for a unique identifier. If
you are using a source code control system such as git, use your git login name.
Otherwise your initials will do.

Leo stores this identifier in the file .leoID.txt. Leo attempts to create
leoID.txt in the .leo sub-directory of your home directory, then in Leo's config
directory, and finally in Leo's core directory. You can change this identifier
at any time by editing .leoID.txt.
</t>
<t tx="ekr.20131008041326.16153">On startup, Leo looks for two arguments of the form::

    --script scriptFile

If found, Leo enters batch mode. In batch mode Leo does not show any windows.
Leo assumes the scriptFile contains a Python script and executes the contents of
that file using Leo's Execute Script command. By default, Leo sends all
output to the console window. Scripts in the scriptFile may disable or enable
this output by calling app.log.disable or app.log.enable

Scripts in the scriptFile may execute any of Leo's commands except the Edit Body
and Edit Headline commands. Those commands require interaction with the user.
For example, the following batch script reads a Leo file and prints all the
headlines in that file::

    path = r"&lt;path-to-folder-containing-the-leo-folder&gt;\\leo\\test\\test.leo"

    g.app.log.disable() # disable reading messages while opening the file
    flag,newFrame = g.openWithFileName(path,None)
    g.app.log.enable() # re-enable the log.

    for p in newFrame.c.all_positions():
        g.es(g.toEncodedString(p.h,"utf-8"))
</t>
<t tx="ekr.20131008041326.16154">.. _`associating .leo files with python.exe`: installing.html#creating-windows-file-associations

Leo sends more detailed error messages to stderr,
the output stream that goes to the console window. In Linux and MacOS
environments, python programs normally execute with the console window visible.

On Windows, you can run Leo with the console window visible by `associating .leo files with python.exe`_ *not* pythonw.exe.
</t>
<t tx="ekr.20131008041326.16155">Leo uses os.expanduser('~') to determine the HOME directory if no HOME environment variable exists.

Leo puts several files in your HOME/.leo directory: .leoID.txt, .leoRecentFiles.txt, and myLeoSettings.leo.
</t>
<t tx="ekr.20131008041326.16156">@nowrap
Leo supports the following command-line options. As usual, you can see the list by typing the following in a console window::

    leo -h

or::

    leo --help

You will get the following::

    usage: launchLeo.py [options] file1, file2, ...

    options:
      -h, --help            show this help message and exit
      -b, --black-sentinels write black-compatible sentinel comments
      --diff                use Leo as an external git diff
      --fail-fast           stop unit tests after the first failure
      --fullscreen          start fullscreen
      --gui=GUI             specify gui: console,curses,qt,text,null
      --listen-to-log       start log_listener.py on startup
      --maximized           start maximized
      --minimized           start minimized
      --no-plugins          disable all plugins
      --no-splash           disable the splash screen
      --quit                quit immediately after loading
      --save-session        always save session data when Leo closes
      --script=PATH         execute a script and then exit
      --script-window       execute script using default gui
      --select=ID           headline or gnx of node to select
      --silent              disable all log messages
      --theme=NAME          use the named theme file
      --trace=LIST          add one or more strings to g.app.debug

            A comma-separated list. Valid values are:
            abbrev, beauty, cache, coloring, drawing, events, focus, git, gnx,
            importers, keys, layouts, plugins, save, select, sections,
            shutdown, size, speed, startup, themes, undo, verbose, zoom.

      --trace-binding=KEY   trace commands bound to a key
      --trace-setting=NAME  trace where named setting is set
      --window-size=SIZE    initial window size: (height x width)
      --window-spot=SPOT    initial window position: (top x left)
      -v, --version         print version number and exit
</t>
<t tx="ekr.20131008041326.16178"></t>
<t tx="ekr.20131008041326.16203">.. |---| unicode:: U+02015
   :trim:

.. |br| raw:: html

   &lt;br /&gt;

##################
Leo in 20 Minutes
##################

This chapter introduces Leo's most important features and terminology.

.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="ekr.20131008041326.16222">.. |---| unicode:: U+02015 .. for quotes
   :trim:

###########################################
Using Leo as a Personal Information Manager
###########################################

This chapter tells how you can use Leo as a Personal Information Manager. It introduces `clones`_: one of Leo's most unusual and powerful features for organizing data.

.. contents:: Contents
    :depth: 2
    :local:

</t>
<t tx="ekr.20131008041326.16241">.. |---| unicode:: U+02015 .. for quotes
   :trim:

.. |br| raw:: html

   &lt;br /&gt;

########################################
Creating Documents from Outlines
########################################

.. _`LaTeX`:    https://www.latex-project.org/
.. _`Python's`: https://www.python.org/
.. _`Sphinx`:   https://sphinx-doc.org/
.. _`Sphinx documentation`: https://sphinx-doc.org/contents.html
.. _`docutils`: https://docutils.sourceforge.net
.. _`reStructuredText`: https://docutils.sourceforge.net/rst.html
.. _`rST primer`: https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html
.. _`first tutorial`: tutorial-basics.html

Leo's rst3 command converts Leo trees containing `reStructuredText`_ (rST) or `Sphinx`_ markup to HTML, PDF, `LaTeX`_, and other kinds of output files. This tutorial gives step-by-step instructions for using the rst3 command.

**Prerequisites**: Please make sure you have read the `first tutorial`_ before reading this one. If you are new to rST, please read the `rST primer`_. For full information about Sphinx, please read the `Sphinx documentation`_.

The rst3 command makes using rST or Sphinx *much* easier by automatically creating underlining for rST sections. To reorganize a document, just reorganize the corresponding Leo outline: you don't have to change underlining characters by hand.

The tutorial covers only the basic features of the rst3 command. This is enough to generate all of Leo's documentation!

CheatSheet.leo contains an expanded version of the example used in this tutorial. You can open CheatSheet.leo from Leo's help menu.

.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="ekr.20131008041326.16253">Leo 4.9 (June 21, 2011): The rendering pane can now display movies, html, svg images, etc.
</t>
<t tx="ekr.20131008041326.16341">##########
Appendices
##########

.. |br| raw:: html

   &lt;br /&gt;

.. contents:: Contents
    :depth: 2
    :local:

</t>
<t tx="ekr.20131009050634.17610"></t>
<t tx="ekr.20131009050634.17616"></t>
<t tx="ekr.20131009050634.17622"># True: rst.report() sends output to log pane and the console pane.</t>
<t tx="ekr.20131009050634.17623"># Used only if generate_rst is True.</t>
<t tx="ekr.20131009050634.17658"></t>
<t tx="ekr.20131009065148.31758">####################
Directives Reference
####################

.. |br| raw:: html

   &lt;br /&gt;

.. contents:: Contents
    :depth: 4
    :local:

</t>
<t tx="ekr.20131009065148.31760">#########################
Exploring Leo's Code Base
#########################

.. |br| raw:: html

   &lt;br /&gt;

This chapter is for anyone who wants to understand Leo's code base,
including those who want to be one of Leo's implementors.

You already know that leoFind.py and leoUndo.py implement Leo's find and
undo command, and so on.

This chapter focuses on the *process* of finding your way around Leo's
code, not the myriad details you will find within Leo's code.

It's actually very easy! Try it. You'll see.

Reading this chapter should take about 20 minutes.

.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="ekr.20131009100732.16737">.. index::
    pair: URL; Tutorial
    pair: @url; Tutorial

Leo highlights URLs whenever syntax is coloring is enabled.

``Ctrl-Left-Click (open-url-under-cursor)``
    Opens the URL under the cursor.
``open-url``
    Opens a URL appearing either in the headline or the first line of body text. If a headline starts with ``@url``, the rest of the headline is taken to be a url.

**Note**:

- Leo opens URLs that look like file names using os.startfile.
- Leo opens all other URLs with your default web browser.
- Any scheme (http, mailto, ftp, file, etc.) supported by your browser is valid.
- URLs should contain no spaces: use ``%20`` instead.

`See the Appendix &lt;appendices.html#valid-url-s&gt;`_ for a complete description of valid URLs.
</t>
<t tx="ekr.20131009100732.16748">.. index::
    pair: @rst Node; Tutorial

1. Create a node someplace in your outline.

2. Type this in the headline::

        @rst myDocument.html

The @rst node, including its descendants, represents your document.</t>
<t tx="ekr.20131009100732.16750">Put something like this in the body of the @rst node::

    #############
    War and Peace
    #############

rST markup uses over/underlining to indicate chapter titles. Put an **overline** consisting of pounds signs above the title (War and Peace), and an identical **underline** of pound signs below as shown. rST markup for chapter titles is a bit picky:

- under/overlines must be at least 4 characters long
- under/overlines must be at least as long as the title.
- The overline and underline must be identical.

Note: the rst3 command requires that the "#" character be used in the over/underlines for chapter titles.
</t>
<t tx="ekr.20131009100732.16751">Now you write your novel, short story, documentation, or whatever. Organize your work as always:

| **nodes create sections, subsections, sub-sub-sections, etc.**
| **depending on their position in the outline**.
</t>
<t tx="ekr.20131009100732.16752">.. index::
    pair: rst3 Command; Tutorial

``&lt;Alt-X&gt;rst3&lt;Return&gt;`` runs the rst3 command.

- If the present node is an @rst node (or a descendant of an @rst node) the rst3 command applies to the nearest ancestor @rst node.

- Otherwise, the rst3 command applies to all descendant @rst trees.

If @bool rst3_call_docutils is True, the rst3 command will call docutils automatically to create the output files. For more information about Leo's settings, see `this section &lt;tutorial-basics.html#configuring-leo&gt;`_.

When using sphinx, run sphinx's "make" utility after running the rst3 command to create the final output files.

**Errors and warnings**:

1. Install docutils and then restart Leo if you see this error::

    writeToDocutils: docutils not present

2. ​Leo has a default stylesheet ​​that centers titles and makes them big and bold, so you can disregard messages such as::

    stylesheet not found &lt;path-to&gt;default.css
</t>
<t tx="ekr.20131009100732.16753">You now know enough to get started with the rst3 command. Some possible next steps are:

- Look at Leo's own documentation in LeoDocs.leo.
  Discover how the nodes in this tree correspond to the documentation you see before you.

- ``LeoDocs.leo`` has an @button make-sphinx script that calls sphinx automatically.

- Create your own ``@rst`` nodes. Run the rst3 command on them and see what happens.

- If you get stuck, please ask for help at https://groups.google.com/forum/#!forum/leo-editor.
</t>
<t tx="ekr.20131009100732.16754">Put the rst3_call_docutils setting in the @settings tree in the .leo file containing the @rst node. This setting determines whether to use plain rST markup or full sphinx markup. To use plain reStructuredText markup::

    @bool rst3_call_docutils = True

To use sphinx markup::

    @bool rst3_call_docutils = False
</t>
<t tx="ekr.20131009100732.16755">Sometimes you want to organize text without creating sections:

1. Create an outline node to organize your text.

2. Type the following in the headline::

    @rst-no-head &lt;any text: it is ignored&gt;

The rst3 command adds the body text of this node to the previous section:

- The headline is ignored.
- The @rst-no-head node does not change the rST section structure in any way.
</t>
<t tx="ekr.20131009100732.16760">.. index::
    pair: Abbreviation; Tutorial

Leo optionally expands abbreviations as you type. Abbreviations typically end with something like ``;;`` so they won't trigger by accident.

To use abbreviations, you must enable them in myLeoSettings.leo::

    @bool enable-abbreviations = True

You define abbreviations in ``@data abbreviations`` nodes or ``@data global-abbreviations`` nodes. None come predefined, but ``leo/config/exampleSettings.leo`` contains example abbreviations in the node ``@data abbreviations examples``

Abbreviations can be shortcuts::

    ncn;;=@nocolor

Abbreviations can span multiple lines. Continued lines start with ``\:``, like this::

    form;;=&lt;form action="main_submit" method="get" accept-charset="utf-8"&gt;
    \:&lt;p&gt;&lt;input type="submit" value="Continue &amp;rarr;"&gt;&lt;/p&gt;
    \:&lt;/form&gt;\n

Abbreviations can define templates in which ``&lt;|a-field-name|&gt;`` denotes a field to be filled in::

    input;;=&lt;input type="text/submit/hidden/button"
    \:name="&lt;|name|&gt;"
    \:value="" id="&lt;|id|&gt;"&gt;\n

Typing ``,,`` after inserting a template selects the next field.

Abbreviations can execute **abbreviation scripts**, delimited by ``{|{`` and ``}|}``::

    date;;={|{import time ; x=time.asctime()}|}
    ts;;={|{import time ; x=time.strftime("%Y%m%d%H%M%S")}|}

To use abbreviations scripts, enable them in myLeoSettings.leo as follows::

    @bool scripting-abbreviations = True

With abbreviation scripts enabled, typing ``ts;;`` gives::

    20131009171117

It's even possible to define a context in which abbreviation scripts execute. See leoSettings.leo for full details.
</t>
<t tx="ekr.20131009100732.19038">.. _`bookmarks.py`:     plugins.html#bookmarks-py
.. _`contextmenu.py`:   plugins.html#contextmenu-py
.. _`mod_scripting.py`: plugins.html#mod-scripting-py
.. _`quicksearch.py`:   plugins.html#quicksearch-py
.. _`todo.py`:          plugins.html#todo-py
.. _`viewrendered.py`:  plugins.html#viewrendered-py

.. index::
    pair: Plugins; Tutorial

`Leo plugins &lt;plugins.html&gt;`_ are Python programs that extend what Leo can do. Plugins usually reside in the leo/plugins folder. **@enabled-plugins** settings node enable plugins. Leo has dozens of plugins, including:

- `bookmarks.py`_ manages and shows bookmarks.
- `contextmenu.py`_ shows a context menu when you right-click a headline.
- `mod_scripting.py`_ supports @button and @command nodes.
- `quicksearch.py`_ Adds Nav tab for searching.
- `todo.py`_ provides to-do list and simple project-management capabilities.
- `viewrendered.py`_ creates the rendering pane and renders content in it.
</t>
<t tx="ekr.20131009100732.19039">Open bookmarks in a list, and show bookmarks in a pane.
</t>
<t tx="ekr.20131011050613.16815">The LoadManager (LM) class (in leoApp.py) is responsible for initing all objects and settings. This is a complex process. Here is the big picture:

- The LM reads each local (non-settings) file twice. The first load discovers the settings to be used in the second load. This ensures that proper settings are *available* during the second load.

- Ctors init settings "early", before calling the ctors for subsidiary objects. This ensures that proper settings are *in effect* for subsidiary ctors.
</t>
<t tx="ekr.20131011050613.16860">Leo uses a model/view/controller architecture.

- Controller: The Commands class and its helpers in leoCommands.py and leoEditCommands.py.

- Model (data): The VNode and Position classes in leoNodes.py.

- View: The gui-independent base classes are in the node "Gui Base Classes". The Qt-Specific subclasses are in the node "Qt gui".

.. _`David Parnas`:   https://en.wikipedia.org/wiki/David_Parnas
.. _`Glenford Myers`: https://en.wikipedia.org/wiki/Glenford_Myers

In Leo, each class hides (encapsulates) the details of its internal workings from user (client) classes. This design principle has been spectacularly successful. Leo's overall design has remained remarkably stable for 20 years, even as the internal details of many classes have radically changed. Two computer scientists influenced my thinking greatly: `David Parnas`_ and `Glenford Myers`_.

The distinction between gui-dependent and gui-independent is important. Almost all gui-dependent code resides in the plugins folder. Leo's core code is almost completely gui independent.

Leo's core typically assumes that w (an abstract widget) is a subclass of the baseTextWidget class. This class implements the DummyHighLevelInterface interface. Actually, w is usually a LeoQTextBrowser or leoQtBaseTextWidget object, defined in qtGui.py. These classes provide thin wrappers for corresponding Qt widgets.

Wrapper classes are useful, regardless of gui independence:

- Wrapper classes often simplify the corresponding code in Leo's code.
- Wrapper classes provide convenient methods for debugging and tracing.
</t>
<t tx="ekr.20131011050613.16862">Once you know approximately where to look, it is easy to use traces to
discover what is going on. To trace the last n (default 4) callers of any
function:

.. code-block:: python

    g.trace(g.callers(n))

Many complex methods define a trace variable:

.. code-block:: python

    trace = False and not g.unitTesting

A good rule of thumb: the more complex a method is, the more useful its
traces are likely to be.

You can also to use g.pdb() to single-step through the code.
I typically use g.pdb() only for deep mysteries!

**Note**: you must run Leo from a console window to use either g.trace or
g.pdb. I recommend always running Leo from a console.</t>
<t tx="ekr.20131011050613.16866">Several modules contain long comments:

.. code-block:: python

    &lt;&lt; about new sentinels &gt;&gt; (leoAtFile.py)
    &lt;&lt; about the leoBridge module &gt;&gt; (leoBridge.py)
    &lt;&lt; how to write a new importer &gt;&gt; (leoImport.py)
    &lt;&lt; How Leo implements unlimited undo &gt;&gt; (leoUndo.py)
    &lt;&lt; about gui classes and gui plugins &gt;&gt;
    &lt;&lt; About handling events &gt;&gt; (leoFrame.py)
    &lt;&lt; Theory of operation of find/change &gt;&gt; (leoFind.py)
    &lt;&lt; Key bindings, an overview &gt;&gt; (leoKeys.py)
    &lt;&lt; about 'internal' bindings &gt;&gt; (leoKeys.py)
    &lt;&lt; about key dicts &gt;&gt; (leoKeys.py)

These comments may be helpful, but do *not* assume that they are accurate. When in doubt, trust the code, not the comments.
</t>
<t tx="ekr.20131011050613.16868">You can learn *anything* about Leo, provided that you can cause Leo to execute the relevant code. That's usually very easy!

- It should be straightforward to isolate the module or modules involved.
- The next several sections give hints about finding interesting code.
- Once you find a bit of interesting code, use g.pdb or g.trace to study it.

The following sections provide more details...
</t>
<t tx="ekr.20131011050613.16870">The following methods and their helpers all have useful traces:

- leoQtEventFilter.eventFilter (qtGui.py) and helpers create keystrokes 
  (LeoKeyEvents) from QKeyEvent events.

- k.masterKeyHandler (leoKeys.py) receives LeoKeyEvents from eventFilter
  and invokes one of Leo's commands based on the users bindings.

- k.getArg handles commands like Ctrl-F (search-with-present-options)
  that prompt the user for input.
</t>
<t tx="ekr.20131011050613.16871">c.outerUpdate and helpers eliminate flicker by redrawing the screen only at
the end of each command.

c.outerUpdate contains several sophisticated and useful traces.

qtGui.set_focus (qtGui.py) is the only place that actually explicitly sets
focus in Leo. Enabling a trace there can be useful.
</t>
<t tx="ekr.20131011050613.16876">The following methods are surprisingly fragile. Change them only after careful thought. Make *sure* to run all unit tests after changing them in any way:

- leoTree.select and c.selectPosition switch nodes.

- c.endEditing ends editing in a headline and updates undo data.

- leoBody.onBodyChanged updates undo data when body text changes.

- baseNativeTree.onHeadChanged (baseNativeTree.py) updates undo data.

  **Note**: This method overrides leoTree.onHeadChanged (leoFrame.py),
  which is not used.

In addition, *all* event handling in baseNativeTree.py is extremely fragile. Don't even think about changing this code unless you know exactly what you are doing.
</t>
<t tx="ekr.20131012060912.16768">Leo creates commands in two ways:

1. Using the @g.command(command-name) decorator.

2. Using tables, usually getPublicCommands methods in various classes.

For example, to find the code for the sort-lines command, search for
sort-lines. You will find::

    'sort-lines':    self.sortLines,

Now search for "def sortLines" and you have arrived.</t>
<t tx="ekr.20131012060912.16770">Leo's key handling is complex because it does inherently complex things:

- Code in various places translate user key bindings to dictionaries.

- eventFilter and its helpers translates incoming QKeyEvents to LeoKeyEvents.

- k.masterKeyHandler associates incoming LeoKeyEvents with
  mode-and-pane-dependent bindings.

Much of this complexity is a direct result in the flexibility given to users in specifying key bindings.
</t>
<t tx="ekr.20131012060912.16775">.. index::
    pair: Generator; Tutorial

Commanders and positions define several `Python generators &lt;https://wiki.python.org/moin/Generators&gt;`_ to traverse (step through) an outline. The `scripting portion`_ of `Leo's cheat sheet`_ lists all of Leo's generators. For example, c.all_positions() traverses the outline in outline order.  The following prints a properly-indented list of all headlines:

.. code-block:: python

    for p in c.all_positions():
        print(' '*p.level()+p.h)

.. index::
    pair: Invalid positions; Tutorial

Scripts may capture positions like this:

.. code-block:: python

    aList = list(c.all_positions())

All of Leo's generators now yield *copies* of positions.

**Warning**: stored positions become invalid when outline changes. **c.positionExists(p)** is True if p is valid in c's outline.
</t>
<t tx="ekr.20131012060912.16788">g.es can send it's output to tabs other than the log tab:

.. code-block:: python

    c.frame.log.selectTab('Test')
        # Create Test or make it visible.

    g.es('Test',color='blue',tabName='Test')
        # Write to the test tab.

.. Fix Leo Issue #1101: https://github.com/leo-editor/leo-editor/issues/1101

Plugins and scripts may call c.frame.log.createTab to create non-text widgets in the log pane:

.. code-block:: python

    from leo.core.leoQt import QtWidgets
    log = c.frame.log
    w = log.createTab('My Tab', createText=False, widget=QtWidgets.QFrame())
    log.selectTab('My Tab')
</t>
<t tx="ekr.20131012191145.16789">.. in writingPlugins.html

For any commander c:

+------------------------------+--------------------------------------------+
| **Property**                 | **Value**                                  |
+------------------------------+--------------------------------------------+
| c.p                          | the presently selected position            |
+------------------------------+--------------------------------------------+
| **Ivar**                     | **Value**                                  |
+------------------------------+--------------------------------------------+
| c.frame                      | the leoFrame representing the main window. |
+------------------------------+--------------------------------------------+
| c.frame.body                 | the leoBody representing the body pane.    |
+------------------------------+--------------------------------------------+
| c.frame.body.wrapper         | a leoQTextEditWidget.                      |
+------------------------------+--------------------------------------------+
| c.frame.body.wrapper.widget  | a LeoQTextBrowser (a QTextBrowser)         |
+------------------------------+--------------------------------------------+
| c.frame.tree                 | a leoQtTree, representing the tree pane    |
+------------------------------+--------------------------------------------+
| c.frame.tree.treeWidget      | a LeoQTreeWidget (a QTreeWidget)           |
+------------------------------+--------------------------------------------+
| c.user_dict                  | a Python dictionary for use by scripts and |
|                              | plugins. Does not persist when Leo exists. |
+------------------------------+--------------------------------------------+</t>
<t tx="ekr.20131013060803.16851">@language python

# Should be run from an empty .leo file.
# Such traces might be part of the tutorial, but aren't at present.

g.cls()

def print_p(p):
    c,result = p.v.context,[]
    v,n = p.v,p.childIndex()
    for data in p.stack:
        v,n = data
        result.append('(%s %s)' % (n,v.h))
    return ','.join(result)

for p in c.all_positions():
    print('(%s %s) p.stack: %s' % (p.childIndex(),p.h,print_p(p)))
</t>
<t tx="ekr.20131013060803.16852">.. index::
    pair: Hello World Example; Tutorial

Here is the obligatory "Hello World!" script:

.. code-block:: python

    g.es('Hello World!')  # g.es prints all its arguments to the log pane.

In more detail:

1. Create a node anywhere in the outline.
2. Put ``g.es('hello, world!')`` in the node's body text.
3. Select the node and type Ctrl-B.

**Important** If text is selected, execute-script executes only the selected text. If you are in LeoDocs.leo, you can run the script from this node.
</t>
<t tx="ekr.20131014050027.16801">.. index::
    pair: Position; Tutorial
    pair: position class; Tutorial
    pair: Vnode; Tutorial
    pair: vnode class; Tutorial

.. _`Python properties`: https://stackabuse.com/python-properties/

A **position** represents an outline node at a *specific position* in the outline. Positions provide methods to insert, delete and move outline nodes. The `scripting portion`_ of `Leo's cheat sheet`_ lists the most important methods of the position class.

Because of clones, the *same* node may appear at *multiple positions* in the outline. A **vnode** represents the node's data, which is shared by all positions referring to that node.

.. _`user attributes`: customizing.html#adding-extensible-attributes-to-nodes-and-leo-files

For any position p, **p.b** is the node's body text, **p.h** is the node's headline and **p.u** is the node's `user attributes`_, and **p.v** is the position's vnode. Similarly, for any vnode v, **v.b** is the node's body text, **v.h** is the node's headline and **v.u** is the node's user attributes. 

</t>
<t tx="ekr.20131014053720.16816">The .leo files in Leo's distribution contain many @button nodes (many disabled), that do repetitive chores. Here is one, @button promote-child-bodies, from LeoDocs.leo:

.. code-block:: python

    """Copy the body text of all children to the parent's body text."""

    # Great for creating what's new nodes.
    result = [p.b]
    b = c.undoer.beforeChangeNodeContents(p)
    for child in p.children():
        if child.b:
            result.append('\n- %s\n\n%s\n' % (child.h,child.b))
        else:
            result.append('\n- %s\n\n' % (child.h))
    p.b = ''.join(result)
    c.undoer.afterChangeNodeContents(p,'promote-child-bodies',b)

This creates a fully undoable promote-child-bodies command.</t>
<t tx="ekr.20131015035606.16778">When focus is in the outline pane::

    Right-arrow (expand-and-go-right)
    Left-arrow (contract-or-go-left)
    Up-arrow (goto-prev-visible) 
    Down-arrow (goto-next-visible)

Regardless of focus::

    Alt-Home (goto-first-visible-node) 
    Alt-End (goto-last-visible-node)
    Alt-Right-arrow (expand-and-go-right)
    Alt-Left-arrow (contract-or-go-left)
    Alt-Up-arrow (goto-prev-visible) 
    Alt-Down-arrow (goto-next-visible)
</t>
<t tx="ekr.20131015035606.16780">When focus is in any of Leo's text panes (body pane, log pane, headlines):

    +-------------------+-----------------------+
    | **Key**           | **Move Cursor**       |
    +-------------------+-----------------------+
    | Arrow keys        | one character         |
    +-------------------+-----------------------+
    | Ctrl-LeftArrow    | back one word         |
    +-------------------+-----------------------+
    | Ctrl-RightArrow   | forward one word      |
    +-------------------+-----------------------+
    | Home              | beginning of line     |
    +-------------------+-----------------------+
    | End               | end of line           |
    +-------------------+-----------------------+
    | Ctrl-Home         | beginning of the body |
    +-------------------+-----------------------+
    | Ctrl-End          | end of body           |
    +-------------------+-----------------------+
    | PageDown          | down one page         |
    +-------------------+-----------------------+
    | PageUp            | up one page           |
    +-------------------+-----------------------+

Adding the Shift key modifier to any of the keys above moves the cursor and extends the selected text.
</t>
<t tx="ekr.20131015035606.16786">Directives starting with '@ in the leftmost column

See the `Directives reference &lt;directives.html&gt;`_ for full details::

    @                       # starts doc part
    @c                      # ends doc part
    @color
    @doc                    # starts doc part
    @killcolor
    @nocolor
    @language python
    @language c
    @language rest          # restructured text
    @language plain         # plain text: no syntax coloring.
    @lineending lineending
    @nosearch               # suppress searching for cff &amp; cfa commands.
    @pagewidth 100
    @tabwidth -4            # use spaces
    @tabwidth 8             # use tabs
    @nowrap
    @wrap

Leading whitespace is allowed (and significant) for::

    @all
    @others
    </t>
<t tx="ekr.20131015035606.16788">For documentation see node: "About this file" in leoSettings.leo::

    Command history:    @history-list
    Key bindings:       @shortcuts
    Visual settings:    @data qt-gui-plugin-style-sheet
    Enabling plugins:   @enabled-plugins

To disable a binding for a key, bind it to do-nothing::

    do-nothing = Insert

This overrides the following default binding in leoSettings.leo::

    insert-node = Insert
</t>
<t tx="ekr.20131015035606.16799">.. From cheat sheet

\@&lt;file&gt; nodes create external files::

    @asis &lt;filename&gt;        write only, no sentinels, exact line endings
    @auto &lt;filename&gt;        recommended
    @clean &lt;filename&gt;       recommended
    @edit &lt;filename&gt;        @edit node contains entire file
    @file &lt;filename&gt;        recommended
    @nosent &lt;filename&gt;      write only, no sentinels

This table summarizes the differences between @&lt;file&gt; nodes::

                             Sections &amp;   File data in
    @&lt;file&gt; kind  Sentinels?  @others?    .leo file?    Notes             
    ------------  ---------- -----------  ------------  -----
    @asis          no          no          yes
    @auto          no          yes         no           1, 2
    @auto-xx       no          yes         no           1, 2
    @clean         no          yes         yes     
    @edit          no          no          no    
    @file          yes         yes         no
    @nosent        no          yes         yes

\@auto nodes read files using language-specific importers.
By default, the file's extension determines the importer::

    Extensions                  Importer
    ----------                  --------
    .c, .cc, .c++, .cpp,.cxx    C
    .cs', .c#'                  C Sharp
    .el                         Elisp
    .h, .h++                    C
    .html, .htm                 HTML
    .ini                        Config file
    .ipynb                      Jupyter notebook
    .java                       Java
    .js                         JavaScript
    .md                         Markdown
    .org                        Org Mode
    .otl                        Vim outline
    .pas                        Pascal
    .php                        PHP
    .py, .pyi, .pyw             Python
    .rest, .rst                 reStructuredText
    .ts                         TypeScript
    .xml                        XML

You can also specify importers *explicitly* as follows::

    @auto-xxx           Importer
    ---------           --------
    @auto-ctext         ctext
    @auto-markdown      markdown
    @auto-md            markdown
    @auto-org           org-mode
    @auto-org-mode      org-mode
    @auto-otl           vimoutline
    @auto-vim-outline   vimoutline
    @auto-rst           reStructuredText

**Important**: The importers/exporters for markdown, org-mode, reStructuredText and vimoutline files automatically generate section headings corresponding to Leo's outline level. Body text of the top-level @auto node is ignored.

See the `Directives reference &lt;directives.html&gt;`_ for full details.

</t>
<t tx="ekr.20131015035606.16800">When focus is in the outline::

    Shift-Down-arrow (move-outline-down) 
    Shift-Left-arrow (move-outline-left) 
    Shift-Right-arrow (move-outline-right) 
    Shift-Up-arrow (move-outline-up)

Regardless of focus::

    Alt-Shift-Down-arrow (move-outline-down) 
    Alt-Shift-Left-arrow (move-outline-left) 
    Alt-Shift-Right-arrow (move-outline-right) 
    Alt-Shift-Up-arrow (move-outline-up)
    Ctrl-D (move-outline-down)
    Ctrl-L (move-outline-left) 
    Ctrl-R (move-outline-right)
    Ctrl-U (move-outline-up)
</t>
<t tx="ekr.20131015035606.16801">For much more information, see the `Commands Reference &lt;commands.html&gt;`_.

Copy/Paste (text)::

    Ctrl-C (copy-text)
    Ctrl-K (kill)
    Ctrl-V (paste-text)
    Ctrl-X (cut-text)
    Ctrl-Y (yank)
    Alt-Y  (yank-pop)
    kill-...

Files::

    Ctrl-N (new) 
    Ctrl-O (open-outline)
    Ctrl-S (save-file) 
    Ctrl-Q (exit-leo)

Focus::

    Alt-T (focus-to-tree) 
    Ctrl-T (toggle-active-pane)
    Ctrl-Tab (tab-cycle-next)

Help::

    Alt-0 (vr-toggle)
    F1 (help) 
    F11 (help-for-command) 
    F12 (help-for-python)
    show-bindings
    show-settings
    help-for-...

Find/Replace::

    Ctrl-F (search-with-present-options) 
    Shift-Ctrl-R (replace-string)
    Ctrl-minus (replace-then-find) 
    F3 (find-next) 
    F2 (find-previous)

Minibuffer::

    Alt-X (full-command)
    Ctrl-G (keyboard-quit)
    Tab (not a command, completes typing)

Nodes::

    Ctrl-I or Insert (insert-node)
    Ctrl-H (edit-headline)
    &lt;Return&gt; (when editing a headline) (end-edit-headline)
    Ctrl-Shift-C (copy-node)
    Ctrl-Shift-X (cut-node) 
    Ctrl-Shift-V (paste-node) 
    Ctrl-{ (promote)
    Ctrl-} (demote)
    Ctrl-M (mark) 

Undo::

    Ctrl-Z (undo)
    Ctrl-Shift-Z (redo)
</t>
<t tx="ekr.20131015091948.16784">#############################
A Miscellany of Leo Scripting
#############################

This chapter covers miscellaneous topics related to Leo scripts.

You might call this a FAQ for scripts...

.. contents:: Contents
    :depth: 3
    :local:
</t>
<t tx="ekr.20131015104133.16763"></t>
<t tx="ekr.20131015104133.16766">########################
Installing &amp; Running Leo
########################

This chapter tells how to install and run Leo.

.. toctree::
   :maxdepth: 4

   installing
   running
</t>
<t tx="ekr.20131016021541.16893">- execute-script predefines c, g, and p.
- c is a commander, g is the leoGlobals module, and p is the current position.
- Vnodes contain all outline data.
- Positions provide easy access to vnodes.
- Positions become invalid when outline nodes are inserted, deleted, or moved.
- Generators visit all or parts of the outline, in a specified order.

For more information, consult `Leo's cheat sheet &lt;cheatsheet.html&gt;`_ and `Leo's scripting miscellany &lt;scripting-miscellany.html&gt;`_</t>
<t tx="ekr.20131016103844.16730">See the docstring of these plugins for more details::

    bookmarks.py        Manages URL's used as bookmarks.
    contextmenu.py      Creates context menus for headlines.
    demo.py             Creates demos and slides.
    mod_scripting.py    Supports @button and @command nodes.
    quicksearch.py      Adds Nav tab for searching.
    todo.py             To-do lists and simple project management.
    viewrendered.py     Creates a rendering pane.
                        Automatically loaded by Leo's help commands.
                        Supports @graphics-script, @image, @html,
                        @movie and @svg nodes.
    viewrendered3.py    An enhanced version of viewrendered3.py.
    vim.py &amp; xemacs.py  Interface with vim and xemacs.
</t>
<t tx="ekr.20131017051340.16732">These are not included on the web, but may be of interest to those
reading LeoDocs.leo.</t>
<t tx="ekr.20131017051340.16733">This chapter uses the following outline (with all nodes expanded) as an ongoing example::

    + A (clone)
      + B
        - C
      - D
    - E
    + A (clone)
      + B
        - C
      - D
    - F

Only the A nodes are clones of each other.

c.all_positions, when applied to the example tree above, yields::

    A, B, C, D, E, A, B, C, D, F.
</t>
<t tx="ekr.20131017051340.16735">This script::

    def print_p_stack(p):
        c,result = p.v.context,[]
        v,n = p.v,p.childIndex()
        for data in p.stack:
            v,n = data
            result.append('(%s %s)' % (n,v.h))
        return ','.join(result)

    for p in c.all_positions():
        print('(%s %s) p.stack: %s' % (
            p.childIndex(),p.h,print_p_stack(p)))

yields the following when applied to the example outline::

    (0 A) p.stack:
    (0 B) p.stack: (0 A)
    (0 C) p.stack: (0 A),(0 B)
    (1 D) p.stack: (0 A)
    (1 E) p.stack:
    (2 A) p.stack:
    (0 B) p.stack: (2 A)
    (0 C) p.stack: (2 A),(0 B)
    (1 D) p.stack: (2 A)
    (3 F) p.stack:

Top-level nodes::

    (0 A) p.stack:
    (1 E) p.stack:
    (2 A) p.stack:
    (3 F) p.stack:

B::

    (0 B) p.stack: (0 A)
    (0 B) p.stack: (2 A)

C::

    (0 C) p.stack: (0 A),(0 B)
    (0 C) p.stack: (2 A),(0 B)

All Leo generators use a single, ever-changing, position object::

    for p in c.all_positions():
        print('id(p): %s id(p.v): %s (%s %s) p.stack: %s' % (
            id(p),id(p.v),p.childIndex(),p.h,print_p_stack(p)))

The output is something like::

    id(p): 214733232 id(p.v): 192725360 (0 A) p.stack:
    id(p): 214733232 id(p.v): 192725488 (0 B) p.stack: (0 A)
    id(p): 214733232 id(p.v): 192725552 (0 C) p.stack: (0 A),(0 B)
    id(p): 214733232 id(p.v): 192725520 (1 D) p.stack: (0 A)
    id(p): 214733232 id(p.v): 192725392 (1 E) p.stack:
    id(p): 214733232 id(p.v): 192725360 (2 A) p.stack:
    id(p): 214733232 id(p.v): 192725488 (0 B) p.stack: (2 A)
    id(p): 214733232 id(p.v): 192725552 (0 C) p.stack: (2 A),(0 B)
    id(p): 214733232 id(p.v): 192725520 (1 D) p.stack: (2 A)
    id(p): 214733232 id(p.v): 192725584 (3 F) p.stack:

A::

    id(p): 214733232 id(p.v): 192725360 (0 A) p.stack:
    id(p): 214733232 id(p.v): 192725360 (2 A) p.stack:

B::

    id(p): 214733232 id(p.v): 192725552 (0 C) p.stack: (0 A),(0 B)
    id(p): 214733232 id(p.v): 192725552 (0 C) p.stack: (2 A),(0 B)

C::

    id(p): 214733232 id(p.v): 192725552 (0 C) p.stack: (0 A),(0 B)
    id(p): 214733232 id(p.v): 192725552 (0 C) p.stack: (2 A),(0 B)

D::

    id(p): 214733232 id(p.v): 192725520 (1 D) p.stack: (0 A)
    id(p): 214733232 id(p.v): 192725520 (1 D) p.stack: (2 A)

Each Leo outline contains a hidden vnode, c.hiddenRootNode::

    c.hiddenRootNode.children: [A, E, A, F]
    A.children: [B]
    B.children: [C]
    C.children: []
    D.children: []
    E.children: []
    F.children: []

    c.hiddenRootNode.parents: []
    A.parents: [c.hiddenRootNode,c.hiddenRootNode]
    B.parents: [A]
    C.parents: [B]
    D.parents: [A]
    E.parents: [c.hiddenRootNode]
    F.parents: [c.hiddenRootNode]
</t>
<t tx="ekr.20131017051340.16847">@language python

</t>
<t tx="ekr.20131017051340.16850">@language python
</t>
<t tx="ekr.20131017174814.17479">.. |---| unicode:: U+02015 .. for quotes
   :trim:

.. |br| raw:: html

   &lt;br /&gt;

#############################
Technical introduction to Leo
#############################

.. Use full links here so links are active in LeoDocs.leo
.. _`clones`: tutorial-pim.html
.. _`leonine`: leonine-world.html
.. _`Python API`: tutorial-scripting.html
.. _`Scripting basics chapter`: tutorial-basics.html#scripting-basics

Leo puts hierarchy (outline structure) at the center of everything. This structure helps you create, manage, and revise any kind of document, including computer programs, documentation, to-do lists, and novels. Leo can write external files automatically from select parts of the outline.

Leo outlines may contain programs in any programming or markup language, including Python, C++, JavaScript, Rust, Markdown, and restructuredText.

**Multiple views of data**

Writers and programmers often want to view or manipulate the same text in different ways, depending on context. Leo's `clones`_ lets you create multiple different views of data within the *same* outline. You can organize code by functionality in one view and by file in another. You can see documentation from as many points of view as you like.

**Integrated Python Scripting**

Leo is fully scriptable in Python. Any outline node can contain a Python script that accesses the outline’s data directly. Such `leonine`_ scripts also have full access to all of Leo's source code via a straightforward `Python API`_. Leonine scripts and plugins can create new Leo commands. See Leo's `scripting basics chapter`_  for more details.

**Summary**

Traditional editors *simulate* hierarchy through comments, naming conventions, and the hierarchy of external files. In contrast, Leo puts hierarchy (outline structure) at the center of everything. As a result, Leo excels in managing complex text, including computer programs.
</t>
<t tx="ekr.20131018100353.16706">To start a project, clone nodes related to the project and drag them at or near the top level, where you can get at them easily. When the project is complete, just delete the clones. This workflow is surprisingly effective:

- The original nodes never move, but they change whenever their clones do.

- There is nothing to "put back in place" when you are done. Just delete the clones.

Used this way, **clones create views**: when you gather cloned nodes together for a project, you are, in effect, creating a project-oriented view of the outline. This view **focuses your attention** on only those nodes that are relevant to the task at hand.
</t>
<t tx="ekr.20131019035402.17557"></t>
<t tx="ekr.20131019035402.17573">#################
The Leonine World
#################

**Leonine** refers to Leo's unique way of organizing data and programs. This has many implications:

**Browsing**: Leo remembers your outline organization. Class browsers don't. Doh!

**The big picture**: Outline nodes hide messy details, revealing the big picture *at all times*.

**Programming**: Leo outlines naturally organize programs into modules, classes and functions. Leonine sources are their own design document. How you organize outlines is a choice in a new design space.

**User-defined types**: Headlines naturally describe a node's contents: **headlines naturally define types**. Leo's core supports types such as @button, @rst, @url, etc. Plugins define @bookmark, @graph, @html and @task types. Scripts can easily define other types.

.. _`clone-find`: https://leo-editor.github.io/leo-editor/commands.html#id1

**Work flow**: The `clone-find`_ commands gather all match a pattern under a single node. No need to keep searching for them. You can change the clones, and the original nodes change as well. This is a great way to fix bugs or to write books.

**Databases**: Leo's clones create new opportunities for scriptable databases. In my brother Speed's outlines, suboutlines *are* SQL queries!
</t>
<t tx="ekr.20131019061259.16686">execute-script predefines::

    c: The commander of the present outline.
    g: The leo.core.leoGlobals module.
    p: The presently selected position, c.p.
</t>
<t tx="ekr.20131019061259.16688">**Ivars**::

    c.config                c's configuration object
    c.frame                 c's outer frame, a leoFrame instance.
    c.undoer                c's undo handler.
    c.user_dict             A temporary dict for use of scripts and plugins.

**SubCommanders**::

    # In leo/core...
    c.atFileCommands
    c.chapterController
    c.fileCommands
    c.findCommands
    c.importCommands
    c.keyHandler = c.k
    c.persistenceController
    c.printingController
    c.rstCommands
    c.shadowController
    c.tangleCommands
    c.testManager
    c.vimCommands

    # In leo/commands...
    c.abbrevCommands
    c.controlCommands
    c.convertCommands
    c.debugCommands
    c.editCommands
    c.editFileCommands
    c.gotoCommands
    c.helpCommands
    c.keyHandlerCommands
    c.killBufferCommands
    c.rectangleCommands
    c.spellCommands

**Generators** (New in Leo 5.5: All generators yield distinct positions)::

    c.all_positions()
    c.all_unique_positions()

**Most useful methods**::

    c.isChanged()
    c.deletePositionsInList(aList, callback=None)
                            # safely deletes all the positions in aList.
    c.positionExists(p)
    c.redraw(p=None)        # Redraw the screen. Select p if given.
    c.save()                # Save the present outline.
    c.selectPosition()

**Using Command names**

When learning Leo's codebase, it may be easier to refer to a command by its 'command name'. You can therefore use  c.doCommandByName('command-name') instead of calling the proper method on the commander. This will return the same value as that method.

**Leo Script Return Values**

Commands created with @command and @button nodes can return values as well. Since top-level return statements aren't allowed in scripts executed with exec, you can define a global variable named **result**, and Leo will return its value::

    global result
    result = 42

**Official ivars** of any leoFrame f::

    f.c                     is the frame’s commander.
    f.body                  is a leoBody instance.
    f.body.bodyCtl          is a leoQTextEditWidget instance.
    f.body.bodyCtrl.widget  is a LeoQTextBrowser(QTextBrowser) instance.
    f.log                   is a leoLog instance.
    f.tree                  is a leoQtTree instance.
    f.tree.treeWidget       is a LeoQTreeWidget (a QTreeWidget) instance.

Use autocompletion to explore these objects!
</t>
<t tx="ekr.20131019061259.16690">**Ivars**::

    v.b:    v's body text.
    v.gnx   v's gnx.
    v.h:    v's headline text.
    v.u:    v.unknownAttributes, a persistent Python dictionary.

v.u (uA's or unknownAttributes or userAttributes) allow plugins or scripts
to associate persistent data with vnodes. For details see the section about
`userAttributes &lt;customizing.html#adding-extensible-attributes-to-nodes-and-leo-files&gt;`_ in the `Customizing Leo &lt;customizing.html&gt;`_ chapter.

*Important*: Generally speaking, vnode properties are fast, while the
corresponding position properties are much slower. Nevertheless, scripts
should usually use *position* properties rather than *vnode* properties
because the position properties handle recoloring and other details.
Scripts should use *vnode* properties only when making batch changes to
vnodes.
</t>
<t tx="ekr.20131019061259.16691">**Properties**

::

    p.b: same as p.v.b.  *Warning*: p.b = s is expensive.
    p.h: same as p.v.h.  *Warning*: p.h = s is expensive.
    p.u: same as p.v.u.

**Generators** (New in Leo 5.5: All generators yield distinct positions)

::

    p.children()
    p.parents()
    p.self_and_parents()
    p.self_and_siblings()
    p.following_siblings()
    p.subtree()
    p.self_and_subtree()

**Getters** These return *new positions*

::

    p.back()
    p.children()
    p.copy()
    p.firstChild()
    p.hasBack()
    p.hasChildren()
    p.hasNext()
    p.hasParent()
    p.hasThreadBack()
    p.hasThreadNext()
    p.isAncestorOf(p2)
    p.isAnyAtFileNode()
    p.isAt...Node()
    p.isCloned()
    p.isDirty()
    p.isExpanded()
    p.isMarked()
    p.isRoot()
    p.isVisible()
    p.lastChild()
    p.level()
    p.next()
    p.nodeAfterTree()
    p.nthChild()
    p.numberOfChildren()
    p.parent()
    p.parents()
    p.threadBack()
    p.threadNext()
    p.visBack()
    p.visNext()

**Setters**

::

    p.setDirty()  *Warning*: p.setDirty() is expensive.
    p.setMarked()

**Operations on nodes**

::

    p.clone()
    p.contract()
    p.doDelete(new_position)
    p.expand()
    p.insertAfter()
    p.insertAsNthChild(n)
    p.insertBefore()
    p.moveAfter(p2)
    p.moveToFirstChildOf(parent,n)
    p.moveToLastChildOf(parent,n)
    p.moveToNthChildOf(parent,n)
    p.moveToRoot(oldRoot=None)
        # oldRoot **must** be the old root position if it exists.

**Moving positions**

The following move positions *themselves*: they change the node to which a
position refers. They do *not* change outline structure in any way! Use
these when generators are not flexible enough::

    p.moveToBack()
    p.moveToFirstChild()
    p.moveToLastChild()
    p.moveToLastNode()
    p.moveToNext()
    p.moveToNodeAfterTree(p2)
    p.moveToNthChild(n)
    p.moveToParent()
    p.moveToThreadBack()
    p.moveToThreadNext()
    p.moveToVisBack(c)
    p.moveToVisNext(c)
</t>
<t tx="ekr.20131019061259.16692">For full details, see @file leoGlobals.py in LeoPyRef.leo.

**g vars**

::

    g.app
    g.app.gui
    g.app.windowlist
    g.unitTesting
    g.user_dict  # a temporary dict for use of scripts and plugins.

**g decorator**

::

    @g.command(command-name)

**g functions** (the most interesting: there are many more in leoGlobals.py)

::

    g.angleBrackets()
    g.app.commanders()
    g.app.gui.guiName()
    g.es(*args,**keys)
    g.es_print(*args,**keys)
    g.es_exception()
    g.getScript(c,p,
        useSelectedText=True,
        forcePythonSentinels=True,
        useSentinels=True)
    g.openWithFileName(fileName,old_c=None,gui=None)
    g.os_path_... # Wrappers for os.path methods.
    g.pdb(message='')
    g.toEncodedString(s,encoding='utf-8',reportErrors=False)
    g.toUnicode(s, encoding='utf-8',reportErrors=False)
    g.trace(*args,**keys)
    g.warning(*args,**keys)
</t>
<t tx="ekr.20131019061259.16693"></t>
<t tx="ekr.20131019190351.16664"></t>
<t tx="ekr.20131019190351.16947">::

    go-anywhere (quicksearch plugin)
    help-for-abbreviations
    help-for-dynamic-abbreviations
    help-for-find-commands
    help-for-regular-expressions
    insert-node-before
    leoscreen-jump-to-error
    normalize-whitespace
    parse-body
    show-buttons
    vr-expand &amp; vr-contract. All viewrendered commands now start with vr
    zoom-in/out commands
</t>
<t tx="ekr.20131019190351.16975">::

    --no-plugins command-line option
    @wrap now suppresses horizontal scrolling
    Added importers for .otl, .ipnyb, TypeScript and vimoutliner
    Added sublime Text 2, a dark colorizing theme
    Added support for @testsetup and @testclass
    Added syntax coloring for clojure language
    Added yes-to-all button when prompting for dangerous writes
    Allow periods before section names in headlines
    Border color changes depending on input state
    Clones are now valid anywhere in @file nodes
    Fully supported `:`: convention in @mode nodes
    Help commands now use &lt;pre&gt; formatting if docutils is not available
    Leo issues a warning if the same .leo file is open in another Leo instance
    Show all commands after &lt;alt-x&gt;&lt;tab&gt;
    Major additions to abbreviations, including templates
</t>
<t tx="ekr.20131019190351.16990">::

    leomylyn.py
    markup_inline.py
    printing.py
    richtext.py
    rss.py
    screen_capture.py
    screencast.py
    timestamp.py
</t>
<t tx="ekr.20131019190351.17002">::

    By Terry Brown:

        Add @script node
        Cross-outline node editing
        Export full contents
        Full tree view (See the discussion in the child)
        Indexing files for full text search
        Persistent state with json as a leo abbreviation
        Tool for diffing Leo files

    By Edward K. Ream:

        Cleanup imported nodes
        Create global data structures from in modes/*.py files
        Get all comments from modes (slow)
        Import org mode
        Recursive import script

    By Brian Theado:

        Display function call hierarchy in Leo
</t>
<t tx="ekr.20131019190351.17004">::

    Added @color minibuffer-foreground-color
    Added @color log_warning_color
    Added @bool enable-tree-dragging</t>
<t tx="ekr.20131023151757.17122"></t>
<t tx="ekr.20131023151757.17124">"I would never again willingly program without Leo"---Edward K. Ream

From Terry Brown:

    If you're looking for an *environment* which includes a good editor and outliner and is completely scriptable / interactive / "live-code" in Python, then Leo wins hands down. Of course, it's basically alone in this field, as far as I know, but I'm sure it would do well even if it wasn't :-). Take out the Python part, and maybe they're some others out there, but who'd want to take out the Python part :) I guess Emacs is sort of an environment like this, only in Lisp with a prehistoric GUI system.

    Sometimes I've wondered why Leo seems to appeal to people who aren't comfortable in Python, I think now it's because they still recognize the value of an *environment*, and there's just not much in this niche.

    My feeling, talking generally and not about Leo in particular, is that while not everyone needs to be a "programmer", everyone who uses computers would benefit from being able to interact with them with more of the flexibility and efficiency that comes with even relatively simple "scripting", and less of the limitations that come with the "buy our latest product and you'll be able to do anything you want with a click" view pushed by other suppliers of computing environments.

From Jacob Peck:

    Leo's impact on my life since I found it in January has been substantial.

    Leo allows me to automate my life to a great extent. It is my to-do list, my personal assistant, my address book, my password log, my recipe archive, my rss feed reader (due to rss.py), and my favored editor. It partially powers my blog (along with git, ruby, and heroku), allowing me to create a new blog entry with one click and a bit of editing. Viewrendered (with markdown support!) has changed the way I write READMEs and blog posts. On top of all of that, it has allowed to me to organize several disparate tabletop game design projects I have going, as well as my numerous writing projects. Not to mention the impact it has on my ability to understand and decode large python projects!

    But what really cinches all of this for me is how crazy extensible Leo is. Script buttons in particular are an integral part of my daily workflow, allowing me to transform my productivity over the last month...I'm now a thing-getter-doner, and I find much of it is due to the powerful core of Leo, plus scripting.py and todo.py.

From Ville M. Vainio:

    The outliner format helps me organize/reorganize my thoughts gradually, instead of putting everything in the right place from the beginning. I write a lot of body text with few headlines, and Leo's approach leaves lots of space for the body text and therefore suits my workflow. I find that I end up revisiting notes composed on Leo more often than notes slapped into tools like Evernote or random files in the file system.

    With Leo, I can interleave "notes" (most of the content), generated files and even random data and python scripts to manipulate that data. I process this data in various tools, but Leo helps me group it together in "project specific" Leo files.

    I know how to script the outline, so I can easily whip up different tools for my needs that deal with the headline structure directly.

From Terry Brown:

    Why Leo? Because I have two nodes which were originally identical but are now different and I want to see the differences.

    My outline loads a @file called ~/.leo/t/gen which contains a @button with several @rclick children for commonly used tasks. I add a new one, @rclick diff::

        selected = c.getSelectedPositions()
        open('/tmp/a_diff', 'w').write(selected[0].b)
        open('/tmp/b_diff', 'w').write(selected[1].b)
        import os
        os.system("xxdiff /tmp/a_diff /tmp/b_diff &amp;")

    which is horrible for a number of reasons but also took only moments to write. And now, not only does this Leo session have a visual node diff capability, but also every future session which loads ~/.leo/t/gen.

    When you can go from wanting to having a feature in less time than it takes to write an email about it - well, that's "why Leo".
</t>
<t tx="ekr.20131024051649.17136">Put introductory words in the body of the @rst node itself:

    "Well, Prince, so Genoa and Lucca are now just family estates of the
    Buonapartes. But I warn you, if you don't tell me that this means war,
    if you still try to defend the infamies and horrors perpetrated by that
    Antichrist--I really believe he is Antichrist--I will have nothing more
    to do with you and you are no longer my friend, no longer my 'faithful
    slave,' as you call yourself! But how do you do? I see I have
    frightened you--sit down and tell me all the news."

    It was in July, 1805, and the speaker was the well-known Anna Pavlovna
    Scherer, maid of honor and favorite of the Empress Marya Fedorovna.
    With these words she greeted Prince Vasili Kuragin, a man of high rank
    and importance, who was the first to arrive at her reception. Anna
    Pavlovna had had a cough for some days. She was, as she said, suffering
    from la grippe; grippe being then a new word in St. Petersburg, used
    only by the elite.
</t>
<t tx="ekr.20131024051649.17137">To create a new section, subsection, etc., in the output file:

1. Create a new outline node, as some descendant of the @rst node.

2. **The new node's headline becomes the section's title**.

3. Type the contents of the section in the body text of the node.

That's all there is to it:

- **The rst3 command generates rST underlining automatically**.

- **You reorganize your document by reorganizing nodes**.

There is *no* need to change markup when reorganizing your document, a huge improvement over writing "raw" rST.
</t>
<t tx="ekr.20131025044901.17144">"Not sure why you said 'you can specify a computer program as an outline like thing in an outliner like setting.' Why not just say, 'write a computer program in an outline?' Is there some nuance I am missing?"---EKR

There are probably a million reasons I said it like that, but I think the main one is my ever present, brightly burning belief that a program should be designed before its coded. Remember those guys, back in the day, who after receiving their programming assignment, would go to the keyboard and start pounding out C code? Remember their finished product? Remember how long it took them to finally complete the project?

Meanwhile, when receiving an assignment, I'd spend hours to days with a bunch of paper, drawing diagrams. By the time I sat down at the terminal, I knew my data structures and algorithms. The hours to days head start of the "start coding immediately" guys evaporated because for me, coding was just a secretarial task, and I was required to do less refactoring, or even worse, kludging. Later, sometimes I'd substitute an outliner for the diagrams on paper; in the days of functional decomposition, an outliner was the perfect fit.

Back to your question: If all I needed to do was **write** a program, I'd just sit down at a computer and start pounding out C or Python or Lua or whatever. But that's not my style. I need to **design** a program, and after all, a design is just a specification of how the program is going to be written.

So it seems to me that I *design* the program on Leo, and then, when the time comes, I flip a switch and Leo *writes* the program for me. That's how I'd view what I've heard about Leo.
</t>
<t tx="ekr.20131025044901.17147">It is often useful to put reference material in your @rst tree that will *not* be included in the actual output. To have the rst3 command ignore a single node, type this in the node's headline::

    @rst-ignore &lt;ignored-text&gt;

Neither the headline nor body text will be part of the output file.

To have the rst3 command ignore a node and all its descendants, type this in the node's headline::

    @rst-ignore-tree &lt;ignored-text&gt;
</t>
<t tx="ekr.20131025044901.17148">The `rST manual &lt;https://docutils.sourceforge.net/docs/user/rst/quickref.html#directives&gt;`_ tells how to insert "raw" markup into the output. For example, Leo's documentation defines the following::

    .. |---| unicode:: U+02015 .. for quotes
       :trim:

Now ``---`` inserts ---, the unicode "quotation dash" used to indicate the author of quotations. Note that rST automatically turns ``--`` into a dash: --.

The rST ``|`` markup breaks text into specific lines, but there are times when it can't be used.  The following inserts a line break into text::

    .. |br| raw:: html

       &lt;br /&gt;
</t>
<t tx="ekr.20131027064821.17144">The rst3 command applied to::

    @rst myDocument.html

will generate an **output file**, myDocument.html, from this node and its children, grandchildren, etc. The rst3 command creates the output file in the same directory as the .leo file containing the @rst node. You can specify other directories using absolute or relative paths. Examples::

    @rst myDocument.html        # in same folder as the .leo file
    @rst html/myDocument.html   # in a subfolder
    @rst ~/docs/myDocument.html # an absolute path to the folder

The rst3 command writes an **intermediate file** in the same directory as the output file. This intermediate file contains the reStructuredText markup generated by the rst3 command. It has the suffix .txt::

    myDocument.html.txt


</t>
<t tx="ekr.20131027064821.18685"></t>
<t tx="ekr.20131027064821.18689">When using sphinx you must ensure that sphinx's conf.py file is configured so that it will find the intermediate files created by the rst3 command. For example, the conf.py file for Leo's docs contains the following::

    source_suffix = '.html.txt'

This "matches" the form of the intermediate files.  For example, given::

    @rst myDocument.html

and the default value for the rst3_write_intermediate_extension setting::

    @string rst3_write_intermediate_extension = .txt

the name of the intermediate file will be::

    myDocument.html.txt

myDocument.html.txt is the **input** file for sphinx.
</t>
<t tx="ekr.20131028155339.17098">def openEmptyWorkBook(self):
    '''Open an empty frame and paste the contents of CheatSheet.leo into it.'''
    lm = self
    # Create an empty frame.
    fn = lm.computeWorkbookFileName()
    c = lm.loadLocalFile(fn, gui=g.app.gui, old_c=None)
    # Open the cheatsheet.
    if not g.os_path_exists(fn):
        # Paste the contents of CheetSheet.leo into c1.
        c2 = c.openCheatSheet(redraw=False)
        if c2:
            for p2 in c2.rootPosition().self_and_siblings():
                c2.selectPosition(p2)
                c2.copyOutline()
                p = c.pasteOutline()
                c.selectPosition(p)
                p.contract()
                p.clearDirty()
            c2.close(new_c=c)
            root = c.rootPosition()
            if root.h == g.shortFileName(fn):
                root.doDelete(newNode=root.next())
            p = g.findNodeAnywhere(c, "Leo's cheat sheet")
            if p:
                c.selectPosition(p, enableRedrawFlag=False)
                # p.expand()
            c.target_language = 'rest'
                # Settings not parsed the first time.
            c.clearChanged()
            c.redraw()
    return c
</t>
<t tx="ekr.20131028213522.17138">::

    usage: launchLeo.py [options] file1, file2, ...

    options:
      -h, --help            show this help message and exit
      -b, --black-sentinels write black-compatible sentinel comments
      --diff                use Leo as an external git diff
      --fail-fast           stop unit tests after the first failure
      --fullscreen          start fullscreen
      --gui=GUI             specify gui: console,curses,qt,text,null
      --listen-to-log       start log_listener.py on startup
      --maximized           start maximized
      --minimized           start minimized
      --no-plugins          disable all plugins
      --no-splash           disable the splash screen
      --quit                quit immediately after loading
      --save-session        always save session data when Leo closes
      --script=PATH         execute a script and then exit
      --script-window       execute script using default gui
      --select=ID           headline or gnx of node to select
      --silent              disable all log messages
      --theme=NAME          use the named theme file
      --trace=LIST          add one or more strings to g.app.debug

            A comma-separated list. Valid values are:
            abbrev, beauty, cache, coloring, drawing, events, focus, git, gnx,
            importers, keys, layouts, plugins, save, select, sections,
            shutdown, size, speed, startup, themes, undo, verbose, zoom.

      --trace-binding=KEY   trace commands bound to a key
      --trace-setting=NAME  trace where named setting is set
      --window-size=SIZE    initial window size: (height x width)
      --window-spot=SPOT    initial window position: (top x left)
      -v, --version         print version number and exit</t>
<t tx="ekr.20131028213522.17150"></t>
<t tx="ekr.20131030082936.17514">s = p.b
for child in p.children():
    s = s + '\n- ' + child.h
p.b = s</t>
<t tx="ekr.20131030184445.16582">##################
More Leo Resources
##################

.. _`2012 PyOhio talk`:     https://www.youtube.com/watch?v=JgJ89ekGj-s
.. _`Icons`:                icons.html
.. _`Introduction to Leo`:  https://www.youtube.com/watch?v=Zu6J-J0qFi0
.. _`Leo in a nutshell`:    https://groups.google.com/d/msg/leo-editor/lgHE4OJSLzw/2VXkckrvnsIJ
.. _`Leo page viewer`:      https://bl.ocks.org/kaleguy/cef095e16e147bc04dd6c5812d732fb2
.. _`Leo University`:       https://github.com/leo-editor/leo-editor/issues/816

.. Not a secure link
.. .. _`Mind Mapping`:         http://www.mind-mapping.org/
.. _`bookmarks plugin video`: https://vimeo.com/77720098 
.. _`literate programming`: http://www.literateprogramming.com/
.. _`scripting tutorial`:   http://blog.suspended-chord.info/2014/01/28/intro-to-leo-scripting/
.. _`slashdot article`:     testimonials.html#speed-ream-s-slashdot-article
.. _`wikipedia page`:       http://en.wikipedia.org/wiki/Leo_(editor)

Videos:

- Ville Vainio's `Introduction to Leo`_.
- Terry Brown's `bookmarks plugin video`_.
- Tom Fetherston's `2012 PyOhio talk`_

More resources:

- `Leo University`_: A short series of articles for would-be Leo developers.
- Speed Ream's `slashdot article`_ about Leo.
- Jacob Peck's `scripting tutorial`_.
- Leo's `wikipedia page`_.
- A page about `literate programming`_.
- Joe Orr's `Leo page viewer`_.
- Satish Goda's `Leo tutorial &lt;https://github.com/satishgoda/leo-editor-tutorial&gt;`_.
- `Icons`_ telling the world that you used Leo.
- `Leo in a nutshell`_: A summary Leo's more than one million lines of source code.
</t>
<t tx="ekr.20131031101712.16486">Supported by Leo's core::

    @chapter
    @rst, @rst-no-head, @rst-ignore, @rst-ignore-tree
    @settings
    @url

Within @settings trees::

    @bool, @buttons, @color, @commands
    @directory, @encoding
    @enabled-plugins, @float, @font,
    @history-list, @int
    @menus, @menu, @menuat, @item
    @openwith, @path, @shortcuts, @string

Supported by plugins::

    bookmarks.py:       @bookmarks, @bookmark
    at_folder.py:       @folder
    at_produce.py:      @produce
    at_view.py:         @clip, @strip, @view
    expfolder.py:       @expfolder
    mod_scripting.py:   @button, @command, @script
    viewrendered.py:    @graphics-script, @image
                        @html, @movie, @svg
</t>
<t tx="ekr.20131102044158.16488">The rst3 command requires the `docutils`_ Python package. You must also install the `Sphinx`_ package if you use sphinx markup. Sphinx gives Leo's and `Python's`_ websites their distinctive appearance and features. After installing docutils or sphinx, you must restart Leo so that the new installation will take effect.
</t>
<t tx="ekr.20131115075142.16636">Use .leo files to test settings rather than to contain data. These files would typically contain just an @settings tree, and one or two nodes illustrating their effect. Opening such files limits the effects of experimental/non-standard/risky settings. This is a great tip to know.

For example, the files leo10pt.leo, leo12pt.leo, leo14-12pt.leo and leo14pt.leo in the leo/config folder make it easy to compare different font settings.

As another example, when starting the vim-mode project I created a .leo file containing @bool vim-mode = True. By opening this file I test vim mode without interfering with my normal work flow.
</t>
<t tx="ekr.20131120115900.16329">################
Videos about Leo
################

.. |br| raw:: html

   &lt;br /&gt;

This page links to videos about Leo.  **Important notes**:

- Videos hosted at screencast.com look a bit clearer than YouTube videos, |br|
  but they may not always be available due to bandwidth limits.
- screencast.com viewers: click the "Full Size" button. |br|
- YouTube viewers: select top quality in the video settings. |br|
  YouTube videos typically become clearer after a few seconds.

**Potential screencasters**: please read these
`tips for screencast authors &lt;FAQ.html#how-to-make-a-screencast&gt;`_.

.. list-table::
   :widths: 10 30 10 10
   :header-rows: 1

   * - Level
     - Title
     - Screencast
     - YouTube
   * - Intro
     - A Brief Introduction to Leo
     - `hi-res &lt;https://www.screencast.com/t/xDZAOqfsAhPZ&gt;`__
     - `regular &lt;https://www.youtube.com/watch?v=tuM8MvI9g6k&gt;`__
   * - Intro
     - Leo for Programmers
     - `hi-res &lt;https://www.screencast.com/t/lgR6lMhWK&gt;`__
     - `regular &lt;https://www.youtube.com/watch?v=WkUbJAuFfI4&gt;`__
   * - Intro
     - Ville Vianio introduces Leo
     -
     - `regular &lt;https://www.youtube.com/watch?v=Zu6J-J0qFi0&gt;`__
   * - Basic
     - Using Leo’s Find pane
     - `hi-res &lt;https://www.screencast.com/t/O7915mYD3&gt;`__
     - `regular &lt;https://www.youtube.com/watch?v=K5mmlnSOkLM&gt;`__
   * - Basic
     - Using Leo’s minibuffer
     - `hi-res &lt;https://www.screencast.com/t/tEQ7brI4n6&gt;`__
     - `regular &lt;https://www.youtube.com/watch?v=dEaGOi6hVpo&gt;`__
   * - Intermediate
     - Using abbreviations
     -
     - `regular &lt;https://www.youtube.com/watch?v=WRoiXO53Aac&gt;`__
   * - Intermediate
     - Using clones to speed your work flow
     - `hi-res &lt;https://www.screencast.com/t/l8W9H5G8zB&gt;`__
     - `regular &lt;https://www.youtube.com/watch?v=DsHEHNLKi2o&gt;`__
   * - Plugin
     - Terry Brown demos bookmarks.py
     -
     - `regular &lt;https://vimeo.com/77720098&gt;`__
   * - Plugin
     - Fidel Perez demos mod_http.py
     -
     - `regular &lt;https://www.youtube.com/watch?v=9AvbL_0JEMw&amp;feature=youtu.be&gt;`__
   * - Plugin
     - mod_ftp.py
     -
     - `regular &lt;https://www.youtube.com/watch?v=bnj0NQuljQo&gt;`__
</t>
<t tx="ekr.20131122055946.16401">Making screencasts is a lot easier than you probably think. Here are some tips to get you started quickly.







</t>
<t tx="ekr.20131122055946.16402">The primary purpose of this script is to open your app at a fixed, unchanging size. This is surprisingly important:

- It ensures that the window will always render to pixels in the same way.
- It makes it easier to splice in new video to an existing video.
- It makes it easier to plan your video to ensure everything will appear as you expect.
- It provides continuity when making a series of videos.

Here is a script that I use when making Leo's screencasts::

    python launchLeo.py --gui=qttabs
    --window-size=682x1264 &lt;list of .leo files&gt; %*​

This *particular* --window-size causes Camtasia to create a window whose actual size is 720x1280, the nominal 720p resolution. It may prevent text blur. Or not. I do know that Leo's screencasts look great at 720p.
</t>
<t tx="ekr.20131122055946.16403">Make sure that you can actually upload *excellent quality* videos before doing anything else. This step is crucial. If you skip this step, all of your initial recording an post-production work could be utterly wasted.

Use *short* (10-second) test videos at this step. Their primary purpose verify that you can can get to the *end* of the production process successfully. You *are* going to make lots of mistakes here: using short videos helps you make these mistakes quickly.

Don't even *think* about making longer videos until the answers to all the following questions are clearly "yes":

- Is your camera working?
- Is your microphone working?
- Do you know how to record your voice and screen?
- Can you log into YouTube or screencast.com?
- Can you upload to YouTube or screencast.com?
- Is the sound in your *uploaded* video great?
- Do the pixels in your *uploaded* look great?

This last item is particularly important. Just because pixels look good in your video editor is no guarantee that they will look good when uploaded.

You are ready to try your first "real" take *only* when you can upload a video that looks and sounds great.
</t>
<t tx="ekr.20131122055946.16404">Before rushing right out and making your first video, I recommend watching the tutorial screencasts at screencast.com: https://www.techsmith.com/tutorial-camtasia-8.html

Watch the tutorials to see how the presentations themselves are organized. Watch them until it feels natural to emulate their style.

If you will be using Camtasia, you will also want to watch the tutorials to learn how Camtasia works.
</t>
<t tx="ekr.20131122055946.16405">Now it's time to go beyond test videos. Even now, though, I recommend keeping your first efforts short: one minute or so. Again, this saves time. You'll ending up throwing away two or three anyway ;-)

Bring up your app using you demo script and run through your presentation.

Here's the **most important tip**: As you narrate your video, audio flubs are inevitable, but they don't matter at all *provided* that you *realize* that you have just flubbed a word or phrase.

When you flub a line, don't panic! Just *pause*, regroup, and repeat the phrase until you get it right. *Pausing is essential*: it simplifies inserting and deleting sound bites during post production.

You'll relax once you realize that flubs don't matter and that pausing makes post-production easier. Once you relax, getting a good take will suddenly become easier.

Correcting flubs *as soon as they happen* is absolutely essential. Don't even *think* about fixing audio flubs in post-production. It simply can't be done. Instead of spending 20 minutes trying (and failing) to correct a flub in post production, it is much faster and better to take 20 seconds during your take to correct the flub.

Similar remarks apply to video, but in my experience it's much easier to get the video right. If you do flub the video, it will be much easier if you just do a complete retake. With Camtasia, you can separate the audio and video tracks, but usually that won't work, especially if there is audio of key clicks.

By retaking audio flubs as they happen, I find it easy to work without a script. It feels more natural to me than reading a script. YMMV. When I get stuck, I just pause. Or just start over. Otoh, it wouldn't be that hard to read a script. Just *pause* before and after each phrase. Never rush your audio!

In short, the key Aha is: insert (audio) pauses *everywhere* as needed. It's easy to edit them out. It's virtually impossible to edit in the middle of words, even with the world's best audio editor.
</t>
<t tx="ekr.20131122055946.16406">Post production should be easy provided that you have corrected all audio flubs as they happen. This keeps the audio and video in sync. Just edit out flubs and reduce overly-long pauses.

I won't discuss production details here because they depend on the editor you are using.

Do a new take if you don't have clean audio. Depending on the complexity of your video, it may be possible to splice a partial take in the middle or end of your video. Similarly, it may be possible to splice in a new take to add material you didn't cover in your first take.

One final word of advice. When editing your video, settle for "good enough". Perfectionism is not your friend.
</t>
<t tx="ekr.20131122055946.16407">Making a screencast is a lot easier than you think :-)

- Create a script that will open your app at a fixed, optimal, size.

- Emulate the style and form of screencast.com tutorials.

- Verify the *entire* production process with short test videos.

  Before making longer videos, make *sure* that the test videos look and sound great *when they have been uploaded*.

- When doing a take, flubs don't matter, *provided* you correct them *during the take*.  Use pauses.  Make haste slowly!

- Splice in new takes during post-production to fix flubs and add new material.
</t>
<t tx="ekr.20131129061821.16884">Here are some more tips I've learned from experience:

1. Redo audio tests and video tests every time you start a new session. It's amazing how hum can creep into recordings.

2. The most important step in post production is to get the pacing so it feels right. Beware of editing out pauses. Make sure you give your viewers time to see what you are doing, and to see what you have done.

3. Don't waste time on callouts or captions until the audio and video work together at a relaxed pace. It's almost as hard to correct pacing mistakes as it is to correct audio flubs.
</t>
<t tx="ekr.20131211054925.16388">1. Enable volume leveling and noise removal in Camtasia. This tip, all by itself, makes a big difference.

2. Use a better microphone, preferably one with about a 1-inch diaphragm. This is the kind of microphone that Andrew Price uses. The Audio-technica AT2020 USB is relatively inexpensive.

3. Use "pop filter" with the microphone. This is a cloth or (better) a metal screen that is placed in front of the microphone. It smooths the sound.

4. Adjust the sound level for maximum volume without distortion: With the microphone about a foot from your mouth, turn the volume as loud as possible, then turn down until no red is visible in the meter.
</t>
<t tx="ekr.20140216125129.16666"></t>
<t tx="ekr.20140720203932.17747">Leo can automatically import and export Emacs org-mode (.org) files. Nodes like::

    @auto-org-mode &lt;path to .org file&gt;

or equivalently::

    @auto-org &lt;path to .org file&gt;

import the org-mode file as a Leo outline. 

These nodes work like other @auto nodes: when Leo loads an outline, Leo reads the .org file into the @auto-org-mode tree. When Leo writes an outline, Leo writes any @auto-org-mode tree back to the org-mode file.

After creating an @auto-org-mode node by hand, be sure to use Leo's refresh-from-disk command to populate the node. Do this *before* saving the .leo file. If you try to save an empty @auto-org-mode node Leo will warn you that you are about to overwrite the file.

The ``refresh-from-disk`` command creates an @auto-org-mode node whose **children** represent the contents of the external .org file. Leo does *not* write the @auto-org-mode node itself. This allows you to put Leo directives in the node.
</t>
<t tx="ekr.20140720203932.17748">Leo can automatically import and export vimoutline (.otl) files. Nodes like::

    @auto-otl &lt;path to .otl file&gt;

or equivalently::

    @auto-vimoutline &lt;path to .otl file&gt;

import the .otl as a Leo outline.

These nodes work like other @auto nodes: when Leo loads an outline, Leo reads the .otl file into the @auto-otl tree. When Leo writes an outline, Leo writes any @auto-otl tree back to the .otl file.

After creating an @auto-otl node by hand, be sure to use Leo's refresh-from-disk command to populate the node. Do this *before* saving the .leo file. If you try to save an empty @auto-otl node Leo will warn you that you are about to overwrite the file.

The refresh-from-disk command creates an @auto-otl node whose **children** represent the contents of the external .otl file. Leo does *not* write the @auto-otl node itself. This allows you to put Leo directives in the node.
</t>
<t tx="ekr.20140729162415.18086">def init_at_auto_names(self):
    '''Init the app.atAutoNames set.'''
    self.atAutoNames = set([
        "@auto-rst", "@auto",
    ])
</t>
<t tx="ekr.20140729162415.18091">def init_at_file_names(self):
    '''Init the app.atFileNames set.'''
    self.atFileNames = set([
        "@asis",
        "@edit",
        "@file-asis", "@file-thin", "@file-nosent", "@file",
        "@clean", "@nosent",
        "@shadow",
        "@thin",
    ])
</t>
<t tx="ekr.20140810085801.18216"></t>
<t tx="ekr.20140810085801.18217">Leo's vim mode dispatches keystrokes sent to it from k.masterKeyHandler to **key handlers**.

Each key handler handles the incoming key and then calls either vc.accept(), vc.done(), vc.ignore() or vc.quit(). These methods tell k.masterKeyHandler whether vim-mode has completely handled the key. If so, k.masterKeyHandler simply returns. Otherwise, k.masterKeyHandler handles the key as usual.
</t>
<t tx="ekr.20140810085801.18218">Key handlers handle a single key during the parsing of a vim command. Key handlers can either complete a command, thereby actually doing something, or change state so as to be able to parse (and possibly complete) the next incoming keystroke.

For example, the key handler for the G command handles the command completely. In contrast, two key handlers are needed to handle the gg command. The first handler, vc.vim_g, simply calls vc.accept(handler=vc.vim_g2). This call changes the vc.handler ivar to point to the **follow-on handler**, vim_g2. vim_g2 handles all commands after the user has typed 'g' in normal mode.

Each key handler must end with a call to an **acceptance method**. vc.accept is one such method. Acceptance methods prepare for the next keystroke by setting internal state ivars used by the various dispatchers.

Many key handlers simply call vc.done(). This method handles all the details of completing a key handler: it hides the details of parsing vim command.

**Important**: Any key handler that wants to change vc.state should set vc.state *before* calling vc.done()

Key handlers can call either **direct acceptance methods**, vc.accept, vc.delegate, vc.done, vc.ignore, vc.not_ready, vc.quit, and vc.reset, or **indirect acceptance methods**: vc.begin_insert_mode, vc.begin_motion, vc.end_insert_mode, and vc.vim_digits. Indirect acceptance methods must eventually call direct acceptance methods.
</t>
<t tx="ekr.20140810085801.18219">Dispatchers set the following ivars for each key handler:

**vc.w** is the widget that has focus. Key handlers may use convenience methods to determine the location and type of vc.w. The most important are:

- vc.is_text_widget(w): True if w is any text widget, including headlines, body text and log pane.

- vc.in_headline(w): True if w is a headline widget in edit mode.

**vc.stroke** is a standard Leo stroke representing the incoming key. Note that the spelling of the stoke using the Tk spellings. Take a look at entries in the dispatch dicts to see such spellings. When in doubt, enable the trace in vc.do_key to see the incoming strokes.

**vc.n1** and **vc.n** are the repeat counts in effect for each key handler. Dispatchers and their allies handle most details of setting these repeat counts, so most key handlers can simply use vc.n1*vc.n as the ultimate repeat count.

**vc.motion_i** is the insertion point *before* the motion has taken place.
</t>
<t tx="ekr.20140810085801.18220">The simplest way of moving the cursor or changing text is to use the vc.do method, a thin wrapper for c.k.simulateCommand.  For example:

.. code-block:: python

    if vc.state == 'visual':
        vc.do('end-of-buffer-extend-selection')
    else:
        vc.do('end-of-buffer')

Key handlers may also use the **high-level interface**. This is the API used throughout Leo's core. For details, see the HighLevelInterface class in leoFrame.py and various subclasses in qtGui.py.
</t>
<t tx="ekr.20140810085801.18221">The vc.vim_d method and its follow-on methods handle vim's d commands.

The vc.vis_d method handles the d keystroke that ends visual mode.

The following sections examine each piece of the code in detail. If you understand how it works you should know everything you need to write any other key handler.
</t>
<t tx="ekr.20140810085801.18222">:

.. code-block:: python

    def vim_d(vc):
        '''
        N dd      delete N lines
        d{motion} delete the text that is moved over with {motion}
        '''
        if vc.is_text_widget(vc.w):
            vc.n = 1
            vc.accept(handler=vc.vim_d2)
        else:
            vc.quit()

This is the key handler for the 'd' key in normal mode.

The entry in vc.normal_dispatch_d for 'd' is: 'd':vc.vim_d.

Because this command changes text, vc.is_text_widget(vc.w) must be True. If
so, this handler simply calls vc.accept(handler=vc.vim_d2) to queue up the
follow-on handler. Otherwise, the handler calls vc.quit() to end the
command.

</t>
<t tx="ekr.20140810085801.18223">:

.. code-block:: python

    def vim_d2(vc):
        if vc.is_text_widget(vc.w):
            if vc.stroke == 'd':
                w = vc.w
                i = w.getInsertPoint()
                for z in range(vc.n1*vc.n):
                    # It's simplest just to get the text again.
                    s = w.getAllText()
                    i,j = g.getLine(s,i)
                    # Special case for end of buffer only for n == 1.
                    # This is exactly how vim works.
                    if vc.n1*vc.n == 1 and i == j == len(s):
                        i = max(0,i-1)
                    w.delete(i,j)
                vc.done()
            else:
                vc.d_stroke = vc.stroke # A scratch var.
                vc.begin_motion(vc.vim_d3)
        else:
            vc.quit()

This is the follow-on handler for the 'd' command. It will be called when
the user types a *second* character following the 'd' command in normal
mode.

All forms of the 'd' command alter text, so this handler calls vc.quit if
vc.w is not a text widget.

If the second character is another 'd', we have the 'dd' command. The code
uses the high-level interface to delete a line, then calls vc.done() to end
the command.

If the second character is *not* a 'd', it should be a following motion,
such as "2j" in "d2j".

vc.vim_d2 remembers the character that started the motion in a **scratch
ivar**, vc.d_stroke. Such ivars are not inited or touched outside of vim_d
and its follow-on key handlers. This code must remember this character so
that the vim_d3 handler will know whether to expand the deleted text to a
line.

Finally, vc.vim_d2 calls vc.begin_motion, which does the following:

- Calls vc.ignore if the second character doesn't really start a motion.
- Sets vc.handler to vc.do_inner_motion.  This handles the motion.
- Sets the vc.after_motion to the next follow-on handler: vc.vim_d3.
  vc.vim_d3 will be called when the motion is complete. The details are
  complicated, but happily the key handlers don't have to know about them!
</t>
<t tx="ekr.20140810085801.18224">:

.. code-block:: python

    def vim_d3(vc):
        '''Complete the d command after the cursor has moved.'''
        # d2w doesn't extend to line.  d2j does.
        trace = False and not g.unitTesting
        if vc.is_text_widget(vc.w):
            extend_to_line = vc.d_stroke in ('jk')
            w = vc.w
            s = w.getAllText()
            i1,i2 = vc.motion_i,w.getInsertPoint()
            if i1 == i2:
                if trace: g.trace('no change')
            elif i1 &lt; i2:
                for z in range(vc.n1*vc.n):
                    if extend_to_line:
                        i2 = vc.to_eol(s,i2)
                        if i2 &lt; len(s) and s[i2] == '\n':
                            i2 += 1
                        if trace: g.trace('extend i2 to eol',i1,i2)
                w.delete(i1,i2)
            else: # i1 &gt; i2
                i1,i2 = i2,i1
                for z in range(vc.n1*vc.n):
                    if extend_to_line:
                        i1 = vc.to_bol(s,i1)
                        if trace: g.trace('extend i1 to bol',i1,i2)
                w.delete(i1,i2)
            vc.done()
        else:
            vc.quit()

This is the second and last follow-on handler for the d command. The
dispatcher that handles vim motions will call this handler after the
motions **have actually happened**.

First, the code double-checks that we are still in a text widget, calling
vc.quit() if not.

Next, the code compares the present insertion point, w,getInsertPoint(),
with the insertion point before the motion happened, vc.motion_i. It
extends the selection range if the scratch ivar, vc.d_stroke, is in ('jk').
The code then deletes the selected text.

Finally, this method calls vc.done().
</t>
<t tx="ekr.20140810085801.18225">:

.. code-block:: python

    def vis_d(vc):
        '''Delete the highlighted text and terminate visual mode.'''
        w  = vc.vis_mode_w
        if vc.is_text_widget(w):
            i1 = vc.vis_mode_i
            i2 = w.getInsertPoint()
            w.delete(i1,i2)
            vc.state = 'normal'
            vc.done()
        else:
            vc.quit()

This is the key handler for the 'd' key in normal mode.

It is *not* a follow-on method of vim_d. The dispatcher calls this method
after visual mode has highlighted text. Here is the entry for 'd' in
vc.visual_dispatch_d: 'd':vc.vis_d.

Visual mode has already highlighted the text to be deleted, so this code
simply deletes the highlighted text and calls vc.done().

</t>
<t tx="ekr.20140810085801.18226">The VimCommands class in leoVim.py implements Leo's vim mode. Vim mode is active only if @bool vim-mode = True.

The following sections will be of interest only to those seeking a deep knowledge of how vim mode's dispatchers work. Such knowledge should rarely be required because dispatchers and key handlers are completely unaware of each other. Dispatch dicts and acceptance methods shield dispatchers and key handlers of all knowledge of each other. In particular, acceptance methods handle the sometimes tricky details of ending a key handler.

Leo's vim code is spectacularly different from the real vim's code. Wherever possible, Leo uses methods to hide implementation details.

Ironically, now that everything is hard coded in tables, it would be easy for plugins to customize the workings of vim-mode.
</t>
<t tx="ekr.20140810085801.18227">The init code for each Leo commander c assigns an instance of VimCommands to c.vimCommands. This is done regardless of the @bool vim-mode setting.

Each ivar of the VimCommands class is inited by exactly one of the following::

    vc.init_constant_ivars()
    vc.init_dot_ivars()
    vc.init_persistent_ivars()
    vc.init_state_ivars()
    vc.create_dispatch_dicts()

In effect, this code partitions each ivar into disjoint sets. This partitioning simplifies code that must re-init some ivars but not others.

The init code creates **dispatch dicts** used by dispatchers.  
</t>
<t tx="ekr.20140810085801.18228">Depending on various state date, dispatchers route incoming keys to the proper **key handler**. Dispatchers use **dispatch dicts** to assign handlers to incoming keys. These dicts eliminate almost all special case code.

vc.do_key is the top-level dispatcher. k.masterKeyHandler calls it for all keys *except* Ctrl-G. **Note**: k.masterKeyHandler calls vc.do_key only when there no key state in effect, that is, when the minibuffer is not active.

As discussed below, the value returned by vc.do_key tells k.masterKeyHandler whether vim mode has completely handled the key.

Depending on the vc.handler ivar, vc.do_key can route the incoming key either to an **inner dispatcher** or directly to a key handler.

Inner dispatchers handle keys for a particular vim mode using dispatch dicts. Inner dispatchers the following ivars behind the scenes::

    vc.handler, vc.next_func, vc.return_value
    vc.in_motion and vc.motion_func

Handling these ivars can be tricky; hiding the details greatly simplifies all key handlers.
</t>
<t tx="ekr.20140810085801.18229">vc.do_key returns the value of vc.return_value. Most the acceptance functions set vc.return_value to True, indicating that vim mode has completely handled the key and that k.masterKeyHandler should simply return. k.masterKeyHandler handles the key as usual if vc.do_key returns False.

Each key handler sets vc.return_value indirectly by calling an acceptance method. A simple check in vc.do_key ensures that every key handler, has, in fact, called an acceptance method. In practice, this check has been very effective.
</t>
<t tx="ekr.20140810085801.18230">In general, vim-mode in Leo works much as in the real vim. There are three modes, insert, normal and visual.



</t>
<t tx="ekr.20140810085801.18231"></t>
<t tx="ekr.20140810085801.18232">#############################
Vim Mode: Theory of Operation
#############################

.. |br| raw:: html

   &lt;br /&gt;

This is the theory of operation of Leo's vim mode, contained in
leo/core/leoVim.py. It discusses everything you need to understand the code
and to add new vim commands.

.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="ekr.20140810153947.6747">- Cursor motions: ^,$,0,b,e,f,F,gg,gG,j,h,k,l,t,T,w.
- The gb,ge,gh commands are synonyms for 0,$,^.
- The h,j,k,l commands work on outlines when entered in the outline pane.
- 0 in outline pane: goto-first-visible-node
- e in outline pane: goto-last-visible-node.
- Deleting text: d{motion},{motion}d,v{motion}d,diw,x.
- Insert commands: a,A,i,o,O and switch to insert mode if entered in the outline pane.
- Yank &amp; paste commands: y,p. These act on outlines if entered in the outline pane.
- Search commands: /,?,n,*,#.  These commands are node-only searches.
- The dot command '.' works for motions, but not yet for inserts or searches.
- v: start/end visual mode.

Notes:

- Except as noted above, all vim-mode commands must be entered in the body pane.
- &lt;Return&gt; in headlines switches to the outline pane.
- &lt;Return&gt; in the outline pane switches to the body pane.
</t>
<t tx="ekr.20140810153947.6749">- The ``jj`` abbreviation switches to normal mode, preserving the changed
  status of the .leo file.
- Return in visual/normal mode enters insert mode.

..  - ``,,`` in normal mode now moves to insert mode.
..  ``,,`` in insert mode does nothing, unless there is an abbreviation template available.
</t>
<t tx="ekr.20140810153947.6750">The ':' command enters Leo's minibuffer, with ':' pre-inserted. You may
backspace over the ':'. Here are the commands::

    :! Execute a shell command.
    :e! Revert all changes to a .leo file, prompting if there have been changes.
    :gt cycle-focus
    :q Quit, prompting for saves.
    :qa Quit only if there are no unsaved changes.
    :r Prompt for a file name.  Insert it at the cursor.
    :tabnew Prompt for a file name, and open a new tab.
    :w Save the .leo file.
    :wa Save all changed  .leo files.
    :wq Save all open files and exit.
    :xa ave all open files and exit.

The following colon commands are unique to Leo::

    :print-vim-dot
    :toggle-vim-mode
    :toggle-vim-trainer-mode
</t>
<t tx="ekr.20140810153947.6751">**@bool vim-mode = False**: Enables Leo's vim mode when True.

**@bool vim-crosses-lines = True**: When True the f,F,h,l,t,T,x
commands may cross line boundaries.
</t>
<t tx="ekr.20140810153947.6752">- The gb,ge,gh commands are synonyms for 0,$,^.
- The h,j,k,l commands work on outlines when entered in the outline pane.
- The a,A,i,o,O commands switch to insert mode if entered in the outline pane.
- The y,p commands act on outlines if entered in the outline pane.
- Ending visual mode with 'v' retains the selection range.
- Ctrl-H puts the headline in insert mode.
- Mouse clicks never change vim's state.

</t>
<t tx="ekr.20140811083910.18246">The handler for the G command moves or extends the cursor depending on vc.state:

.. code-block:: python

    def vim_G(vc):
        '''Put the cursor on the last character of the body pane.'''
        if vc.is_text_widget(vc.w):
            if vc.state == 'visual':
                vc.do('end-of-buffer-extend-selection')
            else:
                vc.do('end-of-buffer')
            vc.done()
        else:
            vc.quit()

On entry, the dispatcher has set vc.w to the widget with focus. First, the code ensures that this widget is a text widget. If so, the code uses the vc.do method, a thin wrapper for c.k.simulateCommand, to execute Leo commands by name.
</t>
<t tx="ekr.20141030042423.9">Use the %~dp0 syntax.  Example::

  %~dp0\Python27\python.exe %~dp0\Leo-editor\launchLeo.py

https://ss64.com/nt/syntax-args.html
https://stackoverflow.com/questions/5034076/what-does-dp0-mean-and-how-does-it-work

FYI, this FAQ entry fixes the following bug: https://bugs.launchpad.net/leo-editor/+bug/613153 unable to describe root directory on thumb drive
</t>
<t tx="ekr.20141102043816.5">def define_delegate_language_dict(self):
    self.delegate_language_dict = {
        # Keys are new language names.
        # Values are existing languages in leo/modes.
        "less": "css",
        "hbs": "html",
        "handlebars": "html",
    }
</t>
<t tx="ekr.20141105050314.163">::

    --no-persist and --trace-plugins command-line options
    Optional warning buttons when selecting large text
    Added support for delegate languages
    Added support for the dart language
    Added leo/external/leoftsindex.py
</t>
<t tx="ekr.20141105050314.181">::

    Most plugins now work with PyQt5
    Rewrote at_produce.py
    Added livecode.py
    Added nodetags.py
    Added viewrendered2.py
    Added wikiview.py
</t>
<t tx="ekr.20141105050314.197">::

    Added settings that control PythonTidy-based beautify command:

        @bool use_python_tidy = True
        @bool tidy_add_blank_lines_around_comments = True
        @bool tidy_double_quoted_strings = False
        @bool tidy_keep_blank_lines = True
        @bool tidy_left_adjust_docstrings = False
        @int  tidy_lines_before_split_lit = 2
        @int  tidy_seps_before_split_line = 8

    Other settings:

        Added @bool auto-scroll-find-tab
        Added support for html handlebar syntax coloring
        Leo's main style sheet is fully parameterized
        Leo stylesheets now support all color names in leoColor.py
</t>
<t tx="ekr.20141105050314.25"></t>
<t tx="ekr.20141105052052.2">::

    Idle-time commands:

        disable-idle-time-events
        disable-idle-time-tracing
        enable-idle-time-events
        enable-idle-time-tracing
        toggle-idle-time-events
        toggle-idle-time-tracing

    Spell as you type commands:

        spell-as-you-type-toggle
        spell-as-you-type-next
        spell-as-you-type-undo

    Other commands:

        clone-find-parents
        clone-to-last-node
        flatten-outline-to-node
        focus-to-find
        focus-to-spell
        help-for-drag-and-drop
        insert-file-name
        pylint
        style-reload</t>
<t tx="ekr.20141105055521.5">The ``livecode-show`` commands shows the live code evaluation pane. Hover on the buttons for helpful tool-tips.

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

    pip install meta

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

   a = 7

is easy, but::

   m[m[5]] = 7

is not.
</t>
<t tx="ekr.20141105055521.6">Provides node tagging capabilities to Leo. See the docstring for details. By Jacob M. Peck.

</t>
<t tx="ekr.20141105055521.7">An alternative to the viewrendered plugin.  See the plugin's docstring for details, as well as these two posts:

https://groups.google.com/d/msg/leo-editor/3dH_NSQ4TsQ/ueVewAn50ZcJ

https://groups.google.com/d/msg/leo-editor/BDzmytlSegw/C0IbSz0US54J

</t>
<t tx="ekr.20141105055521.8">Creates a global search window. Use the ``global-search`` command to show this window. To restore the original appearance of the window, type help. Requires the whoosh library ('easy_install whoosh') to do full text searches.
</t>
<t tx="ekr.20141108064630.12">File under things-I-didn't-know-but-should-have:

Instead of creating batch files all over the place to fire up python programs, and then having to cope with annoying "Terminate batch job (Y/N)?" with Ctrl-C/Break you can ask python setuptools to create an .exe in the Python\Scripts folder.

in same folder as foo.py create setup.py, populate like so::

    from setuptools import setup

    setup(
        name='Foo for you',
        version='0.3',
        py_modules=['foo'],
        entry_points='''
            [console_scripts]
            foo = foo
            '''
        )

Then run "pip --editable install . " in the same folder. Foo.exe will be created in C:\pythonxx\Scripts. As long as that folder is in path you can use foo like any other command line program. Furthermore the "editable" parameter means we can continue to edit and change foo.py and the changes are always live.

Yeah! No more "pushd ..\path\to\data\folder &amp;&amp; python ..\path\to\code\foo.py
--do-stuff-here ..." for me. :)

.. Works for Leo too -- with the existing setup.py. It creates leo.exe and leoc.exe for Windowed mode (no log messages to console) and console mode respectively.
</t>
<t tx="ekr.20141108064630.13">.. in FAQ

Leo executes scripts with c and g predefined.

g is the leo.core.leoGlobal. Use g to access any function or class in leo/core/leoGlobals.py::

    g.app                   A LeoApp instance.
    g.app.gui               A LeoGui instance. 
    g.app.pluginsController A LeoPluginsController instance.
    g.app.*                 Leo's global variables.

c is the Commander object for the present outline. Commander objects define **subcommanders** corresponding to files in leo/core and leo/commands::

    # in leo/core...
    c.atFileCommands
    c.chapterController
    c.fileCommands
    c.findCommands
    c.importCommands
    c.keyHandler = c.k
    c.persistenceController
    c.printingController
    c.rstCommands
    c.shadowController
    c.testManager
    c.vimCommands

    # In leo/commands...
    c.abbrevCommands
    c.controlCommands
    c.convertCommands
    c.debugCommands
    c.editCommands
    c.editFileCommands
    c.gotoCommands
    c.helpCommands
    c.keyHandlerCommands
    c.killBufferCommands
    c.rectangleCommands
    c.spellCommands

Scripts can gain access to all of the code in these files via these subcommanders. For example, c.k is an instance of the LeoKeys class in leo/core/leoKeys.py.</t>
<t tx="ekr.20141108064630.14">If I want to use leo to make mathematical notes, how can I type in some special mathematical symbols? Or is there a good way to make mathematical notes using leo?

===== Terry

I use itex2MML with reStructuredText.  So within Leo you're looking at LaTeX math markup, and you get outputs in PDF and XHTML, with MathML in the latter.

===== Jose

I've been doing this for about a year now.  I use the math docutils directive.  A custom .XCompose file (for example: https://github.com/kragen/xcompose)  also helps.

===== Terry

I think math was added to docutils after I started using itex2mml, neater to use docutils built in math now I think.

Although having said that, playing with docutils math a bit suggests itex2mml gives more complete support for both MathML and perhaps LaTeX math (with the PDF target).

===== Jose

Terry, your setup is probably more flexible, but I haven't had any problems with docutils math. It seems to support all the syntax that I've found necessary.

I forgot to mention that the viewrendered plug-in doesn't display math correctly.  I'm not sure what the problem is, I remember trying to figure it out a while back, but I never got anywhere.  It's not really a big problem though, I have scripts to compile nodes to html/pdfs and open them in firefox/pdf reader; math works fine that way.

===== Offray

Is not properly Leo, but is python related, tailored for math and with a web interface and has leo bindings, check IPython: https://ipython.org/

I'm using it for all my math related writing and I think that point the future of interactive writing in Python. I dream of a body pane on leo with the features of the python qt console.
</t>
<t tx="ekr.20141108064630.15">The code that handles the rclick menu is in the QtIconBarClass class in qt_frame.py.

Show that the  top-level button contains structure, do this::

    @string mod_scripting_subtext = ▾

An alternative: ▼ U=25BC: Black Down-Pointing Triangle.

It's reasonable to have the top-level button just be a placeholder for subsidiary @rclick nodes. To do that without getting a warning when clicking the top-level button, set its script to "empty string".
</t>
<t tx="ekr.20141108064630.16">Put the following in the style-sheet:

    QTextEdit#richTextEdit { background-image: url('/home/tbrown/Desktop/cow2.jpg'); }

If you wanted node specific backgrounds Leo would have to start setting an attribute on the body widget, probably the gnx, so you could do::

    QTextEdit#richTextEdit[leo_gnx='tbrown.20130430222443.19340'] { 
        background-image: url('/home/tbrown/Desktop/cow2.jpg'); 
    }
</t>
<t tx="ekr.20141108064630.18">I'm trying to create a interactive chart in a embedded in a new leo pane using matplotlib. However, I am not sure about the the best way to implement this. I would appreciate some guidance on this please? The questions I would like answered are:

1. How do I create a new blank pane for embedding a chart as well as other QtWidgets.

2. Can I do this in a script or do I need to work with leo source?

I want to create a data processing and visualization tool kit in leo. Like Excel but using nodes instead of columns. Nodes will have data and I want to create new data nodes by applying python functions to data in existing nodes. The thing missing is the visualization within a leo pane (I can easily launch a chart in it's own window).

**Terry Brown**

You can run this script from any body pane::

    '''
    A script that adds a MatPlotLib pane to Leo.

    After running this script, right click on one of the pane dividers and
    select Insert. A new pane with a button 'Action' appears. Click it, and
    select "Add matplot" from the context menu.
    '''

    from leo.core.leoQt import QtWidgets

    class MatplotPaneProvider:
        def __init__(self, c):
            self.c = c
            if hasattr(c, 'free_layout'):
                splitter = c.free_layout.get_top_splitter()
                if splitter:
                    splitter.register_provider(self)
        def ns_provides(self):
            return[('Add matplot', '_add_matplot_pane')]
        def ns_provide(self, id_):
            if id_ == '_add_matplot_pane':
                c = self.c
                w = QtWidgets.QSlider() ### w = myMatplotWidget()
                return w
        def ns_provider_id(self):
            # used by register_provider() to unregister previously registered
            # providers of the same service
            # provider ID is not the same as the service id_ above
            return "completely unique value here"

    MatplotPaneProvider(c)

**OP**

I have managed to get a matplotlib graph embedded within a pane in leo as a widget. I now need some help with how to interact with the widget using scripts in leo. I am unsure about the following:

*1/ How do I expose the widget within the leo environment?* 

If you were only going to have one and you weren't going to destroy it, you could just do something simple like c._matplot = self in its constrictor (assuming c was passed to the constructor).

If you're going to have more than one and they may be destroyed, it might be simplest to let the free_layout / nested_splitter system manage them::

    ts = c.free_layout.get_top_splitter()
    matplotters = ts.findChildren(myMatplotWidget)

should return a list of the widgets of your class in the layout, but only if they're in the main window, widgets in extra windows opened from the "Open window" context menu item would be missed, I can add a find_children() method to complement the find_child() method the splitters already have to account for this.

Detail: the above is just using Qt's QObject.findChildren(), the nested_splitter find_child() and (not yet written) find_children() versions search the extra windows as well.

Here I have created a self.mat in your MatplotPaneProvider class to make the widget accessible but it doesn't feel like the correct way to do this::

    mat = MatplotPaneProvider(c)
    mat.mat.someMethod()
    mat.mat.someOtherMethod()

2. I would also like to make the widget accessible from any script within leo. What's the leo way of doing this?

See above

3. If I create more than 1 pane containing these widgets. How do I switch between them in scripts?

See above

4. Running this script more than once creates multiple items for Add Matplot when pressing the Action button. How do I stop this from happening? I have already tried returning a unique integer in * ns_provider_id *but that did not work.*

The value returned by ns_provider_id should be unique for the provider class, but constant. So it can just return something like "matplotlib provider ver 1"
</t>
<t tx="ekr.20141108064630.8">.. https://groups.google.com/d/msg/leo-editor/4s44H9cUJGY/ewRBDBSw-A8J

For the last several weeks I've used clones in a new, more effective way, inspired by git's stash/unstash commands. Here are the main ideas.

1. [Most important] I avoid putting clones in two different *external* files.

For any task, I create a task node that resides in @file leoToDo.txt. I clone that node and put it in the outline, *never* in any other @file node. This instantly eliminates clone wars.

2. I use top-level "stashed" nodes/trees in my local copy of leoPy.leo.

These clones are *not* written to any external file, so they would be lost if I lost leoPy.leo. But the risks are negligible because all stashed nodes are clones of nodes that *do* exist in external files.

3. I have two main stashed trees: recent files and recent code.

The "recent files" tree contains clones of all the @file nodes I have worked on recently. This speeds up access to them. That happens surprisingly often--often enough to be well worth maintaining the tree. Furthermore, because Leo's new pylint command now works on trees, I can check all recently-changed files simply by running pylint on the "recent files" tree.

The "recent code" tree is even more valuable, for three reasons. The first is obvious--it speeds access to recently-changed nodes.

Second, the "recent code" tree allows me to work on multiple tasks without getting overwhelmed by details and loose nodes lying around. I add organizer nodes as needed to make accessing the nodes faster, and also to jog my memory about what I was doing when I changed those nodes ;-)

Third, the "recent code" tree allows me *not* to put clones in the @file leoProjects.txt tree. This leads me to...

4. I use clones in a stylized way when fixing and committing bugs.

I always use clones when working on a project. A "task" node contains clones of all nodes related to the task. The task node typically remains in leoToDo.txt until the task is completely finished. While working on the bug, I create a clone of the task node, and move that clone to the bottom top-level node of the outline. Among other things, this makes it easy to limit searches without actually choosing "suboutline only" in the Find panel. This workflow is decades old.

The following is the heart of the new workflow. When a task is complete, I do the following:

A. First, I create a **stashed-task** node, containing all the clones that were previously in the task node.

The *stashed-task* becomes pre-writing for the commit log. The *task* node instantly becomes pre-writing for the release notes, so if it needs to discuss any code in the clones that have just been moved to the stashed-task node, I write those words immediately, while all details are fresh in my mind.

B. Now I move the cloned task node that is in leoToDo.txt to the appropriate place in leoProjects.txt.

C. Next I do the commit.

The *other* clone of the task node, and the stashed task node are still within easy reach, and I typically use both nodes to create the commit log. The commit will typically consist of the changed leoToDo.txt and leoProjects.txt and whatever .py files the task itself changed. Happily, leoToDo.txt and leoProjects.txt are now up-to-date because of steps A and B.

D. Finally, I clean up.

I delete the top-level clone of the task node, and move the stashed-task
node to the "recent code" tree.

E. Later, when it appears that activity has died down on various projects, I'll delete nodes from the "recent files" an "recent code" trees. This is a minor judgment call: I want to leave nodes in the trees while they are useful, but not significantly longer than that. I do *not* regard these trees as permanently useful. leoProjects.txt should contain *all* permanent notes about a project.

===== Conclusions

This work flow may seem complicated. Believe me, it is not. It's easier to use than to describe.

This workflow has big advantages:

1. Clone wars are gone for good.
2. All recent data is easily available.
3. Task nodes and stashed-task nodes provide natural places for proto-documentation.
4. Banning clones from leoProjects.txt forces me to complete the first draft of the documentation before committing the fix.
</t>
<t tx="ekr.20141109053526.4"></t>
<t tx="ekr.20141109053526.8">GTD (Getting Things Done) https://www.amazon.com/Getting-Things-Done-Stress-Free-Productivity/dp/0142000280 is, by far, the best productivity book I have ever read. Many aspects of Leo are idea for putting GTD into practice.

Here is a surprisingly useful workflow tip related to GTD.

Ideas often "intrude" when I am busy with something else. When that happens, I create a top-level node of the form::

    ** description of idea

Now I can continue what I was doing! This is such a simple idea, but it's really really important: it means I never have to put off getting my ideas into Leo. The "**" draws my attention to the new to-do item. Later, when I am not fully immersed in the previous task, I can put the "**" node somewhere else.

It's super important to deal with new ideas *instantly* but *without* greatly interrupting the task at hand. Creating "**" nodes does that. This new workflow has been a big improvement to my GTD practice.
</t>
<t tx="ekr.20141117065749.3"></t>
<t tx="ekr.20141124094250.2">A **session** specifies a list of .leo files that Leo opens automatically when Leo first starts.  Leo will reload the last session provided that command-line arguments *don't* contain any file names.

Leo stores session state in ``~/.leo/leo.session``. Session state consists of the list of open files and the selected node in each file.</t>
<t tx="ekr.20141210095600.11">I am a microbiologist mostly analyzing large numbers of bacteria genomes for which I use almost entirely Python tools. A couple of years ago while working at Yale University I gave Leo go for writing Python and organizing my notes with.

Not only do I now use Leo is a central repository for scripts I write as I explore the data, generate plots, start analyses with third party applications etc., but also for storing and organizing ideas for research and notes parsed out of PDFs of academic papers. And that's just for work!

I have a calendar, addresses all my general PIM-type info, and notes for any project I'm tinkering with. In short whether I'm at work or play Leo is usually involved :-)
</t>
<t tx="ekr.20150210062226.4">This appendix documents the Mulder/Ream update algorithm in detail, with an informal proof of its correctness.

Prior to Leo 5.1, Leo used Bernhard Mulder's original algorithm to read @shadow files. Starting with Leo 5.1, Leo uses this algorithm to read both @clean and @shadow files. Conceptually, both algorithms work as described in the next section.

In February 2015 EKR realized that the @shadow algorithm could be used to update @clean (@nosent) files. Simplifying the algorithm instantly became a top priority. The new code emerged several days later, made possible by the x.sentinels array. It is an important milestone in Leo's history.
</t>
<t tx="ekr.20150210062226.5">The algorithm depends on three simple, guaranteed, properties of
SequenceMatcher.opcodes. See
https://docs.python.org/2/library/difflib.html#sequencematcher-examples

**Fact 1**: The opcodes tell how to turn x.a (a list of lines) into x.b
(another list of lines).

The code uses the a and b terminology. It's concise and easy to remember.

**Fact 2**: The opcode indices ai, aj, bi, bj *never* change because
neither x.a nor x.b changes.

Plain lines of the result can be built up by copying lines from x.b to x.results::

    'replace'   x.results.extend(x.b[b1:b2])
    'delete'    do nothing  (b1 == b2)
    'insert'    x.results.extend(x.b[b1:b2])
    'equal'     x.results.extend(x.b[b1:b2])

**Fact 3**: The opcodes *cover* both x.a and x.b, in order, without any gaps.

This is an explicit requirement of sm.get_opcode:

- The first tuple has ai==aj==bi==bj==0.

- Remaining tuples have ai == (aj from the preceding tuple) and bi == (bj
  from the previous tuple).

Keep in mind this crucial picture:

- The slices x.a[ai:aj] cover the x.a array, in order without gaps.
- The slices x.b[bi:bj] cover the x.b array, in order without gaps.

</t>
<t tx="ekr.20150210062226.6">Given the x.sentinels array, the strategy for creating the results is
simple. Given indices ai, aj, bi, bj from an opcode, the algorithm:

- Writes sentinels from x.sentinels[i], for i in range(ai,aj).

- Writes plain lines from b[i], for i in range(bi,bj).

This "just works" because the indices cover both a and b.

- The algorithm writes sentinels exactly once (in order) because each
  sentinel appears in x.sentinels[i] for some i in range(len(x.a)).

- The algorithm writes plain lines exactly once (in order) because
  each plain line appears in x.b[i] for some i in range(len(x.b)).

This completes an informal proof of the correctness of the algorithm.

The leading and trailing sentinels lines are easy special cases. This
code, appearing before the main loop, ensures that leading lines are
written first, and only once:

.. code-block::

    x.put_sentinels(0)
    x.sentinels[0] = []

Similarly, this line, at the end of the main loop, writes trailing
sentinels:

.. code-block::

    x.results.extend(x.trailing_sentinels)
</t>
<t tx="ekr.20150210062226.7">The algorithm creates an updated set of lines *with* sentinels using the
@clean outline and the updated external file. These new lines then replace
the original @clean with a new @clean tree. The algorithm uses only
difflib. It will work with *any* kind of text file. No knowledge of any
language is needed.

The algorithm depends on simple, guaranteed, properties of indices in
SequenceMatcher opcodes.

The algorithm steps through x.sentinels and x.b, extending x.results
as it goes.

The algorithm gets all needed data directly from opcode indices into
x.sentinels and x.b. Using opcode indices requires neither reader
classes nor auxiliary indices.

The algorithm is simple enough to be understood at first reading. I'll
remember its details for the rest of my life.
</t>
<t tx="ekr.20150211131925.9">Mulder's original algorithm was hard to understand or to change. The
culprit was the x.mapping array, which mapped indices into arrays of lines
*with* sentinels to indices into arrays of lines *without* sentinels.

The new algorithm replaces the x.mapping array with the x.sentinels array.
As a result, diff indices never need to be adjusted and handling diff
opcodes is easy.

For any index i, x.sentinels[i] is the (possibly empty) list of sentinel
lines that precede line a[i]. Computing x.sentinels from old_private_lines
is easy. Crucially, x.a and x.sentinels are *parallel arrays*. That is,
len(x.a) == len(x.sentinels), so indices into x.a are *also* indices into
x.sentinels.
</t>
<t tx="ekr.20150212182032.4"></t>
<t tx="ekr.20150220115528.4">Leo updates @clean trees using a simplified version of the Mulder update algorithm previously used to update @shadow trees. This algorithm  is easy to understand, provably correct and completely documented. It may be of interest to the developers of other outliners.

https://leo-editor.github.io/leo-editor/appendices.html#the-mulder-ream-update-algorithm
</t>
<t tx="ekr.20150220145456.4">For simplicity, this discussion will assume that we are updating an
external file, x, created with @clean x. The update algorithm works
exactly the same way with @shadow trees.

The algorithm works with *any* kind of text file. The algorithm uses only
difflib. It knows nothing about the text or its meaning. No parsing is ever
done.

Suppose file x has been changed outside of Leo. When Leo reads x it does
the following:

1. Recreates the *old* version of x *without* sentinels by writing the
   @clean x *outline* into a string, as if it were writing the @clean x
   outline again.

2. Recreates all the lines of x *with* sentinels by writing the @clean x
   *outline* into a string, as if it was writing an @file node! Let's call
   these lines the **old sentinels** lines.

3. Uses difflib.SequenceMatcher to create a set of diffs between the
   old and new versions of x *without* sentinels.

   **Terminology**: the diffs tell how to change file a into file b. The
   actual code uses this terminology: **a** is set of lines in the old
   version of x, **b** is the set of lines in the new version of x.

4. Creates a set of lines, the **new sentinels lines** using the old
   sentinels lines, the a and b lines and the diffs.

   This is the magic. Bernhard Mulder's genius was conceiving that a
   three-way merge of lines could produce the new outline, *with*
   sentinels. The code is in x.propagate_changed_lines and its helpers.

5. Replaces the @clean tree with the new tree created by reading the new
   sentinels lines with the @file read logic.

**Important**: The update algorithm never changes sentinels. It never
inserts or deletes nodes. The user is responsible for creating nodes to
hold new lines, or for deleting nodes that become empty as the result of
deleting lines.
</t>
<t tx="ekr.20150220200101.2">Leo 5.1 (April 16, 2015) added ``@clean`` and the Mulder/Ream update algorithm.

In February 2015 I realized that the ``@shadow`` algorithm could be used to update ``@clean`` (aka ``@nosent``) files. This inspired me to simplify the ``@shadow`` update algorithm. The Mulder/Ream algorithm emerged several days later.

Thinking of using Leo as a diff program *might* have been the line of thought that lead to ``@clean``. It turned my attention to the ``@shadow`` algorithm, and that may have been enough to see that the algorithm could get sentinels from the ``.leo`` file instead of hidden shadow files.

I'll probably never be able to recreate a clearer picture of how the Aha came to be. That's the nature of big Aha's: they obliterate previous ways of thought so completely that it's hard to remember the time before the Aha.

The following paragraphs explain why ``@clean`` is one of the most important developments in Leo's history.
</t>
<t tx="ekr.20150222035621.5"></t>
<t tx="ekr.20150225133846.7">def doDiff(self):
    '''Support --diff option after loading Leo.'''
    if len(self.old_argv[2:]) == 2:
        pass # c.editFileCommands.compareAnyTwoFiles gives a message.
    else:
        # This is an unusual situation.
        g.es('--diff mode. sys.argv[2:]...', color='red')
        for z in self.old_argv[2:]:
            g.es(g.shortFileName(z) if z else repr(z), color='blue')
    commanders = g.app.commanders()
    if len(commanders) == 2:
        c = commanders[0]
        c.editFileCommands.compareAnyTwoFiles(event=None)
</t>
<t tx="ekr.20150311123850.39">Sentinels are necessary for clones, but sentinels would still be necessary if clones did not exist.

Sentinels create **identity**, the notion that a particular nodes starts at *this* place in the external file and extends to *this other* place. Identity is a persistent, invariant attribute of a file: Leo recreates all the nodes of the external files when re-reading the file.

It's really that simple, but here are some consequences:

1. Identity remains even when the contents of a node changes. Thus, there is *no way* to use content-related mechanisms to recreate identity. Git can never help recover identity.

2. Leo's sentinels mark an *arbitrary* range of text within the external file. @auto files can never be as flexible as @file nodes.
</t>
<t tx="ekr.20150311123850.41">::

    Added nodes-dark icons &amp; stylesheet.
    (https://groups.google.com/d/msg/leo-editor/BrruEaWaX4Y/A0g4HQFvNtAJ)
    Added --diff command-line option.
    @auto persistence enabled if and only if an @persistence node exists.
    @auto style parse on first @clean 'Refresh From Disk'
    (https://github.com/leo-editor/leo-editor/issues/148)
    Added LeoReleaseNotes.leo.
    Improved messages when find commands fail.
    Improved &lt;?xml-stylesheet&gt;.
    Added g.getLanguageAtPosition. Should have been done long ago.</t>
<t tx="ekr.20150311123850.56">@clean is a long-sought breakthrough. For the first time, Leo can be used in *all* situations without compromise.  There is no longer any need to make excuses for sentinel lines, or argue whether people should accept them.  Sentinels are simply gone.
</t>
<t tx="ekr.20150312013449.4">Leo 5.0 (November 24, 2014): Leo now stores "ephemeral" or position-related data *in vnodes*. This was a completely new idea in Leo's history!
</t>
<t tx="ekr.20150312080344.12">Leo's Gui code is built on wrapper and widget classes. A **widget** is an actual Qt widget. A **wrapper** is an object whose API hides the details of the underlying gui **text** widgets. Leo's core code usually uses wrappers, not raw widgets.

There is a back door for special cases. All wrapper classes define an official ``widget`` ivar (instance variable), so core or plugin code can gain access to the real Qt widget using ``wrapper.widget``. Searching for ``wrapper.widget`` should find all gui-dependent snippets of code in Leo's core.

Wrappers allow the same text-handling code to work regardless of whether the actual text widgets are a QTextBrowser or a QsciScintilla object. Without wrappers, all of Leo's text-editing commands would have to know the details of the api of the actual Qt text widget!
</t>
<t tx="ekr.20150312080344.14">Various vim commands advertise, just by having a tab_callback method, that they want to handle a tab that follows their name. ga.do_tab then defers to the vim command. Vim's tab handler no longer knows *anything* about colon commands, or what any command intends to do with the tab. If the command handler has a tab_callback attribute, vim's tab handler just calls it.

Here is the flattened form of the class that handles the :tabnew command. Note that the __call__ and tab_callback methods are trivial:

.. code-block:: python

    class Tabnew:
        '''
        A class to handle Vim's :tabnew command.
        This class supports the do_tab callback.
        '''
        def __init__(self,vc):
            '''Ctor for VimCommands.tabnew class.'''
            self.vc = vc
        __name__ = ':tabnew'
            # Required.

        def __call__(self,event=None):
            '''Prompt for a file name, the open a new Leo tab.'''
            self.vc.c.k.getFileName(event,callback=self.open_file_by_name)

        def tab_callback(self):
            '''Called when the user types :tabnew&lt;tab&gt;'''
            self.vc.c.k.getFileName(event=None,callback=self.open_file_by_name)

        def open_file_by_name(self,fn):
            c = self.vc.c
            if fn and not g.os_path_isdir(fn):
                c2 = g.openWithFileName(fn,old_c=c)
                try:
                    g.app.gui.runAtIdle(c2.treeWantsFocusNow)
                except Exception:
                    pass
            else:
                c.new()

This pattern is particularly well suited to Leo, because the various getPublicCommands methods reference those functions in their command dictionaries. Here, the new entries are::

    ':r':       vc.LoadFileAtCursor(vc),
    ':tabnew':  vc.Tabnew(vc),
</t>
<t tx="ekr.20150312080344.20">The leo/plugins/importers folders now contains importer plugins.

The leo/plugins/writers folders now contain writer plugins.

Both importer and writer plugins can defined new kinds of @auto nodes.

Importers and writers can register either @auto-names or file extensions. For example, @auto x.xyzzy will use both the importer and the writer for the .xyzzy extension, that is, importers/test.py and writers/test.py. So, for *unique* extensions, there is no need to use a separate @auto name, you can just use @auto.</t>
<t tx="ekr.20150312080344.31">::

    Leo 5.0 final released November 24, 2014

    Better compatibility with vim, Emacs, pylint and PyQt:

        Optional native emulation of vim commands
        Full support for Emacs org-mode outlines
        Better support for pylint
        Support for both PyQt4 and PyQt5

    Better handling of nodes containing large text:

        Idle time syntax coloring eliminates delay
        Optional delayed loading of large text

    Power features:

        File name completion
        Cloned nodes expand and contract independently
        @data nodes can be composed from descendant nodes
        Leo's main style sheet can be customized with @color and @font settings
        @persistence nodes save data in @auto trees
        Leo now uses pluggable architecture for @auto nodes
        &lt;Alt-X&gt;&lt;tab&gt; shows all commands
        Leo's beautify commands now uses PythonTidy by default

    New plugins for tagging, display and node evaluation

    Leo's default workbook files contains Leo's quickstart guide
</t>
<t tx="ekr.20150312080344.32">::

    Leo 4.11 final released November 6, 2013
    Leo's tutorials have been rewritten and simplified
    Greatly improved abbreviations, including templates
    Clones are now valid anywhere in @file nodes
    Leo now warns if a .leo file is open elsewhere
    Leo's IPython bridge now works with IPython 1.x
    Added support for @testsetup and @testclass
    Added support for sessions
    Added colorizing themes
    A colored border highlights the pane with focus
    Added support for the clojure, markdown and TypeScript languages
    Added importers for .ipynb, .otl and vimoutliner files
</t>
<t tx="ekr.20150312080344.33">::

    Leo 5.1 b2 released April 10, 2015.
    @clean outlines create external files without sentinels.
    Leo regularly checks the integrity of the outline.
    Up/Down arrows in the minibuffer cycle though command history.
    load-leo.html displays .leo files in the browser.
    Leo now honors @language inside @doc parts.
    @data nodes can now be composed from a tree of nodes.
        This feature appeared in Leo 5.0, but was not documented.
    Added @int qt-cursor-width setting.
    Added g.IdleTime &amp; LeoQtGui.IdleTime.
</t>
<t tx="ekr.20150312080344.34">::

    4.4 final released May 11, 2006
    An Emacs-like mini-buffer
    Many new commands
    You can use Leo without using a mouse
    Flexible key bindings and input modes
    A tabbed log pane
    Autocompletion and calltips</t>
<t tx="ekr.20150312080344.35">::

    Leo 4.4.1 final released August 30, 2006
    Multiple editors in Leo's body pane
    A new colorizer plugin controlled by jEdit language description files
    Search commands now support regex replace patterns
    Support for external debuggers: https://leo-editor.github.io/leo-editor/debuggers.html
</t>
<t tx="ekr.20150312080344.36">::

    Leo 4.4.3 final released June 26, 2006
    The **big reorg** removed all gui-dependent code from Leo's core
    Added chapters
    Added zipped .leo files
    Added leoBridge module
    Better support for the winpdb debugger
    Added @enabled-plugins and @openwith nodes
    Added __wx_gui.py
</t>
<t tx="ekr.20150312080344.37">::

    Leo 4.4.4 Final released November 2, 2007
    The Great Graph Aha.  See the History of Leo
    @auto
    @menus trees
    @buttons trees
    A faster colorizer plugin
</t>
<t tx="ekr.20150312080344.45">::

    Leo 4.4.5 final released December 11, 2007
    Leo now recognizes directives in headlines
</t>
<t tx="ekr.20150312080344.46">::

    Leo 4.4.6 final released January 26, 2008
    Added @data nodes
    Added @auto importers for javascript and xml files
    Added find-next-clone and toggle-sparse-move commands
</t>
<t tx="ekr.20150312080344.47"></t>
<t tx="ekr.20150312080344.48">::

    Leo 4.4.7 final released February 18, 2008
    The IPython bridge (ipython plugin)
</t>
<t tx="ekr.20150312080344.50">::

    Leo 4.4.8 final released April 6, 2008
    Host Leo's sources on bzr
    Began using Google groups
    Translate arguments to g.es and g.es_print with gettext
    Completed ILeo: a bridge between IPython and Leo
    Common @commands nodes in settings files
</t>
<t tx="ekr.20150312080344.52">::

    Leo 4.6 final released July 15, 2009
    Cached external files
    Automatic syntax checking of .py files
    The Qt gui is now the default
    @auto-rst
    Added p.b, p.h and p.gnx; v.b, v.h and v.gnx properties
    Tab and Shift-Tab indent &amp; unindent text
</t>
<t tx="ekr.20150312080344.53">::

    New --config, --file and --gui command-line options
    The open command creates @edit nodes when opening non-.leo files
    Leo opens a workbook if no file is given
    Predefined 'self' in @test/@suite nodes
    Escapes for underindented lines
    Improved Leo's unit testing framework
    New warnings for dangerous writes to @auto and @file nodes
    @nocolor-node directive
    qtGui and tkGui plugins
</t>
<t tx="ekr.20150312080344.55">::

    Leo 4.7 final released February 23, 2010
    The one-node world
    Leo now works with Python 3 &amp; requires Python 2.6+
    'Recovered Nodes' nodes guard against clone conflicts
</t>
<t tx="ekr.20150312080344.56">::

    Leo 4.8 final released November 26, 2010
    New-style sentinels
    Drag and drop
    Improved abbreviations
    Spell checking based on PyEnchant
    Leo creates "Resurrected Nodes"
</t>
<t tx="ekr.20150312080344.57">::

    Leo can open multiple files from the command line
    Added an .ini importer
    Added support for .nsi files
    New screenshots plugin
</t>
<t tx="ekr.20150312080344.58">::

    code-to-rst
    cascade-windows
    minimize-all-windows
    head-to-prev-node
    tail-to-next-node
    extract-python-method
</t>
<t tx="ekr.20150312080344.59">::

    Leo 4.9 final released June 21, 2011
    The Qt gui completely replaces Tk gui
    Nodes may contain multiple @language directives
    Unified extract and import commands
    Greatly improved the autocompleter
    The rendering pane displays movies, html, svg images, etc.</t>
<t tx="ekr.20150312080344.60">::

    Added --no-splash, --script and --silent command-line options
    Leo highlights URL's everywhere
    Ctrl-clicking a URL's opens them in the browser
    Leo uses an @file node's extension if there is no @language directive
    Plain up/down arrow keys in headline-editing mode select a new node
    Added namespace directive to .leo files
    Added cython colorizing
</t>
<t tx="ekr.20150312080344.61">::

    Commands now have common prefixes:

        abbrev-     abbreviation commands
        apropos-    help
        buffer-     buffer command
        ddabrev-    dynamic abbreviations
        directory-  director commands
        file-       file commands
        find-       find commands
        gc-         garbage collection
        isearch-    incremental search
        print-      print information
        rectangle-  rectangle commands
        register    register commands
        run-        run unit tests
        toggle-     toggle settings
        yank-       yank

    The import-file commands replaces all the following commands:

        import-at-file                    
        import-cweb-files         
        import-derived-file       
        import-flattened-outline      
        import-noweb-files

    Commands related to uA's:

        clear-all-uas
        clear-node-uas
        show-all-uas
        show-node-uas
        set-ua

    Other commands:

        insert-hard-tab
        insert-soft-tab
        replace-current-character command
        save-all
        toggle-abbrev-mode
        toggle-case-region
</t>
<t tx="ekr.20150312080344.63">::

    Leo 4.10 final released March 29, 2012
    Detached windows
    Major improvements to Leo's abbreviations
</t>
<t tx="ekr.20150312080344.65">::

    beautify-c
    c-to-python
    clone-find-all-flattened
    clone-marked-nodes
    delete-marked-nodes
    move-marked-nodes
    run-marked-unit-tests-externally
    run-marked-unit-tests-locally
    select-to-matching-bracket
    split-defs
</t>
<t tx="ekr.20150312080344.66">::

    EditCommandsManager
    KeyStroke &amp; ShortcutInfo
    LoadManager
    TestManager
</t>
<t tx="ekr.20150312080344.67"></t>
<t tx="ekr.20150312080344.68">##############
History of Leo
##############

This chapter discusses the most important milestones in history of Leo and summarizes each of Leo's public releases.  The focus is on the *important* and *interesting* developments.  It is not a chronicle of every change made to Leo.

One of Leo's most important developments, ``@button``, came directly from e's ``dyna_menu`` plugin. The exact date seems lost, but it certainly existed by Leo 4.3.

.. contents:: Contents
    :depth: 2
    :local:

</t>
<t tx="ekr.20150313192232.12">@language python
'''
Print all command names from headlines in Docstrings outline not appearing in
Commands Reference.

This script assumes the following outline structure::

    - This script
        - Docstrings (a tree produced by "Print commands &amp; docstrings" script).
    - Commands Reference
'''
g.cls()
ref = p.next()
assert ref.h == 'Commands Reference'
found, not_found = [],[]
child = p.firstChild()
for group in child.children():
    for p in group.children():
        target = p.h
        # print(target)
        for p2 in ref.subtree():
            s = p2.b
            if s.find(target) &gt; -1:
                found.append(target)
                break
        else:
            not_found.append(target)
if 0:
    print('===== %s Found =====' % len(found))
    for z in sorted(found):
        print(z)
if 1:
    print('===== %s Not Found =====' % len(not_found))
    for z in sorted(not_found):
        print(z)
print('found: %s not found: %s' % (len(found),len(not_found)))</t>
<t tx="ekr.20150314044011.7">@language python
# From Script: clean ekr-spellpyx.txt
p.b = ''.join(sorted(set(g.splitLines(p.b.rstrip()+'\n'))))</t>
<t tx="ekr.20150315132217.3">Here's how to switch focus without using the mouse:

``Alt-0 (vr-toggle)``
    Hides or shows the viewrendered pane.
``Alt-T (focus-to-tree)``
    Puts focus in the outline pane, regardless of focus.
``Ctrl-T (toggle-active-pane)``
    Toggles focus between the outline and body panes.
``Ctrl-Tab (tab-cycle-next)``
    Switches between outline tabs. You may open multiple Leo outlines in different tabs within the same main window.
``Ctrl-G (keyboard-quit)``
    Puts focus in the body pane. More effective than hitting Alt-Tab twice.</t>
<t tx="ekr.20150318043636.14">The following script imports files from a given directory and all subdirectories:

.. code-block:: python

    c.recursiveImport(
        dir_ = 'path to file or directory',
        kind = '@clean',        # or '@file' or '@auto'
        one_file = False,       # True: import only one file.
        safe_at_file = False,   # True: generate @@clean nodes.
        theTypes = None,        # Same as ['.py']
    )
</t>
<t tx="ekr.20150318043636.16"></t>
<t tx="ekr.20150318043636.17"></t>
<t tx="ekr.20150318110552.10">.. contents:: Contents
    :depth: 3
    :local:

</t>
<t tx="ekr.20150318110552.18">.. contents:: Contents
    :depth: 2
    :local:</t>
<t tx="ekr.20150318110552.20">Leo supports unlimited undo and redo with the ``undo`` (Ctrl-Z) and ``redo`` (Ctrl-Shift-Z) commands. Think of actions that may be undone or redone as a string of beads. A "bead pointer" points to the present bead. Performing an operation creates a new bead after the present bead and removes all following beads. Undoing an operation moves the bead pointer backwards; redoing an operation moves the bead pointer forwards. The ``undo`` command is disabled when the bead pointer moves in front of the first bead; the ``redo`` command is disabled when the bead pointer points to the last bead.

The ``@string undo_granularity`` setting controls the granularity of undo. There are four possible values:

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

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

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

``char`` (not recommended)
    Starts a new undo unit for each character typed.
    This wastes lots of computer memory.
</t>
<t tx="ekr.20150318110552.21">``cut-text (Ctrl-X)``
    Cut the selected text and put it to the clipboard.
``copy-text (Ctrl-C)``
    Copy the selected text to the clipboard.
``paste-text (Ctrl-V)``
    Paste test from the clipboard.
``select-all(Ctrl-A)``
    Select all text in the text pane.

These commands work with either headline or body text.</t>
<t tx="ekr.20150318110552.22">``always-indent-region``
     Shift selected lines right one tab position. Inserts one unit of indentation if no text is selected.
``indent-region (Tab)`` 
    Shift selected lines right one tab position. Inserts a tab (or spaces) if no text is selected.
``unindent-region (Shift-Tab)``
    Shifts selected lines left one tab position. Deletes one unit of indentation if no text is selected.

**Notes**:

- These commands shift the entire line if any characters in that line are selected. If no text is selected.

- The ``@tabwidth`` directive determines which characters these commands insert or delete.

- Leo auto indents unless ``@nocolor`` is in effect.  Typing a newline automatically inserts the same leading whitespace present on the previous line.

- If Python is the present language, Leo inserts an additional tab if the previous line ends with a colon.  When the ``smart_auto_indent setting`` is True, Leo uses Emacs-style auto-indentation instead.  This style of auto-indent aligns newly created lines with unmatched ``( [{`` brackets in the previous line.
</t>
<t tx="ekr.20150318110552.23">``add-comments (Ctrl-))``
    Adds comments to the selected lines, according to the ``@language``
    directive in effect. These commands use single-line comments if
    possible. It's not necessary to select all of the first or last lines.
``delete-comments (Ctrl-()``
    Deletes comments in the selected lines.
</t>
<t tx="ekr.20150318110552.24">.. _`Python's time module`: https://docs.python.org/3/library/time.html

``clean-lines``
    Removes trailing whitespace from all lines, preserving newlines.
``clear-selected-text``
    Delete the selected text.
``convert-tabs``
    Converts leading tabs to blanks in a single node.
``convert-blanks``
    Converts blanks to tabs in a single node.
``convert-all-tabs``
    Converts leading tabs to blanks throughout the selected tree.
``convert-all-blanks``
    Converts leading blanks to tabs throughout the selected tree.

**@tabwidth**: The ``convert-*`` commands convert between tabs and blanks using the ``@tabwidth`` setting presently in effect.

``insert-body-time`` and ``insert-headline-time``
    Insert formatted time and date into body or headline text. You must be editing a headline to be able to insert the time/date into the headline. The body_time_format_string and headline_time_format_string settings specify the format of the inserted text. These settings are the format string passed to time.strftime.

**Time format**: For format options see `Python's time module`_. By default, the commands use ``%m/%d/%Y %H:%M:%S``, giving timestamps like ``1/30/2003 8:31:55``.

``pretty-print-python-code`` and ``pretty-print-all-python-code``
    Pretty prints body text. You can customize this code by overriding the following methods of class prettyPrinter in leoCommands.py::

        putOperator:      puts whitespace around operators.
        putNormalToken:   puts whitespace around everything else.

``reformat-paragraph (Ctrl-Shift-P)``
    Rearranges the words in a text paragraph to fill each line as full as possible, up to the ``@pagewidth`` setting. A paragraph is delimited by blank lines, Leo directives, and (of course) start and end of text in a node. The width of the line used by the reformatting operation is governed by ``@pagewidth`` and the indentation that would be applied to the node when Leo writes the file.

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

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

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

  2. This is the second paragraph,
     and it too has a hanging indentation.

``replace-current-character``
     Replace the selected character with the next character typed.
``toggle-angle-brackets``
    Adds or removes double angle brackets from the headline of the selected node.
``unformat-paragraph (Ctrl-Shift-U)``
    Removes all extra whitespace from a paragraph, including leading whitespace.  This command is useful when ``@wrap`` is in effect.
</t>
<t tx="ekr.20150318110552.25">``extract (Ctrl-Shift-D)``
    Creates a new node whose headline is the first line of selected body text and whose body is all other lines of selected text. Previously selected text is deleted from the original body text.
``extract-names (Ctrl-Shift-N)``
    Creates one or more child nodes, one for each section name in the selected body text. The headline of each created node is the section name.
``line-to-headline``
    Creates a new node whose headline is the selected body line.</t>
<t tx="ekr.20150318110552.26">``execute-script (Ctrl-B)``
    Executes body text as a Python script. Leo execute the selected text, or the entire body text if no text is selected. The Execute Script command pre-defines the values c, g and p as follows:

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

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

Leo preprocesses all scripts by simulating the writing of a external file to a string. The ``execute-script`` command sets app.scriptDict["script1"] to the value of the script before preprocessing, and sets app.scriptDict["script2"] to the value of the script after preprocessing. Scripts may examine and change app.scriptDict as they please.
</t>
<t tx="ekr.20150318110552.29">.. contents:: Contents
    :depth: 2
    :local:</t>
<t tx="ekr.20150318110552.30">``file-open-by-name``
    Gets the name of a Leo outline from the minibuffer and opens it. File name completion is supported.
``new (Ctrl-N)``
    Creates a new Leo main window.
``open-outline (Ctrl-O)``
    Opens an existing .leo file. Selecting a non-.leo file loads the file into an ``@edit`` node in the present outline.
``open-outline-by-name``
    Opens the file given by typing the filename in the minibuffer. Supports filename completion.
``read-outline-only``
    Reads only the .leo file, not any external files.
``revert``
    Reloads the outline, discarding any changes made since it was last saved.
``save-all``
    Saves all open tabs windows/tabs. 
``save-buffers-kill-leo``
    Quits Leo, prompting to save any unsaved files first. 
``save-file or file-save (Ctrl-S)``
    Saves the Leo window to a file.
``save-file-as``
    Saves the Leo outline, changing outline's file name.
``save-file-to``
    Saves a copy of the Leo outline, changing outline's file name.

**Opening specific files**:

``open-cheat-sheet-leo``
    Opens CheatSheet.leo in a new tab or window.
``open-leoDocs-leo``
    Opens LeoDocs.leo in a new tab or window.
``open-scripts-leo``
    Opens scripts.leo in a new tab or window.
``open-leoSettings-leo``
    Opens ``leoSettings.leo`` in a new tab or window.

**Writing external files without saving the outline**:

``write-at-auto-nodes``
    Writes all ``@auto`` nodes in the selected tree.
``write-outline-only``
    Saves the outline without writing any @&lt;file&gt; trees.
``write-at-file-nodes``
    Writes all @&lt;file&gt; trees.
``write-at-shadow-nodes``
    Writes all ``@shadow`` nodes in the selected tree.
``write-dirty-at-file-nodes``
    Writes all modified @&lt;file&gt; trees.
``write-dirty-at-shadow-nodes``
    Writes all modified ``@shadow`` trees.
``write-missing-at-file-nodes``
    Write all @&lt;file&gt; nodes for which the corresponding external file does not exist.
</t>
<t tx="ekr.20150318110552.31">``close-others``
    Closes all windows except the present window.
``close-window (Ctrl-F4)``
    Closes the selected Leo window, prompting you to save your work if necessary.
``exit-leo (Ctrl-Q or Alt-F4)``
    Exits Leo, prompting you to save any changed outline. Closing the last outline tab also exits Leo.
</t>
<t tx="ekr.20150318110552.32">.. _CWEB:   https://www-cs-faculty.stanford.edu/~knuth/cweb.html
.. _noweb:  https://www.cs.tufts.edu/~nr/noweb/

``export-headlines``
    Exports all headlines to an external file.
``export-html-outline-viewer``
    Exports the Leo outline as a self-contained HTML interactive outline viewer. This command requires the "leo_to_html_outline_viewer.py" plugin to be active.
``file-insert``
    Prompts for the name of a file and put the selected text into it.
``flatten-outline``
    Creates a text file in MORE format from the selected outline.
``import-file``
    Import a file into an ``@file`` node. This command handles files regardless of whether they contain sentinels. This command can also read files in MORE outline format.
``import-MORE-file``
    Import one or MORE files into ``@file`` nodes.
``import-tabbed-files``
    Import one or more tab-or-space-delimited files into ``@file`` nodes.
``import-zim-folder``
    Imports a zim folder, https://zim-wiki.org/, as the last top-level node of the outline. This command uses the following Leo settings::

        @int rst_level = 0
        @string rst_type
        @string zim_node_name
        @string path_to_zim

``outline-to-cweb``
    Creates a `CWEB`_ file from the selected outline.
``outline-to-noweb``
    Creates a `noweb`_ file from the selected outline.
``read-at-auto-nodes``
    Reads all ``@auto`` nodes in the presently selected outline. 
``read-at-shadow-nodes``
    Reads all ``@shadow`` nodes in the presently selected outline.
``read-at-file-nodes``
    Updates all @&lt;file&gt; nodes in an outline.
``read-file-into-node``
    Prompts for a filename, creates a new node and puts the contents of the file into its body text.
``refresh-from-disk``
    Refreshes an @&lt;file&gt; node from disk. 
``remove-sentinels``
    Removes all sentinel lines from a file derived from an ``@file`` node.
``weave``
    Formats the selected text and writes it to a file. 
``write-file-from-node``
    Writes the body text of the selected node to a file. The command prompts for a file name if the node is not an @&lt;file&gt; node.
</t>
<t tx="ekr.20150318110552.33">``session-clear``
    Closes all tabs except the presently selected tab. 
``session-create``
    Creates a new ``@session`` node. 
``session-refresh``
    Refreshes the current ``@session`` node. 
``session-restore``
    Opens a tab for each item the selected ``@session`` node.
``session-snapshot-load``
    Loads a snapshot of a session from the leo.session file. 
``session-snapshot-save``
    Saves a snapshot of the present session to the leo.session file.

A **session** specifies a list of .leo files that Leo opens automatically when Leo first starts.  Leo will reload the last session provided that command-line arguments *don't* contain any file names.
</t>
<t tx="ekr.20150318110552.34">.. _`Idle`: https://en.wikipedia.org/wiki/IDLE_%28Python%29
.. _`Open Office`: https://www.openoffice.org/
.. _`SciTe`: https://www.scintilla.org/SciTE.html

``cm-external-editor``
    Open the selected node in the external editor specified by the ``LEO_EDITOR/EDITOR`` environment variable.
``open-with-idle``
    Open the selected node in `Idle`_.
``open-with-open office``
    Open the selected node in `Open Office`_.
``open-with-scite``
    Open the selected node in `SciTe`_.
``open-with-word``
    Open the selected node in Word.

**About open-with**:

1. Leo creates a temporary file and invokes an external program. Leo periodically checks whether this temporary file has changed; Leo changes the corresponding node in the outline if so. You must create the entries using an ``@openwith`` node in ``myLeoSettings.leo``. See the documentation there.

2. All ``open-with`` commands require that the corresponding ``@openwith`` node correctly specifies an editor.</t>
<t tx="ekr.20150318110552.35">``directory-make``
    Prompts for the name of a directory and creates it.
``directory-remove``
    Prompts for the name of a directory and deletes it.
``file-delete``
    Prompts for the name of a file and delete it. 
</t>
<t tx="ekr.20150318110552.36">``clean-recent-files``
    Removes duplicate entries from entries in the Recent Files menu.
``clear-recent-files``
    Deletes all entries in the Recent Files except the most recent file. The files themselves are not affected.
``sort-recent-files``
    Sorts the recent files list in the File menu.
</t>
<t tx="ekr.20150318110552.37">``about-leo``
    Puts up a dialog box showing the version of Leo.
``help``
    Shows an introduction to Leo's help system.
``help-for-command (F11)``
    Prompts for a Leo command name in the minibuffer (tab completion is allowed) and shows the docstring for the command.
``help-for-python (F12)``
    Prompts for a Python module or function and shows its docstring.
``help-for-&lt;topic&gt;``
    Opens a discussion of a topic::

        help-for-abbreviations
        help-for-autocompletion
        help-for-bindings
        help-for-creating-external-files    
        help-for-debugging-commands
        help-for-drag-and-drop
        help-for-dynamic-abbreviations
        help-for-find-commands
        help-for-minibuffer
        help-for-regular-expressions
        help-for-scripting

``open-online-home``
    Opens Leo's home page at https://leo-editor.github.io/leo-editor/.
``open-online-toc``
    Opens Leo's table of contents at https://leo-editor.github.io/leo-editor/leo_toc.html.
``open-online-tutorials``
    Opens Leo's tutorials page at https://leo-editor.github.io/leo-editor/tutorial.html.
``open-online-videos``
    Opens Leo's video page at https://leo-editor.github.io/leo-editor/screencasts.html.
``open-quickstart-leo``
    Opens Leo's quickstart guide in a new tab or window.
``open-users-guide``
    Opens Leo's Users Guide at https://leo-editor.github.io/leo-editor/usersguide.html.


</t>
<t tx="ekr.20150318110552.38">``full-command (Alt-X)``
    Execute a command by name. Tab completion is supported.
``keyboard-quit``
    Exits the minibuffer, putting focus in the body pane.
``repeat-complex-command``
    Execute the last command entered from the minibuffer.

</t>
<t tx="ekr.20150318110552.39">.. contents:: Contents
    :depth: 2
    :local:</t>
<t tx="ekr.20150318110552.40">The following commands trigger event hooks::

    click-click-box
    click-headline
    click-icon-box
    ctrl-click-at-cursor
    ctrl-click-icon    
    double-click-headline
    double-click-icon-box # Invokes vim or xemacs plugin if enabled.
    simulate-begin-drag
    simulate-end-drag
</t>
<t tx="ekr.20150318110552.41">::

    activate-cmds-menu
    activate-edit-menu
    activate-file-menu
    activate-help-menu
    activate-outline-menu
    activate-plugins-menu
    activate-window-menu
    cycle-focus
    cycle-log-focus
    focus-to-body
    focus-to-find
    focus-to-log
    focus-to-minibuffer
    focus-to-nav
    focus-to-tree
    gui-all-hide
    gui-all-show
    gui-all-toggle
    gui-iconbar-hide
    gui-iconbar-show
    gui-iconbar-toggle
    gui-menu-hide
    gui-menu-show
    gui-menu-toggle
    gui-minibuffer-hide
    gui-minibuffer-show
    gui-minibuffer-toggle
    gui-statusbar-hide
    gui-statusbar-show
    gui-statusbar-toggle
    gui-tabbar-hide
    gui-tabbar-show
    gui-tabbar-toggle
    tab-cycle-next
    tab-cycle-previous
    toggle-active-pane
</t>
<t tx="ekr.20150318110552.42">::

    contract-body-pane
    contract-log-pane
    contract-outline-pane
    contract-pane
    delete-script-button-button
    detach-editor-toggle
    detach-editor-toggle-max
    equal-sized-panes
    expand-body-pane
    expand-log-pane
    expand-outline-pane
    expand-pane
    fully-expand-body-pane
    fully-expand-log-pane
    fully-expand-outline-pane
    fully-expand-pane
    hide-body-pane
    hide-log-pane
    hide-outline-pane
    hide-pane
    iconify-frame 
    resize-to-screen
    tab-detach
</t>
<t tx="ekr.20150318110552.43">.. contents:: Contents
    :depth: 2
    :local:</t>
<t tx="ekr.20150318110552.44">``clone-node (Ctrl-\`)`` (Grave accent, not a single quote)
    Creates a clone as the immediate sibling of a selected node.
``clone-node-to-last-node``
    Creates a clone as the last top-level node of the outline.
``insert-node (Ctrl-I or Insert)``
    Inserts a new node into the outline.  The new node becomes the first child of the present node if the present node is expanded.  Otherwise, the new node becomes the next sibling of the present node.
``insert-node-before``
    Inserts a node before the presently selected node.
``delete-node``
    Deletes a node and all its descendants.
</t>
<t tx="ekr.20150318110552.45">``contract-all (Alt-hyphen)``
    Contracts every node in the outline.
``contract-all-other-nodes``
    Contract all nodes except the parents of the selected node.
``contract-node``
    Contracts a node.
``contract-or-go-left (Alt-Left)``
    Contract the node if it is expanded.  Otherwise, select the node's parent.
``contract-parent``
    Select the parent of the selected node and contract it.
``expand-all``
    Expands every node in the outline.
``expand-node``
    Expands a node.
``expand-and-go-right (Alt-Right)``
    Expands a node if not expanded.  Otherwise, selects the first child if there is one.
``expand-all-subheads``
    Expand all the direct children of the selected node.
``expand-ancestors-only``
    Expand all the ancestors of the selected node.

These commands expand all descendants of the selected nodes::

    expand-next-level
    expand-prev-level (reverses expand-next-level)
    expand-to-level-1
    expand-to-level-2
    expand-to-level-3
    expand-to-level-4
    expand-to-level-5
    expand-to-level-6
    expand-to-level-7
    expand-to-level-8
    expand-to-level-9
</t>
<t tx="ekr.20150318110552.46">``abort-edit-headline``
    Ends editing of the headline, discarding any changes.
``edit-headline``
    Begins editing of the headline of the presently-selected node.
``end-edit-headline``
    Ends editing of the headline.
</t>
<t tx="ekr.20150318110552.47">**Arrow keys**: When focus is in the outline pane, you can move about the outline using *plain* arrow keys. Regardless of focus, Alt-Arrow keys select nodes in the outline pane.

``goto-first-sibling``
    Select the first sibling of the selected node.
``goto-last-sibling``
    Select the last sibling of the selected node.

Similarly, these commands select various nodes in the outline::

    go-back
    go-forward
    goto-char
    goto-first-node
    goto-first-visible-node
    goto-last-node
    goto-last-visible-node
    goto-line
    goto-next-changed
    goto-next-clone
    goto-next-history-node
    goto-next-node
    goto-next-sibling
    goto-next-visible
    goto-parent
    goto-prev-history-node
    goto-prev-node
    goto-prev-sibling
    goto-prev-visible

``leoscreen-jump-to-error`` (Unix only)
    Jumps to the python error reported in the shell window, if the
    file's loaded in the current Leo session. Just looks for a line::

        File "somefile.py", line NNN, in xxx

    and looks for a node starting with "@" and ending with "somefile.py",
    then jumps to line NNN in that file.
</t>
<t tx="ekr.20150318110552.48">``copy-node (Ctrl-Shift-C)``
    Copies a node and all its descendants to the clipboard
``cut-node (Ctrl-Shift-X)``
    Copies a node and all its descendants to the clipboard and then delete them.
``delete-node``
    Deletes a node and all its descendants.
``paste-node (Ctrl-Shift-V)``
    Pastes a node and its descendants from the outline. This commands creates *copies* of nodes, not clones.
``past-retaining-clones``
    Pastes a node and its descendants from the outline.  This command preserves the identify (gnx's) of the pasted nodes, thereby preserving any clone links. This command ensures that no newly-pasted node is an ancestor of itself.

**Outline representation**: When cutting or copying an outline to the clipboard, Leo writes the outline in the same xml (text) format used in .leo files. You may copy this text representation into a body pane (or into any other text editor) using ``Ctrl-V``.
</t>
<t tx="ekr.20150318110552.49">``move-outline-down (Ctrl-D or Shift-Down or Alt-Shift-Down)``
    Move the selected node down, if possible.
``move-outline-left (Ctrl-L or Shift-Left or Alt-Shift-Left)``
    Move the selected node left, if possible.
``move-outline-right (Ctrl-R or Shift-Right or Alt-Shift-Right)`` 
    Move the selected node right, if possible.
``move-outline-up (Ctrl-U or Shift-Up Alt-Shift-Up)``
    Move the selected node up, if possible.

**Alt Modifiers not needed in the outline pane**: When focus is in the outline pane, you can move nodes without adding the Alt modifier. Shift-Up moves the select node up, etc.

**Important**: The following commands reorganize groups of nodes:

``de-hoist``
    Undoes the effect of the previous ``hoist`` command.
``demote (Ctrl-])``
    Makes all following siblings of a node children of the node.
``hoist``
    Redraws the screen so presently selected tree becomes the only visible part of the outline. You may hoist an outline as many times as you wish.
``promote (Ctrl-[)``
    Makes all the children of a node siblings of the node.
``sort-children``
    Sort all children of the children of the present node by their headlines.
``sort-siblings (Alt-A)``
    Sort the present node and all its siblings by their headlines.
</t>
<t tx="ekr.20150318110552.50">``code-to-rst``
    Format the presently selected node as computer code.
``flatten-outline-to-node``
    Appends the headline and body text of all descendants of the selected node to the body text of the selected node.
``parse-body``
    Parse p.b as source code, creating a tree of descendant nodes.
    This is essentially an import of p.b.
</t>
<t tx="ekr.20150318110552.51">You may drag a node (including all its descendants) from one place to another in an outline. To start a drag, press the main (left) mouse button while the cursor is over the icon for a node. The cursor will change to a hand icon. If you release the mouse button while the hand cursor is above another node, Leo will move the dragged node after that node. If you release the mouse button when the hand cursor is not over a node, Leo will leave the outline pane as it is. Leo scrolls the outline pane as the result of mouse-moved events, so to continue scrolling you must keep moving the mouse.

If the recipient node has children and is expanded, the dropped node will be inserted as the first child of the recipient node, otherwise the dropped node will be inserted after the recipient node.

Holding down Alt before releasing the node will force insertion as a child of the recipient node, even if the recipient node is not expanded. Holding down Control before releasing the node will cause a clone to be dropped, leaving the original where it was.
</t>
<t tx="ekr.20150318110552.52">``copy-marked``
    Copies all marked nodes as children of a new node. 
``diff-marked-nodes``
    When exactly two nodes are marked, this command creates a diff node as the last top-level node whose children are clones of the marked nodes.
``goto-next-marked``
    Selects the next marked node.
``mark (Ctrl-M)``
    Marks node if it is unmarked, and unmarks the node if it is already marked.
``mark-changed-items``
    Marks all nodes whose headline or body text has been changed since the file was last saved.
``mark-subheads``
    Marks all children of the presently selected node.
``marked-list``
    Lists all marked nodes in the Nav pane.
``unmark-all``
    Unmarks all marked nodes in the outline.

**Marking groups of nodes**: Leo's find and change commands mark nodes if the "Mark Changes" and "Mark Finds" checkboxes are checked. You can change these checkboxes with the ``toggle-find-mark-changes-option`` and ``toggle-find-mark-finds-option`` commands.
</t>
<t tx="ekr.20150318110552.53">``clone-marked-nodes``
    Makes clones of all marked nodes and moves them to be children of the present position.
``delete-marked-nodes``
    Deletes all marked nodes.
``move-marked-nodes``
    Moves all nodes to be children of the present position.
</t>
<t tx="ekr.20150318110552.54">``file-compare-leo-files``
    Prompts for another (presumably similar) .leo file that will be compared with the presently selected outline file (main window). It then creates clones of all inserted, deleted and changed nodes.
``file-diff-files``
    Creates a node and puts the diff between 2 files into it. 
</t>
<t tx="ekr.20150318110552.55">@chapter trees define chapters. Selecting a chapter makes only those nodes in the chapter visible, much like a hoist. The ``main`` chapter represents the entire outline. Selecting the ``main`` chapter shows all outline nodes.

``chapter-select-main``
    Selects the main chapter.

``chapter-select-&lt;chapter-name&gt;``
    Each ``@chapter`` node in the outline creates a corresponding ``chapter-select`` command.

``chapter-next``
    Selects the next chapter.

``chapter-back``
    Selects the previous chapter.

Associated settings:

``@bool use_chapters``
    True: chapters are enabled.

..  ``@bool use_chapter_tabs``
..    True: chapters pop-up menu appears in the icon area.
</t>
<t tx="ekr.20150318110552.56">::

    scroll-down
    scroll-down-extend-selection
    scroll-up
    scroll-up-extend-selection

    scroll-down-half-page
    scroll-down-line
    scroll-down-page
    scroll-up-half-page
    scroll-up-line
    scroll-up-page

    scroll-outline-down-line       
    scroll-outline-down-page       
    scroll-outline-up-line       
    scroll-outline-up-page
    scroll-outline-left
    scroll-outline-right

</t>
<t tx="ekr.20150318110552.57">.. contents:: Contents
    :depth: 2
    :local:</t>
<t tx="ekr.20150318110552.59">Basic searches:

``start-search (Ctrl-F)``
    Prompts for a search string. Typing the ``Return`` key puts the search string in the Find tab and executes a search based on all the settings in the Find tab. Type ``Tab`` to enter replacement text.
``find-next (F3)``
    Continues a search started with ``Ctrl-F``.
``find-previous (F2)``
    Searches backwards using the present search options.
``replace (Ctrl-=)``
    Replaces the selected text with the 'change' text in the Find tab.
``replace-then-find (Ctrl--)``
    Replaces the selected text with the 'change' text in the Find tab, then executes the find command again.

Batch searches:

``find-all``
    Prints all matches in the log pane.
``replace-all``
    Changes all occurrences of the 'find' text with the 'change' text.
    When using the minibuffer to specify search and replace patterns,
    first enter then search pattern,
    then type ``Tab`` and enter the replacement pattern:

    &lt;Alt-x&gt;replace-all&lt;return&gt;find-pattern&lt;tab&gt;replacement-pattern&lt;return&gt;

Searches creating clones:

``clone-find-all-flattened`` aka ``(cfaf)``
    Prompts for a find, then creates clones of all found nodes in an organizer node.
``clone-find-all`` aka ``(cfa)``
    Same as ``clone-find-all-flattened``, but does not create duplicate cloned nodes. If a node is a descendant of another found node, no duplicate top-level node (in the organizer) is created.
``clone-find-marked`` aka ``(cfm)`` and ``clone-find-marked-flattened`` aka ``(cfmf)``
    Creates clones of all marked nodes.
``clone-find-parents``
    Creates an organizer node containing clones of all the parents of the selected node.
</t>
<t tx="ekr.20150318110552.60">Incremental find commands move through the text as you type individual characters. Typing ``BackSpace`` backtracks the search. To repeat an incremental search, type the shortcut for that command again. Here are Leo's incremental find commands::

    Alt+R isearch-backward
          isearch-backward-regexp
    Alt+I isearch-forward
          isearch-forward-regexp
          isearch-with-present-options
</t>
<t tx="ekr.20150318110552.61">The following commands work like ``F3 (start-search)`` with various options set:

``search-backward``
    Searches in the reverse direction.
``word-search-backward`` and ``word-search-forward``
    Sets 'Whole Word' checkbox to True.
``re-search-forward`` and ``re-search-backward``
    Set the 'Regexp' checkbox to True.
</t>
<t tx="ekr.20150318110552.62">The following check boxes options appear in the Find pane:

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

    ``Alt+Ctrl+I (toggle-find-ignore-case-option)`` toggles this checkbox.

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

    ``Alt+Ctrl+C (toggle-find-mark-changes-option)`` toggles this checkbox.

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

    ``Alt+Ctrl+F (toggle-find-mark-finds-option)`` toggles this checkbox.

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

    ``Alt+Ctrl+X (toggle-find-regex-option)`` toggles this checkbox.

::

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

    Examples::

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

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

    ``Alt+Ctrl+B (toggle-find-in-body-option)`` toggles this checkbox.

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

    ``Alt+Ctrl+H (toggle-find-in-headline-option)`` toggles this checkbox.

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

    ``Alt+Ctrl+W (toggle-find-word-option)`` toggles this checkbox.

``Wrap Around``
    When checked, the Find and Change commands continues at the top of the file when the command reaches the bottom of the file. For reverse searches, the find or change command continues at the bottom of the file when the command reaches the top of the file.

    ``Alt+Ctrl+A (toggle-find-wrap-around-option)`` toggles this checkbox.
</t>
<t tx="ekr.20150318110552.63">The following radio buttons appear in the Find pane:

``Entire Outline``
    When selected, Find commands search the entire outline.

    ``Alt+Ctrl+E (set-find-everywhere)`` sets this radio button.

``Node Only``
    When selected, Find commands search only the selected node.

    ``Alt+Ctrl+N (set-find-node-only)`` sets this radio button

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

    ``Alt+Ctrl+S (set-find-suboutline-only)`` sets this radio button.
</t>
<t tx="ekr.20150318110552.64">The following commands refer to spell-as-you-type mode:

``spell-as-you-type-next``
    Cycle the word behind (left of, for ltr languages) the cursor through the full list of suggestions.
``spell-as-you-type-toggle``
    Toggle spell as you type mode.  When enabled, word ending keystrokes will put a short list of suggestions in the log window, if the word is unknown to the speller.  Only shows the first 5 suggestions, even if there are more.
``spell-as-you-type-undo``
    Undo the last spelling correction.
``spell-as-you-type-wrap``
    Toggle wrapping in spell-as-you-type mode.
``spell-tab-open``
    Show the Spell tab.

.. Retired...
..  ``focus-to-spell-tab``
..      Put focus in the Spell tab.
..  ``spell-change``
..      Same as clicking the "Change" button in the Spell Tab.
..  ``spell-change-then-find``
..      Same as clicking the "Change, Find" button in the Spell Tab.
..  ``spell-find``
..      Same as clicking the "Find" button in the Spell Tab.
..  ``spell-ignore``
..      Same as clicking the "Ignore" button in the Spell Tab.
..  ``spell-tab-hide``
..      Hide the Spell tab.
</t>
<t tx="ekr.20150318110552.65">``open-local-settings``
    Select the ``@settings`` node in the present file, if any.
``open-myLeoSettings-leo``
    Open ``myLeoSettings.leo`` in a new window.
``style-reload``
    Reloads all visual setting, but not themes.

    **Example**: Change the ``@string font-size`` setting, then do ``style-reload`` and see what happens.
``style-set-selected``
    Set the global stylesheet to c.p.b.

The following commands enable, disable or toggle various settings::

    clear-extend-mode
    disable-autocompleter
    disable-calltips
    enable-autocompleter
    enable-calltips
    set-colors
    set-command-state
    set-extend-mode
    set-insert-state
    set-overwrite-state
    set-replace-string
    set-search-string
    set-silent-mode
    toggle-abbrev-mode
    toggle-autocompleter
    toggle-calltips
    toggle-case-region
    toggle-extend-mode
    toggle-find-collapses-nodes
    toggle-input-state
    toggle-invisibles
    toggle-sparse-move
    toggle-split-direction
</t>
<t tx="ekr.20150318110552.66">.. contents:: Contents
    :depth: 2
    :local:

``cascade-windows``
    Cascades all Leo windows.
``equal-sized-panes``
    Adjusts the sizes of the outline and body panes so that they are the same height.
``minimize-all``
    Minimizes (hides) all Leo windows.
``show-colors``
    Opens a tab in the log pane showing various color pickers.
    (Not implemented in Qt)
``show-fonts``
    Open a tab in the log pane showing a font picker.
``suspend``
    Minimizes the present Leo window.
``toggle-split-direction``
    Switches between vertical and horizontal orientations of the Leo window.

    In the vertical orientation, the body pane appears below the pane containing the outline and log panes. In the horizontal orientation, the body pane appears to the left the pane containing the outline and log panes. By default, the ratio of pane outline pane to the body pane is 0.5 in the vertical orientation and 0.3 in the horizontal orientation. These two ratios may be changed using settings.

``zoom-in``
    Increases text size by 1 pt.
``zoom-out``.
    Decrease text size by 1 pt.
</t>
<t tx="ekr.20150318110552.74">**Important**: The following describes Leo's new abbreviation scheme.  Such abbreviations *fire immediately* whenever they are completed. You do *not* have to execute a command!  By convention, abbreviations end with ``;;``, something you are not likely to type by accident, but you can pick any abbreviation you like.

**Note**:

1. The ``@data abbreviations-subst-env`` node contains a script defining the environment in which all abbreviations execute. This allows helper functions to be defined. Very handy.

2. Scripts may span multiple lines. Line starting with "\:" (2 characters) continue a script. This allows abbreviations to define multi-line templates.
Helpers defined in ``@data abbreviations-subst-env`` can fill in templates with *calculated* (not predefined) data.

3. Templates may contain placeholders that the user can fill in.  By default, the double comma binding selects the next placeholder.

4. Added a new setting: ``@bool scripting-abbreviations``, default False. Scripting abbreviations will be enabled if *either* of the following is True::

    @bool scripting-abbreviations
    @bool scripting-at-script-nodes

This is a safety feature: it allows scripting abbreviations to be enabled *without* enabling the (very dangerous in general) ``scripting-at-script-nodes`` setting.

5. Added a new example node: ``@data abbreviations`` examples.  This contains
   several extremely useful scripts.

.. _`Emacs-like abbreviation commands`: https://www.gnu.org/software/emacs/manual/html_node/emacs/Abbrevs.html#Abbrevs

Leo also supports `Emacs-like abbreviation commands`_::

    dabbrev-completion
    dabbrev-expands

</t>
<t tx="ekr.20150318110552.75">::

    at-file-to-at-auto
    clean-persistence
    cls
    open-python-window  
    script-button

    # Auto-completion
    - show-calltips
    - show-calltips-force

    # Fonts.
    set-font
    show-fonts

    # Icons.
    insert-icon
    delete-first-icon
    delete-last-icon
    delete-node-icons

    # Layout.
    free-layout-context-menu
    free-layout-load
    free-layout-load-alternate
    free-layout-load-detached-body
    free-layout-load-no-log
    free-layout-load-standard
    free-layout-restore
    free-layout-zoom

    # Modes.
    enter-quick-command-mode
    exit-named-mode

    # uA's.
    clear-all-uas
    clear-node-uas
    show-all-uas
    show-node-uas
    set-ua
</t>
<t tx="ekr.20150318110552.79">``act-on-node``
    Executes node-specific action, typically defined in a plugins as follows:
    
    .. code-block:: python

        import leo.core.leoPlugins

        def act_print_upcase(c,p,event):
            if not p.h.startswith('@up'):
                raise leo.core.leoPlugins.TryNext
            p.h = p.h.upper()

        g.act_on_node.add(act_print_upcase)

    This will upcase the headline when it starts with ``@up``.

Plugins create the following commands::

    # bookmarks.py
    bookmarks-bookmark
    bookmarks-bookmark-child
    bookmarks-level-decrease
    bookmarks-level-increase
    bookmarks-mark-as-target
    bookmarks-open-bookmark
    bookmarks-open-node
    bookmarks-show
    bookmarks-switch
    bookmarks-use-other-outline

    # printing.py
    preview
    preview-node
    preview-tree
    print-expanded-node
    print-expanded-node-body
    print-marked-node-bodies
    print-marked-nodes
    print-preview-expanded-node
    print-preview-expanded-node-body
    print-preview-marked-node-bodies
    print-preview-marked-nodes
    print-preview-selected-node
    print-preview-selected-node-body
    print-preview-selected-node-body-html
    print-selected-node
    print-selected-node-body
    print-selected-node-body-html

    # quicksearch.py
    find-quick
    find-quick-changed
    find-quick-selected
    find-quick-test-failures
    find-quick-timeline
    focus-to-nav
    go-anywhere
    history
    marked-list

    # richtext.py
    cke-text-close
    cke-text-open
    cke-text-switch
    cke-text-toggle-autosave
    richtext-close-editor
    richtext-open-editor
    richtext-switch-editor
    richtext-toggle-autosave

    # viewrendered.py
    vr-contract
    vr-expand
    vr-hide
    vr-lock
    vr-pause-play-movie
    vr-show
    vr-toggle (Alt-0)
    vr-unlock
    vr-update</t>
<t tx="ekr.20150318110552.8">.. _`Emacs cursor commands`: https://www.gnu.org/software/emacs/manual/html_node/emacs/Moving-Point.html#Moving-Point

**Smart cursor moves**: Many editors allow you to jump over, select and delete words, especially those containing or surrounded by special characters, in a smarter way than just "going to the beginning of the word before" (back-word) or "going to the end of the next word" (forward-word)::

    back-word-smart
    back-word-smart-extend-selection
    forward-word-smart
    forward-word-smart-extend-selection
    delete-word-smart
    backward-delete-word-smart

The following commands work much like the `Emacs cursor commands`_::

    back-char
    back-char-extend-selection
    back-page
    back-page-extend-selection
    back-paragraph
    back-paragraph-extend-selection
    back-sentence
    back-sentence-extend-selection
    back-to-home
    back-to-home-extend-selection
    back-to-indentation
    back-word-extend-selection
    backward-delete-char
    backward-find-character
    backward-find-character-extend-selection
    backward-kill-paragraph
    backward-kill-sentence
    backward-kill-word
    beginning-of-buffer
    beginning-of-buffer-extend-selection
    beginning-of-line
    beginning-of-line-extend-selection
    end-of-buffer
    end-of-buffer-extend-selection
    end-of-line
    end-of-line-extend-selection
    find-character
    find-character-extend-selection
    find-word-in-line
    forward-char
    forward-char-extend-selection
    forward-end-word
    forward-end-word-extend-selection
    forward-page
    forward-page-extend-selection
    forward-paragraph
    forward-paragraph-extend-selection
    forward-sentence
    forward-sentence-extend-selection
    forward-word-extend-selection
    move-past-close
    move-past-close-extend-selection
    next-line
    next-line-extend-selection
    previous-line
    previous-line-extend-selection
</t>
<t tx="ekr.20150318110552.87">::

    :!
    :%s
    :e
    :e!
    :gT
    :gt
    :print-dot
    :q
    :q!
    :qa
    :r
    :s
    :tabnew
    :toggle-vim-mode
    :toggle-vim-trace
    :toggle-vim-trainer-mode
    :w
    :wq
    :xa
</t>
<t tx="ekr.20150323102036.1">Scripts and plugins can call g.app.idleTimeManager.add_callback(callback) to cause
the callback to be called at idle time forever. This should suffice for most purposes:

.. code-block:: python

    def print_hi():
        print('hi')

    g.app.idleTimeManager.add_callback(print_hi)
    
For greater control, g.IdleTime is a thin wrapper for the Leo's IdleTime class. The IdleTime class executes a handler with a given delay at idle time. The handler takes a single argument, the IdleTime instance:

.. code-block:: python

    def handler(it):
        """IdleTime handler.  it is an IdleTime instance."""
        delta_t = it.time - it.starting_time
        g.trace(f"{it.count} {c.shortFileName()} {delta_t:2.2}")
        if it.count &gt;= 5:
            g.trace('done')
            it.stop()

    # Execute handler every 500 msec. at idle time.
    it = g.IdleTime(handler, delay=500)
    if it:
        it.start()

The code creates an instance of the IdleTime class that calls the given handler at idle time, and no more than once every 500 msec.  Here is the output::

    handler 1 LeoDocs.leo 0.5
    handler 2 LeoDocs.leo 1.0
    handler 3 LeoDocs.leo 1.5
    handler 4 LeoDocs.leo 2.0
    handler 5 LeoDocs.leo 2.5

Timer instances are completely independent:

.. code-block:: python

    def handler1(it):
        delta_t = it.time-it.starting_time
        g.trace(f"{it.count} {c.shortFileName()} {delta_t:2.2}")
        if it.count &gt;= 4:
            g.trace('done')
            it.stop()

    def handler2(it):
        delta_t = it.time-it.starting_time
        g.trace(f"{it.count} {c.shortFileName()} {delta_t:2.2}")
        if it.count &gt;= 6:
            g.trace('done')
            it.stop()

    it1 = g.IdleTime(handler1, delay=500)
    it2 = g.IdleTime(handler2, delay=1000)
    if it1 and it2:
        it1.start()
        it2.start()

Here is the output::

    handler1 1 LeoDocs.leo 0.5
    handler1 2 LeoDocs.leo 1.0
    handler2 1 LeoDocs.leo 1.0
    handler1 3 LeoDocs.leo 1.5
    handler1 4 LeoDocs.leo 2.0
    handler1 done
    handler2 2 LeoDocs.leo 2.0
    handler2 3 LeoDocs.leo 3.1
    handler2 4 LeoDocs.leo 4.1
    handler2 5 LeoDocs.leo 5.1
    handler2 6 LeoDocs.leo 6.1
    handler2 done
</t>
<t tx="ekr.20150323102918.1">.. Aliases.
find-clone-all
find-clone-all-flattened
find-next-clone
find-quick
find-quick-changed
find-quick-selected
find-quick-test-failures
find-quick-timeline
global-search

.. These *are* still used.
abbrev-kill-all
abbrev-list

disable-idle-time-tracing
enable-idle-time-tracing
toggle-idle-time-tracing

.. Obscure minibuffer-related commands.
context-menu-open
menu-shortcut
</t>
<t tx="ekr.20150323103115.1">.. _`Emacs rectangle commands`: https://www.gnu.org/software/emacs/manual/html_node/emacs/Rectangles.html

The following commands emulate the `Emacs rectangle commands`_::

    rectangle-clear
    rectangle-close
    rectangle-delete
    rectangle-kill
    rectangle-open
    rectangle-string
    rectangle-yank

Given::

    I'm really glad the docs are being updated. I know that's a
    monumental task. I only use a fraction of Leo's commands, mostly
    because I don't even know what they're supposed to accomplish. A few
    examples:

Placing the cursor immediately before the first "I", holding shift and moving it to immediately before the word``examples`` selects a zero width rectangle from the beginning to the end of the selection (zero width because the selection starts and ends in the same column.  Then running ``rectangle-string [largo]&lt;space&gt;&lt;enter&gt;`` yields::

  [largo] I'm really glad the docs are being updated. I know that's a
  [largo] monumental task. I only use a fraction of Leo's commands, mostly
  [largo] because I don't even know what they're supposed to accomplish. A few
  [largo] examples:
</t>
<t tx="ekr.20150323111053.1">Just use cff (clone-find-all-flattened).  This is my workhorse command when fixing complex bugs.</t>
<t tx="ekr.20150323154836.1">If you give no file arguments on the command line Leo will open ``~/.leo/workbook.leo``.  Initially, this file contains Leo's cheat sheet and an example from the rst3 tutorial.
</t>
<t tx="ekr.20150323161357.1">``show-bindings`` prints a complete list of the bindings in effect.

.. contents:: Contents
    :depth: 2
    :local:

</t>
<t tx="ekr.20150323161357.2">When focus is in the outline pane::

    Right-arrow (expand-and-go-right)
    Left-arrow (contract-or-go-left)
    Up-arrow (goto-prev-visible) 
    Down-arrow (goto-next-visible)

Regardless of focus::

    Alt-Home (goto-first-visible-node) 
    Alt-End (goto-last-visible-node)
    Alt-Right-arrow (expand-and-go-right)
    Alt-Left-arrow (contract-or-go-left)
    Alt-Up-arrow (goto-prev-visible) 
    Alt-Down-arrow (goto-next-visible)
</t>
<t tx="ekr.20150323161357.3">When focus is in the outline::

    Shift-Down-arrow (move-outline-down) 
    Shift-Left-arrow (move-outline-left) 
    Shift-Right-arrow (move-outline-right) 
    Shift-Up-arrow (move-outline-up)

Regardless of focus::

    Alt-Shift-Down-arrow (move-outline-down) 
    Alt-Shift-Left-arrow (move-outline-left) 
    Alt-Shift-Right-arrow (move-outline-right) 
    Alt-Shift-Up-arrow (move-outline-up)
    Ctrl-D (move-outline-down)
    Ctrl-L (move-outline-left) 
    Ctrl-R (move-outline-right)
    Ctrl-U (move-outline-up)
</t>
<t tx="ekr.20150323161357.4">When focus is in any of Leo's text panes (body pane, log pane, headlines)::

    Arrows            move one character
    Ctrl-LeftArrow    back one word
    Ctrl-RightArrow   forward one word
    Home              beginning of line
    End               end of line
    Ctrl-Home         beginning of the body
    Ctrl-End          end of body
    PageDown          down one page
    PageUp            up one page

**Shift keys**: Adding the Shift key modifier to any of the keys above moves the cursor and extends the selected text.

</t>
<t tx="ekr.20150323185514.1">.. contents:: Contents
    :depth: 2
    :local:
</t>
<t tx="ekr.20150323185611.1">The following commands typically work like the corresponding Emacs command. For details about any command use ``F11 (help-for-command)``::

    backward-delete-char
    backward-find-character
    backward-find-character-extend-selection
    backward-kill-paragraph
    backward-kill-sentence
    backward-kill-word
    kill-line
    kill-paragraph
    kill-region
    kill-region-save
    kill-sentence
    kill-to-end-of-line
    kill-word
    kill-ws
    yank
    yank-pop
    zap-to-character
</t>
<t tx="ekr.20150323185921.1">The following commands typically work like the corresponding Emacs command. For details about any command use ``F11 (help-for-command)``::

    add-space-to-lines
    add-tab-to-lines
    align-eq-signs
    auto-complete
    auto-complete-force
    capitalize-word
    center-line
    center-region
    clear-kill-ring
    count-pages
    count-region
    delete-char
    delete-indentation
    delete-spaces
    downcase-region
    downcase-word
    exchange-point-mark
    extend-to-line
    extend-to-paragraph
    extend-to-sentence
    extend-to-word
    fill-paragraph
    fill-region
    fill-region-as-paragraph
    hide-invisibles
    how-many
    indent-relative
    indent-rigidly
    indent-to-comment-column
    insert-child
    insert-file-name
    insert-file-name
    insert-hard-tab
    insert-newline
    insert-parentheses
    insert-soft-tab
    join-node-above
    join-node-below
    join-selection-to-node-below
    line-number
    move-lines-down
    move-lines-up
    newline-and-indent
    open-url
    open-url-under-cursor
    remove-blank-lines
    remove-newlines
    remove-space-from-lines
    remove-tab-from-lines
    reverse-region
    reverse-sort-lines
    reverse-sort-lines-ignoring-case
    select-to-matching-bracket
    set-fill-column
    set-fill-prefix
    shell-command
    shell-command-on-region
    show-invisibles
    set-comment-column
    sort-columns
    sort-fields
    sort-lines
    sort-lines-ignoring-case
    split-line
    tabify
    transpose-chars
    transpose-lines
    transpose-words
    untabify
    upcase-region
    upcase-word
    view-lossage
    what-line
</t>
<t tx="ekr.20150323200607.1">``goto-global-line (Alt-G)``
    Selects the locations in your outlines corresponding to a line in a external file.
``match-brackets``
    Enabled if the cursor is next to one of these characters in the body pane: ``( ) [ ] { } &lt; &gt;`` The command looks for the matching character, searching backwards through the body text if the cursor is next to ``)`` ``]`` ``}`` or ``&gt;`` and searching forward through the text otherwise. If the cursor is between two brackets the search is made for the bracket matching the leftmost bracket. If a match is found, the entire range of characters delimited by the brackets is highlighted and the cursor is placed just to the left of the matching characters. Thus, executing this command twice highlights the range of matched characters without changing the cursor.
</t>
<t tx="ekr.20150323200950.1">``c-to-python``
    Converts c or c++ text to python text. The conversion is not perfect, but it eliminates a lot of tedious text manipulation.  This command is a rewrapping of the first Python script I ever wrote.

``import-free-mind-files``
    Prompts for FreeMind files and imports them.

``typescript-to-py``
    Converts typescript text to python text. The conversion is not perfect, but it eliminates a lot of tedious text manipulation.
</t>
<t tx="ekr.20150326140024.1">I just want to provide my own thoughts about the importance of @clean. I look at the posts in this group a fair amount because I find the discussion interesting but I had abandoned Leo as a day-to-day tool principally because of the sentinels in @file nodes. Even for solo projects, I just found them visually unappealing and beyond that occasionally confusing when I went to edit files with external editors. I would sometimes start a project in Leo, particularly if it was based on code I developed in the past using Leo, and then would use the old @nosent to save a version of the code without sentinels and then use my external editor of choice and not use Leo at all. I missed many of the features of Leo but just couldn't get over the sentinel issue.

@clean really seems to solve all the issues that I had. In particular--and
somehow this point doesn't seem to me to have been emphasized enough--it seems to fully support organizer nodes. They are one of the great things about Leo--it's happy to guess initially at what the structure of your program is but it's completely up to you to determine the structure and the ability to do things like break up long methods, group like methods, group menu actions in GUI code, etc etc is one of the very cool things about Leo. My limited but growing experience with @clean's handling of external changes has been mainly with incremental (as opposed to more sweeping) code changes, and the assignment of new lines is reasonable and you can always fix them it quickly if you don't like how external changes have been handled.

There have been some posts about the recovered nodes, comparing the old and new nodes where there were external changes. I think it's genius. As opposed to hoping that Leo has correctly incorporated external changes, it's all there in case you want to take a closer look. Without this, I would just not have the confidence that external changes were being applied correctly and while you can always do a git diff, I am not looking to do that every time I change a file externally especially if I am not at the point where I am about to do a commit.

There has been some discussion of @auto v. @clean. Preference is obviously a matter of taste. I will say that for me the fact that node headlines are unaffected by external file changes is a feature not a problem since I place notes in the headlines that I want preserved when I edit files externally. Yes, if the node headlines are the method names then they won't be updated if an external edit changes a method name but this was true of @file as well.

The ability to work on projects with people who don't have Leo is obvious; one perhaps slightly less obvious benefit of no sentinels is that I suspect that the likelihood that someone will clone a git repository is reduced when that repository's code is riddled with Leo sentinels (unless the potential cloner is a Leo loyalist). The one downside to no sentinels--there is no evidence that Leo is being used but I think that raises the broader question of marketing Leo, which I certainly believe will be aided significantly by being able to take advantage of Leo without sentinels in external files.--- Steve Zatz
</t>
<t tx="ekr.20150415105956.1">clone-find-all-flattened often includes clones of nodes whose location is unclear.  No problem! Just select the mysterious node and do Alt-N (goto-next-clone). Leo will select the next clone of that node, wrapping the search as necessary.  One or two Alt-N takes me to the "real" node, the node having an ancestor @&lt;file&gt; node.

Ideally, the meaning of all nodes would be clear from their headlines.  I typically use the following conventions. For section definitions, the headline should contain file or class name.  Examples::

    &lt;&lt; imports &gt;&gt; (leoCommands.py)
    &lt;&lt; docstring &gt;&gt; (LeoApp)

</t>
<t tx="ekr.20150415110715.1">Clone wars can be most annoying. The solution is simple::

    **Keep clones only in the outline and in one other external file**

In particular, catchall files like leo/doc/leoProjects.txt or leo/doc/leoToDo.txt should never contain clones.
</t>
<t tx="ekr.20150415111217.1">Clones make reorganizing an outline significantly easier and faster.  Simply make top-level clones of the nodes you keep encountering during the reorg. This makes moving a node a snap: just move it from one clone to another.
</t>
<t tx="ekr.20150416100041.1">When organizing data into nodes, **every item should clearly belong to exactly one top-level category**. In other words, avoid top-level *aggregate* categories.

For example, the following are poor top-level categories. They are poor because any item in them could be placed in a more explicit category:

- Contrib
- Developing Leo
- Important
- Maybe
- Others
- Prototype
- Recent
- Won't do/Can't do

We all have had bad experiences with the dreaded "Others" category. The Aha! is that all aggregate categories are just as bad as "Others".

**Note**: I have been talking only about top-level categories.  Within a single category aggregate categories may be useful.  However, when possible I prefer to mark items rather than create subcategories. For example, ``*`` now marks all "Important" items in leoToDo.txt and scripts.leo.  This makes it easy to find important items in a particular category.  To find *all* important items one could do a regex search for ``^\*`` in headlines.
</t>
<t tx="ekr.20150417041505.1">Leo's handling of focus is complicated in order to reduce unwanted screen flash. The following methods queue *requests* for focus::

    c.bodyWantsFocus()
    c.logWantsFocus()
    c.minibufferWantsFocus()
    c.treeWantsFocus()
    c.widgetWantsFocus(w)

Similarly, c.redraw and c.recolor queue requests to redraw the outline pane and to recolorize the body pane.

c.outerUpdate honors all requests after the present command completes, that is, just before idle time.

Sometimes a command requires that an action happen immediately.  The following methods queue a request and then immediately call c.outerUpdate::

    c.bodyWantsFocusNow()
    c.logWantsFocusNow()
    c.minibufferWantsFocusNow()
    c.recolor_now()
    c.redraw_now()
    c.treeWantsFocusNow()
    c.widgetWantsFocusNow(w)
</t>
<t tx="ekr.20150509193629.1">def cmd(name):
    '''Command decorator for the LeoApp class.'''
    # pylint: disable=no-self-argument
    return g.new_cmd_decorator(name, ['g', 'app'])
</t>
<t tx="ekr.20150509193643.1"></t>
<t tx="ekr.20150514125218.1"></t>
<t tx="ekr.20150514125218.2">@g.command('ctrl-click-at-cursor')
def ctrlClickAtCursor(event):
    '''Simulate a control-click at the cursor.'''
    c = event.get('c')
    if c:
        g.openUrlOnClick(event)
</t>
<t tx="ekr.20150514125218.3">@g.command('disable-idle-time-events')
def disable_idle_time_events(event):
    '''Disable default idle-time event handling.'''
    g.app.idle_time_hooks_enabled = False

@g.command('enable-idle-time-events')
def enable_idle_time_events(event):
    '''Enable default idle-time event handling.'''
    g.app.idle_time_hooks_enabled = True

@g.command('toggle-idle-time-events')
def toggle_idle_time_events(event):
    '''Toggle default idle-time event handling.'''
    g.app.idle_time_hooks_enabled = not g.app.idle_time_hooks_enabled
</t>
<t tx="ekr.20150514125218.4">@g.command('join-leo-irc')
def join_leo_irc(event=None):
    '''Open the web page to Leo's irc channel on freenode.net.'''
    import webbrowser
    webbrowser.open("http://webchat.freenode.net/?channels=%23leo&amp;uio=d4")
</t>
<t tx="ekr.20150514125218.5">@g.command('open-url')
def openUrl(event=None):
    '''
    Open the url in the headline or body text of the selected node.

    Use the headline if it contains a valid url.
    Otherwise, look *only* at the first line of the body.
    '''
    c = event.get('c')
    if c:
        g.openUrl(c.p)
</t>
<t tx="ekr.20150514125218.6">@g.command('open-url-under-cursor')
def openUrlUnderCursor(event=None):
    '''Open the url under the cursor.'''
    return g.openUrlOnClick(event)
</t>
<t tx="ekr.20150603115243.1">``@killbeautify``
    This directive completely disables beautification for an entire tree. This is typically required for files containing ``@all``.

``@beautify`` and ``@nobeautify``
    These directives apply to a node and its descendants, until overridden later in a descendants. Both these directives may appear in the same node.  Such **ambiguous directives** do not affect the beautification of descendant nodes.  If both ``@beautify`` and ``@nobeautify`` appear in a node, the first directive determines whether the node will be beautified.

For example:

.. code-block:: python

    @beautify
    ...
    @nobeautify

beautifies the entire node.  Otoh:

.. code-block:: python

    @nobeautify
    ...
    @beautify

skips beautification of the entire node. Yes, this is less precise than one could imagine, but it's good enough.
</t>
<t tx="ekr.20150603115400.1">You can run leoBeautify.py from the command line::

    python -m leo.core.leoAst --orange file1, file2...

Running::

    python -m leo.core.leoAst -h

Produces something like this::

    usage: leoAst.py [-h] [--fstringify | --fstringify-diff | --orange | --orange-diff] [--allow-joined] [--max-join N]
                     [--max-split N] [--recursive] [--tab-width N]
                     [PATHS ...]

    Execute fstringify or beautify commands contained in leoAst.py.

    positional arguments:
      PATHS              directory or list of files

    options:
      -h, --help         show this help message and exit
      --fstringify       fstringify PATHS
      --fstringify-diff  fstringify diff PATHS
      --orange           beautify PATHS
      --orange-diff      diff beautify PATHS
      --allow-joined     allow joined strings
      --max-join N       max unsplit line length (default 0)
      --max-split N      max unjoined line length (default 0)
      --recursive        include directories recursively
      --tab-width N      tab-width (default -4)
</t>
<t tx="ekr.20150603161559.1">.. _`PEP8`: https://peps.python.org/pep-0008/

``beautify-node``
    Beautifies the Python code in the selected node.
``beautify-tree``
    Beautifies all the Python code in the selected tree.
``beautify-c``
    Reformats all C code in the selected tree.

These commands skip any nodes for which ``@language python`` (or ``c``) is not in effect.

The **Python beautifier** (``beautify-tree`` and ``beautify-node``) is `PEP8`_ compliant. The beautifier will *just work* for most people. 

The Python beautifier works only on syntactically correct code. It issues a warning and does nothing for syntactically incorrect code.
</t>
<t tx="ekr.20150621062355.1">def runAlreadyOpenDialog(self, c):
    '''Warn about possibly already-open files.'''
    # g.trace(g.app.already_open_files)
    if g.app.already_open_files:
        aList = sorted(set(g.app.already_open_files))
        g.app.already_open_files = []
        g.app.gui.dismiss_splash_screen()
        message = (
            'The following files may already be open\n'
            'in another copy of Leo:\n\n' +
            '\n'.join(aList))
        g.app.gui.runAskOkDialog(c,
            title='Already Open Files',
            message=message,
            text="Ok")
</t>
<t tx="ekr.20150817125512.1">efc.compareTrees does most of the work of comparing two similar outlines.
For example, here is "@button compare vr-controller" in leoPyRef.leo:

.. code-block:: python

    p1 = g.findNodeAnywhere(c, 'class ViewRenderedController (QWidget) (vr)')
    p2 = g.findNodeAnywhere(c, 'class ViewRenderedController (QWidget) (vr2)')
    assert p1 and p2
    tag = 'compare vr1 &amp; vr2'
    c.editFileCommands.compareTrees(p1, p2, tag)

This script will compare the trees whose roots are p1 and p2 and show the results like "Recovered nodes".  That is, the script creates a node called "compare vr1 &amp; vr2".  This top-level node contains one child node for every node that is different.  Each child node contains a diff of the node.  The grand children are one or two clones of the changed or inserted node.
</t>
<t tx="ekr.20150923111606.1">A new user recently said to me, "Leo is powerful and flexible--and complex and bewildering". This is true. I believe it is always the goal of developers to make their software less complex and bewildering but keep in mind that Leo has been in development for over 20 years...This puts it right up there with Vim and Emacs in terms of maturity. My own experience with Vim and Emacs have been quite similar to my experience with Leo. All three are powerful and flexible and complex and bewildering in their own right.

I believe with tools of this weight and impact, there will always be an investment in learning them. They're all vast forests of features filled with hidden treasures and in the case of each of them he/she that invests in the tool will be rewarded for their effort. It is, however, the responsibility of the community (led by the developers) to help make that treasure hunt as enjoyable and adventurous as possible, as any good treasure hunt should be. 

And this is where Leo does not falter, in the helpfulness of its community (small though it may be). I will reiterate what Edward has said many times, do not struggle on your own if you are lost, confused, or bewildered. Please ask questions. If the documentation or examples do not meet your needs, please ask questions. In my own experience as a once new user (though there may be the occasional disagreement) you will not be chided, scorned, or belittled but will be met with more even more help than you originally asked for. -- John Lunzer &lt;lunzer@gmail.com&gt;</t>
<t tx="ekr.20160123060917.1">This key is normally bound to delete-comments. It is annoying not to have it work.

The only sure workaround is make other key bindings for add-comments and delete-comments.  I suggest Ctrl-[ and Ctrl-].

At one time I thought the following might work, but it appears that it doesn't:

1. In the control panel, click Language.
   This brings up the "Language" panel.

2. Choose "Advanced Settings" in the left area.
   This brings up the "Advanced Settings" panel.

3. Choose "Change language bar hot keys" in the left area.
   This brings up the "Text Services &amp; Input Language" panel.

4. You will see Shift-Ctrl-0 as the binding for "Between input languages".
    Select that item and click the "Change Key Sequence" button.
    This brings up the "Change Key Sequence" panel.

5. Set both radio buttons to "Not Assigned" and click OK.</t>
<t tx="ekr.20160304081437.3">To enable a theme .leo file, put the following setting in myLeoSettings.leo::

    @string theme-name = &lt;theme file, without the .leo extension&gt;

Dark themes::

    @string theme-name = BreezeDarkTheme
    @string theme-name = EKRDark
    @string theme-name = LeoBlackSolarized
    @string theme-name = ZephyrDarkTheme

Light themes::

    @string theme-name = DefaultTheme
    @string theme-name = EKRLight
    @string theme-name = PaperLightTheme

You can also define a theme directly in myLeoSettings.leo as follows:

- *Remove* (or disable) any previous @theme tree in myLeoSettings.leo.
- *Select* one of the @theme trees in leoSettings.leo.
- *Copy* the entire @theme tree to myLeoSettings.leo.
- *Move* the copied tree to the *end* of the @settings tree.
- *Test* by restarting Leo.
</t>
<t tx="ekr.20160304081437.5">Imo, git rivals python as the greatest productivity tool ever devised for programmers.

My workflow on Ubuntu and Windows is essentially identical. Simple aliases (Ubuntu) and .bat files (Windows) support the following console commands::

    gs  (expands to git status)
    gd (git diff)  Uses an external diff program,
                   but I'm starting to prefer text diffs.
    ga . (git add .)
    ga file (git add file)
    gc (git commit: configured to open Scite to create a commit message)
    gc -m "a one-line commit message"
    push (git push)

I use gitk on both platforms to review commits.

And that's about it. I use "git help" and "git help command" as needed.
</t>
<t tx="ekr.20160304081437.7">Leo is a superb tool for understanding, studying and organizing any kind of complex data, including computer programs. The first great Aha in Leo's history was that webs (literate programs) are outlines in disguise. Leo's importers (@auto) make it easy to studying other people's programs. Leo's always-present outline structure clarifies overall program structure and makes many kinds of comments unnecessary.

Leo is also a superb browser for code and data. Unlike many other folding editors, Leo remembers which nodes were expanded when you last saved an outline. This is surprisingly important. And Leo's clones let you organize any data as you want, even if all folds are collapsed.

Leo is a uniquely powerful scripting environment. This power comes from three sources: Leo's API, Leo's ability to compose scripts from outlines and Leo's underlying data structure, a Directed Acyclic Graph, the basis for Leo's clones.

Leo's API consists primarily of generators, such as c.all_positions(), p.self_and_subtree(), etc. and properties, such as p.b, p.h, p.gnx and p.v.u.  Leo's API makes it trivial to write scripts to access or change any node. AFAIK, these capabilities are unique.  Simulating them in vim or Emacs is possible, but so is simulating Python's capabilities in C...

Afaik, no other scripting environment allows you to compose scripts from outlines.  @file, @clean, @auto, @others and section references and definitions make this possible.  Section references and definitions are modeled on the noweb language, but all of Leo's script composition features are fully integrated into Leo's outline structure.

Leo's outline nodes have headlines (p.h) and body text (p.b) and extensible information (p.v.u).  Headlines are descriptions (meta-data) of the data in p.b and p.v.u.  Scripts can rapidly discover and categorize data using metadata.  Leo's @ convention for headlines (@clean, @file, @auto, @html, etc.) show how extensible this node typing is.

So much for the theory.  The following also are important in practice:

- Native scripting in Python, with full access to all of Leo's sources.
- Leo's plugin architecture.
- Leo's rst3 command.
- Leo's support for vim and xemacs.
- Leo's leoBridge module.
- Leo's minibuffer commands, borrowed shamelessly from Emacs.
- @button: bringing scripts to data.
- Leo's outline-oriented directives.

The invention/discovery of @clean earlier this year completes Leo is some sense.

Acknowledgements: Working with Leo's community of Leo's developers and users has been a great pleasure for over 20 years. My only regret is that Bernhard Mulder and Bob Fitzwater are no longer with us. Both made essential contributions. Bob Fitzwater was my mentor. He gently pushed me to consider design, not just "bit twiddling".  Bernhard Mulder contributed two of the most important elements of Leo: Leo's traversers (generators) and the original @shadow algorithm.  Neither @clean nor the revised Mulder/Ream algorithm could possibly have happened without him.  I miss both these great thinkers.  Both would have been proud of what they helped create.

A successful software tool is one that was used to do something undreamed of by its author.' -- Stephen Johnson

Leo is a wild success on this score. I foresaw none of these developments 20 years ago:  Leo's minibuffer, @button, @auto, @clean, Leo's plugin architecture, the rst3 command, and the Leo's bridge.  Surely many other features and uses could be added. None of these would have happened without Leo's community of brilliant people. These features create the Leonine world.  Who knows what will be the result...

Edward K. Ream
</t>
<t tx="ekr.20160304081437.8">This idea of an always-present outline has been key to me for organizing writings. Some coworkers have found in the past that this helps them when we're correcting their text.

&gt; Leo's clones let you organize any data as you want, even if all folds are collapsed.

For me this is the most powerful but misunderstood feature of Leo. Most of the people which compares it with other IDE rant about why Leo doesn't works more automatically imposing structure, but in Leo you're in charge. You impose infrastructure...

For me the second main insight of Leo (besides emergent always present tree structure on almost any file) was to have a tree that is a programmable structure that can be understood and changed by any node inside that tree. I think that Leo brings structure and self-referentiality to the dumb flat file word. So you can create a tree from one (or several) files, deconstruct and reconstruct it they way you want and automatize the way in behaves and talks with the external world...The more I start to focus on interactive writing and going away of the unix inspired OS world, the more the second insight become important to me. I didn't need to deconstruct/reconstruct or impose structure over flat files but to use outlining for structure thought by (interactive) writing and I need the outline be a fully programmable object. That's the essence of most of my Leo experience...

Thanks for Leo and all the key inspiration it brings. And, as always, thanks to the Leo community for the food for thought.
</t>
<t tx="ekr.20160304081437.9">My only input is what makes Leo so special to me.

After learning just a few things about Leo, and after replacing section references mostly with @others, writing code becomes a game rather than a chore.

As soon as an idea becomes complicated, I add a new @others, and break down the complication into chunks until all the complications are now simple.

I'll typically clone that section an the bottom of the outline, then add enough logic at a parent level so that the complication can be tested with control B.

This is my backward implementation of unit testing. This kind of 'unit testing' never has to be refactored when the code is (invariably) improved.

The cloned 'test piece' can be relegated to a testing section, and the new chunks subsequently cloned into whatever structure make real sense for the project.

In practice, this is just fun for me.

Coding without Leo is not really fun any more. I recently finished a c++ socket server using Microsoft's Visual Studio, in concert with someone who didn't have Leo. Microsoft's tools are great, and the project went off without a hitch, but the fun was just plain gone.

Anyway, thanks for the great perspective on Leo.
</t>
<t tx="ekr.20160310060817.1">::

    @bool make-node-conflicts-node
    goto-global-line prefers to find a node *outside* any @&lt;file&gt; tree.
    Added unformat-paragraph.</t>
<t tx="ekr.20160310062634.1"></t>
<t tx="ekr.20160310062651.1">::

    Leo 5.2-final release March 18, 2016

    Easy install with PyInstaller packaging
    c.cloneFindByPredicate
    clone-find-marked commands:
        cfam (clone-find-all-marked)
        cffm (clone-find-all-flattened-marked)
    decorators create all Leo commands
    find-def and find-var
    help-for-keystroke
    Optional line numbers in the left gutter
    show-invisibles uses Qt characters
    --ipyhon command-line option works with latest IPython versions
    Themes
    Wildcard file names on Leo's command line</t>
<t tx="ekr.20160310063235.1">::

    cfa, cff, cfam, cfam
    clear-log
    clone-to-at-spot
    Ctrl-x &amp; Ctrl-C cut/copy the entire line if no text is selected
    find-all now writes to the body of a new top-level node
    find-def and find-var
    flatten-outline-to-node
    goto-next-clone falls back to find-next-clone
    help-for-keystroke
    kill commands cut selected text
    show-invisibles uses Qt characters
    vim-open-file
    @beautify and @nobeautify</t>
<t tx="ekr.20160310064208.18">::

    leoOPML.py plugin

    mod_http.py plugin can control Leo remotely
    (https://groups.google.com/d/msg/leo-editor/wWWUgfDhPi4/VmRRRa_xDAAJ)

    make_stub_files.py script creates stub (.pyi) files
    https://github.com/edreamleo/make-stub-files

    python_to_coffescript.py script converts .py files to .coffee files
    https://github.com/edreamleo/python-to-coffeescript
</t>
<t tx="ekr.20160310064208.24">::

    @bool find-ignore-duplicates
    @bool preload-find-pattern
    @bool syntax-error-popup
    @bool use_find_dialog
    @bool use_gutter = True
    @color find-found-bg = blue
    @color find-found-fg = white
    @color find-not-found-bg = red
    @color find-not-found-fg = white
    @color gutter-bg = @LightSteelBlue1
    @color gutter-fg = black
	@data abbreviations-subst-env now allows Leo directives
    @data history-list
	@data qt-gui-user-style-sheet
    (https://github.com/leo-editor/leo-editor/issues/183)
	@ifenv
    @ifplatform &amp; @ifhostname (improved)
    @int gutter-w-adjust = 12
    @int gutter-y-adjust = 10
    @language coffeescript
    @string gutter-font-family = @font-family
    @string gutter-font-size = @small-font-size
    @string gutter-font-style = @font-style
    @string gutter-font-weight = @font-weight
</t>
<t tx="ekr.20160310064208.5">::

    Abbreviations now support auto-close quotes
    https://groups.google.com/d/msg/leo-editor/yJLz-p3I4mY/Pqa1phYN_10J
    Ctrl-G resets status line
    declutter node: substituting icons for @clean, @file, etc.
    Find commands now show status
    New menu: Settings: Edit Settings
    https://groups.google.com/d/msg/leo-editor/pM8aVJ1D6ao/Z8lq43t7FAAJ
    New menu: File:Print
    Optional line numbers in the left gutter
    Themes
    Wildcard file names on Leo's command line
</t>
<t tx="ekr.20160318142213.1">Installing PyQt on MacOS using::

    brew install qt sip pyqt

may not always work.  In that case, you will see something like this when running Leo::

    Traceback (most recent call last):
    File "launchLeo.py", line 8, in
    leo.core.runLeo.run()
    [Snip]
    File "/Users/your-name/git/leo-editor/leo/plugins/qt_text.py",
    line 434, in class LeoLineTextWidget(QtWidgets.QFrame):
    AttributeError: 'NoneType' object has no attribute 'QFrame'

You can verify that PyQt has not been installed by setting the trace switch to True in leoQt.py. This will trace the import commands related to Qt and tell you exactly what is happening.

One Leo user gives this advice:

For anyone with similar problem the homebrew instruction for adding PyQT to the import path are wrong. Instead edit ~/.bash_profile and add this line::

    export PATH="/usr/local/lib/python3.9/site-packages:${PATH}"

After this leo editor will open with using the default python installation provided by MacOS.</t>
<t tx="ekr.20160410044518.1">.. index::
    pair: @nosent; Reference

The ``@nosent`` directive creates an external file **without** sentinels. When writing
``@nosent`` trees, Leo expands section references and ``@all`` and ``@others`` directives. **Warning**: Because the external file contains no sentinels, ``@nosent`` trees can not be updated from changes made outside of Leo. If you want this capability, use ``@clean`` instead.
</t>
<t tx="ekr.20160410045234.1">When importing files into ``@auto`` trees, Leo performs several checks to ensure that writing the imported file will produce exactly the same file. These checks can produces **errors** or **warnings**. Errors indicate a potentially serious problem. Leo inserts an ``@ignore`` directive in the ``@auto`` tree if any error is found. This prevents the ``@auto`` tree from modifying the external file.

.. index::
    pair: Strict language; Reference

Before importing a file, Leo **regularizes** the leading whitespace of all lines of the original source file. That is, Leo converts blanks to tabs or tabs to blanks depending on the value of the ``@tabwidth`` directive in effect for the ``@auto`` node. Leo also checks that the indentation of any non-blank line is a multiple of the indentation specified by the ``@tabwidth`` directive. **Strict languages** are languages such as Python for which leading whitespace must be preserved exactly as it appears in the original source file. Problems during regularizing whitespace generate errors for strict languages and warnings for non-strict languages.

After importing a file, Leo verifies that writing the ``@auto`` node would create the same file as the original file. Such file comparison mismatches generate errors unless the problem involves only leading whitespace for non-strict languages. Whenever a mismatch occurs the first non-matching line is printed.

File comparison mismatches can arise for several reasons:

1. Bugs in the import parsers. Please report any such bugs immediately.

2. Underindented lines in classes, methods or function.

.. index::
    pair: Underindented line; Reference

An **underindented line** is a line of body text that is indented less then the starting line of the class, method or function in which it appears. Leo outlines can not represent such lines exactly: every line in an external file will have at least the indentation of any unindented line of the corresponding node in the outline. Leo will issue a warning (not an error) for underindented Python comment lines. Such lines can not change the meaning of Python programs.
</t>
<t tx="ekr.20160410103017.1">**Section names** have the form::

    &lt;&lt; any text, except double closing angle brackets &gt;&gt;

**Section-definition nodes** have headlines starting with a section name.

Leo performs **expansions** for all @&lt;file&gt; nodes except @asis.

Expansion of @all:

- Leo replaces @all by the *unexpanded* body text of *all* nodes.

Expansion of section names and @others:

- Leo replaces section names in body text by the *expanded*
  text of the corresponding section definition node.

- Leo replaces @others with the *expanded* text of all nodes
  that *aren't* section-definition nodes.
</t>
<t tx="ekr.20160415031743.21">Start your file with::

    '''
    &lt;&lt; docstring &gt;&gt;
    '''

The &lt;&lt; docstring &gt;&gt; section can just contain::

    @language rest # or md
    @wrap
    @others

This allows the "interior" of the docstring to be colored using rST (or markdown).
The children of the &lt;&lt; docstring &gt;&gt; node form the actual docstring. No section names are required!

This pattern organizes large docstrings in a Leonine way. The only drawback is that the actual external file contains sentinel lines separating the parts of the docstring. In practice, it's no big deal, especially if each child starts with a blank line.
</t>
<t tx="ekr.20160417112500.1"></t>
<t tx="ekr.20160417112511.1">Leo 5.3-final released May 2, 2016.

- Leo now supports Jupyter Notebook (.ipynb) files.
- @chapter is now allowed anywhere. No need for @chapters.
- Faster spell checking.
- The rst3 command supports @rst-table.
- The show-invisibles command now uses native Qt characters.
</t>
<t tx="ekr.20160417112540.32">- Added clean-at-clean-files and clean-at-clean-tree commands.
- Added python-to-coffeescript command.
- Better defaults for open/save file dialogs.
- Improved clone-find commands.
- Improved kill &amp; yank commands.</t>
<t tx="ekr.20160417112540.33">- The livecode plugin is enabled by default, provided that the [meta]
  (https://pypi.python.org/pypi/meta) package is available.

- The viewrendered3 plugin is intended to replace the VR1 and VR2 plugins.</t>
<t tx="ekr.20160428104050.1">The **clone find** commands, cfa and cff,  move clones of all nodes matching the search pattern under a single **organizer node**, created as the last top-level node. **Flattened** searches put all nodes as direct children of the organizer node::

    cfa     clone-find-all
    cff     clone-find-all-flattened

The **clone-marked** commands move clones of all marked nodes under an organizer node. Especially useful for gathering nodes by hand::

    cfam    clone-find-marked 
    cffm    clone-find-flattened-marked
</t>
<t tx="ekr.20160428105918.1">Leo's pylint command hangs Leo while it is running. The top-level leo-editor folder contains pylint-leo.py and pylint-leo-rc.txt. To run pylint outside of Leo, create a .bat or .sh file to run leo-editor/pylint-leo.py. On Windows, I use this pylint.bat file::

    python2 c:\leo.repo\leo-editor\pylint-leo.py ^
    rc=c:\leo.repo\leo-editor\leo\test\pylint-leo-rc.txt %*

The -h option produces this::

    Usage: pylint-leo.py [options]

    Options:
      -h, --help   show this help message and exit
      -a           all
      -c           core
      -e           external
      -f FILENAME  filename, relative to leo folder
      -g           gui plugins
      -m           modes
      -p           plugins
      -s           silent
      -u           user commands
      -v           report pylint version

My typical usage is pylint -a -s
</t>
<t tx="ekr.20160428110816.1">The **clone find** commands, cfa and cff,  move clones of all nodes matching the search pattern under a single **organizer node**, created as the last top-level node. **Flattened** searches put all nodes as direct children of the organizer node::

    cfa     clone-find-all
    cff     clone-find-all-flattened

The **clone-marked** commands move clones of all marked nodes under an organizer node. Especially useful for gathering nodes by hand::

    cfam    clone-find-marked 
    cffm    clone-find-flattened-marked

The `clone-find-parents` command creates clones of all parent nodes of c.p.

The `clone-find-tag` aka ``(cft)`` command creates clones of all nodes having a given tag.

The `tag-children` applies a given tag to all the children of the selected node.
</t>
<t tx="ekr.20160428111506.1">The body text contains a list of commands, one per line, to be preloaded into Leo's command history. You access command history using the up and down arrow keys in Leo's minibuffer.</t>
<t tx="ekr.20160428113347.1">The **clone find** commands, cfa and cff are extraordinarily useful. These commands move clones of all nodes matching the search pattern under a single **organizer node**, created as the last top-level node. **Flattened** searches put all nodes as direct children of the organizer node::

    cfa     clone-find-all
    cff     clone-find-all-flattened

The **clone-marked** commands move clones of all marked nodes under an organizer node. Especially useful for gathering nodes by hand::

    cfam    clone-find-marked 
    cffm    clone-find-flattened-marked
</t>
<t tx="ekr.20160430063406.1">def revertCommander(self, c):
    '''Revert c to the previously saved contents.'''
    lm = self
    fn = c.mFileName
    # Re-read the file.
    theFile = lm.openLeoOrZipFile(fn)
    if theFile:
        c.fileCommands.initIvars()
        c.fileCommands.getLeoFile(theFile, fn, checkOpenFiles=False)
            # Closes the file.
</t>
<t tx="ekr.20160718072648.1">def setStdStreams(self):
    '''
    Make sure that stdout and stderr exist.
    This is an issue when running Leo with pythonw.exe.
    '''
    # pdb requires sys.stdin, which doesn't exist when using pythonw.exe.
    # import pdb ; pdb.set_trace()
    import sys
    import leo.core.leoGlobals as g

    # Define class LeoStdOut
    @others

    if not sys.stdout:
        sys.stdout = sys.__stdout__ = LeoStdOut('stdout')
    if not sys.stderr:
        sys.stderr = sys.__stderr__ = LeoStdOut('stderr')
</t>
<t tx="ekr.20160718091844.1">class LeoStdOut:
    '''A class to put stderr &amp; stdout to Leo's log pane.'''

    def __init__(self, kind):
        self.kind = kind
        g.es_print = self.write
        g.pr = self.write

    def flush(self, *args, **keys):
        pass

    @others
</t>
<t tx="ekr.20160718102306.1">def write(self, *args, **keys):
    '''Put all non-keyword args to the log pane, as in g.es.'''
    trace = False
        # Tracing will lead to unbounded recursion unless
        # sys.stderr has been redirected on the command line.
    if trace:
        for z in args:
            sys.stderr.write('arg: %r\n' % z)
        for z in keys:
            sys.stderr.write('key: %r\n' % z)
    app = g.app
    if not app or app.killed: return
    if app.gui and app.gui.consoleOnly: return
    log = app.log
    # Compute the effective args.
    d = {
        'color': None,
        'commas': False,
        'newline': True,
        'spaces': True,
        'tabName': 'Log',
    }
    # Handle keywords for g.pr and g.es_print.
    d = g.doKeywordArgs(keys, d)
    color = d.get('color')
    if color == 'suppress': return
    elif log and color is None:
        color = g.actualColor('black')
    color = g.actualColor(color)
    tabName = d.get('tabName') or 'Log'
    s = g.translateArgs(args, d)
    if app.batchMode:
        if log:
            log.put(s)
    elif log and app.logInited:
        # from_redirect is the big difference between this and g.es.
        log.put(s, color=color, tabName=tabName, from_redirect=True)
    else:
        app.logWaiting.append((s, color),)
</t>
<t tx="ekr.20161014050133.1">The following shows how to cut and paste text to the clipboard:

.. code-block:: python

    g.app.gui.replaceClipboardWith('hi')
    print(g.app.gui.getTextFromClipboard())
</t>
<t tx="ekr.20161014053105.1"></t>
<t tx="ekr.20161014053127.1">New Commands

- The clone-find commands are a new way to use Leo.
- The clone-find and tag-all-children commands unify clones and tags.
- The pyflakes and flake8 make it possible to check files from within Leo.

Importers

- Added importers for freemind, mindjet, json and coffeescript files.
- Rewrote the javascript importer.
  It can optionally generate section references.
- Imported files can optionally contain section references.

Plugins

- Improved the mod_http plugin.
- The viewrendered plugin supports @pyplot nodes.

All known bugs have been fixed.</t>
<t tx="ekr.20161014053707.1">Added these commands:

- The **extremely important** clone-find commands:

    - clone-find-all (cfa)
    - clone-find-all-flattened (cfaf)
    - clone-find-all-flattened-marked (cffm)
    - clone-find-all-marked (cfam)
    - clone-find-parents
    - clone-find-tag (cft)

- copy-marked
- diff-marked-nodes
- flake8
- import-MORE-files
- import-tabbed-files
  https://groups.google.com/forum/#!topic/leo-editor/qx0okNbjWUk
- pyflakes
- tag-children

The pylint and pyflakes commands now write to Leo's log window, as well as the console.

Improved the clone-marked/copy-marked/move-marked commands.

Removed all static abbrev commands.
Removed all chapter-* commands except the chapter-select and chapter-select-main commands.
</t>
<t tx="ekr.20161014054015.1">- Added installer for file associations.
- Added ``File:Import`` submenu.
- Leo now colorizes basestring, @staticmethod &amp; @classmethod.
- Added dialog when creating myLeoSettings.leo automatically.
- Added support for auto-justified body text.
- Added @button import-tab-files to scripts.leo:
  https://groups.google.com/forum/#!topic/leo-editor/YcT7SOSYEQk
- @chapter trees need no longer be children of @chapters nodes.
- Fixed bug in NSIS installer.
  The old code failed to find Python installations in the 64-bit Windows registry.</t>
<t tx="ekr.20161014054147.1">Added the following settings:

- @bool check_for_changed_external_files
- @bool open_with_save_on_update
- @bool plain-key-outline-search
- @bool run-pyflakes-on-write
- @bool show-iconbar
- @int autojustify
- @int qweb_view_font_size
</t>
<t tx="ekr.20161020064204.1">``flake8``
    Run flake8 on all nodes of the selected tree, or the first ancestor @&lt;file&gt; node.
``pyflakes``
    Runs pyflakes on the Python source files in the selected tree, or the first ancestor @&lt;file&gt; node. Prints results in the console window and Leo's log pane.
``pylint``
    Runs pylint on the Python source files in the selected tree, or the first ancestor @&lt;file&gt; node. This command is also available from the popup menus created by the contextmenu plugin.

</t>
<t tx="ekr.20161020064436.1">``check-derived-file``
    Makes sure an external file written by Leo can be read properly. 
``check-leo-file``
    Performs a full check of the consistency of a .leo file.  As of Leo 5.1, Leo performs checks of gnx's and outline structure before writes and after reads, pastes and undo/redo.
``check-outline``
    Checks the outline for consistency. Leo automatically checks the syntax of Python external files when Leo writes the external file.
``clear-all-caches``
    Clear all file caches in g.app.leoHomeDir/db
``clear-cache``
    Clear the outline's file cache.
``escape``
    Enter watch escape mode.
``find-long-lines``
    Report lines longer than specified by:
    ``@bool max-find-long-lines-length = 110``
``find-missing-docstrings``
    Report python classes, functions and methods lacking python docstrings.
    Does not report nodes that are descendants of ``@nopylint``.
``pdb``
    Drops into debugger, in the middle of the command-handling logic. Get the commander by stepping out into k.masterKeyHandler or k.masterCommandHandler. Using c, one can then get all other info.
``show-buttons``
    Show all ``@button`` and ``@command`` commands, their bindings and their source.

Dumping Leo's internal data::

    dump-all-objects
    dump-new-objects
    dump-outline
    verbose-dump-objects

Python's garbage collector::

    gc-collect-garbage
    gc-dump-all-objects
    gc-dump-objects-verbose
    gc-show-summary
    gc-trace-disable
    gc-trace-enable

Idle time::

    disable-idle-time-events
    enable-idle-time-events
    toggle-idle-time-events

``print-window-state``
    This command is for Leo's developers.

</t>
<t tx="ekr.20161020064706.1">The following print information to Leo's log pane::

    show--bindings
    show--commands
    show--focus
    show--plugin-handlers
    show--plugins-info
    show--settings
    show--style-sheet
    show-colors
    show-find-options</t>
<t tx="ekr.20161026122804.1">class IdleTimeManager(object):
    '''
    A singleton class to manage idle-time handling. This class handles all
    details of running code at idle time, including running 'idle' hooks.

    Any code can call g.app.idleTimeManager.add_callback(callback) to cause
    the callback to be called at idle time forever.
    '''

    def __init__(self):
        '''Ctor for IdleTimeManager class.'''
        self.callback_list = []
        self.timer = None

    @others
</t>
<t tx="ekr.20161026124810.1">on_idle_count = 0

def on_idle(self, timer):
    '''IdleTimeManager: Run all idle-time callbacks.'''
    if not g.app: return
    if g.app.killed: return
    self.on_idle_count += 1
    # Handle the registered callbacks.
    for callback in self.callback_list:
        try:
            callback()
        except Exception:
            g.es_exception()
            g.es_print('removing callback: %s' % callback)
            self.callback_list.remove(callback)
    # Handle idle-time hooks.
    g.app.pluginsController.on_idle()
</t>
<t tx="ekr.20161026125611.1">def add_callback(self, callback):
    '''Add a callback to be called at every idle time.'''
    self.callback_list.append(callback)
</t>
<t tx="ekr.20161028034808.1">def start (self):
    '''Start the idle-time timer.'''
    self.timer = g.IdleTime(
        self.on_idle,
        delay=500,
        tag='IdleTimeManager.on_idle')
    if self.timer:
        self.timer.start()
</t>
<t tx="ekr.20161028035755.1">self.batchMode = False
    # True: run in batch mode.
self.debug = False
    # True: run Leo in debug mode.
self.diff = False
    # True: run Leo in diff mode.
self.enablePlugins = True
    # True: run start1 hook to load plugins. --no-plugins
self.gui = None
    # The gui class.
self.guiArgName = None
    # The gui name given in --gui option.
self.ipython_inited = False
    # True if leoIpython.py imports succeeded.
self.qt_use_tabs = False
    # True: allow tabbed main window.
self.silentMode = False
    # True: no signon.
self.start_fullscreen = False
    # For qt_frame plugin.
self.start_maximized = False
    # For qt_frame plugin.
self.start_minimized = False
    # For qt_frame plugin.
self.trace_plugins = False
    # True: trace imports of plugins.
self.translateToUpperCase = False
    # Never set to True.
self.useIpython = False
    # True: add support for IPython.
self.use_psyco = False
    # True: use psyco optimization.
self.use_splash_screen = True
    # True: put up a splash screen.
</t>
<t tx="ekr.20161028035835.1">self.count = 0
    # General purpose debugging count.
self.debug_app = False
    # True: Enable debugging (of widgets)
self.debug_dict = {}
    # For general use.
self.debug_widgets = False
    # True: enable verbose tracing of widgets.
self.debugSwitch = 0
    # For g.es_exception: 0: Brief; 1: Full.
self.disable_redraw = False
    # True: disable all redraws.
self.disableSave = False
    # May be set by plugins.
self.idle_timers = []
    # A list of IdleTime instances, so they persist.
self.positions = 0
    # The number of positions generated.
self.scanErrors = 0
    # The number of errors seen by g.scanError.
self.structure_errors = 0
    # Set by p.safeMoveToThreadNext.
self.statsDict = {}
    # dict used by g.stat, g.clear_stats, g.print_stats.
self.trace_open_with = True
    # True: trace open-with logic in core and vim and xemacs plugins.
self.trace_shutdown = False
    # True: trace shutdown logic.
self.validate_outline = False
    # True: enables c.validate_outline. (slow)
</t>
<t tx="ekr.20161028035902.1">self.atPathInBodyWarning = None
    # Set by get_directives_dict.
self.menuWarningsGiven = False
    # True: suppress warnings in menu code.
self.unicodeErrorGiven = True
    # True: suppress unicode tracebacks.
</t>
<t tx="ekr.20161028035924.1">self.extensionsDir = None
    # The leo/extensions directory
self.globalConfigDir = None
    # leo/config directory
self.globalOpenDir = None
    # The directory last used to open a file.
self.homeDir = None
    # The user's home directory.
self.homeLeoDir = None
    # The user's home/.leo directory.
self.loadDir = None
    # The leo/core directory.
self.machineDir = None
    # The machine-specific directory.
</t>
<t tx="ekr.20161028035956.1">self.atAutoNames = set()
    # The set of all @auto spellings.
self.atFileNames = set()
    # The set of all built-in @&lt;file&gt; spellings.
self.globalKillBuffer = []
    # The global kill buffer.
self.globalRegisters = {}
    # The global register list.
self.leoID = None
    # The id part of gnx's.
self.lossage = []
    # List of last 100 keystrokes.
self.paste_c = None
    # The commander that pasted the last outline.
self.spellDict = None
    # The singleton PyEnchant spell dict.
self.numberOfUntitledWindows = 0
    # Number of opened untitled windows.
self.windowList = []
    # Global list of all frames.
self.realMenuNameDict = {}
    # Translations of menu names.
</t>
<t tx="ekr.20161028040028.1"># Most of these are defined in initApp.
self.backgroundProcessManager = None
    # The singleton BackgroundProcessManager instance.
self.config = None
    # The singleton leoConfig instance.
self.db = None
    # The singleton leoCacher instance.
self.externalFilesController = None
    # The singleton ExternalFilesController instance.
self.idleTimeManager = None
    # The singleton IdleTimeManager instance.
self.ipk = None
    # python kernel instance
self.loadManager = None
    # The singleton LoadManager instance.
# self.logManager = None
    # The singleton LogManager instance.
# self.openWithManager = None
    # The singleton OpenWithManager instance.
self.nodeIndices = None
    # The singleton nodeIndices instance.
self.pluginsController = None
    # The singleton PluginsManager instance.
# The Commands class...
self.commandName = None
    # The name of the command being executed.
self.commandInterruptFlag = False
    # True: command within a command.
</t>
<t tx="ekr.20161028040054.1">self.already_open_files = []
    # A list of file names that *might* be open in another
    # copy of Leo.
self.dragging = False
    # True: dragging.
self.allow_delayed_see = False
    # True: pqsh.reformat_blocks_helper calls w.seeInsertPoint
self.inBridge = False
    # True: running from leoBridge module.
self.inScript = False
    # True: executing a script.
self.initing = True
    # True: we are initing the app.
self.killed = False
    # True: we are about to destroy the root window.
self.openingSettingsFile = False
    # True, opening a settings file.
self.preReadFlag = False
    # True: we are pre-reading a settings file.
self.quitting = False
    # True: quitting.  Locks out some events.
self.reverting = False
    # True: executing the revert command.
self.syntax_error_files = []
</t>
<t tx="ekr.20161028040141.1"># To be moved to the LogManager.
self.log = None
    # The LeoFrame containing the present log.
self.logInited = False
    # False: all log message go to logWaiting list.
self.logIsLocked = False
    # True: no changes to log are allowed.
self.logWaiting = []
    # List of messages waiting to go to a log.
self.printWaiting = []
    # Queue of messages to be sent to the printer.
self.signon = ''
self.signon2 = ''
self.signon_printed = False
</t>
<t tx="ekr.20161028040204.1">import leo.core.leoFrame as leoFrame
import leo.core.leoGui as leoGui
self.nullGui = leoGui.NullGui()
self.nullLog = leoFrame.NullLog()
</t>
<t tx="ekr.20161028040229.1">self.hookError = False
    # True: suppress further calls to hooks.
    # g.doHook sets g.app.hookError on all exceptions.
    # Scripts may reset g.app.hookError to try again.
self.hookFunction = None
    # Application wide hook function.
self.idle_time_hooks_enabled = True
    # True: idle-time hooks are enabled.
</t>
<t tx="ekr.20161028040303.1">self.searchDict = {}
    # For communication between find/change scripts.
self.scriptDict = {}
    # For use by scripts. Cleared before running each script.
self.scriptResult = None
    # For use by leoPymacs.
self.permanentScriptDict = {}
    # For use by scrips. Never cleared automatically.
</t>
<t tx="ekr.20161028040330.1">self.isExternalUnitTest = False
    # True: we are running a unit test externally.
self.runningAllUnitTests = False
    # True: we are running all unit tests (Only for local tests).
self.suppressImportChecks = False
    # Used only in basescanner.py
    # True: suppress importCommands.check
self.unitTestDict = {}
    # For communication between unit tests and code.
self.UnitTestGui = None
    # A way to override the gui in external unit tests.
self.unitTesting = False
    # True if unit testing.
self.unitTestMenusDict = {}
    # Created in LeoMenu.createMenuEntries for a unit test.
    # keys are command names. values are sets of strokes.
</t>
<t tx="ekr.20161029072351.1">It is dead easy for scripts, including @button scripts, plugins, etc., to drive any external processes, including compilers and interpreters, from within Leo.

- The first section discusses three ways of calling subprocess.popen directly or via Leo helper functions.

- The second section discusses the BackgroundProcessManager class.  Leo's pylint command uses this class to run pylint commands sequentially *without blocking Leo*. Running processes sequentially prevents unwanted interleaving of output.

- The last two sections discuss using g.execute_shell_commands and g.execute_shell_commands_with_options. </t>
<t tx="ekr.20161120073024.1">@language md

These .md files are intended to be viewed on [GitHub](https://github.com/leo-editor/leo-editor/tree/master/leo/doc).

[This page](https://github.com/leo-editor/leo-editor/blob/master/leo/doc/importers.md) contains the cheat sheet for the GitHub flavor of markdown.
</t>
<t tx="ekr.20161120074501.1">##### No longer needed
##### The markdown writer converts headlines to markdown sections,
##### ignoring headlines that start with !
'''Create markdown headers throughout the nearest .md outline.'''
g.cls()
import re
@others

def predicate(p):
    return p.isAnyAtFileNode() and p.h.strip().endswith('.md')

for root in c.all_unique_roots(predicate):
    print(root.h)
    for p in root.self_and_subtree():
        markup(p, root)
c.redraw()

@language python
@tabwidth -4</t>
<t tx="ekr.20161120075731.1"># In @button make-md-heads

pattern = re.compile(r'^(#+\s+)(.*)$')

def markup(p, root):
    '''prepend p.b[0] with markdown section markup, if appropriate.'''
    root_level = root.level()
    lines = g.splitLines(p.b)
    if len(lines) &lt; 2: return
    line0, line1 = lines[0], lines[1]
    if (
        not p.h.startswith('@md-ignore') and
        not line0.isspace() and # A real first line.
        not line0.startswith('@') and # Not a directive
        line1.isspace() # the next line is blank
    ):
        # Remove existing markup.
        m = pattern.match(line0)
        if m:  line0 = m.group(2) + '\n'
        # Add the correct markup.
        hashes = '#'*(p.level()-root_level+1)
        lines[0] = '%s %s' % (hashes, line0)
    # Ensure a blank line, so as not to interfere with later headers.
    s = ''.join(lines).rstrip()+'\n\n'
    if p.b != s:
        g.es_print('changed: %s' % (p.h))
        p.setDirty()
        c.setChanged()
        p.b = s
</t>
<t tx="ekr.20161204055040.1">'''Make a markdown table of contents for an @auto-md node.'''
g.cls()
if c.isChanged(): c.save()

class Controller:
    '''Controller class for @button md-toc.'''
    @others

if 0:
    h = '@auto-md importers.md'
    p = g.findTopLevelNode(c, h)
    g.es_print('not found at top level:', h)
elif c.p.h.startswith('@auto-md'):
    p = c.p
else:
    g.es_print('not @auto-node:', c.p.h)
    p = None
if p:
    Controller().run(p)
@language python
@tabwidth -4
</t>
<t tx="ekr.20161204055436.1">def run(self, p):
    '''The driver for @button md-toc.'''
    if p.h.startswith('@auto-md '): #  or p.h.endswith('.md'):
        last = c.lastTopLevel()
        self.root = last.insertAfter()
        self.root.h = 'Table of contents'
        self.make_toc(p)
    else:
        print('must be an @auto-md node or an x.md node: %s' % p.h)
</t>
<t tx="ekr.20161204055804.1">def make_toc(self, p):
    '''Create the toc in self.root.b.'''
    result, stack = [], []
    prefix = p.h.lstrip('@auto-md').strip()
    for p in p.subtree():
        level = p.level() - self.root.level()
        assert level &gt; 0
        if len(stack) &lt; level:
            stack.append(1)
        else:
            stack = stack[:level]
        n = stack[-1]
        stack[-1] = n+1
        indent = ' '*4*(level-1)
        if 1: # Use bullets
            line = '%s- [%s](%s#%s)\n' % (
                indent, p.h, prefix, self.make_link(p.h))
        else: # Use numbers.
            line = '%s%s. [%s](%s#%s)\n' % (
                indent, n, p.h, prefix, self.make_link(p.h))
        result.append(line)
    if 0:
        g.trace(p.h)
        g.printList(result)
    else:
        self.root.b = ''.join(result)
    c.selectPosition(self.root)
    c.redraw()
</t>
<t tx="ekr.20161204060843.1">def make_link(self, s):
    '''Return the markdown link for s.'''
    result = []
    for ch in s.lower():
        if ch in ' -':
            result.append('-')
        elif ch.isalnum():
            result.append(ch)
        else:
            pass
    return ''.join(result)</t>
<t tx="ekr.20161207052511.1">Let us think of lessons not as explanations, but as puzzles to be solved by the student. The puzzles themselves need no lengthy explanations. They can even be cryptic. This attitude arises from two principles:

1. The less said, the better.
2. Invite people to learn for themselves.

**Pick something that interests you**

Pick a real, worthy, programming task that you (the student) personally want/need to do in Leo. *This step is essential*! It is *useless* to try to learn in a vacuum.

EKR's first python program was C2Py. leoAttic.txt contains the original version. Leo's c-to-python commands contained revised code.

**Overcome fear of crashes and mistakes**

- Run Leo from a console.
- Single-step through your code with g.pdb()
- Deliberately put a crasher in your code and see what happens.

The only way to hard crash Leo is to pass bad pointers to PyQt. Python should catch all other problems. If it doesn't, report a bug to the python people ;-)

**Discover how Leo's code works**

- Where is Leo's source code? Hint: look for leoPy.leo in LeoDocs.leo.
- Look at Leo's demote command.
  - What are three ways of finding the demote command?
  - How does demote change the outline?
  - How does demote handle undo?
- Study any other Leo command that relates to your project.
- Use the cff command to find all definitions of x.
- Use the cff command to find all uses of x.

**Start using Leo for real**

- Add a new command using @button.
- Create an external file containing your real-world project.
  Execute it outside of Leo.
- Write a Leo plugin.
- Advanced: fix one of Leo's bugs.

**Attitude**

Students should always feel free to ask for help, but struggle teaches us the most. **It doesn't matter how long it takes to learn something**. In our culture, we value quickness. But that is a trap. All learning builds momentum:

- Put 10 units of effort in, get 1 unit of results out.
- Put 1 in, get 1 out.
- Put 1 in, get 10 out.

There is no other way! How many times have we given up just because things were not easy or clear at first?

**That which we learn, we learn by doing**

Reading about (and thinking about) are useful, but not good enough. That is why students must have a project that is important to them.  The project will put them into action.</t>
<t tx="ekr.20170123084609.11"></t>
<t tx="ekr.20170123084609.12"> File "c:\leo.repo\leo-editor\leo\core\leoKeys.py", line 414, in auto_completer_state_handler
    kind), color='red')
TypeError: putStatusLine() got an unexpected keyword argument 'color'
</t>
<t tx="ekr.20170123084609.13"></t>
<t tx="ekr.20170123084609.14">https://github.com/leo-editor/leo-editor/issues/325
</t>
<t tx="ekr.20170123084609.16"></t>
<t tx="ekr.20170123084609.17">https://github.com/leo-editor/leo-editor/issues/348
XML CDATA Sections not preserved on round-trip save
</t>
<t tx="ekr.20170123084609.18"></t>
<t tx="ekr.20170123084609.19">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).
</t>
<t tx="ekr.20170123084609.20">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.
</t>
<t tx="ekr.20170123084609.22"></t>
<t tx="ekr.20170123084609.24">Enabled using @bool run-pyflakes-on-write = True
</t>
<t tx="ekr.20170123084609.25"></t>
<t tx="ekr.20170123084609.26">Leo no longer hangs waiting for this command to finish.
https://github.com/leo-editor/leo-editor/issues/328
</t>
<t tx="ekr.20170123084609.27"></t>
<t tx="ekr.20170123084609.28">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.
    '''
</t>
<t tx="ekr.20170123084609.29"></t>
<t tx="ekr.20170123084609.30">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.

2. 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.
</t>
<t tx="ekr.20170123084609.8"></t>
<t tx="ekr.20170123084609.9">A recent in doPlainChar change to handle #14 ruined bracket matching.
</t>
<t tx="ekr.20170123084701.1">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.
</t>
<t tx="ekr.20170123085934.1">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](https://github.com/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**

- [Leo's home page](https://leo-editor.github.io/leo-editor/)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md
</t>
<t tx="ekr.20170123090348.1"></t>
<t tx="ekr.20170123090814.1"></t>
<t tx="ekr.20170123090841.2">- Optionally run pyflakes when saving files.
- Fixed huge performance bug in syntax coloring. The horrible big text hack is no longer needed.
- Leo no longer hangs waiting for the pylint command to finish.
</t>
<t tx="ekr.20170123090841.22">- Added four new generators: c.all_roots, c.all_unique_roots, p.nearest_roots and p.nearest.
- Created singleton BackgroundProcessManager
- Integrated idle-hook processing into the IdleTimeManager
</t>
<t tx="ekr.20170123090841.26">- You can open all important .leo files from the File menu.
- &lt;Alt-X&gt;99 is the same as &lt;Alt-G&gt;99.
- Script abbreviations are allowed in headlines.
- The markdown importer now regularizes sections.</t>
<t tx="ekr.20170123090841.6">- at-button make-importer
  Make a new @@file importers/x.py file.
- at-button make-md-heads
  Create markdown headers throughout the nearest .md outline.
- at-button make-md-toc
  Make a markdown table of contents from an @auto-md node.
- at-button make-table
  Create a table of expected headlines in a unit test.
</t>
<t tx="ekr.20170123152852.1">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170124014606.1">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170124015707.1">https://github.com/leo-editor/leo-editor/issues/374
This caused problems in the importers.</t>
<t tx="ekr.20170124020217.1">https://github.com/leo-editor/leo-editor/issues/334
This was a large project.  See the issue tracker for extensive notes.

Full documentation is here:
https://github.com/leo-editor/leo-editor/blob/master/leo/doc/importers.md

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.
</t>
<t tx="ekr.20170124024347.1">https://github.com/leo-editor/leo-editor/issues/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
                    &lt;Return&gt; or (sometimes) &lt;tab&gt;.

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.
</t>
<t tx="ekr.20170124034150.1">https://groups.google.com/d/msg/leo-editor/RDi2jffWjzI/K-mh4H5QBQAJ

https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170203060220.1">The scripting tutorial contains a few more examples before jumping into the details.</t>
<t tx="ekr.20170205185641.10">https://github.com/leo-editor/leo-editor/issues/389

See the checkin log for details.
</t>
<t tx="ekr.20170205185641.11">https://github.com/leo-editor/leo-editor/issues/395</t>
<t tx="ekr.20170205185641.12">https://github.com/leo-editor/leo-editor/issues/396

https://stackoverflow.com/questions/3254652/
several-ways-of-placing-an-image-in-a-qtextedit</t>
<t tx="ekr.20170205185641.2">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.
</t>
<t tx="ekr.20170205185641.3">https://github.com/leo-editor/leo-editor/issues/257

</t>
<t tx="ekr.20170205185641.4">https://github.com/leo-editor/leo-editor/issues/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. 
</t>
<t tx="ekr.20170205185641.5">https://github.com/leo-editor/leo-editor/issues/371

The fix was to extractExecutableString
</t>
<t tx="ekr.20170205185641.6">https://github.com/leo-editor/leo-editor/issues/375
</t>
<t tx="ekr.20170205185641.7">https://github.com/leo-editor/leo-editor/issues/380
New colorizing code doesn't update properly after changing @language directives. 
</t>
<t tx="ekr.20170205185641.8">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170205185641.9">https://github.com/leo-editor/leo-editor/issues/388</t>
<t tx="ekr.20170205190147.1">https://github.com/leo-editor/leo-editor/issues/392
</t>
<t tx="ekr.20170205201047.1">It can now import demo-it.el.</t>
<t tx="ekr.20170206073747.9">.. .. https://groups.google.com/group/leo-editor/browse_thread/thread/92ae059cc5213ad3

Many thanks to Ludwig Schwardt for the following installation instructions. Using the HomeBrew installation method is *much* easier than before.

**Note from EKR**: When upgrading MacOS, it's probably a good idea to uninstall pyqt, sip and qt first::

    brew remove pyqt sip qt
    brew install qt sip pyqt

I (Ludwig) recently received a new MacBook Pro and did a fresh upgrade to Mac OS 10.7 (Lion). I then used the opportunity to test out installation procedures of various software on a clean system. My main finding is that the excellent Homebrew (mxcl.github.com/homebrew/) makes things much easier these days.

Why Homebrew? It does not try to replace every single bit of functionality on your Mac with their own version, like Macports or fink. It reuses the existing libraries as far as possible. No need to reinstall Python, for example (one of my pet gripes when people try to install new software on their Macs, and the source of much confusion and pain). It installs to /usr/local, the standard place to find third-party libraries and headers, instead of the obscure /opt or /sw. It's simple to use and to extend.

Here is my installation write-up:

- Read the Homebrew installation instructions at https://brew.sh/.

- Make sure you have Xcode installed (test it by confirming that "gcc" runs in the Terminal) Only the smaller command-line tools are required; there is no need to get the full Xcode beast.

- In preparation for Homebrew, the best option in my opinion is to delete /usr/local via::

    sudo rm -rf /usr/local

  and install any software in it via HomeBrew instead.

  The HomeBrew package manager is so easy to use that you will find replacing deleted packages a snap.

  If deleting /usr/local fills you with dread (you do not want to lose your beloved third-party software), the second-best option is to make sure you have write permission for the directory via::

    sudo chown -R &lt;your user name&gt;:admin /usr/local

  If you don't know your username, run "whoami". :-) This is useful because homebrew actually discourages you from installing third-party software as the superuser (the usual Mac apps in /Applications are also installed as the normal user, for that matter).

- Install Homebrew. See the instructions at https://brew.sh/.

- Run "brew doctor" and check any further suggestions to improve your system.

  EKR note: I thought I had installed command-line tools after installing the XCode page. I hadn't, and "brew doctor" told me so.

- Run "brew update" to get the latest formulas

- Install sip and note the caveat::

    brew install sip

  This warns you to add the local python directory to your PYTHONPATH.
  Make a note of what this is (especially if you are not on Lion!).

- Add the following lines to your ~/.bash_profile
  (or ~/.profile on Leopard). This is the default for LION::

      export PATH=/usr/local/bin:$PATH
      # This is for SIP (and PyQt) as suggested by Homebrew
      export PYTHONPATH=/usr/local/lib/python3.9/site-packages:$PYTHONPATH

- Install PyQt::

    brew install pyqt

- Open a new Terminal tab / window so that the above settings take effect, and install Leo. I downloaded the Leo-4.9-final-a.zip, unzipped it, and ran "python launchLeo.py" inside the Leo directory.

It would really be great to get a Leo formula going for Homebrew. As mentioned before, the main question is just where to place all the Leo files in the /usr/local hierarchy.
</t>
<t tx="ekr.20170206095132.1">https://github.com/leo-editor/leo-editor/issues/402

Added g.input_, but this is not a great solution.
</t>
<t tx="ekr.20170212105226.1">@language python
'''Create intro slides for screen shots.'''
# The *same* command/key binding calls both demo-start and demo.next.
if c.isChanged(): c.save()
g.cls()
&lt;&lt; imports &gt;&gt;
#
# Do NOT use @others here.
#
&lt;&lt; class IntroSlides &gt;&gt;
&lt;&lt; main &gt;&gt;
if getattr(g.app, 'demo', None):
    g.app.demo.next()
else:
    root = g.findTopLevelNode(c, '@button IntroSlides')
    demo = IntroSlides(c)
    main(c, demo,
        auto_run=False,
        hoist_node = "Leo's Main Window",
        root = root,
        script_name='intro-slides-script')</t>
<t tx="ekr.20170212105226.10">@language python
</t>
<t tx="ekr.20170212105226.11">@language python

# Doesn't work in the demo framework!
# w = QtWidgets.QFrame()
# w.show()
###

demo.set_top_size(height=400, width=700)
demo.set_ratios(0.5, 0.5)
geom = demo.pane_geometry('body')
table = (
    # (body, 'The Minibuffer (below)', 'center', geom.height()-25),
    ('body', 'The Body Pane'),
    ('tree', 'The Outline Pane'),
    ('log',  'The Log Pane'), # too low.
)
for pane, h in table:
    Callout(h, pane=pane) # , position=(x,y)
###
demo.set_top_size(height=500, width=800)
table = (
    (False, 0, '&lt;-- @file node', '@file leoApp.py'),
    (False, 0, '&lt;-- @test node', '@test init method'),
    (False, 2, '&lt;-- icon box', '@suite plugins syntax'),
)
for arrow, offset, label, headline in table:
    Head(arrow, label, headline, offset=offset)
w = Image(fn=demo.get_icon_fn('box01.png'),
    position=(20, 30), magnification=2)
Callout('&lt;-- An Icon',position=(20+w.width(), w.y()-3))
###
demo.next()</t>
<t tx="ekr.20170212105226.2"># from leo.core.leoQt import QtCore, QtGui
import leo.plugins.demo as demo_module
import imp
imp.reload(demo_module)</t>
<t tx="ekr.20170212105226.3">class IntroSlides (demo_module.Demo):

    @others
</t>
<t tx="ekr.20170212105226.4">@language python

def setup(self, p=None):
    c = self.c
    self.end_on_exception = True # Good for debugging.
    self.delta = 0
    self.ratios = self.get_ratios()
    self.set_text_delta(self.delta)
    if hasattr(self, 'hoist_node'):
        c.selectPosition(self.hoist_node)
        for child in self.hoist_node.children():
            if child.h. startswith('@@'):
                child.h = child.h[1:]
                child.clearDirty()
        c.hoist()
    self.set_top_geometry((400, 200, 700, 400),)
        # x, y, width, height, like QRect.
    c.redraw()
</t>
<t tx="ekr.20170212105226.5">def setup_script(self):
    self.delete_widgets()
</t>
<t tx="ekr.20170212105226.6">@language python

def teardown(self):
    c = self.c
    self.delete_all_widgets()
    if self.delta &gt; 0:
        self.set_text_delta(-self.delta)
    if self.hoist_node:
        for child in self.hoist_node.children():
            if child.h. startswith('@'):
                child.h = '@' + child.h
        c.dehoist()
        # c.selectPosition(self.hoist_node)
    p = g.findTopLevelNode(c, "Slide 1: Leo's main window")
    if p:
        c.selectPosition(p)
    ratio1, ratio2 = self.ratios
    self.set_ratios(ratio1, ratio2)
    c.contractAllHeadlines()
    c.clearChanged()
    c.redraw()
</t>
<t tx="ekr.20170212105226.7">def teardown_script(self):
    if self.auto_run:
        self.wait(0.5)</t>
<t tx="ekr.20170212105226.8">def main(c, demo, script_name, auto_run=False, hoist_node=None, root=None):
    k = c.k
    class_name = demo.__class__.__name__
    # c.frame.log.clearTab('Log')
    # g.es_print('Starting', class_name)
    k.demoNextKey = k.strokeFromSetting('Ctrl-9')
        # Tell k.masterKeyHandler to process Ctrl-9 immediately.
        # Binding demo-next in a setting does *not* work.
    h = '@button %s' % class_name
    p = g.findNodeAnywhere(c, h)
    assert p, h
    script_tree = g.findNodeInTree(c, p, script_name)
    assert script_tree, repr(script_name)
    demo.hoist_node = hoist_node and g.findNodeInTree(c, p, hoist_node)
    demo.start(script_tree, auto_run=auto_run, root=root)</t>
<t tx="ekr.20170212105226.9"></t>
<t tx="ekr.20170212113214.1">'''Imports all plugins or just tests their syntax,
depending on a switch in PluginTestCase.runTest.'''

import glob
import sys
import unittest

@others

suite = makePluginsTestSuite(c)

# g.app.scriptDict['suite'] = suite
</t>
<t tx="ekr.20170212113214.2">def makePluginsTestSuite(c):

    '''Create a plugin test for .py file in the plugins directory'''

    # Create the suite.
    suite = unittest.makeSuite(unittest.TestCase)

    # Add a test case for every plugin.
    paths = (
        g.os_path_join(g.app.loadDir,'..','plugins','*.py'),
        g.os_path_join(g.app.loadDir,'..','plugins','examples','*.py'),
    )
    all_files = []
    for path in paths:
        plugins = g.os_path_join(path)
        plugins = g.os_path_abspath(plugins)
        files = glob.glob(plugins)
        files = [g.os_path_abspath(f) for f in files]
        all_files.extend(files)
    all_files.sort()

    for fn in all_files:
        test = pluginTestCase(c,fn)
        suite.addTest(test)

    if 0:
        # Open a new window after all tests are completed.  Tests many plugins.
        lastTest = lastTestCase(c,openFlag=True)
        suite.addTest(lastTest)

    return suite
</t>
<t tx="ekr.20170212113214.3">class pluginTestCase(unittest.TestCase):

    '''A test case to test a single Leo plugin.'''

    @others
</t>
<t tx="ekr.20170212113214.4">def __init__ (self,c,path):

    # Init the base class.
    unittest.TestCase.__init__(self)

    self.c = c
    self.path = path
</t>
<t tx="ekr.20170212113214.5">def fail (self,msg=None):

    """Mark a unit test as having failed."""

    g.app.unitTestDict["fail"] = g.callerName(2)
</t>
<t tx="ekr.20170212113214.6">def runTest(self):

    trace = False
    c = self.c ; path = self.path
    path,base = g.os_path_split(path)
    fn = base[:-3]

    ignore = (
        # Read error.
        'chinese_menu',
        # Unfinished/absolute gui's.
        'gtkDialogs','gtkGui','ironPython','ironPythonGui',
        'swing_gui','tkGui','wxGui','temacs',
        # Tk-only.
        'ipython',
        # Imports path &amp; win32clipboard.
        'at_view',
        # Experimental.
        'stickynotes_plus',
        # Generated by unit tests.
        'pluginsTest',
        # Imports non-standard modules.
        'interact',         # import pexpect
        'jinjarender',      # import jinga2
        'leofeeds',         # import feedparser
    )

    if fn in ignore:
        return

    if trace: g.trace(fn)

    if 1:
        # Just check the syntax.  Doesn't pollute other unit tests.
        f = open(self.path,'r')
        s = f.read()
        f.close
        assert c.testManager.checkFileSyntax(fn,s,reraise=False,suppress=False)
    else: # Good for initial tests, but pollutes all other unit tests.
        exec('import leo.plugins.%s' % fn)

</t>
<t tx="ekr.20170212113214.7">def setUp(self):

    g.app.unitTestDict = {}
</t>
<t tx="ekr.20170212113214.8">def shortDescription (self):

    return "pluginTestCase: %s" % g.shortFileName(self.path)
</t>
<t tx="ekr.20170212113214.9">class lastTestCase(unittest.TestCase):

    '''A test case to print a message at the end of plugin tests.'''

    def __init__ (self,c,openFlag):
        # Init the base class.
        unittest.TestCase.__init__(self)
        self.c = c
        self.openFlag = openFlag

    def runTest(self):
        c = self.c
        print('\n%s a new window to test more plugin logic\n' % g.choose(
            self.openFlag,'opening','open'))
        if self.openFlag:
            self.new_c = new_c = c.new() # Create the new window.
            new_c.frame.setTitle("unit test for 'new' hook")

    if 0: # Doesn't work
        def shutDown(self):
            c = self.new_c
            c.close()
</t>
<t tx="ekr.20170212113230.1">'''Ensure all plugins have top-level init method *without* importing them.'''

import glob
import inspect

# Get a list of all plugins.
plugins = g.os_path_join(g.app.loadDir,'..','plugins','*.py')
plugins = g.os_path_abspath(plugins)
files = glob.glob(plugins)
files = [g.os_path_abspath(z) for z in files]
files = [z for z in files if not z.endswith('__init__.py')]
files.sort()

exclude = [
    # These are not real plugins...
    'baseNativeTree.py','leocursor.py',
    'qtGui.py',
    'qt_big_text.py',
    'qt_commands.py',
    'qt_events.py',
    'qt_frame.py',
    'qt_idle_time.py',
    'qt_main.py',
    'qt_quickheadlines.py',
    'qt_quicksearch_sub.py',
    'qt_text.py',
    'qt_tree.py',
    'qt_quicksearch.py',
    'swing_gui.py',
]

for fn in files:
    if not g.shortFileName(fn) in exclude:
        f = open(fn,'r')
        s = f.read()
        f.close()
        ok1 = s.find('def init():') &gt; -1
        ok2 = s.find('def init ():') &gt; -1
        assert ok1 or ok2,'fail: %s' % (fn)

</t>
<t tx="ekr.20170213112231.1"></t>
<t tx="ekr.20170213143631.1">from leo.core.leoQt import QtWidgets

w = QtWidgets.QFrame()
w.show()
g.app.permanentScriptDict ['stand-alone-frame'] = w
</t>
<t tx="ekr.20170215031129.1">.. _`full-featured outliner`: commands.html#outline-commands

Leo is a `full-featured outliner`_, with commands to insert, delete, move, hoist, promote and demote nodes.

**Clones** are a unique feature of Leo. Any outline node may be cloned. Cloned nodes are actually the *same* node, but they appear in different places in the outline. Changes to any clone affect all other clones of that node, *including their descendants*. For example, suppose the A` nodes are clones of each other::

    - A`
        - B
        - C
    - D
    - A`
        - B
        - C

Moving C right gives this outline::

    - A`
        - B
            - C
    - D
    - A`
        - B
            - C

.. _`clone-find commands`:

Clones allow you to create multiple views of data within a single outline. For example, Leo's `clone-find commands`_ create clones of all found nodes, moving the newly-created clones so they are all children of an **organizer node** describing the search. The organizer node is a new view of the outline's data, one focused on the found nodes!
</t>
<t tx="ekr.20170215075612.1">.. This is the table of contents for Leo's documentation.

Leo's Documentation Page
========================

.. |br| raw:: html

   &lt;br /&gt;

**Note**: the easiest way to search Leo's documentation is to search LeoDocs.leo.

.. _`Leo's forum`:          https://groups.google.com/g/leo-editor
.. _`Leo's home page`:      https://leo-editor.github.io/leo-editor/
.. _`Leo's Wikipedia page`: https://en.wikipedia.org/wiki/Leo_(text_editor)

`Leo's home page`_ |br|
`Leo's forum`_ |br|
`Leo's Wikipedia page`_

.. toctree::
    :maxdepth: 2

    Preliminaries           &lt;preliminaries&gt;
    Getting Started         &lt;getting-started&gt;
    Tutorials               &lt;tutorial&gt;
    Users Guide             &lt;usersguide&gt;
    Leo and other programs  &lt;leoandotherprograms&gt;
    Advanced Topics         &lt;intermediatetopics&gt;
    Appendices              &lt;appendices&gt;
    More links              &lt;toc-more-links&gt;
</t>
<t tx="ekr.20170215081358.1"></t>
<t tx="ekr.20170215082032.1">Non-programmers: feel free to skip this part.</t>
<t tx="ekr.20170215102815.1">.. New. In commands reference.</t>
<t tx="ekr.20170215103337.1"></t>
<t tx="ekr.20170215105125.1">.. _`Leo's Command Reference`: commands.html
.. _`Leo's minibuffer`: commands.html#executing-commands-from-the-minibuffer
.. _`typing completion`: commands.html#executing-commands-from-the-minibuffer
.. _`key bindings`: commands.html#key-reference
.. _`Emacs minibuffer`: https://www.gnu.org/software/emacs/manual/html_node/emacs/Minibuffer.html 

Leo has hundreds of commands, described in `Leo's Command Reference`_. **Very important**: You can (and should) ignore most of these commands at first. You execute commands using `key bindings`_ or *by name* in `Leo's minibuffer`_, similar to the `Emacs minibuffer`_.

You could type the full command name in the minibuffer, followed by the ``&lt;Return&gt;`` key to invoke the command, but that would be *way* too much work. Instead, you should use **typing completion** to avoid most typing. For example, you can execute the sort-lines commands this way::

    &lt;Alt-X&gt;so&lt;Tab&gt;

Now the minibuffer will list the common prefix of all commands that start with "so", namely::

    sort-

After typing l&lt;Tab&gt; the minibuffer will contain::

    sort-lines

Now, just type &lt;Return&gt; to execute the command.  Typing completion quickly becomes second nature.

**Very important**: There is no need to remember the exact names of Leo’s commands. Instead, you only need to remember a few common command prefixes, such as::

    clone-find  clone-find commands
    file-       file commands
    find-       find commands
    isearch-    incremental search commands
    leo-        open .leo files
    open-       open files or url's
    print-      print commands
    show-       show commands
    sort-       sort commands
    toggle-     toggle settings commands

The following commands pertain to the minibuffer itself:

``Alt-X (full-command)``
    Executes any other command by typing its full name.

``Ctrl-P (repeat-complex-command``
    Repeats the last command entered by name in the minibuffer.

The following keys have special meaning in the minibuffer:

``&lt;Return&gt;``
    Executes the command.

``&lt;Tab&gt;``
    Shows all valid completions.

``&lt;BackSpace&gt;``
    Shows more completions.

``Ctrl-G``
    Exits the minibuffer and puts the focus in the body pane.

``UpArrow``
    Moves backward through command history. The first ``UpArrow`` is the same as ``Ctrl-P``.

``DownArrow``
    Moves forward through command history.
</t>
<t tx="ekr.20170217093636.1">.. in tutorial-basics.html (Scripting basics)

Leo's markup applies to scripts as well as external files. Leo's execute-script command **composes** the script from the selected node, using Leo's markup. For example, this body text defines the top-level part of a script:

.. code-block:: python

    '''My script'''
    &lt;&lt; imports &gt;&gt;
    class Controller:
        # Child nodes define the methods of this class.
        @others
    Controller(c).run # c *is* defined.

Leo recognizes section references only if they appear *alone* on a line.  Therefore the following are *not* section references::

    # &lt;&lt; reference 1 &gt;&gt;
    " &lt;&lt; reference 2 &gt;&gt;
    a = b &lt;&lt; c &gt;&gt; 2;
</t>
<t tx="ekr.20170217093639.1">.. _`commander`: tutorial-basics.html#accessing-outline-data
.. _`position`: tutorial-scripting.html#positions-and-vnodes

The execute-script command pre-defines three names: c, g, and p. **c** is the `commander`_ of the outline in which the script executes. **g** is the ``leo.core.leoGlobals`` module, containing dozens of useful functions and classes.  **p** is the `position`_ of the presently selected node.
</t>
<t tx="ekr.20170217093640.1">The **Commander class** defines both a scripting API and a DOM (Document Object Module) giving *complete* access to all data in an outline.  For example:

.. code-block:: python

    """
        Print all headlines of the outline, properly indented,
        with the number of characters in each node's body text.
    """
    # c.all_positions() yields all positions, in outline order.
    # p.b is p's body text.
    # p.h is p's headline.

    for p in c.all_positions():
        level = ' ' * p.level()  # p.level() is p's indentation level.
        print(f"{len(p.b):3} {len(p.b)} {p.h}")

To run this script, put it in the body text of any node and do Ctrl-B, execute-script.

.. _`scripting tutorial`: tutorial-scripting.html

For more information, see Leo's `scripting tutorial`_.</t>
<t tx="ekr.20170217093640.2">.. index::
    pair: Script Button; Tutorial
    pair: @button Node; Tutorial
    pair: @command Node; Tutorial

**@command nodes** define a command. Running the command runs a script that can be applied to any outline node. That is, p is bound to the presently selected node, *not* the @button node. **@button nodes** work the same way, and also create a button in the icon area. Pressing that button runs the command. For example, this node defines the print-tree command bound to Ctrl-9:

.. code-block:: python

    @command print-tree @key=Ctrl-9 # in the headline

    """
        Print all headlines of the selected subtree, properly indented,
        with the number of characters in each node's body text.
    """
    # p.self_and_subtree() yields p, then all positions in p's subtree, in outline order.
    for p in c.all_positions():
        level = ' ' * p.level()  # p.level() is p's indentation level.
        print(f"{len(p.b):3} {len(p.b)} {p.h}")
</t>
<t tx="ekr.20170217093641.1">**Autocompletion** reminds you of all members (functions, methods, ivars, etc.) contained in objects in Leo's source code, and in Python's standard library modules. ``Alt-1 (toggle-autocompleter)`` enables and disables autocompletion. **Note**: Autocompletion can be enabled only when @language python is in effect.

For example, typing just "c.atF" (in the body pane, with autocompletion enabled) automatically inserts "c.atFileCommands" into the body pane, because "c.atFileCommands" is the only possible completion of "c.atF".

As another example, typing "at.writeA" will show (in an autocompleter tab in the Log pane) all of the write commands in leoAtFile.py::

    writeAll:method
    writeAllHelper:method
    writeAtAutoNodes:method
    writeAtAutoNodesHelper:method
    writeAtShadowNodes:method
    writeAtShadowNodesHelper:method

When a single completion is shown, typing '?' will show the docstring for a method. For example, "c.atFileCommands.write?" shows::

    Write a 4.x derived file.
    root is the position of an @&lt;file&gt; node

**Calltips** show the expected arguments to functions and methods. ``Alt-2 (toggle-calltips)`` enables and disables calltips. ``(`` shows calltips, when @language python is in effect.
``&lt;Return&gt;`` or ``Ctrl-G (keyboard-quit)`` exits calltips. Calltips work for any Python function or method, including Python's global functions. Examples::

    g.toUnicode(            g.toUnicode(s, encoding, reportErrors=False
    c.widgetWantsFocusNow(  c.widgetWantsFocusNow(w
    reduce(                 reduce(function, sequence[, initial]) -&gt; value</t>
<t tx="ekr.20170219074525.1">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.
</t>
<t tx="ekr.20170219074554.1">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</t>
<t tx="ekr.20170225035122.1">Slideshows, screencasts &amp; 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 &lt;https://ckeditor.com/&gt;`_ 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.</t>
<t tx="ekr.20170225081012.1">A plugin that makes making Leo demos easy. See `this page &lt;https://github.com/leo-editor/leo-editor/blob/master/leo/doc/demo.md&gt;`_ for complete documentation. **Important**: This plugin largely replaces screenshots.py and slideshow.py.
</t>
<t tx="ekr.20170225082023.1"></t>
<t tx="ekr.20170228101933.10">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 @&lt;file&gt; nodes.  If no nodes are found, and c.p is a clone, these commands expand the search to the entire tree, looking for an @&lt;file&gt; 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 []</t>
<t tx="ekr.20170228101933.12">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.
</t>
<t tx="ekr.20170228101933.13">The new code works, and is much simpler than the old.</t>
<t tx="ekr.20170228101933.14">https://github.com/leo-editor/leo-editor/issues/391
</t>
<t tx="ekr.20170228101933.15">It suffers from mysterious bugs.</t>
<t tx="ekr.20170228101933.16">- 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.
</t>
<t tx="ekr.20170228101933.17">https://github.com/leo-editor/leo-editor/issues/381

Added g.getEncodingAt(p)</t>
<t tx="ekr.20170228101933.18">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

</t>
<t tx="ekr.20170228101933.19">https://github.com/leo-editor/leo-editor/issues/403

The fix was to v.atFileNodeName.  It must recognize @thin as an @file node.
</t>
<t tx="ekr.20170228101933.2">https://github.com/leo-editor/leo-editor/issues/343
Exception creating path" error when evaluating a path with accents in a @clean expression

The fix was to g.os_path_expandExpression.

</t>
<t tx="ekr.20170228101933.20">Ctrl-click on UNL's goes to the UNL. This already existed, as an Easter Egg for file:// url's.

leoSettings.leo:
- Added two new patterns to @data wikiview-link-patterns.

leoColorizer.py:
- Added jedit.match_unl.
- Added support for unl's at end of jedit.colorRangeWithTag.

leoGlobals.py:
- g.recursiveUNLSearch expands found node if it has children.
- g.handleUnl looks for files in various places.
- g.openUrlHelper adds support for UNLs.

wikiview.py:
- Added a unl linking to the plugins settings. So cool.
</t>
<t tx="ekr.20170228101933.21">https://github.com/leo-editor/leo-editor/issues/340

Added reload-settings command. This does style-reload automatically.
</t>
<t tx="ekr.20170228101933.3">Changed LM.openEmptyWorkBook and LM.computeWorkbookFileName.</t>
<t tx="ekr.20170228101933.49">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170228101933.50">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170228101933.51">https://github.com/leo-editor/leo-editor/issues/426

Added a kludge in dehoistCallback that satisfies k.registerCommand.
</t>
<t tx="ekr.20170228101933.52">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170228101933.6">The proper place to init settings is in write_rst_tree.
rst.rst3 simply inits the file count, n_written
</t>
<t tx="ekr.20170228101933.7">g.openUrlOnClick now catches all exception.

More generally, added @g.callback decorator, which does the same.</t>
<t tx="ekr.20170228101933.8">https://github.com/leo-editor/leo-editor/issues/409

The fix was to restore disabled code in jedit.colorRangeWithTag.
</t>
<t tx="ekr.20170228101933.9">c.recursiveImport uncaught exception on broken (linux) symlinks
https://github.com/leo-editor/leo-editor/issues/408
</t>
<t tx="ekr.20170228103914.1">Q: When can I delete a clone safely?

A: Any time! The only time you can "lose" data is when you delete a non-cloned node, save your work and exit Leo.

Q: What gets "lost" when I delete a non-cloned node?

A: The node, and all it's non-cloned children. In addition, if the node contains all clones of a cloned node, all copies of the cloned node will also be "lost".

Q: Anything else I should be careful about concerning clones?

Not really.  If you move any node out "underneath" an @file (@clean, etc) node, the contents of that node disappears from the external file.

I hope this encourages more people to use clones.  Leo's clone-find commands are something that every Leo programmers should be using every day.</t>
<t tx="ekr.20170228104028.1"></t>
<t tx="ekr.20170228104123.1"></t>
<t tx="ekr.20170228104217.1">Edward Ream::

    alp;;=@language python\n
    alr;;=@language rest\n@wrap\n
    date;;={|{import time;x=time.asctime()}|}
    trace;;=trace = &lt;|bool|&gt; and not g.unitTesting

John Lunzer::

    hl;;={|{x=c.p.h}|}
    es;;=g.es(contents,color='&lt;|color|&gt;')
    ts;;={|{x=time.strftime("%Y%m%d%H%M%S")}|}

Rob (Largo84)::

    ol;;=&lt;ol&gt;\n    &lt;li&gt;&lt;|item|&gt;&lt;/li&gt;\n&lt;/ol&gt;
    li;;=&lt;li&gt;&lt;|ITEM|&gt;&lt;/li&gt;
    link;;=&lt;a href="&lt;|URL|&gt;" target="_blank"&gt;&lt;|TEXT|&gt;&lt;/a&gt;
    enum;;=\begin{enumerate}\n    \item &lt;|item|&gt;\n\end{enumerate}

For more examples, see LeoSettings.leo.

</t>
<t tx="ekr.20170228112247.1">https://github.com/leo-editor/leo-editor/pull/349
Command line option to select type of @&lt;file&gt; node to when opening non-outline files</t>
<t tx="ekr.20170228112643.1">**Decluttering** replaces controls custom formatting of headlines, including:

- Hiding or changing headline text,
- Adding icons to headlines,
- Changing the styling of headlines.

Decluttering is *inactive* when you are editing a headline.

Decluttering is *completely optional*. To enable decluttering, use::

     @bool tree-declutter = True

Decluttering is controlled by **decluttering rulesets**.
You specify decluttering rulesets in the body text of::

    @data tree-declutter-patterns

As usual with ``@data`` nodes:

- Blank lines and lines starting with ``#`` are ignored.
- You may organize the text of the ``@data`` node using child nodes.

Each ruleset consists of a list of lines:

- The first line is a **rule line**, containing a **find pattern**.
- The second line is a **replacement line**.
- The ruleset ends with zero or more **style lines**.

Find patterns are `regular expressions &lt;https://docs.python.org/2/library/re.html&gt;`_.
Decluttering affects only those headlines that match a rule pattern. 

The following section shows some example rulesets. Later sections discuss decluttering commands, patterns and styles in more detail.
</t>
<t tx="ekr.20170228124856.1">https://groups.google.com/d/msg/leo-editor/L4EAfY7NJbw/NgSv5zSDEwAJ

This is buggy.
</t>
<t tx="ekr.20170228125816.1">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:
https://github.com/leo-editor/leo-editor/issues/14</t>
<t tx="ekr.20170228182610.1">The leomail plugin reads .mbox mail archive files into a tree of Leo nodes. This saves a lot of work.

Google "&lt;your favorite mail client&gt; 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.</t>
<t tx="ekr.20170303051729.1">https://github.com/leo-editor/leo-editor/issues/430
rst import: titles with different underline characters on same level.
</t>
<t tx="ekr.20170303063731.1">This was an irritating hangnail that affected, for example, the pylint command.</t>
<t tx="ekr.20170303113742.1">It opens leo/config/themes.leo.
</t>
<t tx="ekr.20170308145129.13">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170308145129.132">g.findRootsWithPredicate now preserves node order.</t>
<t tx="ekr.20170308145129.141">The new code uses the new importer code to clean nodes.</t>
<t tx="ekr.20170308145129.169">https://github.com/leo-editor/leo-editor/issues/350

ssm.expand_css_constants no longer adds constants.
</t>
<t tx="ekr.20170308145129.2">https://github.com/leo-editor/leo-editor/issues/416

The fix, as expected, was to k.stroke2char.
</t>
<t tx="ekr.20170308145129.32">https://github.com/leo-editor/leo-editor/issues/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 &amp; 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.
</t>
<t tx="ekr.20170308145129.59">https://github.com/leo-editor/leo-editor/issues/352
Importer unit tests create both @clean and @file

The fix was disappointingly simple: just init ic.treeType in ic.createOutline and ic.scannerUnitTest.
</t>
<t tx="ekr.20170309071256.1">Lately I've been thinking about programming in general. My thoughts have centered on the limits of the human brain to understand computer programs. This was triggered by watching `Inventing on Principle &lt;https://www.youtube.com/watch?v=PUv66718DII&gt;`_. It's a daunting multifaceted concept which I'm sure people spend their entire lives pondering.

Most recently I've been focusing on one facet, abstraction and program "units". I define a "unit" as a part of the program that is considered a piece onto itself which can be labeled and referred to as a whole. Perhaps, as a daily Leo user, this is easy to think about because Leo does its best to coerce programmers and programs into looking at programming through this lens.

Most tools do not ignore this concept all together. Most programming environments have some sort of "outline" window which allows you to view the structure of a program at a higher level. As I have experienced it this "outline" view is always dictated by the features of a language (ex. outline divided up at module, class, function levels). In addition most tools incorporate "code folding" to help a programmer focus on language specific programming units (again, ex. folding at class and function definitions). 

Leo takes this concept to its limit. Leo offers language agnostic abstraction at arbitrary levels. It allows a programmer to structure their program outside of the confines of the programming paradigms of the language they're programming in. Of course it still helps to use the language specific "units" as a guide, in fact this is what Leo does upon import to create an initial outline structure from programs originating outside of Leo. 

I can't ignore the freedom of arbitrary abstraction, and I've come to rely upon it so much that I struggle to use non-Leo environments. It is well known that the human brain has a limited working memory. The act of programming stretches working memory to it's limit. Leo provides an environment in which a program can seamlessly be restructured to fit within the bounds of a programmers individual working memory. 

I realize this is a "why" and not a "how" and that this doesn't help anyone get better acquainted with Leo. But, as a programmer if you've ever felt frustrated with the organizational constructs of the language you're working in you might be surprised to realize that after using Leo it wasn't the language that was the problem, but a lack of tools to organize your programs in a way that makes sense to you.</t>
<t tx="ekr.20170311055647.1">Thanks to Tsuchi Noko for these.</t>
<t tx="ekr.20170312083548.1">.. index::
    pair: Chapter; Tutorial
    pair: @chapter; Tutorial

@chapter trees denote a **chapter**. You can **activate** a chapter from the icon area, or with chapter-select commands. Activating a chapter makes only those nodes in the chapter visible. The ``main`` chapter represents the entire outline. Activating the ``main`` chapter shows all outline nodes.

``chapter-select-main``
    Selects the main chapter.

``chapter-select-&lt;chapter-name&gt;``
    Selects a chapter by name.
</t>
<t tx="ekr.20170312085351.1">**Very Important**: Leo has hundreds of commands, but because of tab completion you do not have to remember, or even *know about* any of them.  Feel free to ignore commands that you don't use.

You could type the full command name in the minibuffer, followed by the ``&lt;Return&gt;`` key to invoke the command, but that would be *way* too much work. Instead, you can avoid most typing using **tab completion**. With tab completion, *there is no need to remember the exact names of Leo’s commands*.

For example, suppose you want to show the list of Leo’s commands. You might remember only that there are several related commands and that they all start with "print". Just type ``&lt;Alt-X&gt;showTab&gt;``

You will see ``show-`` in the minibuffer. This is the longest common prefix of all the command names that start with ``show``. The Completion tab in the log pane shows all the commands that start with ``show-``.

Now just type ``c&lt;Tab&gt;`` You will see the ``show-commands`` command in the minibuffer.

Finally, ``&lt;Return&gt;`` executes the ``show-commands`` command. The output of the ``show-commands`` command appears in the commands tab, and focus returns to the body pane.
</t>
<t tx="ekr.20170312085434.1">``file-open-by-name``
    Prompts for a filename. This command completes the name of files and directories as in command completion.  As a result, this command can be very fast.  You may want to bind this command to ``Ctrl-O`` instead of the default ``open-outline`` command.
</t>
<t tx="ekr.20170313111502.1">**p.b** is the body text associated with position p. Similarly, **p.h** is p's headline.
p.b and p.h are python properties, so you can assign to p.b and p.h.

This script creates an outline node as the last top-level node:

.. code-block:: python

    p = c.lastTopLevel().insertAfter()
    p.h = 'my new node'
    c.redraw(p) # Selects the new node.

This script creates multiple nodes, with different headlines:

.. code-block:: python

    parent = c.lastTopLevel().insertAfter()
    parent.h = 'New nodes'
    table = (
        ('First node', 'Body text for first node'),
        ('Node 2',     'Body text for node 2'),
        ('Last Node',  'Body text for last node\nLine 2'),
    )
    for headline, body in table:
        child = parent.insertAsLastChild()
        child.b = body.rstrip() + '\n' # Ensure exactly one trailing newline.
        child.h = headline
    c.selectPosition(parent) # Another way to select nodes.
    c.redraw()

This script creates a node containing today's date in the body text:

.. code-block:: python

    import time
    p = c.lastTopLevel().insertAfter()
    p.h = "Today's date"
    p.b = time.strftime("%Y/%m/%d")
    c.redraw(p)
</t>
<t tx="ekr.20170313111626.1">The script writes the body text of the presently selected node to ~/leo_output_file.txt and then prints it to the log pane:

.. code-block:: python

    fn = g.os_path_finalize_join(g.app.homeDir, 'leo_output_file.txt')
    with open(fn, 'w') as f:
        f.write(c.p.b)
    with open(fn, 'r') as f:
        for line in f.readlines():
            g.es(line.rstrip())
</t>
<t tx="ekr.20170313151821.1">See The "What's new in this file" node in scripts.leo for details.</t>
<t tx="ekr.20170313152439.1">**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
</t>
<t tx="ekr.20170314060847.1">.. index::
    pair: @file node; Tutorial

An **@file node** is a node whose headline starts with ``@file`` followed by a path to an external file::

    @file leoNodes.py
    @file ../../notes.txt

The @file node and its descendants represent an external file. Leo updates @file nodes when you change external files outside of Leo. When saving an outline, Leo writes all changed @file trees to their external files.</t>
<t tx="ekr.20170314060926.1">.. in tutorial-basics.html (External files)

.. index::
    pair: Markup; Tutorial

Leo's **markup** tells Leo how to create external files from @file trees. Markup may appear in any body text, and *must* appear in the body of the @file node itself.

There are two kinds of markup: **section references** (&lt;&lt; this is my section &gt;&gt;) and the **@others** directive. Section references refer to **named nodes**, nodes whose *headlines* look like a section reference. @others refers to all *other* (unnamed) nodes. Here is the body text of a typical @file node for a python file:

.. code-block:: python

    """A docstring"""
    &lt;&lt; imports &gt;&gt;
    @others
    if __name__ == '__main__':
        main()
    @language python
    @tabwidth -4
    
A child node must define the &lt;&lt; imports &gt;&gt; node. Other children will typically define classes, methods, functions, and data.

When writing this file, Leo writes:

- The docstring.
- The *body text* of the ``&lt;&lt; imports&gt;&gt;`` node.
- The body text of all *other* nodes, in outline order.
- The lines after the ``@others`` directive.
</t>
<t tx="ekr.20170314061000.1">.. index::
    pair: @clean; Tutorial

When writing **file trees**, Leo writes **sentinel comments** into external files. These comments represent outline structure. When writing an @file tree to a .leo file, Leo writes only the root @file node. To avoid sentinels, use **@clean** instead of @file::

    @clean leoNodes.py
    @clean ../../notes.txt

There is a small cost to @clean: Leo saves the entire @clean tree in the .leo file.
</t>
<t tx="ekr.20170314061022.1">.. index::
    pair: @all; Tutorial
    pair: Outline Order; Tutorial

The **@all** directive tells Leo to write the nodes of an **@file tree** to the external file, *ignoring* all markup. As a result, Leo writes nodes to the file in **outline order**, the order in which they appear in the outline when all nodes are expanded.
</t>
<t tx="ekr.20170314090749.1">Dumps files dropped into Leo.</t>
<t tx="ekr.20170314090824.1">Embeds an python interpreter in Leo's log pane.</t>
<t tx="ekr.20170314090914.1">Adds a calendar widget in the log area.
</t>
<t tx="ekr.20170314091002.1">Enables rich text using the `CKEditor &lt;https://ckeditor.com/&gt;`_ editor.
</t>
<t tx="ekr.20170314091035.1">Adds the Edit Settings menu tree to the Settings menu.</t>
<t tx="ekr.20170314091127.1">Adds Leo to the system tray.</t>
<t tx="ekr.20170314091206.1">Hides/shows parts of urls in the body editor.</t>
<t tx="ekr.20170314091526.1">Read and write .leo files in ` OPML &lt;https://en.wikipedia.org/wiki/OPML&gt;`_.
</t>
<t tx="ekr.20170314091627.1">Edit several nodes at once, in a pannable "notebook" view.</t>
<t tx="ekr.20170314091824.1">Uses the ctags database to provide an autocompletion list.
</t>
<t tx="ekr.20170314091826.1">Uses ctags to provide an autocompletion list.
</t>
<t tx="ekr.20170314091927.1">Supports uploading of files via ftp.
</t>
<t tx="ekr.20170314091958.1">Stores snapshots of outline in git.
</t>
<t tx="ekr.20170314092023.1">Reads from rss, atom or other sources.
</t>
<t tx="ekr.20170314092041.1">Sync local mailbox files over to Leo.
</t>
<t tx="ekr.20170314092107.1">Adds commands that create bold, italic or underlined text.
</t>
<t tx="ekr.20170314092126.1">Provides commands to run text diffs on node bodies within Leo.
</t>
<t tx="ekr.20170314092144.1">Adds ``@edit``-like functionality for remote files over SFTP.
</t>
<t tx="ekr.20170314092158.1">Adds utilities for asynchronous operation of commands.
</t>
<t tx="ekr.20170314092222.1">Adds commands for importing and exporting xml to and from Leo outlines.
</t>
<t tx="ekr.20170315020214.1">**Ivars**::

    g.app                   A LeoApp instance.
    g.app.gui               A LeoGui instance. 
    g.app.pluginsController A LeoPluginsController instance.
    g.app.*                 Leo's global variables.
</t>
<t tx="ekr.20170315072706.1">Leo and `Emacs org mode &lt;https://orgmode.org/&gt;`_ share similar goals. Org mode has many strengths related to non-programming tasks:

- Drawers: visible, pure text, easily extensible uA's.
- Agendas and tables.
- In-pane rendering of Latex and special symbols.
- Support for multiple source languages, including shell scripts, C, etc.
- Code blocks, with arguments.
- Result blocks.

But org mode is unsuitable for software development. Org mode's code block syntax::

    #+NAME: &lt;name&gt;
    #+BEGIN_SRC &lt;language&gt; &lt;switches&gt; &lt;header arguments&gt;
        &lt;body&gt;
    #+END_SRC

would be unbearable in source files.

More generally, org mode lacks the following Leonine features:

- Automatic tangling when saving files.
- Automatic untangling when loading files.
- @others
- Importers for programming languages.
- Clones and especially Leo's clone-find commands. 
- A full Python API and DOM, including generators.
- @command, @button.

.. _`algorithm`: appendices.html#the-mulder-ream-update-algorithm
.. _`Directed Acyclic Graphs`:  https://en.wikipedia.org/wiki/Directed_acyclic_graph

Leo's is based on technologies missing from org mode:

- Clones require that outlines be `Directed Acyclic Graphs`_.
- Leo updates @clean trees using an `algorithm`_ that could not be duplicated in org mode.
- Leo's outlines are true Python objects, with unique, persistent identities.

In contrast, org mode is completely text oriented:

- Org mode's API is limited to parsing body text.
- Org mode simulates a DOM with text filters.
</t>
<t tx="ekr.20170316061434.1">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.
</t>
<t tx="ekr.20170316061456.1">- @bool autojustify-on-at-start
- @bool color-doc-parts-as-rest
- @bool run-pyflakes-on-write
- @bool tree-declutter = True
- @data tree-declutter-patterns
</t>
<t tx="ekr.20170316063618.1">::

    --load-type=LOAD_TYPE
    --fail-fast             # sets failfast option in unit tests.
</t>
<t tx="ekr.20170322084431.1">Here is Leo's main window on Windows 7 showing the outline pane (1), the body pane (2), the minibuffer (3), the log pane, showing the find tab (4).
The body pane shows the contents of the presently selected node in the outline pane:

.. image:: screen-shots/leo-main-window.png
   :scale: 40%
   :alt: Light Main Window

You can choose a dark theme:

.. image:: screen-shots/emacs-config.png
   :scale: 40%
   :alt: Dark Main Window

Leo's main window as it appears on Linux:

.. image:: screen-shots/leo-qt-main-window-linux.png
   :scale: 40%
   :alt: Linux Main Window

</t>
<t tx="ekr.20170322084909.1">.. |leo-thesis| image:: screen-shots/leo-thesis.png

.. _`This page`: https://mutabit.com/offray/static/blog/output/posts/on-deepness-and-complexity-of-ipython-documents.html

`This page`_ describes this screen shot in detail.

|leo-thesis|
</t>
<t tx="ekr.20170403185500.1">The *Position* methods ``p.b``, ``p.h``, and ``p.setDirty()`` are *slow*.

The *VNode* methods ``p.v.b``, ``p.v.b``, and ``p.v.setDirty()`` are *fast*.

However, it's usually better to use the *Position* methods, despite their cost, because Position methods update Leo's outline completely.

Use the *VNode* methods only for repetitive commands, like ``cff``, ``replace-all`` and recursive import.
</t>
<t tx="ekr.20170608071626.1">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](https://github.com/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**

- [Leo's home page](https://leo-editor.github.io/leo-editor/)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md
</t>
<t tx="ekr.20170612093902.1">Use @others unless the contents of a node must appear in a certain spot, or in a certain order. For examples, most of Leo's source files start like this::

    @first # -*- coding: utf-8 -*-
    &lt;&lt; imports &gt;&gt;
    @others

The &lt;&lt; imports &gt;&gt; section reference ensures that imports appear first. Another example::

    @first # -*- coding: utf-8 -*-
    &lt;&lt; imports &gt;&gt;
    &lt;&lt; base classes &gt;&gt;
    @others

This ensures that base classes are defined before their subclasses.
</t>
<t tx="ekr.20170618015524.1">I thought I would write my own testimonial. I don't ever do this, as I often roll my eyes at testimonials, but my enthusiasm is at such a degree about Leo, that I must give "props" where props are due.

**BACKGROUND**

**The Beginning**: Coming from being a Java professional in the early aughts, I was used to Netbeans. It was fine I guess. A few years later I decided I wanted to be a web developer.

**Why I sought out a new editor**: I wanted something extensible in FULL. I wanted to make it my own. It is like your home. You move in, it is up to you to make it your "HOME". So is an editor. You spend all of your time with it. It must be YOURS I figure. Comfy like a pair of old shoes.

**HISTORY**

**Ultra-Edit**: This was my first non-ide, IDE. No disrespect to UltraEdit, I am sure it has many awesome features I never used.  I never really got the chance.  I wanted something lightweight and soon found Scite around 2006.

**Notepad++**: Eventually  I found Notepad++ (which I still think is awesome, and would recommend to anyone).  I have been using it for 8 years, and I still do use it occasionally.  Mostly  because  I am still getting used to Leo.

**NOW**

I am at an age now, and a point in my career where I want to make my life (and job) as simple as possible. Leo helps me do that.  It is hard to explain--the outlining gives the ability to mix thoughts with code--even life with code, in a very intuitive fashion. Perhaps this is "literate programming".  I don't know.  They never mentioned that term in my CS classes.  Whatever it is, I like it.

Side benefit--my code has never been so well formatted and documented!

**The thing I personally love most**

As I alluded to, so much ability to extend.  At work, I work on what my boss wants, but at home, I spend most of my time extending Leo.  I have never seen an editor so easy to extend, and believe me, I have evaluated at least 20 editors in the past 5 months. 

That's the thing--anything I want to work a different way, or anything I want to be better, I can do it on my own. I don't have to submit a request. If I at least have enough curiosity to google or ask for a bit of help, I can make it what I want.

You name it.  

- If I would like the log to work differently, or create my own output pane: no problem.
- If I want to add PHP Unit tests to the menu, no problem.
- If I want to make a personal organizer, mixed in with my work flow, no problem.
- If I want to have my python, PHP code, journal, all integrated together so that everything makes sense from 20,000 feet, no problem.
- If I want to change the entire look and feel...and I mean EVERYTHING...not just some things, no problem.
- If I want to be able to easily explain the code to a non-technical colleague, no problem.  The outline can be followed by anyone with some degree of intelligence.

You get the idea...

And for me, that means everything.</t>
<t tx="ekr.20170707034853.10">https://github.com/leo-editor/leo-editor/issues/470

See also:
https://github.com/leo-editor/leo-editor/issues/449
The original fix was in i.run in linescanner.py.
</t>
<t tx="ekr.20170707034853.11">https://github.com/leo-editor/leo-editor/issues/451
refresh-from-disk doesn't always restore focus to the correct node

- at.readOneAtAutoNode returns the *new* position.
- c.refreshFromDisk selects that position.
</t>
<t tx="ekr.20170707034853.12">https://github.com/leo-editor/leo-editor/issues/452</t>
<t tx="ekr.20170707034853.13">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170707034853.14">https://github.com/leo-editor/leo-editor/issues/458
Set a Qt flag in tt.createControl.
</t>
<t tx="ekr.20170707034853.15">Missing end-of-line characters at the Log Pane
https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170707034853.16">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170707034853.17">UnicodeDecodeError in writeRecentFilesFileHelper
https://github.com/leo-editor/leo-editor/issues/471

The fix was in rf.writeRecentFilesFileHelper.
</t>
<t tx="ekr.20170707034853.18">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170707034853.19">https://github.com/leo-editor/leo-editor/issues/476
</t>
<t tx="ekr.20170707034853.2">For a list of all enhancements added in Leo 5.6, see this page:
https://github.com/leo-editor/leo-editor/issues?utf8=%E2%9C%93&amp;q=is%3Aissue%20label%3AEnhancement%20is%3Aclosed%20milestone%3A5.6%20-label%3AWon%27tDo%20</t>
<t tx="ekr.20170707034853.20">https://github.com/leo-editor/leo-editor/issues/479
Preserve brython indentation when importing .html files
</t>
<t tx="ekr.20170707034853.21">https://github.com/leo-editor/leo-editor/issues/481
</t>
<t tx="ekr.20170707034853.22">https://github.com/leo-editor/leo-editor/issues/487
</t>
<t tx="ekr.20170707034853.23">https://github.com/leo-editor/leo-editor/issues/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).
</t>
<t tx="ekr.20170707034853.24">https://github.com/leo-editor/leo-editor/issues/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
</t>
<t tx="ekr.20170707034853.25">https://github.com/leo-editor/leo-editor/pull/497

Rewrote rf.createRecentFiles, rf.readRecentFilesFile and rf.writeRecentFilesFileHelper.
</t>
<t tx="ekr.20170707034853.26">The bug gave way too many bindings for the move-lines commands.
</t>
<t tx="ekr.20170707034853.27">ga.show_tab_list wasn't showing commands without any shortcuts!
</t>
<t tx="ekr.20170707034853.28">Fixed plugins.registerOneHandler and plugins.registerOneExclusiveHandler
</t>
<t tx="ekr.20170707034853.29">The unit test "@test xml non-ascii tags" failed on Python 2, but not Python 3.

The fix was in xml_i.scan_tag &amp; helper
</t>
<t tx="ekr.20170707034853.3">A new chapter in Leo's documentation: https://leo-editor.github.io/leo-editor/console-gui.html

https://github.com/leo-editor/leo-editor/issues/488
</t>
<t tx="ekr.20170707034853.30">It must return True if g.app.externalFilesController is None.
</t>
<t tx="ekr.20170707034853.31"></t>
<t tx="ekr.20170707034853.32">The change was to pylint.run_pylint.

This removes a major source of confusion.
</t>
<t tx="ekr.20170707034853.33"></t>
<t tx="ekr.20170707034853.34">Added 'recursive' keyword arg to c.recursiveImport and RecursiveImportController ctor.
Recursive is *not* the same as not one_file.
</t>
<t tx="ekr.20170707034853.35"></t>
<t tx="ekr.20170707034853.36">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. 
</t>
<t tx="ekr.20170707034853.37">This makes explicit which importers actually generate section reference. At present, only the javascript importer sets this arg.
</t>
<t tx="ekr.20170707034853.38">These traces detected nothing unusual and have been disabled.
</t>
<t tx="ekr.20170707034853.39">- Removed the allow_at_auto_section switch in leoAtFile.py.

- When writing @auto files &lt;&lt; handle line at s[i] &gt;&gt; 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.
</t>
<t tx="ekr.20170707034853.4">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.
</t>
<t tx="ekr.20170707034853.40">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
</t>
<t tx="ekr.20170707034853.41">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170707034853.42">Improved g.SherlockTracer.do_line, g.gitInfo, g.is_binary_external_file, g.log, g.readFileToUnicodeString.
</t>
<t tx="ekr.20170707034853.43"></t>
<t tx="ekr.20170707034853.44">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170707034853.45">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.
</t>
<t tx="ekr.20170707034853.46">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.



</t>
<t tx="ekr.20170707034853.47"></t>
<t tx="ekr.20170707034853.48">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170707034853.49">@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')
</t>
<t tx="ekr.20170707034853.5">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170707034853.50">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()
</t>
<t tx="ekr.20170707034853.51">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()
</t>
<t tx="ekr.20170707034853.52">Changed find.createCloneFindAllNodes and c.cloneFindMarkedHelper.
</t>
<t tx="ekr.20170707034853.53">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.
</t>
<t tx="ekr.20170707034853.54">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.
</t>
<t tx="ekr.20170707034853.55">https://github.com/leo-editor/leo-editor/issues/456

Made several changes to find.batchChange.
</t>
<t tx="ekr.20170707034853.56"></t>
<t tx="ekr.20170707034853.57"></t>
<t tx="ekr.20170707034853.58"></t>
<t tx="ekr.20170707034853.59">https://github.com/leo-editor/leo-editor/issues/479
Preserve brython indentation when importing .html files

The new code is simpler and handles dubious html syntax.
</t>
<t tx="ekr.20170707034853.6">For a list of all bugs fixed in Leo 5.6, see this page:
https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+is%3Aclosed+milestone%3A5.6+-label%3AWon%27tDo+label%3ABug</t>
<t tx="ekr.20170707034853.60"></t>
<t tx="ekr.20170707034853.61">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170707034853.62">https://github.com/leo-editor/leo-editor/issues/478
</t>
<t tx="ekr.20170707034853.63">https://github.com/leo-editor/leo-editor/issues/484

Added submenus to Windows menu. This significantly simplifies and clarifies the Windows menu.
</t>
<t tx="ekr.20170707034853.64"></t>
<t tx="ekr.20170707034853.65">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.
</t>
<t tx="ekr.20170707034853.66">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.
</t>
<t tx="ekr.20170707034853.67">The first UP-arrow to gives the previous command, the next up-arrow gives the next command, etc.
</t>
<t tx="ekr.20170707034853.68">Changed g.computeWindowTitle.
</t>
<t tx="ekr.20170707034853.7">https://github.com/leo-editor/leo-editor/issues/385
</t>
<t tx="ekr.20170707034853.70">https://groups.google.com/d/msg/leo-editor/sBGJr_oHeyk/3eUjoBC0CQAJ
</t>
<t tx="ekr.20170707034853.72"></t>
<t tx="ekr.20170707034853.73"></t>
<t tx="ekr.20170707034853.74"></t>
<t tx="ekr.20170707034853.75">https://github.com/leo-editor/leo-editor/issues/518

@bool report_unchanged_files = True
</t>
<t tx="ekr.20170707034853.76"></t>
<t tx="ekr.20170707034853.77"></t>
<t tx="ekr.20170707034853.78">These are bound to indent/unindent-region and can be used when no text is selected.
</t>
<t tx="ekr.20170707034853.79"></t>
<t tx="ekr.20170707034853.8">https://github.com/leo-editor/leo-editor/issues/386
All changes made to leo/modes/md.py
</t>
<t tx="ekr.20170707034853.80">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.
</t>
<t tx="ekr.20170707034853.9">https://github.com/leo-editor/leo-editor/issues/438
</t>
<t tx="ekr.20170708002743.1">push-cursor     Saves the location of the cursor, including node(position) on a stack.
pop-cursor      Restores the cursor position from the stack.
</t>
<t tx="ekr.20170708002922.1">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.</t>
<t tx="ekr.20170804153108.135">https://github.com/leo-editor/leo-editor/issues/526

Fixed #526 by writing and restoring uA's:

- fc.compute_attribute_bits writes uA's for @auto nodes.
- pd.restore_gnx now actually sets gnx's(!)

Other changes:
- leoAtFile.py: fixed crasher in exception handling.
- leoFileCommands.py: Refactored code into fc.compute_attribute_bits.
</t>
<t tx="ekr.20170804153108.154">https://github.com/leo-editor/leo-editor/issues/457
Wrap around search now works properly.
</t>
<t tx="ekr.20170804153108.157">https://github.com/leo-editor/leo-editor/issues/495
Leo already supports the point and mark.

https://github.com/leo-editor/leo-editor/issues/496

Added ec.pushCursor and ec.popCursor.
Added ec.finishOfLine &amp; ec.startOfLine &amp; 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.
</t>
<t tx="ekr.20170804153108.166">https://github.com/leo-editor/leo-editor/issues/512
</t>
<t tx="ekr.20170804153108.184">https://github.com/leo-editor/leo-editor/issues/516
</t>
<t tx="ekr.20170804153108.198">https://github.com/leo-editor/leo-editor/issues/522
</t>
<t tx="ekr.20170804153108.4">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170804154716.1">Defaults are::

    @bool log_show_save_time = False
    @string log_timestamp_format = %H:%M:%S
</t>
<t tx="ekr.20170804155213.1">https://github.com/leo-editor/leo-editor/issues/537

See also: How to make Unicode charset in cmd.exe by default?
https://stackoverflow.com/questions/14109024
</t>
<t tx="ekr.20170804155454.10">https://github.com/leo-editor/leo-editor/issues/446
</t>
<t tx="ekr.20170804155454.11">https://github.com/leo-editor/leo-editor/issues/531

Added new settings::

    @bool log_show_save_time = False
    @string log_timestamp_format = "%H%M%S"

Changed fc.putSavedMessage and at.replaceTargetFileIfDifferent.
</t>
<t tx="ekr.20170804155454.3">https://github.com/leo-editor/leo-editor/issues/62
</t>
<t tx="ekr.20170804155454.4">https://github.com/leo-editor/leo-editor/issues/317
</t>
<t tx="ekr.20170804155454.5">https://github.com/leo-editor/leo-editor/issues/473
</t>
<t tx="ekr.20170804155454.6">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170804155454.7">https://github.com/leo-editor/leo-editor/issues/516

</t>
<t tx="ekr.20170804155454.9">Defaults are::

    @bool color_trailing_whitespace = True
    @color trailing_whitespace_color = red
</t>
<t tx="ekr.20170808083130.1">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170822100152.1">https://github.com/leo-editor/leo-editor/issues/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.</t>
<t tx="ekr.20170823085504.1">https://github.com/leo-editor/leo-editor/issues/529
</t>
<t tx="ekr.20170823100047.1">https://github.com/leo-editor/leo-editor/issues/528
</t>
<t tx="ekr.20170823100152.1">https://github.com/leo-editor/leo-editor/issues/529
</t>
<t tx="ekr.20170906040814.1">https://github.com/leo-editor/leo-editor/issues/504</t>
<t tx="ekr.20170906040849.1">https://github.com/leo-editor/leo-editor/issues/508</t>
<t tx="ekr.20170911082347.1"></t>
<t tx="ekr.20170911082432.101">- Added --trace-focus command-line argument.
- Added @bool color_trailing_whitespace = True
- Added @bool log_show_save_time = False
- Added @bool report_unchanged_files = True
- Added @bool run_pyflakes_on_unchanged_files = True
- Added @color trailing_whitespace_color = red
- Added @string log_timestamp_format = %H:%M:%S
- Ctrl-Shift-&lt; and Ctrl-Shift-&gt; are now bound to indent/unindent-region.
  These can be used when no text is selected.
- Restored default: @bool check_for_changed_external_files = True</t>
<t tx="ekr.20170911082432.2">- A new console gui for Leo.
- Added git-diff command
- Added listen-to-log and kill-log-listen commands.
- Added "yes/no to all" buttons for externally changed file dialog
- Leo switches between git branches more smoothly.</t>
<t tx="ekr.20170911082432.3">A new chapter in Leo's documentation: https://leo-editor.github.io/leo-editor//console-gui.html

https://github.com/leo-editor/leo-editor/issues/488
</t>
<t tx="ekr.20170911082432.4">https://github.com/leo-editor/leo-editor/issues/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.</t>
<t tx="ekr.20170911082432.5">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20170911082432.53">- Removed confusing "atAuto" switch from AtFile class.
- Rewrote Leo's at-file read code.
- Rewrote Leo's redraw code, adding c.redraw_later.
- Unit tests now work on all all platforms without failing.
</t>
<t tx="ekr.20170911082432.6">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.
</t>
<t tx="ekr.20170911082432.66">Added the following commands:

- edit-recent-files and write-edited-recent-files
- goto-any-clone
- help-for-settings
- listen-to-log and kill-log-listen
- push-cursor and pop_cursor
- show-color-names and show-color-wheel
- start-of-line and finish-line
- toggle-auto-edit
- vr-zoom
- vs-eval-block (valuescript plugin)

Improved the following commands:

- clone-find*
- indent-region and unindent-region
- move-lines-up and move-lines-down
- paste-retaining-clones now works across different .leo files
- replace-all is much faster.
</t>
<t tx="ekr.20170911082432.88">- Added tcl importer.
- Added lua importer.
- Improved xml and html importers.
- Improved Windows menu.
- Improved caching of files.
- Improved operation of command history.
- Optionally show timestamps when writing files.
- The viewrendered.py plugin renders LaTex (Python 2.x only)</t>
<t tx="ekr.20170913102052.1">https://github.com/leo-editor/leo-editor/issues/541
</t>
<t tx="ekr.20170925084456.1"></t>
<t tx="ekr.20171018084145.1">Synchronize ``@leo_cloud`` subtrees with remote central server.
</t>
<t tx="ekr.20171027125705.1">Private copies of LeoPyRef.leo, that is, leoPy.leo, are "global".  That is, they persist unchanged when switching branches.  In effect, they act like (sometimes) unwanted caches.

If you change the *structure* of @file nodes in leoPy.leo in one branch, such changes will "propagate" to other branches, even though the contents of each node has remained the same.

You can see such changes clearly using leo --diff.

In short, don't make unnecessary structural changes in leoPy.leo when in branches other than master.</t>
<t tx="ekr.20171122090711.1">All rulesets start with a **rule line** of the form::

    RULE &lt;regular expression&gt;

The ruleset matches a headline if and only if the regular expression matches. Matches can start anywhere in the headline. Leo first attempts to a match using re.match. If that doesn't work, Leo tries re.search.

A **replacement line** must follow the rule line. Here are the valid forms::

    REPLACE &lt;substitution expression&gt;
    REPLACE-HEAD
    REPLACE-TAIL
    REPLACE-REST

- ``REPLACE`` replaces the headline by the value of the substitution expression.  For example::

    REPLACE \1

  matches replaces the headline by the first matched regex group.

- ``REPLACE-HEAD`` replaces replace the headline by the text that precedes the matched text.

- ``REPLACE-TAIL`` replaces the headline by the text that follows the matched text.

- ``REPLACE-REST`` replaces the headline by everything except the matched text.
</t>
<t tx="ekr.20171122090722.1">Leo applies style lines only if they appear in a ruleset that matches a headline. Style lines do the following...

Add an icon to the headline::

    ICON path/to/icon

Set the background or foreground color to a color number or names::

    BG #FF8800
    FG @solarized-magenta

Set the font to a given font name::

    Font Times

Set the font size in pixels (PX) or points (PT)::

    PX 40
    PT 16

Enable or disable italics::

    ITALIC 0
    ITALIC 1

Set the font weight to one of Light, Normal, DemiBold, Bold, Black::

    WEIGHT DemiBold
</t>
<t tx="ekr.20171122090736.1">Here are some examples of decluttering rulesets::

    # Hide org-mode tags and bold the headline.
    RULE :([\w_@]+:)+\s*$
    REPLACE-HEAD
    WEIGHT Bold

    # Replace @clean with 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
</t>
<t tx="ekr.20180124094454.1">.. _`long discussion`: https://groups.google.com/d/msg/leo-editor/83avo6mgHXY/nIKOpztyAAAJ

From this `long discussion`_ on leo-editor:

From Rob Keeney:

**Typical Use case**

I teach a variety of classes in a business environment and need handouts,
teaching aids, worksheets and training manuals that are specifically
customized for each client. These documents are easier to manage, print and
protect using standard PDFs.

**Workflow Overview**

- Document content comes from a primary resource directory arranged by
  topic (not client specific).
- I have a Resources.leo file that helps me keep that directory organized.
- All of the content files are written in LaTex (I use a .txi file
  extension of my own invention to indicate the file is an 'input' file
  only, not the main output file which uses .tex).
- I have a Client.leo file for each client in their own directory to
  organize work specific to each client.
- For each document needed for a client project, I create a Document.tex
  file from a standard template and change the document properties as
  needed for the specific client, project and document.
- The Document.tex file acts as the presentation 'shell' for the document
  and I simply add \input{"\ResourcePath Content.txi"} after the
  \begin{document} statement (\ResourcePath is a shortcut command to the
  location of the content resource). This shell determines such things as
  the document title, document type, client name, header/footer information
  and revision date.
- Since I work primarily in Windows, I use TeXNicCenter to process (typeset) the Document.tex file to create PDF output. (I do not use TeXNicCenter for editing, only file processing).

**Workflow Notes and Shortcuts**

- Years ago, I discovered the incredible exam class for LaTex and now
  use it almost exclusively. It makes it much easier to create student
  and teacher versions of the same content (for example, handouts for
  students and training manual with speaking notes for the teacher).
- I use \@outline-data tree-abbreviations in Leo to create each new
  Document.tex file from a template with variables (very cool!)
- I created many @data abbreviations in Leo to speed up typing of standard
  LaTex structures (would be happy to share them if anyone is interested).
- All document content stays in the Resources directory and only 'shell'
  documents are in the client directories.
- These shell documents allow for client-specific information to be added
  to the headers, footers and in some cases as variables inside the content
  area itself (using \theClient variable that I define).

**Software Needed**

- Leo, and its dependencies.
- MiKTex for the LaTex distribution and package management (I have it set
  to auto-update as needed).
- TeXNicCenter for processing (typesetting) to PDF output.

**Example Leo file**

.. _`example Leo file`: https://github.com/leo-editor/snippets/tree/master/examples/workflow/latex-pdf

See this `example Leo file`_.

**Questions**

Q: Can you control TexNicCenter from Leo - or do you process the file and preview process manually?

A: No, I run processing (typesetting) in TeXNicCenter manually. Typically,
I create a blank project file and open however many files required for that
project. That way it's easier to clean up the extra files created during
the process steps. HTH. There might be a way to invoke the LaTex commands
through Leo, but that's way above my pay grade.

From Arjan Mossel:

I'm using Leo to organize sections like \chapter, \section and \subsection.
Since I'm just writing latex in Leo, I need to keep track of the right
hierarchies, so I can't freely move nodes around in the hierarchy or I end
up with \subsection at the same level as \section, etc. It would be great
to be able to let Leo handle this.

MyProject
  - @clean myproject/myproject.tex
  - @clean myproject/references.bib
  - Compile myproject.tex

The compile node has something like this::

    import os
    import subprocess
    import sys

    repository_dir = os.path.abspath(os.curdir)

    # Run the system commands from the folder containing the tex, cls, clo, or bib files.
    working_dir = os.path.join(repository_dir, 'myproject')
    os.chdir(working_dir)

    # The commands to run.
    run_xelatex = 'xelatex ' + working_dir + os.sep + 'myproject.tex'
    run_bibtex =  'bibtex ' + working_dir + os.sep + 'myproject'

    g.es('Running XeLaTeX and BibTeX')
    # os.system starts a new subshell
    # @todo: is it possible to run the below commands in one subshell consecutively?
    os.system(run_xelatex)
    os.system(run_bibtex)
    os.system(run_xelatex)

    # Platform-independent file opening
    def open_file(filename):
        if sys.platform == "win32":
            os.startfile(filename)
        else:
            opener ="xdg-open"
            subprocess.call([opener, filename])

    open_file('myproject.pdf')
</t>
<t tx="ekr.20180124100440.3">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.

4. 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 &amp; 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.

</t>
<t tx="ekr.20180124100440.5">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.
</t>
<t tx="ekr.20180124100440.6">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.
</t>
<t tx="ekr.20180124100450.1">Added over two dozen enhancements.  See
https://github.com/leo-editor/leo-editor/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+milestone%3A5.7+label%3Aenhancement
</t>
<t tx="ekr.20180124100450.1030"></t>
<t tx="ekr.20180124100450.126">https://github.com/leo-editor/leo-editor/issues/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.

2. When selected, the tree pane highlights the '*' line containing c.p.

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

4. The minibuffer works with tab completion. Examples:

    run-a&lt;tab&gt;l&lt;tab&gt;&lt;return&gt; executes run-all-unit-tests-locally.
    toggle-find-r&lt;tab&gt;&lt;return&gt; executes toggle-find-regex-option. # Shows results in status area.

This is a huge step forward in power.

5. 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:
- Arrow keys move *within* a pane, not between panes.
- Link to npyscreen post: https://groups.google.com/d/msg/npyscreen/nk2pjj71bok/OZxBnuiJAQAJ

Without redraws: 34.5 sec.
With redraws: 58.7 sec.
</t>
<t tx="ekr.20180124100450.168">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20180124100450.3">https://github.com/leo-editor/leo-editor/issues/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 = &lt;key&gt;

does not work.  That would eat &lt;key&gt; 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
</t>
<t tx="ekr.20180124100450.328">https://github.com/leo-editor/leo-editor/issues/528

</t>
<t tx="ekr.20180124100450.357">https://github.com/leo-editor/leo-editor/issues/529
</t>
<t tx="ekr.20180124100450.360">https://github.com/leo-editor/leo-editor/issues/556
</t>
<t tx="ekr.20180124100450.367">https://github.com/leo-editor/leo-editor/issues/571

This only happens when clicking the link in the VR pane, and only with Python 2.
</t>
<t tx="ekr.20180124100450.369">Let reformatting unit tests run in more environments
https://github.com/leo-editor/leo-editor/issues/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
</t>
<t tx="ekr.20180124100450.427">https://github.com/leo-editor/leo-editor/issues/589

The @g.commander_command decorator injects ivars into the Commands class.</t>
<t tx="ekr.20180124100450.49">https://github.com/leo-editor/leo-editor/issues/417
</t>
<t tx="ekr.20180124100450.704">Changed qtree.declutter_node.</t>
<t tx="ekr.20180124100450.728">The bug was in LM.computeWorkbookFileName.
It's fine to return the name if the file already exists.

The message came from readFileIntoString:
    &lt;module&gt;,run,load,doPostPluginsInit,openEmptyWorkBook,loadLocalFile,
    openFileByName,initWrapperLeoFile,refreshFromDisk,readOneAtEditNode
</t>
<t tx="ekr.20180124100450.797"></t>
<t tx="ekr.20180124100450.803">This supports the already-existing g.app.trace_shutdown switch.
Presumably --trace-shutdown was removed by mistake some time ago.
</t>
<t tx="ekr.20180124100450.839">**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?
</t>
<t tx="ekr.20180124100450.888">https://github.com/leo-editor/leo-editor/issues/613
</t>
<t tx="ekr.20180124100450.906">https://github.com/leo-editor/leo-editor/issues/597
</t>
<t tx="ekr.20180124100450.913">https://github.com/leo-editor/leo-editor/issues/635</t>
<t tx="ekr.20180124120513.1"></t>
<t tx="ekr.20180124121124.1"></t>
<t tx="ekr.20180124121851.1">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. 
</t>
<t tx="ekr.20180124122055.1">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</t>
<t tx="ekr.20180124124409.1">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.</t>
<t tx="ekr.20180124124532.1">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.</t>
<t tx="ekr.20180125032239.1">@nosearch

You can see all 5.7 issues by visiting:
https://github.com/leo-editor/leo-editor/issues?page=1&amp;q=is%3Aissue+milestone%3A5.7+is%3Aclosed+-label%3ATip+-label%3AWon%27tDo+-label%3AWon%27tFix+-label%3AHelp&amp;utf8=%E2%9C%93
</t>
<t tx="ekr.20180125034327.1">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](https://github.com/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's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md
</t>
<t tx="ekr.20180125034510.1"></t>
<t tx="ekr.20180125034531.1"></t>
<t tx="ekr.20180125034637.1">Fixed dozens of bugs. See:
https://github.com/leo-editor/leo-editor/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+milestone%3A5.7+label%3ABug</t>
<t tx="ekr.20180125035840.1"></t>
<t tx="ekr.20180125041229.1"></t>
<t tx="ekr.20180125041723.1"></t>
<t tx="ekr.20180125042412.1"></t>
<t tx="ekr.20180125094702.1">@language python
import time
import leo.plugins.demo as demo
&lt;&lt; utils &gt;&gt;
@others
</t>
<t tx="ekr.20180125101033.1">def wait(n=2):
    update()
    time.sleep(n)
    d.delete_widgets()
    update()

</t>
<t tx="ekr.20180125101040.1">def highlight(pane):

    w = d.pane_widget(pane)
    if not w:
        return g.trace('bad pane', pane)
    sd = {
        'body': 'QTextEdit#richTextEdit { border: 5px solid red; }',
        'log': 'QTextEdit#log-widget { border: 5px solid red; }',
        'tree': 'QTreeWidget { border: 5px solid red; }',
    }
    sheet2 = sd.get(pane)
    if not sheet2:
        return g.trace('bad pane', pane)
    sheet1 = ssm.expand_css_constants(c.active_stylesheet)
    w.setStyleSheet('%s\n\n%s' % (sheet1, sheet2))
    d.repaint_pane(pane)
    update()
</t>
<t tx="ekr.20180125102041.1">def unhighlight(pane):

    w = d.pane_widget(pane)
    if not w:
        return g.trace('bad pane', pane)
    sd = {
        'body': 'QTextEdit#richTextEdit { border: 5px solid white; }',
        'log': 'QTextEdit#log-widget { border: 5px solid white; }',
        'tree': 'QTreeWidget { border: 5px solid white; }',
    }
    sheet2 = sd.get(pane)
    if not sheet2:
        return g.trace('bad pane', pane)
    # sheet1 = ssm.expand_css_constants(c.active_stylesheet)
    sheet1 = ssm.default_style_sheet
    w.setStyleSheet('%s\n\n%s' % (sheet1, sheet2))
    d.repaint_pane(pane)
    update()
</t>
<t tx="ekr.20180125102554.1">def update():
    g.app.gui.qtApp.processEvents()
    </t>
<t tx="ekr.20180125112540.1">@language python

# Get all *closed* issues for 5.7.
g.getGitIssues(
    c = c,
    label_list = ['Bug','Enhancements'],
    milestone = '5.7',
    state = 'closed',
)
</t>
<t tx="ekr.20180125112749.1">@language python
import leo.core.leoTips as leoTips

if 1: # Creates a tree of tips from leoTips.
    leoTips.make_tip_nodes(c)
else: # Prints only open tips from GitHub.
    leoTips.make_tips(c)
</t>
<t tx="ekr.20180125113535.1">@others</t>
<t tx="ekr.20180125113541.1"># Setup
# c.frame.log.selectTab('Log')
# c.frame.log.clearLog()
ssm = c.styleSheetManager
d = demo.Demo(c)
d.delete_widgets()
# Slides
@others
# Teardown
update()
c.bodyWantsFocusNow()
</t>
<t tx="ekr.20180125235809.10">https://github.com/leo-editor/leo-editor/issues/648</t>
<t tx="ekr.20180125235809.11">https://github.com/leo-editor/leo-editor/issues/645</t>
<t tx="ekr.20180125235809.12">https://github.com/leo-editor/leo-editor/issues/641</t>
<t tx="ekr.20180125235809.13">https://github.com/leo-editor/leo-editor/issues/640</t>
<t tx="ekr.20180125235809.14">https://github.com/leo-editor/leo-editor/issues/639</t>
<t tx="ekr.20180125235809.15">https://github.com/leo-editor/leo-editor/issues/638</t>
<t tx="ekr.20180125235809.16">https://github.com/leo-editor/leo-editor/issues/634</t>
<t tx="ekr.20180125235809.17">https://github.com/leo-editor/leo-editor/issues/630</t>
<t tx="ekr.20180125235809.18">https://github.com/leo-editor/leo-editor/issues/627</t>
<t tx="ekr.20180125235809.19">https://github.com/leo-editor/leo-editor/issues/604</t>
<t tx="ekr.20180125235809.20">https://github.com/leo-editor/leo-editor/issues/603</t>
<t tx="ekr.20180125235809.21">https://github.com/leo-editor/leo-editor/issues/600</t>
<t tx="ekr.20180125235809.22">https://github.com/leo-editor/leo-editor/issues/595</t>
<t tx="ekr.20180125235809.23">https://github.com/leo-editor/leo-editor/issues/593</t>
<t tx="ekr.20180125235809.24">https://github.com/leo-editor/leo-editor/issues/591</t>
<t tx="ekr.20180125235809.25">https://github.com/leo-editor/leo-editor/issues/586</t>
<t tx="ekr.20180125235809.26">https://github.com/leo-editor/leo-editor/issues/585</t>
<t tx="ekr.20180125235809.27">https://github.com/leo-editor/leo-editor/issues/579

Added k.remove_conflicting_definitions.</t>
<t tx="ekr.20180125235809.28">https://github.com/leo-editor/leo-editor/issues/578</t>
<t tx="ekr.20180125235809.29">https://github.com/leo-editor/leo-editor/issues/573</t>
<t tx="ekr.20180125235809.3">https://github.com/leo-editor/leo-editor/issues/657</t>
<t tx="ekr.20180125235809.31">https://github.com/leo-editor/leo-editor/issues/560</t>
<t tx="ekr.20180125235809.4">https://github.com/leo-editor/leo-editor/issues/656</t>
<t tx="ekr.20180125235809.5">https://github.com/leo-editor/leo-editor/issues/654</t>
<t tx="ekr.20180125235809.6">https://github.com/leo-editor/leo-editor/issues/653</t>
<t tx="ekr.20180125235809.7">https://github.com/leo-editor/leo-editor/issues/652</t>
<t tx="ekr.20180125235809.8">https://github.com/leo-editor/leo-editor/issues/651</t>
<t tx="ekr.20180125235809.9">https://github.com/leo-editor/leo-editor/issues/649</t>
<t tx="ekr.20180125235810.1">https://github.com/leo-editor/leo-editor/issues/555</t>
<t tx="ekr.20180125235810.2">https://github.com/leo-editor/leo-editor/issues/554</t>
<t tx="ekr.20180125235810.3">https://github.com/leo-editor/leo-editor/issues/553</t>
<t tx="ekr.20180125235810.4">https://github.com/leo-editor/leo-editor/issues/552</t>
<t tx="ekr.20180125235810.5">https://github.com/leo-editor/leo-editor/issues/550</t>
<t tx="ekr.20180125235810.6">https://github.com/leo-editor/leo-editor/issues/510</t>
<t tx="ekr.20180125235810.7">https://github.com/leo-editor/leo-editor/issues/509

Serious unfixable bugs:
https://leo-editor.github.io/leo-editor/console-gui.html#unfixed-bugs
</t>
<t tx="ekr.20180125235810.8">https://github.com/leo-editor/leo-editor/issues/493</t>
<t tx="ekr.20180125235810.9">https://github.com/leo-editor/leo-editor/issues/489</t>
<t tx="ekr.20180125235811.1">https://github.com/leo-editor/leo-editor/issues/384</t>
<t tx="ekr.20180125235811.2">https://github.com/leo-editor/leo-editor/issues/362</t>
<t tx="ekr.20180125235811.3">https://github.com/leo-editor/leo-editor/issues/327</t>
<t tx="ekr.20180125235814.1">https://github.com/leo-editor/leo-editor/issues/655</t>
<t tx="ekr.20180125235814.10">https://github.com/leo-editor/leo-editor/issues/583</t>
<t tx="ekr.20180125235814.11">https://github.com/leo-editor/leo-editor/issues/577</t>
<t tx="ekr.20180125235814.12">https://github.com/leo-editor/leo-editor/issues/552</t>
<t tx="ekr.20180125235814.13">https://github.com/leo-editor/leo-editor/issues/523</t>
<t tx="ekr.20180125235814.14">https://github.com/leo-editor/leo-editor/issues/510</t>
<t tx="ekr.20180125235814.15">https://github.com/leo-editor/leo-editor/issues/503</t>
<t tx="ekr.20180125235814.16">https://github.com/leo-editor/leo-editor/issues/428</t>
<t tx="ekr.20180125235814.17">https://github.com/leo-editor/leo-editor/issues/417</t>
<t tx="ekr.20180125235814.18">https://github.com/leo-editor/leo-editor/issues/414</t>
<t tx="ekr.20180125235814.2">https://github.com/leo-editor/leo-editor/issues/635</t>
<t tx="ekr.20180125235814.3">https://github.com/leo-editor/leo-editor/issues/613</t>
<t tx="ekr.20180125235814.4">https://github.com/leo-editor/leo-editor/issues/602</t>
<t tx="ekr.20180125235814.5">https://github.com/leo-editor/leo-editor/issues/597</t>
<t tx="ekr.20180125235814.6">https://github.com/leo-editor/leo-editor/issues/596</t>
<t tx="ekr.20180125235814.7">https://github.com/leo-editor/leo-editor/issues/589</t>
<t tx="ekr.20180125235814.8">https://github.com/leo-editor/leo-editor/issues/587</t>
<t tx="ekr.20180125235814.9">https://github.com/leo-editor/leo-editor/issues/584</t>
<t tx="ekr.20180125235816.1">https://github.com/leo-editor/leo-editor/issues/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.</t>
<t tx="ekr.20180126001345.1"></t>
<t tx="ekr.20180126002550.1">.. _`LeoVue`: https://github.com/kaleguy/leovue#leo-vue

- Added Debian package for Leo.
- pip install leo (After 5.7 final).
- A web based Leo viewer, `LeoVue`_, written by Joe Orr.
- 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.
- 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.
- Added a TreePad importer.

</t>
<t tx="ekr.20180126002657.1">- Unit tests can run in more environments.
- The @g.commander_command decorator injects ivars into the Commands class.
- Added CompareLeoOutlines class in leoCompare.py
- Added verbose option to g.callers().
- Revised redraw code.
- Added backup-repo script in leoPy.leo.
- Added c.backup_helper.
- Added @button get-issues to LeoDocs.leo.
</t>
<t tx="ekr.20180126003014.1"></t>
<t tx="ekr.20180126003100.1">- New commands::

    check-conventions
    clean-main-spell-dict
    clean-user-spell-dict
    count-children
    demangle-recent-files
    diff-leo-files
    diff-and-open-leo-files
    edit-pane-csv
    edit-pane-test-open
    insert-as-first-child
    insert-as-last-child
    read-ref-file
    set-ref-file
    update-ref-file

- The cff commands now sort their results.
</t>
<t tx="ekr.20180126003420.1">reinstated --trace-shutdown</t>
<t tx="ekr.20180126003454.1">.. _`5.7 enhancements page`: https://github.com/leo-editor/leo-editor/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+milestone%3A5.7+label%3Aenhancement

- Completed 26 enhancement issues.  See the `5.7 enhancements page`_.
- Improved the javascript importer.
</t>
<t tx="ekr.20180126003617.1">- New plugins::

    patch_python_colorizer.py.
    leo_cloud.py.
    line_numbering.py

- Improved the console_gui plugin.
</t>
<t tx="ekr.20180126060924.1"></t>
<t tx="ekr.20180126060940.1"></t>
<t tx="ekr.20180126061429.10">.. _`abbreviations tutorial`: tutorial-pim.html#using-abbreviations-and-templates

Leo's abbreviations can correct spelling mistakes, expand to multiple lines
or even trees of nodes. Abbreviations can execute scripts and can prompt
for values to be substituted within the abbreviation.
See the `abbreviations tutorial`_ for more details.
</t>
<t tx="ekr.20180126061429.12">.. _`@button nodes`: tutorial-basics.html#button-and-command-nodes

`@button nodes`_ create commands. For example, ``@button my-command`` creates
the `my-command` button and the `my-command` command. Within ``@button``
scripts, c.p is the presently selected outline node.
**@button nodes bring scripts to data**.
</t>
<t tx="ekr.20180126061429.13">Become familiar with Leo's most important plugins:

- bookmarks.py manages bookmarks.
- contextmenu.py shows a menu when right-clicking.
- mod_scripting.py supports @button and @command nodes.
- quicksearch.py adds a Nav tab for searching.
- todo.py handles to-do lists and is a project manager.
- viewrendered.py renders content in the rendering pane.
</t>
<t tx="ekr.20180126061429.14">.. _`personal settings`: customizing.html#specifying-settings

Put your `personal settings`_ in myLeoSettings.leo, not leoSettings.leo.

- The leo-settings command opens leoSettings.leo.
- The my-leo-settings command opens myLeoSettings.leo.
- Copy the desired settings nodes from leoSettings.leo to myLeoSettings.leo.
</t>
<t tx="ekr.20180126061429.15">.. _`clones tutorial`: tutorial-pim.html#clones

Clones are "live" copies of the node itself and all its descendants.
See the `clones tutorial`_ for more details.</t>
<t tx="ekr.20180126061429.16">.. _`commands tutorial`: tutorial-basics.html#commands

To execute a command, type `Alt-X`, followed by the first few characters of the command name, followed by `Tab`. The list of commands matching what you have typed appears.
For more details, see the `commands tutorial`_.
</t>
<t tx="ekr.20180126061429.17">The cff command (aka clone-find-flattened) prompts for a search pattern,
then clones all matching nodes so they are the children of a new last
top-level node. This command is a great way to study code.</t>
<t tx="ekr.20180126061429.18">The cff command (aka clone-find-flattened-marked) clones all marked nodes
as children of a new node, created as the last top-level node. Use this
to gather nodes throughout an outline.</t>
<t tx="ekr.20180126061429.19">g.callers() returns the last n callers (default 4) callers of a function or
method. The verbose option shows each caller on a separate line. For
example:

.. code-block:: python

    g.trace(g.callers())

You must `launch Leo from a console window`_.
</t>
<t tx="ekr.20180126061429.2">You can have a personal shortcut to run a script while developing it. For
example: put ``@key=Alt-4`` in the headline. If your script grows to several
subnodes, you won't have to select the top node every time you wish to run
the script. Just press your universal shortcut.</t>
<t tx="ekr.20180126061429.20">The g.trace function prints all its arguments to the console. g.trace shows
patterns in running code. You must `launch Leo from a console window`_ to
see the output of g.trace.
</t>
<t tx="ekr.20180126061429.21">.. _`Python's pdb debugger`: https://docs.python.org/3/library/pdb.html

g.pdb launches `Python's pdb debugger`_, adapted for Leo.
You must `launch Leo from a console window`_ to use the pdb debugger.
</t>
<t tx="ekr.20180126061429.22">The find-quick-selected (Ctrl-Shift-F) command finds all nodes containing the selected text.</t>
<t tx="ekr.20180126061429.23">The parse-body command parses p.b (the body text of the selected node) into separate nodes.</t>
<t tx="ekr.20180126061429.24">The sort-siblings (Alt-A) command sorts all the child nodes of their parent, or all top-level nodes.</t>
<t tx="ekr.20180126061429.25">leoSettings.leo contains the defaults for all of Leo's settings, with
documentation for each.</t>
<t tx="ekr.20180126061429.26">Use Alt-N to cycle through the clones of the present cloned node.
This command is a fast way of finding the clone whose ancestor is an @&lt;file&gt; node.</t>
<t tx="ekr.20180126061429.27">.. _`cloning nodes`: tutorial-pim.html#clones

Focus your attention on the task at hand by `cloning nodes`, including
\@file nodes, then moving those clones so they are the last top-level nodes
in the outline. This organization allows you to work on nodes scattered
throughout an outline without altering the structure of @file nodes.
</t>
<t tx="ekr.20180126061429.3">When developing scripts that use the Log window to display results, it is
sometimes useful to clear the Log window by inserting the following two lines
at the beginning of your script:

.. code-block:: python

    c.frame.log.selectTab('Log')
    c.frame.log.clearLog()</t>
<t tx="ekr.20180126061429.4">Use section references only when the exact position of a section within a file matters. 

Here is a common pattern for @file nodes for python files:

.. code-block:: python

    """A docstring"""
    &lt;&lt; imports &gt;&gt;
    @others
    if __name__ == '__main__':
        main()
    @language python
    @tabwidth -4</t>
<t tx="ekr.20180126061429.5">The @button make-md-toc script in LeoDocs.leo writes a markdown table of
contents to the console. You can then copy the text from the console to
your document. The selected outline node should be an ``@auto-md`` node.</t>
<t tx="ekr.20180126061429.6">.. _`pyflakes`: https://pypi.python.org/pypi/pyflakes

`pyflakes`_ is a superb programming tool. It checks python files almost instantly.

These settings cause Leo to run pyflakes whenever saving a .py file and to
raise a dialog if pyflakes finds any errors::

    @bool run-pyflakes-on-write = True
    @bool syntax-error-popup = True
</t>
<t tx="ekr.20180126061429.7">The @nobeautify directive suppresses beautification of the node in which it appears.</t>
<t tx="ekr.20180126061429.8">.. _`pylint`: https://www.pylint.org/

Leo's pylint command runs `pylint`_ on all ``@&lt;file&gt;`` nodes in the selected trees.
Pylint runs in the background, so you can continue to use Leo while pylint runs.
</t>
<t tx="ekr.20180126061429.9">.. _`rst3 command`: tutorial-rst3.html

The `rst3 command`_ converts an @rst tree to a document file.
</t>
<t tx="ekr.20180126061923.1">#############################
Useful Tips
#############################

One of these tips appears on startup, by default.

You can disable these tips by setting @bool show-tips = False.

.. contents:: Contents
    :depth: 3
    :local:
</t>
<t tx="ekr.20180126062558.1"></t>
<t tx="ekr.20180126062701.1">.. _`launch Leo from a console window`: running.html#running-leo-from-a-console-window

</t>
<t tx="ekr.20180126062746.1"></t>
<t tx="ekr.20180126063015.1"></t>
<t tx="ekr.20180126063712.1">When True, Leo shows User Tips in a dialog on startup.
</t>
<t tx="ekr.20180126184230.1">Ctrl-P re-executes the last command made from the minibuffer.
You can use this to avoid having to define key bindings.

For example, instead of pressing an @button button, execute
its command from the minibuffer. Now you can re-execute the
button using Ctrl-P.
</t>
<t tx="ekr.20180126185857.1"></t>
<t tx="ekr.20180126190015.1"></t>
<t tx="ekr.20180126190053.1"></t>
<t tx="ekr.20180126191031.1">.. _`Anaconda`:   https://pypi.org/project/anaconda/
.. _`Miniconda`:  https://docs.anaconda.com/free/miniconda/index.html

The `Anaconda`_ scientific computing environment includes Python, NumPy, SciPy, PyQt, and over a thousand other tools, packages and libraries. It's a 500+ MB download but you're guaranteed to have everything needed.

The `Miniconda`_ environment includes just Python and the `conda` package management tool. Pick and choose from the full Anaconda ecosystem.

Preparation, create an environment for Leo, activate it, and then install python::

    conda create -n leo
    conda activate leo
    conda install python

Strictly speaking this step can be skipped and Leo installed in the conda _base_ environment. The conda developers generally advise against installing in _base_ unless this program is the only thing the machine will be used for.

To install Leo run this from a console::

    pip install leo
</t>
<t tx="ekr.20180127092625.1">https://github.com/leo-editor/leo-editor/issues/659</t>
<t tx="ekr.20180128051013.1">for pane in ('body', 'tree', 'log'):
    highlight(pane)
    d.Callout('%s %s' % (pane.capitalize(), pane), pane=pane)
    wait()
    unhighlight(pane)
</t>
<t tx="ekr.20180128052016.1"></t>
<t tx="ekr.20180128101447.1">https://github.com/leo-editor/leo-editor/issues/661
</t>
<t tx="ekr.20180128112939.1">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.
</t>
<t tx="ekr.20180130033527.1">.. _`Install pip`:      https://pip.pypa.io/en/stable/installation/               
.. _`Install Python`:   https://python.org
.. _`pip`:              https://pypi.org/pypi/pip
.. _`PyPi`:             https://pypi.org/

The following will install Leo from `PyPi`_, Python's package repository.

1. `Install Python`_ 3.9 or above.
2. `Install pip`_.
3. Download and install Leo (including all required packages)::

    python -m pip install leo
</t>
<t tx="ekr.20180130055320.1">https://github.com/leo-editor/leo-editor/issues/562</t>
<t tx="ekr.20180130092843.1">.. https://groups.google.com/forum/#!topic/leo-editor/yAtfcG6AL70

.. _`reference .leo files`: FAQ.html#what-is-a-reference-leo-file

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.
</t>
<t tx="ekr.20180130105010.1">`leoeditor/leo/core` contains a **reference .leo file**: **LeoPyRef.leo**.

This file should change only when adding new external files to Leo.

Developers should use a local copy of LeoPyRef.leo (conventionally called
**leoPy.leo**) for their own work.</t>
<t tx="ekr.20180201041411.1"></t>
<t tx="ekr.20180201101506.1">https://github.com/leo-editor/leo-editor/issues/658

The fix was in ni.compute_last_index.

</t>
<t tx="ekr.20180202061934.1">https://github.com/leo-editor/leo-editor/issues/674</t>
<t tx="ekr.20180211112158.1"></t>
<t tx="ekr.20180212065030.1">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
</t>
<t tx="ekr.20180212065845.1">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.
</t>
<t tx="ekr.20180212070758.1">Leo will show the Spell tab if:

1. The pyenchant spell checker has been installed or,

2. Leo finds a main spelling dictionary at ~/.leo/main_spelling_dict.txt.
   In this case, Leo uses a pure-python spell checker.

So if the Spell tab is not visible do the following:

- Download main_spelling_dict.zip from
  https://sourceforge.net/projects/leo/files/Miscellaneous/

- Unzip this file to ~/.leo/main_spelling_dict.txt.

The show-spell-info command tells what spell checker is in effect and the location of the main and user spell dictionaries.
</t>
<t tx="ekr.20180212070807.1"></t>
<t tx="ekr.20180212070925.1">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/</t>
<t tx="ekr.20180212071157.1"></t>
<t tx="ekr.20180212163926.1">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
</t>
<t tx="ekr.20180212164854.1"></t>
<t tx="ekr.20180212165141.1">You can open files such as CheatSheet.leo, quickstart.leo, leoSettings.leo, myLeoSettings.leo and scripts.leo with commands starting with 'leo-'.

&lt;Alt-X&gt;leo-&lt;tab&gt; shows the complete list of commands::

    leo-cheat-sheet
    leo-dist-leo
    leo-docs-leo
    leo-plugins-leo
    leo-py-leo
    leo-quickstart-leo
    leo-scripts-leo
    leo-settings
</t>
<t tx="ekr.20180216043451.7">https://github.com/leo-editor/leo-editor/issues/718
</t>
<t tx="ekr.20180216044139.1">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.</t>
<t tx="ekr.20180216063833.1">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.
</t>
<t tx="ekr.20180216082220.1">Syntax coloring is based on C.
</t>
<t tx="ekr.20180224050255.1">For each ``@button`` node, Leo adds right-click menu items for:

- ``@rclick`` nodes directly *following* the ``@button``.

- ``@rclick`` nodes that are *children* of the ``@button`` node, provided that the
  ``@button`` node has no ``@others`` directive.

**Standard rclick items**: Leo adds two standard right-click menu items for
each ``@button`` node: ``Remove Button`` and ``Goto Script``. Leo adds the
indicator text **only** to buttons that contain right-click menu items in
addition to these two standard right-click menu items.

The headline of the ``@rclick`` node gives the menu title. The body contains a
Leo script to execute when the user selects the menu item.

**Related Setting**:

``@string mod_scripting_subtext = ▼``

This setting specifies **indicator text** that indicates that an ``@button`` button has right-click menu items created by ``@rclick`` nodes.

Unicode chars like ``▼``, ``▾`` and ``…`` are typical choices for this text.
</t>
<t tx="ekr.20180226032107.1">loadOnePlugin: can not load enabled plugin: leo.plugins.viewrendered
https://github.com/leo-editor/leo-editor/issues/702

Leo fails to load when pyenchant is not installed
https://github.com/leo-editor/leo-editor/issues/707

TypeError: coercing to Unicode: need string or buffer, NoneType found
https://github.com/leo-editor/leo-editor/issues/712

TypeError: expected str, bytes or os.PathLike object, not NoneType
https://github.com/leo-editor/leo-editor/issues/713

LeoBridge not explicitly closing the Leo-Editor file leaves the Leo-Editor file open
https://github.com/leo-editor/leo-editor/issues/716

setup.py broken when installing from zipball: execGitCommand not available
https://github.com/leo-editor/leo-editor/issues/720

replace-all can not be saved with crtl + s
https://github.com/leo-editor/leo-editor/issues/722

Recover more gracefully from user errors in abbreviations
https://github.com/leo-editor/leo-editor/issues/725

help-for-command crashes when vr2 plugin is active
https://github.com/leo-editor/leo-editor/issues/734

@rclick buttons not generating commands in work files
https://github.com/leo-editor/leo-editor/issues/739
</t>
<t tx="ekr.20180226091747.1"></t>
<t tx="ekr.20180226091936.1"></t>
<t tx="ekr.20180226092312.1">Add mark/unmark-first-parents commands
https://github.com/leo-editor/leo-editor/issues/714

Predefine script_p and script_gnx values in Leo scripts
https://github.com/leo-editor/leo-editor/issues/736

Improved js_i.clean_headline. This method now applies various regex patterns to the headline to simplify the "summary" of the function, including =&gt; functions.</t>
<t tx="ekr.20180226150731.1"></t>
<t tx="ekr.20180226150747.1">Added g.execute_shell_commands_with_options.</t>
<t tx="ekr.20180226151003.1">The first section discusses three *easy* ways to run code in a separate process by calling subprocess.popen either directly or via Leo helper functions.</t>
<t tx="ekr.20180226152739.1"></t>
<t tx="ekr.20180226152802.1">It has been almost 14 months since I discovered Leo and today I recalled how I found it.

I was searching GitHub for the term "QWidgetAction" and came across its usage in Leo codebase. And then curiosity killed the cat and I was curious about Leo and read about it and downloaded it as well.
</t>
<t tx="ekr.20180226152825.1">I found Leo when I was looking for a replacement for ECCO (anyone remember that program?) I used ECCO for 15 years after it wasn't supported anymore and the core group of diehard users finally lost hope the program owners would open source the code.

Anyway, I don't remember how long ago that was; at least 10 years ago, as I recall. In most respects, Leo is a *major* improvement over ECCO and I don't regret the switch. However, the one thing I still miss about ECCO and wish there was a good Leo integration is the calendar. ECCO could print almost any kind of calendar, in practically any format on any size. I really miss that. There's no other PIM on the market that I know of that has that kind of flexibility.

Perhaps other Leo users figured out how to integrate their calendar(s) with Leo; I haven't and would love to know how (if it's possible).
</t>
<t tx="ekr.20180226152847.1">I found Leo when I was looking for an outliner that supported clones, ran on Linux, and wasn't a website. I live on a farmlet on the edge of the world and our internet has always sucked.

I took Leo up in 2007. And if there is one thing I have learned in the interval it is that with Leo, anything is possible.
</t>
<t tx="ekr.20180226152919.1">I think I was using Freemind before Leo, although I'd spent a long time using the console based outliner hnb, which apparently has been resurrected as tines https://github.com/larrykollar/tines
</t>
<t tx="ekr.20180226152943.1">I think I discovered Leo as a result of a fleeting interest in literate programming. Don't recall the date, but it was before Leo was ported from C++ to Python.

When I learned that Edward lived across town, kitty-corner from a high school sweetheart, I was SOLD!
</t>
<t tx="ekr.20180226153353.1">g.app.backgroundProcessManager is the singleton instance of the BackgroundProcessManager (BPM) class. This class runs background processes, *without blocking Leo*. The BPM manages a queue of processes, and runs them *one at a time* so that their output remains separate.

BPM.start_process(c, command, kind, fn=None, shell=False) adds a process to the queue that will run the given command:

.. code-block:: python

    bpm = g.app.backgroundProcessManager
    bpm.start_process(c, command='ls', kind='ls', shell=True)

``BM.kill(kind=None)`` kills all process with the given kind. If kind is None or 'all', all processes are killed.

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.

**Running multiple processes simultaneously**

Only one process at a time should be producing output. All processes that *do* produce output should be managed by the singleton BPM instance.

To run processes that *don't* produce output, just call subprocess.Popen:

.. code-block:: python

    import subprocess
    subprocess.Popen('ls', shell=True)

You can run as many of these process as you like, without involving the BPM in any way
</t>
<t tx="ekr.20180226154417.1">After running ``pip install leo`` from a console type::

``leo`` - start Leo in normal graphical mode (qt)
``leo-c``, ``leo-console`` - start Leo in console (curses) mode
``leo-m``, ``leo-messages`` [Windows only] - start Leo in normal (qt) mode, and echo log messages to the starting shell

The launchers are installed in ``PYTHONHOME/Scripts``.

If for some reason the launchers fail run Leo directly with::

    python path/to/leo-editor/launchLeo.py
</t>
<t tx="ekr.20180226155008.1">Calling subprocess.popen is often simple and good. For example, the following executes the 'npm run dev' command in a given directory.  Leo continues, without waiting for the command to return:

.. code-block:: python

    os.chdir(base_dir)
    subprocess.Popen('npm run dev', shell=True)

The following hangs Leo until the command completes:

.. code-block:: python

    os.chdir(base_dir)
    proc = subprocess.Popen(command, shell=True)
    proc.communicate()

**Note**: 'cd directory' does not seem to work when run using subprocess.popen on Windows 10.
</t>
<t tx="ekr.20180226155010.1">Use g.execute_shell_commands is a thin wrapper around subprocess.popen.  It calls subprocess.popen once for every command in a list.  

This function waits for each command to complete, except those commands starting with '&amp;':

.. code-block:: python

    def execute_shell_commands(commands, trace=False):
        if g.isString(commands): commands = [commands]
        for command in commands:
            wait = not command.startswith('&amp;')
            if command.startswith('&amp;'): command = command[1:].strip()
            if trace: print('\n&gt;%s%s\n' % ('' if wait else '&amp;', command))
            proc = subprocess.Popen(command, shell=True)
            if wait: proc.communicate()

For example:

.. code-block:: python

    os.chdir(base_dir)
    g.execute_shell_commands(['&amp;npm run dev',])
</t>
<t tx="ekr.20180226155010.2">g.execute_shell_commands_with_options is more flexible.  It allows scripts to get both the starting directory and the commands themselves from Leo's settings. Its signature is:

.. code-block:: python

    def execute_shell_commands_with_options(
        base_dir = None,
        c = None,
        command_setting = None,
        commands = None,
        path_setting = None,
        warning = None,
    ):
        '''
        A helper for prototype commands or any other code that
        runs programs in a separate process.

        base_dir:           Base directory to use if no path_setting is given.
        commands:           A list of commands, for g.execute_shell_commands.
        commands_setting:   Name of @data setting for commands.
        path_setting:       Name of @string setting for the base directory.
        warning:            A warning to be printed before executing the commands.
        '''

For example, put this in myLeoSettings.leo::

    @data my-npm-commands
    yarn dev

    @string my-npm-base = /npmtest

And then run:

.. code-block:: python

    g.execute_shell_commands_with_options(
        c = c,
        command_setting = 'my-npm-commands',
        path_setting= 'my-npm-base',
    )
    

</t>
<t tx="ekr.20180303013046.1">I came about Leo because I was interested in Learning Python and some forum said that Leo, not Zope, was a superb showcase for this language. I found that it supported a form of literate programming, which I was already interesting into. I started to use it almost exclusively for writing, not for programming, from note keeping to even draft of my thesis, since 2005, when I found Leo, to 2015 and then I found Pharo and Roassal and the idea of software as a graph (https://vimeo.com/94724841)

I decided to create my own outliner with ideas of Leo, Jupyter, Smalltalk and others. These days I still use Leo for quick notes and probably I would use it again to deconstruct some large script or textual program. So, my path was Python -&gt; Zope -&gt; Leo -&gt; Outlining for Literate Programming -&gt; Writing -&gt; Pharo, Roassal -&gt; Reproducible research and data storytelling and visualization -&gt; Grafoscopio. Of course, some parts were traversed in parallel and I still try to combine ideas and communities from several places.
</t>
<t tx="ekr.20180303013355.1">I've been trying to recall my own path of discovery. No concrete memory has emerged, but it was somewhere in the intersection of being dissatisfied with wiki notes and mind/concept mapping, starting to learn python, and a multi-decade quest for the perfect text editor (1999-2004, 2010). Gmail says I subscribed to the Leo mailing list in 2009 with my first concrete contribution in August -- a Windows install recipe. Huh. I'm still doing that now!

In spite of the lengthy time since discovering Leo and bringing it into my permanent toolkit, it's still not front and centre for much of my activity. Onenote desktop is my primary writing and organizing tool (the web app is ...meh) and Pyzo the first stop for exploratory python. Much as I love text I'm still a strong graphic creature. My dream writing platform is all of the best parts of rich text &amp; media editing fused with Leo's node management and scripting. Bonus points if it's webby lets me punt Wordpress and all the other web content management things I've tried and discarded (jekyll, acrylamid, drupal, mindtouch, deki-wiki, twiki).

There is substantive aroma of my dream in the air right now, which is very exciting. :)</t>
<t tx="ekr.20180303013437.1">I employed Leo for an oddball use case, which it addressed beautifully. 

How long ago did this start, perhaps 2005?

The job that I held then required that, without help from work infrastructure or from colleagues, I write tools for diagnosing and repairing problems with installations of a complicated software package and the many libraries it used. The package ran under Microsoft Windows, I had to ship the tools easily via e-mail, and they had to run easily, without requiring installation or uninstallation. 

In those less paranoid days, the flexible packaging method was a Windows Script Host file, in which Microsoft allowed scripts in the supported language of one's choice to call modules written in any other supported scripting language. Microsoft allowed the storage of multiple modules and data files in the WSH file; the format Microsoft employed for this was XML. 

The conventional approach would have been to use a commercial XML editor to build the file. XML editors were specialty products sold for huge sums to industrial combines. Commercial products were aimed at Big Enterprise Publishing with Big Enterprise Money, not at software development by a solitary programmer with a garden-variety PC and no budget. I needed to build my own editor, or I needed to write tools to pre-process each of my tools' source code and the source code for the library routines, then assemble the preprocessed code into the multiple WSFs. This would have been multiple tools, at least a preprocessor akin to the Unix "m4" command and an executable akin to Make, and those would need maintenance. I had no budget for buying software. What to use instead?  

Leo offered me a targeted IDE for Python with the ability to manage all my source code. It offered the PIM I needed to organize my development effort. 

I had to write scripts in Visual Basic Scripting Edition (VBS), because Microsoft deployed it everywhere, and because a lot of modules I could use were written in VBScript. With that in mind, I added support for VBScript to Leo's syntax highlighting. Leo's architecture made that easy. 

Each of the multiple tools that I would write would end up in a WSF of its own. Using Leo's @file commands for the individual WSFs would steer me to use a preprocessor-plus-compiler-plus-Make toolkit, so instead I reached for Leo's heritage in Literate Programming: I used Leo's now-deprecated @root command instead of the @file family of commands, and forced Leo to Tangle the section of the outline required to generate a required WSF.

That allowed me to keep a straightforward correspondence between the section of the Leo file for each tool and the WSF for the tool itself: once I told Leo to Tangle the necessary section of its outline, I knew the resulting WSFs were correctly formatted and included exactly what I required, and nothing more. 

Because the the representation of a module within a WSF was XML, the source code for that module had to be encoded, or it had to be packaged specially so that the Windows Script Host software would handle it in its original form. I did not want to do the filtering, I wanted the outline to contain the unchanged file in a Leo node in a form that would guarantee its correct representation in the WSF. I was able to figure out how to surround the source code's node in the Leo outline in a few extra nodes that would allow me to use the source code exactly as it came. That made it painless for me to add new modules to to my library.  

In those days, Leo's GUI was built on the TKinter package that shipped with Python. That release of TKinter is not beautiful by any means, but its place as one of Python's Batteries Included meant that my entire development environment consisted of the installer for Python; the installer for the pywin32 extensions to Python; the installer for Leo; and the comparatively tiny LEO file that contained my tools' source code, the source code for the library routines, and all my notes. All that went on a single CD-RW, and I could install Python and pywin32 and Leo on a Windows computer in minutes and tweak my code as needed.
</t>
<t tx="ekr.20180404015249.1">Leo 5.7.1 April 6, 2018

Leo 5.7.1, https://leo-editor.github.io/leo-editor/ is now available on
[GitHub](https://github.com/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=&lt;name&gt; 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 @&lt;file&gt; nodes, and optionally generate same in recursive imports.
- Improved menus.
- The usual minor bug fixes.

**Links**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md
</t>
<t tx="ekr.20180404015558.1">- Improved support for themes
    - Added the open-theme-file command.
    - Added --theme=&lt;name&gt; 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 @&lt;file&gt; nodes.
- Added add_path keyword argument to c.recursiveImportScript.
  This setting adds @path directives to the root node of imported files.
</t>
<t tx="ekr.20180404015644.1"></t>
<t tx="ekr.20180404015841.10">https://github.com/leo-editor/leo-editor/issues/812
PickleShareDB.keys should definitely not call g.glob_glob.
</t>
<t tx="ekr.20180404015841.11">https://github.com/leo-editor/leo-editor/issues/840
Changed c.config.getData and gcm.getData.
</t>
<t tx="ekr.20180404015841.12">https://github.com/leo-editor/leo-editor/issues/843
</t>
<t tx="ekr.20180404015841.13"></t>
<t tx="ekr.20180404015841.14">Removed unnecessary check in g.get_directives_dict.
</t>
<t tx="ekr.20180404015841.15"></t>
<t tx="ekr.20180404015841.17">They have been replaced by new eval- commands.
</t>
<t tx="ekr.20180404015841.18">https://github.com/leo-editor/leo-editor/issues/822

</t>
<t tx="ekr.20180404015841.2">https://github.com/leo-editor/leo-editor/issues/663
</t>
<t tx="ekr.20180404015841.3">https://github.com/leo-editor/leo-editor/issues/748
</t>
<t tx="ekr.20180404015841.4">https://github.com/leo-editor/leo-editor/issues/763
</t>
<t tx="ekr.20180404015841.5">https://github.com/leo-editor/leo-editor/issues/766
</t>
<t tx="ekr.20180404015841.6">https://github.com/leo-editor/leo-editor/issues/780
</t>
<t tx="ekr.20180404015841.7">https://github.com/leo-editor/leo-editor/issues/783
</t>
<t tx="ekr.20180404015841.8">https://github.com/leo-editor/leo-editor/issues/788
</t>
<t tx="ekr.20180404015841.9">https://github.com/leo-editor/leo-editor/issues/808
</t>
<t tx="ekr.20180404015923.1">https://github.com/leo-editor/leo-editor/issues/467
@string initial-chooser-directory</t>
<t tx="ekr.20180404020037.1"></t>
<t tx="ekr.20180404020226.1"></t>
<t tx="ekr.20180404020244.1"></t>
<t tx="ekr.20180404020342.1">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</t>
<t tx="ekr.20180404021227.1"></t>
<t tx="ekr.20180404021236.1">https://github.com/leo-editor/leo-editor/issues/839
The eval* commands are now in mod_scripting.py.
</t>
<t tx="ekr.20180404021543.1">https://github.com/leo-editor/leo-editor/issues/832
</t>
<t tx="ekr.20180404021630.1">https://github.com/leo-editor/leo-editor/issues/809
</t>
<t tx="ekr.20180404021737.1">https://github.com/leo-editor/leo-editor/issues/802
</t>
<t tx="ekr.20180404021814.1">https://github.com/leo-editor/leo-editor/issues/792
</t>
<t tx="ekr.20180404021847.1">https://github.com/leo-editor/leo-editor/issues/784
</t>
<t tx="ekr.20180404022106.1">https://github.com/leo-editor/leo-editor/issues/781
</t>
<t tx="ekr.20180404063924.1">Command-line options:

- Added --theme=&lt;name&gt;
- Added --trace-themes

Settings:

- Added @string theme-name
- Added @string initial-chooser-directory
  Used by Ctrl-O (file-open-by-name)
</t>
<t tx="ekr.20180404065846.1">A **theme** file is a .leo file containing appearance-related settings.  The leo/themes folder contains several examples.

The ``open-theme-file`` command will show you the effect of a theme file without changing Leo in any way.

To enable a theme, put the following setting in ``myLeoSettings.leo``::

    @string theme-name = &lt;name of theme file&gt;

**Important**: When using themes, it's best to disable all other theme-related settings in ``myLeoSettings.leo``.

Leo looks for the named .leo file in the following order::

    ~  (The users home directory)
    ~/themes
    ~/.leo
    ~/.leo/themes
    leo/themes

Theme files should contain three settings that describe the theme::

    @bool color_theme_is_dark # True for dark themes
    @string color_theme = name # Used to find icons
    @string theme_name # Used to find other graphics elements.
</t>
<t tx="ekr.20180404070940.1"></t>
<t tx="ekr.20180404172529.1">When True, adds @path directives to the root node of imported files.
</t>
<t tx="ekr.20180411070654.1">May 7, 2018

Leo 5.7.2, https://leo-editor.github.io/leo-editor/ is now available on
[GitHub](https://github.com/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**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md
</t>
<t tx="ekr.20180411071648.1">#850: Optionally convert Meta to Alt on MacOs
https://github.com/leo-editor/leo-editor/issues/850
This feature is disabled by default. To enable, set @bool replace-meta-with-alt = True.
</t>
<t tx="ekr.20180411071733.1">- @bool replace-meta-with-alt.
</t>
<t tx="ekr.20180411073507.1"></t>
<t tx="ekr.20180411102234.1">https://github.com/leo-editor/leo-editor/issues/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:

    &lt;h1...9&gt;title&lt;/h1...9&gt;

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.
</t>
<t tx="ekr.20180411105215.1">https://github.com/leo-editor/leo-editor/issues/794
</t>
<t tx="ekr.20180411150947.1"></t>
<t tx="ekr.20180411150950.1">https://github.com/leo-editor/leo-editor/issues/757
</t>
<t tx="ekr.20180427125919.1">https://github.com/leo-editor/leo-editor/issues/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
</t>
<t tx="ekr.20180427130017.1"></t>
<t tx="ekr.20180427130028.1">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 =</t>
<t tx="ekr.20180427130312.1">- 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.
</t>
<t tx="ekr.20180501163005.1">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:

A. Within [*] parts, all non alphanums are removed, except ":" and "-" and blanks.
B. Same for (*) parts, except that blanks are converted to "-".

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

4. 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.</t>
<t tx="ekr.20180505114327.1"></t>
<t tx="ekr.20180505114327.10">.. https://github.com/leo-editor/leo-editor/issues/857

Marcel Franke showed how to use the recommended way of using git branches:
https://groups.google.com/d/msg/leo-editor/p_6ljMQL660/57Z8lYuQAAAJ

Here are his remarks, slightly edited:

- **master** is stable.
- **devel** is "mostly" stable.
- **feature branches** off devel can be wildly unstable.
- **release branches** are candidates for master, so should be stable. 

Everything new comes from devel and goes to devel. Devs **must** run unit tests before pushing to devel, so devel should usually be stable.

All experimental code should reside in a feature branch.

At all times, anyone can pull stable code from master.

Only the maintainer (EKR) is supposed to work on release or master, so nobody needs to hold back or knows what is going on in them. At all times everyone can happily hack on devel,  or better, their personal feature branches.

To prepare a new release,  the maintainer branches devel to a new branch, say 6.x.y.  The maintainer runs tests on it, and makes any last-minute fixes. To publish the release, the maintainer merges the release to master **and** to devel, then optionally deletes the release branch.

This visualization made it all clear to me:
https://blog.seibert-media.net/wp-content/uploads/2014/03/Gitflow-Workflow-3.png</t>
<t tx="ekr.20180505114327.11">.. https://github.com/leo-editor/leo-editor/issues/859

This lesson discusses the *process* of making arbitrarily complex changes throughout a code base.
  It's an elaboration of Lesson 1: Think process, not knowledge, but it's worth reading because it contains helpful hints about tackling *any* big project.  I used this general method when making Leo's code base work with Python 3 as well as Python 2.

The grand summary:

1. Study the code first with clone-find commands.
2. Let python crashes &amp; failed unit tests guide you.

In detail:

1. Create a new git branch for the work.

2. Create a **global master switch** (a boolean) that separates and
   marks the old and new versions of the code. The switch selects the
   new code if True and the old code otherwise.

- All unit tests should continue to pass when the switch selects legacy code.
- All pushes should have the legacy code selected until every works.

These two requirements make it safe to pause work on the project.

3. Make sure you understand what needs to be done.  Use the clone find commands to answer any and all questions about the code and how it should be changed.

4. Make the fundamental changes required, **without worrying about the consequences**.

For the "keys" branch I changed the representation of settings so that they are NewLeoKey objects.

5.  With the switch in the "new" position, run a test copy of Leo.

Because of step 4, we *expect* crashes.  Fix each as they happen, separating the old and new code with a test on the switch.  Repeat this step until no crashes happen.

When this phase works, set the switch to "legacy", re-run all unit tests, and commit the code.

6. For the "keys" branch, getting through startup is only half the task.  When I type a key I *expect* more crashes.  I'll follow step 5 until no crashes happen when I type various key combination.

Again, I'll set the switch to "legacy", re-run all unit tests and commit the code.

7. When normal operation appears to work with the switch in the "new" position, **run all unit tests** and fix any crashes or unit tests failures.

Now you can commit the code with the switch in the "new" position.

8. At this point you can start eating your own dog food.  When satisfied that the code is stable enough, you can do the following:

- Remove the switch and all code disabled when the switch is in the "legacy" position.
- Run all unit tests.
- Continue to eat your own dog food.
- Commit the branch to "devel" when all seems well.

That's the process.  It's extremely effective.  You don't have to remember your changes because a cff on the switch should yield *all* changed code.  Naturally, you can make clones of nodes containing the most important changes.</t>
<t tx="ekr.20180505114327.12">.. https://github.com/leo-editor/leo-editor/issues/891

From this post: https://groups.google.com/forum/#!topic/leo-editor/SjHfXepxiTo
Not everyone agrees with everything I say here.

This LeoU discussion discusses the present code base only. #883 (a low priority item) discusses ways in which the tree of vnodes could be decoupled from c, the Commands instance. 

**The Position class**

The Position class concerns itself only with traversing the tree. The position class contains no node-related data.  In order to insert top-level nodes, methods of the Position class gets access to c.hiddenRootNode via p.v.context. 

**The VNode class**

The VNode class contains all data in an outline, as well as crucial, low-level operations on those data. There is no other place to store node-related data. 

The VNode class is one of the foundations of Leo's scripting. As a result, *none* of the ivars or methods of the VNode class can change in any way. That is, all of the ivars of the VNode class are "official". Scripts can, and do, access these ivars directly. Perhaps the "context" kwarg of `VNode.__init__` should just be called "c", but that can't be done now.

Theoretically, it would be possible to add new kwargs to VNode methods, but that is extremely unlikely. It would also be possible to add new ivars to the VNode class, but uA's make that unnecessary.

The properties of the VNode class, v.b, v.h, v.gnx, v.u, allow higher-level access to various VNode ivars, but in some cases Leo's code accesses the corresponding ivars directly, for greater performance.

**Interaction with other classes**

The v.context ivar is controversial. In fact, the v.context ivar is completely benign. It has never caused problems, and it never will. It does not, in any significant way, make the VNode class dependent on any other class. It has no harmful architectural consequences.

Yes, the FileCommands class must know about gnx's, but *the converse is not true*.  The VNode class knows nothing about how other classes use gnx's.  The FileCommands class creates VNode instances without knowing *anything* about low-level VNode methods.

The VNode class is, in fact, an excellent example of information hiding.  The boundary between the VNode class is well defined and well enforced.

**Possible improvements**

1. A new c.new_vnode method could help instantiate VNodes:

.. code-block:: python

    def new_vnode(self, gnx=None):
        c = self
        return leoNodes.VNode(context=c, gnx=gnx)

The (small) advantage is that clients of c.new_vnode(gnx) would no longer need to import leo.core.leoNodes.

2. The  v.saveCursorAndScroll and v.restoreCursorAndScroll could be moved elsewhere. At present, these methods cause no problems, but moving them would be part of #883.</t>
<t tx="ekr.20180505114327.3">.. https://github.com/leo-editor/leo-editor/issues/786

I recommend using the organization of leo/themes/EKRDark.leo as a guide. **Note**: Syntax coloring settings are required because they are *not* used in the css.

To avoid confusion, it's best if theme .leo files contain no **unbound settings**. This will ensure that the appearance of a theme does not unwittingly depend on settings in myLeoSettings.leo.

**Important**: Theme devs should set the following **theme description settings**::

    @string theme_name   # crucial
    @bool color_theme_is_dark
    @string color_theme = ekr_dark

These settings ensure that relative urls (including ":/" syntax are resolved properly in css, and that icons are found in the proper directories.

**Icons boxes should have constant width**.  Otherwise, the variable indentation of the rest of the headline appears to represent variable outline structure, which is highly confusing.
</t>
<t tx="ekr.20180505114327.5">.. https://github.com/leo-editor/leo-editor/issues/817

Programming is *much* easier than you might think.

Many of Leo's most important devs made major contributions to Leo without asking me a single question.  Do they have super powers?  No, they don't.

But they do know the secret of programming: **Simple processes, endlessly repeated, suffice to find, understand and change *any* software**.  And Leo simplifies these techniques even further.  Here they are...

**Basic skill/process 1: Familiarize yourself with the code**

For any project you want to know what files exist.  When studying other people's code I use a recursive import script https://github.com/leo-editor/leo-editor/issues/846 to create a tree of files. The goal is just to have a *vague* understanding of what files are involved. Don't even think about remember details.

It's even easier with Leo.  LeoPy.py contains Leo's sources.  Peruse this outline, seeing what ``@file`` nodes it contains.

*Don't make a big deal about this step*. It should just take 5 or 10 minutes. Look *only* at files that interest you. In those files you will probably want to look briefly at the top-level classes in the files that interest you. You will likely repeat this step many times, adding a little to your understanding each time.

**Basic skill/process 2: Learn what to search for**

We devs often want to change how commands work.  You can usually find the top-level code for a command simply by searching for the command's name, in single quotes.

To find the definition of a method, function or class, simply control-click on it.  That will start a search for def x and class x.  If that doesn't work, a cff (clone-find-all-flattened) search on a name will find all uses of that name in the present outline.

**Basic skill/process 3: Look for helpers in child nodes**

With Leo outlines **it's natural to put a method's helpers in child nodes**. I usually forget implementation details, but the children of a node usually contain most of the details.

**Basic skill/process 4: Use clones to organize and remember your work**

When working on a project I make create an organizer node as the last top-level node of the outline.  This node will typically contain a link to the github issue.  I make clones of all relevant nodes and move them so they are clones of the organizer node.  For complex projects I may create subsidiary organizer nodes, like "changed", "reference", etc.

When a project is done (or suspended), I move the project's organizer node so it is the last child of *another* organizer node called "Recent Code". This hides all work except the what I am, this minute, working on.  This is important: it hides details and lessens distractions.

**Summary**

The easy processes just described form the basis for programming workflow.

*Expect to repeat these processes many times*.  Don't worry if not everything is clear at first.</t>
<t tx="ekr.20180505114327.6">.. https://github.com/leo-editor/leo-editor/issues/818

I recommend using github issues to track your work. This is especially true for Leo devs.  You want other people to be able to follow and comment on your work.

The convention is to have the first comment for any issue contain an up-to-date summary of the status of the issue.  I have found that it is useful to continually edit the first comment.</t>
<t tx="ekr.20180505114327.7">.. https://github.com/leo-editor/leo-editor/issues/836

Here are the basics of debugging with Leo:

**g.trace**

`g.trace(*args, **kwargs)` prints its arguments to the console.  I use g.trace all throughout Leo's code base.

**g.pdb**

`g.pdb()` invokes python's pdb debugger, https://docs.python.org/3/library/pdb.html, adapted to Leo's Qt gui.  I use g.pdb when g.trace doesn't tell me enough.
</t>
<t tx="ekr.20180505114327.8">.. https://github.com/leo-editor/leo-editor/issues/837

​All devs must run all unit tests before commit anything. Here's how::

    cd &lt;path to&gt;leo-editor
    python -m unittest %*

**Important**: Some unit tests may fail on your environment.  Don't worry about them.  You need only ensure that your new code causes no *new* unit tests to fail.  If in doubt, ask on leo-editor.</t>
<t tx="ekr.20180505114327.9">.. https://github.com/leo-editor/leo-editor/issues/846

c.recursiveImport is a wrapper on the RecursiveImportController class.​ ​You can find the related code by doing a regex cff (ignoring case) on ​ ​"recursive?import".

Here is how to use c.recursiveImport:

.. code-block:: python

    c.recursiveImport(
        dir_ = &lt;&lt; path to root directory &gt;&gt;,
            # You must expand ~ yourself
        kind = '@clean', # '@clean', @nosent','@auto','@file'
        recursive = True,
        safe_at_file = False,
        theTypes = ['.py',],
    )

I like to import to @clean and set safe_at_file = False, but *before doing that* I create a git repo for the to-be-imported directory and check in all the .py files. That way I can track any changes that get made, and revert them if need be.</t>
<t tx="ekr.20180505114332.13">https://github.com/leo-editor/leo-editor/issues/877
</t>
<t tx="ekr.20180505114332.14">https://github.com/leo-editor/leo-editor/issues/879
</t>
<t tx="ekr.20180505114332.15">https://github.com/leo-editor/leo-editor/issues/880
</t>
<t tx="ekr.20180505114332.17">https://github.com/leo-editor/leo-editor/issues/884
</t>
<t tx="ekr.20180505114332.18">https://github.com/leo-editor/leo-editor/issues/886
</t>
<t tx="ekr.20180505114332.2">https://github.com/leo-editor/leo-editor/issues/423

Related issues:

- https://github.com/leo-editor/leo-editor/issues/850
- https://github.com/leo-editor/leo-editor/issues/850
- https://github.com/leo-editor/leo-editor/issues/869
- https://github.com/leo-editor/leo-editor/issues/870
- https://github.com/leo-editor/leo-editor/issues/882
</t>
<t tx="ekr.20180505114332.5">https://github.com/leo-editor/leo-editor/issues/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.</t>
<t tx="ekr.20180505114332.8">https://github.com/leo-editor/leo-editor/issues/862
</t>
<t tx="ekr.20180505114332.9">https://github.com/leo-editor/leo-editor/issues/863
</t>
<t tx="ekr.20180505141445.1">.. https://github.com/leo-editor/leo-editor/issues/890

By the term architecture I mean the design of Leo's modules and classes.

**Information hiding**

Leo's design is based on the thinking of Glenford Meyers. Let's use the word component to mean either a Python module or class.

We devs must be able to change the implementation of a component without affecting any other code. This has been true throughout Leo's 20+ years of history. This is the foundation on which Leo is built.

**Principle 1**: Each class should concern itself with one, easily defined "area of concern".

Modules should contain related classes. All components should have short, simple descriptions, no matter how complex they are internally.

**Principle 2**: Components should know as little as possible about the internal details of other components.

Components have well-defined boundaries. The inside of a component contains the implementation. The outside of a component is its API.

Changes to the API can break code. However, knowing about the existence of a component's high-level methods does not (usually) blur the boundaries of a component!

In most cases, components should know nothing about the ivars and low-level methods. However, components can freely use the so-called official ivars of other classes. These official ivars are highly unlikely ever to change. And they are useful. We wouldn't want to require long-winded alternatives to, say, c.frame.body.wrapper.

**Class design: inheritance vs instantiation**

Leo uses the "has-a" pattern, rather than the "is-a" class pattern. That is, Leo gains access to the capabilities of other classes by instantiating the other classes rather than being subclasses of other classes. The "has-a" pattern is a personal preference of mine, and is now pretty much baked into Leo.

The "has-a" pattern completely insulates classes from the internal details of other classes. There is no need to worry about clashing ivars, or _ ivars, etc. Otoh, the "has-a" pattern results in more complex startup code. Imo, that "extra" complexity is well worthwhile.</t>
<t tx="ekr.20180509042555.1">##############
Leo University
##############

.. _`LeoU issues`: https://github.com/leo-editor/leo-editor/issues/816

This is a backup of the online `LeoU issues`_.
</t>
<t tx="ekr.20180509122406.1">May 28, 2018
Leo 5.7.3, https://leo-editor.github.io/leo-editor/ is now available on
[GitHub](https://github.com/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**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md
</t>
<t tx="ekr.20180509122603.1">Added c.diff_file, c.diff_two_branches and c.git_diff. Examples::

    # creates outline-oriented diffs between all changed files between any two revs.
    # In this case, rev1 is the last rev in devel not affected by removing trace statements.

    c.diff_two_revs(
     rev1="24abd822b", # devel
     rev2="HEAD", # will work in *any* branch
    )

    # Leo's git-diff command:
    c.git_diff()

    # Compares a file in two different branches:
    c.diff_two_branches(
        branch1='master',
        branch2='devel',
        fn='leo/core/leoCommands.py',
    )
</t>
<t tx="ekr.20180509122901.1">For documentation, see the leo/plugins/leo_babel/doc folder.</t>
<t tx="ekr.20180509123007.1">https://github.com/leo-editor/leo-editor/issues/892
</t>
<t tx="ekr.20180509123013.1"></t>
<t tx="ekr.20180509123018.1"></t>
<t tx="ekr.20180509125836.1"></t>
<t tx="ekr.20180509125839.1">https://github.com/leo-editor/leo-editor/issues/875</t>
<t tx="ekr.20180510093733.1">- Removed @bool trace_import.
- Removed @bool trace_bind_key_exceptions.</t>
<t tx="ekr.20180511061629.1">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.</t>
<t tx="ekr.20180511062809.1">https://github.com/leo-editor/leo-editor/issues/901
</t>
<t tx="ekr.20180511101509.1">https://github.com/leo-editor/leo-editor/issues/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.</t>
<t tx="ekr.20180522101650.1">Clicking on underlined links in the log pane takes you to the proper node and line.</t>
<t tx="ekr.20180522101756.1">BackgroundProcessManager.start_process now takes two new kwargs:  link_pattern and link_root:

- link_pattern: a regex string or compiled regex pattern, used to determine whether a message contains a link.

- link_root: the root @file node.

When present, bpm.put_log uses these as follows::

    unl = link_root.get_UNL(with_proto=True, with_count=True)
    nodeLink = "%s,%d" % (unl, -line)
    c.frame.log.put(s + '\n', nodeLink=nodeLink)
</t>
<t tx="ekr.20180522121943.1">Allow local overrides of @data global-abbreviations &amp; @outline-data tree-abbreviations
https://github.com/leo-editor/leo-editor/issues/904</t>
<t tx="ekr.20180523053906.1"></t>
<t tx="ekr.20180523053913.1">https://github.com/leo-editor/leo-editor/issues/909
</t>
<t tx="ekr.20180523063338.1">https://github.com/leo-editor/leo-editor/issues/910</t>
<t tx="ekr.20180523085523.1">@language python
# Get all info and summary issues.
g.getGitIssues(
    c=c,
    label_list = ['LeoU',], # 'Info', 'Summary'
    milestone = None,
    state = None, # Get both open and closed issues.
)
</t>
<t tx="ekr.20180523085905.1"></t>
<t tx="ekr.20180523085918.1"></t>
<t tx="ekr.20180523093753.1"></t>
<t tx="ekr.20180523095243.1">https://github.com/leo-editor/leo-editor/issues/906
#684 Envisages creating a browser gui for Leo, but that's not a high priority at present.

The following projects are **highly risky** and may be **less useful** than might appear at first.  If you are interested in either project, please make yourself known to Leo's core devs **before** doing any programming work. See the post [Leo can be embedded in VS Code if...](https://groups.google.com/forum/#!topic/leo-editor/uESWp-eL8AY) for more details.

**Dubious Project 1**: Leo can be embedded in VS Code (or other platform) if:

a) Somebody (not one of Leo's present devs) takes full responsibility for doing so.
b) All appropriate unit tests pass.
c) Terry and I approve.

The post [ENB: Serious doubts about embedding Leo](https://groups.google.com/d/msg/leo-editor/4kYSK-aIHRg/o0ejILh1AgAJ) tells why trying to embed Leo in another IDE might be a big mistake:

- Embedding Leo in any IDE would be a huge and risky project.
- Such a project would distract us Leo devs, and burden us with endless support.
- Embedding Leo would be less useful than it might seem.
- Leo has its own strengths. Many don't translate easily to other IDE's.

**Dubious Project 2**: Leo can be rewritten in JavaScript (or other language) if:

a) Somebody (not one of Leo's present devs) takes full responsibility for doing so.
b) All appropriate unit tests pass.
c) Leo's python API remains completely unchanged.
d) Terry and I approve.

The post [ENB: Why python will remain Leo's future](https://groups.google.com/forum/#!msg/leo-editor/EaAX7R3_3N0/jKuCjwcuCgAJ) tells why rewriting Leo's core would likely be a mistake. Python is:

- Best for users as the simplest and most flexible scripting language.
- The basis for Leo's API.
- Able to support scripting in any language.</t>
<t tx="ekr.20180523095243.10">https://github.com/leo-editor/leo-editor/issues/715
The following is a reformatting and summary of the readme file in [aspell6-en-2017.08.24-0](http://wordlist.aspell.net/). Closing this issue also closes #711.

**Installation**

- aspell and preunzip are already installed on my Ubuntu system.
- Installed pyenchant in `~/anaconda2` with `PIP install pyenchant`.
- /usr/share/aspell contains many en_*.cwl.gz files.
- /usr/lib/aspell contains many .rws files. These are compressed (binary) files containing spelling lists.

**Expanding dictionaries**

- .cwl files are compressed word lists.
- Googling "aspell uncompile .rws files" yields [this page](https://superuser.com/questions/137957), which gives:

    aspell -d en dump master | aspell -l en expand &gt; en.txt

This works! en.txt contains 9789 lines.</t>
<t tx="ekr.20180523095243.11">https://github.com/leo-editor/leo-editor/issues/710
[This post](https://groups.google.com/d/msg/leo-editor/dy132kU7EnA/S8AIaJ-zBgAJ) by David Szent-Györgyi discusses distributions issue for Windows. My present plan is to leave the NSIS installer unchanged.  The Windows pyinstaller distro will be based on 32-bit code.

I installed 32-bit Anaconda2-5.0.1-Windows-x86.exe, but pyinstaller is incompatible with PyQt4. [This page](https://stackoverflow.com/questions/21637922) tells how to install PyQt4 on Python 2.  The following is a bit different, but works:
```
conda uninstall anaconda-navigator
conda uninstall navigator-updater
conda install qt=4
```
And now pyinstaller works!
```
[a32] pyinstaller --clean --win-private-assemblies launchLeo-unified.spec
```
The second comment here gives scripts for switching between 32 and 64 bit installs.</t>
<t tx="ekr.20180523095243.12">https://github.com/leo-editor/leo-editor/issues/703
[This page](https://electronjs.org/docs/tutorial/quick-start#write-your-first-electron-app) describes how to create the "hello world" electron app.  **Notes**:

- `npm install -g electron` installs to `C:\Users\edreamleo\AppData\Roaming\npm\electron`

A newbie mistake: The -g option is important.  Otherwise the npm gets installed in a node_modules folder in the current directory!

- I created the basic files in c:\test\eleo: 

  @clean c:/test/eleo/package.json
  @file c:/test/eleo/main.js
  @clean c:/test/eleo/index.html

- Running this eleo.bat script runs the hello world script successfully.

    cd c:\test\eleo
    C:\Users\edreamleo\AppData\Roaming\npm\electron .

[This page](https://electronjs.org/docs/tutorial/debugging-main-process#debugging-the-main-process) tells how to debug an electron app in Chrome. Very cool</t>
<t tx="ekr.20180523095243.13">https://github.com/leo-editor/leo-editor/issues/701
This item is motivated by [this](https://stackoverflow.com/questions/10775351/combining-node-js-and-python) stack overflow item.

Installing the **python** zerorpc is easy: `PIP install zerorpc`

Install node.js from node-v8.9.4-x64.msi. To test, type `npm` from a console.

`npm install zerorpc` **FAILS**

Googling finds [npm windows-build-tools](https://github.com/felixrieseberg/windows-build-tools/issues/56). This installs Visual C++ Build Tools 2015(!)

Install windows-build-tools, do the following **in an administrative powershell**:
```
    npm install -g --production --windows-build-tools
    added 128 packages in 460.125s
```
Now the following works:

    npm install -g zerorpc

To test, run the following in **separate consoles**:
```
python c:\test\zerorpc.py
node c:\test\zerorpc.js
```
The output in the node console is "Hello, World!"</t>
<t tx="ekr.20180523095243.14">https://github.com/leo-editor/leo-editor/issues/699
Here is how I installed Anaconda3 on Windows 10:

  Downloaded Anaconda3-5.0.1-Windows-x86_64.exe
  Install to c:\Anaconda3
  Added c:\Anaconda3 and c:\Anaconda3\scripts to my user path
  PIP install zerorpc
  Install node.js from node-v8.9.4-x64.msi
  npm install zerorpc **FAILS** Googling gives [this page about windows-build-tools](https://github.com/felixrieseberg/windows-build-tools/issues/56).

**Install [windows-build-tools](https://www.npmjs.com/package/windows-build-tools)**

Run in administrative powershell:
```
    npm install --global --production --windows-build-tools
    added 128 packages in 460.125s
```
This downloads and installs Visual C++ Build Tools 2015.

**Status**

- pylint version is 1.7.4: no need to downgrade to 1.7
- Leo runs, but without spell checking. See [this post](https://groups.google.com/d/msg/leo-editor/HzxTtIQjxuY/29JoaJYDBgAJ).
`conda install pyenchant` fails: The 'enchant' C library was not found.</t>
<t tx="ekr.20180523095243.15">https://github.com/leo-editor/leo-editor/issues/688
Here is how I installed python2 and python3 on Windows.  This issue will remain open indefinitely.
```
# Install Miniconda itself
Install Miniconda3 to c:\Miniconda3.
Added c:\Miniconda3 and c:\Miniconda3\scripts to my local PATH variable.

   `conda list` lists only basic install tools: There is no python installed yet.

# Create the python2 and python3 environments
conda create -n python3 python=3
conda create -n python2 python=2

# Install pyqt
conda install -n python2 pyqt
conda install -n python3 pyqt

# Note: this would also have worked:
activate python2
conda install pyqt
activate python3
conda install pyqt

# Test launching Leo:
python c:\leo.repo\leo-editor\launchLeo.py --gui=qttabs

# Add a2 and a3 batch files as abbreviations:
a2.bat: activate python2
a3.bat: activate python3

# The rest of the installations were done after doing a2 and/or a3:
(python2/3) PIP install pyenchant
(python3) conda install jupyter
(python2/3) conda install docutils
(python2/3) conda install pyflakes
(python2) PIP install html
(python3) PIP install html **FAILS**
(python2/3) conda install markdown
(python2/3) conda install networkx
(python2/3) conda install pylint (works, but pylint is buggy)
(python2/3) conda install pylint=1.7 (downgrade warning accepted)

# Install pyinstaller and fix for a recent pyinstaller bug:
# https://github.com/pyinstaller/pyinstaller/pull/3233#issuecomment-362094587
(python2/3) PIP install pyinstaller
(python2/3) PIP install https://github.com/bjones1/pyinstaller/archive/pyqt5_fix.zip

pyinstaller --clean --win-private-assemblies launchLeo-unified.spec FAILS:
    Cannot find existing PyQt5 plugin directories
    Paths checked: C:/Users/builder/3/conda-bld/qt_1505994166793/_h_env/Library/plugins

renamed pylint.bat to ll.bat, to invoke pylint properly.

# Changed the target of the command-prompt alias:

    %windir%\system32\cmd.exe "/k c:\scripts\a3.bat"
    # /k executes a3.bat without ending the shell
```

**Notes**

- jupyter should have been installed in a separate jupyter environment, not in the python3 environment.
- Pylint complains about html.parser in the python2 environment.</t>
<t tx="ekr.20180523095243.16">https://github.com/leo-editor/leo-editor/issues/681
There is much to be learned this way.

- [ ] [atom](https://atom.io/docs) is built on electron.
- [ ] [cmap](http://cmap.ihmc.us/): **To do**.
- [ ] [docear](http://www.docear.org/): **To do**.
- [ ] [electron](https://electronjs.org/docs): **To do**. 
- [ ] [jupyter](http://jupyter.org/) and [IPython](https://ipython.org/): In progress.
- [ ] [org mode](https://orgmode.org/): In progress.
- [ ] [LaTex](https://www.latex-tutorial.com/tutorials/): In progress.
- [ ] [PanDoc](https://pandoc.org/): **To do**.
- [ ] [TiddlyWiki](https://tiddlywiki.com/): In progress
- [ ] [xiki](http://xiki.org/): **To do**. See #671 and the leoscreen.py plugin.

And plugins, especially those mentioned recently:

- [ ] backlink.py: Allows arbitrary links between nodes.
- [ ] leoscreen.py: Allows interaction with shell apps via screen.
- [ ] valuespace.py: Supports per-Leo-outline namespaces.
      This plugin creates live objects.  Would it be possible to use them for auto-completion?

And essential python tools:

- [x] [virtualenv](https://virtualenv.pypa.io/en/stable/): This has destroyed my previous Anaconda3 environment.
- [ ] Use Anaconda's conda manager to [manage separate environments](https://conda.io/docs/user-guide/tasks/manage-environments.html)
    This is proper way to set up environments in the Anaconda world.</t>
<t tx="ekr.20180523095243.17">https://github.com/leo-editor/leo-editor/issues/636
_Strictly speaking this is an upstream issue and isn't Leo's problem, but prospective Leo users run into it, so lets document the problem and the workarounds. From mailing list:_

    VR&gt; PyEnchant is now also available as a wheel for Python 2.7 as well as Python 3.x. - See
    VR&gt;
    VR&gt; * https://pypi.python.org/pypi/pyenchant/2.0.0

Unfortunately pyenchant binaries via pip are not available for all platforms, most notably missing is Windows 64bit Python. The issue is 3 years old so a solution doesn't seem to be imminent.

I could add an IF-THEN to setup.py to install it for supported platforms, but have hesitated this far because it would add yet another special case to the install instructions.

~~~
&gt; python --version
Python 3.6.3 :: Anaconda, Inc.

&gt; pip install pyenchant
Collecting pyenchant
  Downloading pyenchant-2.0.0.tar.gz (64kB)
    100% |████████████████████████████████| 71kB 607kB/s
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "&lt;string&gt;", line 1, in &lt;module&gt;
      File "C:\Users\matt\AppData\Local\Temp\pip-build-bzioz5jr\pyenchant\setup.py", line 212, in &lt;module&gt;
        import enchant
      File "C:\Users\matt\AppData\Local\Temp\pip-build-bzioz5jr\pyenchant\enchant\__init__.py", line 92, in &lt;module&gt;
        from enchant import _enchant as _e
      File "C:\Users\matt\AppData\Local\Temp\pip-build-bzioz5jr\pyenchant\enchant\_enchant.py", line 145, in &lt;module&gt;
        raise ImportError(msg)
    ImportError: The 'enchant' C library was not found. Please install it via your OS package manager, or use a pre-built binary wheel from PyPI.

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in C:\Users\matt\AppData\Local\Temp\pip-build-bzioz5jr\pyenchant\
~~~

Also see 
* https://github.com/leo-editor/leo-editor/issues/324
* https://stackoverflow.com/questions/29381919/importerror-the-enchant-c-library-was-not-found-please-install-it-via-your-o
* https://github.com/rfk/pyenchant/issues/42</t>
<t tx="ekr.20180523095243.18">https://github.com/leo-editor/leo-editor/issues/551
I put some .leo files into a git repo. I open a .leo file and change nothing but save it again, it will be marked as changed in the repo. `git diff` shows that many lines have changed. I checked the diffs, and typically these changes are about accessing time etc.

How to make .leo files happy in a git repository? I mean, if nothing about the content changes, these files will keep clean to a git repo. Or could I use git only to trace the changes of outline nodes?</t>
<t tx="ekr.20180523095243.19">https://github.com/leo-editor/leo-editor/issues/517
I have noticed some methods that are not mentioned in documentation nor used in leoSettings.leo.
We should either remove them or document them properly. 

Here is a suspect list:
1. `doAbbrev` and `parseAbbrevLine`
2. I am not 100% sure about this, but shouldn't `doOutlineData` return 'skip'?
3. `doPage`  empty method, can't figure why?

I am working on standalone script for analyzing settings outlines and I want to be clear on what kind of settings are to be supported and which can be skipped in new code.</t>
<t tx="ekr.20180523095243.2">https://github.com/leo-editor/leo-editor/issues/883
**Update**: I think it's time to do this, while I am making other changes to Leo's code base.

This issue records my thoughts here to complete [recent discussions](https://groups.google.com/forum/#!topic/leo-editor/wMlURDDDUvY). To create a stand-alone tree of VNodes the following would be required:

- [ ]Redirect all generators in the node c.Generators on corresponding new Position generators.  There are only 5 such methods.

- [ ] Move v.saveCursorAndScroll and v.restoreCursorAndScroll into the Commands class.

- [ ]Create a new GnxManager class, accessible via g.app.gnxManager.

At minimum, the GnxManager class would be a straightforward refactoring of the NodeIndices class in leoNodes.py.  However, the new GnxManager might also manage a global cache of already-generated gnx's. This might ensure that *different instances* of Leo could not possibly allocate (on a local machine) conflicting gnx's.

At present, at.readPostPass and its helpers check for conflicting gnx's.  The GnxManager class might simplify this code, or it might be a "belt and suspenders" check.</t>
<t tx="ekr.20180523095243.20">https://github.com/leo-editor/leo-editor/issues/486
This could be called a Windows 10 bug.  Leo can do nothing about it, because the bug causes Windows 10 not to pass the Ctrl-).  Apparently Windows 10 binds `Ctrl-)` to something, but I can not find out what.

At one time there was a workaround involving, iirc, a change to the windows registry, but just now googling does not turn up anything.</t>
<t tx="ekr.20180523095243.21">https://github.com/leo-editor/leo-editor/issues/355
This is an information item about a [Python bug](http://bugs.python.org/issue25778) that can't be fixed in Leo, but has been fixed in Python 3.6.1. The bug affects windows users using Python 3.x on some (not all) versions of Windows 10.  The initial bug report was on leo-editor, [here](https://groups.google.com/d/msg/leo-editor/Q8B0gNeaKfc/-9zTKOgzCQAJ).</t>
<t tx="ekr.20180523095243.22">https://github.com/leo-editor/leo-editor/issues/324
I am writing these notes why the details are fresh in my mind.

The latest version of Anaconda is [here](https://www.continuum.io/downloads). Older versions are [here](https://repo.continuum.io/archive/).

Install the 32-bit version of Anaconda. pyenchant does not work with 64-bit installs.
- The 32-bit and 64-bit versions of Anaconda 4.0 and 4.1 **do** work.
- The 64-bit versions of Anaconda 4.0 and 4.1 **don't** work with pyenchant (spell checker)
- **No** version of Anaconda 4.2 works.  They crash and don't draw the tree properly. This is apparently a PyQt 5.6 bug.

When installing any version of Anaconda:
- Check "Install for just me".  Installing for all users creates registry problems later(!)
- Check "update sys.path".

I later rearrange sys.path order so that my scripts folder (`c:\scripts`) is first.

Test: e and e2 work at this point.

pip2/3 install markdown: Test: markdown test works.
pip2/3 install pyenchant: Test: spell tab visible.  Hurray!
pip2/3 install pylint: Test pylint -a works.
pip2/3 install pyinstaller (needed only when distributing Leo).

pylint sometimes can not import the leo module.  As a workaround, my sitecustomize.py files add the leo folder to sys.path.  This should be addressed in Leo's pylint support code.</t>
<t tx="ekr.20180523095243.23">https://github.com/leo-editor/leo-editor/issues/322
The new javascript importer is a template for other importers.  This issue describes what would be done.  As such, is an information item as well as an enhancement request. Much of the following has been taken from [this discussion](https://groups.google.com/forum/#!topic/leo-editor/Ct3ZKqTo_KE) on leo-editor. 

Most of the code resides in the `JavaScriptScanner` class, and its helpers, the `Block` class and the `ScanState` classes. Imo, these classes are the simplest thing that could possibly work. These three classes form a framework for writing any importer.

We could imagine a `GeneralScanState` class that scans input line by line.  A call to

```
    BaseScanner.new_scanner(self)
```

would instantiate the GeneralScanState using the _already existing_ ivars of each scanner. Token info is _already_ found in these ivars:

```
    .blockCommentDelim1/2
    .blockDelim1/2
    .lineCommentDelim/2
    .outerBlockDelim1/2
```

None of the following `BaseScanner` ivars would be needed:

```
    .classTags
    .extraIdChars
    .functionTags
    .outerBlockEndsDecls
    .sigHeadExtraTokens
    .sigFailTokens
```

These ivars are pure hacks.  They modify `BaseScanner.scan_helper` and various code-generation methods in `basescanner.py`.

The new scheme would likely bypass _all_ the code generation routines in the `BaseScanner` class. Instead, the new code just creates child nodes for each block.  Nothing could be simpler, or more natural.

Finally, the new code uses a custom check method.  The existing code parameterizes the checks made in `BaseScanner.check`, but for experimentation it is quite handy simply to override the base class method entirely.

**Summary**

Import code will never be trivial, and special cases will have to be made for some languages.  For example, a completely new version of the `ScanState` class would be needed for Python, because blocks are delimited by indentation, not delimiters.

I would certainly have used the present scheme for all importers if I had discovered it earlier.  For now, I plan to convert an importer to the new scheme only if serious bugs are reported against it.</t>
<t tx="ekr.20180523095243.24">https://github.com/leo-editor/leo-editor/issues/105
## For others

https://bugs.launchpad.net/leo-editor/+bug/1240688
Problems with the Help Menu
Apparently, this bug is related to the leo_dark theme 0 settings.

https://bugs.launchpad.net/leo-editor/+bug/1173798
Notebook plugin command nb-subtree does not start with the right leo file 

https://bugs.launchpad.net/leo-editor/+bug/1230273
Todo.py documentation - image link semi-broken in docstring
## Fixed

[Fixed at 87480b3] https://bugs.launchpad.net/leo-editor/+bug/1158269
viewrendered pane goes blank when url clicked.</t>
<t tx="ekr.20180523095243.3">https://github.com/leo-editor/leo-editor/issues/872
From [this post](https://groups.google.com/d/msg/leo-editor/Gv6D-h8Mcag/wbBEK9gfCgAJ)

**EKR**: It looks like json.dumps may have problems with p.v.unknownAttributes

**Terry**: In theory yes, in practice not so much, although still a potential problem.

The leo_cloud plugin stores outlines (well, subtrees, without expansion info. etc.) in JSON.  The two issues I found were todo.py storing datetime dates, and the tags plugin storing sets.

Python's JSON module supports converting types on write - easy to make set a list, and I think I converted dates to YYYYMMDDTHHMMSS format.

Then you have to handle them on read - so I tweaked tags to convert to set, and todo was already reading text dates, seeing the datetime.dates had been a problem with different pickle versions.

So I guess in general I didn't find actual problems, but there's still the issue that currently someone can do:
```python
p.v.u['pantry'] = {
   ('beans', 'aug'): 17,
   ('beans', 'jun'): 12,
   ('flour', 'jul'): 11,
   ('flour', 'aug'): 10,
}
```
That just doesn't work in JSON.

I don't think we want to go down the track of letting users register JSON read/write helpers for certain keys in p.v.u.  *Maybe* we could handle the case of ints/floats/tuples/(frozen sets) as keys by converting to/from string representations.</t>
<t tx="ekr.20180523095243.4">https://github.com/leo-editor/leo-editor/issues/755
pyzo is pure python with only a few optional dependencies.  Use the binary installer.

See [this pyzo issue](https://github.com/pyzo/pyzo/issues/386) for more details. In particular, the binaries depend on [cx_freeze](http://cx-freeze.readthedocs.io/en/latest/) and maybe [PySide](http://wiki.qt.io/About_PySide).</t>
<t tx="ekr.20180523095243.6">https://github.com/leo-editor/leo-editor/issues/752
**Summary**: Not installed yet on Windows.

The [eric6 download page](http://eric-ide.python-projects.org/eric-download.html).</t>
<t tx="ekr.20180523095243.7">https://github.com/leo-editor/leo-editor/issues/735
LeoVue is Joe Orr's prototype of Leo using vue.js. First announced [here](https://groups.google.com/d/msg/leo-editor/50SZd4136iM/owhCnBqcDAAJ). Joe's [leo-examples page](https://github.com/kaleguy/leo-examples) discusses how to run leovue on a local machine. The git repo is [here](https://github.com/kaleguy/leovue).

I can now successfully build leovue on both Ubuntu and Windows 10. **Note**: Before doing so I simulated a clean install by *uninstalling* java, node.js and a previous copy of leovue.  Uninstalling node.js involved deleting ~AppData/npm and ~AppData/npm-cache.

Here is how to install and run the demo. Note: *installing Java is no longer necessary*.  

**1. install node.js**

On Linux, do the following.  Note the **second** sudo in the curl line!!!

    anywhere&gt;sudo curl -sL https://deb.nodesource.com/setup_6.x | sudo bash -
    anywhere&gt;sudo apt-get install nodejs

On Windows, install nodejs from an executable installer.  I used from node-v8.9.4-x64.msi

**2. Install global npm packages**

     anywhere&gt;sudo npm install -g node-gyp@3.6.2

LeoVue requires a web server to run. Either install it on your server or run it locally with http-server:

    anywhere&gt;sudo npm install -g http-server

**3. Download LeoVue itself**

Do the following where you have permissions. say in ~/repo. It will create a leovue folder.

    ~/repo&gt;git clone https://github.com/kaleguy/leovue.git

**4. Install packages within LeoVue**

    leovue&gt;npm install --silent
        # --silent inhibits the spammy dependency tree.

**6. Run leovue**

    # serve with hot reload at localhost:8080
    leovue&gt;npm run dev

**Important**: Be sure to allow all in noscript or other ad blocker.

**Note**: `npm run dev` is quite slow. Maybe 20 seconds on a fast machine. Eventually the console should show: `&gt; Listening at http://localhost:8080`

**7. Building the production version**

The following also works (it's quite slow):

    # build for production with minification
    leovue&gt;npm run build

    # build for production and view the bundle analyzer report
    leovue&gt;npm run build --report

At the end of the build, this message appears:

    Tip: built files are meant to be served over an HTTP server.
    Opening index.html over file:// won't work.

**From tscv11**: The script 'leo4sqlite' is now online using leovue. The syntax highlighting works well.
I'm looking forward to trying some of leovue's more advanced capabilities. The leovue/leo4sqlite demo lives [here](https://tscv11.github.io/leo4sqlite/#/t/23/)</t>
<t tx="ekr.20180523095243.8">https://github.com/leo-editor/leo-editor/issues/733
This info item describes how to install and run Vitalije's clojurescript demo project, **leocljs**. leocljs uses [electron.js](https://electronjs.org/) and [Om/React](https://github.com/omcljs/om). Vitalije first announced leocljs [here](https://groups.google.com/d/msg/leo-editor/Isd93qGd-RU/SaQoVv7gCQAJ). The *original* sources and documentation are [here](https://repo.computingart.net/leocljs/tree?ci=tip). The *current* sources are in the [leo/proto/Vitalije/leocljs](https://github.com/leo-editor/leo-editor/tree/proto/leo/proto/Vitalije/leocljs) folder of Leo's [proto](https://github.com/leo-editor/leo-editor/tree/proto) branch. 

This item is a distillation of information from [this post]( https://groups.google.com/d/msg/leo-editor/Isd93qGd-RU/tnRajD7qCQAJ) and [this post](https://groups.google.com/d/msg/leo-editor/wAmZfFCQWVU/mwhMfQ_LCgAJ) and [this thread](https://groups.google.com/forum/#!topic/leo-editor/pUN94kB5cLE). All comments and corrections are welcome.

**Notation**:  `leocljs&gt;command` means run command in leo/proto/Vitalije/leocljs

- Install [java](https://java.com/en/), [node.js](https://nodejs.org/en/), [electron](https://electronjs.org/), and [leiningen](https://leiningen.org/).
  Install node.js and leiningen *globally* with the -g option.
  See #703 for detailed instructions about installing and running electron.
- Build the app *once only*: `leocljs&gt;lein descjop-once-dev`
- Run the app using two *separate* consoles:

    - **Console 1**: `leocljs&gt;lein descjop-figwheel`
       This monitors and builds leiningen apps.
       A prompt will appear when the app loads.
       Don't close console 1 before closing console 2.

    - **Console2**:  `leocljs&gt;electron app/dev`
       This runs the app.

**Notes**:

1. In src_front/leo_front/core.cljs file at line 379 is `(get-leo-doc "line-numbering.leo")` Change "line-numbering.leo" to match the Leo file you have placed in app/dev/.

2. Usually you start with: `(in-ns 'leo-front/core)` You must be running the cljs app, otherwise the console will hang.</t>
<t tx="ekr.20180523095243.9">https://github.com/leo-editor/leo-editor/issues/719
rf.cleanRecentFiles does nothing if c.config.getData('path-demangle') is empty, which it is by default.

That *is* ok because Leo's startup logic removes files from the recent files list if they no longer exist.</t>
<t tx="ekr.20180523095245.1">https://github.com/leo-editor/leo-editor/issues/803
- [x] #808 Loading Images in Themes is Broken.
- [x] #766: Create a Themes menu.
- [x] #790: Support @load-themes setting.
   Won't do: `@string theme-name` suffices.</t>
<t tx="ekr.20180523095245.10">https://github.com/leo-editor/leo-editor/issues/907

This is an ongoing info Item.  Here are some preliminary ideas:

**Settings**

I did like the way VS Code handles key bindings.  In particular, settings can be associated with events, not just panes as in Leo. This might be a new direction for Leo.

**Non-outline tabs**

Many IDE's, including VS Code, can display web pages using the entire window. The idea is to allow the VR pane (or an external file) to occupy the entire window, that is, an entire tab.  This would allow Leo to display .md files "natively" in the entire window, rather than squashed into whatever space is allocated to the VR pane. Similarly, one of Kent's favorite requests, a "flattened" view of an entire file, would also be a good candidate for displaying in the full window.  And so on.

**Pylint**

- Add a setting to run Pylint whenever saving a .py file.
- Pylint errors should also create clickable links, if they don't already.

**Other panes**

Most IDE's support lots and lots of other views.  It's an open question how useful these would be in Leo.

**Integrated debugger**

Single-stepping through code *in Leo's outline* would be a good feature to have. The recent work on jedi auto-completion shows how to associate line numbers in the external file with lines in each node of the file.  It's actually very easy and fast to do, which I had not realized until this week.</t>
<t tx="ekr.20180523095245.11">https://github.com/leo-editor/leo-editor/issues/897

From [this post](https://groups.google.com/d/msg/leo-editor/ySG0WtcOdgI/OTtF5ldFBQAJ): The latest release of VS Code includes the idea of FileSystemProviders that allow you to open editors via various [Universal Resource Identifiers](https://en.wikipedia.org/wiki/Uniform_Resource_Identifier).

You would have to develop a leo: or maybe leoFS: scheme to let you open nodes, and probably a LSP to keep node updated in Leo, but it would be a way to let VS Code do editing. There is a memory based example memFS [here](https://marketplace.visualstudio.com/items?itemName=jrieken.vscode-memfs).</t>
<t tx="ekr.20180523095245.16">https://github.com/leo-editor/leo-editor/issues/798
This is an info item summarizing Terry's planned enhancements to Leo's windowing system &amp; gui.

- [ ] #778 Leo-edit-pane (LEP) project
- [ ] #777 QDock layout project
- [ ] #465 Use publish / subscribe architecture</t>
<t tx="ekr.20180523095245.17">https://github.com/leo-editor/leo-editor/issues/797
[The road map for 2018: visualization &amp; services](https://groups.google.com/forum/#!topic/leo-editor/5jydZQF26iE) contains the present plan.
**Summary**: Visualization is the heart of what we want.

**Scripting**

- #760: Optionally use ipython in the python_console plugin.
- #729: Ongoing: support scripting (execute-script) in more languages
- #561: Making Leo a client of Jupyter, by communicating with its kernel
    Add convenient access to jupyter kernels.
- #465: Use publish / subscribe architecture

**Importers**

- #838: Better jupyter notebook (.ipynb) importer/exporter
- #723: More improvements to javascript importer needed

**Plugins**

- #839: Split valuespace plugin (or its docs) in two
  vs-eval-block *already* does much of what jupyter does. It is buggy at present.
- #761: Make the valuespace plugin more visible
- #760: Optionally use ipython in the python_console plugin
- #682: Use live objects for autocompletion in the valuespace plugin
- #447: VR plugin should be improved.
   Support `@`treeview directives so the rendered output of a tree of Leo nodes
   looks like a jupyter notebook.

**Gui**

- #684: Create a browser gui for Leo
- #667: Pipes into the body pane's widget
- #588: Make node attributes visible, with support in Leo's core

**Obsolete**: This [design document](https://groups.google.com/forum/#!topic/leo-editor/5AryK8fvje8) and these [implementation notes](https://groups.google.com/forum/#!topic/leo-editor/cEahcRp0jME) contain the original ideas.</t>
<t tx="ekr.20180523095245.18">https://github.com/leo-editor/leo-editor/issues/796
This item summarizes all info items related to installation:

- #755: How to build pyzo from sources
- #754: Move distribution from SourceForge to github + pip install Leo
- #752: Installing eric6 on Windows
- #735: Installing and running LeoVue
- #733: Installing and running the leocljs demo
- #710: Switching between Anaconda installations
- #703: Running the hello world electron app on Windows
- #701: Summary of installing zerorpc on Windows
- #693: Summary of installing Anaconda3 on Windows
- #688: Summary of installing miniconda on Windows 10
- #324: Installation notes for Anaconda</t>
<t tx="ekr.20180523095245.19">https://github.com/leo-editor/leo-editor/issues/665
Note: #797: Summary: jupyter-related issues contains other issues related to org mode.

- #775: support org-mode agendas.
- #440: Allow args to `@`language directives.
    Add or enhance directives to split body text into different rendering regions.
- #433: Complete the tables.py plugin.
- #429: execute-script should execute unselected code between `@`language directives</t>
<t tx="ekr.20180523095245.2">https://github.com/leo-editor/leo-editor/issues/801
Here are my main plans for this year:

- [x] #803: Complete themes.
- [ ] #797: Support Jupyter notebooks as much as possible.

Ongoing: Support Joe Orr's great work.</t>
<t tx="ekr.20180523095245.20">https://github.com/leo-editor/leo-editor/issues/100
These have been delegated to Ville M. Vainio, the author of this plugin.

https://bugs.launchpad.net/leo-editor/+bug/820019
Shift-Ctrl-F (quicksearch) Sometimes leaves focus in body

https://bugs.launchpad.net/leo-editor/+bug/823538
Plugin quicksearch.py command marked-list does nothing

https://bugs.launchpad.net/leo-editor/+bug/917805
Quicksearch, select string in header, Shift-Ctrl-F does NOT work

https://bugs.launchpad.net/leo-editor/+bug/1199979
find-quick / Nav tab doesn't work with "first_date = events[0].date"</t>
<t tx="ekr.20180523095245.3">https://github.com/leo-editor/leo-editor/issues/799
These will be closed *only* so as not to clutter the [info items page].

- #786: Suggestions for theme developers

- #527: Info: unit tests need not, and should not, depend on settings</t>
<t tx="ekr.20180523095245.4">https://github.com/leo-editor/leo-editor/issues/770
Excerpted from [this post](https://groups.google.com/d/msg/leo-editor/scjyAiA-DXU/BGgYjU4iBAAJ):

-  #762: quickstart.leo &amp; CheatSheet.leo should demo Leo's features, including markdown rendering
- #765: Improve the Cmds menu
- #763: Use html comments to support @file x.md
- #764: Improve the screen shot on Leo's home page
- #803: Summary: Themes items
- #766: Create a Themes menu and simplify theme settings.</t>
<t tx="ekr.20180523095245.5">https://github.com/leo-editor/leo-editor/issues/680
**Update**: Imo, little, if any, truly sclerotic code remains in Leo.  In particular, naming conventions replace unnecessary asserts.  The remaining assert are benign.  Many are a form of documentation.

[This post](https://groups.google.com/d/msg/leo-editor/Ejf3tif-eJs/cT3ZJINIBAAJ) lists Leo's flexible and sclerotic aspects:

- Fixed: **Sclerotic**: Leo's key-handling code. #858 tells how to solve this problem.

- Won't Do: **Sclerotic**: Leo's @shortcuts nodes mix all pane bindings together.
  Instead, use inheritable  `@data &lt;pane&gt;-shortcut` nodes 

- **Sclerotic**: Leo's concrete gui code.
  It might be possible to use a local browser as Leo's rendering engine, while having Leo remain a desktop app. It would be easy to simulate the needed parts of the javascript DOM in Leo's API.

- **Partially sclerotic**: Leo's rendering tools.
  We are suffering from [LeoVue](https://github.com/kaleguy/leovue#leo-vue) envy.

- **Partially sclerotic**: Leo's attribute handling.
  See #588.</t>
<t tx="ekr.20180523095245.7">https://github.com/leo-editor/leo-editor/issues/910
This is the top-level summary of all info items for Leo's devs.  This item will remain open "forever". The items referenced here have all been closed.

**Build instructions**

- #755: How to build pyzo from sources
- #752: How to install eric6 on Windows
- #735: How to install and run LeoVue
- #733: How to Install and run the leocljs demo
- #703: How to install and run the hello world electron app on Windows
- #701: How to install zerorpc on Windows
- #699: How to install Anaconda3 on Windows
- #688: How to install miniconda on Windows 10
- #324: How to install Anaconda

**Other info items**

- #906: Dubious major projects
- #872: Info: how Leo handles uA's
- #710: How to Switch between Anaconda installations
- #681: Use the tools that Leo supports
- #105: Index of old LaunchPad bugs re plugins</t>
<t tx="ekr.20180523095245.8">https://github.com/leo-editor/leo-editor/issues/909
It's easy to use LaTex with Leo. This info item tells how.

**Create external files**: `@clean` create an external file without Leo sentinels, that is, without extra LaTex/tex comment lines.  Leo will automagically incorporate changes you make outside Leo into the `@clean` outline.

Leo may place newly-added lines at the boundary of two nodes in the "wrong" node. If that happens, just move the line to the correct node and save the outline.  Leo will remember what you did.  The next time you open the outline, the moved line will be in the correct node.

**Automate your work flow**: g.execute_shell_commands executes commands without hanging Leo. For example:
```python
g.execute_shell_commands([
    '"C:\Program Files (x86)\SumatraPDF\SumatraPDF.exe",
    'latex_test.pdf'
]) 
```
The argument to g.execute_shell_commands can be a string containing a *single* command, or a list one or more commands, as shown above. 

You can put calls to g.execute_shell_commands into an `@button` or `@command` node to create visible buttons and/or commands that you can execute by name from the minibuffer.</t>
<t tx="ekr.20180523095245.9">https://github.com/leo-editor/leo-editor/issues/908

To do: create a list/matrix of essential Leo features, compared to other IDE's.  This should be useful for everyone: Leo's devs, power users, and newbies.</t>
<t tx="ekr.20180523095623.1"></t>
<t tx="ekr.20180523095717.1"></t>
<t tx="ekr.20180523095925.1"></t>
<t tx="ekr.20180523101133.1"></t>
<t tx="ekr.20180523101514.10">https://github.com/leo-editor/leo-editor/issues/527

Relying on settings nodes in unitTest.leo risks creating hard-to-find dependencies between seemingly unrelated unit tests.  Instead, unit tests can follow the pattern for, say, `@test add python comments`:

```python
w = c.frame.body.wrapper
p = g.findNodeInTree(c,p,'python')
assert p,'not found: python'
# Save the initial value of the setting.
old_indent = c.config.getBool('indent_added_comments',default=True)
table = (
    (
        True,
        '@language python\ndef spam():\n    pass\n\n# after',
        '@language python\ndef spam():\n    # pass\n\n# after',
    ),
    (
        False,
        '@language python\ndef spam():\n    pass\n\n# after',
        '@language python\ndef spam():\n#     pass\n\n# after',
    ),
)
try:
    for indent, s1, expected in table:
        # Step 1: set the setting.
        c.config.set(None, 'bool', 'indent_added_comments', indent, warn=False)
        val = c.config.getBool('indent_added_comments')
        assert indent == val, (repr(indent), repr(val))
        # Step 2: set p.b and the insert point.
        c.selectPosition(p)
        p.b = s1
        i = p.b.find('pass')
        assert i &gt; -1,'fail1: %s' % (repr(p.b))
        w.setSelectionRange(i,i+4)
        # Step 3: test add-comments
        c.addComments()
        assert p.b == expected, ('indent: %5s got:\n%r\nexpected:\n%r' % (indent, p.b, expected))
finally:
    # Restore the initial value of the setting.
    c.config.set(p, 'bool', 'indent_added_comments', old_indent)
    val = c.config.getBool('indent_added_comments')
```
This code saves and restores the actual value of the `@bool indent_added_comments` setting. It uses:
```python
 c.config.set(c.config.set(None, 'bool', 'indent_added_comments', indent, warn=False)
```
to set the setting to the value of 'indent'.  Note that c.config.set is seldom (never?) used in Leo's core.</t>
<t tx="ekr.20180523101514.12">https://github.com/leo-editor/leo-editor/issues/859

This lesson discusses the *process* of making arbitrarily complex changes throughout a code base.  It's an elaboration of [Lesson 1: Think process, not knowledge](https://github.com/leo-editor/leo-editor/issues/817), but it's worth reading because it contains helpful hints about tackling *any* big project.  I used this general method when making Leo's code base work with Python 3 as well as Python 2.

The grand summary:

1. Study the code first with clone-find commands.
2. Let python crashes &amp; failed unit tests guide you.

For example, here is how I am doing [#858: Rewrite Leo's key handling &amp; key binding code](https://github.com/leo-editor/leo-editor/issues/858):

1. Create a new git branch for the work, in this case, "keys".

2. Create a **global master switch**that separates and marks the old and new versions of the code. This is a boolean.  It selects the new code if True and the old code otherwise.  We say the switch is either in the "**new**" position or the "**legacy**" position.

- **All unit tests should continue to pass when the switch selects legacy code.**
- **All pushes should have the legacy code selected until every works.**

These two requirements make it safe to pause work on the project.

3. Make sure you understand what needs to be done.  Use the clone find commands to answer any and all questions about the code and how it should be changed.

4. Make the fundamental changes required, **without worrying about the consequences**.

For the "keys" branch I changed the representation of settings so that they are NewLeoKey objects.

5.  With the switch in the "new" position, run a test copy of Leo.

Because of step 4, we *expect* crashes.  Fix each as they happen, separating the old and new code with a test on the switch.  Repeat this step until no crashes happen.

When this phase works, set the switch to "legacy", re-run all unit tests, and commit the code.

6. For the "keys" branch, getting through startup is only half the task.  When I type a key I *expect* more crashes.  I'll follow step 5 until no crashes happen when I type various key combination.

Again, I'll set the switch to "legacy", re-run all unit tests and commit the code.

7. When normal operation appears to work with the switch in the "new" position, **run all unit tests** and fix any crashes or unit tests failures.

Now you can commit the code with the switch in the "new" position.

8. At this point you can start eating your own dog food.  When satisfied that the code is stable enough, you can do the following:

- Remove the switch and all code disabled when the switch is in the "legacy" position.
- Run all unit tests.
- Continue to eat your own dog food.
- Commit the branch to "devel" when all seems well.

That's the process.  It's extremely effective.  You don't have to remember your changes because a cff on the switch should yield *all* changed code.  Naturally, you can make clones of nodes containing the most important changes.</t>
<t tx="ekr.20180523101514.13">https://github.com/leo-editor/leo-editor/issues/857

Marcel Franke [explained](https://groups.google.com/d/msg/leo-editor/p_6ljMQL660/57Z8lYuQAAAJ) the recommended way of using git branches. Here are his remarks, slightly edited:

- **master** is stable.
- **devel** is "mostly" stable.
- **feature branches** off devel can be wildly unstable.
- **release branches** are candidates for master, so should be stable. 

Everything new comes from devel and goes to devel. Devs **must** run unit tests before pushing to devel, so devel should usually be stable.

All experimental code should reside in a feature branch.

At all times, anyone can pull stable code from master.

Only the maintainer (EKR) is supposed to work on release or master, so nobody needs to hold back or knows what is going on in them. At all times everyone can happily hack on devel,  or better, their personal feature branches.

To prepare a new release,  the maintainer branches devel to a new branch, say 5.7.x.  The maintainer runs tests on it, and makes any last-minute fixes. To publish the release, the maintainer merges the release to master **and** to devel, then optionally deletes the release branch.

This visualization made it all clear to me:

![git branches](https://blog.seibert-media.net/wp-content/uploads/2014/03/Gitflow-Workflow-3.png).</t>
<t tx="ekr.20180523101514.14">https://github.com/leo-editor/leo-editor/issues/816

This the gateway to Leo University, a project devoted to help people become Leo devs.

All lessons have the LeoU label. All comments welcome.

- Lesson 1: [Think process, not memory](https://github.com/leo-editor/leo-editor/issues/817).
    Programming is *much* easier than you might think.
- Lesson 2: [Learn Leo's debugging tools](https://github.com/leo-editor/leo-editor/issues/836).
- Lesson 3: [Running unit tests](https://github.com/leo-editor/leo-editor/issues/837).
- Lesson 4: [Use issues as a programming notebook](https://github.com/leo-editor/leo-editor/issues/818).
- Lesson 5: [c.recursiveImport imports files recursively](https://github.com/leo-editor/leo-editor/issues/846)
- Lesson 6: [How devs should use git branches](https://github.com/leo-editor/leo-editor/issues/857).
- Lesson 7: [How to make complex changes to a code base](https://github.com/leo-editor/leo-editor/issues/859).

And here are some other items for devs:

- #786: LeoU: Suggestions for theme developers
- #527: LeoU: Unit tests need not, and should not, depend on settings
- #890: LeoU: About Leo's Architecture
- #891: LeoU: About Leo's Position and VNode classes</t>
<t tx="ekr.20180523101514.3">https://github.com/leo-editor/leo-editor/issues/891

From [this post](https://groups.google.com/forum/#!topic/leo-editor/SjHfXepxiTo). Not everyone agrees with everything I say here.

This LeoU discussion discusses the present code base only. #883 (a low priority item) discusses ways in which the tree of vnodes could be decoupled from c, the Commands instance. 

**The Position class**

The Position class concerns itself only with traversing the tree. The position class contains no node-related data.  In order to insert top-level nodes, methods of the Position class gets access to c.hiddenRootNode via p.v.context. 

**The VNode class**

The VNode class contains all data in an outline, as well as crucial, low-level operations on those data. There is no other place to store node-related data. 

The VNode class is one of the foundations of Leo's scripting. As a result, *none* of the ivars or methods of the VNode class can change in any way. That is, all of the ivars of the VNode class are "official". Scripts can, and do, access these ivars directly. Perhaps the "context" kwarg of `VNode.__init__` should just be called "c", but that can't be done now.

Theoretically, it would be possible to add new kwargs to VNode methods, but that is extremely unlikely. It would also be possible to add new ivars to the VNode class, but uA's make that unnecessary.

The properties of the VNode class, v.b, v.h, v.gnx, v.u, allow higher-level access to various VNode ivars, but in some cases Leo's code accesses the corresponding ivars directly, for greater performance.

**Interaction with other classes**

The v.context ivar is controversial. In fact, the v.context ivar is completely benign. It has never caused problems, and it never will. It does not, in any significant way, make the VNode class dependent on any other class. It has no harmful architectural consequences.

Yes, the FileCommands class must know about gnx's, but *the converse is not true*.  The VNode class knows nothing about how other classes use gnx's.  The FileCommands class creates VNode instances without knowing *anything* about low-level VNode methods.

The VNode class is, in fact, an excellent example of information hiding.  The boundary between the VNode class is well defined and well enforced.

**Possible improvements**

1. A new c.new_vnode method could help instantiate VNodes:
```python
def new_vnode(self, gnx=None):
    c = self
    return leoNodes.VNode(context=c, gnx=gnx)
```
The (small) advantage is that clients of c.new_vnode(gnx) would no longer need to import leo.core.leoNodes.

2. The  v.saveCursorAndScroll and v.restoreCursorAndScroll could be moved elsewhere. At present, these methods cause no problems, but moving them would be part of #883.</t>
<t tx="ekr.20180523101514.4">https://github.com/leo-editor/leo-editor/issues/890

By the term **architecture** I mean the design of Leo's modules and classes. 

**Information hiding**

Leo's design is based on the thinking of [Glenford Meyers](https://en.wikipedia.org/wiki/Glenford_Myers).  Let's use the word **component** to mean either a Python module or class.

We devs *must* be able to change the implementation of a component *without* affecting any other code.  This has been true throughout Leo's 20+ years of history. This is the foundation on which Leo is built.

**Principle 1**: Each class should concern itself with one, easily defined "area of concern".

Modules should contain related classes.  All components should have short, simple *descriptions*, no matter how complex they are internally.

**Principle 2**: Components should know as little as possible about the internal details of other components.

Components have well-defined **boundaries**.  The **inside** of a component contains the implementation.  The **outside** of a component is its API.

Changes to the API can break code. However, knowing about the *existence* of a component's high-level methods does *not* (usually) blur the boundaries of a component!

In most cases, components should know *nothing* about the ivars and low-level methods.  However, components can freely use the so-called **official ivars** of other classes.  These official ivars are highly unlikely ever to change.  And they are useful.  We wouldn't want to require long-winded alternatives to, say, c.frame.body.wrapper.

**Class design: inheritance vs instantiation**

Leo uses the "has-a" pattern, rather than the "is-a" class pattern. That is, Leo gains access to the capabilities of other classes by instantiating the other classes rather than being subclasses of other classes. The "has-a" pattern is a personal preference of mine, and is now pretty much baked into Leo.

The "has-a" pattern *completely* insulates classes from the internal details of other classes.  There is no need to worry about clashing ivars, or _ ivars, etc. Otoh, the "has-a" pattern results in more complex startup code.  Imo, that "extra" complexity is well worthwhile.</t>
<t tx="ekr.20180523101514.5">https://github.com/leo-editor/leo-editor/issues/837

​All devs must run all unit tests before commit anything. Here's how:

- Open leo/test/unitTest.leo in a console.
- The "Active Unit Tests" node should already be selected. If not, select it.
- Do Alt-4. It is bound in the file to run-selected-unit-tests-locally.

**Important**: Some unit tests may fail on your environment.  Don't worry about them.  You need only ensure that your new code causes no *other* unit tests to fail.  If in doubt, ask on [leo-editor](https://groups.google.com/forum/#!forum/leo-editor).</t>
<t tx="ekr.20180523101514.6">https://github.com/leo-editor/leo-editor/issues/836

Here are the basics:

**g.trace**

g.trace(*args, **kwargs) prints its arguments to the console.

**g.pdb**

g.pdb() invokes a version of [python's pdb debugger]('https://docs.python.org/3/library/pdb.html'), adapted to Leo's Qt gui.  I use g.pdb when g.trace doesn't tell me enough.
</t>
<t tx="ekr.20180523101514.7">https://github.com/leo-editor/leo-editor/issues/818

For any programming project I recommend using github issues to track your work.  You'll be glad you did.

This is especially true for Leo devs.  You want other people to be able to follow and comment on your work.

The convention is to have the first comment for any issue contain an up-to-date summary of the status of the issue.  I have found that it is useful to continually edit the first comment.</t>
<t tx="ekr.20180523101514.8">https://github.com/leo-editor/leo-editor/issues/817

Many of Leo's most important devs made major contributions to Leo without asking me a single question.  Do they have super powers?  No, they don't.

But they do know the secret of programming: **Simple processes, endlessly repeated, suffice to find, understand and change *any* software**.  And Leo simplifies these techniques even further.  Here they are...

**Basic skill/process 1: Familiarize yourself with the code**

For any project you want to know what files exist.  When studying other people's code I use a [recursive import script](https://github.com/leo-editor/leo-editor/issues/846) to create a tree of files. The goal is just to have a *vague* understanding of what files are involved. Don't even think about remember details.

It's even easier with Leo.  LeoPy.py contains Leo's sources.  Peruse this outline, seeing what `@file` nodes it contains.

*Don't make a big deal about this step*. It should just take 5 or 10 minutes. Look *only* at files that interest you. In those files you will probably want to look briefly at the top-level classes in the files that interest you. You will likely repeat this step many times, adding a little to your understanding each time.

**Basic skill/process 2: Learn what to search for**

We devs often want to change how commands work.  You can usually find the top-level code for a command simply by searching for the command's name, in single quotes.

To find the definition of a method, function or class, simply control-click on it.  That will start a search for def x and class x.  If that doesn't work, a cff (clone-find-all-flattened) search on a name will find all uses of that name in the present outline.

**Basic skill/process 3: Look for helpers in child nodes**

With Leo outlines **it's natural to put a method's helpers in child nodes**. I usually forget implementation details, but the children of a node usually contain most of the details.

**Basic skill/process 4: Use clones to organize and remember your work**

When working on a project I make create an organizer node as the last top-level node of the outline.  This node will typically contain a link to the github issue.  I make clones of all relevant nodes and move them so they are clones of the organizer node.  For complex projects I may create subsidiary organizer nodes, like "changed", "reference", etc.

When a project is done (or suspended), I move the project's organizer node so it is the last child of *another* organizer node called "Recent Code". This hides all work except the what I am, this minute, working on.  This is important: it hides details and lessens distractions.

**Summary**

The easy processes just described form the basis for programming workflow.

*Expect to repeat these processes many times*.  Don't worry if not everything is clear at first.</t>
<t tx="ekr.20180523101514.9">https://github.com/leo-editor/leo-editor/issues/786

I recommend using the organization of leo/themes/EKRDark.leo as a guide. **Note**: Syntax coloring settings are required because they are *not* used in the css.

To avoid confusion, it's best if theme .leo files contain no **unbound settings**. This will ensure that the appearance of a theme does not unwittingly depend on settings in myLeoSettings.leo.

**Important**: Theme devs should set the following **theme description settings**:

    @string theme_name   # crucial
    @bool color_theme_is_dark
    @string color_theme = ekr_dark

These settings ensure that relative urls (including ":/" syntax are resolved properly in css, and that icons are found in the proper directories.

**Icons boxes should have constant width**.  Otherwise, the variable indentation of the rest of the headline appears to represent variable outline structure, which is highly confusing.

**Obsolete**: The post [ENB: Simple design principles for style sheets](https://groups.google.com/d/msg/leo-editor/JyyuOscgmow/kAJcGU0xBQAJ) contained my original ideas.  In particular, the so-called "settings Aha" is dubious.</t>
<t tx="ekr.20180523101625.1"></t>
<t tx="ekr.20180524104432.1">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.
</t>
<t tx="ekr.20180525211530.1">https://github.com/leo-editor/leo-editor/issues/738
</t>
<t tx="ekr.20180526130745.1">https://github.com/leo-editor/leo-editor/issues/893

A complete rewrite of the python_terminal plugin.</t>
<t tx="ekr.20180526131023.1"></t>
<t tx="ekr.20180526131124.1">https://github.com/leo-editor/leo-editor/issues/841</t>
<t tx="ekr.20180526213056.1">https://github.com/leo-editor/leo-editor/issues/309
</t>
<t tx="ekr.20180527084114.1">A mass cleanup of Leo's code, removing many unused tracing statements.</t>
<t tx="ekr.20180527084307.1">- 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.</t>
<t tx="ekr.20180529062944.1"></t>
<t tx="ekr.20180529062956.1">An `open issue &lt;https://github.com/leo-editor/leo-editor/issues/333&gt;`_ discusses various possibilities.

</t>
<t tx="ekr.20180529063449.1">Create your markdown files with @auto-md myfile.md.

This automatically converts headlines to section headings.

Optional: change @language md to @language rest.
At present, syntax coloring for markdown is feeble.
   </t>
<t tx="ekr.20180529064039.1">The @button make-md-toc script in LeoDocs.leo writes a TOC to the console log.

Just select the @auto-md node and execute the script.
</t>
<t tx="ekr.20180529064307.1">The following plugin, placed in ~/.leo/plugins, runs code at 'start1' time, that is, while other plugins are loading::

    import leo.core.leoGlobals as g
    print('===== local_plugin.py in ~/.leo/plugins/')

    def hook(tag, keys):
        g.trace(tag)

    def init():
        g.registerHandler('start1', hook)
        return True

Alternatively, the plugin could run code at 'start2' time, after all plugins have been loaded, or at any other time, as described `on this page &lt;writingPlugins.html#handling-events&gt;`_.</t>
<t tx="ekr.20180529064355.1"></t>
<t tx="ekr.20180529064813.1"></t>
<t tx="ekr.20180529065039.1"></t>
<t tx="ekr.20180529065351.1"></t>
<t tx="ekr.20180529065538.1"></t>
<t tx="ekr.20180619051649.1">Organize your myLeoSettings.leo file like this::

    @settings
         -my settings &lt;clone&gt;
              -@bool .... = True
              -@data fldsdf

    @file mysettings.txt
          my settings &lt;clone&gt;

Syncing mySettings.txt will synchronize your settings across your .leo files.

**Note**: Changed settings will not be available in other open outlines until you reload settings. You can do this with the reload-all-settings command.</t>
<t tx="ekr.20180702171546.1">https://github.com/leo-editor/leo-editor/issues/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
</t>
<t tx="ekr.20180821154658.1">- 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.</t>
<t tx="ekr.20180827103758.1">



</t>
<t tx="ekr.20180827104847.1">Leo's @pyplot nodes support
`matplotlib &lt;https://matplotlib.org/users/index.html&gt;`_.
\@pyplot nodes start with @pyplot in the headline.  The rest of the headline is comments. These nodes should contain matplotlib scripts that create figures or animations.  Like this:

.. code-block:: python

    fig2 = plt.figure()
    x = np.arange(-9, 10)
    y = np.arange(-9, 10).reshape(-1, 1)
    base = np.hypot(x, y)
    images = []
    for add in np.arange(15):
        images.append((
            plt.pcolor(x, y, base+add, norm=plt.Normalize(0, 30)),
        ))
    animation = animation.ArtistAnimation(fig2, images,
        interval=50, repeat_delay=3000, blit=True)
    g.app.permanentScriptDict['animations'] = animation
        # Keep a python reference to the animation, so it will complete.

**Notes**

1. If the viewrendered (VR) pane is open, Leo will display the animation in the VR pane whenever the user selects the @pyplot node.  This has been tested only with the viewrendered.py, not the viewrendered2.py plugin.

2. In addition to c, g, and p, the VR code predefines several other vars.  The VR code does the following imports:

.. code-block:: python

    import matplotlib
    import matplotlib.pyplot as plt
    import numpy as np
    import matplotlib.animation as animation

and then predefines the animation, matplotlib, np, numpy and plt vars in the @pyplot script. numpy is also predefined as an alias for np.</t>
<t tx="ekr.20180827105047.1">To display images and animations in an external window, *don't* put the script in an @pyplot node. Instead, put the script in a regular node, with the following modifications:

1. Add the required imports:

.. code-block:: python

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation

2. Place the following at the end of the script:

.. code-block:: python

    plt.ion()
        # sets interactive mode. Prevents this message:
        # QCoreApplication::exec: The event loop is already running
    plt.show()

**Bugs**

1. Once you use the VR pane to display an image, you can't (at present) display an image externally.

2. The VR plugin will refuse to close the VR pane if it ever displays an @pyplot image or animation. This prevents Leo from hard crashing in the pyplot code. As a workaround, you can  resize the VR pane so it is effectively hidden.</t>
<t tx="ekr.20180930062351.1">Leo 5.8 final, https://leo-editor.github.io/leo-editor/ is now available on
[GitHub](https://github.com/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**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md
</t>
<t tx="ekr.20180930062351.10">https://github.com/leo-editor/leo-editor/issues/938

The fix was in abbrev.init_tree_abbrev_helper.
</t>
<t tx="ekr.20180930062351.11">https://github.com/leo-editor/leo-editor/issues/940

added update_nodes method.
</t>
<t tx="ekr.20180930062351.12">https://github.com/leo-editor/leo-editor/issues/943

The fix was to getVnodeFromClipboard.
</t>
<t tx="ekr.20180930062351.13">The fix was to set @&lt;file&gt; nodes dirty by brute force in find.changeAllCommand.

https://github.com/leo-editor/leo-editor/issues/947

See also:

https://github.com/leo-editor/leo-editor/issues/722
https://github.com/leo-editor/leo-editor/issues/880
</t>
<t tx="ekr.20180930062351.14">https://github.com/leo-editor/leo-editor/issues/956

async is a new keyword.
</t>
<t tx="ekr.20180930062351.15">https://github.com/leo-editor/leo-editor/issues/967</t>
<t tx="ekr.20180930062351.16">See c.backup_helper.</t>
<t tx="ekr.20180930062351.17">Traceback (most recent call last):
  File "c:\leo.repo\leo-editor\leo\plugins\qt_frame.py", line 3152, in linkClicked
    url = link.url()
AttributeError: 'QUrl' object has no attribute 'url'</t>
<t tx="ekr.20180930062351.18">It now works in folders besides the leo-editor folder.
</t>
<t tx="ekr.20180930062351.19"></t>
<t tx="ekr.20180930062351.2">For the full list, see: https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A5.8+-label%3Awaiting+is%3Aclosed</t>
<t tx="ekr.20180930062351.20"></t>
<t tx="ekr.20180930062351.21">https://github.com/leo-editor/leo-editor/issues/969
The fix: call c.treeWantsFocusNow in tt.selectTab.
</t>
<t tx="ekr.20180930062351.22">https://github.com/leo-editor/leo-editor/issues/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.</t>
<t tx="ekr.20180930062351.23"></t>
<t tx="ekr.20180930062351.24">https://github.com/leo-editor/leo-editor/issues/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.</t>
<t tx="ekr.20180930062351.25">https://github.com/leo-editor/leo-editor/issues/924
</t>
<t tx="ekr.20180930062351.26"></t>
<t tx="ekr.20180930062351.27">::

         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(&lt;listcomp&gt;) # 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 &lt;frozen importlib._bootstrap_external&gt;: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(&lt;listcomp&gt;)
    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 &lt;frozen importlib._bootstrap_external&gt;: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(&lt;listcomp&gt;)
    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(&lt;listcomp&gt;)
      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(&lt;listcomp&gt;)
     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 &lt;frozen importlib._bootstrap&gt;: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 &lt;frozen importlib._bootstrap&gt;:870(_find_spec)
      693    0.005    0.000    0.007    0.000 &lt;frozen importlib._bootstrap_external&gt;: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(&lt;listcomp&gt;)
     6570    0.005    0.000    0.013    0.000 &lt;frozen importlib._bootstrap_external&gt;:57(_path_join)
      693    0.005    0.000    0.178    0.000 &lt;frozen importlib._bootstrap_external&gt;: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__)
</t>
<t tx="ekr.20180930062351.28">         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(&lt;listcomp&gt;) # 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) #</t>
<t tx="ekr.20180930062351.29">::

         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}</t>
<t tx="ekr.20180930062351.3"></t>
<t tx="ekr.20180930062351.30">         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(&lt;listcomp&gt;) # 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 &lt;frozen importlib._bootstrap_external&gt;: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 &lt;frozen importlib._bootstrap_external&gt;: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(&lt;listcomp&gt;)
    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(&lt;listcomp&gt;)
      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(&lt;listcomp&gt;)
        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(&lt;listcomp&gt;)
    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 &lt;frozen importlib._bootstrap&gt;: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 &lt;frozen importlib._bootstrap&gt;: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 &lt;frozen importlib._bootstrap_external&gt;: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 &lt;frozen importlib._bootstrap_external&gt;: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 &lt;frozen importlib._bootstrap_external&gt;: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 &lt;frozen importlib._bootstrap_external&gt;: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 &lt;frozen importlib._bootstrap&gt;: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 &lt;frozen importlib._bootstrap_external&gt;:59(&lt;listcomp&gt;)
    17862    0.004    0.000    0.004    0.000 leoGlobals.py:2038(_checkKeyType)
       82    0.004    0.000    0.008    0.000 &lt;frozen importlib._bootstrap_external&gt;: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 &lt;frozen importlib._bootstrap&gt;: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)

</t>
<t tx="ekr.20180930062351.31"> 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:&lt;listcomp&gt;,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,&lt;listcomp&gt;,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
</t>
<t tx="ekr.20180930062351.32">    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</t>
<t tx="ekr.20180930062351.33"># 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
</t>
<t tx="ekr.20180930062351.34"># 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
</t>
<t tx="ekr.20180930062351.35">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:

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

B. ~/.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.

3. Leo writes only a vestigial &lt;globals&gt; element in .leo files.  This should be enough to allow old (Leo 4.5 and above) versions of Leo to read .leo files.

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

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

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

https://github.com/leo-editor/leo-editor/issues/934</t>
<t tx="ekr.20180930062351.36">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.</t>
<t tx="ekr.20180930062351.37"># 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
</t>
<t tx="ekr.20180930062351.38"># 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
   </t>
<t tx="ekr.20180930062351.39">#
   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
</t>
<t tx="ekr.20180930062351.4">https://github.com/leo-editor/leo-editor/issues/841
</t>
<t tx="ekr.20180930062351.40"># 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
   </t>
<t tx="ekr.20180930062351.41">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.</t>
<t tx="ekr.20180930062351.42">This is an important simplification of the code.</t>
<t tx="ekr.20180930062351.43"></t>
<t tx="ekr.20180930062351.44">Leo now redraws the screen only once during startup.

Removed qtree.update_appearance and qtree.update_appearance_idle.
</t>
<t tx="ekr.20180930062351.45"></t>
<t tx="ekr.20180930062351.46">https://github.com/leo-editor/leo-editor/issues/871

In fact, this setting has existed for a long time.
</t>
<t tx="ekr.20180930062351.47">https://github.com/leo-editor/leo-editor/issues/913
</t>
<t tx="ekr.20180930062351.48">https://github.com/leo-editor/leo-editor/issues/914
</t>
<t tx="ekr.20180930062351.49">https://github.com/leo-editor/leo-editor/issues/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
</t>
<t tx="ekr.20180930062351.5">https://github.com/leo-editor/leo-editor/issues/893
</t>
<t tx="ekr.20180930062351.50">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20180930062351.51">https://github.com/leo-editor/leo-editor/issues/953
</t>
<t tx="ekr.20180930062351.52">https://github.com/leo-editor/leo-editor/issues/961

Better tracing if the cursor gui fails to load.</t>
<t tx="ekr.20180930062351.53">https://github.com/leo-editor/leo-editor/issues/966
</t>
<t tx="ekr.20180930062351.54"></t>
<t tx="ekr.20180930062351.55"></t>
<t tx="ekr.20180930062351.56"></t>
<t tx="ekr.20180930062351.57">This is for debugging only.</t>
<t tx="ekr.20180930062351.58">https://groups.google.com/forum/#!topic/leo-editor/Nun7rRRhato
</t>
<t tx="ekr.20180930062351.59">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
</t>
<t tx="ekr.20180930062351.6">https://github.com/leo-editor/leo-editor/issues/917
</t>
<t tx="ekr.20180930062351.60">https://groups.google.com/forum/#!topic/leo-editor/09H5wX1QRxw

Added .latex and *.sty files, would automatically be recognized as LaTeX. </t>
<t tx="ekr.20180930062351.61"></t>
<t tx="ekr.20180930062351.7">https://github.com/leo-editor/leo-editor/issues/922</t>
<t tx="ekr.20180930062351.8">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20180930062351.9">https://github.com/leo-editor/leo-editor/issues/936

The change was to load_session.</t>
<t tx="ekr.20180930062538.1">This is the presently active commander, that is, g.app.log.c.
</t>
<t tx="ekr.20181015144118.25"></t>
<t tx="ekr.20181015144118.26">.. code-block:: python

    @g.command('i1')
    def i1_command(event):
        c = event.get('c')
        if not c: return

        def callback(args, c, event):
            g.trace(args)
            c.bodyWantsFocus()

        c.interactive(callback, event, prompts=['Prompt: '])
</t>
<t tx="ekr.20181015144118.27">.. code-block:: python

    @g.command('i2')
    def i2_command(event):
        c = event.get('c')
        if not c: return

        def callback(args, c, event):
            g.trace(args)
            c.bodyWantsFocus()

        c.interactive(callback, event,
            prompts=['Find: ', ' Replace: '])
</t>
<t tx="ekr.20181015144118.28">.. code-block:: python

    @g.command('i3')
    def i3_command(event):
        c = event.get('c')
        if not c: return

        def callback(args, c, event):
            g.trace(args)
            c.bodyWantsFocus()

        c.interactive(callback, event,
            prompts=['One: ', ' Two: ', ' Three: '])
</t>
<t tx="ekr.20181015144118.29">``LeoPyRef.leo`` contains all of Leo's core source code.

Leo's code uses the following conventions throughout::

    c:  a commander.
    ch: a character.
    d:  a dialog or a dict.
    f:  an open file.
    fn: a file name.
    g:  the leoGlobals module.
    i, j, k: indices into a string.
    p:  a Position.
    s:  a string.
    t:  a text widget.
    u:  an undoer.
    w:  a gui widget.
    v:  a Vnode
    z:  a local temp.

In more limited contexts, the following conventions apply::

    si:     a g.ShortcutInfo object.
    ks:     a g.KeyStroke object
    stroke: a KeyStroke object.

    btw:    leoFrame.BaseTextWrapper
    stw:    leoFrame.StringTextWrapper

    bqtw:   qt_text.BaseQTextWrapper
    lqtb:   qt_text.LeoQTextBrowser
    qhlw:   qt_text.QHeadlineWrapper
    qmbw:   qt_text.QMinibufferWrapper
    qlew:   qt_text.QLineEditWrapper
    qsciw:  qt_text.QScintiallaWrapper
    qtew:   qt_text.QTextEditWrapper

Names defined in Leo's core are unlikely to change, especially names used outside their defining module. This includes virtually everything in ``leoGlobals.py``, and many names in ``leoCommands.py`` and other files. </t>
<t tx="ekr.20181015144118.30">The following 'official' ivars (instance vars) will always exist::

    c.frame                 The frame containing the log,body,tree, etc.
    c.frame.body            The body pane.
    c.frame.body.widget     The gui widget for the body pane.
    c.frame.body.wrapper    The high level interface for the body widget.
    c.frame.iconBar         The icon bar.
    c.frame.log             The log pane.
    c.frame.log.widget      The gui widget for the log pane.
    c.frame.log.wrapper     The high-level interface for the log pane.
    c.frame.tree            The tree pane.

The following were official ivars that no longer exist::

    c.frame.body.bodyCtrl   Use c.frame.body.wrapper instead.
    c.frame.log.logCtrl     Use c.frame.log.wrapper instead.
</t>
<t tx="ekr.20181015144118.31">A **widget** is an actual Qt widget. Leo's core seldom accesses widgets directly.  Instead, a  **wrapper class** defines a standard api that hides the details of the underlying gui **text** widgets.

Leo's core uses the wrapper api almost exclusively. That is, Leo's core code treats wrappers *as if* they were only text widgets there are!

A back door exists for special cases. All wrapper classes define an official ``widget`` ivar, so core or plugin code can gain access to the real Qt widget using wrapper.widget. Searching for ``wrapper.widget`` will find all gui-dependent snippets of code in Leo's core.
</t>
<t tx="ekr.20181015144118.33"></t>
<t tx="ekr.20181015144118.34">Leo's Code Academy posts discuss how to do useful things in Leo. The following are distilled from online discussions about Leo's scripting.</t>
<t tx="ekr.20181015144118.35">uA's (user Attributes) associate arbitrary data with any vnode. uA's are dictionaries of dictionaries--an **outer dictionary** and zero or more **inner dictionaries**. The outer dictionary associates plugin names (or Leo's core) with inner dictionaries. The inner dictionaries carry the actual data.

The v.u or p.v properties get and set uA's. You can think of p.u as a synonym for p.v.unknownAttributes on both sides of an assignment. For example:

.. code-block:: python

    plugin_name = 'test_plugin'
    d = p.u.get(plugin_name,{})
    d ['n'] = 8
    p.u [plugin_name] = d

p.u is the outer dictionary. p.u.get.(plugin_name, {}) is the inner dictionary. The last line is all that is needed to update the outer dictionary!

It is easy to search for particular uA's. The following script prints all the keys in the outer-level uA dictionaries:

.. code-block:: python

    for p in c.all_unique_positions():
        if p.u:
            print(p.h, sorted(p.u.keys()))

This is a typical usage of Leo's generators.  Generators visit each position (or node) quickly. Even if you aren't going to program much, you should be aware of how easy it is to get and set the data in each node. In fact, now would be a great time to read Leo's Scripting Tutorial again :-) This will allow you to "dream bigger" with Leo.

The following script creates a list of all positions having an icon, that is, an outer uA dict with a 'icon' key:

.. code-block:: python

    aList = [p.copy() for p in c.all_unique_positions() if 'icon' in p.u]
    print('\n'.join([p.h for p in aList]))

*Important*: If you don't understand these lines, please study Python's list comprehensions.  They are incredibly useful. '\n'.join(aList) is a great idiom to know.  str.join is one of python's most useful string methods. It converts between lists and strings.
</t>
<t tx="ekr.20181015144118.36">This script inserts three icons in the current outline node. Running
the script again will insert three more:

.. code-block:: python

    table = (
        'edittrash.png',
        'connect_no.png',
        'error.png',
    )
    for icon in table:
        fn = g.os_path_finalize_join(g.app.loadDir,
            '..', 'Icons', 'Tango', '16x16', 'status', icon)
        if g.os_path_exists(fn):
            c.editCommands.insertIconFromFile(path=fn)

This deletes all icons of the node at position p:

.. code-block:: python

    c.editCommands.deleteNodeIcons(p=p)
</t>
<t tx="ekr.20181015144118.37">Using Leo’s latest sources from GitHub is highly recommended. Once git is installed, the following gets the latest Leo sources::

    git clone https://github.com/leo-editor/leo-editor.git

Thereafter, you can update Leo's sources with::

    git pull

Git is great in tracking history and reverting unwanted changes. And it has many other benefits.

Using git is very similar to using bzr or hg or any other SCCS.  To change Leo, you add files, you commit files, and you push files.  That's about it.
</t>
<t tx="ekr.20181015144118.38">c.cloneFindByPredicate is a powerful new addition to Leo.  Here is its docstring:

.. code-block:: python

    Traverse the tree given using the generator, cloning all positions for
    which predicate(p) is True. Undoably move all clones to a new node, created
    as the last top-level node. Returns the newly-created node. Arguments:

    generator,      The generator used to traverse the tree.
    predicate,      A function of one argument p returning true if 
                    p should be included.
    failMsg=None,   Message given if nothing found. Default is no message.
    flatten=False,  True: Move all node to be parents of the root node.
    iconPath=None,  Full path to icon to attach to all matches.
    redraw=True,    True: redraw the screen.
    undo_type=None, The undo/redo name shown in the Edit:Undo menu.
                    The default is 'clone-find-predicate'

For example, clone-find-all-marked command is essentially:

.. code-block:: python

    @cmd('clone-find-all-marked')
    def cloneFindMarked(self, flatten):

        def isMarked(p):
            return p.isMarked()

        self.cloneFindByPredicate(
            generator = self.all_unique_positions,
            predicate = isMarked,
            failMsg = 'nothing found',
            flatten = flatten,
            undoType = 'clone-find-marked',
        )

The predicate could filter on an attribute or *combination* of attributes. For example, the predicate could return p has attributes A and B but *not* attribute C. This instantly gives Leo full database query capabilities. If we then hoist the resulting node we see *all and only* those nodes satisfying the query.

These following position methods make it easy to skip @ignore trees or @&lt;file&gt; trees containing @all::

    p.is_at_all()          True if p is an @&lt;file&gt; node containing an @all directive.
    p.in_at_all()          True if p is in an @&lt;file&gt; tree whose root contains @all.
    p.is_at_ignore()       True if p is an @ignore node
    p.in_at_ignore_tree()  True if p is in an @ignore tree.

For example, here is how to gather only those marked nodes that lie outside any @ignore tree:

.. code-block:: python

    def isMarked(p):
        return p.isMarked() and not p.in_at_ignore_tree()

    c.cloneFindByPredicate(
        generator = self.all_unique_positions,
        predicate = isMarked,
        flatten = flatten,
        undoType = 'gather-marked',
    )
</t>
<t tx="ekr.20181015144118.39">Leo University is a project devoted to help people become Leo developers.

Here is the main page.  It contains links to individual lessons.
https://github.com/leo-editor/leo-editor/issues/816
</t>
<t tx="ekr.20181015144118.40">Leo uses a model/view/controller architecture.

- Controller: The Commands class and its helpers in leoCommands.py and leoEditCommands.py.

- Model: The VNode and Position classes in leoNodes.py.

- View: The gui-independent base classes are in the node "Gui Base Classes". The Qt-Specific subclasses are in the node "Qt gui".

**Important**: The general organization of these classes have changed hardly at all in Leo's 20+ year history.  The reason is that what each class does is fairly obvious.  How the gets the job done may have changed drastically, but *that's an internal implementation detail of the class itself*.  This is the crucial design principle that allows Leo's code to remain stable.  *Classes do not know or meddle in the internal details of other classes*.  As a result, nobody, including EKR, needs to remember internal details.
</t>
<t tx="ekr.20181015144118.7">Alt-X puts focus in the minibuffer. Ctrl-G escapes from the minibuffer.

Once there, you can use tab completion to reduce typing. For example, ``&lt;Alt-X&gt;open&lt;tab&gt;`` shows all commands that start with open.

Hit ``&lt;Enter&gt;`` to run a complete command.

``Ctrl-P`` (``repeat-complex-command``) repeats the last command entered from the minibuffer.

Leo maintains a **command history list** of all minibuffer commands you have entered.

When focus is in the minibuffer, ``UpArrow`` shows the previous minibuffer command, and ``DnArrow`` show the commands before that.

The body text of an ``@data history-list`` *setting node* preloads commands into the command history list, ignoring lines starting with ``#``. For example::

    run-pylint
    beautify-tree
    cff
    sort-lines
    # show-data
    check-clones
    expand-log-pane
    contract-log-pane</t>
<t tx="ekr.20190101093224.1">If you want to make a command undoable, you must create "before" and "after" snapshots of the parts of the outline that may change. Here are some examples.  Leo's source code contains many other examples.
</t>
<t tx="ekr.20190101093224.2">To undo a single change to body text:

.. code-block:: python

    command = 'my-command-name'
    b = c.undoer.beforeChangeNodeContents(p, oldYScroll=ypos)
    # Change p's body text.
    c.undoer.afterChangeNodeContents(p,
        command=command, bunch=b, dirtyVnodeList=[])
</t>
<t tx="ekr.20190101093224.3">If your command changes multiple nodes, the pattern is:

.. code-block:: python

    u, undoType = c.undoer, 'command-name'
    u.beforeChangeGroup(c.p, undoType)
    dirtyVnodeList = []
    changed = False
    # For each change, do something like the following:
    for p in to_be_changed_nodes:
        # Change p.
        dirtyVnodeList.append(p.v)
        u.afterChangeNodeContents(p, undoType, bunch)
        changed = True
    if changed:
        u.afterChangeGroup(c.p, undoType,
            reportFlag=False,
            dirtyVnodeList=dirtyVnodeList)
</t>
<t tx="ekr.20190117143933.1">Leo 5.9 final, https://leo-editor.github.io/leo-editor/ is now available on
[GitHub](https://github.com/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 &amp; @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**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md
</t>
<t tx="ekr.20190117143942.2">https://github.com/leo-editor/leo-editor/issues/1002
</t>
<t tx="ekr.20190117143942.29">Leo 6.8.8 removes support for LeoWapp and `--gui=browser`.
Use LeoJS or LeoInteg instead.

https://github.com/leo-editor/leo-editor/issues/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".
</t>
<t tx="ekr.20190117143942.394">https://github.com/leo-editor/leo-editor/issues/1007
</t>
<t tx="ekr.20190117143942.395">https://github.com/leo-editor/leo-editor/issues/1023
</t>
<t tx="ekr.20190117143942.399">When saving a file, Leo now raises a dialog warning if quitting might lose data.

There are three related issues:
https://github.com/leo-editor/leo-editor/issues/1031
https://github.com/leo-editor/leo-editor/issues/1050
https://github.com/leo-editor/leo-editor/issues/1003
</t>
<t tx="ekr.20190117143942.403">https://github.com/leo-editor/leo-editor/issues/1032</t>
<t tx="ekr.20190117143942.438">https://github.com/leo-editor/leo-editor/issues/1033
</t>
<t tx="ekr.20190117143942.450">https://github.com/leo-editor/leo-editor/issues/1036
https://github.com/leo-editor/leo-editor/issues/1046</t>
<t tx="ekr.20190117143942.463">https://github.com/leo-editor/leo-editor/issues/1040

This was a major refactoring of Leo's code.

See this post: https://groups.google.com/forum/#!topic/leo-editor/JfAUMMOSdvQ
</t>
<t tx="ekr.20190117143942.633">https://github.com/leo-editor/leo-editor/issues/1049
</t>
<t tx="ekr.20190117143942.647">https://github.com/leo-editor/leo-editor/issues/1051

Removed @string qt-ui-file-name.
</t>
<t tx="ekr.20190117143942.650">https://github.com/leo-editor/leo-editor/issues/1053

This was an ancient bug!

The fix was to call c.setFileTimeStamp(fileName) in x.replaceFileWithString.
</t>
<t tx="ekr.20190117143942.654">https://github.com/leo-editor/leo-editor/issues/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</t>
<t tx="ekr.20190117143942.672">https://github.com/leo-editor/leo-editor/issues/672

TravisCI: https://travis-ci.org/
</t>
<t tx="ekr.20190117143942.673">https://github.com/leo-editor/leo-editor/issues/804

Changed various style sheets as a workaround for a serious Qt bug.
</t>
<t tx="ekr.20190117143942.681">https://github.com/leo-editor/leo-editor/issues/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 @&lt;file&gt; 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.
</t>
<t tx="ekr.20190117143942.957">https://github.com/leo-editor/leo-editor/issues/998
</t>
<t tx="ekr.20190117143942.976">https://github.com/leo-editor/leo-editor/issues/1057
</t>
<t tx="ekr.20190118085508.1">https://github.com/leo-editor/leo-editor/issues/1056
</t>
<t tx="ekr.20190118222624.1">Leo no longer generates @nonl sentinels, so regularizing trailing ws is much easier.

#1048 @clean: https://github.com/leo-editor/leo-editor/issues/1048
#1037 @file:  https://github.com/leo-editor/leo-editor/issues/1037

</t>
<t tx="ekr.20190118222636.1">https://github.com/leo-editor/leo-editor/issues/1059
</t>
<t tx="ekr.20190118222654.1">https://github.com/leo-editor/leo-editor/issues/1021

The culprit was a mistaken fix to #690:
https://github.com/leo-editor/leo-editor/issues/690
</t>
<t tx="ekr.20190119065631.1">For the complete list, see:
https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A5.9+label%3ABug+is%3Aclosed</t>
<t tx="ekr.20190119070017.1"></t>
<t tx="ekr.20190119071258.1">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: https://github.com/leo-editor/leo-editor-contrib/blob/master/leonine.py

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.
  https://github.com/leo-editor/leo-editor/issues/993
</t>
<t tx="ekr.20190122041941.1">https://github.com/leo-editor/leo-editor/issues/926
</t>
<t tx="ekr.20190122042300.1">https://github.com/leo-editor/leo-editor/issues/1047

The following call FastRead().readFileFromClipboard:

- fc.getLeoOutlineFromClipBoard.
- fc.getLeoOutlineFromClipBoardRetainingClones.
- fc.getPos/VnodeFromClipboard.
</t>
<t tx="ekr.20190122044116.1">- LeoWapp: Leo in a browser.
- Integrated debugger.
- Support for pygments syntax coloring.
- Automatic sessions
  (Removed --session-save and --session-restore command-line arguments.)
- 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.</t>
<t tx="ekr.20190123075604.1">https://github.com/leo-editor/leo-editor/issues/981
https://github.com/leo-editor/leo-editor/issues/977

</t>
<t tx="ekr.20190123075859.1">https://github.com/leo-editor/leo-editor/issues/1065
</t>
<t tx="ekr.20190123122138.1"></t>
<t tx="ekr.20190307093145.1">g.execute_shell_command takes a single argument, which may be either a string or a list of strings. Each string represents one command.

g.execute_shell_command executes each command in order, waiting for each command to complete, except those commands starting with '&amp;'.

Examples:

.. code-block:: python

    # Run the qml app in a separate process:
    g.execute_shell_commands('qmlscene /test/qml_test.qml')

    # List the contents of a directory:
    g.execute_shell_commands([
        'cd ~/test',
        'ls -a',
    ])

    # Run a python test in a separate process.
    g.execute_shell_commands('python /test/qt_test.py')

g.execute_shell_commands_with_options inits an environment and then calls g.execute_shell_commands.  See Leo's source code for details.
</t>
<t tx="ekr.20190307095247.1">g.execute_shell_commands executes one or more commands in a separate process using subprocess.popen.

Wait for each command to complete, except those commands starting with '&amp;'.

See the scripting miscellany for more details.
</t>
<t tx="ekr.20190325062650.1">Leo now optionally supports syntax coloring with pygments.
See https://pygments.org/docs/

Related Leo issues:

- https://github.com/leo-editor/leo-editor/issues/568
- https://github.com/leo-editor/leo-editor/issues/1102

New settings (defaults as shown):

- @bool use-pygments = False
- @bool use-pygments-styles = True
- @string pygments-style-name = default
- Created a 'leonine' style.
  See: https://github.com/leo-editor/leo-editor-contrib/blob/master/leonine.py
</t>
<t tx="ekr.20190327105000.1">Copies the headlines of all descendants to the parent's body text.</t>
<t tx="ekr.20190327105147.364">https://github.com/leo-editor/leo-editor/issues/1081

Added warning when @asis or @nosent files change outside of Leo.
</t>
<t tx="ekr.20190327105249.1">https://github.com/leo-editor/leo-editor/issues/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
</t>
<t tx="ekr.20190327105503.1"></t>
<t tx="ekr.20190327105525.1">https://github.com/leo-editor/leo-editor/issues/1085

This branch removes all Python 2 compatibility code.
It will be the basis of Leo 6.0.
 </t>
<t tx="ekr.20190412074507.11">https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20190412074507.26">https://github.com/leo-editor/leo-editor/issues/1111</t>
<t tx="ekr.20190412074507.3">https://github.com/leo-editor/leo-editor/issues/1098
</t>
<t tx="ekr.20190412074507.4">https://github.com/leo-editor/leo-editor/issues/1090

command line--script relative path is relative to `leo/core` instead of file-system
</t>
<t tx="ekr.20190412074507.50">https://github.com/leo-editor/leo-editor/issues/1113
</t>
<t tx="ekr.20190412074507.52">https://github.com/leo-editor/leo-editor/issues/1114</t>
<t tx="ekr.20190412074507.6">https://github.com/leo-editor/leo-editor/issues/1018

fc.setCachedBits scans *all* nodes for cached data.
This simplifies fc.compute_attribute_bits.
</t>
<t tx="ekr.20190414191837.1">``xdb``
    Start a Leo's integrated debugger in a separate thread.

    Start the debugger from any part of any @&lt;file&gt; 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 commands 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`` is 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.

**Settings**

When ``@bool use_xdb_pane_output_area`` is True, all debugger output is sent to an output area in the Debug pane. The default is True, so you need this setting only if you don't want output set to the Debug pane.
</t>
<t tx="ekr.20190414193128.1">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.</t>
<t tx="ekr.20190414193153.1"></t>
<t tx="ekr.20190414193500.1">This paper explains how to use cff (clone-find-flattened) while
refactoring code. I could not have completed the refactoring of Leo's
atFile write code without using continuous, extensive use of cff.

There are two key ideas:

1. The clones produced by cff are short-term or medium-term data,
   easily created and easily dispensed with.

Such clones are valuable, but not precious. They will eventually be discarded.

2. Unlike tags (or any other kind of non-Leonine data), the clones
   produced by cff can be reorganized.

This is the priceless, unique advantage of clones.  You don't understand clones if you don't get this.

Example

1. While refactoring, it is essential to see all actual uses of a
   symbol (method, or ivar, whatever).

The starting point is to use cff to find all potential uses of the
symbol. If multiple files or classes use the symbol, you can use the
suboutline-only option to limit the matches created by cff.

2. After finding all potential uses of the symbol, you can reorganize
   the resulting clones as follows:

- Delete nodes that are completely irrelevant.
- Squirrel away likely-irrelevant nodes in a new organizer node.
- Highlight the defining node, say by making it the preceding sibling of the cff node.
- Leave all actual uses of the symbol where they are.

3. You have now focused your attention on the nodes that will likely
   change.

You can now rerun the search only on those cloned nodes to see all
instances of the symbol that might be changed. This is a crucial
double check on proposed changes.

Summary

I highly recommend that all Leonine programmers use the approach just
described when refactoring code.

Neither tags, nor filters, nor refactoring packages can emulate the
Leonine way of refactoring.</t>
<t tx="ekr.20190422181351.1">To specify a color, say for comment1, for *all* languages, create an @color node::

    @color comment1 = blue

To specify a color for a **particular** language, say Python, prepend the setting name
with the language name.  For example::

    @color python_comment1 = pink

Here are Leo's legacy (jEdit-based) @color settings:

    @color comment1
    @color comment2
    @color comment3
    @color comment4
    @color doc-part
    @color function
    @color keyword1
    @color keyword2
    @color keyword3
    @color keyword4
    @color keyword5
    @color label
    @color leo-keyword
    @color link
    @color literal1
    @color literal2
    @color literal3
    @color literal4
    @color markup
    @color name
    @color name-brackets
    @color null
    @color operator
    @color show-invisibles-space
    @color tab
    @color trailing-whitespace
    @color url

In addition, the pygments colorizer uses these settings::

    @color comment
    @color comment.hashbang
    @color comment.multiline
    @color comment.preproc
    @color comment.single
    @color comment.special
    @color error
    @color generic
    @color generic.deleted
    @color generic.emph
    @color generic.error
    @color generic.heading
    @color generic.inserted
    @color generic.output
    @color generic.prompt
    @color generic.strong
    @color generic.subheading
    @color generic.traceback
    @color keyword
    @color keyword.constant
    @color keyword.declaration
    @color keyword.namespace
    @color keyword.pseudo
    @color keyword.reserved
    @color keyword.type
    @color literal
    @color literal.date
    @color name.attribute
    @color name.builtin
    @color name.builtin.pseudo
    @color name.class
    @color name.constant
    @color name.decorator
    @color name.entity
    @color name.exception
    @color name.function
    @color name.function.magic
    @color name.label
    @color name.namespace
    @color name.other
    @color name.pygments
    @color name.tag
    @color name.variable
    @color name.variable.class
    @color name.variable.global
    @color name.variable.instance
    @color name.variable.magic
    @color number
    @color number.bin
    @color number.float
    @color number.hex
    @color number.integer
    @color number.integer.long
    @color number.oct
    @color operator.word
    @color other
    @color punctuation
    @color string
    @color string.affix
    @color string.backtick
    @color string.char
    @color string.delimiter
    @color string.doc
    @color string.double
    @color string.escape
    @color string.heredoc
    @color string.interpol
    @color string.other
    @color string.regex
    @color string.single
    @color string.symbol
    @color whitespace
    @color xt

**Note**: all @color settings may optionally end with the _color suffix.
</t>
<t tx="ekr.20190422182440.1">To specify a font, say for keyword_font, to be used as the default font for **all** languages, put the following in the body text of an @font node in leoSettings.leo::

    # keyword_font_family = None
    keyword_font_size = 16
    keyword_font_slant = roman
        # roman, italic
    keyword_font_weight = bold
        # normal, bold

Comments are allowed and undefined settings are set to reasonable defaults. At present, comments can not follow a setting: comments must start a line.

You can specify per-language settings by preceding the settings names by a prefix x. Such settings affect only colorizing for language x (i.e., all the modes in modes/x.py when using the new colorizer). For example, to specify a font for php (only), put the following in the body text of an @font node in leoSettings.leo::

    # php_keyword_font_family = None
    php_keyword_font_size = 16
    php_keyword_font_slant = roman
        # roman, italic
    php_keyword_font_weight = bold
        # normal, bold
</t>
<t tx="ekr.20190424063410.2">https://github.com/leo-editor/leo-editor/issues/1100
</t>
<t tx="ekr.20190424063410.37">https://github.com/leo-editor/leo-editor/issues/1116
</t>
<t tx="ekr.20190424063410.38">https://github.com/leo-editor/leo-editor/issues/1118
</t>
<t tx="ekr.20190608092106.1">g.es_clickable_link(c, p, line_number, message) writes a clickable
message to the Log pane.

Clicking it selects the given line number of p.b.</t>
<t tx="ekr.20190616175854.1">Leo's default gui uses Qt Docks. Use --no-dock to use Leo's legacy gui.

New and improved commands and features:

- Huge speed up of replace-all
- Added find-long-lines. Uses @bool max-find-long-lines-length = 110
- Added find-missing-docstrings. Honors @nopylint.
- Added import-free-mind-files
- Added print-window-state. This command is for Leo's developers.
- The pylint command generates clickable log messages and honor @nopylint.
- Support colorizing of Lua long brackets

New command-line arguments:

--init-docks
--no-dock
--trace=aList https://github.com/leo-editor/leo-editor/issues/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
</t>
<t tx="ekr.20190620113133.1">In the directory leo-editor/leo/themes are a number of theme files. These
can be loaded using the File, Open Outline menu option in Leo. Opening an
outline automatically loads it. Keep opening outlines until you find one
you like.

Then close all of the theme files.

Copy the theme file you chose from leo-editor/leo/themes to ~/.leo/themes
(you will have to create the themes folder here) and rename it something
like this: Original file is BreezeDarkTheme.leo rename to
BreezeDarkThemeLocal.leo

Now open your myLeoSettings.leo file.

Add the following to the headline of a new node as a child of your @settings node::

    @string theme-name = BreezeDarkThemeLocal

Now save the file and restart Leo.

You should now be using the theme of your choice. From here you need to
open the local theme file with Leo. The font sizing and colors are under
Theme Settings in the tree.
</t>
<t tx="ekr.20190622142940.1">This script appends the outline headlines, indented, to the current vim buffer::

    import leo.core.leoBridge as leoBridge
    import vim

    controller = leoBridge.controller(
        gui='nullGui',
        loadPlugins=True,  # True: attempt to load plugins.
        readSettings=True,  # True: read standard settings files.
        silent=True,  # True: don't print signon messages.
        verbose=False,  # True: print informational messages.
    )
    g = controller.globals()
    c = controller.openLeoFile("/home/tbrown/.leo/del.leo")

    def dent(node, result, level=0):
        result.append('  ' * level + node.h)
        for child in node.children:
            dent(child, result, level + 1)
        return result

    result = []
    dent(c.hiddenRootNode, result)
    vim.current.buffer[-1:] = result

It can be invoked with::

    :py import leodent

assuming it's in a file leodent.py and on the Python path.
</t>
<t tx="ekr.20190731085747.1">How it is possible to specify settings in @file? As I understand every setting should be a single outline.

Vitalije:

You can use clones. For example::

    --@settings
    ----my-shared-settings
    ------...
    ----some-specific-settings-for-this-outline
    ------....

    --@file my-shared-settings-somewhere.txt
    ----my-shared-settings

where `my-shared-settings` node is cloned from the @file subtree.

Quite often I use some script to combine some nodes, process them and generate some output file. And such script I put in a node with the following headline: ``@button n-save @key=Ctrl-s``. Then whenever I open this outline and whenever I hit Ctrl-s to save the outline, this script is executed. Of course I put in this script `c.save()` call and on every save my files are regenerated. 

When working for a web I often use Coffeescript, some html template generators like Pug, Sass for generating css files, ... Now all of these command line tools have watching mode where they watch folders for file changes and whenever source file is changed they regenerate the output file. But then you also need to run some packaging tool to bundle all generated files. Instead of watching for file changes, my script bound to Ctrl-s regenerate source files in memory and without saving them execute suitable tool only on changed sources and produced outputs bundle in the final file. This makes the whole process much faster.

Attached to this message is a Leo file that I have extracted from one of my projects. I hope that I didn't miss anything that the script require. 

In the outline you can find build server implemented in Coffeescript. You have to use npm or yarn to install necessary modules for this server to work. Once installed you start server by executing
`coffee tools/build-server.coffee` and it will start listening on port 8011. The script bound to Ctrl-s will search outline for nodes with the headlines like: @vendor, @pug, @coffee, @bulma and for each found node, it checks if the content of this node and its subtree has changed since last time and if it is, this content is sent to build server which transforms the source and returns result that script writes to output file. 
</t>
<t tx="ekr.20190802082825.1"></t>
<t tx="ekr.20191002072123.1">1. The directory leo-editor/leo/themes contains various theme files. You can load these files from the File:Open Outline menu.

Opening a theme outline automatically loads the theme. Keep opening outlines until you find one you like.

2. Close all of the theme files.

3. Copy the theme file you chose from leo-editor/leo/themes to ~/.leo/themes (you will have to create the themes folder here) and rename it something like myTheme.leo.  Note that the folder is ~/.leo, not ~.

4. Open your myLeoSettings.leo file.

Add the following to the headline of a new node as a child of your @settings node:
@string theme-name = myTheme.leo

5. Save the file and restart Leo.

You should now be using myTheme.leo. You can load myTheme.leo from Leo. The font sizing and colors are under Theme Settings in the tree.</t>
<t tx="ekr.20191003050703.1">Leo 6.1, https://leo-editor.github.io/leo-editor/ is now available on
[GitHub](https://github.com/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**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md
</t>
<t tx="ekr.20191003050703.11">This page shows all enhancements related to Leo 6.1:
https://github.com/leo-editor/leo-editor/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+milestone%3A6.1+label%3Aenhancement

#1253: Support @language asciidoc
https://github.com/leo-editor/leo-editor/issues/1253

#1297: warnings about @first &amp; @last
https://github.com/leo-editor/leo-editor/issues/1297

#1342: use labels in Find Tab
https://github.com/leo-editor/leo-editor/issues/1342

#1351: removed click/drag commands
https://github.com/leo-editor/leo-editor/issues/1351

#1353: new cursor commands
https://github.com/leo-editor/leo-editor/issues/1353

#1371: support pandoc and @language pandoc
https://github.com/leo-editor/leo-editor/issues/1371

#1383: Expand ~ in all paths
https://github.com/leo-editor/leo-editor/issues/1383

#1398: Support path expressions in @rst, @adoc, @pandoc and @sphinx nodes
https://github.com/leo-editor/leo-editor/issues/1398

New show-clone-ancestors and show-clone-parents commands</t>
<t tx="ekr.20191003050703.15"></t>
<t tx="ekr.20191003050703.3"></t>
<t tx="ekr.20191003050703.6">This page shows all bugs related to Leo 6.1:
https://github.com/leo-editor/leo-editor/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+milestone%3A6.1+label%3Abug</t>
<t tx="ekr.20191003051240.1">The pyzo_in_leo plugin embeds pyzo (https://pyzo.org/) within Leo.

Added support for black: https://pypi.org/project/black/.

Added support for asciidoc, asciidoctor, pandoc and sphinx.

Added support for @language pandoc.

Added @nopyflakes directive.

The history_tracer plugin animates git commits.

New command-line arguments::

  --global-docks
  --window-spot
</t>
<t tx="ekr.20191003051510.1274">https://github.com/leo-editor/leo-editor/issues/1289</t>
<t tx="ekr.20191003051510.14">https://github.com/leo-editor/leo-editor/issues/1263
</t>
<t tx="ekr.20191003051510.1626">https://github.com/leo-editor/leo-editor/issues/1306
</t>
<t tx="ekr.20191003051510.1696">https://github.com/leo-editor/leo-editor/issues/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
https://github.com/leo-editor/leo-editor/issues/1341</t>
<t tx="ekr.20191003051809.1">#1316: unify g.TypedDict classes
https://github.com/leo-editor/leo-editor/issues/1316

#1323: convert to fstrings
https://github.com/leo-editor/leo-editor/issues/1323

#1350: LeoBridge option to not use the cache
https://github.com/leo-editor/leo-editor/issues/1350

#1364: Use """ for all docstrings
https://github.com/leo-editor/leo-editor/issues/1364

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

</t>
<t tx="ekr.20191003052014.1">#0490: scroll wheel problems
https://github.com/leo-editor/leo-editor/issues/490

#1273: dashed border after dialog
https://github.com/leo-editor/leo-editor/issues/1273

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

#1276: clear-\*-uas don't set outline dirty
https://github.com/leo-editor/leo-editor/issues/1276

#1285: Control-clicks can find definitions in the wrong outline
https://github.com/leo-editor/leo-editor/issues/1285

#1295: too many @first lines
https://github.com/leo-editor/leo-editor/issues/1295

#1307: @first/last invalid in @clean
https://github.com/leo-editor/leo-editor/issues/1307

#1318: better arrangement for docks in new windows
https://github.com/leo-editor/leo-editor/issues/1318

#1327: Missing outlines for non-existent files
https://github.com/leo-editor/leo-editor/issues/1327

#1333: undo glitch
https://github.com/leo-editor/leo-editor/issues/1333

#1334: @language C crashes Leo
https://github.com/leo-editor/leo-editor/issues/1334

#1335: ipython--exec
https://github.com/leo-editor/leo-editor/issues/1336

#1340: body/outline ratio in new files
https://github.com/leo-editor/leo-editor/issues/1344

#1345: unit tests fail from bridge
https://github.com/leo-editor/leo-editor/issues/1345

#1347: @asis problems
https://github.com/leo-editor/leo-editor/issues/1347

#1349: Find Status
https://github.com/leo-editor/leo-editor/issues/1349

#1361: at.precheck is broken
https://github.com/leo-editor/leo-editor/issues/1361

#1362: crash when reloading
https://github.com/leo-editor/leo-editor/issues/1362

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

#1379: Crash on saving workbook while simulating a new user's experience
https://github.com/leo-editor/leo-editor/issues/1378

#1380: Opening workbook for new user selects top-level nodes repeatedly
https://github.com/leo-editor/leo-editor/issues/1380

#1381: Crash on reloading workbook while simulating newbie experience
https://github.com/leo-editor/leo-editor/issues/1381

#1385: Console gui doesn't ask to create leoid
https://github.com/leo-editor/leo-editor/issues/1385

#1392: external file not always saved
https://github.com/leo-editor/leo-editor/issues/1392

#1403: Catch exceptions during startup
https://github.com/leo-editor/leo-editor/issues/1403

#1404: ensure well-formed gnx's
https://github.com/leo-editor/leo-editor/issues/1404

#1415: crash when .leo doesn't exist
https://github.com/leo-editor/leo-editor/issues/1415

#1416: select first .leo file on the command line
https://github.com/leo-editor/leo-editor/issues/1416
</t>
<t tx="ekr.20191003055249.1">#1266: orange (beautify &amp; blacken)
https://github.com/leo-editor/leo-editor/issues/1266

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

#1325: black keeps overindented comments:
https://github.com/leo-editor/leo-editor/issues/1325
</t>
<t tx="ekr.20191003060551.1">https://github.com/leo-editor/leo-editor/issues/1093
The pyzo_in_leo plugin embeds pyzo (https://pyzo.org/) within Leo.
</t>
<t tx="ekr.20191003061844.1">https://github.com/leo-editor/leo-editor/issues/1315</t>
<t tx="ekr.20191003062919.1">Leo 6.0 final, https://leo-editor.github.io/leo-editor/ is now available on
[GitHub](https://github.com/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**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md</t>
<t tx="ekr.20191003062919.10">Problems syntax coloring TeX and LaTeX files
https://github.com/leo-editor/leo-editor/issues/1088

git-diff crash
https://github.com/leo-editor/leo-editor/issues/1136

Fixed a serious crasher
https://github.com/leo-editor/leo-editor/issues/1161

Ctrl-minus selects multiple nodes
https://github.com/leo-editor/leo-editor/issues/1168

Recent files menu
https://github.com/leo-editor/leo-editor/issues/1188

--maximize doesn't work
https://github.com/leo-editor/leo-editor/issues/1189

open-outline buglet
https://github.com/leo-editor/leo-editor/issues/1200

Log pane does not report full commit number
https://github.com/leo-editor/leo-editor/issues/1209

Never crash during startup
https://github.com/leo-editor/leo-editor/issues/1215

Fix the ctagscompleter plugin
https://github.com/leo-editor/leo-editor/issues/1211

Status Bar Won't Accept Style
https://github.com/leo-editor/leo-editor/issues/1218

vim-mode-\*-border settings do not work on Qt 5
https://github.com/leo-editor/leo-editor/issues/1221

gui=console. delete line command d is not working
https://github.com/leo-editor/leo-editor/issues/1224

gui=console. Backspace, delete keys not working
https://github.com/leo-editor/leo-editor/issues/1238

The bookmarks plugin is polluting the .leo file with inappropriate data
https://github.com/leo-editor/leo-editor/issues/1247

vr-lock gets overwritten
https://github.com/leo-editor/leo-editor/issues/1256

Hard crash in @contextmenu plugin if file not found
https://github.com/leo-editor/leo-editor/issues/1257

stickynoteenc traceback
https://github.com/leo-editor/leo-editor/issues/1265

Fixed misalignment in LeoQtLog.put</t>
<t tx="ekr.20191003062919.11">This page shows all enhancements related to Leo 6.0:
https://github.com/leo-editor/leo-editor/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+milestone%3A6.0+label%3Aenhancement
</t>
<t tx="ekr.20191003062919.12">Huge speed up of replace-all
https://github.com/leo-editor/leo-editor/issues/1152

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

Added find-missing-docstrings. Honors @nopylint.
https://github.com/leo-editor/leo-editor/issues/1178

Added import-free-mind-files

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

The pylint command generates clickable log messages.
https://github.com/leo-editor/leo-editor/issues/1173

The pylint command honors @nopylint.
https://github.com/leo-editor/leo-editor/issues/1178

Improved python_terminal plugin.
*Important*: this plugin segfaults when Leo starts up on some machines.
https://github.com/leo-editor/leo-editor/issues/1212</t>
<t tx="ekr.20191003062919.13">Reform how Leo handles git time stamps
https://github.com/leo-editor/leo-editor/issues/1126

Added unit tests for find methods
https://github.com/leo-editor/leo-editor/issues/1179

Suppress menu items at load time
https://github.com/leo-editor/leo-editor/issues/1199

Added g.es_clickable_link.

Added g.GetRepresentativeObjects</t>
<t tx="ekr.20191003062919.14">Disallow nested @&lt;file&gt; nodes: a failed experiment
https://github.com/leo-editor/leo-editor/issues/1134

Support colorizing of Lua long brackets
https://github.com/leo-editor/leo-editor/issues/1175

Add dock commands to Window Menu
https://github.com/leo-editor/leo-editor/issues/1261
</t>
<t tx="ekr.20191003062919.15">New command-line arguments:

--init-docks
https://github.com/leo-editor/leo-editor/issues/1205

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

--trace=aList
https://github.com/leo-editor/leo-editor/issues/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</t>
<t tx="ekr.20191003062919.2">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
</t>
<t tx="ekr.20191003062919.3"></t>
<t tx="ekr.20191003062919.4">Complete transition to python 3
https://github.com/leo-editor/leo-editor/issues/1137

Chinese characters in command names
https://github.com/leo-editor/leo-editor/issues/1121

Use super wherever possible
https://github.com/leo-editor/leo-editor/issues/1169
</t>
<t tx="ekr.20191003062919.5">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
https://github.com/leo-editor/leo-editor/issues/1150

Use --no-dock to use Leo's legacy Qt gui.
https://github.com/leo-editor/leo-editor/issues/1171
</t>
<t tx="ekr.20191003062919.6">This page shows all bugs related to Leo 6.0:
https://github.com/leo-editor/leo-editor/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+milestone%3A6.0+label%3Abug</t>
<t tx="ekr.20191003062919.7">@command vs @item
https://github.com/leo-editor/leo-editor/issues/1117

Recent changes probably broke settings_finder.py
https://github.com/leo-editor/leo-editor/issues/1144

</t>
<t tx="ekr.20191003062919.8">As you can see from this bug list, adding support for Qt docks took a lot of work.

Support docks in "Log pane" plugins
https://github.com/leo-editor/leo-editor/issues/1154

Raise dock with focus
https://github.com/leo-editor/leo-editor/issues/1159

Completion tab is not visible
https://github.com/leo-editor/leo-editor/issues/1163

Can't reopen a closed dock
https://github.com/leo-editor/leo-editor/issues/1167

Random dock layout for new users
https://github.com/leo-editor/leo-editor/issues/1190

Allow the user to choose central widget
https://github.com/leo-editor/leo-editor/issues/1192

Allow Render dock.
https://github.com/leo-editor/leo-editor/issues/1193

Phantom dock widget
https://github.com/leo-editor/leo-editor/issues/1196

Find and spell tabs
https://github.com/leo-editor/leo-editor/issues/1197

New documents have collapsed body pane
https://github.com/leo-editor/leo-editor/issues/1198

Always split body dock
https://github.com/leo-editor/leo-editor/issues/1206

Docks created by plugins can't be closed
https://github.com/leo-editor/leo-editor/issues/1207

free-layout plugin with docks
https://github.com/leo-editor/leo-editor/issues/1216

Render widget not visible: Plugins
https://github.com/leo-editor/leo-editor/issues/1230
</t>
<t tx="ekr.20191003062919.9">Duplicate headlines
https://github.com/leo-editor/leo-editor/issues/1127

LeoWapp key handling in minibuffer
https://github.com/leo-editor/leo-editor/issues/1131

insert-child duplicates p.b
https://github.com/leo-editor/leo-editor/issues/1142

Ctrl-S doesn't save
https://github.com/leo-editor/leo-editor/issues/1143

LeoWapp focus issues
https://github.com/leo-editor/leo-editor/issues/1146
</t>
<t tx="ekr.20191004072604.1">Issues related to asciidoc:
https://github.com/leo-editor/leo-editor/issues?utf8=%E2%9C%93&amp;q=is%3Aissue+milestone%3A6.1+label%3Aasciidoc+

**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 &lt;full path&gt;, 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.

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

</t>
<t tx="ekr.20191004123555.1">``rst3``
    Converts ``@rst`` nodes to restructured text. This command automatically creates underlining for rST sections. To reorganize a document, just reorganize the corresponding Leo outline: you don't have to change markup by hand. Search or "rst" in ``leoSettings.leo`` to see the pertinent settings.

``adoc``
     Converts ``@adoc`` nodes to asciidoc text. This command automatically creates markup for asciidoctor sections. To reorganize a document, just reorganize the corresponding Leo outline: you don't have to change markup by hand.</t>
<t tx="ekr.20191007104843.1">**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.</t>
<t tx="ekr.20191026191805.1">https://github.com/leo-editor/leo-editor/issues/1388
</t>
<t tx="ekr.20191118115949.1">This is the Theory of Operation for the TokenOrderGenerator (TOG) class and
related classes.</t>
<t tx="ekr.20191206062224.1">The **TokenOrderGenerator** (TOG) class injects two-way links between all
tokens and the corresponding ast nodes. The TOG class also injects
parent/child links into all ast nodes.

The TOG class defines visitors that visit ast nodes in **token order**, the
traversal order that corresponds to the order of the tokens produced by
python's tokenizer module. The only way to ensure this correspondence is to
use separate visitors for all ast nodes. All visitors are straightforward
generators.

TOG visitors eventually call ``TOG.sync_token``, which checks that that tokens
are, in fact, visited in the correct order. ``TOG.sync_token`` is an
ever-present unit test.

The **TokenOrderTraversal** (TOT) class uses the parent/child links created
by the TOG class. TOT.traverse contains a single for-loop that calls all
nodes of the parse tree in token order. This loop is extremely fast. Using
the TOT class, client code can easily modify the token list or parse tree
as desired.
</t>
<t tx="ekr.20191206063508.1">The ``TOG.do_If`` visitor calls ``TOG.find_next_significant_token`` to
determine whether ``TOG.do_If`` should generate an "if" or an "elif" token.
This help is essential, because the following two source files generate
identical parse trees!

::

  if 1:            if 1:
      pass             pass
  else:            elif 2:
      if 2:            pass
          pass

Similarly, the ``TOG.do_Str`` and ``TOG.do_JoinedStr`` visitors call
``TOG.get_concatenated_string_tokens`` to handle one ore more concatenated
string tokens.

Finally, ``TOG.do_slice`` calls ``TOG.find_next_significant_token`` to determine
whether a slice without a step contains an optional colon.

``TOG.find_next_significant_token`` and ``TOG.get_concatenated_string_tokens`` are
crucial inventions. TOG class would not be possible without them.
</t>
<t tx="ekr.20191206064645.1">``TOG.px`` is an index into the token list. It is either -1, or it points
at the previous significant token. *Note*: TOG.find_next_significant_token
and TOG.get_concatenated_string_tokens use TOG.px, but never change TOG.px.

TOG.sync_token(self, kind, val) associates tokens with ast nodes as
follows:

1. If (kind, val) denote an *insignificant* token, TOG.sync_token does
   nothing.

2. Otherwise, (kind, val) denotes a *significant* token. TOG.sync_token
   associates that token, *plus* all previous *insignificant* tokens with
   self.node, the ast node presently being visited.

In addition, if (kind, val) denotes a *significant* token, TOG.sync_token
checks that the next *significant* token in the token list has the expected
kind and value. This is done as follows:

- TOG.sync_token advances TOG.px to point at the next significant token,
  call it T.
- TOG.raises AssignLinksError if (T.kind, T.value) != (kind, val)

To summarize token syncing:

- The TOG.px index tracks the last-seen *significant* token.
- TOG.px advances monotonically through the token list.
- TOG.find_next_significant_token and TOG.get_concatenated_string_tokens
  scan forward through the token list using a private copy of TOG.px. These
  methods never change TOG.px itself.
- This token-syncing machinery is the *simplest* thing that could possibly
  work. It is also the *fastest* thing that could possibly work.
</t>
<t tx="ekr.20200107105607.1">**Simplicity**:

- The distinction between significant and insignificant tokens makes
  token-order traversals possible. This distinction drastically simplifies
  TOG visitors. They never have to generate insignificant tokens!

- TOG.find_next_significant_token and TOG.get_concatenated_string_tokens()
  use TOG.px to look ahead in the token list.

- It took a long time to realize that the parse tree needs help from the
  token list, not the other way around!

**Speed**: The TOG creates links between tokens and ast nodes in roughly the time
taken by python's tokenize.tokenize and ast.parse library methods. The TOT
class traverses trees annotated with parent/child links even more quickly.

TOG class avoids both ``ast.fix_missing_locations`` and ``ast.get_source_segment``,
which are too slow to be useful.

**Memory**: The TOG class makes no significant demand on python's resources:

- Generators add nothing to python's call stack.
- The *only* variable-length data created by the TOG is TOG.node_stack.
  This stack resides in python's heap, so its length is unimportant. In the
  worst case, it might contain a few thousand entries.
- The TOT uses no variable-length data whatever.
</t>
<t tx="ekr.20200107142458.1">To access the code, do one of the following:

.. code-block::

    import leoAst
    import leo.core.leoAst as leoAst

You can then run the fstringify commands as follows:

.. code-block::

    changed = leoAst.Fstringify().fstringify_file(filename)
    changed = leoAst.Fstringify().fstringify_diff_files(filename)</t>
<t tx="ekr.20200107143607.1">The following runs all unit tests for leoAst.py::

    python -m leo.core.leoAst

The following runs coverage tests::

    pytest -x --cov-report html --cov-report term-missing --cov=leo.core.leoAst leo/core/leoAst.py
</t>
<t tx="ekr.20200113232354.1">The **Token** class represents one token, created by tokenize.tokenize.

The **Fstringify** class is an re-implementation of the external fstringify
project using the TOG class.

The **Orange** class is a re-implementation of the black project. |br|
The name "Orange" is a play on words: "Orange is the new black".

The **AstDumper** class provides an extensive set of tools for examining
token lists, parse trees, and the links between them.

The **BaseTest** class provides common infrastructure for all other test classes.
*Important*: BaseTest.make_data is, all by itself, a very strong unit test.
</t>
<t tx="ekr.20200113234440.1">The distinction between **significant** and **insignificant** tokens is
crucial. Visitors call ``TOG.gen_token``, ``TOG.gen_op``, etc. *only* for
significant tokens. The ``is_significant`` and ``is_significant_token``
functions define which tokens are significant.

Visitors can't know, just by looking at the parse tree, whether the input
contains *insignificant* tokens. For example, the source tokens might
contain non-essential parentheses, or optional trailing commas, or whether
two statements are separated by a semicolon.
</t>
<t tx="ekr.20200213034654.1">Leo is starting on one of the external monitors and I have no way to
move it back to my laptop screen.

This has happened to me on Windows for as long as I can remember, mid
1990s and Windows 3. It's rare, but I don't think a year has gone by
where it hasn't occurred to me. At any rate, the most reliable and
portable solution I've come across is:

- Press [Alt]-[Tab] until the invisible program has focus.
- Press [Alt]-[spacebar] to bring up window controls (Move, Size, Min, Max, Close).
- Press [M] to activate Move.
  A dotted or thin gray outline of window shape should appear.
- Press arrow cursor keys to move the outline centrally on active screen.
  (usually right- and down-arrow)
- Press [enter] when it's moved on-screen enough to nab the Title bar with the mouse cursor.</t>
<t tx="ekr.20200225075435.1">Leo 6.2.1, https://leo-editor.github.io/leo-editor/ is now available on [GitHub](https://github.com/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**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md</t>
<t tx="ekr.20200313051859.1">Persistent body editors:
https://github.com/leo-editor/leo-editor/issues/1268

Improve alt-click popups:
https://github.com/leo-editor/leo-editor/issues/1286

Add tool tips for headlines:
https://github.com/leo-editor/leo-editor/issues/1310

Add an importer for todo.txt files
https://github.com/leo-editor/leo-editor/issues/1499</t>
<t tx="ekr.20200313051926.1">For a list of all bugs fixed in Leo 6.2 see:
https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.2+label%3Abug
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:
https://github.com/leo-editor/leo-editor/issues/1437
The fix is due to Vitalije Milosevic.

Possible problems with marks:
https://github.com/leo-editor/leo-editor/issues/1484

execute_shell_commands creates zombie processes:
https://github.com/leo-editor/leo-editor/issues/1489
</t>
<t tx="ekr.20200313052138.1">Convert Leo's code to fstrings:
https://github.com/leo-editor/leo-editor/issues/1421

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

Simplify startup logic:
https://github.com/leo-editor/leo-editor/issues/1472

Retire @doc file convention:
https://github.com/leo-editor/leo-editor/issues/1496

Add ivars for command1/2 event handlers:
https://github.com/leo-editor/leo-editor/issues/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:
https://github.com/leo-editor/leo-editor/issues/1539</t>
<t tx="ekr.20200313053803.1">Leo's legacy layout is now the default:
https://github.com/leo-editor/leo-editor/issues/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.
</t>
<t tx="ekr.20200313054557.1">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:
https://github.com/leo-editor/leo-editor/issues/1518
At present, they work only w/o docks.</t>
<t tx="ekr.20200313060126.1">Commands:

- Added the fstringify-files and diff-fstringify-files commands.
- Improved the beautify-files command. Added the diff-beautify-files commands.

Code:

- Added the TokenOrderGenerator and TokenOrderTraverser classes in leoAst.py.
  See https://github.com/leo-editor/leo-editor/issues/1440
- Rewrote c.deletePositionsInList. New code by Виталије Милошевић, (Vitalije Milosevic).

Features and settings:

- Added importers for the rust language and todo.txt files.
- Added the viewrendered3 plugin.
- Leo's legacy layout is now the default.
- Removed unused settings from leoSettings.leo.
- Added an importer for rust.

Bugs:

- Fixed all known bugs, including some notable, long-standing bugs.
</t>
<t tx="ekr.20200526090848.1">Sun, Dec 15, 2019
	
I had some really old version of leo - I believe it was 5.x and was
installed 1.5 years ago. I use Leo for collecting thoughts, writing
down stuff, structuring a talk etc. Decided to get out of comfort zone
and cloned git repo and daily git pull and started using that.

This is brilliant. Bunch of my myLeoSettings.leo stuff is no longer
needed with dockable panes for body and outline; and it remembers
setting too. Plus, the default look is very nice (I am on elementaryos
5.1)

Went to LeoVue site and only one word. *Wow*. Installed the CDN
version on laptop as well and put it under local nginx. So good that I
actually don't use any of the render stuff that I used to do before.

Now there is a blue bar that shows the opened files - under window
title bar, and above menus. I usually have only one file open and this
takes away premium vertical space in my laptop - how do I get rid of
that? When I had multiple files open, I could right click on one of
them and do some "detach" to get it out for that file - but I want
this to be permanently hidden. FWIW, I also keep icon-bar always
hidden to save space - which seems to be remembered in this version
than me having to start leo with such a setting.

Overall awesome stuff - rarely do one get so thrilled to see software so nicely advanced and still true to its core in a short time.


I am trying to convert different people to use Leo and they have their
own leo files. We share those over git or shared folder. Having an
ability to import also allows individual contribs to larger outlines.

It also helps in keeping the left side outline pane a bit more
manageable. On large outlines, there is too much vertical scrolling to
keep focus. This can also be solved by giving some option to collapse
everything outside current node to one single ellipsis/plus sign as
well.

Back to learning new leo  then :)</t>
<t tx="ekr.20200807105709.1">The classes in `leoAst.py &lt;https://github.com/leo-editor/leo-editor/blob/devel/leo/core/leoAst.py&gt;`_
unify python's token-based and ast-based worlds by creating two-way links
between tokens in the token list and ast nodes in the parse tree.

Are you sure you want to use leoAst?

- `asttokens &lt;https://asttokens.readthedocs.io/en/latest/user-guide.html&gt;`_ will usually be a better choice:
- Support for the leoAst module ends with Python 3.14.

leoAst.py is part of `Leo &lt;https://leo-editor.github.io/leo-editor/&gt;`_, and can be used
completely independently of Leo.

You must use Leo to see the intended outline structure of the code. Without
Leo, you will see special **sentinel comments** that create Leo's outline
structure. These comments have the form::

    #@&lt;comment-kind&gt;:&lt;user-id&gt;.&lt;timestamp&gt;.&lt;number&gt;: &lt;outline-level&gt; &lt;headline&gt;

If you have any trouble installing or using this code, please help for help
on `Leo's forum &lt;https://groups.google.com/forum/#!forum/leo-editor&gt;`_
</t>
<t tx="ekr.20200807105737.1">.. _`Leo issue #1440`: https://github.com/leo-editor/leo-editor/issues/1440

New ast nodes are sometimes required to support new language features,
especially language features that require new syntax or keywords. Python
has added new nodes fairly often in the past. New nodes may be added in
future. When that happens, the following changes will be needed to
leoAst.py:

- Add a visitor for the new node.
- Add one or more unit tests that fully cover the new visitor.

The ``test_visitors_exist`` unit test checks that visitors exist for all
ast nodes defined by to a particular version of python.

See `Leo issue #1440`_ for notes relating to the code.
</t>
<t tx="ekr.20200807110628.1">leoAst.py is designed to be run from the command line::

    usage:
        leoAst.py --help
        leoAst.py [--fstringify | --fstringify-diff | --orange | --orange-diff] PATHS
        leoAst.py --py-cov [ARGS]
        leoAst.py --pytest [ARGS]
        leoAst.py --unittest [ARGS]

    examples:
        --py-cov "-f TestOrange"
        --pytest "-f TestOrange"
        --unittest TestOrange

    positional arguments:
      PATHS              directory or list of files

    optional arguments:
      -h, --help         show this help message and exit
      --fstringify       leonine fstringify
      --fstringify-diff  show fstringify diff
      --orange           leonine Black
      --orange-diff      show orange diff
      --py-cov           run pytest --cov on leoAst.py
      --pytest           run pytest on leoAst.py
      --unittest         run unittest on leoAst.py</t>
<t tx="ekr.20200807111156.1"></t>
<t tx="ekr.20200909171301.1">#####################
Leo's Markup Language
#####################

.. index::
    pair: Markup; Reference
    pair: Section Reference; Reference
    pair: @others; Reference

Leo's **markup** tells Leo how to create external files from ``@file`` trees. Markup may appear in any body text, and *must* appear in the body of the ``@file`` node itself.

There are two kinds of markup: **section references** (``&lt;&lt; this is my section &gt;&gt;``) and the **@others** directive. Section references refer to **named nodes**, nodes whose *headlines* look like a section reference. ``@others`` refers to all *other* (unnamed) nodes. Here is the body text of a typical ``@file`` node for a python file:

.. code-block:: python

    """A docstring"""
    &lt;&lt; imports &gt;&gt;
    @others
    if __name__ == '__main__':
        main()
    @language python
    @tabwidth -4

A child node must define the ``&lt;&lt; imports &gt;&gt;`` node. Other children will typically define classes, methods, functions and data.

When writing this file, Leo writes:

- The docstring.
- The *body text* of the ``&lt;&lt; imports&gt;&gt;`` node.
- The body text of all *other* nodes, in outline order.
- The lines after the ``@others`` directive.

Leo's markup applies to scripts as well as external files. Leo's ``execute-script`` command **composes** the script from the selected node, using Leo's markup. For example: this body text defines the top-level part of a script:

.. code-block:: python

    """My script"""
    &lt;&lt; imports &gt;&gt;
    class Controller:
        # Child nodes define the methods of this class.
        @others
    Controller(c).run # c *is* defined.

**Important**: Leo recognizes section references *everywhere*, even inside strings or comments.
</t>
<t tx="ekr.20201014052236.1">Leo 6.3, https://leo-editor.github.io/leo-editor/ is now available on
[GitHub](https://github.com/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**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md</t>
<t tx="ekr.20201014052236.2">**Major change**

Refactor Leo's key handling code
https://github.com/leo-editor/leo-editor/issues/1269

**Other changes**

Remove pylint complaints from npyscreen sources
https://github.com/leo-editor/leo-editor/issues/1709

Remove pyflakes complaints from mod_http.py
https://github.com/leo-editor/leo-editor/issues/1710
</t>
<t tx="ekr.20201014052236.3">contract-all-subheads
https://github.com/leo-editor/leo-editor/issues/1632

cycle-editor-focus (Restored)
https://github.com/leo-editor/leo-editor/issues/1575

import-legacy-external-files
https://github.com/leo-editor/leo-editor/issues/1581

paste-as-template
https://github.com/leo-editor/leo-editor/issues/1593

move-lines-to-next-node
https://github.com/leo-editor/leo-editor/issues/1606

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

restart-leo
https://github.com/leo-editor/leo-editor/issues/1128

show-settings: Add [T] to legend to indicate theme file settings.
https://github.com/leo-editor/leo-editor/issues/1698
</t>
<t tx="ekr.20201014052236.4">**Major features**

leoAst.py: Unify the ast and token worlds
https://github.com/leo-editor/leo-editor/issues/1440

Retire qt docks
https://github.com/leo-editor/leo-editor/issues/1672

**Other features**

Better alt-click popups
https://github.com/leo-editor/leo-editor/issues/1286

Add support for --trace=zoom
https://github.com/leo-editor/leo-editor/issues/1569

Ctrl-click should ignore defs in @nosearch
https://github.com/leo-editor/leo-editor/issues/1592

Show github branch in outline title
https://github.com/leo-editor/leo-editor/issues/1616

Add support for @language json
https://github.com/leo-editor/leo-editor/issues/1619

#1620: git-diff clones added nodes
https://github.com/leo-editor/leo-editor/issues/1620

Added @button write-leoPyRef.leo
https://github.com/leo-editor/leo-editor/issues/1716
</t>
<t tx="ekr.20201014052236.5">For a list of all bugs fixed in Leo 6.3 see:
https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.3+label%3Abug
The first comment in each bug contains a summary of the bug and its fix.

Crash on reloading workbook while simulating newbie experience
https://github.com/leo-editor/leo-editor/issues/1381

Headline icons doubled
https://github.com/leo-editor/leo-editor/issues/1559

Abbreviations w/ German keyboards
https://github.com/leo-editor/leo-editor/issues/1563

Open theme file fails on posix
https://github.com/leo-editor/leo-editor/issues/1564

Tab pane disappears
https://github.com/leo-editor/leo-editor/issues/1570
PR: https://github.com/leo-editor/leo-editor/pull/1660

No command function for 'About...'
https://github.com/leo-editor/leo-editor/issues/1595

Crash in c.executeMinibufferCommand
https://github.com/leo-editor/leo-editor/issues/1596

leoAst.py fails for python 3.8
https://github.com/leo-editor/leo-editor/issues/1600

Typescript colorizer does not color block comments properly
https://github.com/leo-editor/leo-editor/issues/1602

Exit after refresh-from-disk
https://github.com/leo-editor/leo-editor/issues/1603

open-theme-file on arch linux
https://github.com/leo-editor/leo-editor/issues/1621

Set language for cloned nodes
https://github.com/leo-editor/leo-editor/issues/1625

forward-word-extend-selection doesn't work the same as back-word-extend-selection
https://github.com/leo-editor/leo-editor/issues/1653

Remove duplicates in nested splitter Open Window list
https://github.com/leo-editor/leo-editor/issues/1678

Performance bugs on open
https://github.com/leo-editor/leo-editor/issues/1688

@test nodes not colored correctly
https://github.com/leo-editor/leo-editor/issues/1696

Problems with marked bits
https://github.com/leo-editor/leo-editor/issues/1694

Bug in php importer
https://github.com/leo-editor/leo-editor/issues/1717

unittest fails w/ python3.8
https://github.com/leo-editor/leo-editor/issues/1700</t>
<t tx="ekr.20201014052236.6">Added @bool add-context-to-headline
https://github.com/leo-editor/leo-editor/issues/1605

Removed the following command-line options:

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

Added support for --trace=zoom</t>
<t tx="ekr.20201015122734.1">Render asciidoc and pandoc markup in VR
https://github.com/leo-editor/leo-editor/issues/333

VR plugin should honor headline directives
https://github.com/leo-editor/leo-editor/issues/1287

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

Use standard opml tags
https://github.com/leo-editor/leo-editor/issues/1473

Context menu
https://github.com/leo-editor/leo-editor/issues/1531

Deprecated settings_finder plugin
https://github.com/leo-editor/leo-editor/issues/1669
</t>
<t tx="ekr.20201015152218.1">JS importer fails with reveal.js
https://github.com/leo-editor/leo-editor/issues/1481

Python importer does not import black.py properly
https://github.com/leo-editor/leo-editor/issues/1493

Create a Rust importer
https://github.com/leo-editor/leo-editor/issues/1538

Create a cython importer
https://github.com/leo-editor/leo-editor/issues/1608

Fix ts importer problems
https://github.com/leo-editor/leo-editor/issues/1617

Fix c++ importer problems
https://github.com/leo-editor/leo-editor/issues/1626
</t>
<t tx="ekr.20201017061850.1">Major features:
- leoAst.py unifies the ast and token worlds.
- Retired support for Qt docks.
- Refactored Leo's key handling code.

Features:
- Merged leoPlugins.leo into LeoPluginsRef.leo
- Added cython and rust importers
- Improved C++, Javascript, Python, TypeScript importers.
- Added 7 new commands.
- Added support for @language json.

Fixed all known bugs.</t>
<t tx="ekr.20210326081805.1"></t>
<t tx="ekr.20210402080752.1">.. _`docutils`: https://docutils.sourceforge.net
.. _`LaTeX`:    https://www.latex-project.org/
.. _`Sphinx`:   https://sphinx-doc.org/
.. _`reStructuredText`: https://docutils.sourceforge.net/rst.html
.. _`4478`: https://github.com/leo-editor/leo-editor/issues/4478

This section explains how to use **user filters** to alter the output of the ``rst3`` command. See Leo info issue `4478`_ and ``leo/plugins/example_rst_filter.py`` and for examples.

**Background**

The ``rst3`` command converts ``@rst`` trees containing `reStructuredText`_ (rST)
or `Sphinx`_ markup to an **intermediate string**. Depending on user
options, ``rst3`` will:

- write the intermediate string to an **intermediate file**.
- send the intermediate string to `docutils`_ for conversion to HTML, PDF,
  `LaTeX`_, etc.

**User filters**

Plugins or scripts may define two functions: a **headline filter** and a **body filter**. The signature of both filters is ``filter-name (c, p)`` where c and p are defined as usual.

- ``rst3`` calls the body filter for all nodes except descendants of ``@rst-ignore`` or ``@rst-ignore-tree`` nodes.

- ``rst3`` calls the headline filter for all nodes except ``@rst-no-head nodes`` or descendants of ``@rst-ignore`` or ``@rst-ignore-tree`` nodes.

- plugins or scripts register filters as follows:

.. code-block:: python

    c.rstCommands.register_body_filter(body_filter)
    c.rstCommands.register_headline_filter(headline_filter)

**Using context in filters**

Filters are not limited to using ``p.b``, ``p.h``, ``p.u``, or ``p.gnx``. Filters may access:

- Any ancestor or descendant of position p.
- Any data accessible from c, that is, *all* the data in the outline, including cached data!

Filters can define their own conventions, including:

- Special-format comments embedded in ``p.b``,
- Special-purpose headlines.

For example:

.. code-block:: python

    def in_context(p: Position, context: str) -&gt; bool:
        return any(z.h == context for z in p.parents())

    def body_filter(c, p):
        return (
            do_faq(p) if if in_context(p, 'FAQ')
            else do_ref(p) if in_context(p, 'Ref')
            else ''
        )

    def headline_filter(c, p):
        return (
            f"FAQ: {p.h}" if in_context(p, 'FAQ')
            else f"Ref: {p.h}" if in_context(p, 'Ref')
            else ''
        )

**Simulating half clones**

Filters may simulate half clones by ignoring children of clones in some contexts and processing those same children in other contexts. That's all there is to it!
</t>
<t tx="ekr.20210405100137.1058">https://github.com/leo-editor/leo-editor/issues/1806</t>
<t tx="ekr.20210405100137.1061">https://github.com/leo-editor/leo-editor/issues/1808</t>
<t tx="ekr.20210405100137.1062">https://github.com/leo-editor/leo-editor/issues/1813
</t>
<t tx="ekr.20210405100137.1340">https://github.com/leo-editor/leo-editor/issues/1831

https://github.com/leo-editor/leo-editor/issues/2049
</t>
<t tx="ekr.20210405100137.1345">https://github.com/leo-editor/leo-editor/issues/1832</t>
<t tx="ekr.20210405100137.1384">https://github.com/leo-editor/leo-editor/issues/1840</t>
<t tx="ekr.20210405100137.1396">https://github.com/leo-editor/leo-editor/issues/1841</t>
<t tx="ekr.20210405100137.1743">https://github.com/leo-editor/leo-editor/issues/1867</t>
<t tx="ekr.20210405100137.1798">https://github.com/leo-editor/leo-editor/issues/1849
</t>
<t tx="ekr.20210405100137.2">https://github.com/leo-editor/leo-editor/issues/442</t>
<t tx="ekr.20210405100137.456">https://github.com/leo-editor/leo-editor/issues/1240</t>
<t tx="ekr.20210405100137.468">https://github.com/leo-editor/leo-editor/issues/1413

PR: https://github.com/leo-editor/leo-editor/issues/1759
</t>
<t tx="ekr.20210405100137.563">https://github.com/leo-editor/leo-editor/issues/1721</t>
<t tx="ekr.20210405100137.787">https://github.com/leo-editor/leo-editor/issues/1754

w.see works for the first time ever!</t>
<t tx="ekr.20210405100137.912">https://github.com/leo-editor/leo-editor/issues/1768</t>
<t tx="ekr.20210405100137.915">https://github.com/leo-editor/leo-editor/issues/1772

Added gdc.diff_pull_request.</t>
<t tx="ekr.20210405100137.923">https://github.com/leo-editor/leo-editor/issues/1780</t>
<t tx="ekr.20210405100137.931">https://github.com/leo-editor/leo-editor/issues/1781</t>
<t tx="ekr.20210405100137.946">https://github.com/leo-editor/leo-editor/issues/1792</t>
<t tx="ekr.20210405100137.955">https://github.com/leo-editor/leo-editor/issues/1798

Note: Leo can not recognize @path directives in the body text of @file nodes!</t>
<t tx="ekr.20210405104357.1">- Support for LeoInteg: "Leo in vs-code".
  - Add leoserver.py, stand-alone server for Leo.
  - Support .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.
</t>
<t tx="ekr.20210405104422.1">Leo https://leo-editor.github.io/leo-editor/ 6.4 is now available on
[GitHub](https://github.com/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](https://github.com/boltex/leointeg#-leo-for-vs-code): "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**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@language md
</t>
<t tx="ekr.20210405104614.1">For a list of all the bugs fixed in Leo 6.4 see:
https://github.com/leo-editor/leo-editor/issues?q=milestone%3A6.4+label%3Abug+</t>
<t tx="ekr.20210405104619.1">For a list of all changes to codebase see:
https://github.com/leo-editor/leo-editor/issues?q=milestone%3A6.4+label%3Acode+

Only the highlights are shown below.</t>
<t tx="ekr.20210405104753.1">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.
</t>
<t tx="ekr.20210405104825.1">Add @bool allow-text-zoom = True
https://github.com/leo-editor/leo-editor/issues/1923

Add support for --trace-speed.
https://github.com/leo-editor/leo-editor/issues/1936

Add settings for Leo's mypy command:
https://github.com/leo-editor/leo-editor/issues/1831
https://github.com/leo-editor/leo-editor/issues/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</t>
<t tx="ekr.20210405110053.1"></t>
<t tx="ekr.20210405110145.1"></t>
<t tx="ekr.20210528082736.11">https://github.com/leo-editor/leo-editor/issues/1955</t>
<t tx="ekr.20210528083337.1">https://github.com/leo-editor/leo-editor/issues/1846
</t>
<t tx="ekr.20210528083510.1">https://github.com/leo-editor/leo-editor/issues/1672

Leo's Qt docks caused great confusion. Leo is better off without them.
</t>
<t tx="ekr.20210606081234.1">https://github.com/leo-editor/leo-editor/issues/1715

Add c.general_script_helper.</t>
<t tx="ekr.20210607135729.1">The execute-general-script command invokes an external language processor on an **script file** as follows:

- If c.p is any kind of @&lt;file&gt; node, the script file is the corresponding external file.
  Otherwise, the script file is a temp file.

- The ``@data exec-script-commands`` setting tells how to invoke the appropriate language processor.
  See the setting for more details.

- The ``@data exec-script-patterns`` settings describes error messages so that Leo can create
  clickable links to errors.  See the setting for more details.

- This command is a thin wrapper around the c.general_script_helper method.
  Scripts can call this method directly if desired.
</t>
<t tx="ekr.20210710040014.2">https://github.com/leo-editor/leo-editor/issues/1944
PR: https://github.com/leo-editor/leo-editor/pull/1948</t>
<t tx="ekr.20210710040931.1">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.</t>
<t tx="ekr.20210710163244.2">https://github.com/leo-editor/leo-editor/issues/2023</t>
<t tx="ekr.20210717092635.918">https://github.com/leo-editor/leo-editor/issues/2005</t>
<t tx="ekr.20210718082823.2">https://github.com/leo-editor/leo-editor/issues/2081</t>
<t tx="ekr.20210802163908.31">https://github.com/leo-editor/leo-editor/issues/2103</t>
<t tx="ekr.20210823181157.1">https://github.com/leo-editor/leo-editor/issues/2005
https://github.com/leo-editor/leo-editor/issues/1973</t>
<t tx="ekr.20210824081721.1"></t>
<t tx="ekr.20210824081815.1">######################
Leo's WebSocket Server
######################

leo/core/leoserver.py is websocket server providing Leo's resources to
clients. The server offers single or multiple concurrent websockets.

*WebSocket is a computer communications protocol, providing full-duplex
communication channels over a single TCP connection.*

Clients can be written in any language:
- leo.core.leoclient is an example client written in python.
- leoInteg (https://github.com/boltex/leointeg) is written in typescript.

At startup, the server creates a single instance of Leo's bridge. (core.leoBridge)
Clients can open (or create) Leo outlines in the bridge. Thereafter,
clients can query or change the contents of the outlines.

Clients encode requests as JSON strings and receive results from the server
as JSON strings.

Run the leoserver.py script with the "--help" command line parameter to learn
more about the server's capabilities.

.. contents:: Contents
    :depth: 2
    :local:</t>
<t tx="ekr.20210824083951.1">JSON requests (from the client to the server) must have three keys:

"id": A string containing a positive integer.

"action": A string denoting the kind of request. There are three forms:

1. Actions prefixed with '!' must be the name of public method of the
   LeoServer class in leoserver.py.
2. Actions prefixed with '-' must be the name of a Leo command.
3. Otherwise, the action must be name of a method in one of Leo's
   subcommander classes.

"param": A dict containing additional information. The param key often
contains "ap", "text" and "keep" keys.

The server's **_ap_to_p** and **_p_to_ap** methods convert Leo positions to
**archived positions** (strings) that can be converted to JSON.

The "action" and "param" members mimic the "function name" and "parameters" or
a procedure call. And is in fact implemented as a remote procedure call.

The LeoServer._do_message method checks and handles incoming requests in a
one by one, blocking synchronous manner.
</t>
<t tx="ekr.20210824085857.1">JSON responses (from the server to the client) always have the following keys
unless the request was a 'getter' command:

* "id": The incoming request id this JSON message is responding to.
* "commander": A dict describing c, the open commander.
* "node":  None, or an archived position describing c.p.

Optional keys:

* "package": A dict containing extra data.
* "p": "An archived position".

If the request was a 'getter' command, the JSON response will only contain the
specific structure that was requested.
</t>
<t tx="ekr.20210825021830.1">The following sections describe the communication protocol, that is, the
format of requests sent from the client and responses sent from the server.
</t>
<t tx="ekr.20210825021904.1">Requests from the client to the server may reference:

* Public methods of the LeoServer class.
* The names of Leo commands.
* Methods of Leo's subcommander classes.

The public methods of the LeoServer class can only be changed in an upward
compatible manner. If necessary, new public methods can be added at any
time.

Leo is a programming environment in which user scripts can access all of
Leo's source code. For this reason, the names of methods in Leo's core
change rarely. Similarly, clients can usually assume that the names of Leo
commands won't change.
</t>
<t tx="ekr.20210921102613.1">Leo https://leo-editor.github.io/leo-editor/ 6.5 is now available on
[GitHub](https://github.com/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**

- [6.5 issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.5)
- [6.5 pull requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.5)
- [6.5 bug fixes](https://github.com/leo-editor/leo-editor/issues?q=label%3Abug+milestone%3A6.5+)
- [6.5 enhancements](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.5+label%3Aenhancement+)
- [6.5 code-level improvements](https://github.com/leo-editor/leo-editor/issues?q=milestone%3A6.5+label%3Acode+)

**General Links**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language md
</t>
<t tx="ekr.20210921102613.13">#2256: view-recent-commands
https://github.com/leo-editor/leo-editor/issues/2256

#2267: python-to-typescript
https://github.com/leo-editor/leo-editor/issues/2267
</t>
<t tx="ekr.20210921102613.20">#1766: Use traditional unit tests
https://github.com/leo-editor/leo-editor/issues/1766
PR: https://github.com/leo-editor/leo-editor/pull/2159

#2194: black-compatible sentinels
https://github.com/leo-editor/leo-editor/issues/2194

#2219: c.findCommands.interactive_search_helper
https://github.com/leo-editor/leo-editor/issues/2219
</t>
<t tx="ekr.20210921102613.40">@data python-to-typescript-types

A list of key/value pairs. Keys are argument names (as used in Leo); values
are typescript type names.</t>
<t tx="ekr.20210921103230.1">- 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.</t>
<t tx="ekr.20211014165743.1">- leoTest2.py create temporary Leo applications and outlines for unit tests.
- Remove ``@test``, ``@suite``, unitTest.leo and leoTest.py.</t>
<t tx="ekr.20211105051031.1">Leo https://leo-editor.github.io/leo-editor/ 6.6 final is now available on
[GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [6.6 issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.6)
- [6.6 pull requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.6)
- [6.6 bug fixes](https://github.com/leo-editor/leo-editor/issues?q=label%3Abug+milestone%3A6.6+)
- [6.6 enhancements](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.6+label%3Aenhancement+)
- [6.6 code-level improvements](https://github.com/leo-editor/leo-editor/issues?q=milestone%3A6.6+label%3Acode+)

**General Links**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language md
</t>
<t tx="ekr.20211105051309.1">- Replaced @raw and @end_raw with @section-delims.
- Leo recognizes section references only when they appear on an otherwise blank line.
- Many improvements to 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.</t>
<t tx="ekr.20220129083216.1">Plugins may define filters that alter the output of any node. When writing the headline of a node p, the rst3 command calls the **body filter** to change the p.b. Similarly, the rst3 command calls the **headline filter** to change p.h. By default, these filters do nothing. That is, they return p.b and p.b respectively. However, the signatures of these filters are:

.. code-block:: python

    def headline_filter(c, p)
    def body_filter(c, p)

so these filters have full access to all nodes of the entire outline. As a result, these filters can return arbitrary text that comes from anywhere in the outline.

The ``leo/plugins/example_rst_filter.py`` shows how to define and register these filters.</t>
<t tx="ekr.20220129091501.1">Leo's status area shows the path from the root node to the selected node. We call such paths **UNLs** (Uniform Node Locators).  Given a UNL, ``g.handleUnl(unl, c)`` will select the referenced node.  For example:

.. code-block:: python

    g.handleUnl('LeoDocs.leo#Use g.handleUnl to select nodes', c)

will select this node in ``LeoDocs.leo``.
</t>
<t tx="ekr.20220401072939.1">Leo https://leo-editor.github.io/leo-editor/ 6.6.1 is now available on
[GitHub](https://github.com/leo-editor/leo-editor/releases) 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 @&lt;file&gt; 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**

- [6.6.1 issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.6.1)
- [6.6.1 pull requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.6.1)
- [6.6.1 bug fixes](https://github.com/leo-editor/leo-editor/issues?q=label%3Abug+milestone%3A6.6.1+)
- [6.6.1 enhancements](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.6.1+label%3Aenhancement+)
- [6.6.1 code-level improvements](https://github.com/leo-editor/leo-editor/issues?q=milestone%3A6.6.1+label%3Acode+)

**General Links**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language md
</t>
<t tx="ekr.20220420153633.1">There have been one or two recent threads on how different people discovered or use Leo.  But I haven't really seen anything that gives the flavor of how very many ways Leo can be used, apart from outright programming that is.  So I thought I'd try to lay out how I typically use it.  It's true that many of these items are programming-related, but many are not.  Some of them do require the help of one or another script, which need to be written if they don't already exist.  But one often can borrow someone else's script.

Here are some of the main ways I'm using Leo these days.

1. Managing a software project.  Leo makes managing all the files and documentation way easier than anything else I know.

2. Simplifying programming itself.  Leo has many strengths that make the actual job of programming much easier, especially for python but also for other languages..

3. Learning how to make bits of code work.  It often takes a lot of guessing and experimenting to turn what you read into correctly working code.  Leo makes this way easier than anything else I know.  And often you can avoid littering  up your file system with small experimental files as you work out your problems.

4. Writing in structured languages like RestructuredText, Markdown, and Asciidoc.  The viewrendered3 plugin displays a fully rendered version of your document, removing an element of guesswork.

5. Writing technical documentation using Sphinx.  Sphinx can produce beautifully readable documents, both for HTML and pdf.  Leo's outlines and rst3 command make it much easier and faster to use Sphinx.  It's gotten hard for me to even imagine producing this kind of documentation without Leo.

6. Producing drafts of documents in formats like .doc files or Libreoffice Writer format.  You need the help of pandoc for this, and a bit of glue script.  I don't know of any way to round-trip these documents, so once your draft gets into the word processor, you can't get it back into Leo in a usable form. Even so, writing the first draft in Leo is a big win.

7. Jupyiter notebook-style mixing of text, code, and output.  The viewrendered3 plugin can do similar things, although more Python-oriented and being less practical for rather long documents.

8. Keeping time records,  with notes, for consulting projects.

9. I have a bookmark manager in Leo - I mean, browser bookmarks - that makes finding the promising bookmarks , adding one to the collection, and organizing them much more practical than anything else I have tried.  It does use a bit of "real" programming, but now that it's working, a user doesn't need to write more.

10. I have adapted the "zettel-kasten" system for storing research notes and inter-linking them to a collection of family history (genealogical) data.  With the help of some scripts that are easy to use, Leo becomes a family history database.  More scripts can produce several family tree-like charts (with the help of Graphviz) that display within Leo and can show a line of descent from a candidate ancestor to a chosen person.  I'm really enjoying using this system.

11. Producing mind maps.  I'm very fond of mind maps, and I have contributed a set of scripts that can turn Leo trees, or any indented list, into a mind map.  It's a bit primitive so far, but it does the basics that I want.  The scripts are in the Leo repo.

12. On-the-spot plotting of 2D numerical data.  If you can get the data into the clipboard, you can plot it using the viewrendered3 plugin with minimal fuss.

13. Literate programming - if you want to go full out with literate programming, there are several ways to do this with Leo.

I'm sure I'm not thinking of several more things here, but you get the idea.  The range of activities that Leo can support is amazingly wide.  That's why it's hard to tell someone what Leo "is".  It's like the elephant and the blind men - none of them can see the whole of the elephant.

To me, the base of Leo's versatility is the extremely good and convenient handling of its outline tree, the ability to subdivide projects into convenient pieces, combined with the ability for anyone to easily extend Leo's core capabilities with scripts and user commands of all kinds.

Phenomenal!</t>
<t tx="ekr.20220427143133.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 @&lt;file&gt; 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.</t>
<t tx="ekr.20220523084825.1">Leo https://leo-editor.github.io/leo-editor/ 6.6.2 is now available on
[GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [6.6.2 issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.6.2)
- [6.6.2 pull requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.6.2)
- [6.6.2 bug fixes](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.6.2+label%3Abug+is%3Aclosed)
- [6.6.2 enhancements](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.6.2+label%3Aenhancement+)
- [6.6.2 code-level improvements](https://github.com/leo-editor/leo-editor/issues?q=milestone%3A6.6.2+label%3Acode+)

**General Links**

- Leo's home page: https://leo-editor.github.io/leo-editor/
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language md
</t>
<t tx="ekr.20220523145755.1">- 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.</t>
<t tx="ekr.20220704113115.1">Leo https://leo-editor.github.io/leo-editor/ 6.6.3 is now available on
[GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- 6.6.3 issues: https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.6.3+
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language md
</t>
<t tx="ekr.20220719064316.1">- 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.</t>
<t tx="ekr.20220831093321.1">- Enhance leoserver.py to support LeoInteg and LeoJS.
- Simplify all of Leo's importers.
- Importers no longer generate underindented escape strings.
- Begin annotating Leo's core files.
- The usual assortment of minor bug fixes.</t>
<t tx="ekr.20220912154542.1">- Leo now requires Python 3.9 or later.
- Enhance leoserver.py to support LeoInteg and LeoJS.
- Importers no longer generate underindented escape strings.
- Delete all of Leo's cover- and test- commands.
- Allow unit tests to run with the Qt gui.
- Several mass code updates:
   - Annotate Leo's core files and important plugins.
   - Simplify all of Leo's importers.
   - Speed Leo's redraw code by rewriting Leo's icon drawing logic.
   - Retire Tk indices, except in unit tests.
</t>
<t tx="ekr.20221018092737.1">Leo https://leo-editor.github.io/leo-editor/ 6.7.1 is now available on
[GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [6.7.1 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.7.1+)
- [6.7.1 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.7.1)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language md
</t>
<t tx="ekr.20221018092915.1">- Several enhancements to leoserver.py.
- Add support for ocaml syntax coloring.
- Improve markdown importer.
- @bool plain-key-outline-search = False by default.
- Several minor code cleanups.
- Delete cascade-windows, flush-lines, keep-lines and open-offline-tutorial commands.</t>
<t tx="ekr.20221108064344.1"></t>
<t tx="ekr.20221108064449.1"></t>
<t tx="ekr.20230105123159.1">The **check-nodes** command finds **dubious** nodes, that is, nodes that:

- contain multiple defs.
- start with leading blank lines.
- are non-organizer nodes containing no body text.

This command is specially useful when using ``@clean`` nodes in a collaborative
environment. Leo's ``@clean`` update algorithm will update ``@clean`` nodes when
others have added, deleted or moved code, but the update algorithm won't
assign changed code to the optimal nodes. This script highlights nodes that
needed attention.

**Settings**: You can customize the behavior of this command with ``@data`` nodes:

- ``@data check-nodes-ok-patterns``

  The body of the ``@data`` node contains a list of regexes (strings), one per
  line. This command compiles each regex as if it were a raw string.
  Headlines matching any of these compiled regexes are not considered
  dubious. The defaults ignore unit tests::

    .*test_
    .*Test

- ``@data check-nodes-ok-prefixes``

  The body of the ``@data`` node contains a list of strings, one per line.
  Headlines starting with any of these strings are not considered dubious.
  The defaults ignore top-level @&lt;file&gt; nodes and marker nodes::

    @
    **
    ==
    --

- ``@data check-nodes-suppressions``

  The body of the ``@data`` node contains a list of strings, one per line.
  Headlines that match these suppressions *exactly* are not considered
  dubious. Default: None.</t>
<t tx="ekr.20230110152131.1">Leo https://leo-editor.github.io/leo-editor/ 6.7.2 is now available on
[GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- PR #3019: Leo's website has moved to GitHub Pages: https://leo-editor.github.io/leo-editor/

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

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.7.2 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.7.2+)
- [6.7.2 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.7.2)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language md
</t>
<t tx="ekr.20230110152214.1"></t>
<t tx="ekr.20230110152240.1"></t>
<t tx="ekr.20230110152344.1">"""
Report broken links in all .html files leo-editor/docs.

Adapted from https://brianli.com/2021/06/how-to-find-broken-links-with-python/

pip install beautifulsoup4
https://www.crummy.com/software/BeautifulSoup/
"""
@language python
g.cls()
import glob
import os
import requests
from bs4 import BeautifulSoup
from concurrent.futures import ThreadPoolExecutor

root_domain = 'https://leo-editor.github.io/leo-editor/'

# Define helpers
@others

if 1:  # Best test.
    links = find_docs_links()
elif 1:
    links = find_outline_links()
else:
    url = f"{root_domain}/index.html"
    links = find_web_links(url)
# Report the found links.
links = list(set(links))
# Report all broken links.
n = len(links)
# g.printObj(links, tag=f"{len(links)} links")
g.es_print(f"Testing {n} link{g.plural(n)}")
broken_links = find_broken_links(links)
n1, n2 = len(links), len(broken_links)
g.es_print(f"Found {n1} link{g.plural(n1)}, {n2} broken")
</t>
<t tx="ekr.20230110152349.1"></t>
<t tx="ekr.20230110153129.1">def find_web_links(url):
    """Return a list of all links with the root domain."""
    # Make request to URL.        
    data = requests.get(url).text

    # Parse HTML from request.
    soup = BeautifulSoup(data, features="html.parser")

    return sorted(list(set([
        link.get("href") for link in soup.find_all("a")
    ])))
</t>
<t tx="ekr.20230110153304.1">def find_outline_links():
    """Find all links in this outline."""
    links = set()
    for p in c.all_unique_positions():
        # Parse HTML in the body.
        soup = BeautifulSoup(p.b, features="html.parser")
        # Create a list containing all links with the root domain.
        for link in soup.find_all("a"):
            links.add(link.get("href"))
    return sorted(list(links))
</t>
<t tx="ekr.20230110153501.1">def find_broken_links(links):

    broken_links = []
    suppress = (
        '&lt;|URL|&gt;',
    )

    def validate_url(url):
        if url in suppress:
            g.trace(f"Skip: {url}")
            return
        r = requests.head(url)
        if r.status_code == 404:
            broken_links.append(url)

    # Loop through links checking for 404 responses, and append to list.
    broken_links = []
    with ThreadPoolExecutor(max_workers=8) as executor:
        executor.map(validate_url, links)

    for link in broken_links:
        g.es_print(f"Bad link: {link}")
    return broken_links
</t>
<t tx="ekr.20230111160833.1">.. _`PR #3019`: https://github.com/leo-editor/leo-editor/pull/3019

Leo's website has moved to Github Pages: https://leo-editor.github.io/leo-editor/

- `PR #3019`_: Host Leo's website using GitHub pages.

Commands:

.. _`PR #3031`: https://github.com/leo-editor/leo-editor/pull/3031
.. _`PR #3056`: https://github.com/leo-editor/leo-editor/pull/3056
.. _`PR #3140`: https://github.com/leo-editor/leo-editor/pull/3140
.. _`PR #3166`: https://github.com/leo-editor/leo-editor/pull/3166

- `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`: https://github.com/leo-editor/leo-editor/pull/2979
.. _`PR #2983`: https://github.com/leo-editor/leo-editor/pull/2983
.. _`PR #3038`: https://github.com/leo-editor/leo-editor/pull/3038
.. _`PR #3053`: https://github.com/leo-editor/leo-editor/pull/3053
.. _`PR #3132`: https://github.com/leo-editor/leo-editor/pull/3132

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

Bugs

.. _`PR #2962`: https://github.com/leo-editor/leo-editor/pull/2962
.. _`All noteworthy pull requests`: https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.7.2+label%3ANoteworthy
.. _`All noteworthy issues`: https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.7.2+label%3ANoteworthy+

- `PR #2962`_: Leo's git-diff command can clear top-level cloned node.
- `All noteworthy pull requests`_.
- `All noteworthy issues`_.</t>
<t tx="ekr.20230111163935.1">c.backup_helper(sub_dir='leoDocs')
</t>
<t tx="ekr.20230111171223.1">def find_docs_links():
    """Find all links in all .html files in the leo-editor/docs directory."""
    docs_path = g.os_path_finalize_join(g.app.loadDir,'..','..','docs')
    if not os.path.exists(docs_path):
        g.es_print(f"Not found: {docs_path!r}")
        return []
    files = glob.glob(f"{docs_path}{os.sep}*.html")
    if not files:
        g.es_print(f"No .html files in {docs_path!r}")
        return []
    links = set()
    for filename in files:
        with open(filename,'rb') as f:
            contents = g.toUnicode(f.read())
        soup = BeautifulSoup(contents, features="html.parser")
        for link in soup.find_all("a"):
            ref = link.get("href")
            if not ref.startswith(('mailto:',)):
                links.add(ref)
    return sorted(list(links))
</t>
<t tx="ekr.20230119101059.1">From the movie, My Cousin Vinny::

    Mona Lisa Vito: So what's your problem?
    Vinny Gambini: My problem is, I wanted to win my first case
    without any help from anybody.
    Mona Lisa: Well, I guess that plan's moot.
    Vinny : Yeah.
    Mona Lisa: You know, this could be a sign of things to come.
    You win all your cases, but with somebody else's help, right?
    You win case after case, and then afterwards you have to go up
    to somebody and you have to say, "thank you."
    [pause]
    Oh my God, what a fucking nightmare!
</t>
<t tx="ekr.20230119101129.1">Leo owes much of its visual design to MORE, possibly the most elegant computer program ever written. |br|
More inspired Leo's cloned nodes.
</t>
<t tx="ekr.20230119101215.1">Leo's very important people:

- David Brock wrote TSyntaxMemo, used in early versions of Leo.
- Terry Brown wrote important plugins, including Leo's user-modifiable panes.
- e inspired @button nodes, a brilliant idea.
- The late Bob Fitzwater kept me focused on design. |br|
  Oh, how I wish he could see today's Leo.
- Jonathan M. Gilligan showed how to put the Leo icon in Leo's windows.
- The Jupyter development team taught me how to support pygments colorizing.
- Brian Harry contributed numerous plugins, including a prototype for Leo's minibuffer, and wrote jyLeo: Leo in Jython.
- Almar Klein wrote pyzo, yoton and flexx, the basis of LeoWapp (--gui=browser).
- Donald Knuth invented the CWEB language and literate programming.
- Félix Malboeuf wrote LeoInteg, LeoJS, LeoWeb, leoserver.py and leoclient.py.
- Виталије Милошевић, (Vitalije Milosevic) made vital code-level contributions.
- The late Bernhard Mulder invented the @shadow algorithm, the foundation of @clean. |br|
  Bernhard also inspired Leo's generators and Position class.
- Tsuchi Noko created transparent icons.
- Neal Norwitz wrote PyChecker.
- The late Eric Norman was my friend and mentor.
- Joe Orr created LeoVue and XSLT stylesheets for Leo.
- John K. Ousterhout created tcl/Tk, used in early versions of Leo.
- Marc-Antoine Parent urged me to use XML for Leo's file format and helped improve it.
- Thomas Passin is one of Leo's core devs. He revised and simplified Leo's layout code.
- Paul Paterson created the plugin architecture, helped with spell checking and contributed many plugins.
- François Pinard wrote pymacs, the foundation of Leo's emacs bridge.
- Viktor Ransmayr has been a tireless tester. He has saved my blushes many times.
- Norman Ramsey created noweb and gave permission to quote from the noweb web documentation.
- Edward K. Ream is Leo's project leader and chief programmer.
- Rich Ries has contributed a huge number of suggestions.
- Guido van Rossum created Python.
- Steven P. Schaefer pointed out security problems.
- Gil Shwartz helped with unicode support.
- Phil Straus has been a great friend and constant support.
- Kent Tenney contributed key insights about VNodes.
- Ville M. Vainio contributed to the one-node world, the IPython bridge and several plugins.
- Paul S. Wilson greatly improved Leo's Wikipedia entry and helped license Leo's logo.
- Dave Winer created MORE, the foundation of Leo's visual design.
- Dan Winkler helped support Leo on the Mac.

Special thanks to my family. My brother, David Speed Ream, tested Leo and made many useful suggestions. Rebecca, James and Linda make it all worthwhile. During a conversation with Rebecca I realized that MORE could be used as a prototype for Leo. That was a crucial first step.
</t>
<t tx="ekr.20230119101405.1">The following people reported bugs, answered questions, and made suggestions for improving Leo:

Alex Abacus, Shakeeb Alireze, Steve Allen, Bruce Arnold, Chris Barker, Dennis Benzinger, David Boddie, Jason Breti, Eric Brown, Terry Brown, Darius Clarke, Martin Clifford, Jason Cunliffe, Josef Dalcolmo, Gil Dev, Bill Drissel, Wenshan Du, Allen Edwards, Chris Elliot, Dethe Elza, Reinhard Engle, Mark Engleberg, Roger Erens, Stephen Ferg, Tom Fetherston, Tomaz Ficko, Niklas Frykholm, Fred Gansevles, Jonathan M. Gilligan, Zak Greant, Thomas Guettler, Romain Guy, Dave Hein, Tiago Castro Henriques, Gary Herron, Steve Holden, Klass Holwerda, Matthias Huening, Robert Hustead, John Jacob, Paul Jaros, Christopher P. Jobling, Eric S. Johansson, Garold Johnson, James Kerwin, Nicola Larosa, David LeBlanc, Chris Liechti, Steve Litt, Martin v. Löwis, Robert Low, Fredrik Lundh, Michael Manti, Alex Martelli, Marcus A. Martin, Gidion May, David McNab, Frank Merenda, Martin Montcrieffe, Will Munslow, Lewis Neal, Chad Netzer, Derick van Niekerk, Jeff Nowland, Naud Olivier, Joe Orr, Marc-Antoine Parent, Paul Paterson, Sean Shaleh Perry, Tim Peters, David Priest, Gary Poster, Scott Powell, Bruce Rafnel, Walter H. Rauser, Olivier Ravard, David Speed Ream, Rich Ries, Aharon Robbins, Guido van Rossum, David Rowe, Davide Salomoni, Steven Schaefer,Johannes Schöön, Wolfram Schwenzer, Casey Wong Kam Shun, Gil Shwartz, Jim Sizelove, Paul Snively, Jurjen Stellingwerff, Phil Straus, David Szent-Györgyi, Kent Tenney, Jeffrey Thompson, Gabriel Valiente, Jim Vickroy, Tony Vignaux, Tom van Vleck, Kevin Walzer, Ying-Chao Wang, Cliff Wells, Dan Wharton, John Wiegley, Wim Wijnders, Dan Winkler, Vadim Zeitlin.

This list is out of date!
</t>
<t tx="ekr.20230119101501.1"></t>
<t tx="ekr.20230119134825.1">.. _`Tribal Lion`: https://www.dreamstime.com/royalty-free-stock-photos-tribal-lion-image3490018
.. _`dreamstime.com`: https://www.dreamstime.com

Leo's Logo is the `Tribal Lion`_ image licensed from `dreamstime.com`_.</t>
<t tx="ekr.20230120090521.1"></t>
<t tx="ekr.20230121052337.1"></t>
<t tx="ekr.20230121054117.1">################
Clones and views
################

.. toctree::
    :maxdepth: 1

    About clones                &lt;slide-001&gt;
    Clones are the same node    &lt;slide-002&gt;
    Changing cloned headlines   &lt;slide-003&gt;
    A new node                  &lt;slide-004&gt;
    Adding a child node         &lt;slide-005&gt;
    Creating a second child     &lt;slide-006&gt;
    Tracking changed nodes      &lt;slide-007&gt;
    Tracking changed files      &lt;slide-008&gt;
    The ultimate filing cabinet &lt;slide-009&gt;
    Views are sets of nodes     &lt;slide-010&gt;
    Views focus attention       &lt;slide-011&gt;
    Views concentrate data      &lt;slide-012&gt;
</t>
<t tx="ekr.20230121054859.1">####################
Using external files
####################

.. toctree::
    :maxdepth: 1

    About external files                &lt;slide-001&gt;
    Loading and saving files            &lt;slide-002&gt;
    Sentinel lines                      &lt;slide-003&gt;
    External files without sentinels    &lt;slide-004&gt;
    Using @file trees                   &lt;slide-005&gt;
    Top-level markup                    &lt;slide-006&gt;
    Section references                  &lt;slide-007&gt;
    Section definitions                 &lt;slide-008&gt;
    The @others directive               &lt;slide-009&gt;
    References &amp; expansions             &lt;slide-010&gt;
    Indentation                         &lt;slide-011&gt;
    More about indentation              &lt;slide-012&gt;
    More about expansions               &lt;slide-013&gt;
    Orphan nodes                        &lt;slide-014&gt;
    A common pattern                    &lt;slide-015&gt;
    SpamClass                           &lt;slide-016&gt;
    EggsClass                           &lt;slide-017&gt;
    Alternatives to @file               &lt;slide-019&gt;
    Using @auto nodes                   &lt;slide-020&gt;
    @auto example                       &lt;slide-021&gt;
    Using @edit nodes                   &lt;slide-022&gt;

..  Using @others to group code         &lt;slide-018&gt;
</t>
<t tx="ekr.20230121054950.1">############
Leo's Basics
############

This is a step-by-step introduction showing you how to use Leo outlines.

.. no slide 1
.. toctree::
    :maxdepth: 1

    The workbook file               &lt;slide-002&gt;
    Editing headlines               &lt;slide-003&gt;
    Typing in a headline            &lt;slide-004&gt;
    The icon box                    &lt;slide-005&gt;
    Switching focus                 &lt;slide-006&gt;
    Saving your work                &lt;slide-007&gt;
    Inserting new nodes             &lt;slide-008&gt;
    &lt;Return&gt; ends headline editing  &lt;slide-009&gt;
    The blue square                 &lt;slide-010&gt;
    Move a node right               &lt;slide-011&gt;
    Move a node left                &lt;slide-012&gt;
    Undo and redo                   &lt;slide-013&gt;
    Add a to-do node                &lt;slide-014&gt;
    Add a to-do item                &lt;slide-015&gt;
    Move a node up                  &lt;slide-016&gt;
    Hide child nodes                &lt;slide-017&gt;
    Changing focus                  &lt;slide-018&gt;
    Left-Arrow: contract a node     &lt;slide-019&gt;
    Right-Arrow: expand a node      &lt;slide-020&gt;
    Summary: arrow keys             &lt;slide-021&gt;
    Shift-Ctrl-C: copy an outline   &lt;slide-022&gt;
    Shift-Ctrl-V: paste an outline  &lt;slide-023&gt;
    Copy works on entire trees      &lt;slide-024&gt;
    Summary                         &lt;slide-025&gt;
</t>
<t tx="ekr.20230121055005.1">#############
Scripting Leo
#############

.. toctree::
    :maxdepth: 1

    Introduction to scripting       &lt;slide-001&gt;
    c, g and p                      &lt;slide-002&gt;
    Official ivars                  &lt;slide-003&gt;
    Hello world                     &lt;slide-004&gt;
    p.h and p.b                     &lt;slide-005&gt;
    Iterators                       &lt;slide-006&gt;
    Using iterators                 &lt;slide-007&gt;
    Building scripts from outlines  &lt;slide-008&gt;
    g.openWithFileName              &lt;slide-009&gt;
    Debugging scripts               &lt;slide-010&gt;
    Further reading                 &lt;slide-011&gt;
</t>
<t tx="ekr.20230121055019.1">####################
Using the minibuffer
####################

.. toctree::
    :maxdepth: 1

    Introduction        &lt;slide-001&gt;
    Tab completion      &lt;slide-002&gt;
    Example             &lt;slide-003&gt;
    Example, continued  &lt;slide-004&gt;
    Example, concluded  &lt;slide-005&gt;
    Shortcuts           &lt;slide-006&gt;
    Search arguments    &lt;slide-007&gt;
    Search string       &lt;slide-008&gt;
    Replace string      &lt;slide-009&gt;
    Doing the find      &lt;slide-010&gt;
    Doing the replace   &lt;slide-011&gt;

</t>
<t tx="ekr.20230121060317.1"></t>
<t tx="ekr.20230121060325.1">############
About clones
############

Clones are one of Leo’s most unusual and most useful features.

A clone is a node that appears in more than one place in a Leo outline.

Here, we have cloned node A by selecting A and doing Ctrl=` (clone-node)

Clones are marked with a small red clone arrow* in the icon box. Deleting
the penultimate clone removes the red arrow from the node.

.. image:: _images/slide-001.png
</t>
<t tx="ekr.20230121060347.1">########################
Clones are the same node
########################

Changing the headline or body text of a clone changes the headline or body
text of all other clones of that node. Furthermore, changing any
descendants of a clone, including inserting, deleting or moving nodes,
results in the same changes being made to all other clones.

In fact, all clones of a node are actually the exactly the same node, so
any change to one clone inevitably affects all other clones.

.. no image for this slide.</t>
<t tx="ekr.20230121061300.1"></t>
<t tx="ekr.20230121061309.1"></t>
<t tx="ekr.20230121061335.1"></t>
<t tx="ekr.20230121061433.1"></t>
<t tx="ekr.20230121110340.1" _mod_time="4741d993336a2ad5e02e">@language batch
echo off
echo off
cd C:\Repos\leo-editor\leo\doc\html
echo make clean
call make clean
</t>
<t tx="ekr.20230121110345.1"></t>
<t tx="ekr.20230121110533.1" _mod_time="4741d993336a2adb852e">@language batch
echo off
echo off
cd C:\Repos\leo-editor\leo\doc\html
echo make html
call make html</t>
<t tx="ekr.20230121135204.1">The workbook file
=================

Leo opens the **workbook file** when you start
Leo without a filename.

The body has focus--it is colored a pale pink, and
contains a blinking cursor.

**Note**: on some monitors the colors will be almost
invisible.  You can choose such colors to suit your
taste.

.. image:: _images/slide-002.png
</t>
<t tx="ekr.20230121135205.1">Editing headlines
=================

Ctrl-H edits the presently selected headline.

You can type Ctrl-H at any time, regardless of
where the focus is.

The body pane is now blue, indicating that it no longer has focus.

.. image:: _images/slide-003.png

</t>
<t tx="ekr.20230121135205.2">Typing in the headline
======================

.. image:: _images/slide-004.png
</t>
<t tx="ekr.20230121135205.3">The icon box
============

Typing the &lt;return&gt; key ends editing of the headline
and puts focus back in the body pane.

The **icon box** to the left of the headline now has a dark outline,
indicating that the node is **dirty**, that is, the node's headline or body
text has changed.

.. image:: _images/slide-005.png</t>
<t tx="ekr.20230121135206.1">Switching focus
===============

- Alt-D always puts focus in the body.
- Alt-T always puts focus in the outline.
- When the focus is in the tree, &lt;return&gt; puts the focus in the body.
</t>
<t tx="ekr.20230121135206.2">Saving the outline
==================

Ctrl-S saves the outline.

Afterwards, all icon boxes once have gray borders,
indicating that no nodes are now dirty.

.. image:: _images/slide-007.png

</t>
<t tx="ekr.20230121135206.3">Inserting new nodes
===================

Ctrl-I inserts a new node.

.. image:: _images/slide-008.png

</t>
<t tx="ekr.20230121135206.4">&lt;Return&gt; ends headline editing
===============================

The focus is now in the body pane.

.. image:: _images/slide-009.png

</t>
<t tx="ekr.20230121135206.5">The blue square
===============

Whatever I type will appear in the body pane.

I added a shopping list.

The blue square in the icon area indicates that the body pane contains text.

.. image:: _images/slide-010.png</t>
<t tx="ekr.20230121135312.10">Left-Arrow: contracts a node
============================


With the "to-do today" node selected,
hitting the Left-Arrow key will contract the node.

.. "to do" contracted.

.. image:: _images/slide-019.png

</t>
<t tx="ekr.20230121135312.11">Right-Arrow: expand a node
==========================


To expand the "to do" node,
I merely hit the Right-Arrow key.

We can now see the entire to-do list.

.. image:: _images/slide-020.png

</t>
<t tx="ekr.20230121135312.2">Moving nodes right
==================


Ctrl-R moves a node right.

The "go shopping" node becomes a **child**
of the "to do" node.

The "to do" node is the **parent** node.

.. image:: _images/slide-011.png

</t>
<t tx="ekr.20230121135312.3">Moving nodes left
=================


Ctrl-L moves the "go shopping" node left.

The "go shopping" node becomes a **sibling**
of the "to do" node.

.. image:: _images/slide-012.png

</t>
<t tx="ekr.20230121135312.4">Undo and redo
=============


Leo has unlimited undo/redo capabilities.

Here, I typed Ctrl-Z to undo the previous move.
The "go shopping" node is once again a child of
the "to do" node.

**Note**: Ctrl-Shift-Z redoes a previous undo.

.. image:: _images/slide-013.png

</t>
<t tx="ekr.20230121135312.5">Add a to-do node
================

Let's add a new node with Ctrl-I.

.. image:: _images/slide-014.png

</t>
<t tx="ekr.20230121135312.6">Add a to-do item
================

.. image:: _images/slide-015.png

</t>
<t tx="ekr.20230121135312.7">Move a node up
==============


The car should have first priority.

Type Ctrl-U to move the "fix car" node up.
The node becomes the first child of the "to do" node.

.. image:: _images/slide-016.png

</t>
<t tx="ekr.20230121135312.8">Hide child nodes
================


After creating the to-do list, I want to hide it
by **collapsing** the "to do" node.

I could do that by clicking the black triangle
to the left of the "to do" node.

However, using the mouse is not recommended--there are much easier ways.

.. arrow points to black triangle.

.. image:: _images/slide-017.png

</t>
<t tx="ekr.20230121135312.9">Changing focus
==============

With the focus in the tree pane, the Up-Arrow key selects the previous node.

There are several ways to put focus in the tree:

- Alt-T (focus to the tree pane) followed by Up-Arrow.
- Alt-Up-Arrow.

.. image:: _images/slide-018.png

</t>
<t tx="ekr.20230121135448.2">Summary: arrow keys
===================


The arrow keys do different things depending on
which pane has focus. Using arrow keys is **much**
easier than using the mouse.

**Focus in outline pane**

    The **plain** arrow keys **select** nodes,
    expanding or contracting nodes as needed.

    The **shift** arrow keys **move** nodes. The
    Shift-Left-Arrow and Shift-Up-Arrow contract
    nodes as needed. **Note**: the
    Shift-Down-Arrow and Shift-Right-Arrow keys
    never expand nodes.

**Focus in body pane**

    As usual, the **plain** arrow keys move the
    cursor and the **shift** arrow keys move the
    cursor and extend the solution.

    The **alt** arrow keys move the focus to the
    outline pane and then select nodes. The
    **alt-shift** arrow keys move the focus to the
    outline pane and then move nodes.

..  - The Up-Arrow and Down-Arrow keys select
..  the previous or next visible nodes.

..  - The Right-Arrow key contracts a node if the node
..  is expanded. Otherwise the Right-Arrow key
..  selects the node's parent.

..  - The Left-Arrow key does nothing if the selected
..  node has no children.  If the node does have
..  children, the Left-Arrow key expands the node
..  (if the children or invisible) or selects the
..  first child (if the children are visible).

..  This is exactly how Windows explorer works, and
..  it quickly becomes second nature.

</t>
<t tx="ekr.20230121135448.3">Shift-Ctrl-C: copy an outline
=============================


We can copy and paste nodes and all their descendants.

Using the arrow keys as necessary, I select the
"to do" node.

The Shift-Ctrl-C key copies the selected outline.

I want to do the paste *after* the to-do list, so I collapse
the original node before doing the paste:

.. image:: _images/slide-022.png

</t>
<t tx="ekr.20230121135448.4">Shift-Ctrl-V
===============

Shift-Ctrl-V pastes the outline.

.. image:: _images/slide-023.png

</t>
<t tx="ekr.20230121135448.5">Copy works on entire trees
==========================

Expanding the node shows that the copy operation
copied the node and all its descendants.

.. image:: _images/slide-024.png

</t>
<t tx="ekr.20230121161822.1">Summary
=======

This concludes the introduction to Leo's outline operations:

- Ctrl-I: Create a new node.
- &lt;Return&gt; ends headline editing and puts focus in the body.
- Arrow keys and other shortcuts move, expand and contract nodes.
- Shift-Ctrl-C: copies the selected node and all its descendants.
- Shift-Ctrl-V: pastes the copied outline.
</t>
<t tx="ekr.20230121164642.1">Changing cloned headlines
=========================

Changing the headline of node A changes the headlines of all cloned nodes.

.. image:: _images/slide-003.png
</t>
<t tx="ekr.20230121165506.1">A new node
==========

Here we have created a node C following the first clone of B.

.. image:: _images/slide-004.png
</t>
<t tx="ekr.20230121165507.1">Adding a child node
===================

Moving C to the right makes C a child of node B. As you can see, C appears as a child of both cloned nodes.

Even the expansion state of cloned nodes are identical: both clones are now expanded.

.. image:: _images/slide-005.png
</t>
<t tx="ekr.20230121165507.2">Creating a second child
=========================

Here, I have created a new node D with Ctrl-I (insert-node).

The node appears as a child of both cloned nodes.

In general, any change to one clone produces the corresponding change in all other clones.

.. image:: _images/slide-006.png
</t>
<t tx="ekr.20230121165507.3">Tracking changed nodes
=========================

Changing a node marks all clones of that node as changed.

When saving an outline, Leo automatically writes all the external files that contain dirty nodes.

For example, the cloned spam node appears in two places.

.. image:: _images/slide-007.png
</t>
<t tx="ekr.20230121165507.4">Tracking changed files
======================

After changing either clone, Leo marks both as changed.

Leo also marks any ancestor @file nodes as changed, ensuring
that Leo will also update all changed external files.


.. image:: _images/slide-008.png
</t>
<t tx="ekr.20230121165508.1">The ultimate filing cabinet
===========================

Clones are important because they allow you to create as many views of the
data in the outline as you like.

Leo acts like flexible filing cabinet.

Any ordinary node can act like a folder in the filing cabinet. Using
clones, you can “file” a node in as many folders as you like.

.. no image for this slide.</t>
<t tx="ekr.20230121165508.2">Views are sets of nodes
=======================

A Leo **view** is just a subset of the nodes of the outline.

We represent a view as ordinary node, called a view node (1).

The children of the view node are the subset of nodes that define the view.

An outline may contain arbitrarily many views.
You don't have to choose just one "correct" view.

.. image:: _images/slide-010.png
</t>
<t tx="ekr.20230121165549.1">Views focus attention
=====================

Views focus attention on tasks. I track issues as follows:

I create a **task node** whose children contain all the relevant data.

Cloned children gather data from all parts of the outline.

Non-cloned children contain supplemental data:
- A summary of the task.
- Test data.
- Any other notes.

.. image:: _images/slide-011.png
</t>
<t tx="ekr.20230121165549.2">Views concentrate data
======================

Task nodes focus attention on the task at hand.

There is no need to jump around the outline!

No matter how complex the task (or the outline!), all relevant data appear in one place (the task node and its descendants).

Leo will mark as dirty all @&lt;file&gt; nodes containing any changed clones.
As a result, Leo will update all external files automatically. Everything “just works”.

.. no image for this slide.</t>
<t tx="ekr.20230122011127.1">About external files
====================

Trees whose root headline starts with @file, @auto or @edit create external
files on your file system. Here are some example headlines::

    @file myClass.py
    @auto ../graphics/circles.cpp
    @edit ~/.leo/.leoID.txt

As you can see, these nodes specify file names, which can be an absolute
path or a path relative to the directory containing the Leo outline.

Collectively, nodes that create external files are known as @&lt;file&gt; nodes.
Leo defines several other kinds of @&lt;file&gt; nodes, but this slideshow will
not discuss them.

.. This slides contains no image.</t>
<t tx="ekr.20230122011226.1">Loading and saving files
========================

Leo automatically loads all @&lt;file&gt; trees when you open a Leo outline, and
Leo writes any modified @&lt;file&gt; tree when you save an outline. Reading
external files is very fast because of an efficient file-caching scheme.

A single Leo outline may be connected to dozens of external files: this
makes Leo work like an Integrated Development Environment (IDE). Leo
outlines act like project files. For example, one Leo outline,
leoPyRef.leo, contains @file trees for all of Leo’s core source files.
Another Leo outline, leoPluginsRef.leo, creates the external files for all
of Leo’s plugins, and LeoDocs.leo contains all of Leo’s documentation.

.. This slides contains no image.</t>
<t tx="ekr.20230122011227.1">Sentinel lines
==============

Leo stores the structure of @file trees in external files themselves using
comment lines called **sentinel lines** (sentinels, for short). Sentinels
represent outline structure, including clone relationships.

.. This slides contains no image.</t>
<t tx="ekr.20230122011227.2">External files without sentinels
================================

.. _`Leo's directives documentation`: https://leo-editor.github.io/leo-editor/directives.html#part-1-file-directives

Sentinels may be objectionable in collaborative environments.

There are several ways of creating external files that don't use sentinels,
including `@auto` and `@clean`.
See `Leo's directives documentation`_ for full details.

.. This slides contains no image.</t>
<t tx="ekr.20230122011227.3">Using @file trees
=================

The next few slides will show how to create external files with @file trees.

First, create an @file node giving the path to the external file. This path
can be a full, absolute path, or a relative path. Relative paths start at
Leo’s load directory, the directory containing the .leo file for the
present outline. No path prefix is usually required.

.. image:: _images/slide-005.png
</t>
<t tx="ekr.20230122011228.1">Top-level markup
================

The body text contains Leo markup.

The next few slides will discuss this markup line by line.

.. image:: _images/slide-006.png</t>
<t tx="ekr.20230122011228.2">Section references
==================

The `&lt;&lt; imports &gt;&gt;` line is a section reference. “Imports” is the section name. This line tells Leo to insert the section definition into the output file at the place where section reference occurs.

.. image:: _images/slide-007.png</t>
<t tx="ekr.20230122011228.3">Section definitions
===================

Section definition nodes create section definitions. Section definition nodes contain a section name in the headline. The body text contains the section definition.

The definition of &lt;&lt; imports &gt;&gt; are the lines::

    import os
    import sys

Each section definition node must be a descendant of the node containing the section reference.

.. image:: _images/slide-008.png</t>
<t tx="ekr.20230122011228.4">The @others directive
=====================

The **@others** directive is similar to a section reference; @others tells Leo to insert text into the output file. Instead of inserting the body text of one particular node, as in a section reference, @others tells Leo to insert the body text of all nodes that are *not* section definition nodes. That’s where the name comes from: it inserts all the *other* nodes.

.. image:: _images/slide-009.png
</t>
<t tx="ekr.20230122011228.5">References &amp; expansions
=======================

The term **reference** means either a section reference or an @others directive. 

The **expansion** of a reference is the set of all lines that Leo writes to the output file as the result of that reference.

.. This slides contains no image.</t>
<t tx="ekr.20230122011229.1">Indentation
===========

The indentation of references is significant. Leo indents each line of the expansion of a reference by the total amount of leading whitespace that is in effect at the point of the reference. This allows Leo to handle languages like Python in which indentation is especially important.

Here there is no leading whitespace before the reference to `&lt;&lt;imports &gt;&gt;`,
but there are four spaces before the @others directives. So:

- Leo writes the import statements without additional indentation.
- Leo adds 4 spaces before all nodes written as the result of the @others
  directive.

.. This slides contains no image.</t>
<t tx="ekr.20230122011229.2">More about indentation
======================

Indentation is controlled *only* by the indentation of references. The outline level of nodes in expansions does not affect indentation in any way.

This *decoupling* of outline structure from indentation is crucial:

  *organizer nodes do not affect the indentation of the lines*.

.. image:: _images/slide-012.png</t>
<t tx="ekr.20230122011229.3">More about expansions
=====================

Node may contain arbitrarily many section references.

No node may contain more than one @others directive.

The expansion of a section reference is the expansion of the body of the
section definition node. That expansion may include expansions of other
references appearing in that node.

The expansion of an @others directive is the expansion of all descendant
nodes that are *not* section definition nodes.

No node is ever included in the expansion of more than one @other
directive. If several ancestors contain @others directives, the @others
directive in the nearest ancestor applies.

.. This slides contains no image.</t>
<t tx="ekr.20230122011229.4">Orphan nodes
============

**Orphan nodes** are descendants of @&lt;file&gt; nodes that would not be included the external file.

Leo checks for orphan nodes when writing any @&lt;file&gt; tree:

- There must be a section reference for section definition node.
- There must be an @others directive for nodes that aren't section
  definitions nodes.

Leo will issue an error if an @&lt;file&gt; tree contains orphan nodes.

.. This slides contains no image.
</t>
<t tx="ekr.20230122011229.5">A common pattern
================

The next two slides illustrate a common pattern for a file that defines two classes.

In each example, a top-level node includes imports, and then uses @others to include the expansion of the rest of the outline.

.. Misleading slide number.
.. image:: _images/slide-018.png</t>
<t tx="ekr.20230122011230.1">SpamClass
=========

The first child node creates the expansion of SpamClass. The lines::

    class SpamClass:
        '''A class representing spam.'''

have no extra indentation, because the @others in the top-level node has no leading whitespace.

However, the two methods of the class will have 4 spaces of indentation because the @others directive in this node is indented by 4 spaces.

.. image:: _images/slide-016.png</t>
<t tx="ekr.20230122011230.2">EggsClass
=========

The second child node creates the expansion of EggsClass in a similar manner.

.. image:: _images/slide-017.png</t>
<t tx="ekr.20230122011230.4">Alternatives to @file
=====================

The next few slides discuss two alternatives to @file, @auto and @edit.

@auto and @edit create external files without sentinel lines. The cost of avoiding sentinel lines is that Leo can not preserve outline structure exactly.


.. image:: _images/slide-019.png</t>
<t tx="ekr.20230122011230.5">Using @auto nodes
=================

When reading an @auto node, Leo uses an **importer** to create an outline.

Leo has importers for many languages including C, html, Java, Javascript, PHP, Python, and xml.

The file's extension determines which importer to use.

If no importer exists for a language, @auto copies the entire file into the @auto node.

.. This slides contains no image.
</t>
<t tx="ekr.20230122011444.1">@auto example
=============

Here is an example of an actual Python file imported into Leo.

The importer has created the entire outline, including the body text of the root @auto node.

The importer created an @others directive (1) to place the expansion of the descendant nodes properly, before the final top-level lines of the file (2).

.. image number is misleading.
.. image:: _images/slide-022.png</t>
<t tx="ekr.20230122011445.1">Using @edit nodes
=================

When Leo reads and @edit node, Leo reads the entire contents of the external file into the body text of the @edit node. Any changes to the external file will appear in the @edit node the next time Leo loads the external file. Rather than creating new files with @edit, it is more common to use @edit to connect Leo with files that already exist on your file system.

.. image number is misleading.
.. image:: _images/slide-023.png</t>
<t tx="ekr.20230122081543.1">Introduction to scripting
=========================

For me, scripting is the most fun part of Leo.

Leo can execute any body text as a Leo script, Python scripts that have full access to all data in any open Leo outline, as well as full access to all parts of Leo’s source code.

Leo’s Ctrl-B (execute-script) command runs the body text of a node as a Leo script.
</t>
<t tx="ekr.20230122081601.1">c, g and p
==========

Leo scripts execute in an environment containing three predefined objects: c, g and p.

**g** is Leo’s leoGlobals module. This module contains dozens of utility functions and classes.

**c** is the commander of the outline containing the script. Commanders
define all of Leo’s commands, as well as other data.

**p** is the position of the presently selected node. Positions objects
represent positions in the traversal of Leo outlines.

This slideshow shows how to use c, g and p in Leo scripts. For full details
about scripting in Leo, see the Scripting Chapter in Leo’s Users Guide.</t>
<t tx="ekr.20230122081602.1">Official ivars
==============

The c, g and p objects give Leo scripts access to all parts of Leo and Leo outlines. There are many official ivars (instance variables) that scripts may use. Here are a few:

**c.frame** is an object representing the actual parts of Leo screen.

For any frame, frame.c is the frame’s commander, so c.frame.c is always c.

**g.app** is the object representing the entire Leo application.

The ivars of g.app represent Leo’s global variables.

**p.v** is the **vnode** at position p.

A vnode represents an outline node. Vnodes hold most of the data in Leo outlines. For any vnode v, v.h is the node’s headline, and v.b is the node’s body text.

**p.h** and **p.b** are synonyms for p.v.h and p.v.b.

Because of clones, a *vnode may appear in several positions in a traversal*.
</t>
<t tx="ekr.20230122081602.2">Hello world
===========

g.es is a function that prints its arguments to Leo’s log pane.

Here is the hello world program as a Leo script::

    g.es('Hello world!')

Leo scripts may also use Python’s print command provided that Leo is running in a console.</t>
<t tx="ekr.20230122081602.3">p.h and p.b
===========

For any position p, p.h is the headline text of p.v, and p.b is the body text of p.v.

p.h and p.b are Python properties, which means you can set the headline and body text by assigning to them::

    p.h = p.h + ' more'

After changing a headline, Leo scripts should redraw the outline::

    c.redraw()


</t>
<t tx="ekr.20230122081603.1">Iterators
=========

Leo defines Python iterators that return positions. These iterators are the easiest way of gaining access to the nodes of Leo outlines. Here are just a few examples:

- **c.all_positions()** returns all the positions of the outline in order.

  *Note*: Cloned nodes will appear several times in this list.

- **c.all_unique_nodes()** returns all the vnodes of the outline.
- **p.self_and_subtree()** returns p and all its descendants.
- **p.children()** returns all of p’s direct children.
</t>
<t tx="ekr.20230122081603.2">Using iterators
===============

Iterators give access to all the data in a Leo outline. For example, the following script prints all headlines in an outline, indented to show outline level::

    for p in c.all_positions():
        g.es(' '*p.level(),p.h)

The output of this script, when run from LeoDocs.leo, will look something like this::

    Startup
     @file doc-startup.txt
      @chapters
      Buttons
       Disabled buttons
    ... and hundreds of other nodes.

*Note*: p.level() is a method of the position class that returns the outline level of the node at position p: 0 for top-level nodes, 1 for their children, and so on.
</t>
<t tx="ekr.20230122081628.1">Building scripts from outlines
==============================

Leo scripts can be composed of more than one node, just as with external files.

The Execute Script command expands expanding section references and @others directives. For example::

    """docstring"""
    @others
    controller(c).run()

A child node will contain something like the following::

    class controller:
        def __init__(self,c):
            self.c = c
        @others

The children of the top-level class node will contain all the methods of the controller class.</t>
<t tx="ekr.20230122081635.1">g.openWithFileName
==================

g.openWithFileName opens a .leo file::

    ok, frame = g.openWithFileName(fileName,c)
    new_c = frame.c

The returned frame value represents the frame of the visual outline.

frame.c is the frame’s commander, so new_c is the commander of the newly-created outline.</t>
<t tx="ekr.20230122081949.1">Debugging scripts
=================

**g.pdb()** invokes Python's debugger.

You must run Leo from a console if your script calls g.pdb().

Leo's pudb plugin changes g.pdb so that it invokes the Pudb debugger instead of Python's pdb.
</t>
<t tx="ekr.20230122081950.1">Further reading
===============

This concludes our brief introduction to scripting in Leo.

For full details about scripting in Leo, see the Scripting Chapter in Leo’s Users Guide.
</t>
<t tx="ekr.20230122101310.1">Introduction
============

Leo’s minibuffer appears at the bottom of Leo’s main window.

You use the minibuffer to execute commands by name.

Type &lt;Alt-x&gt; to put the cursor in the minibuffer.

.. image:: _images/slide-001.png
</t>
<t tx="ekr.20230122101506.1">Tab completion
==============

You can execute any Leo command by typing the command's **full name**
in the minibuffer, followed by the &lt;return&gt; key.

You can use **tab completion** to avoid typing full command names.

With tab completion *you don't have to remember the exact names of Leo’s commands*.

.. This slides contains no image.
</t>
<t tx="ekr.20230122101506.2">Example
=======

Suppose you want to print out the list of Leo’s commands.

You need only remember that commands start with “show”. Just type::

    &lt;alt-x&gt;pri&lt;tab&gt;

You will see “show-” in the minibuffer.

The Completion tab in the log pane shows all the commands that start with “show-”.

.. image:: _images/slide-003.png</t>
<t tx="ekr.20230122101507.1">Example, continued
==================

Now just type `c&lt;tab&gt;`.

You will see one the single show-commands command in the minibuffer.

Finally, type &lt;return&gt; to execute the command.

.. image:: _images/slide-004.png</t>
<t tx="ekr.20230122101507.2">Example, concluded
==================

You will see the output of the show-commands command in the commands tab.

Focus returns to the body pane.

.. image:: _images/slide-005.png</t>
<t tx="ekr.20230122101507.3">Shortcuts
=========

- &lt;tag&gt; shows all valid completions.
- &lt;BackSpace&gt; removes previously-typed characters, showing more completions.
- &lt;Ctrl-G&gt; exits the minibuffer without executing any command.

.. This slides contains no image.
</t>
<t tx="ekr.20230122101507.4">Search arguments
================

Leo’s find command accumulates the search and replace strings in the minibuffer.

&lt;Ctrl-F&gt; invoke the find command, type &lt;Ctrl-F&gt;.

Focus moves to the minibuffer and shows the Find tab.

.. image:: _images/slide-007.png</t>
<t tx="ekr.20230122101507.5">Search string
=============

Now type the search string.


.. image:: _images/slide-008.png</t>
<t tx="ekr.20230122101508.1">Replace string
==============

You can invoke the find by typing &lt;return&gt;.

You can also specify a replacement strings.

Type &lt;tab&gt;. The minibuffer prompts for the replacement string.

.. image:: _images/slide-009.png</t>
<t tx="ekr.20230122101508.2">Doing the find
==============

Type a replacement string.

Type &lt;return&gt; to start the find-next command.

.. image:: _images/slide-010.png</t>
<t tx="ekr.20230122101508.3">Doing the replace
=================

Now Leo has found the next instance of “def” in the body pane.

- &lt;Ctrl-minus&gt; makes the replacement.
- &lt;F3&gt; continues searching without making a replacement.
- &lt;Ctrl-G&gt; ends the search.

.. image:: _images/slide-011.png</t>
<t tx="ekr.20230123101622.1"></t>
<t tx="ekr.20230123101657.1">##############
More Leo Links
##############

.. toctree::
    :maxdepth: 1

    FAQ                 &lt;FAQ&gt;
    Cheat Sheet         &lt;cheatsheet&gt;
    Code Snippets       &lt;https://github.com/leo-editor/snippets&gt;
    Tutorial slides     &lt;slides&gt;
    Screen shots        &lt;screen-shots&gt;
    Screencasts         &lt;screencasts&gt;
    History of Leo      &lt;history&gt;
    Glossary            &lt;glossary&gt;
    What's New          &lt;what-is-new&gt;
    Still more links    &lt;leoLinks&gt;
    </t>
<t tx="ekr.20230124061650.1">.. _`Black`: https://github.com/psf/black

Leo's ``beautify`` command differs from `Black`_ as follows:

- ``beautify`` never changes Leo's sentinel comments.
- ``beautify`` never splits or joints lines (with the default settings).
  Black sometimes inserts horrible line breaks.
- ``beautify`` never converts single-quote strings to double-quote strings.
  That is, ``beautify`` simulates Black's ``--skip-string-normalization`` command-line option.
- ``beautify`` doesn't insert extra blank lines at the end of nodes.
  Technically, this is a pep8 violation, but these extra lines are not Leonine.
</t>
<t tx="ekr.20230228100301.1"></t>
<t tx="ekr.20230228100301.2">When checked, the Find and Change commands ignore the case of alphabetic characters when determining matches.
</t>
<t tx="ekr.20230228100301.3"></t>
<t tx="ekr.20230303070618.1">ctrl-click-at-cursor
make-sphinx
find-bad-links</t>
<t tx="ekr.20230409052507.1">Leo https://leo-editor.github.io/leo-editor/ 6.7.3 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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 ``@&lt;file&gt;`` 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.7.3 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.7.3+)
- [6.7.3 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.7.3)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language rest
</t>
<t tx="ekr.20230409053106.1">.. _`PR #3260`: https://github.com/leo-editor/leo-editor/pull/3260

- `PR #3260`_:  Improved and safer handling of paths in ``@&lt;file&gt;`` 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`: https://github.com/leo-editor/leo-editor/pull/3227
.. _`PR #3255`: https://github.com/leo-editor/leo-editor/pull/3255
.. _`PR #3192`: https://github.com/leo-editor/leo-editor/pull/3192

- `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`: https://github.com/leo-editor/leo-editor/pull/3208
.. _`PR #3214`: https://github.com/leo-editor/leo-editor/pull/3214
.. _`PR #3224`: https://github.com/leo-editor/leo-editor/pull/3224
.. _`PR #3241`: https://github.com/leo-editor/leo-editor/pull/3241
.. _`PR #3264`: https://github.com/leo-editor/leo-editor/pull/3264
.. _`PR #3277`: https://github.com/leo-editor/leo-editor/pull/3277

- `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.
- `PR #3264`_ and `PR #3277`_: Simplify Leo's path-related code.

- 20+ issues and 30+ pull requests.
</t>
<t tx="ekr.20230628032632.1">###############
Clickable links
###############

Leo syntax colors clickable links in the body pane. They have four forms:

1. Error messages produced by flake8, mypy, pyflakes, pylint, python:

   Some of these tools produce clickable links in the log pane when run
   *within* Leo. Some do not.

   When running these tools *outside of* Leo, copying an error message from
   the *console* to Leo's log pane will create clickable links in the log
   pane. Control-clicking these links will select the proper node and line
   provided the outline contains an ``@&lt;file&gt;`` node for file mentioned in
   the error message.

2. UNLs based on gnxs (global node indices):

   Links of the form ``unl:gnx:`` + ``//outline#gnx`` open the given
   outline and select the first outline node with the given gnx. These UNLs
   will work as long as the node exists anywhere in the outline.

   *Note*: ``outline`` is optional. It can be an absolute path name or
   a relative path name resolved using ``@data unl-path-prefixes``.

3. Leo's headline-based UNLs, as shown in the status pane:

   Headline-based UNLs consist of ``unl://`` + ``//outline#headline-list``
   where ``headline-list`` is a list of headlines separated by ``--&gt;``.

   *Note*: ``outline`` is optional. It can be an absolute path name or
   a relative path name resolved using ``@data unl-path-prefixes``.

4. Web URLs: file, ftp, gopher, http, https, mailto, news, nntp, prospero, telnet, wais.

   For example, Leo's forum: https://leo-editor.github.io/leo-editor/
</t>
<t tx="ekr.20230703101804.1">Leo https://leo-editor.github.io/leo-editor/ 6.7.4 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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 &amp; #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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.7.4 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.7.4+)
- [6.7.4 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.7.4)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language rest
</t>
<t tx="ekr.20230709070852.1">.. Use the link-pr abbreviation to create these links.

.. _`PR #3215`: https://github.com/leo-editor/leo-editor/pull/3215
.. _`PR #3424`: https://github.com/leo-editor/leo-editor/pull/3424
.. _`PR #3433`: https://github.com/leo-editor/leo-editor/pull/3433

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

`PR #3433`_: Callers must remove the "fn" positional arg from
at.readOneAtEditNode and at.readOneAtAsisNode.

**gnx-based unls**

- `PR #3215`_ and `PR #3424`_: gnx-based unls (clickable links).
  These links will break only if the original node is deleted.
  See: https://leo-editor.github.io/leo-editor/clickablelinks.html


**New settings**

- @string unl-status-kind = gnx
- @bool full-unl-paths = True
- @data unl-path-prefixes

**Other improvements**

.. _`PR #3330`: https://github.com/leo-editor/leo-editor/pull/3330
.. _`PR #3345`: https://github.com/leo-editor/leo-editor/pull/3345
.. _`PR #3363`: https://github.com/leo-editor/leo-editor/pull/3363
.. _`PR #3379`: https://github.com/leo-editor/leo-editor/pull/3379
.. _`PR #3376`: https://github.com/leo-editor/leo-editor/pull/3376

- `PR #3330`_: Improve importers for C, C++, and cython.
- `PR #3345`_: Improve importer architecture.
- `PR #3363`_ &amp; `PR #3379`_: Improve c.recursiveImport.
- `PR #3376`_: Improve python importer.

**Large code changes**:

.. _`PR #3365`: https://github.com/leo-editor/leo-editor/pull/3365
.. _`PR #3367`: https://github.com/leo-editor/leo-editor/pull/3367

- `PR #3365`_: Simplify all 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.
  The first was dangerous. gnx-based unls obsolete the other two.

- 50+ issues and 70+ pull requests.</t>
<t tx="ekr.20230716051446.1">Leo syntax colors clickable links in the body pane. For example:

Leo's home page: https://leo-editor.github.io/leo-editor/

The status area shows the UNL (*Universal Node Locator*) for each node.

Control-clicking a UNL will take you to its target node, even if the target is in another Leo file!
gnx-based UNLs won't break even if you move or rename the target node.

Try these examples!

The "Key bindings" node in this file:
unl:gnx://CheatSheet.leo#ekr.20131019184243.16685

The "6.7.5 release notes" node in LeoDocs.leo.
unl:gnx://LeoDocs.leo#ekr.20230703101804.1
</t>
<t tx="ekr.20230901233131.1">Leo https://leo-editor.github.io/leo-editor/ 6.7.5 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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 &amp; 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.7.5 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.7.5+)
- [6.7.5 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.7.5)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language rest
</t>
<t tx="ekr.20230901233844.1">.. Use the link-pr abbreviation to create these links.

.. _`PR #3509`: https://github.com/leo-editor/leo-editor/pull/3509
.. _`PR #3511`: https://github.com/leo-editor/leo-editor/pull/3511
.. _`PR #3515`: https://github.com/leo-editor/leo-editor/pull/3515
.. _`PR #3517`: https://github.com/leo-editor/leo-editor/pull/3517
.. _`PR #3568`: https://github.com/leo-editor/leo-editor/pull/3568

- `PR #3568`_: Improve word-oriented finds and improve Leo's spell checker.
- `PR #3515`_ and `PR #3517`_: Significantly improve python importer.
- `PR #3509`_ and `PR #3511`_: Improve rust importer.

**Other improvements**

.. _`PR #3499`: https://github.com/leo-editor/leo-editor/pull/3499
.. _`PR #3503`: https://github.com/leo-editor/leo-editor/pull/3503
.. _`PR #3519`: https://github.com/leo-editor/leo-editor/pull/3519
.. _`PR #3521`: https://github.com/leo-editor/leo-editor/pull/3521
.. _`PR #3525`: https://github.com/leo-editor/leo-editor/pull/3525
.. _`PR #3528`: https://github.com/leo-editor/leo-editor/pull/3528
.. _`PR #3531`: https://github.com/leo-editor/leo-editor/pull/3531
.. _`PR #3533`: https://github.com/leo-editor/leo-editor/pull/3533
.. _`PR #3538`: https://github.com/leo-editor/leo-editor/pull/3538
.. _`PR #3541`: https://github.com/leo-editor/leo-editor/pull/3541
.. _`PR #3552`: https://github.com/leo-editor/leo-editor/pull/3552
.. _`PR #3560`: https://github.com/leo-editor/leo-editor/pull/3560
.. _`PR #3607`: https://github.com/leo-editor/leo-editor/pull/3607

- `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 &amp; move-outline-to-last-child commands.
- `PR #3528`_: Fix 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.
</t>
<t tx="ekr.20230908140206.569">This "fallow" period prepared contained important performance improvements and paved the way for ``leoInteg``.

An acknowledgment is appropriate here. About this time, Vitalije Milosevic (Виталије Милошевић) insisted that Leo's code could be improved by removing kwargs. Yes, doing so requires duplicating code, but the resulting simplicity is almost always significant. In many cases, the simplifications ripple throughout Leo's codebase. These simplifications continue to the present day.

Vitalije also suggested that local helper functions would also improve Leo's code. I use this pattern less often, but it too has its place.

Leo 5.4 (October 22, 2016): Add ``clone-find`` commands.

Leo 5.5 (March 23, 2017): A bug fix made syntax coloring 20x faster!

Leo 5.6 (September 25, 2017):

- Add the ``git-diff`` command.
- Add the ``cursesGui2.py`` plugin. This plugin contained the ``p_to_ap`` and
  ``ap_to_p`` functions that became crucial parts of ``leoInteg``.

Leo 5.8 (October 1, 2018): Replace caching with Vitalije's super-fast read code.

Leo 5.9 (May 1, 2019): Add ``LeoWapp.py``, Leo in a browser.</t>
<t tx="ekr.20230908152641.1">August, 2020: edreamleo's first PR. Félix Malboeuf encouraged me to use PRs for all significant code changes.

Around this time Félix started a careful code review of *all* of Leo's core, including many plugins. This ongoing review found many "quirps" and some larger bugs.

6.2 (March 27, 2020): The rise of f-strings in Leo. How did I ever live without them?

6.3 (November 6, 2020): ``leoAst.py``.

June 21, 2021: The dawn of ``LeoInteg``: The first commit by Félix Malboeuf for leoserver.py, a stand-alone server for Leo.

6.4 (September 20, 2021): The first release supporting ``LeoInteg``: integration of Leo with VS code. ``LeoInteg`` and ``LeoJS`` are the future of Leo. All later releases contain support for ``LeoInteg`` and ``LeoJS``. This was the first release containing leoserver.py.

.. _`leo-integ-announcement`: https://groups.google.com/g/leo-editor/c/8SPF7GFo5f4/m/GcaWR7ohBQAJ

Sep 24, 2021: Félix releases LeoInteg 1.0, with this `leo-integ-announcement`_.

This is one of the most important dates in Leo's history:

- LeoInteg promises to make millions of people aware of Leo.
  One click in `vs-code` installs `LeoInteg`.
- `LeoJS` will allow Leo to run in a browser!
- `LeoInteg` brings all of `vs-code`'s features to Leo. For example, there
  are several vim-emulator modes for `vs-code`, each much better than Leo's vim mode.

Leo on vs-code means that Leo will live on. Nothing lasts forever, but when IDE's become obsolete, the replacement might build on `vs-code` and Leo. That's pretty close to immortality in my book.

6.5: (October 22, 2021): Removed ``@test/@suite``, fixing the biggest mistake I ever made with Leo. It was shocking how much *harder* ``@test`` made unit testing! The ``create_app`` function in leoTest2.py allows Leo to use python's ``unittest`` module.

6.7.0 (September 26, 2022): Fully annotate Leo's core files and important plugins.

6.7.4 (August 17, 2023) A spectacular collapse in the importer architecture. The Aha! Use **guide lines** to make parsing incoming lines easier.
</t>
<t tx="ekr.20230909063921.1"></t>
<t tx="ekr.20230909063947.1"></t>
<t tx="ekr.20230909073504.2">I just want to provide my own thoughts about the importance of ``@clean``. I look at the posts in this group a fair amount because I find the discussion interesting but I had abandoned leo as a day-to-day tool principally because of the sentinels in ``@file`` nodes. Even for solo projects, I just found them visually unappealing and beyond that occasionally confusing when I went to edit files with external editors. I would sometimes start a project in leo, particularly if it was based on code I developed in the past using leo, and then would use the old ``@nosent`` to save a version of the code without sentinels and then use my external editor of choice and not use leo at all. I missed many of the features of leo but just couldn't get over the sentinel issue.

``@clean`` really seems to solve all the issues that I had. In particular--and somehow this point doesn't seem to me to have been emphasized enough--it seems to fully support organizer nodes. They are one of the great things about leo--it's happy to guess initially at what the structure of your program is but it's completely up to you to determine the structure and the ability to do things like break up long methods, group like methods, group menu actions in GUI code, etc etc is one of the very cool things about leo. My limited but growing experience with ``@clean``'s handling of external changes has been mainly with incremental (as opposed to more sweeping) code changes, and the assignment of new lines is reasonable and you can always fix them it quickly if you don't like how external changes have been handled.

There have been some posts about the recovered nodes, comparing the old and new nodes where there were external changes. I think it's genius. As opposed to hoping that leo has correctly incorporated external changes, it's all there in case you want to take a closer look. Without this, I would just not have the confidence that external changes were being applied correctly and while you can always do a git diff, I am not looking to do that every time I change a file externally especially if I am not at the point where I am about to do a commit.

There has been some discussion of ``@auto`` v. ``@clean``. Preference is obviously a matter of taste. I will say that for me the fact that node headlines are unaffected by external file changes is a feature not a problem since I place notes in the headlines that I want preserved when I edit files externally. Yes, if the node headlines are the method names then they won't be updated if an external edit changes a method name but this was true of ``@file`` as well.

The ability to work on projects with people who don't have leo is obvious; one perhaps slightly less obvious benefit of no sentinels is that I suspect that the likelihood that someone will clone a git repository is reduced when that repository's code is riddled with leo sentinels (unless the potential cloner is a leo loyalist). The one downside to no sentinels--there is no evidence that leo is being used but I think that raises the broader question of marketing leo, which I certainly believe will be aided significantly by being able to take advantage of leo without sentinels in external files.
</t>
<t tx="ekr.20230909073504.3">.. _`recursive import script`: scripting-miscellany.html#recursive-import-script
.. _git: https://git-scm.com/

``@clean`` is the long-sought breakthrough that just might allow Leo to "go viral". For the very first time, Leo can be used in *all* situations without compromise.  There is no longer any need to make excuses for sentinel lines, or argue whether people should accept them.  Sentinels are simply gone.

I have just realized how inconvenient sentinels might be for my *own* work flow.  This was a shocking revelation. To illustrate, here is an excerpt from the programming tutorial:

When I study other people's code I do the following:

- Create a git repo of the directory to be studied, adding all the source files and doing an initial commit.

- Use a `recursive import script`_ to create the desired ``@clean`` nodes.

- Explicitly save all the imported files using ``Ctrl-Shift-W`` (``write-at-file-nodes``).

- Use `git`_ diff to ensure that no important changes have been made while importing the nodes.

- Use git diff to track any changes I make (such as adding tracing or debugging statements) for the purposes of studying the code. Using ``@clean`` is an essential part of this work flow. The diffs would be much harder to read if I had imported files into ``@file`` trees instead.

In short, I have just now realized how badly sentinels interfered with git diffs.
</t>
<t tx="ekr.20231013091132.1">.. index::
    pair: @path; Reference
.. index::
    pair: Absolute path; Reference
.. index::
    pair: Path prefix; Reference

Sets the **path prefix** for relative filenames for all ``@&lt;file&gt;`` trees *except* ``@file`` trees.

The ``@path`` directive may appear in any headline or the body text ``@&lt;file&gt;`` nodes (``@clean``, ``@auto``, etc.).

*Note*: The ``@path`` directive is *not* allowed in the body text of ``@file`` nodes.

The path is an **absolute path** if it begins with ``c:\\`` or ``/``, otherwise the path is a **relative** paths.

Multiple ``@path`` directives may contribute to the path prefix. Absolute paths overrides any ancestor ``@path`` directives. Relative paths add to the path prefix.

If no ``@path`` directives are in effect, the default path prefix is the directory containing the .leo file.
</t>
<t tx="ekr.20231126120048.1">.. Use the link-pr abbreviation to create these links.

.. _`PR #3575`: https://github.com/leo-editor/leo-editor/pull/3575
.. _`PR #3642`: https://github.com/leo-editor/leo-editor/pull/3642
.. _`PR #3645`: https://github.com/leo-editor/leo-editor/pull/3645
.. _`PR #3659`: https://github.com/leo-editor/leo-editor/pull/3659
.. _`PR #3673`: https://github.com/leo-editor/leo-editor/pull/3673
.. _`PR #3693`: https://github.com/leo-editor/leo-editor/pull/3693
.. _`PR #3701`: https://github.com/leo-editor/leo-editor/pull/3701

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.
</t>
<t tx="ekr.20231126121710.1">Leo https://leo-editor.github.io/leo-editor/ 6.7.6 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.7.6 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.7.6+)
- [6.7.6 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.7.6)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language rest
</t>
<t tx="ekr.20240110034554.1">gnx: ekr.20170130080532.1
</t>
<t tx="ekr.20240110034554.2">gnx: ekr.20240110034324.1
unl: Leo's demo.py plugin
gnx: ekr.20240110034324.2
unl: Overview
gnx: ekr.20240110034324.3
unl: A simpler work flow
gnx: ekr.20240110034324.4
unl: Graphics classes &amp; helpers
gnx: ekr.20240110034324.5
unl: Using demo scripts
gnx: ekr.20240110034324.6
unl: Using demo scripts--&gt;Script trees and lists
gnx: ekr.20240110034324.7
unl: Using demo scripts--&gt;Predefined symbols
gnx: ekr.20240110034324.8
unl: Using demo scripts--&gt;Positioning graphics
gnx: ekr.20240110034324.9
unl: Using demo scripts--&gt;Deleting graphics
gnx: ekr.20240110034324.10
unl: Using demo scripts--&gt;Details
gnx: ekr.20240110034324.11
unl: Example scripts
gnx: ekr.20240110034324.12
unl: Example scripts--&gt;Top-level script
gnx: ekr.20240110034324.13
unl: Example scripts--&gt;Simulate typing
gnx: ekr.20240110034324.14
unl: Example scripts--&gt;Change the demo namespace
gnx: ekr.20240110034324.15
unl: Example scripts--&gt;Add graphics
gnx: ekr.20240110034324.16
unl: Example scripts--&gt;Switch focus
gnx: ekr.20240110034324.17
unl: Helper methods
gnx: ekr.20240110034324.18
unl: Helper methods--&gt;Ivars
gnx: ekr.20240110034324.19
unl: Helper methods--&gt;Menus
gnx: ekr.20240110034324.20
unl: Helper methods--&gt;Magnification and styling
gnx: ekr.20240110034324.21
unl: Helper methods--&gt;Simulated typing
gnx: ekr.20240110034324.22
unl: Helper methods--&gt;Startup, setup and teardown
gnx: ekr.20240110034324.23
unl: Helper methods--&gt;Window position and ratios
gnx: ekr.20240110034324.24
unl: Summary
gnx: ekr.20240110034324.25
unl: History and change log
</t>
<t tx="ekr.20240110034554.3">gnx: ekr.20161120073038.1
</t>
<t tx="ekr.20240118094108.1">Leo https://leo-editor.github.io/leo-editor/ 6.7.7 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.7.7 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.7.7+)
- [6.7.7 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.7.7)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)

@nowrap
@language rest
</t>
<t tx="ekr.20240118094134.1">.. Use the link-pr abbreviation to create these links.

.. _`PR #3761`: https://github.com/leo-editor/leo-editor/pull/3761

- `PR #3761`_: Improve leoserver.py to support LeoInteg.
</t>
<t tx="ekr.20240222121215.1">Leo https://leo-editor.github.io/leo-editor/ 6.7.8 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.7.8 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.7.8+)
- [6.7.8 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.7.8)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)</t>
<t tx="ekr.20240222121346.1">.. Use the link-pr abbreviation to create these links.

.. _`PR #3757`: https://github.com/leo-editor/leo-editor/pull/3757
.. _`PR #3771`: https://github.com/leo-editor/leo-editor/pull/3771
.. _`PR #3786`: https://github.com/leo-editor/leo-editor/pull/3786
.. _`PR #3790`: https://github.com/leo-editor/leo-editor/pull/3790
.. _`PR #3805`: https://github.com/leo-editor/leo-editor/pull/3805
.. _`PR #3806`: https://github.com/leo-editor/leo-editor/pull/3806
.. _`PR #3807`: https://github.com/leo-editor/leo-editor/pull/3807
.. _`PR #3817`: https://github.com/leo-editor/leo-editor/pull/3817

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.
</t>
<t tx="ekr.20240302082146.1">.. _`Leo's GitHub repository`:  https://github.com/leo-editor/leo-editor
.. _`Install Git`: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git

The following will install Leo from `Leo's GitHub repository`_.

1. `Install Python`_ 3.9 or above.
2. `Install pip`_.
3. `Install Git`_.
4. Clone Leo's repository::

    git clone https://github.com/leo-editor/leo-editor.git

5. Install Leo's dependencies from Leo's `requirements.txt` file::

    cd leo-editor
    python -m pip install -r requirements.txt
    
**Note for Ubuntu**


After installing on Ubuntu you may get this error messages when attempting to run Leo::

    qt.qpa.plugin: From 6.5.0, xcb-cursor0 or libxcb-cursor0 is needed to load the Qt xcb platform plugin.

To install the missing library run::

    sudo apt install libxcb-cursor0
</t>
<t tx="ekr.20240303071512.1">gnx: ville.20090609182215.5676
</t>
<t tx="ekr.20240303071512.2">gnx: ekr.20240303070818.1
unl: Python list based description of trees ('objtrees')
gnx: ekr.20240303070818.2
unl: Using objtrees for caching
gnx: ekr.20240303070818.3
unl: The `Leo database` (c.db, g.app.db)
</t>
<t tx="ekr.20240527100702.1">Leo https://leo-editor.github.io/leo-editor/ 6.8.0 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.8.0 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.8.0+)
- [6.8.0 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.8.0)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [A web page that displays .leo files](https://leo-editor.github.io/leo-editor/load-leo.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)</t>
<t tx="ekr.20240527100956.1"></t>
<t tx="ekr.20240527101024.1">.. Use the link-pr abbreviation to create these links.

.. _`PR #3828`: https://github.com/leo-editor/leo-editor/pull/3828
.. _`PR #3832`: https://github.com/leo-editor/leo-editor/pull/3832
.. _`PR #3841`: https://github.com/leo-editor/leo-editor/pull/3841
.. _`PR #3870`: https://github.com/leo-editor/leo-editor/pull/3870
.. _`PR #3872`: https://github.com/leo-editor/leo-editor/pull/3872
.. _`PR #3893`: https://github.com/leo-editor/leo-editor/pull/3893
.. _`PR #3902`: https://github.com/leo-editor/leo-editor/pull/3902
.. _`PR #3911`: https://github.com/leo-editor/leo-editor/pull/3911
.. _`PR #3921`: https://github.com/leo-editor/leo-editor/pull/3921
.. _`PR #3922`: https://github.com/leo-editor/leo-editor/pull/3922
.. _`PR #3979`: https://github.com/leo-editor/leo-editor/pull/3979


**Breaking changes to Leo's API**

- `PR #3828`_: Leo now requires PyQt6.
  Plugins that use earlier versions will break.
- `PR #3911`_: Leo's core no longer uses the free_layout or nested_splitter plugins.
  Scripts that rely on `c.free_layout` or the `NestedSplitter` class must be rewritten.
- `PR #3872`_: Improve how Leo searches for definitions:
  - Add `@bool prefer-nav-pane` setting.
  - This PR changes the signatures of `LeoFind.find_def` and `LeoFind.find_var`.
- `PR #3979`_: Change name of `save-file-as-zipped` command to `save-file-as-db`
  and change the name of the corresponding method.

**Other significant changes**

- `PR #3841`_: Add `g.traceUnique` and `g.traceUniqueClass` functions.
- `PR #3870`_: Leo's beautifier works faster.
- `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.
- `PR #3922`_: Improved the `restart-leo` command.
</t>
<t tx="ekr.20240724062137.1"></t>
<t tx="ekr.20240818070101.1">`pip install leo` does not install PyQt6-WebEngine on some Linux distributions.

The real problems are missing system libraries (`*.so` files). This missing files aren't exactly a Python/PyQt issue but have to be solved if a distro doesn't have them installed.

Follow the suggestion in the error message if the message tells how to install the missing libraries.

If these suggestions don't work try using  pip's `--user` and `--break-system-packages` options:

`python3 -m pip install --user --break-system-packages -r requirements.txt`.

The same will apply to any packages installed by pip, even pip install leo. --user is not needed unless you have admin privileges because pip in Linux goes to --user if installing to the primary locations fails. But if you include --user you don't get an error message about it, and if you have admin authority (e.g., you ran `sudo python -m pip`) your packages won't go into --user where you want them.
</t>
<t tx="ekr.20240828095959.1">.. Use the link-pr abbreviation to create these links.

.. _`PR #4033`: https://github.com/leo-editor/leo-editor/pull/4033
.. _`PR #4038`: https://github.com/leo-editor/leo-editor/pull/4038
.. _`PR #4047`: https://github.com/leo-editor/leo-editor/pull/4047
.. _`PR #4068`: https://github.com/leo-editor/leo-editor/pull/4068
.. _`PR #4071`: https://github.com/leo-editor/leo-editor/pull/4071
.. _`PR #4113`: https://github.com/leo-editor/leo-editor/pull/4113
.. _`PR #4119`: https://github.com/leo-editor/leo-editor/pull/4119
.. _`PR #4138`: https://github.com/leo-editor/leo-editor/pull/4138

Most important:

- `PR #4119`_ and `PR #4138`_: @jupytext makes it *easy* to work with Jupyter notebooks!
- `PR #4033`_: Add four new layouts and related code and commands.

Others:

- `PR #4038`_: Add reload-outline command.
- `PR #4068`_: Optionally run pylint when saving changed files.
- `PR #4071`_: Optionally run Leo's beautifier when saving changed files.

Retired features:

- `PR #4047`_: Delete add-editor command and all related code.
- `PR #4113`_: Retire ILeo, Leo's IPython bridge. It hasn't worked in years.
</t>
<t tx="ekr.20241027051721.1"></t>
<t tx="ekr.20241027051739.1">################################
Using Leo with Jupyter Notebooks
################################

.. |br| raw:: html

   &lt;br /&gt;

.. _`jupytext library`: https://jupytext.readthedocs.io/en/latest/
.. _`jupytext text notebook`: https://jupytext.readthedocs.io/en/latest/#text-notebooks

The chapter discusses ``@jupytext``, a new kind of ``@&lt;file&gt;`` node.

**Summary**

- Use ``@jupytext`` instead of ``@clean`` to manage ``.ipynb`` files.
- ``@jupytext`` nodes are thin wrappers around the `jupytext library`_.
- ``@jupytext`` nodes have the form: ``@jupytext x.ipynb``.
- When Leo reads an ``@jupytext`` node without children,
  Leo splits the text into Leo nodes, one cell per node.
- You can edit the ``@jupytext`` tree as usual: |br|
  Leo will remember those changes when you save an outline. |br|
  Leo will restore those changes when you reopen the outline.

.. contents:: Contents
   :depth: 2
   :local:</t>
<t tx="ekr.20241105100428.1">When reading an outline, Leo **populates** each ``@jupytext x.ipynb`` tree as follows:

1. Use the jupytext library to convert ``x.ipynb`` to `jupytext text notebook`_ text.
2. Use Leo's ``@clean`` update algorithm to propagate all changes in the ``x.ipynb`` file
   back to the corresponding node in the ``@jupytext`` tree.

*Notes:*

- **Notebook text** looks like Python but usually contains syntax errors,
  so Leo never checks notebook text for syntax errors.
- Notebook text *exists only within Leo.*
  You never need to synchronize ``x.ipynb`` with ``x.py``!
</t>
<t tx="ekr.20241105103314.1">Three settings control how ``@jupytext`` nodes work

**@int jupytext-max-headline-length = 60**

This setting sets the maximum length of child headlines.

Leo truncates long lines at word boundaries.

**@string jupytext-fmt = py:percent**

See https://jupytext.readthedocs.io/en/latest/config.html

**@data jupyter-prefix**

The default body text of this node is::

    # ---
    # jupyter:
    #   jupytext:
    #     formats: py:percent
    #     text_representation:
    #       extension: .py
    #       format_name: percent
    #       format_version: '1.3'
    #       jupytext_version: 1.16.4
    #   kernelspec:
    #     display_name: Python 3 (ipykernel)
    #     language: python
    #     name: python3
    # ---

    # %%
</t>
<t tx="ekr.20241107062843.1">Each time you save an outline, Leo uses the jupytext library to write each ``@jupytext`` tree back to the corresponding ``ipynb`` file.

- Leo *remembers all your changes* when you save an outline.
- Leo *restores those changes* when you reopen that outline.
</t>
<t tx="ekr.20241107063856.1">``@jupytext`` nodes must have the form::

    @jupytext &lt;path&gt;x.ipynb
    
The path is optional. It may be absolute or relative.
As usual, Leo resolves relative paths by appending the outline's directory.
    
After creating this node you can **populate** the ``@jupytext`` node in two ways:

1. [recommended] Execute the ``refresh-from-disk`` command *before* saving the outline.
   Leo will immediately populate the outline.
   
2. [also works] Save the outline. **Say "no"** when Leo asks whether you want to overwrite ``x.ipynb``!
   Leo will populate ``@jupytext x.ipynb`` when you reopen the outline.

**Populating the outline**

Populating the outline splits the incoming notebook text into child nodes, one node per Jupyter Notebook cell.

- Leo populates ``@jupytext`` only if the node contains no children.
- Otherwise, Leo uses the ``@clean`` update algorithm to propagate changes from
  ``x.ipynb`` to the ``@jupytext x.ipynb`` tree.
</t>
<t tx="ekr.20241107070438.1">``@jupytext`` nodes work just like ``@clean``.
You can add, delete, change and reorganize child nodes like any other outline tree.</t>
<t tx="ekr.20241107080948.1">.. _`HaveF`: https://github.com/HaveF
.. _`GoNB`: https://github.com/janpfeifer/gonb
.. _`jupytext library`: https://jupytext.readthedocs.io/en/latest/
.. _`Jupyter kernels`: https://docs.jupyter.org/en/stable/projects/kernels.html#kernels
.. _`go`: https://go.dev/
.. _`block-level syncing`: https://github.com/user-attachments/assets/e29d4b27-48d9-4006-ab94-d4e8276c2e79

This section contains comments by ``HaveF`` (edited by EKR) about ``@jupytext``.
The ``What People are Saying about Leo`` page contains the full version of these remarks.

Users of Jupyter Notebooks have a love-hate relationship with ``.ipynb`` files. Notebooks make it super easy to write code and see the results, but version control systems don't handle ``.json`` files very well. However, GitHub now offers comparison tools for ``.ipynb`` files.

That's where the `jupytext library`_ comes in. This library converts between ``.ipynb`` files to **pseudo-python** ``.py`` files. These files look like Python, but they usually contain syntax errors.

Furthermore, the jupytext library isn't limited to converting Python-based ``.ipynb`` files. The library can handle ``.ipynb`` files created with many other `Jupyter kernels`_ such as the `GoNB`_ kernel.

``@jupytext`` integrates Leo with Jupyter notebooks. You can store your notebooks directly in Leo and use Leo's powerful outlining capabilities to manage them. When you save, Leo converts them right back to ``.ipynb`` files. This is huge.

You can edit one notebook, save it, and boom—every notebook that shares that content is automatically updated. No fuss, no hassle. The workflow is completely flexible and you won’t find these features in any other editor.

And just to make things sweeter, Thomas Passin (another Leo contributor) added a rendering feature for jupytext files in Leo, so you can even see the rendered content directly within Leo.

**Summary**

Working with ``.ipynb`` files becomes a breeze with Leo.

Leo can handle any ``.ipynb`` file, regardless of the Jupyter kernel that created the file.
</t>
<t tx="ekr.20241107122714.1">Ever heard of the Lindy Effect? https://en.wikipedia.org/wiki/Lindy_effect

It says that the longer an idea or a technology sticks around, the longer it’s likely to stay. So if something has lasted for a long time already, chances are it's here for the long haul. And that's exactly what’s happening with Leo, under development for 20 years. You’d think it might be outdated by now, right? But nope—Leo still feels full of life, fresh, and even groundbreaking. Although it is not so well known.

So what exactly is Leo Editor? Well, it's hard to compare it to anything. If your first thought is that it's just another IDE or text editor, think again—it's way more than that. Leo describes itself as a

PIM: https://en.wikipedia.org/wiki/Personal_information_manager an
IDE https://en.wikipedia.org/wiki/Integrated_development_environment

and an outliner all rolled into one. It helps programmers, authors, and web designers organize their work like never before. In Leo, outline nodes can exist in multiple places, letting you organize data in all sorts of creative ways.

Now, outlining is definitely a core feature of Leo, but it’s just scratching the surface. Imagine an editor that has the ability to program itself. Sounds wild, right? If you’ve used VS Code, you know there are a ton of plugins to add extra features. But with Leo, adding features can be as simple as writing a script directly in the editor. No need to learn an entire plugin system—just control the nodes, write a Python script, run it, and voila! You've got a new feature.

If you've used Jupyter notebooks, you might have a love-hate relationship with `.ipynb` files. They make it super easy to write code and see the results, but the JSON format can be tough to manage in version control (although GitHub does now offer some comparison tools for `.ipynb` files). That's where jupytext comes in—it lets you convert `.ipynb` files to a more version-control-friendly .py file format, and vice versa. Jupyter supports kernels beyond just Python, which means jupytext isn't limited to converting Python-based `.ipynb` files to .py. It also supports other kernels, such as

Go with GoNB: https://github.com/janpfeifer/gonb

and many others that I won't go into here. Maybe you don't like Jupyter either, thinking it's not suitable for serious software development. Honestly, I'm not here to argue that—it really depends on your context. But there's no denying that it's a core tool in data science. If you haven't seen Jeremy Howard's (FastAI) video, I highly recommend checking it out:

Someone told me not to use notebooks for 'serious' software development!
https://nbdev.fast.ai/getting_started.html#q-someone-told-me-not-to-use-notebooks-for-serious-software-development

So far, so good, right?

Then one day, Edward K. Ream found a brilliant way to integrate jupytext with Leo. Essentially, you can store the text content (jupytext's output) of your notebooks directly in Leo, use Leo's powerful outlining capabilities to manage them, and when you save, Leo converts it right back to an `.ipynb` file.

And this is huge. Imagine having a Jupyter notebook, let's call it A, that you're using for some kind of step-by-step workflow (in this case, let's say a machine learning example)—gathering data, cleaning data, training a model, and validating results. Now imagine you have another notebook, B, which follows a similar flow but isn't quite the same. The part where you clean the data (step 2) is identical. Without Leo, you'd need to copy all the relevant cells from A to B and hope nothing changes later. But if you update A, you also need to go back and manually update B. It’s a headache. Now imagine you have five similar notebooks. Ouch.

With Leo, this becomes a breeze. You make an edit to the cleaning part of one notebook, save it, and boom—every notebook that shares that content is automatically updated. Leo’s nodes can be cloned and reused—no fuss, no hassle. **That's block-level syncing**, and it's completely flexible. Honestly, it’s something you just won’t find in any other editor. (Btw, If you do this in the context of a Version Control Systems (VCS) like git, you will feel very safe and confident.)

Screen shot: https://github.com/user-attachments/assets/e29d4b27-48d9-4006-ab94-d4e8276c2e79)

You might say, "But wait, isn't it better to abstract repeated code into reusable modules?" Sure, in an ideal world, everything should be neatly abstracted. But when you’re in the early stages of experimentation, abstraction can feel like premature optimization—it just adds overhead. With Leo, you can reuse content with zero effort or cost and feel free to abstract later.

For example, in the screenshot above, `exp_A.ipynb` and `exp_B.ipynb` share some common code by coping in jupyter lab, but we are not sure whether we need to abstract this part into another module (there may be more files that need this part later, but we are not sure for now). When we are not sure whether to abstract this part of the code, let Leo be responsible for synchronizing the code in the two ipynb files(we still use jupyter lab to write code and conduct experiments, but use Leo's `@jupytext node` to organize all related ipynb files). Once we decide to abstract this part, we only need to change the code in one file directly (for example, this part is reduced to a simple function call), and then use Leo to synchronize the changes to all ipynb files.

You can understand it this way: Leo uses the characteristics of jupytext to achieve very powerful collaboration between ipynb files. Leo did not change the workflow we were used to, we just used its outline feature to enhance our process, manipulating sections between multiple ipynb files at once.

And just to make things sweeter, Thomas Passin (another Leo contributor) added a rendering feature for jupytext files in Leo, so you can even see the rendered content directly within the tool.

So if you're using Jupyter, you should definitely give jupytext a try. If you’re using jupytext, try out Leo's `@jupytext` nodes. Even if you’re not using Jupyter, I’d say give Leo a shot. Sure, IDEs come and go—VS Code, JetBrains, Vim, you name it—but there’s really nothing quite like Leo in some aspects. I’m not suggesting you replace those editors with Leo, but rather, consider using Leo alongside them. It’s genuinely unique in this world. You can even try LeoJS, a vs-code plugin

LeoJS: https://boltex.github.io/leojs/

Yes, Leo does have a bit of a learning curve, but mastering the basics is easier than you’d think, and you’ll quickly be leveraging its outlining power. It’s the kind of investment that pays off big time. Leo is definitely an underrated gem.

Big thanks to Edward, Thomas, Félix, aka boltex (the author of LeoJS and leointeg), and all the other contributors—you guys are truly amazing, and Leo is living proof of that!</t>
<t tx="ekr.20241112030815.1">.. _`QSyntaxHighlighter`:   https://doc.qt.io/qt-6/qsyntaxhighlighter.html

Are you sure you want to read this appendix? It is intended *only* for Leo's core developers.

This appendix contains the theory of operation for the ``JEditColorizer`` (**jedit**) class in ``leoColorizer.py``. Unless qualified, *all methods are members of the jedit class*.

**Executive summary**

Use the ``--trace=coloring`` to see the colorizer in action.

The jedit class collaborates with the **qsh**, a singleton instance of the `QSyntaxHighlighter`_ class.

This collaboration allows the qsh to *minimize* the calls to ``jedit.redraw``. The qsh calls ``redraw(s)`` *only* if line ``s`` could possibly need recoloring.

Leo's core *must never* call ``redraw``! These calls must happen automatically. Calling ``redraw`` from Leo's core could cause hard-to-find bugs!

**States** allow the jedit class to handle constructs like strings or comments that continue from one line to another.

**Mode files**, python files in the ``leo/modes`` directory, tell the jedit class how to colorize specific languages.

**Pattern matchers** do the actual syntax coloring.
</t>
<t tx="ekr.20241112044810.1">The qsh can (and will) call ``recolor(s)`` where s is *out-of-sequence* with the preceding call. For example, the following snippet is typical in ``@language jupytext`` nodes:

.. code-block:: python

    # %% (like @language python)

    def spam():

    # %% [markdown] (like @language md)

    # Section 1
    It was the best of times; it was the worst of times.

The user can click (or cut or paste) anywhere in this text. The qsh will then call ``recolor(s)`` starting with the first changed line.

*There is no necessary relationship between* ``s`` *and the line that* ``recolor`` *last saw*!</t>
<t tx="ekr.20241112064750.1">Several settings control Leo's syntax colorer.

You may specify default fonts and colors.
You may also specify fonts and colors on a language-by-language basis.</t>
<t tx="ekr.20241112094914.1">The ``JEditColorizer`` class consists of **drivers**, **pattern matchers** and various **helper utilities**.

**Drivers**

The ``redraw`` and ``mainLoop`` methods are the interface between the qsh and the methods of the jedit class. 

``qsh.rehighlight`` calls ``redraw(s)`` to colorize a *single* line ``s``. After initing the **initial state**, ``redraw`` calls ``mainLoop``.

Leo's core *must never* call ``redraw``! Doing so could cause hard-to-find bugs.

``redraw(s)`` calls ``mainLoop(s)`` to do the actual syntax coloring.
 
``mainLoop(s)`` calls **rule functions** (defined in mode files).

Rule functions delegate their work to exactly one **pattern matcher** (described next). In other words, *pattern matchers are callbacks.*

**Pattern matchers**

Pattern matchers form the bulk of the jedit class. Each pattern matcher does the following:

- Examines the string ``s[i:]``, where s is the argument to ``mainLoop(s)``.
- Updates the **ending state** for successful matches.
- Returns an integer **return code**::

    -1: complete failure: mainLoop returns
     0: partial failure: mainLoop tries to match other rules
    &gt;0: success: mainLoop increments i by n and tries to match other rules
</t>
<t tx="ekr.20241112111533.1">States allow the colorizer to handle out-of-order calls to ``recolor``.

The colorizer collaborates the qsh in *only one way*, namely by calling ``self.highlighter.setCurrentBlockState(n)``, where ``n`` is an *integer* state number.

Internally, the colorizer uses *string* states. The colorizer's **state utilities** handle the conversion between integer and string representations.

States represent, for a *particular* line:

- Which ``@language`` directive is in effect.
- Which coloring directive (``@killcolor``, ``@color``, ``@nocolor``, etc.) is in effect.
- Whether the coloring for the line *continues* to the next line.
  For example, Python docstrings may span multiple lines.

A fine point: The state utilities ensure that all integer state numbers are unique and refer to the proper language in effect. For example, if a node contains multiple ``@language`` directives, the default states of the two languages must have different state numbers!

The colorizer keeps track of states as follows:

``recolor`` first computes the line's **initial state** from the **ending state** of the *previous* line. By default, the initial state becomes the ending state of *current* state.

Pattern matchers usually leave the ending state unchanged.

If a pattern matcher matches an ``@language`` or coloring directive, the matcher creates (indirectly, via the state utilities) a new state representing the directive. This is the easy case.

If a pattern matcher matches syntax that continues to the next line, the pattern matcher creates a **restarter matcher** by calling ``setRestart``. The restarter matchers are essentially closures, bindings of the pattern matcher *and all of its kwargs*. The details are hairy, but the coding pattern is the same for all cases. See the source code for details.
</t>
<t tx="ekr.20241126091524.1">Leo https://leo-editor.github.io/leo-editor/ 6.8.3 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.8.3 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.8.3+)
- [6.8.3 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.8.3)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)</t>
<t tx="ekr.20241126091611.1">.. Use the link-pr abbreviation to create these links.

.. _`Theory of Operation`: https://leo-editor.github.io/leo-editor/appendices.html#leo-s-colorizer-theory-of-operation
.. _`info issue`: https://github.com/leo-editor/leo-editor/issues/4158

.. jedit PRs
.. _`4147`: https://github.com/leo-editor/leo-editor/pull/4147
.. _`4173`: https://github.com/leo-editor/leo-editor/pull/4173
.. _`4182`: https://github.com/leo-editor/leo-editor/pull/4182
.. _`4183`: https://github.com/leo-editor/leo-editor/pull/4183
.. _`4188`: https://github.com/leo-editor/leo-editor/pull/4188

.. @language PRs
.. _`PR #4177`: https://github.com/leo-editor/leo-editor/pull/4177
.. _`PR #4178`: https://github.com/leo-editor/leo-editor/pull/4178
.. _`PR #4198`: https://github.com/leo-editor/leo-editor/pull/4198
.. _`PR #4203`: https://github.com/leo-editor/leo-editor/pull/4203

.. Leo's website.
.. _`PR #4207`: https://github.com/leo-editor/leo-editor/pull/4207
.. _`PR #4209`: https://github.com/leo-editor/leo-editor/pull/4209

- PRs `4147`_, `4173`_, `4182`_, `4183`_, and `4188`_: Improve Leo's colorizer.
- Rewrite the colorizer's `Theory of Operation`_ on Leo's website.
- Rewrite the colorizer's `info issue`_.
- `PR #4177`_ and `PR #4178`_: Add ``@language openscad``.
- `PR #4198`_: Add ``@language glsl``.
- `PR #4203`_: Add ``@language vue``.
- `PR #4207`_: Upgrade Leo's website using the latest version of Sphinx.
- `PR #4209`_: Improve the ``@button sphinx-build`` script in ``LeoDocs.leo``.
</t>
<t tx="ekr.20241206192042.1">gnx: ekr.20240110034324.27
unl: Table of contents
gnx: ekr.20240110034324.28
unl: The grand overview
gnx: ekr.20240110034324.29
unl: The new importers vs. the old
gnx: ekr.20240110034324.30
unl: The Importer class
gnx: ekr.20240110034324.31
unl: The Importer class--&gt;i.gen lines &amp; helpers
gnx: ekr.20240110034324.32
unl: The Importer class--&gt;The line-oriented API
gnx: ekr.20240110034324.33
unl: The Importer class--&gt;Indentation
gnx: ekr.20240110034324.34
unl: The ScanState classes
gnx: ekr.20240110034324.35
unl: The ScanState classes--&gt;ScanState.context
gnx: ekr.20240110034324.36
unl: The ScanState classes--&gt;ScanState.level()
gnx: ekr.20240110034324.37
unl: The ScanState classes--&gt;ScanState protocols
gnx: ekr.20240110034324.38
unl: Using @button make-importer
gnx: ekr.20240110034324.39
unl: Notes
gnx: ekr.20240110034324.40
unl: Notes--&gt;Recognizing multi-line patterns
gnx: ekr.20240110034324.41
unl: Notes--&gt;The python importer must count brackets
gnx: ekr.20240110034324.42
unl: Notes--&gt;Scanning strings and comments
gnx: ekr.20240110034324.43
unl: Conclusion
</t>
<t tx="ekr.20250317133518.1">@language rest

All clones of the same node share the same VNode, and thus they all have exactly the same headline, body text, and children. Therefore, changing p.b or p.h, or adding a child to one clone modifies the underlying VNode, reflected instantly in all other clones.

However, Leo's users often request a vague enhancement informally known as "half clones." We can make this ill-defined notion precise by saying that we often want to treat clones differently depending on **context**, the **Position** of that clone within the entire outline.

**Using context in scripts**

Scripts are not limited to using the data in `p.v`, that is, `p.b`, `p.h`, `p.u`, or `p.gnx`.  Scripts may access:

- Any ancestor or descendant of `p`.
- Any data accessible from `c`, that is, *all* the data in the outline, including cached data!

Scripts can define their own conventions, including:

- Special-format comments embedded in `p.b`,
- Special-purpose conventions for headlines.

**Changing text depending on context**

.. code-block:: python

    def in_context(p: Position, context: str) -&gt; bool:
        return any(z.h == context for z in p.parents())
 
    for p in c.all_positions():
        if in_context(p, 'FAQ'):
            handle_faq_node(p)
        elif in_context(p, 'Reference'):
            handle_ref_node(p)

**Simulating half clones**

Scripts may simulate half clones by ignoring children (of clones) in some contexts and processing those *same* children in other contexts. That's all there is to it!
</t>
<t tx="ekr.20250422050813.2">.. Use the link-pr abbreviation to create these links.

.. _`PR #4252`: https://github.com/leo-editor/leo-editor/pull/4252
.. _`PR #4253`: https://github.com/leo-editor/leo-editor/pull/4253
.. _`PR #4261`: https://github.com/leo-editor/leo-editor/pull/4261
.. _`PR #4275`: https://github.com/leo-editor/leo-editor/pull/4275
.. _`PR #4277`: https://github.com/leo-editor/leo-editor/pull/4277
.. _`PR #4278`: https://github.com/leo-editor/leo-editor/pull/4278
.. _`PR #4279`: https://github.com/leo-editor/leo-editor/pull/4279
.. _`PR #4281`: https://github.com/leo-editor/leo-editor/pull/4281
.. _`PR #4287`: https://github.com/leo-editor/leo-editor/pull/4287
.. _`PR #4296`: https://github.com/leo-editor/leo-editor/pull/4296
.. _`PR #4303`: https://github.com/leo-editor/leo-editor/pull/4303
.. _`PR #4316`: https://github.com/leo-editor/leo-editor/pull/4316
.. _`PR #4314`: https://github.com/leo-editor/leo-editor/pull/4314
.. _`PR #4320`: https://github.com/leo-editor/leo-editor/pull/4320
.. _`PR #4322`: https://github.com/leo-editor/leo-editor/pull/4322
.. _`PR #4324`: https://github.com/leo-editor/leo-editor/pull/4324
.. _`PR #4351`: https://github.com/leo-editor/leo-editor/pull/4351

- `PR #4252`_: Add the `show-buttons-and-at-commands` command.
- `PR #4253`_: Support mathjax in VR plugin.
- `PR #4261`_: Improve syntax coloring.
- `PR #4275`_, `PR #4278`_, `PR #4279`_: Improve syntax coloring for Rust.
- `PR #4277`_: Fix all remaining bugs in Rust importer.
- `PR #4281`_: Allow rest comments to be colored differently from @language rest
- `PR #4287`_: All backslashes in find strings.
- `PR #4296`_: Add the `find-source-for-command` command.
- `PR #4303`_: Support `@language typst`.
- `PR #4314`_: Scripts (including `@command` and `@button` scripts) may now return a value.
- `PR #4316`_: Remove the `join-leo-irc` command.

**Significant code cleanups**

- `PR #4320`_: Add best possibly mypy annotations for Leo's core and official plugins.
- `PR #4322`_: Remove last significant hangnails in Leo's code.
- `PR #4324`_: 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.

**Breaking change**

`PR #4281`_: create a subtle **breaking change** to colorizing settings.

To maintain compatibility with previous versions of Leo, define `#00aa00` as the color for all the following settings::

    @color rest_comments.literal1: The default color.
    @color rest_comments.literal2: The color for numbers.
    @color rest_comments.literal3: The color for italics.
    @color rest_comments.literal4: The color for bold.
    
- `PR #4351`_: Add the `beautify-script` command.
               Also, `execute-script` beautifies `c.p`'s tree if
               `@bool beautify-python-code-on-write = True`.

</t>
<t tx="ekr.20250422050813.3">Leo https://leo-editor.github.io/leo-editor/ 6.8.4 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.8.4 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.8.4+)
- [6.8.4 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.8.4)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)</t>
<t tx="ekr.20250422050948.1"></t>
<t tx="ekr.20250626165415.1">Leo https://leo-editor.github.io/leo-editor/ 6.8.5 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.8.5 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.8.5+)
- [6.8.5 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.8.5)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)</t>
<t tx="ekr.20250626165619.1">.. Use the link-pr abbreviation to create these links.
.. _`6.8.5 Issues`: https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.8.5+
.. _`6.8.5 Pull Requests`: https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.8.5

- Change the signatures of the `k.registerCommand` and `k.registerCommandShortcut` methods.

This release consists entirely of code cleanups and minor bug fixes:
  
- `6.8.5 Issues`_
- `6.8.5 Pull Requests`_
</t>
<t tx="ekr.20250727055239.1">Leo 6.8.0 (July 3, 2024):

A new framework for layouts replaces the free_layout and nested_splitter plugins.
The gui "Easter Egg" is no more.

Jul 27, 2024: Félix releases LeoJS 1.0, with this `leo-js-announcement
&lt;https://groups.google.com/g/leo-editor/c/nNSaJTMAB3s/m/Df1roWA5AgAJ&gt;`_
along with a `scripting samples repository
&lt;https://github.com/boltex/scripting-samples-leojs?tab=readme-ov-file#how-to-use-on-the-web-in-your-browser&gt;`_
and a `dedicated website &lt;https://boltex.github.io/leojs/&gt;`_.

LeoJS is a JavaScript implementation of Leo's original Python source packaged as a VSCode extension. It is also usable with VSCode for the web.

Leo 6.8.2 (November 8, 2024):

@jupytext uses the jupytext library https://jupytext.readthedocs.io/en/latest/ to handle Jupyter Notebooks seemlessly.

Leo 6.8.6: (August 1, 2025):

- @leo and related commands makes it easy to use Leo on huge repositories.
- LeoInteg (and leoserver.py) supports websockets.

Mar 22, 2026: Félix releases `LeoWeb &lt;https://boltex.github.io/leo-web/&gt;`_, a browser-based version of the Leo Editor. This project is a TypeScript implementation, scriptable in either Javascript or Typescript, that uses the browser's File System API for local file access.
</t>
<t tx="ekr.20250728123954.1">Leo https://leo-editor.github.io/leo-editor/ 6.8.6.1 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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 &lt;path&gt;;` 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.8.6 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.8.6+)
- [6.8.6.1 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.8.6.1+)
- [6.8.6 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.8.6)
- [6.8.6.1 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.8.6.1)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)
</t>
<t tx="ekr.20250728124612.1">.. Use the link-pr abbreviation to create these links.
.. _`PR #4386`: https://github.com/leo-editor/leo-editor/pull/4386
.. _`PR #4389`: https://github.com/leo-editor/leo-editor/pull/4389
.. _`PR #4395`: https://github.com/leo-editor/leo-editor/pull/4395
.. _`PR #4391`: https://github.com/leo-editor/leo-editor/pull/4391
.. _`PR #4405`: https://github.com/leo-editor/leo-editor/pull/4405

**Leo 6.8.6**

- `PR #4386`_ and `PR #4395`_: Major improvements for `@clean`.
   See https://leo-editor.github.io/leo-editor/directives.html#leo-directives
- `PR #4389`_: Support websockets in Leo's server and LeoInteg.
- `PR #4391`_: Add a theme file for SwotMoknokai.

**Leo 6.8.6.1**

- `PR #4405`_: Fix a critical bug present in Leo 6.8.6.</t>
<t tx="ekr.20250729083112.1">.. _`Rust's compiler repo`: https://github.com/rust-lang/rust/tree/master/compiler

``@leo`` directives have the form ``@leo &lt;path&gt;`` where ``path`` is a path (absolute
or relative) to another Leo outline. To move between outlines, just select
an ``@leo`` node and execute the ``open-at-leo-file`` command!

``@leo`` directives help split a single (too large) outline in a small **top-level outline** and various **sub-outlines**.

For example, using a single outline to manage `Rust's compiler repo`_  causes performance problems.
Managing each the 70+ sub-directories with a smaller sub-outline solves these problems.

A new script helper, **c.makeLinkLeoFiles**, creates the sub-outlines automatically.
For example, here is the script I use to create dozens of sub-outlines in my local clone of Rust's compiler.

.. code-block:: python

    c.makeLinkLeoFiles(
        extensions=['.rs'],
        top_directory=r'C:\Repos\ekr-fork-rust\compiler',
    )

This script creates the ``compiler_links.leo`` outline in the ``compiler``
directory. In addition, for each direct sub-directory (say x) of the
top-level directory, the script creates an outline called ``x_links.leo``.

The script is essential for large repos. The top-level ``compiler`` directory
contains more than 70 sub-directories!

The top-level outline (``compiler_links.leo``) contains ``@leo`` directives for all the sub-outline::

  @leo rustc/rustc.leo
  @leo rustc_abi/rustc_abi.leo
  @leo rustc_arena/rustc_arena.leo
  And dozens of others.
  
Note that all paths above are relative to ``compiler_links.leo``.
  
Each sub-outline contains:

- One ``@leo`` node (the back link) pointing to the top-level outline.
- One ``@clean`` node for each ``.rs`` file in the subdirectory and *all descendant directories*.
</t>
<t tx="ekr.20250830050853.1">Leo https://leo-editor.github.io/leo-editor/ 6.8.7 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.8.7 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.8.7+)
- [6.8.7 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.8.7)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)
</t>
<t tx="ekr.20250830050946.1">.. Use the link-pr abbreviation to create these links.
.. _`PR #4403`: https://github.com/leo-editor/leo-editor/pull/4403
.. _`PR #4412`: https://github.com/leo-editor/leo-editor/pull/4412
.. _`PR #4418`: https://github.com/leo-editor/leo-editor/pull/4418
.. _`PR #4421`: https://github.com/leo-editor/leo-editor/pull/4421
.. _`PR #4423`: https://github.com/leo-editor/leo-editor/pull/4423
.. _`PR #4430`: https://github.com/leo-editor/leo-editor/pull/4430
.. _`PR #4444`: https://github.com/leo-editor/leo-editor/pull/4444
.. _`PR #4456`: https://github.com/leo-editor/leo-editor/pull/4456
.. _`PR #4484`: https://github.com/leo-editor/leo-editor/pull/4484

- `PR #4403`_: Require python 3.10 or above. Add support for Python 3.14.
- `PR #4412`_: Greatly improve Leo's `parse-body` command.
- `PR #4418`_: Don't pollute uAs with the `_mod_time` command.
- `PR #4421`_: Fix several beautifier bugs.
- `PR #4423`_: A milestone: Leo's beautifiers import `@clean` files perfectly.
- `PR #4430`_: Fix bugs in Leo's colorizer.
- `PR #4444`_: Fix a crasher in Leo's undo logic.
- `PR #4456`_: Added leo_to_html_outline_viewer.py plugin.

</t>
<t tx="ekr.20251204122149.1">.. Use the link-pr abbreviation to create these links.
.. _`PR #4464`: https://github.com/leo-editor/leo-editor/pull/4464
.. _`PR #4467`: https://github.com/leo-editor/leo-editor/pull/4467
.. _`PR #4477`: https://github.com/leo-editor/leo-editor/pull/4477
.. _`PR #4484`: https://github.com/leo-editor/leo-editor/pull/4484
.. _`PR #4486`: https://github.com/leo-editor/leo-editor/pull/4486
.. _`PR #4487`: https://github.com/leo-editor/leo-editor/pull/4487
.. _`PR #4490`: https://github.com/leo-editor/leo-editor/pull/4490
.. _`PR #4498`: https://github.com/leo-editor/leo-editor/pull/4498
.. _`PR #4502`: https://github.com/leo-editor/leo-editor/pull/4502
.. _`PR #4503`: https://github.com/leo-editor/leo-editor/pull/4503
.. _`PR #4506`: https://github.com/leo-editor/leo-editor/pull/4506
.. _`PR #4531`: https://github.com/leo-editor/leo-editor/pull/4531
.. _`PR #4551`: https://github.com/leo-editor/leo-editor/pull/4551
.. _`PR #4571`: https://github.com/leo-editor/leo-editor/pull/4571
.. _`PR #4575`: https://github.com/leo-editor/leo-editor/pull/4575
.. _`PR #4588`: https://github.com/leo-editor/leo-editor/pull/4588

- `PR #4464`_ and `PR #4588`_: Fix abbreviation bugs.
- `PR #4467`_: Remove support for leoflexx and --gui=browser.
- `PR #4477`_: Fix colorizer bug.
- `PR #4484`_: Add check_leo script.
- `PR #4486`_: Improve the flatten-outline-to-node command.
- `PR #4490`_, Add support for ruff format and retire Leo's legacy beautifier.
  This PR summarizes several other PRs relating to this project.
- `PR #4498`_: Fix bug: the external files controller leaves ``c.p`` unchanged.
- `PR #4487`_ and `PR #4551`_: Reformat Leo using ruff format.
- `PR #4503`_ and `PR #4506`_: Add ``gdc.summary_diff_two_revs`` script helper.
- `PR #4531`_: Add ``dump-last-colorizer-trace`` command.
- `PR #4571`_: Add setting to bypass file-update dialogs.
- `PR #4575`_: Preserve indentation when adding comments.

**Add settings for ruff format**

The defaults are shown below:

- Add ``@int black-line-length = None``
- Add ``@string black-toml = None``

**Retire settings for Leo's legacy beautifier**

- Retire ``@bool beautify-allow-joined-strings``
- Retire ``@bool indent-added-comments``
- Retire ``@int beautify-max-join-line-length``
- Retire ``@int beautify-max-split-line-length``

**New settings**

- Add ``@bool raise-file-update-dialogs = False``

**New commands**

- Add ``dump-last-colorizer-trace`` command.

**Minor breaking API change**

- Retire two Commands methods: ``c.goToNextHistory`` and ``c.goToPrevHistory``.
  Use ``c.goNextVisitedNode`` and ``c.goPrevVisitedNode`` instead.

</t>
<t tx="ekr.20251204122305.1">Leo https://leo-editor.github.io/leo-editor/ 6.8.8 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.8.8 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.8.8+)
- [6.8.8 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.8.8)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)
</t>
<t tx="ekr.20260531063735.1">Leo https://leo-editor.github.io/leo-editor/ 6.8.9 is now available on [GitHub](https://github.com/leo-editor/leo-editor/releases) 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**

- [Install Leo](https://leo-editor.github.io/leo-editor/installing.html)
- [6.8.9 Issues](https://github.com/leo-editor/leo-editor/issues?q=is%3Aissue+milestone%3A6.8.9+)
- [6.8.9 Pull Requests](https://github.com/leo-editor/leo-editor/pulls?q=is%3Apr+milestone%3A6.8.9)
- [Documentation](https://leo-editor.github.io/leo-editor/leo_toc.html)
- [Tutorials](https://leo-editor.github.io/leo-editor/tutorial.html)
- [Video tutorials](https://leo-editor.github.io/leo-editor/screencasts.html)
- [Forum](https://groups.google.com/group/leo-editor)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](https://leo-editor.github.io/leo-editor/testimonials.html)
- [More links](https://leo-editor.github.io/leo-editor/leoLinks.html)
</t>
<t tx="ekr.20260531063902.1">.. Use the link-pr abbreviation to create these links.
.. _`PR #4576`: https://github.com/leo-editor/leo-editor/pull/4576
.. _`PR #4587`: https://github.com/leo-editor/leo-editor/pull/4587
.. _`PR #4607`: https://github.com/leo-editor/leo-editor/pull/4607
.. _`PR #4611`: https://github.com/leo-editor/leo-editor/pull/4611
.. _`PR #4615`: https://github.com/leo-editor/leo-editor/pull/4615
.. _`PR #4617`: https://github.com/leo-editor/leo-editor/pull/4617
.. _`PR #4618`: https://github.com/leo-editor/leo-editor/pull/4618
.. _`PR #4619`: https://github.com/leo-editor/leo-editor/pull/4619
.. _`PR #4631`: https://github.com/leo-editor/leo-editor/pull/4631
.. _`PR #4637`: https://github.com/leo-editor/leo-editor/pull/4637
.. _`PR #4639`: https://github.com/leo-editor/leo-editor/pull/4639
.. _`PR #4654`: https://github.com/leo-editor/leo-editor/pull/4654
.. _`PR #4660`: https://github.com/leo-editor/leo-editor/pull/4660
.. _`PR #4675`: https://github.com/leo-editor/leo-editor/pull/4675
.. _`PR #4678`: https://github.com/leo-editor/leo-editor/pull/4678
.. _`PR #4695`: https://github.com/leo-editor/leo-editor/pull/4695
.. _`PR #4698`: https://github.com/leo-editor/leo-editor/pull/4698

**Enhancements**

- `PR #4587`_ and `PR #4611`_: Improve java importer.
- `PR #4654`_: Add support for ``@language pug``.
- `PR #4660`_: Handle backslashes properly in Find/Change text.
- `PR #4675`_: Replace the ``,,`` Easter Egg with Leo's Find command.
- `PR #4695`_: Enhance security for Leo's server.
- `PR #4698`_: Support Find/Change history.

**Retired settings**

- ``@bool auto-scroll-find-tab``
- ``@bool cursor-stay-on-paste``
- ``@string abbreviations-next-placeholder``

**Performance enhancements**

- `PR #4615`_, `PR #4617`_, `PR #4618`_, `PR #4619`_: Significant performance improvements.

**Code Improvements**

- PR `PR #4576`_: More concrete type annotations.
- PR `PR #4607`_: Improve formatting of unit tests.
- PR `PR #4631`_, `PR #4637`_, `PR #4639`_:  Remove the confusion between wrappers and widgets.
- PR `PR #4678`_: Remove unnecessary ``type-ignore`` suppressions.
</t>
<t tx="ekr.20260605070320.1">@language python
"""
Run this script from the `gh-pages` branch.

1. Generate intermediate files for all headlines in the table.
2. Run `make html` from the leo/doc/html directory.

After running this script, copy files
- from leo/doc/html/_build/html to leo-editor/docs
- from leo/doc/html/_build/html/_static to leo/editor-docs/_static
"""

@language python

g.cls()
g.cls()

from datetime import datetime
import glob
import os
import re
import shutil
from sphinx import __version__ as sphinx_version

trace = False
headlines = [
    "Leo's Documentation"
]

join = os.path.join
norm = os.path.normpath

def finalize(s):
    return g.os_path_finalize(norm(s))

@others  # define helpers

if c.isChanged():  # Save this file initially.
    c.save()
run()
if c.isChanged():  # Save this file again if we have patched the home page.
    c.save()
</t>
<t tx="ekr.20260605070320.2">def copy_files(from_directory: str, to_directory: str) -&gt; None:
    """Copy *all* html files from `from_directory` to `to_directory`."""
    if not os.path.exists(to_directory):
        print(f"Directory not found: {to_directory!r}")
        return
    files = glob.glob(f"{from_directory}{os.sep}*")
    files = [z for z in files if os.path.isfile(z)]
    # Announce.
    written = 0
    for f in files:
        try:
            fn = finalize(f)
            shutil.copy2(fn, to_directory)
            written += 1
        except Exception as e:
            print(f"Not Copied {e} {fn}")
    print(f"Copied {written:3} files from {from_directory:55} to {to_directory}")
</t>
<t tx="ekr.20260605070320.3">def copy_recursive(from_directory: str, to_directory: str) -&gt; None:

    if os.path.exists(to_directory):
        val = shutil.copytree(from_directory, to_directory, dirs_exist_ok=True)
        g.trace(val)
    else:
        print(f"Directory not found: {to_directory!r}")
</t>
<t tx="ekr.20260605070320.4">conf_version_pat = re.compile(r"version\s*= '([0-9]+\.[0-9]+\.[0-9]+)'")

def get_leo_version():
    """Return the version in conf.py"""    
    h = '@edit html/conf.py'
    p = g.findNodeAnywhere(c, h)
    assert p, h
    for m in conf_version_pat.finditer(p.b):
        version = m.group(1)
        if version:
            return version
    assert False, 'no version in conf.py'
</t>
<t tx="ekr.20260605070320.5">def git_status():
    """Report git status"""
    leo_path = finalize(join(g.app.loadDir, '..', '..'))
    os.chdir(leo_path)
    g.execute_shell_commands([
        'git status',
    ])

</t>
<t tx="ekr.20260605070320.6">def make_html(html_path):
    """
    Run the `make html` command in the leo/doc/html directory.
    """
    cwd = finalize(os.getcwd())
    assert cwd.lower() == html_path.lower(), (cwd, html_path)
    
    if 0:  # `make clean` is good for testing.
        g.execute_shell_commands(['make clean'])
        
    if 1:  # Simplest, safest.
        g.execute_shell_commands(['make html'])
    elif 0:  # Works. Arguments are from the MakeFile.
        g.execute_shell_commands([
            'python -m sphinx -b html -d _build/doctrees . _build/html',
        ])
    else:  # Fastest, but depends on sphinx's API.
        from sphinx.cmd import build
        args = '-b html -d _build/doctrees . _build/html'
        argv = args.split(' ')
        build.build_main(argv)</t>
<t tx="ekr.20260605070320.7">date_pat = re.compile(r'^(.*?)(Last updated on\s*)(.+)(.*)$')
leo_version_pat = re.compile(r'^(.*?)Leo\s*([0-9]+\.[0-9]+\.[0-9]+)(.*)$')
sphinx_version_pat = re.compile(r'^(.*?)Sphinx\s*([0-9]+\.[0-9]+\.[0-9]+)(.*)$')

def patch_home_page():
    """
    Update (in *this*file) the "Last updated" and "Created using" fields in
    the node `@file ../../docs/index.html` or its descendants.
    """
    today = datetime.today()
    date = datetime.date(today).strftime("%B %d, %Y")  # Same as conf.py.
    leo_version = get_leo_version()

    def date_repl(m: re.Match) -&gt; str:
        s = m.group(0)
        i, j = m.start(3), m.end(3)
        return s[:i] + date + s[j:]
    
    def leo_version_repl(m: re.Match) -&gt; str:
        s = m.group(0)
        i, j = m.start(2), m.end(2)
        return s[:i] + leo_version + s[j:]

    def sphinx_version_repl(m: re.Match) -&gt; str:
        s = m.group(0)
        i, j = m.start(2), m.end(2)
        return s[:i] + sphinx_version + s[j:]

    table = (
        (date_pat, date_repl),
        (leo_version_pat, leo_version_repl),
        (sphinx_version_pat, sphinx_version_repl),
    )
    h = '@file ../../docs/index.html'
    home_page = g.findNodeAnywhere(c, h)
    if not home_page:
        g.trace(f"Not found: {h!r}")
        return
    any_changed = False
    for p in home_page.self_and_subtree():
        old_lines = g.splitLines(p.b)
        new_lines = old_lines[:]
        for i, old_line in enumerate(old_lines):
            new_line = old_line
            for pattern, repl in table:
                new_line = re.sub(pattern, repl, new_line)
                if new_line != old_lines[i]:
                    print('')
                    print(f"Changed line {i:&lt;2} of {p.h}")
                    print(new_line.rstrip())
                    new_lines[i] = old_lines[i] = new_line
                    changed = True
        if new_lines != g.splitLines(p.b):
            p.b = ''.join(new_lines)
            print('')
            c.setChanged()
            home_page.setDirty()
            any_changed = True</t>
<t tx="ekr.20260605070320.8">@language python

def run():
    """
    Make all html files using sphinx and copy the results to leo-editor/docs.
    """
    # Step 1. Compute all paths.

    # Base paths. Not finalized.
    docs = join(g.app.loadDir, '..', '..', 'docs')
    doc = join(g.app.loadDir, '..', 'doc')
    
    # We will cd to the html path.
    html_path = finalize(join(doc, 'html'))

    # We will copy all files from build_path to docs_path.
    build_path = finalize(join(doc, 'html', '_build', 'html'))
    docs_path = finalize(docs)
    
    # We will copy the static folder from doc/html/_build/html/_static to docs.
    # We *must* use the _build-related path to update sphinx .css files.
    docs_static_path = finalize(join(docs, '_static'))
    doc_static_path = finalize(join(doc, 'html', '_build', 'html', '_static' ))
    
    doc_slides_path = finalize(join(doc, 'html', '_build', 'html', 'slides'))  ### New
    docs_slides_path = finalize(join(docs, 'slides'))  ###
    
    # Step 2: Make sure all paths exist.
    paths = (build_path, docs_path, docs_static_path, html_path)
    fails = [z for z in paths if not g.os_path_exists(z)]
    if fails:
        g.printObj(fails, tag='run: Missing paths...')
        return
        
    # Step 3: Do nothing else outside 'gh-pages' branch.
    if not g.gitBranchName().startswith('gh-pages'):
        g.es_print('Run `make-sphinx` from `gh-pages` branch')
        return
    try:
        old_p = c.p
        os.chdir(html_path)
        patch_home_page()
        write_intermediate_files()
        make_html(html_path)
        print('')
        copy_files(build_path, docs_path)
        copy_files(doc_static_path, docs_static_path)
        copy_recursive(doc_slides_path, docs_slides_path)
        print('')
        git_status()
    finally:
        c.selectPosition(old_p)
</t>
<t tx="ekr.20260605070320.9">def write_intermediate_files() -&gt; int:
    """Return True if the rst3 command wrote any intermediate files."""
    total_n = 0
    for headline in headlines:
        p = g.findTopLevelNode(c, headline)
        if p:
            c.selectPosition(p)
            n = c.rstCommands.rst3()
            total_n += n
        else:
            g.es_print(f"Not found: {headline!r}")
            return False
    if total_n == 0:
        g.es_print('No intermediate files changed', color='red')
    return total_n &gt; 0</t>
<t tx="felix.20210825213137.1">Since a WebSocket server can receive events from clients, process them to update the
application state, and synchronize the resulting state across clients, leoserver.py
has the ability to listen and interact with more than one concurrent client, and have
the state of the underlying Leo core application be represented in real time to all
connected clients.

If a server is started with the command line argument parameter 'limit' set to more than one (1),
then it will allow for more than one client to be connected at the same time, sharing in real
time the state, and control, of the underlying Leo instance.

This can be used to have multiple client programs share the same views and functionality
of a single Leo instance. Or be used to live-share the editing process with collaborators
or spectators in real time.

*By default, this limit is set to one (1) to prevent multiple connections and force each client
to have their own individual Leo server instances running on different ports.*
</t>
<t tx="felix.20210825222316.1">The server also sends asynchronous messages, i.e. messages that are not responses
to a specific request, that are meant to communicate a changed state or request
a user input through a modal dialog, or anything else that was not initiated by
a connected clients' direct request.

Examples of 'async' messages:

* An entry added to the log pane.
* Signal the detection of an external file change.
* Signal the automatic refresh of an outline.
* A signal to ask the user about reloading a Leo file that has changed after changing a git branch.
</t>
<t tx="felix.20210826001302.1">leoserver.py has optional command line arguments that you can provide
to get specific behaviors from the server.

**--file &lt;filename&gt; or -f &lt;filename&gt;**

    Open the given file after starting the server.

**--persist**

    Prevent the server from closing when last client disconnects

**--limit &lt;number&gt; or -l &lt;number&gt;**

    Allow more than one connection to be open simultaneously.
    By default, only one connection may be open at a time.

**--address &lt;address&gt; or -a &lt;address&gt;**

    Set the listening address.

**--port &lt;number&gt; or -p &lt;number&gt;**

    Set the listening port.

**--help or -h**

    List all available command-line arguments.
</t>
<t tx="felix.20210902210559.1">The **ws_handler** function contains the main server loop. 

ws_handler dispatches incoming requests to the **_do_request** method,
which then calls the appropriate handler, either in the LeoServer class, or
(via Leo's bridge) to Leo itself.

Request handlers raise the following exceptions:

- ServerError indicates an invalid user request.
  The server returns a response describing the error.
- InternalServerError and error within the server itself.
  The server prints an error message and stops.
- TerminateServer causes the server to terminate normally.</t>
<t tx="felix.20210902210710.1">Félix Malboeuf wrote the original version of leoserver.py, including the
first draft of the all-important ws_handler function.

Edward K. Ream made the code more pythonic and provided Leo-specific
advice.
</t>
<t tx="felix.20251005130847.1">**Question**: Is there a way to export an outline in an html format where the format of the html is similar to the desktop version of Leo with the expands and collapses?  I want to send someone a copy of my outline that they can use in a browser to view.

**Answer**: Use the "leo_to_html_outline_viewer" plugin.

(It is enabled by default as of Leo 6.8.7. For existing installs, add "leo_to_html_outline_viewer.py" to the @enabled-plugins node's body in your "myLeoSettings.leo" file.)

This plugin adds an "Export HTML Outline Viewer" entry in the File-&gt;Export Files menu which outputs the Leo outline as a self-contained HTML interactive outline viewer. 

The file is saved in the user's home/.leo folder and also opened with your default viewer.
</t>
<t tx="felix.20251005132812.1">This plugin adds an "Export HTML Outline Viewer" entry in the File-&gt;Export Files menu
which outputs the Leo outline as a self-contained HTML interactive outline viewer.
The file is saved in the user's home/.leo folder and also opened with your default viewer.

Made by Félix Malboeuf (https://github.com/boltex)</t>
<t tx="felix.20260601125039.1">To prevent unauthorized access, the server requires a password when it is started. Clients must prove knowledge of this password before they can issue commands to the server.

When a client connects, the server begins a challenge-response authentication sequence by sending a JSON message containing two members:

- An action member with the value "challenge".
- A challenge member containing a randomly generated string.

The client computes an HMAC-SHA256 hash using the password as the key and the challenge string as the message, then sends the resulting hexadecimal digest back to the server in an !auth request. Because the password itself is never transmitted over the connection, authentication can be performed without exposing the password to network observers.

The following example from leoclient.py demonstrates this procedure:

.. code-block:: python

    uri = f"ws://{wsHost}:{wsPort}"
    async with websockets.connect(uri) as websocket:
        # React to the server's challenge for authentication.
        parsedData = json.loads(g.toUnicode(await websocket.recv()))
        if parsedData.get("action") == "challenge":
            challenge = parsedData.get("challenge")
            expected_hash = hmac.new(
                password.encode(), challenge.encode(), hashlib.sha256
            ).hexdigest()
            await websocket.send(json.dumps({"action": "!auth", "response": expected_hash}))
        else:
            print(f"expected challenge, got: {parsedData}")
            return</t>
<t tx="felix.20260601132011.1">Using TLS encryption is optional. When TLS is enabled, all communication between the client and server is encrypted and the WebSocket endpoint uses the wss:// scheme instead of ws://.

To enable TLS, start the server with the --cert and --key arguments:

--cert: Path to the server certificate file (PEM format).
--key: Path to the corresponding private key file (PEM or KEY format).

For example:

.. code-block:: bash

    python leoserver.py --port 32125 --password mypassword --cert server-cert.pem --key server-key.pem

When both arguments are provided, the server automatically starts in secure mode and accepts encrypted WebSocket connections.

Clients must then connect using a wss:// URL instead of ws://:

.. code-block:: python

    uri = f"wss://{wsHost}:{wsPort}"
    async with websockets.connect(uri) as websocket:
    ...

If a self-signed certificate is used, client software may need additional configuration to trust the certificate.</t>
<t tx="matt.20200331213038.1">When Leo has been installed in non-editable mode* (the above) there will be messages in the log pane window when opening certain .leo files distributed with Leo, such as LeoDocs.leo. (_File &gt;&gt; Open Leo File &gt;&gt; ..._). The warnings are not serious and may be ignored.

This is a known issue with no practical solution. Files in the root folder of the leo-editor code repository is not installed when using pip. This is because they need to be relative to ``./leo-editor/leo`` folder, which make them at the top of ``PYTHONHOME/lib/site-packages``, and thus in the global namespace and not part of leo as far as python is concerned.

Details at `Missing files when installing Leo from PyPI using "pip install leo"`_.

\* An editable install is from source code, either a git clone or downloaded archive. See: 

* An editable install is from source code, either a git clone or downloaded archive. See:

- Installing Leo with git
- Installing from sources (Windows)

</t>
<t tx="mhw.20191008134016.1"></t>
<t tx="mhw.20191008134029.1">##########################
Leo and Asciidoctor
##########################

**New with Leo 6.1**

The Leo ``@adoc`` directive and the ``adoc`` command need either **Asciidoc3** or **Asciidoctor** tool installed and in PATH.Asciidoctor is probably the best of the two to use.

**Linux:** use your system package manager or ruby `gem install asciidoctor`. More info at https://asciidoctor.org/#installation


**Windows:** installing on Windows is not straightforward as one needs to install Ruby first. Asciidoc3 isn't the straightest either, but enough that it can be shortened to couple of instructions, namely::

    pip install asciidoc3
       # stuff happens

    asciidoc3_postinstall
       # more stuff happens

    #now asciidoc3 is ready and Leo can use it:
    asciidoc3 --help

</t>
<t tx="peckj.20130813123907.6841">Documenting new plugins is important for users to be able understand and use the features they add. To that effect, there are a few documentation steps that should not be overlooked.

- Document the plugin thoroughly in the plugin's docstring. This allows the documentation to be accessed from the Plugins menu.

- Document any new commands with a proper docstring. This allows the minibuffer command `help-for-command` to provide help for the command.

- In ``leo/doc/sphinx-docs/sphinxDocs.leo``, to the node ``@file leo.plugins.rst``, add the following snippet (preferably in alphabetical order), with the name of the plugin modified to the name of your plugin (here `xxx`). This allows the API docs to be automatically updated::

    :mod:`xxx` Module
    -----------------

    .. automodule:: leo.plugins.xxx
        :members:
        :undoc-members:
        :show-inheritance:
</t>
<t tx="rkeeney.20190823135126.4"></t>
<t tx="shadow.20080825171547.9">**Question**: I must follow a coding standard when writing source code. It includes a maximum line length restriction. How can I know the length of a line when it gets written to the external file?

**Answer**: If a node belongs to a external file hierarchy, its body might get indented when it is written to the external file. It happens when an @others directive or a section name appears indented in a higher-level node body. While (**line**, **col**) in status area show the line and column containing the body text's cursor, **fcol** shows the cursor coordinate relative to the external file, not to the current node. The relation **fcol &gt;= col** is always true.
</t>
<t tx="sps.20100708203040.19008">@language python
import os
pos = c.find_h("Users Guide")[0]
c.selectPosition(pos)
c.k.simulateCommand('rst3')
&lt;&lt; html manual &gt;&gt;
&lt;&lt; pdf manual &gt;&gt;
</t>
<t tx="sps.20100708203040.19009">d = c.scanAllDirectives(p)
mandir = d.get('path') + "/html"
g.es(mandir)
os.chdir(mandir)
os.system('make html')
</t>
<t tx="sps.20100708203040.19010"># you probably need to install several packages 
# to create pdf (e.g. jadetex)
mandir = d.get('path') + "/html"
g.es(mandir)
os.chdir(mandir)
os.system('make latex')
os.chdir('_build/latex')
os.system('../../fixup.pl &lt; Leodocumentation.tex &gt; LeoDoc.tex')
os.system('make LeoDoc.pdf')
</t>
<t tx="tom.20230107235603.1">Title case means that all words start with capital letters.  The
following script converts the selected body text to title case.  If
nothing has been selected, the entire current node is converted. The
conversion is undoable:

.. code-block:: python

    """Undoably convert selection or body to title case."""
    w = c.frame.body.wrapper
    p = c.p
    s = p.b
    u = c.undoer

    start, end = w.getSelectionRange()
    use_entire = start == end  # no selection, convert entire body

    undoType = 'title-case-body-selection'
    undoData = u.beforeChangeNodeContents(p)

    if use_entire:
        p.b = s.title()
    else:
        sel = s[start:end]
        head, tail = s[:start], s[end:]
        p.b = head + sel.title() + tail

    c.setChanged()
    p.setDirty()
    u.afterChangeNodeContents(p, undoType, undoData)
    c.redraw()

[Contributed by T. B. Passin]</t>
<t tx="ville.20090602181814.6219">def commanders(self):
    """ Return list of currently active controllers """
    return [f.c for f in g.app.windowList]
</t>
<t tx="ville.20090620122043.6275">def setGlobalDb(self):
    """ Create global pickleshare db

    Usable by::

        g.app.db['hello'] = [1,2,5]

    """
    # Fixes bug 670108.
    import leo.core.leoCache as leoCache
    g.app.db = leoCache.Cacher().initGlobalDB()
</t>
<t tx="ville.20090705224948.5734">import os
pos = c.find_h("Users Guide")[0]
c.selectPosition(pos)
c.k.simulateCommand('rst3')
&lt;&lt; html manual &gt;&gt;
# no pdf manual creation, perhaps too "involved" for many
</t>
<t tx="ville.20090705225609.5736">mandir = g.app.leoDir + "/doc/html"
g.es(mandir)
os.chdir(mandir)
os.system('make html')
</t>
<t tx="ville.20090705225609.5738"># you probably need to install several packages 
# to create pdf (e.g. jadetex)
mandir = g.app.leoDir + "/doc/html"
g.es(mandir)
os.chdir(mandir)
os.system('make latex')
os.chdir('_build/latex')
os.system('make all-pdf')
</t>
</tnodes>
</leo_file>
