<?xml version="1.0" encoding="utf-8"?>
<!-- Created by Leo: http://leoeditor.com/leo_toc.html -->
<leo_file xmlns:leo="http://leoeditor.com/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="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.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.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.17625"><vh>@bool rst3_code_mode = False</vh></v>
<v t="ekr.20150319142303.4"><vh>@bool rst3_debug = False</vh></v>
<v t="ekr.20050812123002.7"><vh>@bool rst3_format_headlines = True</vh></v>
<v t="ekr.20131009050634.17627"><vh>@bool rst3_generate_rst = True</vh></v>
<v t="ekr.20131009050634.17610"><vh>@bool rst3_http_server_support = False</vh></v>
<v t="ekr.20050812123002.6"><vh>@bool rst3_massage_body = False</vh></v>
<v t="ekr.20131009050634.17630"><vh>@bool rst3_show_headlines = True</vh></v>
<v t="ekr.20131009052848.6456"><vh>@bool rst3_show_leo_directives = True</vh></v>
<v t="ekr.20131009050634.17631"><vh>@bool rst3_show_organizer_nodes = True</vh></v>
<v t="ekr.20150320085538.4"><vh>@bool rst3_silent = True</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.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 t="ekr.20050812123002.1"><vh>Http options...</vh>
<v t="ekr.20050812123002.2"><vh>@bool rst3_clear_http_attributes = False</vh></v>
<v t="ekr.20050812123002.3"><vh>@string rst3_http_attributename = rst_http_attribute</vh></v>
<v t="ekr.20050812123002.4"><vh>@bool rst3_http_server_support = False</vh></v>
<v t="ekr.20050812123002.5"><vh>@string rst3_node_begin_marker = http-node-marker-</vh></v>
</v>
</v>
</v>
<v t="ekr.20131017051340.16847"><vh>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.20111017085134.16198"><vh>@@button remove-image-directives</vh></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>
<v t="ekr.20130803073926.17120"><vh>@@button clean-mail</vh></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.20150314044011.7"><vh>@@button remove dups</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="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.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.20131016083406.16724"><vh>@button make-sphinx</vh></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 t="ekr.20131007143750.16111"><vh>To do</vh>
<v t="ekr.20131108071132.17025"><vh>improve MacOS install: chmod</vh></v>
<v t="ekr.20131028213522.17137"><vh>Examples for cheat sheet</vh></v>
<v t="ekr.20180124100723.1"><vh>New docs: To do</vh>
<v t="ekr.20180124100723.2"><vh>Consider using Leo if...</vh></v>
<v t="ekr.20180124100723.3"><vh>Leo as a compendium</vh></v>
<v t="ekr.20180124100723.4"><vh>Reproducible research</vh></v>
<v t="ekr.20180124100723.5"><vh>Scripting for scientists</vh></v>
<v t="ekr.20180124100723.6"><vh>Underlying technologies</vh>
<v t="ekr.20180124100723.7"><vh>LP and RR</vh></v>
<v t="ekr.20180124100723.8"><vh>Scripting</vh></v>
<v t="ekr.20180124100723.9"><vh>Data model</vh></v>
</v>
</v>
</v>
</v>
<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.5"><vh>#754: Move distribution from SourceForge to github + pip install Leo</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.20100805171546.4412"><vh>Web pages</vh>
<v t="ville.20090609182215.5676"><vh>@auto-rst treecaching.txt</vh></v>
<v t="ekr.20090428133936.2"><vh>@edit html\conf.py</vh></v>
<v t="ekr.20101112045055.5064"><vh>@file plugin_catalog.py</vh></v>
<v t="ekr.20101112045055.5065"><vh>@url docs generated from plugin_catalog.py</vh></v>
<v t="ekr.20131005214621.16088"><vh>Home page</vh>
<v t="ekr.20100808060203.4273"><vh>@file html/index.html</vh></v>
</v>
<v t="ekr.20101007100904.4372"><vh>Slideshows</vh>
<v t="ekr.20101028110015.8271" descendentVnodeUnknownAttributes="7d710028580b000000302e312e312e382e322e3171017d7102580b0000007374725f6c656f5f706f7371035800000000710473580b000000302e312e312e382e332e3171057d7106580b0000007374725f6c656f5f706f737107680473580b000000302e312e312e382e342e3171087d7109580b0000007374725f6c656f5f706f73710a680473580b000000302e312e312e382e352e31710b7d710c580b0000007374725f6c656f5f706f73710d680473752e"><vh>@file slideshows.txt</vh></v>
</v>
<v t="ekr.20101115152915.4937"><vh>wikipedia entry</vh></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.20100821182153.4343"><vh>@rst html/slides.html</vh></v>
<v t="ekr.20170130080532.1"><vh>@auto-md ../doc/demo.md</vh></v>
<v t="ekr.20170202125807.1"><vh>@auto-md ../doc/colorizer.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>
<v t="ekr.20131017094004.16739"><vh>How to...</vh>
<v t="ekr.20090401113141.1"><vh>How to generate odt/rtf/pdf files</vh>
<v t="ekr.20090620131445.5595"><vh>Post from ville</vh></v>
<v t="ekr.20090401113141.2"><vh>@rst c:/test/test.html</vh>
<v t="ekr.20090401113141.4"><vh>section 1</vh></v>
</v>
</v>
<v t="ekr.20101104024804.4898"><vh>How to generate these docs</vh></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>
<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>
<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.20111127144911.5544"><vh>@rst html/download.html</vh>
<v t="tbrown.20140412113009.50227"><vh>Snapshots</vh></v>
</v>
<v t="ekr.20131008041326.16094"><vh>@rst html/installing.html</vh>
<v t="ekr.20141105052052.4"><vh>Dependencies</vh></v>
<v t="ekr.20180130033527.1"><vh>Installing Leo with pip</vh></v>
<v t="ekr.20101125062332.5090"><vh>Installing packages</vh></v>
<v t="ekr.20170206073848.1"><vh>Installing Leo itself</vh>
<v t="ekr.20170206073747.2"><vh>Installing Leo on Windows</vh>
<v t="ekr.20170206073747.3"><vh>Using the single-click installer</vh></v>
<v t="ekr.20170206073747.4"><vh>Installing from sources (Windows)</vh></v>
<v t="ekr.20170206073747.5"><vh>Creating Windows file associations</vh></v>
</v>
<v t="ekr.20170206073747.10"><vh>Installing Leo with git</vh></v>
<v t="ekr.20170206073747.6"><vh>Installing Leo on Linux</vh>
<v t="ekr.20170206073747.7"><vh>Installing from a debian package</vh></v>
<v t="ekr.20170206073747.8"><vh>Installing from sources (Linux)</vh></v>
</v>
<v t="ekr.20170206073747.9"><vh>Installing Leo on MacOs 10.7 (Lion) and later</vh></v>
</v>
<v t="ekr.20180126191031.1"><vh>Installing everything with Anaconda or Miniconda</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.20090212054250.5"><vh>Getting Leo</vh>
<v t="ekr.20090212054250.6"><vh>Where can I get official releases of Leo?</vh></v>
<v t="ekr.20080603124653.1"><vh>How do I use git to get the latest sources from Leo's GitHub site?</vh></v>
<v t="ekr.20090212054250.7"><vh>How can I get recent snapshots of Leo?</vh></v>
</v>
<v t="ekr.20070623145346"><vh>Installing Leo</vh>
<v t="matt.20180826201749.1"><vh>How to  Pip install from GitHub?</vh></v>
<v t="ekr.20090202191501.7"><vh>Leo's installer failed, what do I do?</vh></v>
<v t="ekr.20150313053238.40"><vh>Common problems</vh></v>
</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.20150415111549.1"><vh>How can I customize the clone-find-all commands?</vh></v>
<v t="ekr.20150415110715.1"><vh>How can I eliminate clone wars?</vh></v>
<v t="ekr.20160414191631.1"><vh>How can I simulate more flexible clones?</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.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-file 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.20050830115714.29"><vh>How can I add support for a new language?</vh></v>
<v t="ekr.20141108064630.18"><vh>How can I create a pane for matplotlib charts?</vh></v>
<v t="ekr.20060915112109"><vh>How can I enable and disable support for psyco?</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 can I use a dark theme in Leo?</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?</vh></v>
<v t="ekr.20091105080104.9031"><vh>How do I specify qt fonts?</vh></v>
<v t="ekr.20050830115714.30"><vh>How do I submit a plugin?</vh></v>
</v>
<v t="ekr.20170906090516.1"><vh>Developing Leo</vh>
<v t="ekr.20170804153108.2"><vh>How can I use dev nodes to develop and test Leo's own code?</vh></v>
<v t="ekr.20050830120857"><vh>How can I use Leo to develop Leo itself?</vh></v>
<v t="ekr.20110531155858.20559"><vh>How does EKR (Leo's developer) use Leo?</vh></v>
<v t="ekr.20160309092522.1"><vh>What is the Stupendous Aha and why does it matter?</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="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.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.20160304081437.4"><vh>How can I use Leo in virtualenv?</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.10"><vh>How do I run unit tests from Leo?</vh></v>
<v t="ekr.20141108064630.14"><vh>How to use leo to make mathematical notes?</vh></v>
<v t="ekr.20160304081437.6"><vh>Tip: run unit tests locally using clones</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.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.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.20170612101117.1"><vh>What about code that looks like a section reference?</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.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 t="ekr.20120229094652.15137"><vh>What's the recommended way to upgrade 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.20170217093640.3"><vh>\@test 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 accelerate work flow by creating 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.20131030071311.17087"><vh>@rst-ignore notes</vh></v>
<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>
<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</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.11"><vh>Use @test 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>
</v>
</v>
<v t="ekr.20131008041326.16080"><vh>Users Guide</vh>
<v t="ekr.20131008041326.16082"><vh>@rst html/usersguide.html</vh></v>
<v t="ekr.20050901101608.4"><vh>@rst html/customizing.html</vh>
<v t="EKR.20040524104904.140"><vh>Specifying 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>\@button</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.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 t="ekr.20100122073254.11655"><vh>Writing new importers</vh></v>
</v>
<v t="ekr.20050818163826"><vh>@rst html/rstplugin3.html</vh>
<v t="ekr.20100813075851.4296"><vh>Options</vh>
<v t="ekr.20100809122216.4286"><vh>General options</vh></v>
<v t="ekr.20050818163826.7"><vh>Headline commands</vh></v>
<v t="ekr.20050818163826.8"><vh>Option doc parts</vh></v>
<v t="ekr.20050818163826.9"><vh>Settings give defaults for options</vh></v>
<v t="ekr.20050818163826.5"><vh>Http plugin options</vh></v>
<v t="ekr.20110612104631.16414"><vh>Section expansion options</vh></v>
</v>
<v t="ekr.20100813075851.4297"><vh>Other topics</vh>
<v t="ekr.20100810091118.4298"><vh>Markup doc parts</vh></v>
<v t="ekr.20050818163826.11"><vh>Required cascading style sheets</vh></v>
<v t="ekr.20060527103630"><vh>Controlling the rst3 command from scripts</vh></v>
</v>
<v t="ekr.20050818163826.13"><vh>Further study</vh></v>
<v t="ekr.20050818163826.14"><vh>Theory of operation</vh></v>
<v t="ekr.20050818163826.4"><vh>Advanced topics</vh>
<v t="ekr.20100810203016.4298"><vh>Modes</vh></v>
<v t="ekr.20100810091118.4301"><vh>Code mode options</vh></v>
<v t="ekr.20100810091118.4306"><vh>Rst mode options</vh></v>
<v t="ekr.20050818163826.10"><vh>The code-block directive</vh></v>
</v>
<v t="ekr.20050818163826.16"><vh>Acknowledgements</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.9427"><vh>pretty_print.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.9440"><vh>ipython.py</vh></v>
<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.20170314091501.1"><vh>injarnder.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="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.9483"><vh>UNL.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.20131009100732.19040"><vh>valuespace.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.20131002055813.19837"><vh>Undoing and redoing changes</vh></v>
<v t="ekr.20160428113347.1"><vh>Clone-find commands</vh></v>
<v t="ekr.20131001100335.15947"><vh>Help commands</vh></v>
<v t="ekr.20180130094948.1"><vh>Operations on reference .leo files</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.27"><vh>Multiple body editors</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.20150323185151.1"><vh>Macro commands</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.20150603120140.1"><vh>What the Python beautifier does</vh></v>
<v t="ekr.20150603120515.1"><vh>What the Python beautifier doesn't do</vh></v>
<v t="ekr.20150603115243.1"><vh>Beautifier directives</vh></v>
<v t="ekr.20150603115204.1"><vh>Beautifier settings</vh></v>
<v t="ekr.20150603115311.1"><vh>Beautifier rough edges</vh></v>
<v t="ekr.20150603115400.1"><vh>Stand-alone beautifier</vh></v>
<v t="ekr.20150603120245.1"><vh>Enough is enough</vh></v>
<v t="ekr.20150603120150.1"><vh>Summary of the beautifier</vh></v>
</v>
<v t="ekr.20150318110552.86"><vh>Unit testing commands</vh></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>Part 1: \@&lt;file&gt; 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.20160410043905.1"><vh>Path expressions</vh></v>
</v>
<v t="ekr.20100806170836.4411"><vh>Part 2: \@all and \@others</vh></v>
<v t="ekr.20100806170836.4398"><vh>Part 3: Syntax coloring directives</vh></v>
<v t="ekr.20100806170836.4408"><vh>Part 4: Dangerous directives</vh></v>
<v t="ekr.20100804133903.7262"><vh>Part 5: 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="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.20080203101507"><vh>ILeo - the IPython bridge</vh>
<v t="ekr.20080203101507.1"><vh>@rst html\IPythonBridge.html</vh>
<v t="vivainio.20080302174639.1"><vh>Overview</vh></v>
<v t="vivainio.20080302174639.2"><vh>Starting ILeo</vh></v>
<v t="ekr.20131001045038.18981"><vh>Running Leo scripts from IPython</vh></v>
<v t="ekr.20131001045038.18980"><vh>Running IPython scripts from Leo</vh></v>
<v t="ekr.20131001045038.18979"><vh>ILeo as an IPython notebook</vh></v>
<v t="ekr.20131001100236.15927"><vh>ILeo and the valuespace plugin</vh></v>
<v t="ekr.20131001045038.17448"><vh>Acknowledgements and history</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>The basics</vh></v>
<v t="ekr.20150328073917.1"><vh>Example: running unit tests from leoBridge</vh></v>
<v t="ekr.20071210094621"><vh>Running leoBridge from within Leo</vh></v>
</v>
</v>
<v t="ekr.20060913164304"><vh>Leo and ZODB</vh>
<v t="ekr.20060913164304.1"><vh>@rst html\zodb.html</vh>
<v t="ekr.20060913170145"><vh>Configuring Leo to use zodb</vh></v>
<v t="ekr.20060913170403"><vh>Initing zodb</vh></v>
<v t="ekr.20060913170403.1"><vh>Writing data to zodb</vh></v>
<v t="ekr.20060913175437"><vh>Defining zodb keys</vh></v>
<v t="ekr.20060913170403.2"><vh>Reading data from zodb</vh></v>
<v t="ekr.20060913175437.1"><vh>About connections</vh></v>
<v t="ekr.20060913165542.1"><vh>Convenience routines</vh>
<v t="ekr.20060913165542.2"><vh>g.init_zodb (pathToZodbStorage,verbose=True)</vh></v>
<v t="ekr.20060913165542.3"><vh>v.detach()</vh></v>
</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.20060430221745"><vh>Controlling syntax coloring</vh>
<v t="ekr.20060430221745.1"><vh>@rst html\coloring.html</vh>
<v t="ekr.20060830142929"><vh>Syntax coloring settings</vh></v>
<v t="ekr.20060430220749"><vh>Files</vh></v>
<v t="ekr.20060502084233"><vh>The colorizer's inner loop</vh></v>
<v t="ekr.20060502084233.1"><vh>Format of colorizer control files</vh>
<v t="ekr.20060502100550"><vh>Ruleset names</vh></v>
<v t="ekr.20060502090516"><vh>x.properties</vh></v>
<v t="ekr.20060510085547"><vh>Attribute dictionaries and x.attributesDictDict</vh></v>
<v t="ekr.20060502090516.1"><vh>Keyword dictionaries and x.keywordsDictDict</vh></v>
<v t="ekr.20060502090516.2"><vh>Rules, rules dictionaries and x.rulesDictDict</vh></v>
<v t="ekr.20060503072213"><vh>x.importDict and imported versus delegated rulesets</vh></v>
</v>
<v t="ekr.20060502122950"><vh>Rule methods</vh>
<v t="ekr.20060503064515"><vh>Arguments to rule methods</vh></v>
<v t="ekr.20060502122950.7"><vh>match_eol_span</vh></v>
<v t="ekr.20060502122950.10"><vh>match_eol_span_regexp</vh></v>
<v t="ekr.20060502122950.13"><vh>match_keywords</vh></v>
<v t="ekr.20060502122950.14"><vh>match_mark_following</vh></v>
<v t="ekr.20060502125223"><vh>match_mark_previous</vh></v>
<v t="ekr.20060502122950.40"><vh>match_seq</vh></v>
<v t="ekr.20060502122950.41"><vh>match_seq_regexp</vh></v>
<v t="ekr.20060502122950.42"><vh>match_span</vh></v>
<v t="ekr.20060502122950.47"><vh>match_span_regexp</vh></v>
<v t="ekr.20060502122950.48"><vh>match_terminate</vh></v>
</v>
</v>
</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>Writing 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.20070628083442"><vh>Unit testing with Leo</vh>
<v t="ekr.20070628083442.1"><vh>@rst html\unitTesting.html</vh>
<v t="ekr.20070628084351"><vh>Using @test nodes</vh></v>
<v t="ekr.20070628094515.1"><vh>Using @suite nodes</vh></v>
<v t="ekr.20120229094652.15125"><vh>Using @mark-for-unit-tests</vh></v>
<v t="ekr.20170301013432.1"><vh>Test driven development in Leo</vh></v>
<v t="ekr.20070628094515.2"><vh>How the unit test commands work</vh></v>
<v t="ekr.20080729064227.6"><vh>\@button timer</vh></v>
<v t="ekr.20080729064227.7"><vh>\@button profile</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>
<v t="ekr.20070115172724.3"><vh>The execute-script command with explicit debugger breaks</vh></v>
</v>
</v>
</v>
<v t="ekr.20170618113437.1"><vh>Leo's console gui</vh>
<v t="ekr.20170618113503.1"><vh>@rst html\console-gui.html</vh>
<v t="ekr.20170815082542.1"><vh>System requirements</vh></v>
<v t="ekr.20170618111245.1"><vh>Starting Leo with the console gui</vh></v>
<v t="ekr.20170618162705.1"><vh>Exiting Leo &amp; saving files</vh></v>
<v t="ekr.20170618111248.3"><vh>Navigation and editing</vh></v>
<v t="ekr.20170618111248.5"><vh>Leo key bindings</vh></v>
<v t="ekr.20170618115641.1"><vh>Limitations</vh>
<v t="ekr.20171201041242.1"><vh>Curses limitations</vh></v>
<v t="ekr.20171201041304.1"><vh>npyscreen limitations</vh></v>
<v t="ekr.20171204104344.1"><vh>Unfixed bugs</vh></v>
</v>
<v t="ekr.20170618115228.1"><vh>Broadcasting and listening</vh></v>
<v t="ekr.20171130105248.1"><vh>Developing the cursesGui2 plugin</vh>
<v t="ekr.20171201034131.1"><vh>Tracing is essential</vh></v>
<v t="ekr.20171201034133.1"><vh>Noteworthy functions and methods</vh></v>
<v t="ekr.20171201042151.1"><vh>Running unit tests</vh></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="ekr.20161014160238.1"><vh>Creating code that will run on both Python 2 and 3</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>
<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 and paths</vh></v>
<v t="ekr.20131012060912.16788"><vh>Writing g.es output to other tabs</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.2"><vh>LeoU: Unit tests should not depend on settings</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.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.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.20170311120214.1"><vh>Test driven development</vh></v>
<v t="ekr.20170403185500.1"><vh>Performance gotchas</vh></v>
<v t="ekr.20170314164228.1"><vh>About names</vh></v>
</v>
<v t="ekr.20131028213522.17138"><vh>Command-line options</vh></v>
</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.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 t="ekr.20080315115427.568"><vh>2006-2008: 4.4.x: Hundreds of improvements</vh>
<v t="ekr.20060822140418"><vh>4.4.1: new colorizer, slideshow, multiple editors</vh></v>
<v t="ekr.20061008190905"><vh>4.4.2: autocontract, opml, zodb, sax, myLeoSettings, leoPymacs</vh></v>
<v t="ekr.20070316182323"><vh>4.4.3: winpdb, leoBridge, gui reorg, chapters</vh></v>
<v t="ekr.20070806090235"><vh>4.4.4: @auto, @menus, threading syntax colorer, the Great Graph Aha</vh></v>
<v t="ekr.20071115102421"><vh>4.4.5: Directives in headlines</vh></v>
<v t="ekr.20080106114331"><vh>4.4.6: Bug fixes</vh></v>
<v t="ekr.20080218154129"><vh>4.4.7: The ipython plugin</vh></v>
<v t="ekr.20080311060457.215"><vh>4.4.8: translation</vh></v>
</v>
<v t="ekr.20101025080245.6085"><vh>2008: 4.5: Code reorg, @shadow, vim bindings</vh></v>
<v t="ekr.20101025080245.6086"><vh>2009: 4.6: Caching, 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.20131031101712.16685"><vh>2012: 4.10: Many improvements</vh></v>
<v t="ekr.20131031101712.17211"><vh>2013: 4.11: More improvements</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.20150313053238.44"><vh>Steve Zatz: in praise of @clean</vh></v>
<v t="ekr.20150313053238.45"><vh>EKR: Why @clean is so important</vh></v>
<v t="ekr.20150312080344.28"><vh>Genesis of @clean</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.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.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 t="ekr.20180411071654.1"><vh>#850: Optionally convert Meta to Alt on MacOs</vh></v>
</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.20180404015721.1"><vh>What's new in Leo 5.x</vh>
<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.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.69"><vh>Restored importer;; abbreviation</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.20180124123920.1"><vh>Added find-all-unique-regex command</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 print-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 t="ekr.20180930062430.1"><vh>Leo 5.8 release notes</vh>
<v t="ekr.20180528114703.1"><vh>Leo 5.8 b2 release notes</vh>
<v t="ekr.20180601095122.1"><vh>Bugs</vh>
<v t="ekr.20180828095555.1"><vh>Fixed in b1</vh>
<v t="ekr.20180822072454.2"><vh>#841: Python importer does not always handle decorators properly</vh></v>
<v t="ekr.20180822072454.4"><vh>#893: Python Console gets stuck on IndentationError</vh></v>
<v t="ekr.20180601095134.1"><vh>#917: System keys on Microsoft keyboard insert unwanted text</vh></v>
<v t="ekr.20180702154446.1"><vh>#922: text following @others is ignored</vh></v>
<v t="ekr.20180708035251.1"><vh>#933: Leo clears the user's clipboard on first time startup</vh></v>
<v t="ekr.20180822124637.1"><vh>#936: hang on sesson start</vh></v>
<v t="ekr.20180704130141.1"><vh>#938: New code breakes tree abbreviations </vh></v>
<v t="ekr.20180822140501.1"><vh>#940: Crashes in stickynotes.py</vh></v>
<v t="ekr.20180821062138.89"><vh>#943: Error in reload-all-settings</vh></v>
<v t="ekr.20180806043625.1"><vh>#947: replace-all</vh></v>
<v t="ekr.20180821062022.32"><vh>#956: syntax error</vh></v>
<v t="ekr.20180824085929.1"><vh>#967: Cross-bile backlink errors</vh></v>
<v t="ekr.20180821062022.38"><vh>backup script saves/restores cwd</vh></v>
<v t="ekr.20180708081949.1"><vh>Fixed crasher in LeoQtLog.linkClicked</vh></v>
<v t="ekr.20180708030832.1"><vh>Fixed problems with git-diff command</vh></v>
<v t="ekr.20180821062138.296"><vh>git-diff now works outside of leo-editor folder</vh></v>
</v>
<v t="ekr.20180828095605.1"><vh>Fixed in b2</vh>
<v t="ekr.20180828095610.1"><vh>#969: Chapter button</vh></v>
<v t="ekr.20180829083210.1"><vh>#970: Crash opening mal-formed .leo files</vh></v>
</v>
</v>
<v t="ekr.20180608054147.1"><vh>Code</vh>
<v t="ekr.20180821062138.2"><vh>#296: private plugin directories</vh></v>
<v t="ekr.20180821062138.15"><vh>#924: Improved performance of at.readAll</vh>
<v t="ekr.20180821062138.16"><vh>Stats...</vh>
<v t="ekr.20180821062138.17"><vh>CProfile: .leo FAST = False</vh></v>
<v t="ekr.20180821062138.18"><vh>cProfile: .leo FAST = True</vh>
<v t="ekr.20180821062138.19"><vh>originals</vh></v>
</v>
<v t="ekr.20180821062138.20"><vh>cProfile, with FAST = True (much improved)</vh></v>
<v t="ekr.20180821062138.21"><vh>Stats: g.isUnicode (before &amp; after)</vh></v>
<v t="ekr.20180821062138.22"><vh>Stats: is_special: before (no change)</vh></v>
<v t="ekr.20180821062138.23"><vh>Stats: g.match_word: before &amp; after</vh></v>
<v t="ekr.20180821062138.24"><vh>Stats: p.ctor (no change will be made)</vh></v>
</v>
</v>
<v t="ekr.20180608054151.1"><vh>Much faster reading of external files</vh></v>
<v t="ekr.20180608054356.1"><vh>Added copy kwarg to generators</vh>
<v t="ekr.20180821062138.130"><vh>Stats: p.copy (before)</vh></v>
<v t="ekr.20180821062138.131"><vh>Stats: p.copy (after, with s.bat)</vh></v>
<v t="ekr.20180821062138.132"><vh>Stats: p.copy (after changing p.get_UNL)</vh></v>
<v t="ekr.20180821062138.133"><vh>Stats: p.copy (after2)</vh></v>
<v t="ekr.20180821062138.134"><vh>Stats: p.copy (after 3)</vh></v>
</v>
<v t="ekr.20180821062022.4"><vh>Removed "adjust" and "reassignIndices" kwargs</vh></v>
<v t="ekr.20180828033232.1"><vh>Removed qtree.update_appearance*</vh></v>
<v t="ekr.20180828033450.1"><vh>Improved Leo's outline drawing code</vh></v>
</v>
<v t="ekr.20180528114740.1"><vh>Features</vh>
<v t="ekr.20180528114754.1"><vh>#871: A setting to position the icon bar </vh></v>
<v t="ekr.20180626054937.1"><vh>#913: Show base classes in python importer</vh></v>
<v t="ekr.20180829160908.1"><vh>#914: Fix jedi completion glitches</vh></v>
<v t="ekr.20180821062138.38"><vh>#932: use "show" prefix for many commands</vh></v>
<v t="ekr.20180806054424.1"><vh>#949: Smart quotes</vh></v>
<v t="ekr.20180821062022.35"><vh>#953: better warnings about importing qt</vh></v>
<v t="ekr.20180821062022.33"><vh>#961: curses gui</vh></v>
<v t="ekr.20180828032757.1"><vh>#966: Better support for clojurescript</vh></v>
<v t="ekr.20180821062419.1"><vh>Added --trace-drawing and --trace-startup</vh></v>
<v t="ekr.20180806085322.1"><vh>Added .sty and .latex entries in extension_dict</vh></v>
<v t="ekr.20180821062138.107"><vh>Added @nosearch to results of cff</vh></v>
<v t="ekr.20180708120421.1"><vh>Added dump-clone-parents command</vh></v>
<v t="ekr.20180806095812.1"><vh>Added md_docer.py plugin</vh></v>
<v t="ekr.20180608055318.1"><vh>Added print-stats command &amp; improved tracing</vh></v>
<v t="ekr.20180821062138.301"><vh>Leo ecognizes .latex and .sty as LaTeX files</vh></v>
<v t="ekr.20180821155534.1"><vh>Removed --no-cache &amp; --trace-cache</vh></v>
</v>
</v>
</v>
</v>
</v>
<v t="ekr.20180821154658.1"></v>
<v t="ekr.20180930062351.1"><vh>Leo 5.8 final 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 print-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>
</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 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 **LeoSettings.leo** (note the capital 'L'), and appearing in a unique directory.

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" str_atime="1376412038.0">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::

    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" str_atime="1376411987.0">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;
    An xml-stylesheet line is option.  For example::

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

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

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

        &lt;leo_header file_format="2" tnodes="0" max_tnode_index="5725" clone_windows="0"/&gt;

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

&lt;globals&gt;
    The globals element specifies information relating to the entire file.
    For example::

        &lt;globals body_outline_ratio="0.50"&gt;
            &lt;global_window_position top="27" left="27" height="472" width="571"/&gt;
            &lt;global_log_window_position top="183" left="446" height="397" width="534"/&gt;
        &lt;/globals&gt;

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

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

&lt;preferences&gt;
    This element is vestigial.
    Leo ignores the &lt;preferences&gt; element when reading.
    Leo writes an empty &lt;preferences&gt; element.

&lt;find_panel_settings&gt;
    This element is vestigial.
    Leo ignores the &lt;find_panel_settings&gt; element when reading.
    Leo writes an empty &lt;find_panel_settings&gt; element.

&lt;clone_windows&gt;
    This element is vestigial.
    Leo ignores the &lt;clone_windows&gt; element when reading.
    Leo no longer writes &lt;clone_windows&gt; elements.

&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;
    The &lt;v&gt; 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.
    This nesting indicates outline structure in the obvious way.
    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.
    The xxx denotes one or more upper-case letters whose meanings are as follows::

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

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

    **New in 4.0**:

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

    -   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;
    The &lt;t&gt; 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 trace: print('onQuit',g.app.save_session,g.app.sessionManager)
    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">@ @rst-options
.. A very cool option: doc parts will be rendered properly,
.. but will be ignored by the Execute script command.
..
show_doc_parts_as_paragraphs = True
@c

.. |---| unicode:: U+02015 .. for quotes
   :trim:

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

..  "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... just the possibility of keeping system
..  maintenance scripts in the IT manual is mind boggling."---David Nichols

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;http://docs.python.org/2/tutorial/&gt;`_. Jacob Peck has written a more `informal scripting tutorial &lt;http://blog.suspended-chord.info/2014/01/28/intro-to-leo-scripting/&gt;`_.

.. ``Ctrl-B (execute-script)`` executes the body text of the presently selected node. Guided by Leo's markup, execute-script **composes** the script from the node and possibly some or all of its descendants.

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

**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" rst_http_attribute="5d71002858460000003c6120636c6173733d22746172676574222069643d22687474702d6e6f64652d6d61726b65722d323722206e616d653d22687474702d6e6f64652d6d61726b65722d3237223e710158040000003c2f613e71025d710328582e0000003c64697620636c6173733d2273656374696f6e222069643d227570646174696e672d7468652d73637265656e223e710458060000003c2f6469763e71055d710628583f0000003c64697620636c6173733d22646f63756d656e74222069643d22636861707465722d372d736372697074696e672d6c656f2d776974682d707974686f6e223e710758060000003c2f6469763e71085d71092858060000003c626f64793e710a58070000003c2f626f64793e710b5d710c2858430000003c68746d6c20786d6c6e733d22687474703a2f2f7777772e77332e6f72672f313939392f7868746d6c2220786d6c3a6c616e673d22656e22206c616e673d22656e223e710d58070000003c2f68746d6c3e710e4e6565656558070000003c2f6469763e0a710f583a0000003c64697620636c6173733d2273656374696f6e222069643d22696e766f6b696e672d636f6d6d616e64732d66726f6d2d73637269707473223e0a711058760000003c68313e3c6120636c6173733d22746f632d6261636b7265662220687265663d22236964313422206e616d653d22696e766f6b696e672d636f6d6d616e64732d66726f6d2d73637269707473223e496e766f6b696e6720636f6d6d616e64732066726f6d20736372697074733c2f613e3c2f68313e0a7111652e">Leo dispatches commands using c.doCommand, which calls the "command1" and "command2" hook routines for the given label. c.doCommand catches all exceptions thrown by the command::

    c.doCommand(c.markHeadline,label="markheadline")

You can also call command handlers directly so that hooks will not be called::

    c.markHeadline()

You can invoke minibuffer commands by name.  For example::

    c.executeMinibufferCommand('open-outline')

c.keyHandler.funcReturn contains the value returned from the command. In many cases, as above, this value is simply 'break'.
</t>
<t tx="ekr.20040403173920.19" rst_http_attribute="5d71002858460000003c6120636c6173733d22746172676574222069643d22687474702d6e6f64652d6d61726b65722d323922206e616d653d22687474702d6e6f64652d6d61726b65722d3239223e710158040000003c2f613e71025d71032858390000003c64697620636c6173733d2273656374696f6e222069643d22696e766f6b696e672d636f6d6d616e64732d66726f6d2d73637269707473223e710458060000003c2f6469763e71055d710628583f0000003c64697620636c6173733d22646f63756d656e74222069643d22636861707465722d372d736372697074696e672d6c656f2d776974682d707974686f6e223e710758060000003c2f6469763e71085d71092858060000003c626f64793e710a58070000003c2f626f64793e710b5d710c2858430000003c68746d6c20786d6c6e733d22687474703a2f2f7777772e77332e6f72672f313939392f7868746d6c2220786d6c3a6c616e673d22656e22206c616e673d22656e223e710d58070000003c2f68746d6c3e710e4e6565656558070000003c2f6469763e0a710f583b0000003c64697620636c6173733d2273656374696f6e222069643d2267657474696e672d616e642d73657474696e672d707265666572656e636573223e0a711058780000003c68313e3c6120636c6173733d22746f632d6261636b7265662220687265663d22236964313522206e616d653d2267657474696e672d616e642d73657474696e672d707265666572656e636573223e47657474696e6720616e642073657474696e6720707265666572656e6365733c2f613e3c2f68313e0a7111652e">Each commander sets ivars corresponding to settings.

Scripts can get the following ivars of the Commands class::

    ivars = (
        'output_doc_flag',
        'page_width',
        '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::

    c.tab_width = -4    # Change this and see what happens.
    c.frame.setTabWidth(c.tab_width)
</t>
<t tx="ekr.20040403173920.24" rst_http_attribute="5d71002858460000003c6120636c6173733d22746172676574222069643d22687474702d6e6f64652d6d61726b65722d333722206e616d653d22687474702d6e6f64652d6d61726b65722d3337223e710158040000003c2f613e71025d71032858260000003c64697620636c6173733d2273656374696f6e222069643d22672d726566696e64616c6c223e710458060000003c2f6469763e71055d710628584f0000003c64697620636c6173733d2273656374696f6e222069643d2266756e6374696f6e732d666f722d66696e64696e672d616e642d6368616e67696e672d746578742d66726f6d2d73637269707473223e710758060000003c2f6469763e71085d710928583f0000003c64697620636c6173733d22646f63756d656e74222069643d22636861707465722d372d736372697074696e672d6c656f2d776974682d707974686f6e223e710a58060000003c2f6469763e710b5d710c2858060000003c626f64793e710d58070000003c2f626f64793e710e5d710f2858430000003c68746d6c20786d6c6e733d22687474703a2f2f7777772e77332e6f72672f313939392f7868746d6c2220786d6c3a6c616e673d22656e22206c616e673d22656e223e711058070000003c2f68746d6c3e71114e656565656558070000003c2f6469763e0a711258070000003c2f6469763e0a711358350000003c64697620636c6173733d2273656374696f6e222069643d2272756e6e696e672d6c656f2d696e2d62617463682d6d6f6465223e0a7114586c0000003c68313e3c6120636c6173733d22746f632d6261636b7265662220687265663d22236964313922206e616d653d2272756e6e696e672d6c656f2d696e2d62617463682d6d6f6465223e52756e6e696e67204c656f20696e206261746368206d6f64653c2f613e3c2f68313e0a7115652e">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 = 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" str_atime="1376411963.0">@pagewidth 70
@tabwidth -4

These are the sources for Leo's users guide.

They contain sphinx markup. See::

    http://sphinx.pocoo.org/
    http://docutils.sourceforge.net/docs/user/rst/quickstart.html
    
To generate these docs::

    cd leo/doc/html
    make html
    
Important files:

- doc\html\conf.py contains settings, including the name of the master toctree
  document, leo_toc.html.txt.

- leo_toc.html.txt contains a list of all file to be included.
</t>
<t tx="ekr.20040414172218.4">
################
Acknowledgements
################

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! 

Leo owes much of its visual design to MORE, possibly the most elegant computer program ever written. Leo's clone nodes are inspired by MORE.

The following deserve special thanks:

- David Brock wrote TSyntaxMemo, used in early versions of Leo.
- Terry Brown contributed many important features including Leo's user-modifiable panes, and several important plugins, including bookmarks.py and todo.py. He also pushes back against my foolish ideas.
- e inspired @button nodes, a truly brilliant idea.
- The late Bob Fitzwater kept me focused on design. Oh, how I wish he could see today's Leo.
- Jonathan M. Gilligan showed how to put the Leo icon in Leo's windows.
- Donald Knuth invented the CWEB language and literate programming.
- LeoUser (B.H.) contributed numerous plugins, including a prototype for Leo's minibuffer, and wrote jyLeo: Leo in Jython.
- The late Bernhard Mulder invented the fundamental @shadow algorithm, a stroke of genius. Bernhard also inspired Leo's generators and position class. The one-node world could not have happened without Bernhard.
- Joe Orr created tutorials and XSLT stylesheets for Leo: http://www.jserv.com/jk_orr/xml/leo.htm.
- John K. Ousterhout created tcl/Tk, used in early versions of Leo.
- Tsuchi Noko created transparent icons.
- Neal Norwitz wrote PyChecker.
- Marc-Antoine Parent urged me to use XML for Leo's file format and helped improve it.
- Paul Paterson created the plugin architecture, helped with spell checking and contributed many plugins.
- François Pinard wrote pymacs.
- Norman Ramsey created noweb and gave permission to quote from the noweb web documentation.
- Rich Ries has contributed a huge number of suggestions.
- Steven P. Schaefer pointed out security problems.
- Gil Shwartz helped with unicode support.
- Phil Straus has been a great friend and constant support.
- Kent Tenney lobbies constantly to make Leo easier to use and understand. His comment opened the door to the one-node world.
- Guido van Rossum created Python.
- Dave Winer created MORE.
- Ville M. Vainio made invaluable contributions, including the one-node world,
  the IPython bridge code and the contextmenu.py and valuespace.py plugins.
- 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.

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.

The following have contributed plugins to Leo:

Rodrigo Benenson, Pierre Bidon, Felix Breuer, Terry Brown, Mike Crowe, Josef Dalcolmo, Michael Dawson, e, Roger Erens, Andrea Galimberti, Engelbert Gruber, Timo Honkasalo, Jaakko Kourula, Maxim Krikun, Zhang Le, LeoUser, Frédéric Momméja, Bernhard Mulder, Mark Ng, Alexis Gendron Paquette, Paul Paterson, Jacob Peck, Dan Rahmel, Davide Salomoni, Ed Taekema, Kent Tenney, Brian Theado, Ville M. Vainio, Steve Zatz.

The following people have made generous donations to the Leo project: Robert Low, Nic Cave-Lynch.
</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:: uA

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::

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

For example::

    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::

    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 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 afterX methods. Indeed, u.afterX merely needs to set the bunch.undoHelper and bunch.redoHelper ivars to the methods used to undo and redo the operation. See the code for the various u.beforeX and afterX methods for guidance.

p.setDirty and p.setAllAncestorAtFileNodesDirty now return a dirtyVnodeList that all vnodes that became dirty as the result of an operation. More than one list may be generated: client code is responsible for merging lists using the pattern dirtyVnodeList.extend(dirtyVnodeList2)

See the section &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"></t>
<t tx="ekr.20050812123002.1"></t>
<t tx="ekr.20050812123002.2">Deletes p.v.rst2_http_attributename from all nodes after writing.

Deletes p.v.unknownAttributes if it then becomes empty.
</t>
<t tx="ekr.20050812123002.3"></t>
<t tx="ekr.20050812123002.4">@nocolor

If False, add_node_marker and http_support_main  do nothing.  Otherwise add_node_marker does the following:

1. add_node_marker writes a string using generate_node_marker.

Generates 'http-node-marker-'+str(number), where number is config.node_counter
(incremented each time add_node_marker is called.

2. Enables the following code in :
@color

    if config.tag == 'open2':
        http_map = self.http_map
    else:
        http_map = {}
        config.anchormap = {}
        # maps v nodes to markers.
        config.node_counter = 0
    # [snip] code to write the tree
    if config.rst2_http_server_support:
        self.http_map = http_map
</t>
<t tx="ekr.20050812123002.5"></t>
<t tx="ekr.20050812123002.6">True: call body_filter to massage text.

Removes @ignore, @nocolor, @wrap directives.
</t>
<t tx="ekr.20050812123002.7">Used differently.  See rst2_pure_document.
</t>
<t tx="ekr.20050818163826">######################
rst3 Command Reference
######################

.. _`rst3 tutorial`: tutorial-rst3.html

Please read the `rst3 tutorial`_ before reading this chapter.

This chapter covers advanced settings and features of the rst3 command. It is for power users only.

*Are you sure you want to read this chapter?* The tutorial covers everything most people need to know about the rst3 command. Leo's own documentation uses none of the features discussed here.

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

</t>
<t tx="ekr.20050818163826.10">The rst3 command defines a code-block rST directive. The primary purpose of this directive is to show formatted source code.

In rst mode you can insert the code-block directive like any other rST markup. The rst3 command generates code-block directives automatically in code mode. This directive takes one argument, a language name.  Like this::

    .. code-block:: Python

        import leo.core.leoPlugins as leoPlugins
        import leo.core.leoGlobals as g

The output looks like this::

    import leo.core.leoPlugins as leoPlugins
    import leo.core.leoGlobals as g

.. _`Scripting Tutorial`:   tutorial-scripting.html

See the `Scripting Tutorial`_ for many examples of how to use code-blocks.
</t>
<t tx="ekr.20050818163826.11">HTML files generated by the rst3 command assume that three .css (cascading style sheet) files exist in the same directory. For the HTML output to look good the following .css files should exist:

- default.css is the default style sheet that docutils expects to exist.

- leo_rst.css contains some style improvements based on Gunnar Schwant's DocFactory.

.. - silver_city.css is the style sheet that controls the syntax highlighting generated by SilverCity.

The latter two style sheets are imported at the end of the default.css.

**Important:** You can use cascading style sheets to do things that otherwise wouldn't be possible with "plain" rST. For instance, the background color of this page was specified in a body style.
</t>
<t tx="ekr.20050818163826.13">.. _ListManagerDocs.html: ListManagerDocs.html
.. _wxListManager.leo:    wxListManager.leo

The file `ListManagerDocs.html`_ is an impressive example of the kind of output that can be generated relatively easily using the rst3 command.

The source for ListManagerDocs.html is `wxListManager.leo`_. **Important**: wxListManager.leo was written for the old rst2 plugin; it could be greatly simplified if adapted for the rst3 command.

This documentation was created using the rst3 command. The source code for this documentation is in LeoDocs.leo. The source code for the rst3 command is in leoRst.py in leoPy.leo.
</t>
<t tx="ekr.20050818163826.14">Leo 5.1 substantially simplifies the code in leoRst.py. The only rules:

- All top-level commands must call rst.initSettings, which calls rst.preprocessTree.
- Code that writes body text must call rst.init_write.

``rst.d0``
    This dictionary contains the defaults for each option. Keys are the option name, *not* including the ``rst3_`` prefix. Settings in @settings trees update its entries.
    
``rst.dd``
    A dictionary of dictionaries. Keys are vnodes. Values are a dictionary of settings set in that *particular* vnode.

``rst.getOption(p,name)``
    Searches the ``rst.dd`` and ``rst.d0`` dicts, starting at ``p``, looking for an entry for ``name``. This greatly simplifies the code that creates ``rst.dd``. Surprisingly, this search makes the code about 50% faster.
</t>
<t tx="ekr.20050818163826.16">Josef Dalcolmo wrote the initial rst plugin. Timo Honkasalo, Bernhard Mulder, Paul Paterson, Kent Tenney and Steve Zatz made contributions to the rst and rst2 plugins.
</t>
<t tx="ekr.20050818163826.4">The section covers complex options arising from two equivalent problems:

- How to generate documentation from computer source code in a Leo outline.
- How to embed documentation in computer source code in a Leo outline.

*Please stop reading now if these problems don't interest you!*
</t>
<t tx="ekr.20050818163826.5">The following options are for the use of Bernhard Mulder's http plugin. The http plugin creates an http server running on a local port, typically 8130. When the http plugin is running you will see a purple message in the log window that looks something like this::

    http serving enabled on port 8130...

To use the http plugin, start a web browser and enter this url::

    http://localhost:8130/

You will see a a top level page containing one link for every open .leo file. Clicking on a link will cause the http server to pass a new page to the browser. You can use the browser's refresh button to update the top-level view in the browser after you have opened or closed files.

**Important**: See the docstring for the http plugin for information on configuring the plugin. Some of the following rst3 settings must match values of settings for the http plugin.

Here are the rst3 options that support the http plugin:

.. glossary::

``http_server_support (default: False)``
    A master switch: none of the following options have any effect unless this option is True. If True, the rst3 command does the following:

- Writes **node markers** in the rst output for use by the http plugin. Node markers are rst named hyperlink targets. By default they look like: ``.. _http-node-marker-N``, where N is a unique node number.

- Adds additional information to all nodes of the tree being formatted using Leo's unknownAttributes mechanism.

``http_attributename (default: rst_http_attribute)``
    The name of the attribute name written to the ``unknownAttributes`` attribute of each outline node in the rst root tree. The default is ``rst_http_attribute``. It should match this setting: ``@string rst_http_attributename = rst_http_attribute``.

``clear_http_attributes (default: False)``
    **True**: the rst3 command initially clears the fields specified by `http_attributename`.  

``node_begin_marker (default: http-node-marker-)``
    The string used for node markers.
</t>
<t tx="ekr.20050818163826.7">Any headline that starts with @rst- controls the rst3 command.

.. glossary::
    :sorted:

..  @rst-code &lt;section&gt; 
..      Enter code mode. (Code mode is covered in the advanced topics sections)
..      Create a section if the show_headlines option is True.

``@rst-ignore &lt;ignored-text&gt;``
    Ignore the node, but *not* its descendants.

``@rst-ignore-node &lt;ignored-text&gt;``
    Same as `@rst-ignore`.

``@rst-ignore-tree &lt;ignored-text&gt;``
    Ignore the node and its descendants.

``@rst-no-head &lt;ignored-text&gt;``
    Ignore the headline but not the body text of this node. *This option has no effect on descendant nodes*.

``@rst-no-headlines &lt;ignored-text&gt;``
    Ignore the headline of this node and descendant nodes.
    
``@rst-table &lt;ignored text&gt;``
    Ignore headlines and write exactly one newline at the end of this node and all descendant nodes. Very useful for creating rST tables.

``@rst-option &lt;option&gt; = &lt;value&gt;``
    Set a single option to the given value. The default value is True.

``@rst-options &lt;ignored-text&gt;``
    Set options from body text. The body text should contain nothing but
    lines of the form ``&lt;option&gt;=&lt;value&gt;``

``@rst-preformat &lt;ignored-text&gt;``
    Format the body text of the node as computer source code. In effect, this option adds a line containing '::' at the start of the body text. The option then indents all following lines. *This option has no effect on descendant nodes*.

..  @rst-rst
..      Enter rst mode. (Rst mode is the mode of operation discussed in the tutorial.)
..      Create a section if the show_headlines option is True.
</t>
<t tx="ekr.20050818163826.8">**Option doc parts** set rst3 options. Option doc parts start with ``@ @rst-options`` followed by lines of the form ``name=value``. Comment lines starting with ``..`` are allowed. For example::

    @ @rst-options
    .. This comment line is ignored.
    show_headlines=False
    show_leo_directives=False
    verbose=True
    @c

This is a real Leo doc part. Like all other doc parts an option doc part starts with ``@`` and continues until the end of body text or until the next ``@c``.
</t>
<t tx="ekr.20050818163826.9">Settings in leoSettings.leo or myLeoSettings.leo specify the defaults to be used for all rst3 options.  The form of these settings is::

    @bool rst3_&lt;option name&gt; = True/False
    @string rst3_&lt;option name&gt; = aString

That is, to create a default value for an rst3 setting, you must prefix the option name with ``rst3_``.  For example::

    @bool rst3_write_intermediate_file = True
</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
</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`: http://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. For example, see http://www.3dtree.com/ev/e/sbooks/leo/sbframetoc_ie.htm In this case, the upper window of Leo is the meta-structure, and the bottom window is the file to which the meta-structure is being applied, viewed one node at a time.

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

Some other cool things about Leo which Word doesn't feature:
1. Pure xml output that is easy to transform into other formats (next version of Word will have true XML format, but not as easy to work with). One consequence of this is that Leo files can be transformed pretty easily to web pages with their outlining capability intact.
2. Easy to add features since is programmed in 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

.. _`Thrive`: https://refiction.com/resource-reviews/leo-editor-for-writers

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

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

"A Leo file is an ideal documentation tool, collecting the assorted readme.txt files, the comments from the source files...as well as the config files themselves."---Kent Tenney
</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: http://snippy.ceejbot.com/wiki/show/start/2003/01/29/001 She said: 'You'd need a bulldozer to start refactoring it.' That was my cue to write a long message explaining that there is indeed such a bulldozer and it's called Leo. (You can see my message there as a reply to her original posting.) I gave her my recipe for how to get someone else's messy, scary code into Leo and how to break it down into manageable chunks."---Dan Winkler

"Ed, you continue to push the envelope. The amazing thing is that the footprint isn't doubling every few months like it would be in another designer's hands. Adding features by removing constraints, hot refactoring while adding unit tests. Forget the book. I would pay to see the movie."
</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" str_atime="1376412852.0">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: http://sourceforge.net/forum/message.php?msg_id=3240374

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

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

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

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

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

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

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

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

In Excel you would see 4500 below those two numbers. This is completely independent of where the block of three cells exists on the sheet.
</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">Here is a posting which might be helpful: http://sourceforge.net/forum/message.php?msg_id=2300457 The @first directive_ is the key to output usable code in unsupported languages. For example, to use Leo with the Basic language, use the following::

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

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

    $IFDEF LEOHEADER &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" str_atime="1376412984.0"></t>
<t tx="ekr.20050830115714.29">See the instructions are in LeoPy.leo in::

    Notes:How To:How to add support for a new language section.

This section contains clones of all relevant parts of Leo that you will change. Coming in Leo 4.4: Leo will use JEdit's language description files to drive the syntax colorer. To add support for a new language, just add another such description file.
</t>
<t tx="ekr.20050830115714.30" str_atime="1376412828.0">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" str_atime="1376412985.0"></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:           http://docutils.sourceforge.net/
.. _`git repository`:   https://github.com/leo-editor/leo-editor
.. _unicode:            http://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" str_atime="1376412842.0">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.20050830120857">The trick is to create a workflow that separates editing from testing. Putting test code in LeoPy.leo would waste a lot of time. To run tests you would have to exit Leo and reload LeoPy.leo. A much quicker way is to put all test code in a test.leo file. So to change and test code, do the following:

1. Save LeoPy.leo but do **not** exit Leo.

2. Quit the copy of Leo running test.leo, then reload test.leo.

3. Run test scripts from test.leo.

That's all. Python will recompile any changed .py files in the new copy of Leo. **Note**: I create a batch file called t.bat that runs test.leo, so to the "edit-reload-test" cycle is just:

1. Control-S (in LeoPy.leo: saves the .leo file)
2. t (in a console window: runs test.leo, compiling all changed .py files as a side effect)
3. Control-E (in test.leo: runs the test script)

The benefits of the new workflow:

- test.leo loads  _much_ more quickly than LeoPy.leo does. This new approach can increase the speed of the edit-reload-test cycle by more than a factor of 10. Hitting Control-S, t, Control-E takes about 5 seconds.

- LeoPy.leo runs with the *old* code, so it is much easier to fix syntax errors or exceptions in the *new* code: just fix the problem and save LeoPy.leo *without* closing LeoPy.leo, then restart test.leo. You run your tests on the new code, but you edit the new code with the old, stable code.

- test.leo is the perfect place to develop test. I can create and organize those tests and when I am done, ''test.leo'' is a log of my work.
</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:
http://leoeditor.com/installing.html

For everything a beginner needs to know about Leo see:
http://leoeditor.com/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`: http://www.logilab.org/857

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::

        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 `Specifying settings`_ for a description of how to change Leo's settings.

.. contents:: Contents
    :depth: 3
    :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 Final went out the door 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 Final was released 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.

::

    The debut of @all, @test and @suite
    The mod_scripting plugin creates script buttons
    A much faster and more robust spell checker plugin
    Leo saves t.unknownAttributes in the root nodes of @thin trees
    New iterators</t>
<t tx="ekr.20050902105852.12">Leo 4.3 final was released May 23, 2005.  This release 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.

::

    Leo stores recent files in .leoRecentFiles.txt files
    Added PluginsManager plugin
    Support for extensions in the leo/extensions directory
    Leo predefines c, g and p in scripts and @test nodes
    
Leo 4.3.3 final went out the door September 17, 2005.  It added 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 an wxWindows version of Leo. This did not work out, but something good did come from this effort. I spent a lot of time adding Python scripting to the wxWindows code and I became familiar with Python and its internals.

I really started to 'get' Python in September 2001. I wrote the white papers at about this time. Python solved *all* my programming problems. I rewrote Leo in Python in about two months! For the first time in my career I was no longer anxious while programming; it simply isn't possible to create bad bugs in Python. The Python version of Leo was the first officially OpenSoftware version of Leo. The first functional version of Leo in Python was 0.05 alpha, December 17, 2001.

In October of 2001 I began work on the leo.py, an Open Software version of leo.py, a version of Leo written in Python and Tk.  At last I have found the proper platform for Leo.  leo.py naturally supports scripting in Python.  The combination of Python and Tk is incredibly powerful, very easy to use, and truly cross platform.  I rewrote Leo in Python in about two months!  For the first time in my career I no longer am anxious while programming; it simply isn't possible to create bad bugs in Python.

Tk was officially retired in June 2011.
</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:

- Nested @others directives appeared in 3.2.
- Unicode support started in 3.3.
- @first and @last appeared in 3.7
- @asis and @nosent appeared in 3.8.
- Incremental syntax coloring and incremental undo appeared in 3.9.
- Paul Paterson created Leo's plugin architecture sometime during this period.
- 3.12 fixed a huge memory leak.
- 3.12 Final, the last 3.x version, appeared July 17, 2003.
</t>
<t tx="ekr.20050902105852.9">In late 2002 and throughout 2003 I worked on an entirely new file format. 4.0 final went out the door October 17, 2003.

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!

::

    - Added support for uA's
    - Eliminated child indices, extraneous blank lines and @body sentinels
    - Eliminated @node sentinels
    - New @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)::

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

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

    leoPlugins.registerHandler("idle", on_idle)

causes Leo to call on_idle at "idle" time.

Event handlers must have the following signature::

    def myHook (tag, keywords):
        whatever

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

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

    c = keywords.get('c')
</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.

**Important**: Ever since Leo 4.2, the v, old_v and new_v keys in
the keyword dictionary contain *positions*, not vnodes. These keys are
deprecated. The new_c key is also deprecated. Plugins should use the c key instead.

============================= ======== =================================== =============================
Event name (tag argument)     Stop?    When called                         Keys in keywords dict
============================= ======== =================================== =============================
'after-auto'                           after each @auto file loaded        c,p (note 13)
'after-create-leo-frame'               after creating any frame            c
'after-redraw-outline'                 end of tree.redraw                  c (note 6)
'before-create-leo-frame'              before frame.finishCreate           c
'bodyclick1'                   yes     before normal click in body         c,p,v,event
'bodyclick2'                           after normal click in body          c,p,v,event
'bodydclick1'                  yes     before double click in body         c,p,v,event
'bodydclick2'                          after  double click in body         c,p,v,event
'bodykey1'                     yes     before body keystrokes              c,p,v,ch,oldSel,undoType
'bodykey2'                             after  body keystrokes              c,p,v,ch,oldSel,undoType
'bodyrclick1'                  yes     before right click in body          c,p,v,event
'bodyrclick2'                          after  right click in body          c,p,v,event
'boxclick1'                    yes     before click in +- box              c,p,v,event
'boxclick2'                            after  click in +- box              c,p,v,event
'clear-all-marks'                      after clear-all-marks command       c,p,v
'clear-mark'                           when mark is set                    c,p,v
'close-frame'                          in app.closeLeoWindow               c
'color-optional-markup'        yes *   (note 7)                            colorer,p,v,s,i,j,colortag (note 7)
'command1'                     yes     before each command                 c,p,v,label (note 2)
'command2'                             after  each command                 c,p,v,label (note 2)
'create-optional-menus'                (note 8)                            c (note 8)
'create-popup-menu-items'              in tree.OnPopup                     c,p,v,event (new)
'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
'hypercclick1'                 yes     before control click in hyperlink   c,p,v,event
'hypercclick2'                         after  control click in hyperlink   c,p,v,event
'hyperenter1'                  yes     before entering hyperlink           c,p,v,event
'hyperenter2'                          after  entering hyperlink           c,p,v,event
'hyperleave1'                  yes     before leaving  hyperlink           c,p,v,event
'hyperleave2'                          after  leaving  hyperlink           c,p,v,event
'iconclick1'                   yes     before single click in icon box     c,p,v,event (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'                        yes     before opening any file             c,old_c,new_c,fileName (note 4)
'open2'                                after  opening any file             c,old_c,new_c,fileName (note 4)
'openwith1'                    yes     before Open With command            c,p,v,d (note 14)
'openwith2'                            after  Open With command            c,p,v,(note 14)
'recentfiles1'                 yes     before Recent Files command         c,p,v,fileName,closeFlag
'recentfiles2'                         after  Recent Files command         c,p,v,fileName,closeFlag
'redraw-entire-outline'        yes     start of tree.redraw                c (note 6)
'save1'                        yes     before any Save command             c,p,v,fileName
'save2'                                after  any Save command             c,p,v,fileName
'scan-directives'                      in scanDirectives                   c,p,v,s,old_dict,dict,pluginsList (note 10)
'select1'                      yes     before selecting a position         c,new_p,old_p,new_v,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,old_v,old_v
'\@url1'                        yes     before double-click @url node       c,p,v,url (note 5)
'\@url2'                                after  double-click @url node       c,p,v(note 5)
============================= ======== =================================== =============================

**Notes**:

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

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

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

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

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

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

    You can use old_c.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.  These hooks are useful for testing.

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

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

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

10. g.scanDirectives calls 'scan-directives' hook.
    g.scanDirectives returns a dictionary, say d.
    d.get('pluginsList') is an a list of tuples (d,v,s,k) where:

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

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

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

12. Leo calls the 'headkey1' and 'headkey2' when the headline *might* have 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
</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" str_atime="1376413508.0">#######
Plugins
#######

This chapter discusses the plugins contained in leoPlugins.leo. These plugins 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: http://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: http://www.jedit.org/
.. _`jEdit's documentation`: http://www.jedit.org/42docs/users-guide/writing-modes-part.html

The `jEdit`_ editor drives its syntax colorer using xml **language description files.** Rather than using the xml language description files directly, Leo uses Python **colorer control files**, created automatically from the xml files by a script called jEdit2Py.  All these files reside in the leo/modes directory.

These Python files contain all the information in the jEdit's xml files, so we can (loosely) speak of modes, rulesets, rules, properties and attributes in the Python colorer control files. Later sections of this documentation will make this loose correspondence exact.

`jEdit's documentation`_ contain a complete description of these xml files. Each xml file describes one **colorizing mode**. A mode consists of one or more **rulesets**, and each ruleset consists of a list of **colorizing rules**. In addition, modes, rulesets and rules may have associated **properties** and **attributes**. Various rules may specify that the colorizer uses another ruleset (either in the same mode or another mode).

**Important**: jEdit's xml language description files contain no explicit &lt;RULE&gt; elements Rules are simply sub-elements of an enclosing &lt;RULES&gt; element. The element indicates the kind of rule that is specified, for example, &lt;SPAN&gt;, &lt;SEQ&gt;, etc. By the term **rule element** we shall mean any sub-element of the &lt;RULES&gt; element.

**Important**: throughout this documentation, **x.py** will refer to the Python colorer for language x, and **x.xml** will refer to the corresponding xml language-description file.

Using Python colorer control files has the following advantages:

- Running jEdit2Py need only be done when x.xml changes, and the speed of the xml parser in jEdit2Py does not affect the speed of Leo's colorizer in any way. Moreover, the jEdit2Py script can contain debugging traces and checks.

- Colorer control files are valid .py files, so all of Python's import optimizations work as usual. In particular, all the data in colorer control files is immediately accessible to Leo's colorer.

- Colorer control files are easier for humans to understand and modify than the equivalent xml file. Furthermore, it is easy to insert debugging information into Python colorer control files.

- It is easy to modify the Python colorer control files 'by hand' without changing the corresponding xml file. In particular, it would be easy to define entirely new kinds of pattern-matching rules in Python merely by creating functions in a colorer control file.
</t>
<t tx="ekr.20060430221745"></t>
<t tx="ekr.20060430221745.1">###########################
Controlling Syntax Coloring
###########################

This chapter discusses the settings to control Leo's syntax colorer. This chapter also discusses how to extend Leo's colorizer by creating xml language descriptions files and corresponding Python files. **Important**: this material is for those who want to support Leo's colorizing code. To use Leo's colorizers you only need to know about syntax-coloring settings.

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

</t>
<t tx="ekr.20060502084233">When Leo's syntax colorer sees the '@language x' directive, it will import x.py from Leo's modes folder. The colorer can then access any module-level object obj in x.py as x.obj.

Colorizer control files contain **rules functions** corresponding to rule elements in x.xml. The colorizer can call these functions as if they were members of the colorizer class by passing 'self' as the first argument of these functions. I call these rules *functions* to distinguish them from the corresponding **rules methods** which are actual methods of the colorizer class. Rules *functions* merely call corresponding rules *methods*. Indeed, rules functions are simply a way of binding values to keyword arguments of rules methods. These keywords arguments correspond to the xml attributes of rule elements in x.xml.

The colorizer calls rules functions until one matches, at which point a range of text gets colored and the process repeats. The inner loop of the colorizer is this code::

    for f in self.rulesDict.get(s[i],[]):
        n = f(self,s,i)
        if n &gt; 0:
            i += n ; break
        else: i += 1

- rulesDict is a dictionary whose keys are rulesets and whose values are ruleset dictionaries.
  Ruleset dictionaries have keys that are single characters and whose values are
  the list of rules that can start with that character. 

- s is the full text to be colorized.

- i is the position within s is to be colorized.

Rules methods (and functions) return n &gt; 0 if they match, and n == 0 if they fail.
</t>
<t tx="ekr.20060502084233.1">The following sections describe the top-level data in x.py.
</t>
<t tx="ekr.20060502090516">**x.properties** is a Python dictionary corresponding to the &lt;PROPS&gt; element in x.xml. Keys are property names; values are strings, namely the contents of &lt;PROPERTY&gt; elements in x.xml. x.properties contains properties for the entire mode. That is, only modes have &lt;PROPS&gt; elements. For example, here is x.properties in php.py::

    # properties for mode php.xml
    properties = {
        "commentEnd": "--&gt;",
        "commentStart": "&lt;!--",
        "indentCloseBrackets": "}",
        "indentOpenBrackets": "{",
        "lineUpClosingBracket": "true",
    }
</t>
<t tx="ekr.20060502090516.1">x.py contains a **keyword dictionary** for each ruleset in x.xml. x.py contains an empty keywords dictionary if a ruleset contains no &lt;KEYWORDS&gt; element.

Keys are strings representing keywords of the language describe by the mode. Values are strings representing syntactic categories, i.e. a TYPE attribute valid in x.xml, namely: COMMENT1, COMMENT2, COMMENT3, COMMENT4, FUNCTION, KEYWORD1, KEYWORD2, KEYWORD3, KEYWORD4, LABEL, LITERAL1, LITERAL2, LITERAL3, LITERAL4, MARKUP, NULL and OPERATOR.

For example, here (parts of) some keyword dictionaries in php.py::

    # Keywords dict for mode php::PHP
    php_PHP_keywords_dict = {
        "COM_invoke": "keyword2",
        "COM_load": "keyword2",
        "__CLASS__": "keyword3",
        ...
        "abs": "keyword2",
        "abstract": "keyword1",
        "accept_connect": "keyword2",
        ...
    }

    # Keywords dict for mode php::JAVASCRIPT_PHP
    php_JAVASCRIPT_PHP_keywords_dict = {}

    # Keywords dict for mode php::PHPDOC
    php_PHPDOC_keywords_dict = {
        "@abstract": "label",
        "@access": "label",
        "@author": "label",
        ...
        "@var": "label",
        "@version": "label",
    }

x.py also contains **x.keywordsDictDict**. Keys are ruleset names, values are keywords dictionaries. Here is keywordsDictDict for php.py::

    # Dictionary of keywords dictionaries for php mode.
    keywordsDictDict = {
        "php_javascript": php_javascript_keywords_dict,
        "php_javascript_php": php_javascript_php_keywords_dict,
        "php_main": php_main_keywords_dict,
        "php_php": php_php_keywords_dict,
        "php_php_literal": php_php_literal_keywords_dict,
        "php_phpdoc": php_phpdoc_keywords_dict,
        "php_tags": php_tags_keywords_dict,
        "php_tags_literal": php_tags_literal_keywords_dict,
    }

The colorizer can get the keywords dictionary for a ruleset as follows::

    keywordsDict = x.keywordsDictDict(rulesetName)

**Note**: The jEdit2Py script creates 'friendly' names for keyword dictionaries *solely* as an aid for people reading the code. Leo's colorer uses only the name x.keywordsDictDict; Leo's colorer never uses the actual names of keywords dictionaries such as php_PHPDOC_keywords_dict.
</t>
<t tx="ekr.20060502090516.2">x.py contains one **rule function** for every rule in every ruleset (&lt;RULES&gt; element) in x.xml. These rules have names rule1 through  ruleN, where N is the total number of rules in all rulesets in x.xml.

Each rules *function* merely calls a rules *method* in Leo's colorizer. Which method gets called depends on the corresponding element in `x.xml`. For example, the first rule in php.xml is::

    &lt;SPAN TYPE="MARKUP" DELEGATE="PHP"&gt;
		&lt;BEGIN&gt;&amp;lt;?php&lt;/BEGIN&gt;
		&lt;END&gt;?&amp;gt;&lt;/END&gt;
	&lt;/SPAN&gt;

and the corresponding rule function is::

    def php_rule0(colorer, s, i):
        return colorer.match_span(s, i, kind="markup", begin="&lt;?php", end="?&gt;",
            at_line_start=False, at_whitespace_end=False, at_word_start=False,
            delegate="PHP",exclude_match=False,
            no_escape=False, no_line_break=False, no_word_break=False)


php_rule0 calls colorer.match_span because the corresponding xml rule is a &lt;SPAN&gt; element.

For each ruleset, x.py also contains a **rules dictionary**, a Python dictionary whose keys are characters and whose values are all lists of rules functions that that can match the key. For example::

    # Rules dict for phpdoc ruleset.
    rulesDict8 = {
        "*": [rule64,],
        "0": [rule70,],
        "1": [rule70,],
        "2": [rule70,],
        "3": [rule70,],
        "4": [rule70,],
        "5": [rule70,],
        "6": [rule70,],
        "7": [rule70,],
        "8": [rule70,],
        "9": [rule70,],
        "&lt;": [rule65,rule66,rule67,rule68,rule69,],
        "@": [rule70,],
        "A": [rule70,],
        "B": [rule70,],
        ...
        "X": [rule70,],
        "Y": [rule70,],
        "Z": [rule70,],
        "_": [rule70,],
        "a": [rule70,],
        "b": [rule70,],
       ...
        "x": [rule70,],
        "y": [rule70,],
        "z": [rule70,],
        "{": [rule63,],
    }

**Note**: The order of rules in each rules list is important; it should be the same as rules element in x.xml.

Finally, x.py contains **x.rulesDictDict**. Keys are ruleset names, values are rules dictionaries. The colorer can get the rules list for character ch as follows::

    self.rulesDict = x.rulesDictDict.get(rulesetName) # When a mode is inited.
    ...
    rules = self.rulesDict.get(ch,[]) # In the main loop.

For example, here is the rules dictionary for php.py::

    # x.rulesDictDict for php mode.
    rulesDictDict = {
        "php_javascript": rulesDict6,
        "php_javascript_php": rulesDict7,
        "php_main": rulesDict1,
        "php_php": rulesDict4,
        "php_php_literal": rulesDict5,
        "php_phpdoc": rulesDict8,
        "php_tags": rulesDict2,
        "php_tags_literal": rulesDict3,
    }

**Note**: The jEdit2Py script creates 'friendly' names for rules lists *solely* as an aid for people reading the code. Leo's colorer uses only the name x.rulesDictDict; Leo's colorer never uses the actual names of rules lists such as rulesDict8, and Leo's colorer never uses the actual names of rules functions such as rule64.
</t>
<t tx="ekr.20060502100550">A **ruleset name** is a Python string having the form 'x_setname', where setname is the value of the SET attribute of the &lt;RULES&gt; element in x.xml. For example, the ruleset name of the ruleset whose SET attribute is JAVASCRIPT in php.xml is 'php_JAVASCRIPT'. **Important**: by convention, the ruleset name of the default &lt;RULES&gt; element is 'x_main'; note that default &lt;RULES&gt; element have no SET attributes.

The colorizer uses ruleset names to gain access to all data structures in x.py. To anticipate a bit, ruleset names are keys into two standard dictionaries, x.rulesDict and x.keywordsDictDict, from which the colorizer can get all other information in x.py::

    # The rules list for the 'JAVASCRIPT' ruleset in php.xml.
    rules = x.rulesDict('php_JAVASCRIPT')

    # The keywords dict for the 'JAVASCRIPT' ruleset in php.xml.
    keywordsDict = x.keywordsDictDict('php_JAVASCRIPT')

In fact, ruleset names (and x.rulesDict and x.keywordsDictDict) are the **only** names that the colorizer needs to know in order to access all information in x.py.
</t>
<t tx="ekr.20060502122950">This section describes each rules method in Leo's new colorizer. Rules methods are called by rules functions in colorizer control file; they correspond directly to rules elements in jEdit's language description files. In fact, this documentation is a 'refactoring' of `jEdit's documentation`_.

All rule methods attempt to match a pattern at a particular spot in a string. These methods all return True if the match succeeds.
</t>
<t tx="ekr.20060502122950.10">::

    def match_eol_span_regexp (self,s,i,kind,regex,
        at_line_start = False,
        at_whitespace_end = False,
        at_word_start = False,
        delegate = '',
        exclude_match = False):

match_eol_span_exp succeeds if:

1. The regular expression regex matches at s[i:], and

2. The at_line_start, at_whitespace_end and at_word_start conditions are all satisfied.

If successful, match_eol_span_regexp  highlights from i to the end of the line. If the exclude_match argument is True, only the text before the matched text will be colored. The delegate argument, if present, specifies the ruleset to color the colored text.
</t>
<t tx="ekr.20060502122950.13">::

    def match_keywords (self,s,i):

match_keywords succeeds if s[i:] starts with an identifier contained in the mode's keywords dictionary d.

If successful, match_keywords colors the keyword. match_keywords does not take a kind keyword argument. Instead, the keyword is colored as specified by d.get(theKeyword).
</t>
<t tx="ekr.20060502122950.14">::

    def match_mark_following (self,s,i,kind,pattern,
        at_line_start = False,
        at_whitespace_end = False,
        at_word_start = False,
        exclude_match = False):

match_mark_following succeeds if s[i:].startswith(pattern), and the at_line_start, at_whitespace_end and at_word_start conditions are all satisfied.

If successful, match_mark_following colors from i to the start of the next token with the color specified by kind. If the exclude_match argument is True, only the text after the matched text will be colored.
</t>
<t tx="ekr.20060502122950.40">::

    def match_seq (self,s,i,kind,seq,
        at_line_start = False,
        at_whitespace_end = False,
        at_word_start = False,
        delegate = ''):

match_seq succeeds if s[i:].startswith(seq) and the at_line_start, at_whitespace_end and at_word_start conditions are all satisfied.

If successful, match_seq highlights from i to the end of the sequence with the color specified by kind. The delegate argument, if present, specifies the ruleset to color the colored text.
</t>
<t tx="ekr.20060502122950.41">::

    def match_seq_regexp (self,s,i,kind,regex,
        at_line_start = False,
        at_whitespace_end = False,
        at_word_start = False,
        delegate = ''):

match_seq succeeds if:

1. The regular expression regex matches at s[i:], and

2. The at_line_start, at_whitespace_end and at_word_start conditions are all satisfied.

If successful, match_seq_regexp highlights from i to the end of the sequence with the color specified by kind. The delegate argument, if present, specifies the ruleset to color the colored text.
</t>
<t tx="ekr.20060502122950.42">::

    def match_span (self,s,i,kind,begin,end,
        at_line_start = False,
        at_whitespace_end = False,
        at_word_start = False,
        exclude_match = False,
        delegate = ''
        no_escape = False,
        no_line_break = False,
        no_word_break = False):

match_span succeeds if there is an index j &gt; i such that s[:i].startswith(begin) and s[i:j].endswith(end) and the at_line_start, at_whitespace_end, at_word_start, no_escape, no_line_break and no_word_break conditions are all satisfied.

If successful, match_span highlights from s[i:j with the color specified by kind; but if the exclude_match argument is True, the begin and end text are not colored. The delegate argument, if present, specifies the ruleset to color the colored text.
</t>
<t tx="ekr.20060502122950.47">::

    def match_span (self,s,i,kind,regex,end,
        at_line_start = False,
        at_whitespace_end = False,
        at_word_start = False,
        exclude_match = False,
        delegate = ''
        no_escape = False,
        no_line_break = False,
        no_word_break = False):

match_span_regex succeeds if:

1. The regular expression regex matches at s[i:],

2. There is an index j &gt; i such that s[i:j].endswith(end),

3. The at_line_start, at_whitespace_end, at_word_start,
   no_escape, no_line_break and no_word_break conditions are all satisfied.

If successful, match_span colors s[i:j], with the color specified by kind; but if the exclude_match argument is True, the begin and end text are not colored. The delegate argument, if present, specifies the ruleset to color the colored text.
</t>
<t tx="ekr.20060502122950.48">::

    def match_terminate (self,s,i,kind,at_char):

match_terminate succeeds if s[i:] contains at least at_char more characters.

If successful, match_terminate colors at_char characters with the color specified by kind.
</t>
<t tx="ekr.20060502122950.7">::

    def match_eol_span (self,s,i,kind,begin,
        at_line_start = False,
        at_whitespace_end = False,
        at_word_start = False,
        delegate = '',
        exclude_match = False):

match_eol_span succeeds if s[i:].startswith(begin) and the at_line_start, at_whitespace_end and at_word_start conditions are all satisfied.

If successful, match_eol_span highlights from i to the end of the line with the color specified by kind. If the exclude_match argument is True, only the text before the matched text will be colored. The delegate argument, if present, specifies the ruleset to color the colored text.
</t>
<t tx="ekr.20060502125223">::

    def match_mark_previous (self,s,i,kind,pattern,
        at_line_start = False,
        at_whitespace_end = False,
        at_word_start = False,
        exclude_match = False):

match_mark_previous succeeds if s[i:].startswith(pattern),and the at_line_start, at_whitespace_end and at_word_start conditions are all satisfied.

If successful, match_mark_previous colors from the end of the previous token to i with the color specified by kind. If the exclude_match argument is True, only the text before the matched text will be colored.
</t>
<t tx="ekr.20060503064515">.. _`Ruleset name`: `Ruleset names`_

All rule methods take three required arguments and zero or more optional keyword arguments.

Here is a list of the required arguments and their meaning:

- **self**: An instance of Leo's colorizer.

- **s**: The string in which matches may be found.

- **i**: The location within the string at which the rule method looks for a match.

Here is a list of all optional keyword arguments and their meaning:

- **at_line_start**:
  If True, a match will succeed only if i is at the start of a line.

- **at_whitespace_end**:
  If True, the match will succeed only if i is at the first non-whitespace text in a line.

- **at_word_start**:
  If True, the match will succeed only if i is at the beginning of a word.

- **delegate**:
  If non-empty, the value of this argument is a `ruleset name`_.
  If the match succeeds, the matched text will be colored recursively with the indicate ruleset.

- **exclude_match**:
  If True, the actual text that matched will not be colored.
  The meaning of this argument varies slightly depending on whether one or two sequences are matched.
  See the individual rule methods for details.

- **kind**: A string representing a class of tokens, i.e., one of:
  'comment1', 'comment2', 'comment3', 'comment4', 'function',
  'keyword1', 'keyword2', 'keyword3', 'keyword4',
  'label', 'literal1', 'literal2', 'literal3', 'literal4',
  'markup', 'null' and 'operator'.

- **no_escape**:
  If True, the ruleset's escape character will have no effect before the end argument to match_span.
  Otherwise, the presence of the escape character will cause that occurrence of the end string to be ignored.

- **no_line_break**:
  If True, the match will not succeed across line breaks.

- **no_word_break**:
  If True, the match will not cross word breaks.

New in Leo 4.4.1 final: the regular expression rule matchers no longer get a hash_char argument
because such matchers are called only if the present search pattern starts with hash_char.
</t>
<t tx="ekr.20060503072213">x.importDict is a Python dictionary. Keys are ruleset names; values are a list of ruleset names. For example::

    # Import dict for php mode.
    importDict = {
        "php_javascript_php": ["javascript::main"],
    }

For any ruleset R whose ruleset name is N, x.importDict.get(N) is the list of rulesets names whose rulesets appear in a DELEGATE attribute of an &lt;IMPORT&gt; rule element in R's ruleset. Such **imported** ruleset are copied to the end of the R's rules list. Leo's colorizer does this copying only once, when loading ruleset R for the first time.

**Note 1**: Loading imported rulesets must be done at 'run time'. It should definitely not be done by jEdit2Py at 'compile time'; that would require running jEdit2Py on *all* .xml files whenever any such file changed.

**Note 2**:  Multiple &lt;IMPORT&gt; rule elements in a single ruleset are allowed: delegated rules are copied to the end of N's rules list in the order they appear in the ruleset.

**Note 3**: The DELEGATE attribute of &lt;IMPORT&gt; elements is, in fact, completely separate from the DELEGATE attributes of other rules as discussed in `Arguments to rule methods`_. Indeed, the DELEGATE attribute of &lt;IMPORT&gt; elements creates entries in x.importDict, which in turn causes the colorizer to append the rules of the imported ruleset to the end of the present rules list. In contrast, the DELEGATE attributes of other rules sets the delegate argument to rules methods, which in tern causes the colorizer to recursively color the matched text with the **delegated** ruleset. In short:

- The rules of **imported** rulesets are appended to the end of another rules list; the rules of **delegated** rulesets never are.

- **Imported** ruleset names appear as the values of items in x.importDict; **delegated** ruleset names appear as delegate arguments to rule methods.
</t>
<t tx="ekr.20060510085547">x.py contains a **attribute dictionary** for each ruleset in x.xml. Keys are attribute names, values strings representing the values of the attributes. This dictionary is empty if a ruleset contains no attributes. The valid keys are:

- 'default': the default token type.  'null' is the default.

- 'digit_re': a regular expression.
  Words matching this regular expression are colored with the digit token type.

- 'ignore_case': 'true' or 'false'.  Default is 'true'.

- 'highlight_digits': 'true' or 'false'.  Default is 'true'.

- 'no_word_sep': A list of characters treated as 'alphabetic' characters when matching keywords.

For example, here is one attribute dictionary in php.py::

    # Attributes dict for php_javascript ruleset.
    php_javascript_attributes_dict = {
        "default": "MARKUP",
        "digit_re": "",
        "highlight_digits": "true",
        "ignore_case": "true",
        "no_word_sep": "",
    }

x.py also contains **x.attributesDictDict**. Keys are ruleset names, values are attribute dictionaries. Here is attributesDictDict for php.py::

    # Dictionary of attributes dictionaries for php mode.
    attributesDictDict = {
        "php_javascript": php_javascript_attributes_dict,
        "php_javascript_php": php_javascript_php_attributes_dict,
        "php_main": php_main_attributes_dict,
        "php_php": php_php_attributes_dict,
        "php_php_literal": php_php_literal_attributes_dict,
        "php_phpdoc": php_phpdoc_attributes_dict,
        "php_tags": php_tags_attributes_dict,
        "php_tags_literal": php_tags_literal_attributes_dict,
    }

**Note**: The jEdit2Py script creates 'friendly' names for attribute dictionaries *solely* as an aid for people reading the code. Leo's colorer uses only the name x.attributeDictDict; Leo's colorer never uses the actual names of attribute dictionaries.
</t>
<t tx="ekr.20060527103630">A new method has been added to make it more easily to write rST code from scripts::

    c.rstCommands.writeNodeToString(p)

``writeNodeToString`` scans p's tree (p defaults to presently selected node) looking for @rst nodes. When the first @rst node is found, writeNodeToString processes the node as usual, with the following changes:

- @rst need not be followed by a filename; any filename and its extension are *ignored*.

- Only the ext argument to writeNodeToString determines the type of output produced. The valid values for the ext argument are None (for rst output), '.html', '.pdf', and '.tex'.

- Instead of writing the result to a file, writeNodeToString returns the tuple (p,s), where p is the node whose tree produced the output, and s is the output itself.

- writeNodeToString returns after processing at most one @rst node.

Scripts can easily use writeNodeToString to convert @rst trees into various kinds of output. For example::

    p,s = c.rstCommands.writeNodeToString(p,ext='html')

Notes:

- This script scans the presently selected tree for @rst nodes. In particular, if the presently selected tree does not contain an @rst node the search continues in parent trees. When an @rst node is found, it converts the node (and descendants) to html and returns p, the found @rst node and s, the html itself.

- Valid values for the ext argument are ".html", ".tex" or None (specifies rst output)

- There is some support for ext=".pdf", but this is experimental code.  Expect crashes.
</t>
<t tx="ekr.20060527105211" str_atime="1376414159.0"></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 a few more details, see `Leo 4.0: Eliminating error 'recovery'`_ in `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" str_atime="1376414161.0">.. Most of this has nothing to do with *writing* plugins.</t>
<t tx="ekr.20060612103240" str_atime="1376414163.0">###############
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.

leoPlugins.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">::

    add-editor
    delete-editor
    cycle-editor-focus
    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 Final was released May 11, 2006.  It 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).

::

    A tabbed log pane
    Autocompletion and calltips
    @mode nodes
    The **New World Order**: drawing happens immediately, not at idle time
    The **Newer World Order**: c.endUpdate is equivalent to c.redraw_now

Development on long-delayed projects accelerated after 4.4 final went out the door::

    Syntax coloring controlled using jEdit's xml language-description files
    Support for debugging scripts using external debuggers
    Leo's vnodes and tnodes can support ZODB
    Using pymacs to write Leo scripts within Emacs
    Added the leoBridge module
</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.20060822140418">Leo 4.4.1 final was released August 30, 2006.

::

    Added new colorizer plugin controlled by jEdit language description files
    Added the shadow files plugin, a precursor to @shadow
    Added support for multiple editors in the body pane
</t>
<t tx="ekr.20060830142929">.. _`Customizing Leo`: customizing.html

This section discusses only those settings that affect syntax coloring. See `Customizing Leo`_ for a general discussion of Leo's settings.

Both the old colorizer (in Leo's core) and the new colorizer (the threading_colorizer and qtGui plugins) now support @color and @font settings for colorizing options. The settings for the old colorizer are::

    comment_font, cweb_section_name_font, directive_font,
    doc_part_font, keyword_font, leo_keyword_font, section_name_font,
    section_name_brackets_font, string_font, undefined_section_name_font,
    latexBackground_font, and latex_background_font.

The settings for the new colorizer are all of the above (except keyword_font) plus the following::

    comment1_font, comment2_font, comment3_font, comment4_font, function_font,
    keyword1_font, keyword2_font, keyword3_font, keyword4_font, label_font,
    literal1_font, literal2_font, literal3_font, literal4_font, markup_font,
    null_font, and operator_font.
    
To specify a color, say for comment1, for *all* languages, create an @color node::

    @color comment1_color = blue
    
To specify a color for a **particular** language, say Python, prepend the setting name
with the language name.  For example::

    @color python_comment1_color = pink

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.20060913164304"></t>
<t tx="ekr.20060913164304.1">###################
Using ZODB with Leo
###################

.. _`ZODB`: http://www.zope.org/Wikis/ZODB/guide/zodb.html

This chapter discusses how to write Leo scripts that store and retrieve data using `ZODB`_.

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

</t>
<t tx="ekr.20060913165542.1"></t>
<t tx="ekr.20060913165542.2">This function inits the zodb. pathToZodbStorage is the full path to the zodb storage file. You can call g.init_zodb as many times as you like. Only the first call for any path actually does anything: subsequent calls for a previously opened path simply return the same value as the first call.
</t>
<t tx="ekr.20060913165542.3">This vnode method returns v2, a copy of v that is completely detached from the outline. v2.fileIndex is unrelated to v.fileIndex initially, but it may be convenient to copy this field::

    v2 = v.detach()
    v2.fileIndex = v.fileIndex
</t>
<t tx="ekr.20060913170145">.. _`Installing ZODB`: http://www.zope.org/Wikis/ZODB/guide/node3.html#SECTION000310000000000000000

To enable zodb scripting within Leo, you must set use_zodb = True in the root node of leoNodes.py. You must also install ZODB itself.  See `Installing ZODB`_ for details.

When ZODB is installed and use_zodb is True, Leo's vnode class becomes a subclass of ZODB.Persistence.Persistent. This is all that is needed to save/retrieve vnodes or tnodes to/from the ZODB.

**Important notes**:

- Scripts **should not** store or retrieve positions using the ZODB! Doing so makes sense neither from Leo's point of view nor from ZODB's point of view.

- The examples below show how to store or retrieve Leo data by accessing the so-called root of a ZODB connection. However, these are only examples. Scripts are free to do with Leo's vnodes *anything* that can be done with ZODB.Persistence.Persistent objects.
</t>
<t tx="ekr.20060913170403">Scripts should call g.init_zodb to open a ZODB.Storage file. g.init_zodb returns an instance of ZODB.DB.  For example::

    db = g.init_zodb (zodbStorageFileName)

You can call g.init_zodb as many times as you like. Only the first call for any path actually does anything: subsequent calls for a previously opened path simply return the same value as the first call.
</t>
<t tx="ekr.20060913170403.1">The following script writes v, a tree of vnodes, to zodb::

    db = g.init_zodb (zodbStorageFileName)
    connection = db.open()
    try:
        root = connection.root()
        root[aKey] = v # See next section for how to define aKey.
    finally:
        get_transaction().commit()
        connection.close()

Notes:

- v must be a vnode.
  Scripts should *not* attempt to store Leo positions in the zodb.
  v can be the root of an entire outline or a subtree.
  For example, either of the following would be reasonable::

    root[aKey] = c.rootPosition().v
    root[aKey] = c.p.v

- To write a single vnode without writing any of its children you can use v.detach.
  For example::

    root[aKey] = v.detach()

- **Important**: It is simplest if only one zodb connection is open at any one time,
  so scripts would typically close the zodb connection immediately after processing the data.
  The correct way to do this is in a finally statement, as shown above.

- The script above does not define aKey.
  The following section discusses how to define reasonable zodb keys.
</t>
<t tx="ekr.20060913170403.2">The following script reads a tree of vnodes from zodb and sets p as the root position of the tree::

    try:
        connection = db.open()
        root = connection.root()
        v = root.get(aKey)
        p = leoNodes.position(v)
    finally:
        get_transaction().commit()
        connection.close()
</t>
<t tx="ekr.20060913175437">The keys used to store and retrieve data in connection.root() can be any string that uniquely identifies the data. The following are only suggestions; you are free to use any string you like.

1. When saving a file, you would probably use a key that is similar to a real file path.
   For example::

        aKey = c.fileName()

2. When saving a single vnode or tree of vnodes, say v,
   a good choice would be to use v's gnx, namely::

        aKey = g.app.nodeIndices.toString(v.fileIndex)

   Note that v.detach() does not automatically copy v.fileIndex to the detached node,
   so when writing a detached node you would typically do the following::

       v2 = v.detach()
       v2.fileIndex = v.fileIndex
       aKey = g.app.nodeIndices.toString(v2.fileIndex)
</t>
<t tx="ekr.20060913175437.1">The scripts shown above close the zodb connection after processing the data. This is by far the simplest strategy. I recommend it for typical scripts.

**Important**: you must **leave the connection open** if your script modifies persistent data in any way. (Actually, this statement is not really true, but you must define zodb transaction managers if you intend to use multiple connections simultaneously. This complication is beyond the scope of this documentation.) For example, it would be possible to create a new Leo outline from the data just read, but the script must leave the connection open. I do not recommend this tactic, but for the adventurous here is some sample code::

    connection = self.db.open()
    root = connection.root()
    v = root.get(fileName)
    if v:
        c2 = c.new()
        c2.openDirectory = c.openDirectory # A hack.
        c2.mFileName = fileName # Another hack.
        c2.beginUpdate()
        try:
            c2.setRootVnode(v)
            c2Root = c2.rootPosition()
            c2.atFileCommands.readAll(c2Root)
            g.es_print('zodb read: %s' % (fileName))
        finally:
            c2.endUpdate()
        # Do *not* close the connection while the new Leo window is open!
    else:
        g.es_print('zodb read: not found: %s' % (fileName))


This will work **provided** that no other zodb connection is ever opened while this connection is opened. Unless special zodb precautions are taken (like defining zodb transaction managers) calling get_transaction().commit() will affect **all** open connections. You have been warned.
</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 describe the format of external files. Leo's `sentinel lines`_ are comments, and this section describes those comments.

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

New sentinels do not include @nonl or @nl. As a result, body text always ends with at least one newline.

Here are the sentinels used by Leo, in alphabetical order. Unless otherwise noted, the documentation applies to all versions of Leo. In the following discussion, gnx denotes a gnx as described above.

\@&lt;&lt;
    A sentinel of the form @&lt;&lt;section_name&gt;&gt; represents a section reference.

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

\@@
    The @@ sentinel represents any line starting with @ in body text
    except @*whitespace*, @doc and @others.
    Examples::

      @@nocolor
      @@pagewidth 80
      @@tabwidth 4
      @@code

\@afterref
    Marks non-whitespace text appearing after a section references.

\@+all
    Marks the start of text generated by the @all directive.

\@-all
    Marks the end of text generated by the @all directive.

\@at and @doc

    The @+doc @+at sentinels indicate the start of a doc parts.

..  Officially retired in Leo 5.7.4.
..  We use the following **trailing whitespace convention** to
..  determine where putDocPart has inserted line breaks::
..      A line in a doc part is followed by an inserted newline
..      if and only if the newline if preceded by whitespace.
..  To make this convention work, Leo's write code deletes the trailing
..  whitespace of all lines that are followed by a "real" newline.

\@+body **(Leo 3.x only)**
    Marks the start of body text.

\@-body **(Leo 3.x only)**
    Marks the end of body text.

\@delims
    The @delims directive inserts @@delims sentinels into the
    external file. The new delimiter strings continue in effect until
    the next @@delims sentinel *in the external file* or until the
    end of the external file. 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.

\@+leo
    Marks the start of any external file. 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.
    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
    Marks the end of the Leo file.
    Nothing but whitespace should follow this directive.

\@+middle **(Created in Leo 4.0, removed in Leo 5.3)**

\@-middle **(Created in Leo 4.0, removed in Leo 5.3)**
    Marks the start/end of intermediate nodes between the node that
    references a section and the node that defines the section.
    
    These sentinels were a **mistake** that created bugs.  See:
    https://github.com/leo-editor/leo-editor/issues/132
    
\@nl **(Leo 3.x only)**
    Insert a newline in the outline.

\@+node
    Mark the start and end of a node::

        @+node:gnx:&lt;headline&gt;
        
\@nonl **(Leo 3.x only)**
    Suppresses a newline in the outline.

\@others
    The @+others sentinel indicates the start of the expansion of an @+others          
    directive, which continues until the matching @-others sentinel.

\@verbatim
    @verbatim 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
    @verbatimAfterRef is generated when a comment following a section reference would
    otherwise be treated as a sentinel. In Python code, an example would be::

      &lt;&lt; ref &gt;&gt; #+others
</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.20061008190905">Leo 4.4.2.1 final was released October 29, 2006.

::

    The find command optionally closes nodes:
        Added @bool collapse_nodes_during_finds
        Added @bool sparse_move_outline_left
    Added support for ZODB in Leo's vnode and tnode classes
    Added support for opml files
    Added leoPymacs module
    Leo optionally began reading .leo files using a sax parser
    Added the leoOPML, slideshow, leo_to_rtf and leo_to_html plugins
    Added leoPymacs module

</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`:   http://pymacs.progiciels-bpi.ca/index.html
.. _`elisp`:    http://en.wikipedia.org/wiki/Emacs_Lisp
.. _`Emacs`:    http://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** 

   The pymacs installation instructions should be clear enough.
   A clarification is needed about two-way communication between Python and lisp scripts:
   in truth, Python scripts can call the Pymacs.lisp function *only* if the Python script
   was invoked from emacs.
   Otherwise, calling Pymacs.lisp will hang the process making the call.
   For example, executing the following script as an ordinary Leo script will hang Leo::

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

**Step 2. Load the leoPymacs module from Emacs, creating a hidden Leo application**

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

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

  The call to pymacs-load is similar to 'import leoPymacs as leo-' in
  Python. The side effect of pymacs-load is to define the elisp
  function leo-x for every top-level function x in leoPymacs.py,
  namely leo-dump, leo-get-app, leo-get-g, leo-get-script-result,
  leo-init, leo-open and leo-run-script. The first call to any of
  these functions creates a **hidden Leo application** in which .leo
  files may be loaded, modified and saved, and in which Leo scripts
  may be executed. This hidden Leo application uses Leo's nullGui
  class as its gui, so Leo commands and Leo scripts that require a
  fully functional gui will not work as expected in the hidden Leo
  application. Steps 3 and 4 tell how to use this hidden Leo
  application.

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

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

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

**Step 3. From Emacs, open .leo files**

   Once we have loaded the leoPymacs module
   we can open a .leo file as follows::

    (setq c (leo-open fileName))

   This binds the elisp c variable to the Leo commander created by opening fileName.
   fileName should be the full path to a .leo file.
   In the next step we will use this c variable to execute *Leo* scripts in the
   context of an open Leo outline.

   Sometimes we want to execute a Leo script before opening any Leo commanders.
   For example, we might want to compute the fileName passed to leo-open.
   leo-run-script allows the c argument to be nil,
   in which case leo-run-script creates a dummy commander in which to run the script.
   For example, the following script calls g.os_path_join and g.os_path_abspath::

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

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

   leo-run-script returns the value of g.app.scriptResult
   As shown above, Python scripts may set g.app.scriptResult to indicate their result.
   elisp scripts can also get g.app.scriptResult using leo-script-result.
   Note that the Python script may span multiple lines.

**Step 4. From Emacs, execute Leo (Python) scripts**

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

        (leo-run-script c aLeoScript)

   For example::

        (setq c (leo-open fileName)
        (csetq script "print 'c',c,'h',c.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 print-commands &lt;Return&gt;.
</t>
<t tx="ekr.20070115172724">.. _`embedded winpdb`: http://www.digitalpeers.com/pythondebugger/embedded.htm
.. _`winpdb`: http://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::

    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::

    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.20070316182323">Leo 4.4.3 final was released June 26, 2006. The **big reorg** made the vnode and tnode classes completely independent of the rest of Leo.

::

    Added chapters
    Added zipped .leo files
    Added a leoBridge module
    Added spell checking with aspell
    
Leo 4.4.3.1 was released July 3, 2006::

    Added better support for unit testing
</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 use the leoBridge module as follows::

    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::

    g = controller.globals()

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

The statement::

    c = controller.openLeoFile(path)

invisibly opens the .leo file given by the path argument. This call returns a completely standard Leo commander, properly inited. This is the big payoff from the leoBridge module: the host program gets instant access to c.config.getBool, etc. Do you see how sweet this is?

For example, the following script runs leo/test/leoBridgeTest.py outside of Leo. leoBridgeTest.py uses the leoBridge module to run all unit tests in leo/test/unitTest.leo::

    import os,sys

    path = g.os_path_abspath(
        g.os_path_join(
            g.app.loadDir,'..','test','leoBridgeTest.py'))

    os.system('%s %s' % (sys.executable,path))

The file leo/test/test.leo contains the source code for leoBridgeTest.py. Here it is, stripped of its sentinel lines::

    '''A program to run unit tests with the leoBridge module.'''

    import leo.core.leoBridge as leoBridge
    import leo.core.leoTest as leoTest

    def main ():
        tag = 'leoTestBridge'

        # Setting verbose=True prints messages that would be sent to the log pane.
        bridge = leoBridge.controller(gui='nullGui',verbose=False)
        if bridge.isOpen():
            g = bridge.globals()
            path = g.os_path_abspath(g.os_path_join(
                g.app.loadDir,'..','test','unitTest.leo'))
            c = bridge.openLeoFile(path)
            g.es('%s %s' % (tag,c.shortFileName()))
            runUnitTests(c,g)

        print tag,'done'

    def runUnitTests (c,g):
        nodeName = 'All unit tests' # The tests to run.
        try:
            u = leoTest.testUtils(c)
            p = u.findNodeAnywhere(nodeName)
            if p:
                g.es('running unit tests in %s...' % nodeName)
                c.selectPosition(p)
                c.debugCommands.runUnitTests()
                g.es('unit tests complete')
            else:
                g.es('node not found:' % nodeName)
        except Exception:
            g.es('unexpected exception')
            g.es_exception()
            raise

    if __name__ == '__main__':
        main()
</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:

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

**Important**: you can use the show-colors minibuffer command to guide you in making these settings.
</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
    print-bindings
    print-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"></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.20070628083442"></t>
<t tx="ekr.20070628083442.1">#####################
Unit testing with Leo
#####################

.. _`run Leo in a console window`: installing.html#running-leo-from-a-console-window

This chapter describes how you can execute Python unit test from within Leo
outlines.

Leo's **unit test commands** run the unit tests created by @test and @suite
nodes. run-unit-tests and run-unit-tests-locally run all unit tests in the
presently selected part of the Leo outline; run-all-unit-tests and
run-all-unit-tests-locally run all unit tests in the entire Leo outline.

Important: you must `run Leo in a console window`_ to see the output the
unit tests. Leo's unit test commands run all the unit tests using the
standard unittest text test runner, and the output of the unit tests
appears in the console.

test/unitTest.leo contains many examples of using @test and @suite nodes.

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

</t>
<t tx="ekr.20070628084351">**@test nodes** are nodes whose headlines start with @test. The unit test commands convert the body text of @test nodes into a unit test automatically. That is, Leo's unit test commands automatically create a unittest.TestCase instances which run the body text of the @test node. For example, let us consider one of Leo's actual unit tests. The headline is::

    @test consistency of back/next links

The body text is::

    if g.unitTesting:
        c,p = g.getTestVars() # Optional: prevents pychecker warnings.
        for p in c.all_positions():
            back = p.back()
            next = p.next()
            if back: assert(back.getNext() == p)
            if next: assert(next.getBack() == p)

When either of Leo's unit test commands finds this @test node the command will
run a unit test equivalent to the following::

    import leo.core.leoGlobals as g

    class aTestCase (unittest.TestCase):
        def shortDescription():
            return '@test consistency of back/next links'
        def runTest():
            c,p = g.getTestVars()
            for p in c.all_positions():
                back = p.back()
                next = p.next()
                if back: assert(back.getNext() == p)
                if next: assert(next.getBack() == p)

As you can see, using @test nodes saves a lot of typing:

- You don't have to define a subclass of unittest.TestCase.
- Within your unit test, the c, g and p variables are predefined, just like in Leo scripts.
- The entire headline of the @test node becomes the short description of the unit test.

**Important note**: notice that the first line of the body text is a **guard line**::

    if g.unitTesting:

This guard line is needed because this particular @test node is contained in the file leoNodes.py. @test nodes that appear outside of Python source files do not need guard lines. The guard line prevents the unit testing code from being executed when Python imports the leoNodes module; the g.unitTesting variable is True only while running unit tests.

**New in Leo 4.6**: When Leo runs unit tests, Leo predefines the 'self' variable to be the instance of the test itself, that is an instance of unittest.TestCase. This allows you to use methods such as self.assertTrue in @test and @suite nodes.

**Note**: Leo predefines the c, g, and p variables in @test and @suite nodes, just like in other scripts.  Thus, the line::

    c,p = g.getTestVars()

is not needed. However, it prevents pychecker warnings that c and p are undefined.
</t>
<t tx="ekr.20070628094515.1">**@suite nodes** are nodes whose headlines start with @suite. @suite nodes allow you to create and run custom subclasses of unittest.TestCase.

Leo's test commands assume that the body of an suite node is a script that creates a suite of tests and places that suite in g.app.scriptDict['suite']. Something like this::

    if g.unitTesting:
        __pychecker__ = '--no-reimport' # Prevents pychecker complaint.
        import unittest
        c,p = g.getTestVars() # Optional.
        suite = unittest.makeSuite(unittest.TestCase)
        &lt;&lt; add one or more tests (instances of unittest.TestCase) to suite &gt;&gt;
        g.app.scriptDict['suite'] = suite

**Note**: as in @test nodes, the guard line, 'if unitTesting:', is needed only if the
@suite node appears in a Python source file.

Leo's test commands first execute the script and then run suite in g.app.scriptDict.get('suite') using the standard unittest text runner.

You can organize the script in an @suite nodes just as usual using @others, section references, etc. For example::

    if g.unitTesting:
        __pychecker__ = '--no-reimport'
        import unittest
        c,p = g.getTestVars() # Optional.
        # children define test1,test2..., subclasses of unittest.TestCase.
        @others 
        suite = unittest.makeSuite(unittest.TestCase)
        for test in (test1,test2,test3,test4):
            suite.addTest(test)
        g.app.scriptDict['suite'] = suite
</t>
<t tx="ekr.20070628094515.2">The run-all-unit-tests-locally and run-unit-tests-locally commands run unit tests in the process that is running Leo. These commands *can* change the outline containing the unit tests.

The run-all-unit-tests and run-unit-tests commands run all tests in a separate process, so unit tests can never have any side effects. These commands never changes the outline from which the tests were run. These commands do the following:

1. Copy all @test, @suite, @unit-tests and @mark-for-unit-test nodes (including their descendants) to the file test/dynamicUnitTest.leo.

2. Run test/leoDynamicTest.py in a separate process.

   - leoDynamicTest.py opens dynamicUnitTest.leo with the leoBridge module.
     Thus, all unit tests get run with the nullGui in effect.

   - After opening dynamicUnitTest.leo, leoDynamicTest.py runs all unit tests
     by executing the leoTest.doTests function.

   - The leoTests.doTests function searches for @test and @suite nodes and
     processes them generally as described above. The details are a bit
     different from as described, but they usually don't matter. If you *really*
     care, see the source code for leoTests.doTests.
</t>
<t tx="ekr.20070806090235">Leo 4.4.4 Final was released November 2, 2007.

::

    Added @auto
    Added @menus trees
    Added @buttons trees
    Added a threading_colorizer plugin

The **Great Graph Aha**: Leo outlines can represent arbitrary directed graphs. There is no need for a separate 'graph world'. The graphed.py plugin is a direct result of this Aha.
</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" str_atime="1376412994.0">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.  File names end in .py and are resolved relative to the leo/plugins directory.  Module names do *not* end in .py and are found using Python's import mechanism--the module name must be on PYTHONPATH.

- 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: http://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::

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

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

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

    g.app.gui.runOpenFileDialog(title,filetypes,defaultextension,multiple=False)
    g.app.gui.runSaveFileDialog(initialfile,title,filetypes,defaultextension)

For details about how to use these file dialogs, look for examples in Leo's own source code. The runOpenFileDialog returns a list of file names.
</t>
<t tx="ekr.20071115102421">Leo 4.4.5 final was released December 11, 2007::

    Fixed all known bugs
    Leo now recognizes directives in headlines
</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`:     http://docs.python.org/lib/module-gettext.html
.. _Emacs:                  http://www.xemacs.org/
.. _pymacs:                 http://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::

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

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

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

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

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

    c.setCurrentPosition(pos_of_branch_to_return)
    c.copyOutline()
    print '&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::

    g.app.gui.replaceClipboardWith(response)
    c.pasteOutline()
</t>
<t tx="ekr.20071217093444"></t>
<t tx="ekr.20080106114331">Leo 4.4.6 final was released January 26, 2008.</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::

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

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

    c.editCommands.deleteFirstIcon() 
    c.editCommands.deleteLastIcon() 
    c.editCommands.deleteNodeIcons() 
</t>
<t tx="ekr.20080203101507"></t>
<t tx="ekr.20080203101507.1">##########################
ILeo: Leo's IPython Bridge
##########################

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

</t>
<t tx="ekr.20080218154129">Leo 4.4.7 final was released February 18, 2008.  This release added ipython plugin, the result of an excellent collaboration between EKR and Ville M. Vainio.
</t>
<t tx="ekr.20080310093038.4">.. _gettext: http://docs.python.org/lib/module-gettext.html

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

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

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

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

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

- You can use the script in the node "@button print g.es stats" in scripts.leo to create catalogs of all scripts that need to be translated. Such catalogs are used by Python's gettext module. (This script was also used to check that the proper arguments to g.es and g.es_print were translated.)
</t>
<t tx="ekr.20080311060457.215">Leo 4.4.8 final was released April 6, 2008.

::

    Leo's discussion is now hosted by Google Groups
    Arguments to g.es and g.es_print can be translated using gettext
</t>
<t tx="ekr.20080314081157.127"></t>
<t tx="ekr.20080315115427.568">This series of releases featured hundreds of improvements.
</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:

- @if *expression*

  A node whose headline starts with @if *expression* acts like an organizer node if the expression evaluates to True, otherwise acts like an @ignore node. If the expression is empty the body text should contain a script that will be evaluated (in an empty context).

- @ifplatform *platform-name*

  Same as @if sys.platform == "platform-name": except that it isn't necessary to import sys.

- @ifhostname *hostA,!hostB*

  Evaluates to True if and only if: h=g.computeMachineName(); h==hostA and h!=hostB. The "!" version allows matching to every machine name except the given one to allow differing settings on only a few machines.
</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.20080603124653.1">Many users will want to track the development version of Leo, in order to stay on top of the latest features and bug fixes. Running the development version is quite safe and easy, and it's also a requirement if you want to contribute to Leo.

1. First, you need to get git from http://git-scm.com/.

2. Get Leo from GitHub by doing::

        git clone https://github.com/leo-editor/leo-editor (http access)
    
   or::
   
        git clone git@github.com:leo-editor/leo-editor.git (ssh access)

And that's it! You can run the launchLeo script (in the top-level branch directory) directly. When you want to refresh the code with latest modifications from GitHub, 'run git pull'.
</t>
<t tx="ekr.20080729064227.6">The timit button in unitTest.leo allows you to apply Python's timeit module. See http://docs.python.org/lib/module-timeit.html. The contents of @button timer is::

    import leo.core.leoTest as leoTest
    leoTest.runTimerOnNode(c,p,count=100)

runTimerOnNode executes the script in the presently selected node using timit.Timer and prints the results.
</t>
<t tx="ekr.20080729064227.7">The profile button in unitTest.leo allows you to profile nodes using Python's profiler module. See http://docs.python.org/lib/module-profile.html The contents of @button profile is::

    import leo.core.leoTest as leoTest
    leoTest.runProfileOnNode(p,outputPath=None) # Defaults to leo\test\profileStats.txt

runProfileOnNode runs the Python profiler on the script in the selected node, then reports the stats.
</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, http://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::
   
    @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::
   
    @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">Scripts can easily determine what directives are in effect at a particular position in an outline. c.scanAllDirectives(p) returns a Python dictionary whose keys are directive names and whose values are the value in effect at position p. For example::

    d = c.scanAllDirectives(p) g.es(g.dictToString(d))

In particular, d.get('path') returns the full, absolute path created by all @path directives that are in ancestors of node p. If p is any kind of @file node (including @file, @auto, @clean, etc.), the following script will print the full path to the created file::

    path = d.get('path')
    name = p.anyAtFileNodeName()
    if name:
       name = g.os_path_finalize_join(path,name)
       g.es(name)
</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

**Important**: you can use the show-fonts minibuffer 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:

1. Default settings files:

   a. configDir/leoSettings.leo
   b. homeDir/leoSettings.leo
   c. localDir/leoSettings.leo

2. Personal settings files:

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

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

**Important**: 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" str_atime="1376412853.0">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-plugin node appear A's @enabled-plugin 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.
</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 http://groups.google.com/group/leo-editor
</t>
<t tx="ekr.20090130144433.2">Please consider *asking for help* at http://groups.google.com/group/leo-editor before filing bug reports.

Please report bugs at http://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.20090202191501.7">You can simply unpack Leo anywhere and run from there.  You don't need the installer.

From a console window, cd to the top-level leo folder.  Run Leo as follows::

    python launchLeo.py

To run Leo with Qt look and feel, use the --gui=qt option::

    python launchLeo.py --gui=qt

To load Leo's source, load leoPyRef.leo::

    python launchLeo.py --gui=qt leo\\core\\leoPyRef.leo
</t>
<t tx="ekr.20090212054250.5"></t>
<t tx="ekr.20090212054250.6">See `Leo's download page &lt;download.html&gt;`_.
</t>
<t tx="ekr.20090212054250.7">Daily snapshots are available `here &lt;download.html&gt;`_.
</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-2018 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.**
</t>
<t tx="ekr.20090223065025.3">**Important**: The changes you make below **will not persist** unless your script calls c.frame.body.onBodyChanged after making those changes. This method has the following signature::

    def onBodyChanged (self,undoType,oldSel=None,oldText=None,oldYview=None):

Let::

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

Scripts can get or change the context of the body as follows::

    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.20090401113141.1">To generate .odt or .rtf or .pdf files, you create an intermediate file and ignore the the "official" output file, in this case test.html. The intermediate file contains the rST text corresponding to the @rst tree.

To tell the rst3 command to generate an intermediate file, do::

    write_intermediate_file = True

After you create the intermediate file, in this case, test.html.txt, You can create an odt file as follows::

    python &lt;path-to-python&gt;/scripts/rst2odt.py test.html.txt test.odt

I a batch file, rst2odt.bat, like this:

    rst2odt test

Note that rst3odt.py is in the tools directory of the DocUtils distribution.

To generate .rtf, you can use PanDoc to convert test.html.txt to RTF.

To generate .pdf files, you would first convert test.html.txt to LaTeX::

    python rst2newlatex.py test.html.txt test.tex

    -- OR --

    cd leo\docs\html
    make latex

You can then use one of the LaTeX to .pdf converters to create the final .pdf file. See http://docutils.sourceforge.net/docs/user/latex.html#pdf-generation for details.
</t>
<t tx="ekr.20090401113141.2">====
Test
====

This is a test.
</t>
<t tx="ekr.20090401113141.4">This is section 1
</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.20090620131445.5595">I just tweaked conf.py a bit to enable pdf generation.

Howto:

QQQ

4. To create pdf (probably easiest on Linux, with necessary latex
packages installed):

- make latex
- cd _build/latex
- make all-pdf

QQQ

There were several errors in the pdf generation process. Notably,
there are probably lots of unicode errors (and toc doesn't appear).
Nevertheless, you can steal a peek at the doc here:

http://vvtools.googlecode.com/files/Leodocumentation.pdf 
</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">@language rest
@wrap

################
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.
This pane can render `reStructuredText &lt;http://docutils.sourceforge.net/rst.html&gt;`_:

.. 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.20091105080104.9031">When using the Qt gui, you specify fonts using the node in leoSettings.leo called::

    @data qt-gui-plugin-style-sheet

As usual, you will probably want to put this node in your myLeoSettings.leo file.
</t>
<t tx="ekr.20091111112709.6672">#########
Glossary
#########

.. 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`: http://www.python.org/

..  "Leo should either replace or greatly augment the development tools
..  that I use."---Zak Greant

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

..  "We who use Leo know that it is a breakthrough tool and a whole new way
..  of writing code."---Joe Orr
    
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::

    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
    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, @clean, @edit, @file, @shadow, @thin, or their longer forms. We often refer to outline nodes by the directives they contain. For example, an @file node is a node whose headline starts with @file, etc.

.. 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 pieces if an importer exists for the give filetype. Importers presently exist for the following languages: C, C++, C#, HTML, INI files, Java, PHP, Pascal, Python and XML.

.. 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. 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: @end_raw; Glossary

\@end_raw

    Ends a section of 'raw' text.

.. 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. **Important**: @file is the recommended way to create and edit most files. Using @file trees is **highly recommended** when sharing external files in a collaborative environment.

.. index::
    pair: @first; Glossary

\@first &lt;text&gt;

    The @first directive allows you to place one or more lines 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 to break doc parts 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: @raw; Glossary

\@raw
    Starts a section of "raw" text that ends *only* with the
    @end_raw directive or the end of the body text.

.. 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`: http://www.eecs.harvard.edu/~nr/noweb/

Escape convention

    A convention for representing sequences of characters that would otherwise
    have special meaning. **Important**: Leo does not support escape conventions
    used by `noweb`_. Any line containing matched &lt;\&lt; and &gt;\&gt; is a section
    reference, regardless of context. 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

Leo's `git repository`_ and Leo distributions contain the following reference files: LeoPyRef.leo, LeoPluginsRef.leo and leoGuiPluginsRef.leo. These reference files should contain nothing but @file nodes and should change only when new external files get added to the project. Developers should use *local copies* of reference files for their own work. For example, instead of using LeoPyRef.leo directly, I use a copy called LeoPy.leo.


.. index::
    pair: reStructuredText; Glossary
    pair: rST; Glossary

.. _`rST primer`: http://docutils.sourceforge.net/docs/user/rst/quickstart.html


reStructuredText (rST)

    A simple, yet powerful 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 enclosed in &lt;\&lt; and &gt;\&gt;. Section names may contain any characters
    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

Underindent 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 or when the
    @all or @raw directives are in effect.

.. 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, 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 to break doc parts 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: @path; Reference
.. index::
    pair: Absolute path; Reference
.. index::
    pair: Path prefix; Reference

\@path &lt;path&gt;

   Sets the **path prefix** for relative filenames for all @&lt;file&gt; tree.

   This directive may appear in headlines or body text, and may
   appear in top-level @&lt;file&gt; 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.
   
.. index::
    pair: @persistence; Reference
    
\@persistence
    
With @clean and @file, Leo can store **persistent data** in nodes. This information consists of the node's **gnx** (Global Node Index) and the node's **uA**, (User Attributes). The gnx gives each node a unique, immutable identity. Gnx's make clones possible. The uA allows scripts and plugins to associate arbitrarily much additional data with each node.

By default, Leo's importers preserve neither gnx's nor uA's. This makes imported @auto trees second class citizens. To remedy this, 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 later. 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.

.. 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`:         http://en.wikipedia.org/wiki/Org-mode
.. _`Emacs`:            emacs.html#using-org-mode-org-files-in-leo
.. _`markdown`:         http://en.wikipedia.org/wiki/Markdown
.. _`reStructuredText`: http://docutils.sourceforge.net/rst.html
.. _`vim outline`:      http://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

.. 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.
</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;
    
    to create comments that will be removed from the output by Genshi. 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::

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

.. index::
    pair: @raw; Reference
    pair: @end_raw; Reference

\@raw and \@end_raw

    \@raw starts a section of "raw" text that ends *only* with the @end_raw directive
    or the end of the body text containing the @raw directive. Within this
    range, Leo ignores all section references and directives, and Leo generates
    no additional leading whitespace.
</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.20100809122216.4286">Here is a complete list of options for the rst3 and code-to-rst commands:

.. glossary::
    :sorted:

``call_docutils (default: True)``
    Call docutils to process the intermediate file.

``default_path (default: '')``
    The path to be prepended to filenames given in root nodes.

``default_encoding (default: utf-8)``
    The default encoding to be used for non-ascii (unicode characters).

``generate_rst (default: True)``
    A master switch. **True**: generate rST markup for rST sections and rST code-blocks. **False**: generate plain text and ignore ``@ @rst-markup`` doc parts.

``generate_rst_header_comment (default: True)``
    **True**: Leo writes a comment line of the form ``.. rst3: filename: &lt;filename&gt;`` at the start of intermediate files. This option has effect only if the ``generate_rst`` and ``write_intermediate_file`` options are both True.

``publish-argv-for-missing-stylesheets (Default: '')``
    The arguments to be passed to ``docutils.core.Publisher().publish()`` when no stylesheet is in effect. This is a string that represents a comma-separated list of strings: For example, the option::

        publish-argv-for-missing-stylesheets=--language=de,--documentclass=report,--use-latex-toc

    results in the call::

        publish(['--language=de','--documentclass=report','--use-latex-toc'])

``show_headlines (default: True)``
    **True**: automatically generate rST sections from headlines. **False**: ignore headlines.
    
    **Note**: The level of the node in the outline determines the level of the section underlining in the rST markup. Higher-level headlines in the outline correspond to higher-level section headings; lower-level headlines in the outline correspond to lower-level section headings.

``show_organizer_nodes (default: True)``
    **True**: generate rST sections for nodes that do not contain body text. *This option has no effect unless the rST section would otherwise be written*.

``show_sections (default: True)``
    **True**: generate rST sections corresponding to headlines. **False**: Generate lines of the form ``headline`` instead of sections.
    
``silent (default: False)``
    Write only the number of files written and the time taken to the log and console.

``strip_at_file_prefixes (default: True)``
    **True**: remove ``@auto``, ``@file``, ``@clean``, and ``@thin`` from the start of headlines.

``stylesheet_name (default: 'default.css')``
    The name of the stylesheet passed to docutils.

``stylesheet_path (default: '')``
    The directory containing the stylesheet passed to docutils.
    
    **Note**: If the ``stylesheet_embed`` option is True, specify a path relative to the location of the Leo file. If the ``stylesheet_embed`` option is False, specify a path relative to the location of the HTML file.

``stylesheet_embed (default: True)``
    **True**: The content of the stylesheet file will be embedded in the HTML file. **False**: The HTML file will link to an external stylesheet file.

``underline_characters (default: #=+*^~"'\`-:&gt;\_)``
    The underlining characters to be used to specify rST sections. The first character is reserved so you can specify the top-level section explicitly.

``verbose (default: True)``
    **True**: write informational messages to the log as well as the console.

``write_intermediate_file (default: False)``
    Tells whether to write an intermediate file.
    
    **True**: writes the intermediate file to the external file system. The name of the intermediate file has the name of the output file with ``.txt`` appended. This option has effect only if the ``generate_rst option`` is True.
</t>
<t tx="ekr.20100810091118.4298">**Markup doc parts** have the following form::

    @ @rst-markup
    any rST markup
    @c

Markup doc parts inserts the markup directly into the output. Markup doc parts are most useful when formatting an outline as code using the code-to-rst command.
</t>
<t tx="ekr.20100810091118.4301">The following options have effect only in code mode.

.. glossary::
    :sorted:

``number_code_lines (default: True)``
    Controls whether to number code lines in code mode. *This option has no effect in rst mode*.

``show_leo_directives (default: True)``
    True: include Leo directives False: ignore Leo directives.

``show_markup_doc_parts (default: False)``
    True: include markup doc parts. False: ignore markup doc parts.

``show_options_doc_parts (default: False)``
    True: include options doc parts. False: ignore options doc parts.

``show_doc_parts_as_paragraphs (default: False)``
    True: Move doc parts outside of the code-block directive. False: Show doc parts in the code-block directive.
    
    **Cool**: Any rST markup in doc parts included as the result of this option will be rendered properly.

``show_options_nodes (default: False)``
    True: show @rst-options nodes. False: Ignore @
</t>
<t tx="ekr.20100810091118.4306">The following option has effect only in rst mode.

.. glossary::

``show_doc_parts_in_rst_mode [True,False or class names] (default: True)``
    This option is most useful for rst documents which are not computer code. It allows you to use doc parts to make comments on the draft document which are either excluded from the output or formatted in a way that highlights their nature as comments rather than content. For example, you're writing a book, and you want to use a doc part at the top of a section to remind yourself "need to explain how Ted got to Sally's". Note: you may need to add CSS to have them formatted differently.

    The option can be `True`, `False`, or one or more class names.
    
    **True**: Treat the entire doc part from the opening '@' to the closing '@c
    as normal markup.
    
    **False**: Remove the doc part.

    **class names**: Process the contents of the doc part as it if were in an rst `container` directive. For example::

         @ @rst-options
         show_doc_parts_in_rst_mode = notes literal
         @c

This would wrap the doc part contents in the output in a div with classes "container notes literal". Furthermore, if one of the class names is ``literal``, then the doc part content will be output as a literal block wrapped in a container as described above. This allows you to use text which is not valid rst as rough notes for annotating a draft document.
</t>
<t tx="ekr.20100810203016.4298">The rst3 command supports three different modes.

``rst mode``
    The default mode, as discussed in the Tutorial. The rst3 command treats body text as rST (or Sphinx) markup.
    
``code mode``
    The rst3 command treats body text as computer source code, generating the appropriate rST or Sphinx markup. Code mode is inherently complex. It supports *many* options.
    
``doc-only mode``
    The rst3 command outputs only regular doc parts and @ @rst-markup doc parts. Headlines create section in doc_only mode only if:

1. The node contains a doc part or

2. The show_organizer_nodes option is in effect.

The code_mode and doc_only_mode options determine the mode as follows:

``code_mode=False; doc_only_mode=False (the default)``
    Enters rst mode.
    
``code_mode=False; doc_only_mode=True``
    Enters doc_only mode.

``code_mode=True; (doc_only_mode ignored)``
    Enters code mode.
</t>
<t tx="ekr.20100813075851.4296">This section discusses options--what they are, how to set them and how to set their defaults.
</t>
<t tx="ekr.20100813075851.4297"></t>
<t tx="ekr.20100821182153.4343">@ @rst-options
call_docutils=False
stylesheet_path=..\doc
write_intermediate_file = True
@c

######
Slides
######

This is the front page for various slide shows about Leo.

.. links
.. _`Clones and views`:         slides/clones-and-views/slide-001.html
.. _`External files`:           slides/external-files/slide-005.html
.. _`Installation`:             slides/installation/slide-001.html
.. _`Leo Basics Step By Step`:  slides/leo-basics-step-by-step/slide-001.html
.. _`Scripting Leo`:            slides/scripting-leo/slide-001.html
.. _`Using Leo's Minibuffer`:   slides/using-leos-minibuffer/slide-001.html

Basic slide shows
-----------------

`Installation`_  tells how to install Leo.

`Leo Basics Step By Step`_  explains the basics of Leo outlines.

`External Files`_ discusses creating external files with @file, @clean and @edit.

`Clones and views`_ illustrates how clones work and show how they create views.

`Using Leo's Minibuffer`_ tells how to execute Leo's commands by name.

Intermediate slide shows
------------------------

`Scripting Leo`_ explains how to use Python scripting in Leo.
</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.20101007100904.4372"></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: 2
    :local:
</t>
<t tx="ekr.20101025080245.5798"></t>
<t tx="ekr.20101025080245.5799" str_atime="1376411965.0"></t>
<t tx="ekr.20101025080245.5805"></t>
<t tx="ekr.20101025080245.6085">Leo 4.5 final was released September 2, 2008. Leo's drawing and focus code was substantially simplified, removing all calls to c.beginUpdate and c.endUpdate.

::

    Full support for @shadow files in Leo's core
    Major improvements to Leo's key binding code &amp; usable vim-like bindings
    uA's may now be associated with vnodes in @thin and @shadow files
    Leo now always uses sax to read .leo files
</t>
<t tx="ekr.20101025080245.6086">Leo 4.6 final was released July 15, 2009.  The big feature was caching of external files, a feature suggested by Ville M. Vainio.  Caching *greatly* reduces the time to load .leo files.

::

    Leo used Qt interface by default.
    Leo tests syntax of .py files when saving them
    Added @auto-rst and @edit
    Added Properties of commanders, positions and vnodes
    Leo warns on dangerous writes to @thin and @file nodes
</t>
<t tx="ekr.20101025080245.6087">Leo 4.7 final was released February 23, 2010. Leo 4.7.1 final fixed a serious bug in Leo 4.7.  It went out the door just days later, on 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
    Automatically converts from old-style to new-style sentinels
    Added a new Windows installer

Leo 4.7.1 fixed dangerous bug in Leo 4.7. The problem arose because it was too easy to save the .leo file (thus deleting the tnodeList) without forcing the converted external files to be saved. The next time Leo attempted to read the external files, the tnodeList would be missing and data would be lost.
</t>
<t tx="ekr.20101025080245.6089">Leo 4.8 final was released 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 may be the final chapter in the epic saga of error recovery in Leo.

::

    Added Drag and Drop of outlines
    Defined abbreviations in Leo settings nodes
    Leo now uses PyEnchant to check spelling
    Deprecated the ancient Tangle and Untangle commands
</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.20101104024804.4898">- Select the node "Leo's Documentation"

- Run the make-sphinx command or click the make-sphinx button.


To generate these docs by hand:

    - From this file, run rst3 on desired tree.
    - cd leo\doc\html
    - make html

To create pdf (probably easiest on Linux, with necessary latex packages installed):

    - make latex
    - cd _build/latex
    - make all-pdf
    
Important files:

- doc\html\conf.py contains settings, including the name of the master toctree
  document: leo_toc.html.txt.

</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):
    fn = g.os_path_finalize_join(g.app.loadDir,'..','plugins','leoPlugins.leo')
    c = g.openWithFileName(fn, old_c=self.c, gui=None,)
    if not c:
        g.error('can not open leoPlugins.leo')
    return c
</t>
<t tx="ekr.20101111175617.5037" str_atime="1376412919.0">'''
Creates an outline containing most docstrings from leoPlugins.leo.

Some docstrings are suppressed.
'''

@others
controller(c).run()
@language python
</t>
<t tx="ekr.20101111175617.56915" str_atime="1376412768.0">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.20101112045055.5065" str_atime="1376412774.0">http://www.greygreen.org/tmp/plugins.html</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" str_atime="1376413523.0">.. 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.
``jinjarender.py``
    Renders @jinja nodes.
``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_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.
``pretty_print.py``
    Customizes pretty printing.   
``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;http://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. See http://leo-editor.github.io/screen_capture.html
``screenshots.py``
    Creates stand-alone slideshows containing screenshots.
``script_io_to_body.py``
    Sends output from the Execute Script command to the end of the body pane.
``scripts_menu.py``
    Creates a Scripts menu for LeoPy.leo.
``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 http://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.
``valuespace.py``
    Supports outline-based calculations similar to spreadsheets.
``viewrendered.py``
    Creates a window for *live* rendering of rst, html, etc.
    This plugin uses docutils, http://docutils.sourceforge.net/,
    to do the rendering, so installing docutils is recommended.
    Supports @graphics-script, @image, @html, @movie and @svg nodes.
``viewrendered2.py``
    An alternate/enhanced version of viewrendered.py.
``vim.py``
    Enables two-way communication with VIM.
``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" str_atime="1376413520.0"></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::

    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*::

    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 

http://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::

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

or::

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

All parameters are optional except c.

**Parameters**

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

    If the text starts with 'rst:' it is assumed to be rst text and
    is converted to html for display after the rst: prefix has been removed.
    If the text starts with '&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.

..  To Do
..  - Add parameters to control position, size, closing, hiding etc.
..  - Save or print files from the dialog.
..  - Add an option to put the dialog in leo's log notebook.
..  - Add @settings to control default behavior
..  - Provide a menu of plugins that allows their docstring to be displayed.
..  - Provide a menu of @rst nodes in the current outline, automatically track changes
..    if it is set to display any of these nodes.
</t>
<t tx="ekr.20101113063552.9407">Launches the spyder environment with access to Leo instance.
See http://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: http://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.9427">Customizes pretty printing.

The plugin creates a do-nothing subclass of the default pretty printer. To customize, simply override in this file the methods of the base prettyPrinter class in leoCommands.py. You would typically want to override putNormalToken or its allies. Templates for these methods have been provided. You may, however, override any methods you like. You could even define your own class entirely, provided you implement the prettyPrintNode method.

</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 th `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: http://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" str_atime="1376412861.0">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.9440">Creates a two-way communication (bridge) between Leo scripts and IPython running in the console from which Leo was launched.

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

.. _`IPython Bridge Guide`: IPythonBridge.html

For full details, see the `IPython Bridge Guide`.
</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 path_to_folder', the content (file and folder names) of the folder and the children of that node will synchronized whenever the node's status-iconbox is double clicked.

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

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

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

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

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

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

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

There are commands on the Plugins active_path submenu:

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

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

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

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

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

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

    @language rest # AUTOLOADED DOCSTRING

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

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

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

active_path is a rewrite of the at_directory plugin to use @path directives (which influence @auto and other @file type directives), and to handle sub-folders more automatically.
</t>
<t tx="ekr.20101113063552.9449">Synchronizes @folder nodes with folders.

If a node is named '@folder path_to_folder', the content (filenames) of the folder and the children of that node will be sync. Whenever a new file is put there, a new node will appear on top of the children list (with mark). So that I can put my description (i.e. annotation) as the content of that node. In this way, I can find any files much easier from leo.

Moreover, I add another feature to allow you to group files(in leo) into children of another group. This will help when there are many files in that folder. You can logically group it in leo (or even clone it to many groups), while keep every files in a flat/single directory on your computer.

</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 parent nodes are used to find the full filename path.  Fore example::

    @mime foodir/document.pdf

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

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

Where '%s' is replaced with the full pathname.

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

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

For other sys.platform's, add an elif case to the section "guess file association handler" and either define a default _mime_open_cmd string, where "%s" will be replaced with the filename, or define a function taking the filename string as its only argument and set as open_func.
</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 http://www.ietf.org/rfc/rfc0791.txt
    @read-only ftp://ftp.someserver.org/filepath

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

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

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 'cmd args' will execute the command. There are several other features, including @arg and @input nodes.

The run_nodes.py plugin introduce two new nodes that transform leo into a terminal. It was mostly intended to run compilers and debuggers while having the possibility to send messages to the program.

Double clicking on the icon of an node whose headline is @run &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 "\n" 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 http://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 nodes, @command, @plugin nodes and
@script nodes whenever a .leo file is opened.

- @button nodes create script buttons.
- @command nodes create minibuffer commands.
- @plugin nodes cause plugins to be loaded.
- @script nodes cause a script to be executed when opening a .leo file.

Such nodes may be security risks. This plugin scans for such nodes only if the corresponding atButtonNodes, atPluginNodes, and atScriptNodes constants are set to True in this plugin.

You can specify the following options in leoSettings.leo.  See the node:
@settings--&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::

    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: http://www.inkscape.org/
  Allows the user to edit screenshots.
  Required to create final output (PNG) files.

PIL (Optional but highly recommended)
  The Python Imaging Library,
  http://www.pythonware.com/products/pil/

Wink (Optional)
  A program that creates slideshows and slides.
  http://www.debugmode.com/wink/

**Summary**

@slideshow &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: http://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',
  'Leo4-80-border.jpg', '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.

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

http://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.9483">Supports Uniform Node Locators (UNL's) for linking to nodes in any Leo file.

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

This plugin consists of two parts:

1) Selecting a node shows the UNL in the status line at the bottom of the Leo window. You can copy from the status line and paste it into headlines, emails, whatever.

2) Double-clicking @url nodes containing UNL's select the node specified in the UNL. If the UNL species in another Leo file, the other file will be opened.

Format of UNL's:

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

    headline1--&gt;headline2--&gt;...--&gt;headlineN

headline1 is the headline of a top-level node, and each successive headline is the headline of a child node.

UNL's of the form::

    file:&lt;path&gt;#headline1--&gt;...--&gt;headlineN

refer to a node specified in &lt;path&gt; For example, double clicking the following headline will take you to Chapter 8 of Leo's Users Guide::

    @url file:c:/prog/leoCvs/leo/doc/leoDocs.leo#Users Guide--&gt;Chapter 8: Customizing Leo

For example, suppose you want to email someone with comments about a Leo file. Create a comments.leo file containing @url UNL nodes. That is, headlines are @url followed by a UNL. The body text contains your comments about the nodes in the _other_ Leo file! Send the comments.leo to your friend, who can use the comments.leo file to quickly navigate to the various nodes you are talking about. As another example, you can copy UNL's into emails. The recipient can navigate to the nodes 'by hand' by following the arrows in the UNL.

**Notes**:

- At present, UNL's refer to nodes by their position in the outline. Moving a node will break the link.

- Don't refer to nodes that contain UNL's in the headline. Instead, refer to the parent or child of such nodes.

- You don't have to replace spaces in URL's or UNL's by '%20'.
</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" str_atime="1376413521.0"></t>
<t tx="ekr.20101113063552.9794" str_atime="1376412861.0">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 formated for use by the python ConfigParser class.

**Special Methods**

Certain methods defined at the top level are considered special.

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

applyConfiguration

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
      |
      +- http:\\*
      |
      +- @file *.py

**Configuration**

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

@bool nodeActions_save_atFile_nodes = False

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

  :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
        |
        +- http:\\*
        |
        +- @file *.py

**Pattern directives**

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

:[X]:
  Use python's regular expression type patterns instead of the Unix
  shell-style pattern syntax.

  For example, the following patterns will match the same headline string::

     Unix shell-style pattern:
        @files *.py

     Regular Expression pattern:
        ^@files .*\.py$ [X]

:[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;]

**Scripts**

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

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

**Examples**

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

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

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

     g.os.system('"Start /b ' + pClicked.bodyString() + '"')
</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">@nocolor-node

{{Infobox software
| name = Leo: Leonine Editor with Outlines
| screenshot = [http://sourceforge.net/project/screenshots.php?group_id=3458&amp;ssid=22298 Screenshots]
| caption =
| developer = Edward K. Ream
| latest_release_version = 5.8b1
| latest_release_date = {{release date and age|2018|01|27}}
| operating_system = [[Cross-platform]]
| genre = [[Text editor]], [[Outliner]], [[Integrated development environment|IDE]]
| license = [[Python (programming language)|Python]] License
| website = http://leoeditor.com
}}

'''Leo''' ('''L'''eonine '''E'''ditor with '''O'''utlines) is a [[text editor]]
that features [[outliner|outlines]] with clones as its central tool of
organization, navigation, customization and scripting.

==Language==

Leo is written in [[Python (programming language)|Python]] and uses the [[Qt
(toolkit)|Qt]]. It is fully scriptable using Python and can be extended with
plugins. In Leo, outlines are hierarchical data structures that people use to
work with and manage text files—including code.

==Trees, clones and views==

Leo is an [[outliner]]. Leo's outline pane shows a [[tree (data structure)]] 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|directed acyclic graphs]];
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.
Views and clones turn Leo into a supremely flexible filing cabinet: any node may be filed
in arbitrarily many places.
&lt;ref&gt;[http://leoeditor.com/nutshell.html Leo documentation: Leo in a Nutshell]&lt;/ref&gt;

==External files==

@file nodes represent external files, files on the computer's file system.
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 reading an outline, these comments allows Leo to recreate
@file trees using only the data in the external file.

@auto 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.

==Scripting==

Leo's scripting environment takes full advantage of outline structure:

* The body text of any node may contain a Leo script, a Python script executed in the context of a Leo outline.

* A simple [[API]] &lt;ref&gt;[http://leoeditor.com/scripting.html Leo documentation: Scripting Leo with Python]&lt;/ref&gt; 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]] &lt;ref&gt;[http://leoeditor.com/tutorial.html#section-references Leo documentation: Tutorial]&lt;/ref&gt; tells Leo how to create scripts from (parts of) an outline.

* Headlines naturally control and guide scripts.

** @test nodes represent unit tests. Leo can execute the body of an @test node as unit test, without the body having to create an explicit subclass of Python's UnitTest.TestCase class. &lt;ref&gt;[

** @button nodes contain scripts that can be applied to other nodes.  In effect, @button nodes create user-defined commands. &lt;ref&gt;

==External links==
{{Portal|Free software}}
*[http://leoeditor.com Leo's homepage]
*[http://sourceforge.net/projects/leo/ Leo at SourceForge],[http://sourceforge.net/project/screenshots.php?group_id=3458&amp;ssid=22298 screenshots]
*[http://groups.google.com/group/leo-editor leo-editor Google Group]
*{{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/ }}
*{{cite book | author = Vreda Pieterse, Derrick G. Kourie, Andrew Boake | title=ACM International Conference Proceeding Series; Vol. 75. Proceedings of the 2004 annual research conference of the South African institute of computer scientists and information technologists on IT research in developing countries | chapter=A case for contemporary literate programming | editor=[[Association for Computing Machinery|ACM]] | pages=2–9 | url=http://portal.acm.org/citation.cfm?id=1035054}} (cited in references)

==References==
&lt;references/&gt;

{{DEFAULTSORT:Leo (Text Editor)}}
[[Category:Free text editors]]
[[Category:Free software programmed in Python]]
[[Category:Outliners]]
</t>
<t tx="ekr.20101125062332.5090">**Python**: Leo will work on any platform that supports Python 2.6 or above, including Python 3.0 and above. To install Python, see http://python.org.

**PyQt**: `PyQt`_ provides Leo's widgets:

* Download PyQt4 from http://www.riverbankcomputing.com/software/pyqt/download.
* Download PyQt5 from http://www.riverbankcomputing.com/software/pyqt/download5.

**Important**: The PyQt version must match your installed Python version. Remember that Leo requires Python 2.6 or later, or Python 3.0 or later.

**PyEnchant**: You must install `PyEnchant`_ if you want to use Leo's Spell tab. There is an executable installer for Windows users.
</t>
<t tx="ekr.20110521135104.18151">Cross-file clones are cloned nodes in one outline that refer to data in another outline. This is a frequently requested feature. For example::

    I would absolutely love to have the leo files in different project
    directories, and a "master" leo file to rule them all.

However, cross-file clones will never be a part of Leo. Indeed, cross-file clones would violate the principle that data should be defined and managed in exactly one place. Just as human managers would not willingly accept shared responsibility for even a single line of code, every piece of Leonine data should be the responsibility of one and *only* one .leo file.

The problem is fundamental. If the *same* (cloned) data were "owned" by two different Leo files we would have a classic "multiple update problem" for the data. Each outline could change the data in incompatible ways, and whichever outline changed the data last would "win."

To make such a scheme workable and safe, one would have to devise a scheme that would keep the data in "component" .leo files consistent even when the component .leo files changed "randomly", without the "master" .leo file being in *any* way in "control" of the changes. Good luck :-)

Let us be clear: it's no good having a scheme that works *most* of the time, it must work *all* the time, even with unexpected or even pathological file updates. If it doesn't you are asking for, and will eventually get, catastrophic data loss, without being aware of the loss for an arbitrarily long period of time. Even with a source code control system this would be an intolerable situation.
</t>
<t tx="ekr.20110531155858.20559">.. _`This FAQ entry`: FAQ.html#how-can-i-use-leo-to-develop-leo-itself

Here is the workflow I use to develop Leo. The intention is to help present and potential developers use Leo effectively.

Overview:

- Develop in an outline containing all of Leo's source files. Close this outline rarely: this keeps the code I am using stable while I'm hacking the code.

- Test in a *separate, private* .leo file, say ~/test.leo.

On Windows I use the following *common* @button node, defined in the @buttons tree in myLeoSettings.leo::

    @button load-test @key=F5
    
    import os
    os.system("start  cmd /c t")
    
Now F5 runs t.bat in a separate console. Leo remains responsive. t.bat opens the test file. t.bat ends with the Windows "exit" command, so the console closes when I close Leo.

Additional tips:

A. Avoid using the mouse whenever possible. For example, use alt-tab to switch between windows.

B. Always develop Leo in a console. This allows you to see the output of g.trace.

Speaking of g.trace, I hardly ever use 'print' because g.trace prints the name of the function or method in which it appears. The typical pattern for enabling traces is::

    trace = True and not g.unitTesting
    if trace: g.trace(whatever)

This pattern is especially useful when a method contains multiple calls to g.trace.

C. I use scripts to open particular Leo files. These are batch files on Windows, and aliases on Linux, but invoking them is the same on either platform::

    all:     opens all my main development files using the qt-tabs gui.
    t:       opens test.leo.
    e:       opens ekr.leo.  I use this file for private testing.
    d:       opens LeoDocs.leo.
    s:       opens LeoPy.leo.
    plugins: opens leoPlugins.leo.
    gui:     opens leoGui.leo.
    u:       opens unitTest.leo.

These run Leo with Python 3.x. There are similar scripts, ending in 2, that run Leo with Python 2.x. For example, u2 opens unitTest.leo with Python 2.x. Thus, to run a test, I alt-tab to an available console window, then type 'e' or 't' or 'u' or, if I want Python 2.x, 'e2' or 't2' or 'u2'.

D. Use clones to focus attention on the task at hand. For more details, see the tutorial's introduction to `clones`_.

E. For thousand of example of my programming style, see leoPy.leo and leoGuiPlugins.leo. The projects section in leoPy.leo contains many examples of using clones to create view nodes. I typically delete the clones in the views shortly before a release.

Writing documentation:

- Use postings as pre-writing for documentation. I don't mind blabbing on and on about Leo because all my posts become pre-writing for Leo's documentation. I simply copy posts to nodes in the "documentation to-do" section. At release time, I edit these nodes and put them in Leo's main documentation or the release notes. This posting is an example.
  
- Use the vr command to debug reStructuredText documentation. The viewrendered pane updates as you type. This makes Leo a killer app for rST.
   
Administrative tips:

- Never rely on memory. A project like this contains thousands and thousands of details. Everything eventually goes into a Leo node somewhere. If it doesn't it surely *will* be forgotten.

- Do easy items first. This keeps to-do lists short, which keeps energy high.
</t>
<t tx="ekr.20110531155858.20563">The following script will create a minimal Leo outline::

    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">You set most colors in the following settings node::

    @data qt-gui-plugin-style-sheet
    
However, settings for colors that can change during Leo's execution are found in the node::

    Body pane colors
    
These settings are as follows, with the defaults as shown::
    
    @color body_cursor_background_color = None
    @color body_cursor_foreground_color = None
    @color body_insertion_cursor_color = None
    @color body_text_background_color = None
    @color body_text_foreground_color = None
    @color command_mode_bg_color = #f2fdff
    @color command_mode_fg_color = None
    @color insert_mode_bg_color = #fdf5f5
    @color insert_mode_fg_color = black
    @color overwrite_mode_bg_color = azure2
    @color overwrite_mode_fg_color = black
    @color unselected_body_bg_color = #ffffef
    @color unselected_body_fg_color = black
</t>
<t tx="ekr.20110601105631.19349">
</t>
<t tx="ekr.20110612104631.16414">The following options allow you to expand noweb section references, much like Leo itself does. The rst3 command ensures that unbounded expansions can not happen. While expanding any section, the rst3 will not expand again any sections that have already occurred in the expansion.

``expand_noweb_references``
   True: Replace references by definitions. Definitions must be descendants of the referencing node.

``ignore_noweb_definitions``
    True: ignore section definition nodes.

``expand_noweb_recursively``
    True: recursively expand definitions by expanding any references found in definitions.
        
**Note**: This is an experimental feature: all aspects might changed. The defaults for all these options ensure that the rst3 command works as it has always.
</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" str_atime="1376412901.0">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::

    from PyQt4 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::

    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.20111127144911.5544">@pagewidth 75

@ @rst-options
call_docutils=False
stylesheet_path=..\doc
write_intermediate_file = True
@c

.. _`Installing Leo with git`:  installing.html#installing-leo-with-git
.. _`Installing Leo with pip`:  installing.html#installing-leo-with-pip
.. _`Nightly snapshot`:         download.html#snapshots       
.. _`Python wheel`:             https://pythonwheels.com/
.. _`SourceForge`:              https://sourceforge.net/projects/leo/files/Leo/
.. _`git`:                      https://git-scm.com/

###############
Downloading Leo
###############

There are four ways to download Leo:

- **New**: Leo 5.7 final will have a `Python wheel`_, so ``pip install leo`` will automatically download *and* install Leo, including all Leo's dependencies. See `Installing Leo with pip`_.

- We recommend installing Leo using `git`_, see `Installing Leo with git`_. Git gives you the latest, thoroughly tested code. All of Leo's developers use git.

- If you prefer a new development version, or a version from from 1, 2, 5, 10, 30 or 90 days ago, download a `Nightly snapshot`_.
</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('--session-restore', action='store_true', dest='session_restore',
        help='restore previously saved session tabs at startup')
    add('--session-save', action='store_true', dest='session_save',
        help='save session tabs on exit')
    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))
    # --session-restore &amp; --session-save
    g.app.restore_session = bool(options.session_restore)
    g.app.save_session = bool(options.session_save)
    # --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.setChanged(False)
        # 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 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 @command 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.15125">When running unit tests externally, Leo copies any @mark-for-unit-tests nodes to dynamicUnitTest.leo.  Of course, this is in addition to all @test nodes and @suite nodes that are to be executed. You can use @mark-for-unit-test nodes to include any "supporting data" you want, including, say, "@common test code" to be imported as follows::

    exec(g.findTestScript(c,'@common test code'))

**Note**: putting @settings trees as descendants of an @mark-for-unit-test node will copy the @setting tree, but will *not* actually set the corresponding settings.
</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.15137">.. .. http://groups.google.com/group/leo-editor/browse_thread/thread/61019e45d75a6f18/71ee770ee4421222

1. Archive and remove the previous version of Leo.
2. Download the nightly snapshot zip file.
3. Unzip it into the same place as the previous version.
4. Enjoy your up-to-date Leo code...

To make this work, it's important to keep your folder containing Leo separate from your .mySettings.leo and any data files.
</t>
<t tx="ekr.20120229094652.15148">.. _`this posting about BibTeX citations`: http://groups.google.com/group/leo-editor/browse_thread/thread/d36d76174dcd6786/9c2a298049f4f01c

.. _`raw-data`: http://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 PyQt4 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::

    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::

    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: http://en.wikipedia.org/wiki/Mylyn

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

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

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

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

Mylyn was a nice boost back in the eclipse days, it could work for Leo too. My main motivation right now was to demonstrate the signals with something that is much simpler than using them in qmlnotebook.
</t>
<t tx="ekr.20130815102041.15630">By Terry Brown. See http://leo-editor.github.io/screen_capture.html

screen_capture now captures an image immediately, screen_capture_5sec waits
five seconds, so you can position the pointer, open menus etc. The only
feedback is in the console, as messages in the log would be distracting in
the captured image.</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.20131001045038.17448">This idea got started when I (Ville M. Vainio) saw this post by Edward Ream on IPython developer mailing list: http://lists.ipython.scipy.org/pipermail/ipython-dev/2008-January/003551.html

I was using FreeMind as mind mapping software, and so I had an immediate use case for Leo (which, incidentally, is superior to FreeMind as mind mapper). The wheels started rolling, I got obsessed with the power of this concept (everything clicked together), and Edwards excitement paralleled mine. Everything was mind-bogglingly easy/trivial, something that is typical of all promising technologies.

The goal of close cooperation between Leo and IPython went from vague dream to completed reality over the span of about 10 days. The IPython bridge has continued to evolve since then.
</t>
<t tx="ekr.20131001045038.18979">.. _`IPython Notebook`: http://projects.scipy.org/ipython/ipython/wiki/NoteBook

The IPython bridge turns Leo into another kind of `IPython Notebook`_. IPython users typically use %edit to produce non-trivial functions/classes instead of entering them directly on the interactive prompt. But this is a bit clumsy. With Leo, *every Leo node works like an IPython %edit file*:

- You can execute any Leo node in IPython with ipython-exec.
- Saving your Leo outline saves all your IPython scripts.
- You can use Leo as always to organize all your IPython scripts.
</t>
<t tx="ekr.20131001045038.18980">*You can run any IPython script from Leo*. Leo's ipython-exec command executes the body text of the presently selected Leo node in the address space of the IPython shell. Such scripts *immediately* affect the IPython interpreter.

The IPython bridge sets several global variables *within Leo*, allowing Leo scripts *complete* access to all of IPython's code and data:

- g.app.ipk is a *singleton* instance of the InternalIPKernel class,
  defined in leoIPython.py.
- g.app.ipk.namespace is IPython's namespace.
- g.app.ipk.kernelApp is an IPython IPKernelApp object.
- g.app.ipk.kernelApp.shell is an IPython InteractiveShell object.
  Depending on your installation, this may be a ZMQInteractiveShell.
</t>
<t tx="ekr.20131001045038.18981">*You can run any Leo script from IPython*. The IPython bridge injects an object called _leo into IPython's namespace. IPython scripts may access Leo's c and g objects as follows::

    c,g = _leo.c, _leo.g

This allows IPython scripts to do *anything* that a Leo script can do. Scripts run from IPython *immediately* change Leo, *exactly* as if the script were run from Leo.

**Important**: the _leo object is an instance of LeoNameSpace class, defined in leo.core.leoIPython.py. This class allows IPython scripts to access multiple Leo outlines at once. See the actual code for details.

**Note**: _leo.c is a property which can return None in some situations. Here is its definition:

.. code-block:: python

    def __get_c(self):
        '''Return the designated commander, or the only open commander.'''
        self.update()
        if self.commander and self.commander in self.commanders_list:
            return self.commander
        elif len(self.commanders_list) == 1:
            return self.commanders_list[0]
        else:
            return None
    
    def __set_c(self,c):
        '''Designate the commander to be returned by the getter.'''
        self.update()
        if c in self.commanders_list:
            self.commander = c
        else:
            g.trace(g.callers())
            raise ValueError(c)
    
    c = property(
        __get_c, __set_c,
        doc = "LeoNameSpace c property")
</t>
<t tx="ekr.20131001100236.15927">Leo's valuespace.py plugin uses the ipython namespace when the ``--ipython`` command line switch is in effect.

This plugin provides a "workbook" like way to get data from Leo document to the namespace, and do calculations based on that data. Having this data be accessible to the ipython instance makes it convenient to interact and poke around with the same data.
</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 not create this file automatically: you should create it yourself. 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::

    print-bindings
    print-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
    help-for-sessions

</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 nodes status. For example, the icon box has a black 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. Use ``demote`` to "gather" nodes so they can all be moved with their parent.
``Ctrl-{ (promote)``
    Makes all the children of a node siblings of the node. Use ``demote`` to "scatter" the nodes after moving their parent.
</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** until 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 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 set page width (used when formatting paragraphs). 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. Clones are marked with a small red arrow in its icon box. 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.

Clones allow data to be stored in multiple places within an outline.

``Ctrl-` (clone-node)``
    Clones node A. The shortcut is a grave accent, *not* a single quote.  This 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 becomes a regular node again.
</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 tabs (.leo files) that Leo opens automatically when Leo first starts. When the ``--session-save`` and ``--session-restore`` command-line options are in effect, Leo will save session data on exit and will reload outlines when Leo restarts. For full details, see `Using sessions &lt;commands.html#using-sessions&gt;`_ in Leo's `Users Guide &lt;usersguide.html&gt;`_.
</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.
- @test nodes create unit tests.
- 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.
  
- The rst3 command provides *many* other capabilities. For details, see `the rst3 chapter &lt;rstplugin3.html&gt;`_.
  </t>
<t tx="ekr.20131007143750.16070">#################
Leo's Cheat Sheet
#################
   
**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, 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.20131007143750.16111"></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::

    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::

    import leo.core.leoGlobals as g
    
Plugins gain access to c using event handlers::

    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::

    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 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.
- Because of clones, a node may appear in many views at once.
- 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.

**Contents**

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

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

This is Leo's Users Guide. It covers additional material not covered in the
`Leo Tutorial`_.

.. toctree::
   :maxdepth: 2

   customizing
   rstplugin3
   plugins
   commands
   directives

</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`: http://groups.google.com/group/leo-editor

This chapter tells how to install and run Leo on Windows, Linux and MacOS.

**Important**: 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

   coloring
   writingPlugins
   unitTesting
   debuggers
   console-gui
   
.. 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

   emacs
   vimBindings
   leoBridge
   IPythonBridge
   zodb

</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" rst_http_attribute="5d71002858460000003c6120636c6173733d22746172676574222069643d22687474702d6e6f64652d6d61726b65722d333722206e616d653d22687474702d6e6f64652d6d61726b65722d3337223e710158040000003c2f613e71025d71032858260000003c64697620636c6173733d2273656374696f6e222069643d22672d726566696e64616c6c223e710458060000003c2f6469763e71055d710628584f0000003c64697620636c6173733d2273656374696f6e222069643d2266756e6374696f6e732d666f722d66696e64696e672d616e642d6368616e67696e672d746578742d66726f6d2d73637269707473223e710758060000003c2f6469763e71085d710928583f0000003c64697620636c6173733d22646f63756d656e74222069643d22636861707465722d372d736372697074696e672d6c656f2d776974682d707974686f6e223e710a58060000003c2f6469763e710b5d710c2858060000003c626f64793e710d58070000003c2f626f64793e710e5d710f2858430000003c68746d6c20786d6c6e733d22687474703a2f2f7777772e77332e6f72672f313939392f7868746d6c2220786d6c3a6c616e673d22656e22206c616e673d22656e223e711058070000003c2f68746d6c3e71114e656565656558070000003c2f6469763e0a711258070000003c2f6469763e0a711358350000003c64697620636c6173733d2273656374696f6e222069643d2272756e6e696e672d6c656f2d696e2d62617463682d6d6f6465223e0a7114586c0000003c68313e3c6120636c6173733d22746f632d6261636b7265662220687265663d22236964313922206e616d653d2272756e6e696e672d6c656f2d696e2d62617463682d6d6f6465223e52756e6e696e67204c656f20696e206261746368206d6f64653c2f613e3c2f68313e0a7115652e">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">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 something like the following::

    Usage: launchLeo.py [options] file1, file2, ...

    Options:
      -h, --help            show this help message and exit
      --debug               enable debug mode
      --diff                use Leo as an external git diff
      --fullscreen          start fullscreen
      --ipython             enable ipython support
      --fail-fast           stop unit tests after the first failure
      --gui=GUI             gui to use (qt/qttabs/console/null)
      --listen-to-log       start log_listener.py on startup
      --load-type=LOAD_TYPE @&lt;file&gt; type for loading non-outlines from command line
      --maximized           start maximized
      --minimized           start minimized
      --no-cache            disable reading of cached files
      --no-plugins          disable all plugins
      --no-splash           disable the splash screen
      --screen-shot=SCREENSHOT_FN
                            take a screen shot and then exit
      --script=SCRIPT       execute a script and then exit
      --script-window=SCRIPT_WINDOW
                            open a window for scripts
      --select=SELECT       headline or gnx of node to select
      --session-restore     restore previously saved session tabs at startup
      --session-save        save session tabs on exit
      --silent              disable all log messages
      --trace-binding=BINDING
                            trace key bindings
      --trace-focus         trace changes of focus
      --trace-plugins       trace imports of plugins
      --trace-setting=SETTING
                            trace where setting is set
      --trace-shutdown      trace shutdown logic
      -v, --version         print version number and exit
      --window-size=WINDOW_SIZE
                            initial window size (height x width)</t>
<t tx="ekr.20131008041326.16178"></t>
<t tx="ekr.20131008041326.16203">.. |---| unicode:: U+02015
   :trim:
   
.. |br| raw:: html

   &lt;br /&gt;

##################
Leo in 10 Minutes
##################

..  "Edward...you've come up with perhaps the most powerful new concept in
..  code manipulation since VI and Emacs."---David McNab
    
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
###########################################

..  "Cloning is pure genius!"---Michael Manti

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

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`:    http://www.latex-project.org/
.. _`Python's`: http://www.python.org/
.. _`Sphinx`:   http://sphinx-doc.org/
.. _`Sphinx documentation`: http://sphinx-doc.org/contents.html
.. _`docutils`: http://docutils.sourceforge.net
.. _`reStructuredText`: http://docutils.sourceforge.net/rst.html
.. _`rST primer`: http://sphinx-doc.org/rest.html
.. _`first tutorial`: tutorial-basics.html

..  "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
    
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 final was released June 21, 2011.  This release completely switches over to Qt.

::

    Completed the Autocompleter
    The rendering pane can now display movies, html, svg images, etc.
    Nodes may contain multiple @language directives
    Leo highlights URL's everywhere
    Ctrl-click URL's opens them in your web browser
    Added unified extract and import commands
</t>
<t tx="ekr.20131008041326.16341">##########
Appendices
##########

.. |br| raw:: html

   &lt;br /&gt;
   
.. contents:: Contents
    :depth: 3
    :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.17625"># True: generate rst markup from @code and @doc parts.</t>
<t tx="ekr.20131009050634.17627"># True: generate rst markup. False: generate plain text.</t>
<t tx="ekr.20131009050634.17630"># Can be set by @rst-no-head headlines.</t>
<t tx="ekr.20131009050634.17631"></t>
<t tx="ekr.20131009050634.17658"></t>
<t tx="ekr.20131009052848.6456"></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 take 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.
- URL's should contain no spaces: use ``%20`` instead of spaces.

`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, and all 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 a **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.

In addition, 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 node 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 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 simply 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
.. _`valuespace.py`:    plugins.html#valuespace-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 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.
- `valuespace.py`_ adds outline-oriented spreadsheet capabilities.
- `viewrendered.py`_ creates the rendering pane and renders content in it.
</t>
<t tx="ekr.20131009100732.19039">.. leoPlugins.leo#Plugins--&gt;Files and nodes--&gt;@file bookmarks.py

Open bookmarks in a list, and show bookmarks in a pane.
</t>
<t tx="ekr.20131009100732.19040">Supports outline-based calculations similar to spreadsheets.
</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`:   http://en.wikipedia.org/wiki/David_Parnas
.. _`Glenford Myers`: http://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::

    g.trace(g.callers(n))
    
Many complex methods define a trace variable::

    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::

    &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::

    for p in c.all_positions():
        print(' '*p.level()+p.h)

.. index::
    pair: Invalid positions; Tutorial
    
Scripts may capture positions like this::

    aList = list(c.all_positions())
    
**Warning**: stored positions become invalid when outline changes. **c.positionExists(p)** is True if p is valid in c's outline.

**New in Leo 5.5**: All generators now yield *copies* of positions.
    
</t>
<t tx="ekr.20131012060912.16788">g.es can send it's output to tabs other than the log tab::

    c.frame.log.selectTab('Test')
        # Create Test or make it visible.

    g.es('Test',color='blue',tabName='Test')
        # Write to the test tab.

Plugins and scripts may call the c.frame.canvas.createCanvas method to create a log tab containing a graphics widget. Here is an example script::

    log = c.frame.log ; tag = 'my-canvas'
    w = log.canvasDict.get(tag)
    if not w:
        w = log.createCanvas(tag)
        w.configure(bg='yellow')
    log.selectTab(tag)
</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::

    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`: http://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 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::

    '''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
    @raw, @end_raw          # @file only.
    @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)
    print-bindings
    print-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">#####################################
Downloading, Installing &amp; Running Leo
#####################################

.. _`Python`:                   https://www.python.org/
.. _`Leo's dependencies`:       installing.html#dependencies
.. _`Installing Leo using pip`:    installing.html#installing-leo-with-pip

**Overview**: Leo is a `Python`_ program.  You must install Python itself, `Leo's dependencies`_, and then download and install Leo itself.

.. toctree::
   :maxdepth: 4

   download
   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.20131016083406.16724">@language python
'''Run sphinx make clean ; make html.'''
import os
trace = True
g.cls()
c.setComplexCommand('make-sphinx')
if c.isChanged():
    c.save()
aList = c.rstCommands.rst3()
if aList:
    path = g.os_path_finalize_join(g.app.loadDir,'..','doc','html')
    os.chdir(path)
    if len(aList) &gt; 1: g.execute_shell_commands('make clean',trace=trace)
    g.execute_shell_commands('make html',trace=trace)
    fn = aList[0].h.strip() if len(aList) == 1 else 'leo_toc.html'
    fn = g.os_path_finalize_join(path,'_build','html',g.os_path_basename(fn))
    if g.os_path_exists(fn):
        # Don't wait for this command to exit!
        g.execute_shell_commands(['&amp;%s' % (fn)],trace=trace)
</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.
    valuespace.py:      Creates an outline-oriented spreadsheet.
    viewrendered.py:    Creates a rendering pane.
                        Automatically loaded by Leo's help commands.
                        Supports @graphics-script, @image, @html,
                        @movie and @svg nodes.
    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.20131017094004.16739"></t>
<t tx="ekr.20131017174814.17479">.. |---| unicode:: U+02015 .. for quotes
   :trim:
   
.. |br| raw:: html

   &lt;br /&gt;

   
######################
A Brief Summary of Leo
######################

.. Use full links here so links are active in LeoDocs.leo

.. _`Emacs`: https://www.gnu.org/software/emacs/
.. _`Leo's tutorial`: tutorial.html
.. _`ask for help`:   https://groups.google.com/forum/#!forum/leo-editor
.. _`Directed Acyclic Graphs`: https://en.wikipedia.org/wiki/Directed_acyclic_graph
.. _`group of developers and users`: https://groups.google.com/forum/#!forum/leo-editor
.. _`Leonine`: leonine-world.html
.. _`Clones`: tutorial-pim.html
.. _`Python API`: tutorial-scripting.html
.. _`outline-oriented directives`: tutorial-basics.html#markup
.. _`Next`: testimonials.html

    "Word outlines are very useful. But Leo makes Word look like a clunky toy."---Joe Orr

Leo is a fundamentally different way of using and organizing data, programs and scripts. Leo has been under active development for 20+ years with an active `group of developers and users`_.

**Leo is:**

- A fully-featured IDE, with many features inspired by `Emacs`_.
- An outliner. Everything in Leo is an outline.
- A data manager, data manager and personal information manager.
- A powerful scripting environment.
- A tool for organizing and studying computer code.
- Extensible via a simple plugin architecture.
- A tool that plays well with  IPython, Vim and Emacs.
- Written in 100% pure Python

**Leo's unique features**

Leo *completely integrates* Python scripting and outlines. Simulating the following features in Vim, Emacs or Eclipse is possible, just as it is possible to simulate Python in assembly language...

- All commands and scripts have easy access to outline structure via a simple `Python API`_. |br|
  For example, p.b is the body text of the selected outline node. |br|
  Scripts have full access to all of Leo's sources.
- `Clones`_ create multiple views of an outline.  |br|
  Leo's underlying data is a `Directed Acyclic Graphs`_.  |br|
  As a result, Leo organizes data in completely new ways.
- Scripts and programs can be composed from outlines using `outline-oriented directives`_.
- Importers convert flat text into outlines.
- @test and @suite scripts create unit tests automatically.
- @button scripts apply scripts to outline data.

These features combine to create a `Leonine`_ way of programming and
organizing. You won't learn all about Leo in a day or two. `Leo's
tutorial`_ explains the basic features. You can learn more advanced
features later. Please `ask for help`_ immediately if you get stuck.

</t>
<t tx="ekr.20131018100353.16706">Clones can greatly accelerate your work flow. 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 work flow 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, @suite, @url, etc. Plugins define @bookmark, @graph, @html and @task types. Scripts can easily define other types.

**Testing**: Leo's @test nodes creates a unique unit-testing framework:

- @test nodes focus on the real test code.
- It is easy to run only the @test nodes in a particular suboutline.
- @test scripts can easily use data in their children.

.. _`clone-find`: tutorial-basics.html#clone-find-commands

**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.
    
@test scripts predefine all the above, plus::

    self: The instance of unittest.TestCase
</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()
    
**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.
</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
    print-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" str_atime="1376412280.0">::

    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
        jinja2 templating
        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;http://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, grand-children, 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 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.setChanged(False)
            c.redraw()
    return c
</t>
<t tx="ekr.20131028213522.17137">Samples of use (Maybe):

    Sample on how to import bookmarks from Internet browser (I have that
    script ready myself, I could add that)

    Sample of website generated with an outline, easy to open and edit for
    the user to view its power. Ideally, just after transforming the
    outline to website, the user should be able to open it and see it in
    html.

    Sample of RST outline and one click opening with render pane.

    The RPG helper we recently discussed about.

    And as many other practical and ready-to-go samples that could impress
    the new user. All of them, ready to go, no edit required to view. There
    are ways of using Leo that beginners can't think of and those would make
    a great addon for such a beginner's leo file.

Other (JKN)
    how to invoke Leo (short list of command-line parameters    
    brief note on creating your own settings (myLeoSettings etc)    
    How to 'install' plugins, adding buttons    
    @node summary usage    

More: Rest of the directives:
    @button    
    @rclick    
    and all of them, with sample of usage    

More: Associate leo files    
    Include the bat + instructions on how to associate Leo files for
    double-click opening in windows.
</t>
<t tx="ekr.20131028213522.17138">::

    Usage: launchLeo.py [options] file1, file2, ...
    
    Options:
      -h, --help            show this help message and exit
      --debug               enable debug mode
      --diff                use Leo as an external git diff
      --fullscreen          start fullscreen
      --ipython             enable ipython support
      --fail-fast           stop unit tests after the first failure
      --gui=GUI             gui to use (qt/qttabs)
      --load-type=LOAD_TYPE
                            @&lt;file&gt; type for loading non-outlines from command
                            line
      --maximized           start maximized
      --minimized           start minimized
      --no-cache            disable reading of cached files
      --no-plugins          disable all plugins
      --no-splash           disable the splash screen
      --screen-shot=SCREENSHOT_FN
                            take a screen shot and then exit
      --script=SCRIPT       execute a script and then exit
      --script-window=SCRIPT_WINDOW
                            open a window for scripts
      --select=SELECT       headline or gnx of node to select
      --session-restore     restore previously saved session tabs at startup
      --session-save        save session tabs on exit
      --silent              disable all log messages
      --trace-plugins       trace imports of plugins
      -v, --version         print version number and exit
      --window-size=WINDOW_SIZE
                            initial window size (height x width)
</t>
<t tx="ekr.20131028213522.17150"></t>
<t tx="ekr.20131030071311.17087">This tutorial would benefit from an example toolchain for a writer. How to actually get an html file that can be loaded into a word processor to output an .odt or .docx file for example.

For most of the purposes that a programmer would use rst, i.e., documentation or a web page, the tutorial goes far enough. But for those who have different output goals, highlighting the flexibility that Leo with rst should be a primary goal. There are literally hundreds of writers in the world for every programmer. If you want Leo to become popular, this is a critical understanding.
</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
##################

.. _`blog post`: http://rickardlindberg.me/writing/reflections-on-programming/2013-02-24-related-things-are-not-kept-together/
.. _`2012 PyOhio talk`:     http://www.youtube.com/watch?v=JgJ89ekGj-s
.. _`Icons`:                icons.html
.. _`Introduction to Leo`:  http://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
.. _`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
.. _`web viewer`:           load-leo.html
.. _`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;`_.
- The `Mind Mapping`_ page.
- A `web viewer`_ page for .leo files.
- `Icons`_ telling the world that you used Leo.
- `Leo in a nutshell`_: A summary Leo's more than one million lines of source code.
- Rickard Lindberg's `blog post`_ about how Leo improves computer code.

</t>
<t tx="ekr.20131031101712.16486">Supported by Leo's core::

    @chapter
    @rst, @rst-no-head, @rst-ignore, @rst-ignore-tree
    @settings
    @test, @testsetup, @testclass
    @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.20131031101712.16685">Leo 4.10 final was released March 29, 2012. It contained a huge number of improvements and bug fixes::

  Tab completion now shows all @command &amp; @button nodes
  Leo tabs may be detached from the main window
  The bigdash plugin searches across multiple files
  Much improved abbreviations using @data nodes
  Improved handling of URL's
  Detachable windows
  Improved Leo's home page
  Easier installation on MacOS
</t>
<t tx="ekr.20131031101712.17211">Leo 4.11 final was released November 6, 2013.

::

    Clones are now valid anywhere in @file nodes
    A colored border highlights the pane with focus
    Added support for sessions
    By Terry Brown:
        Added templates to abbreviations
        Leo warns if a .leo file is open elsewhere
        Added colorizing themes

Leo 4.11.1 final was released December 20, 2013.

::

    @data qt-gui-user-style-sheet overrides @data qt-gui-plugin-style-sheet
    Rewrote and simplified Leo's tutorials
    A colored border highlights the pane with focus
</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`_ web sites 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.20131108071132.17025"></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;http://www.screencast.com/t/xDZAOqfsAhPZ&gt;`__
     - `regular &lt;http://www.youtube.com/watch?v=tuM8MvI9g6k&gt;`__
   * - Intro
     - Leo for Programmers
     - `hi-res &lt;http://www.screencast.com/t/lgR6lMhWK&gt;`__
     - `regular &lt;http://www.youtube.com/watch?v=WkUbJAuFfI4&gt;`__
   * - Intro
     - Ville Vianio introduces Leo
     -
     - `regular &lt;http://www.youtube.com/watch?v=Zu6J-J0qFi0&gt;`__
   * - Basic
     - Using Leo’s Find pane
     - `hi-res &lt;http://www.screencast.com/t/O7915mYD3&gt;`__
     - `regular &lt;https://www.youtube.com/watch?v=K5mmlnSOkLM&gt;`__
   * - Basic
     - Using Leo’s minibuffer
     - `hi-res &lt;http://www.screencast.com/t/tEQ7brI4n6&gt;`__
     - `regular &lt;https://www.youtube.com/watch?v=dEaGOi6hVpo&gt;`__
   * - Intermediate
     - Using abbreviations
     -
     - `regular &lt;http://www.youtube.com/watch?v=WRoiXO53Aac&gt;`__
   * - Intermediate
     - Using clones to speed your work flow
     - `hi-res &lt;http://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;http://www.youtube.com/watch?v=9AvbL_0JEMw&amp;feature=youtu.be&gt;`__
   * - Plugin
     - mod_ftp.py
     -
     - `regular &lt;http://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: http://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::

    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">@language 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()
@language rest

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">@language 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()
@language rest

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">@language 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()
@language rest

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">@language 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()
@language rest 

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">@language rest

The handler for the G command moves or extends the cursor depending on vc.state.

@language 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()
            
@language rest

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

http://ss64.com/nt/syntax-args.html
http://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.20141105052052.4">.. _`Anaconda`:   https://www.anaconda.com/download/
.. _`Miniconda`:  https://conda.io/miniconda.html
.. _`Docutils`:   http://docutils.sourceforge.net
.. _`feedparser`: https://pypi.python.org/pypi/feedparser
.. _`Markdown`:   http://daringfireball.net/projects/markdown/syntax
.. _`Python`:     https://www.python.org/
.. _`PyEnchant`:  http://pythonhosted.org/pyenchant/download.html
.. _`PythonTidy`: https://pypi.python.org/pypi/PythonTidy/
.. _`PyQt`:       http://www.riverbankcomputing.co.uk/software/pyqt/intro
.. _`PyQt4`:      http://www.riverbankcomputing.com/software/pyqt/download
.. _`PyQt5`:      http://www.riverbankcomputing.com/software/pyqt/download5
.. _`Sphinx`:     http://www.sphinx-doc.org/en/stable/

Leo's minimal dependencies are:

* `Python`_ 2.6 or later, including all Python 3.x versions.
* `PyQt4`_ or `PyQt5`_.

The following packages are optional, but recommended:

* `Docutils`_: required for the rst3 command and the viewrendered plugins.
* `Sphinx`_: required to regenerate Leo's documentation.
* `PyEnchant`_: required for spell checking.

Plugins may require other packages.  For example, viewrendered requires `Markdown`_ if one wishes to use markdown rendering, but it is optional. rss.py will not function without `feedparser`_. Etc.
</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.10">Leo makes it easy to create and run unit tests from individual outline nodes or trees. A node whose headline starts with @test defines a unit test. The body text of the @test node contains a **self-contained** unit test. For example, this creates a complete unit test::

    @test fails  (headline)
    assert False (body text)

To run this test, select the @test node and do::

    &lt;alt-x&gt;run-selected-unit-tests-locally.

Leo will create and run the unit test automatically.

To see all of Leo's unit testing commands, do::

    &lt;alt-x&gt;run&lt;tab&gt;

Leo pre-defines 'c', 'g' and 'p' in unit tests just as in scripts.

.. _`unit testing`: unitTesting.html

For more details about unit testing, the `unit testing`_ page.

**Notes for Leo developers**

leo/test/unitTest.leo contains all of Leo's own unit tests.

Running all tests is not necessary.  Just select::

    Active Unit Tests

and then do Alt-4 (run-selected-unit-tests-locally).

**Note**: Some tests will likely fail on machines other than EKR's. You only need to be concerned about unit tests that start failing after you make your changes.
</t>
<t tx="ekr.20141108064630.12">@language rest

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::

@language python

    from setuptools import setup
    
    setup(
        name='Foo for you',
        version='0.3',
        py_modules=['foo'],
        entry_points='''
            [console_scripts]
            foo = foo
            '''
        )
    
@language rest

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

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: http://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">@language rest

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 windget accessible but it doesn't feel like the correct way to do this.

@language python

    mat = MatplotPaneProvider(c)
    mat.mat.someMethod()
    mat.mat.someOtherMethod()
    
@language rest
 
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) http://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. Like this::

    leo --session-save --session-restore &lt;list of .leo files&gt;
    
When Leo closes, it stores session state in ``~/.leo/leo.session``. Session state consists of the list of open files and the selected node in each file. The next time Leo starts with those options, Leo will open these files and will select the appropriate nodes.
</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::

    x.put_sentinels(0)
    x.sentinels[0] = []

Similarly, this line, at the end of the main loop, writes trailing
sentinels::

    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.

http://leoeditor.com/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 b1 was released March 20, 2015.  This release features @clean, one of the most important developments in Leo's history. The Mulder/Ream update algorithm puts @clean on a completely sound footing.

::
  
  http://leoeditor.com/load-leo.html displays .leo files in the browser
  Added the LeoQtGui.IdleTime class and the g.IdleTime wrapper
  Leo now honors @language inside @doc parts
  @shadow is deprecated
</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 final was released November 24, 2014. During this time, Leo's video tutorials made their debut.  These tutorials helped a lot of people learn Leo.

::

    Added leo/core/leoVim.py: full emulation of vim
    Added support for Emacs org-mode outlines
    Added the pylint command
    Added support for PyQt5
    Syntax coloring happens at idle time
    Cloned nodes expand and contract independently
    Added a pluggable architecture for @auto nodes
    Leo's default workbook files contains Leo's quickstart guide
    
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, 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">@language rest
.. @language python below

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::

@language 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()
            
@language rest

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::

@language python

    ':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.28">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 may 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.
</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.
    http://leoeditor.com/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: http://leoeditor.com/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
        macro-      macro expansion
        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
        print-all-uas
        print-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: 3
    :local:

</t>
<t tx="ekr.20150313053238.40">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.20150313053238.44">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.20150313053238.45">.. _`recursive import script`: scripting-miscellany.html#recursive-import-script
.. _git: http://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 an `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.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::

    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">``indent-region (Tab)`` 
    Shift selected lines right one tab position. Inserts one unit of indentation 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, using single-line comments if possible.
``delete-comments (Ctrl-()``
    Deletes comments in the selected lines.
</t>
<t tx="ekr.20150318110552.24">.. _`Python's time module`: http://www.python.org/doc/current/lib/module-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.

``flush-lines``
    Deletes each line that contains a match for regexp, operating on the text after point.
    In Transient Mark mode, if the region is active, the command operates on the region instead.

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

``keep-lines``
    Deletes each line that does not contain a match for regexp, operating on the text after point. In Transient Mark mode, if the region is active, the command operates on the region instead. 

``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.
</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.27">``add-editor``
    Adds a new editor in the body pane and gives it the body editor focus.
``delete-editor``
    Deletes the editor with body editor focus.
``cycle-editor-focus``
    Cycles body editor focus between editors in the body text. The editor that has focus shows the content of the selected outline node; the other body editors continue to show the node contents they last had when they had the body editor focus.
</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 a copy of the Leo outline, changing outline's file name.
``save-file-to``
    Saves a copy of the Leo outline, without changing the outline's file name
``save-file-as-zipped``
    Same as ``save-file-as``, compressing the .leo file with Python's zipfile module.
``save-file-as-unzipped``
    Same as ``save-as``, suppressing compression.


**About compression**: The ``save-file``, ``save-file-as`` and ``save-file-to`` commands compress the file if it was originally compressed. Leo always uses the .leo extension, regardless of whether the file is zipped. Zipped .leo files contain a single archive, whose name is the same as the .leo file itself. Outside of Leo you can change the extension to .leo.zip and use stuffit or other program to expand the .leo file contained within.

**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-leoPlugins-leo``
    Opens LeoPlugins.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:   http://www-cs-faculty.stanford.edu/~knuth/cweb.html
.. _noweb:  http://www.eecs.harvard.edu/~nr/noweb/

``export-headlines``
    Exports all headlines to an external file.
``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, http://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.

**About sessions**: An @session node specifies a list of tabs (.leo files) that Leo opens automatically when Leo first starts. The ``--session-save`` and ``--session-restore`` command-line options write and read ``@session nodes`` from the leo.session file. The next time Leo is started with those options, the files will be open, and the nodes focused as when the previous session ended.
</t>
<t tx="ekr.20150318110552.34">.. _`Idle`: http://en.wikipedia.org/wiki/IDLE_%28Python%29
.. _`Open Office`: https://www.openoffice.org/
.. _`SciTe`: http://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 http://leoeditor.com.
``open-online-toc``
    Opens Leo's table of contents at http://leoeditor.com/leo_toc.html.
``open-online-tutorials``
    Opens Leo's tutorials page at http://leoeditor.com/tutorial.html.
``open-online-videos``
    Opens Leo's video page at http://leoeditor.com/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 http://leoeditor.com/usersguide.html.


</t>
<t tx="ekr.20150318110552.38">``eval-expression``
    Evaluate an expression entered in the minibuffer.
``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.
``head-to-prev-node``
    Moves non-empty text preceding a class, method or function definition to the end of the previous sibling node.
``parse-body``
    Parse p.b as source code, creating a tree of descendant nodes.
    This is essentially an import of p.b.
``tail-to-next-node``
    Moves non-empty text following a class, method or function definition to the start of the next sibling node.
</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.
    
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+S 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.
    
The following commands refer to the Spell Tab:

``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.
``spell-tab-open``
    Show 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`: http://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
    join-leo-irc
    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
    print-all-uas
    print-node-uas
    set-ua
</t>
<t tx="ekr.20150318110552.79">``act-on-node``
    Executes node-specific action, typically defined in a plugins as follows::

        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`: http://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.86">``run-all-unit-tests-externally``
    Run all unit tests in a separate process.
``run-all-unit-tests-locally``
    Run all unit tests in this outline.
``run-marked-unit-tests-externally``
    Run all marked unit tests in a separate process.
``run-marked-unit-tests-locally``
    Run all marked unit tests in this outline.
``run-selected-unit-tests-externally``
    Run all unit tests in the selected tree in a separate process.
``run-selected-unit-tests-locally``
    Run all unit tests in the selected tree in this outline.
</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.20150319142303.4"></t>
<t tx="ekr.20150320085538.4"># True: suppress all output from rst.report()</t>
<t tx="ekr.20150323102036.1">@language rest

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::

@language python

    def print_hi():
        print('hi')
    
    g.app.idleTimeManager.add_callback(print_hi)

@language rest

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::

@language python
    
    def handler(it):
        """IdleTime handler.  it is an IdleTime instance."""
        delta_t = it.time-it.starting_time
        g.trace(it.count,it.c.shortFileName(),'%2.4f' % (delta_t))
        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()

@language rest

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 ekr.leo 0.5100
    handler 2 ekr.leo 1.0300
    handler 3 ekr.leo 1.5400
    handler 4 ekr.leo 2.0500
    handler 5 ekr.leo 2.5610
    handler done
    
Timer instances are completely independent::

@language python

    def handler1(it):
        delta_t = it.time-it.starting_time
        g.trace('%2s %s %2.4f' % (it.count,it.c.shortFileName(),delta_t))
        if it.count &gt;= 5:
            g.trace('done')
            it.stop()

    def handler2(it):
        delta_t = it.time-it.starting_time
        g.trace('%2s %s %2.4f' % (it.count,it.c.shortFileName(),delta_t))
        if it.count &gt;= 10:
            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()
        
@language rest

Here is the output::

    handler1  1 ekr.leo 0.5200
    handler2  1 ekr.leo 1.0100
    handler1  2 ekr.leo 1.0300
    handler1  3 ekr.leo 1.5400
    handler2  2 ekr.leo 2.0300
    handler1  4 ekr.leo 2.0600
    handler1  5 ekr.leo 2.5600
    handler1 done
    handler2  3 ekr.leo 3.0400
    handler2  4 ekr.leo 4.0600
    handler2  5 ekr.leo 5.0700
    handler2  6 ekr.leo 6.0800
    handler2  7 ekr.leo 7.1000
    handler2  8 ekr.leo 8.1100
    handler2  9 ekr.leo 9.1300
    handler2 10 ekr.leo 10.1400
    handler2 done
    
**Recycling timers**

The g.app.idle_timers list retrains references to all timers so they *won't* be recycled after being stopped.  This allows timers to be restarted safely.

There is seldom a need to recycle a timer, but if you must, you can call its destroySelf method. This removes the reference to the timer in g.app.idle_timers. **Warning**: Accessing a timer after calling its destroySelf method can lead to a hard crash.
</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

.. Deprecated tangle/untangle commands.
.. These will never be removed.
tangle
tangle-all
tangle-marked
untangle
untangle-all
untangle-marked
</t>
<t tx="ekr.20150323103115.1">.. _`Emacs rectangle commands`: http://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">``print-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.20150323185151.1">.. _`Emacs macro commands`: http://www.gnu.org/software/emacs/manual/html_node/emacs/Keyboard-Macros.html#Keyboard-Macros

The following commands emulate the `Emacs macro commands`_::

    macro-call
    macro-call-last
    macro-end-recording
    macro-load-all
    macro-name-last
    macro-print-all
    macro-print-last
    macro-save-all
    macro-start-recording
</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.

``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.20150328073917.1">Here is a python program that will run unitTest.leo using the leoBridge module. Change the path as required::
    
    import leo.core.leoBridge as leoBridge
    import leo.core.leoTest as leoTest
    path = &lt;path to unitTest.leo&gt;/unitTest.leo'
    
    def main ():
        tag = 'leoTestBridge'
    
        # Setting verbose=True prints messages that would be sent to the log pane.
        bridge = leoBridge.controller(
            gui='nullGui',
            loadPlugins=False,
            readSettings=False,
            silent=True,
            verbose=False) 
        if bridge.isOpen():
            g = bridge.globals()
            c = bridge.openLeoFile(path)
            runUnitTests(c,g)
        print('done: %s' % tag)
    
    def runUnitTests (c,g):
        nodeName = 'Active unit tests' # The tests to run.
        try:
            u = leoTest.TestManager(c)
            p = u.findNodeAnywhere(nodeName)
            if p:
                print('running unit tests in %s...' % nodeName)
                c.selectPosition(p)
                c.debugCommands.runSelectedUnitTestsLocally()
                print('unit tests complete')
            else:
                print('===== node not found: %s' % nodeName)
        except Exception:
            print('unexpected exception')
            g.es_print_exception()
            raise
    
    if __name__ == '__main__':
        main()</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.20150415111549.1">The c.cloneFindAllAtNode and c.cloneFindAllFlattenedAtNode methods start the clone-find-all and clone-find-all-flattened commands at a particular node. For example, here is the body of ``@button cfa-code @args add`` in leoPy.leo::

    c.cloneFindAllFlattenedAtNode('Code',top_level=True)
    
The ``@args add`` part of the headline causes Leo to add the ``cfa-code`` command to Leo's history list, so there is no urgent need to use a separate key binding for this command.</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.20150603115204.1">``@bool tidy-autobeautify = False``
    When True, Leo beautifies all changed files when saving an outline. The default must always be False in leoSettings.leo and in unitTest.leo.

``@bool tidy-keep-blank-lines = False``
    When True, the beautifier retains blank lines within classes, functions and methods.
</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::

    @beautify
    ...
    @nobeautify

beautifies the entire node.  Otoh::

    @nobeautify
    ...
    @beautify

skips beautification of the entire node. Yes, this is less precise than one could imagine, but it's good enough for now.
</t>
<t tx="ekr.20150603115311.1">The following 5 problems are relatively minor.  They apply only to the Python beautifier. The workaround in most cases is to use ``@nobeautify``.

**1. Syntax Errors**

The pass hack converts::

    if 1:
        &lt;&lt; a section &gt;&gt;

to::

    if 1:
        #!!!!! &lt;&lt; a section &gt;&gt;
        pass

which is usually, but not always, syntactically correct Python. Here is an example from Leo's core::

    patterns = [
        &lt;&lt; Sherlock patterns for pylint &gt;&gt;
    ]

The pass hack produces syntactically incorrect code::

    patterns = [
        #!!!!! &lt;&lt; Sherlock patterns for pylint &gt;&gt;
        pass
    ]

**2. Alignment**

The beautifier eliminates blanks used to align code.  For example::

    d = {
        key1:     value1,
        longKey2: value2,
    }

The beautifier might preserve such lines, but there are no plans at present to do so.

The regular expression: ``=([ ])*\{([^}])*$`` will discover complex dictionaries that you may want to protect with ``@nobeautify``.

**3. Operator priority**

Pep 8 suggests considering eliminating blanks around higher-priority operators.  The beautifier puts blank lines about all operators, except unary operators.

This is a difficult problem of style, for which no approach works in all cases.  Surprisingly, retaining blanks around ``*`` usually looks best in Leo's own code.

**4. @clean &amp; @auto**

Consider adding @nobeautify for all ``@auto`` and ``@clean`` nodes, on the theory that such nodes are not primarily your responsibility.  But adding ``@nobeautify`` is completely up to you.

**5. Extra blank lines**

The beautifier will sometimes insert extra spaces between class/def lines and preceding comments.
</t>
<t tx="ekr.20150603115400.1">You may invoke a *lightly tested* stand-alone version the Python beautifier from the command line.

You can run leoBeautify.py from any directory, provided that a copy of leoGlobals.py exists in the same directory.

Run the stand-alone beautifier as follows::

    python -m leoBeautify file1, file2, ...

To get a usage message, do::

    python -m leoBeautify -h

This produces::

    Usage: python leoBeautify -m file1, file2, ...
    
    Options:
      -h, --help             show this help message and exit
      -d, --debug            print the list of files and exit
      -k, --keep-blank-lines keep-blank-lines

</t>
<t tx="ekr.20150603120140.1">.. _`Pep 8 recommendations for whitespace`: https://www.python.org/dev/peps/pep-0008/#whitespace-in-expressions-and-statements
.. _`pep 8 recommendations for blank lines`: https://www.python.org/dev/peps/pep-0008/#blank-lines

The beautifier will *just work* for most people. 

The beautifier follows the `Pep 8 recommendations for whitespace`_. It ensures that names, operators, strings and comments are separated by zero or one blanks::

    def spam(a, b, c=5, *args, **keys):
        foo(a, 25, b=2)
        a = b + c - 5
        b = -d
        if 0 &lt; b &lt; 26:
            ...

Leo follows the `pep 8 recommendations for blank lines`_ *between* classes and defs, with minor variations due to Leo's node structure.

Optionally, the beautifier can remove blank lines *within* classes and defs, controlled by the setting *@bool tidy-keep-blank-lines*.
</t>
<t tx="ekr.20150603120150.1">Except for dictionary definitions, the beautifier does what is expected, leaving difficult or idiosyncratic cases completely at the user's discretion.

- For the first time ever, Leo's beautify commands work properly with Leonine syntax.
- All files in leoPy.leo can now be beautified without fuss.
- Except for spacing around operators, the beautifier mostly leaves your code **as it is**.
- The beautifier makes no difficult choices. It preserves your choices.
</t>
<t tx="ekr.20150603120245.1">The following could be done only at the cost of more settings and debates about what the default settings should be.

- Splitting long lines.
- Improving spacing around operators.
- Moving or indenting comment lines.

All these involve significant personal judgments and preferences. Pep 8 explicitly allows various approaches.
</t>
<t tx="ekr.20150603120515.1">The Python beautifier never creates new lines! The beautifier never adds or changes:

- Line breaks for "long" lines.
- Line breaks in function argument lists.
- Leading whitespace in continued argument lines.
- Line breaks call arguments.
- Leading whitespace in continue function call arguments.
- Whitespace (including line breaks) within statements.

Pep 8 allows considerable flexibility regarding continued lines. The beautifier will leave all of the following unchanged, whether or not they conform to the pep 8 recommendation::

    def function1 (a, b, c):
        pass
    
    def function2 (
    a = 2, # a comment
    b = 3, # another comment
    ):
        pass
    
    def function3 (
        a = 2, # a comment
        b = 3, # another comment
    ):
        pass
    
    def function4(
                  a = 2, # a comment
                  b = 3, # another comment
                 ):
        pass

Similarly, the beautifier will not touch arguments in function calls.
</t>
<t tx="ekr.20150603161559.1">``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 *safe*.  It can never alter the meaning of a program because it compare the parse trees of the original and beautified code. The code remains unchanged if there is a mismatch. Such **beautifier errors** produce debugging dumps. Please report any such errors to Leo's developers.

The Python beautifier works only on syntactically correct code. It issues a warning and does nothing for syntactically incorrect code.

The Python beautifier converts **Leonine syntax** (directives, section references and @doc parts) to comments, possibly with a trailing ``pass`` statement.  Usually this produces syntactically correct text.  As discussed below, the trailing ``pass`` can create SyntaxError's.

The following sections describe how the beautify-tree and beautify-node commands work in more detail.</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 leoPluginsRef.leo::

    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;

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.4">https://groups.google.com/d/msg/leo-editor/LePOMe_ckeg/_UasKCKP6NMJ

Some time ago there were a discussion about Leo in virtualenv.

Now I could test it in Python3, PyQt5 on Kubuntu:

Here are the steps (I worked in a folder with write permission '/leo'):

1. Install PyQt5 in the system:

sudo aptitude install python3-pyqt5

2. Create the virtual environment with the '--system-site-packages' switch and without pip (I've found this the only way, which worked):

pyvenv-3.4 --system-site-packages --without-pip py3-pyqt5

3. Install setuptools and pip into the created environment:

wget --no-check-certificate https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O ez_setup.py

py3-pyqt5/bin/python ez_setup.py --insecure

wget --no-check-certificate https://pypi.python.org/packages/source/p/pip/pip-6.0.8.tar.gz#md5=2332e6f97e75ded3bddde0ced01dbda3

tar xzvf pip-6.0.8.tar.gz

cd pip-6.0.8

../py3-pyqt5/bin/python setup.py install

cd ..

Now you can install what you want in the created environment, without affecting the system.

py3-pyqt5/bin/pip install Sphinx

4. From the leo-editor source folder launch Leo with the new interpreter:

In my case:

/leo/py3-pyqt5/bin/python launchLeo.py</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.6">Running a unit test locally, without exiting Leo, saves a lots of time.  It's much faster than having to load unitTest.leo or even a small .leo file.

The question is, how to use the newest code?  imp.reload often doesn't work. But there is a trick that does work.  Clone the code under development and put it under an @test node.  The script in the @test node uses @others to gain access to the code, not an import.

For instance, here is the @test node I use to develop the new javascript importer::

    g.cls()
    p1 = p.copy()
    if c.isChanged():
        c.save()
    import leo.plugins.importers.basescanner as basescanner
    @others
    scanner = JavaScriptScanner(c.importCommands)
    h = '@ignore js-test'
    p = g.findNodeAnywhere(c, h)
    if p:
        while p.firstChild():
            p.firstChild().doDelete()
    else:
        p = c.insertHeadline()
        p.h = h
    c.selectPosition(p)
    fn = r'c:\prog\jQuery-short2.js'
    s = open(fn, 'r').read()
    print('Sources..\n\n%s\n\n' % s)
    scanner.scan(s, p)
    c.selectPosition(p1)
    c.redraw()
    print('done')

To repeat, the code under test is a child of this node, so the script uses @others to gain access to it.  It's super fast.</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, vim, xemacs and ILeo (IPython bridge), and leoBridge module.
- Leo's minibuffer commands, borrowed shamelessly from Emacs.
- @test and @suite: Leo's outline-oriented unit testing framework.
- @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, @test, @auto, @clean, Leo's plugin architecture, the rst3 command, the Leo bridge and the IPython 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.20160309092522.1">The name "Stupendous Aha" is a bit ironical.  From one point of view it may seem obvious. Nevertheless, it was a true Aha for me.

Unit tests permanent check of the correctness of a piece of code. Test Driven Development expands this view. But unit tests are much more important.  In fact, unit tests are *general-purpose helper scripts* that can be run at any time.

1. Unit tests codify and make explicit desired or expected behavior.

2. Unit tests are a way of "maintaining attention" on a problem.  Unit tests don't forget, and they are permanent.

3. Unit tests *do whatever we want*, and they do it automatically.

In short, unit tests are a *master tool* for any programmer or designer.

Leo's @test nodes are one way to run unit tests.  You can also use @button to encapsulate your tests.  After running an @button script, you can quickly re-run @button scripts with Ctrl-P, repeat-complex-command.
</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/python2.7/site-packages:${PATH}"
    
After this leo editor will open with using the default python installation provided by MacOS.</t>
<t tx="ekr.20160410043905.1">Within @path and @&lt;file&gt; paths, Leo evaluates ``{{exp}}`` with the the following symbols defined: ``c``, ``g``, ``p``, ``os`` and ``sys``. Also, ``sep`` is defined as os.sep.
File names are relative to the directory containing the .leo file, but that can be overridden, depending on the form of the file name. For example::

    @file {{c.config.getString('my-dir')}}{{sep}}myFile.py

</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.  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.20160414191631.1">A frequently requested feature is for clones that don't share children. The typical use case is to gather data from one place to be used in another. For instance, we might want to document a function by special-cloning only its node excluding its children. A **gathering script** can provide most of the benefits of detached clone:

1. The script has complete flexibility to find a desired positions anywhere, including other .leo files.  This moots the need for cross-file clones.

2. For any gathered position p, the script has complete flexibility to make available p.h, p.b or p.children, depending on the needs of the script.

For example, a documentation script might "scrape" one or more .leo files for data, and then create nodes that reference the scraped data.


</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::

    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.20161014160238.1">Leo uses constants and functions defined in leoGlobals.py to ensure that Leo's code works on both Python 2.7+ and Python 3.x.

- g.isPython3: True if Leo is running Python 3.x.  False otherwise.
 
You should be particularly aware of:

- g.isBytes, g.isInt, g.isString, g.isUnicode.
- g.toUnicode, g.toEncodedString, g.isValidEncoding.
- g.u, g.ue.

If you use the above methods there should never be a need for direct calls to unicode(s), encode(s) or decode(s).  The above methods are clearer, safer, and do better error checking and recovery.

A few other functions should be on your radar:

- g.readFileIntoEncodedString
- s, e = g.readFileIntoString
- g.stripBOM

There may be cases where direct tests against g.isPython3 seem the clearest. That's fine, but usually you can avoid direct tests.

**Important**: g.u and g.toUnicode are not always interchangeable. You should always use g.u to convert Qt QStrings to unicode. Here is an example from quicksearch.py::

    t = g.u(self.ui.lineEdit.text())

Similarly, use g.ue to convert Qt bytes to unicode. Here is an example from LM.openZipFile::

    s = theFile.read(name)
    if g.isPython3:
        s = g.ue(s, 'utf-8')
    return StringIO(s)

Actually, the above code is dubious, because it will break if the mode of the open command changes.

**Note**: Leo's code sometimes does s = g.u('aString'), but this isn't needed since Python 2.7 which supports unicode literals.</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.
``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.
``print-buttons``
    Print 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-new-objects
    gc-dump-objects-verbose
    gc-print-summary
    gc-trace-disable
    gc-trace-enable

Idle time::

    disable-idle-time-events
    enable-idle-time-events
    toggle-idle-time-events

</t>
<t tx="ekr.20161020064706.1">The following print information to Leo's log pane::

    print-bindings
    print-commands
    print-focus
    print-plugin-handlers
    print-plugins-info
    print-settings
    print-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.restore_session = False
    # True: restore session on startup.
self.save_session = False
    # True: save session on close.
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.
self.sessionManager = None
    # The singleton SessionManager 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.
</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(True)
        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](http://leoeditor.com/) 5.5 is now available on [SourceForge](http://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](http://leoeditor.com/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](http://leoeditor.com)
- [Documentation](http://leoeditor.com/leo_toc.html)
- [Tutorials](http://leoeditor.com/tutorial.html)
- [Video tutorials](http://leoeditor.com/screencasts.html)
- [Forum](http://groups.google.com/group/leo-editor)
- [Download](http://sourceforge.net/projects/leo/files/)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [What people are saying about Leo](http://leoeditor.com/testimonials.html)
- [A web page that displays .leo files](http://leoeditor.com/load-leo.html)
- [More links](http://leoeditor.com/leoLinks.html)
</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')

@language rest
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

http://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.10">.. _`git`: https://git-scm.com/

**Important**: This section tells how to set up `git`_ so that you can grab
the latest sources using ``git clone``.

Many users will want to track the development version of Leo, in order to stay
on top of the latest features and bug fixes. Running the development version is
quite safe and easy, and it's also a requirement if you want to contribute to
Leo.

1. First, you need to get git from http://git-scm.com/.
2. Get Leo from GitHub by doing::

        git clone https://github.com/leo-editor/leo-editor (http access)
    
   or::
   
        git clone git@github.com:leo-editor/leo-editor.git (ssh access)

And that's it! You can run launchLeo.py directly. When you want to refresh the
code with latest modifications from GitHub, run git pull.
</t>
<t tx="ekr.20170206073747.2">Install Python and Qt, as described above (`Installing Packages`_).

Now you have a choice.  You can use Leo's binary (single-click) installer
or download Leo's sources directly.
</t>
<t tx="ekr.20170206073747.3">.. _`SourceForge download page`: http://sourceforge.net/projects/leo/files/Leo/
.. _`Running Leo`: running.html

Leo has a binary installer for Windows, available at the `SourceForge download page`_. The binary installer installs Leo and sets Windows file associations. Now see `Running Leo`_ for how to run Leo after installing it.
</t>
<t tx="ekr.20170206073747.4">.. _`Leo's download page`: download.html

You may download Leo's sources in one of three ways, as described at `Leo's download page`_. If the sources are zipped, unpack them into a temp folder. You may place the sources anywhere you like, including Python's \*site-packages* folder, for example, C:\\Python26\\Lib\\site-packages.

Next, you will find it convenient to create Windows files associations for .leo files, as described in the next section.
</t>
<t tx="ekr.20170206073747.5">*Important*: Leo's binary Windows installer sets file associations
automatically, so this section is needed only if you are installing Leo
from a .zip file or other sources.

There are two ways of associating .leo files with Leo. The first uses the
Windows control panel, the second, the Windows console.

**Method 1: Using the Windows Control Panel**

The goal is that you want to associate .leo files with the following command::

    "&lt;path to python&gt;\python.exe" "&lt;path to launchLeo.py&gt;\launchLeo.py" "%1"
    
Before Windows 7, you do this with using the Folder Options control panel.
In Windows 7, you do this with the Default Programs control panel.

*Note*: "%1" passes just the file being clicked on, quoted for spaces etc.
The quotation marks are needed to handle file paths containing spaces.

*Warning:* In a batch file, %1 passes just the first command line parameter.
It is logical to expect %* to work for file associations just as in batch
files. Alas, it does not.

**Method 2: Using the Windows Console**

Open a Windows console with administrator privileges, then type::

    ftype LeoFile="&lt;path to python&gt;\pythonw.exe" "&lt;path to launchLeo.py&gt;\launchLeo.py" "%1" %*
    assoc .leo=LeoFile

And put this leo.bat in %PATH%::

    @start /b "Leo" "&lt;path to python&gt;\python.exe" "&lt;path to launchLeo.py&gt;\launchLeo.py" %*
    
You may omit the /b option if you want to create a separate console window for Leo.
</t>
<t tx="ekr.20170206073747.6">.. _`install Leo from a debian package`: installing.html#installing-from-a-debian-package
.. _`install Leo from sources`: installing.html#installing-from-sources-linux

If you are using Debian/Ubuntu, it's best to
`install Leo from a debian package`_, as described next.
This provides file associations, icons, launcher items, etc.
Otherwise, you may `install Leo from sources`_.
</t>
<t tx="ekr.20170206073747.7">Add these files to `/etc/apt/sources.list`::

    deb http://ppa.launchpad.net/villemvainio/ppa/ubuntu jaunty main
    deb-src http://ppa.launchpad.net/villemvainio/ppa/ubuntu jaunty main

Then run::

    sudo apt-get update
    sudo apt-get install leo
</t>
<t tx="ekr.20170206073747.8">.. _`download Leo's sources`: download.html

You may `download Leo's sources`_ in one of three ways. If the sources
are zipped, unzip them into a folder in your home directory, say
~/leo-5.8.

You now have several choices.

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

2. You can install leo into /usr/local/lib and /usr/local/bin with:

    cd ~/leo-5.8
    sudo python setup.py install

See `Running Leo`_ for how to run Leo after installing it.
</t>
<t tx="ekr.20170206073747.9">.. .. http://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 http://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 (http://mxcl.github.com/homebrew/) by running the
  following command in the Terminal::
    
    ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

- 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/python2.7/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.20170206073848.1"></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.setChanged(False)
    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
========================

**Important**: the easiest way to search Leo's documentation is to search LeoDocs.leo.

.. _`Leo's home page`: http://leoeditor.com/

`Leo's home page`_

.. toctree::
   :maxdepth: 2
   
   preliminaries
   
.. toctree::
   :maxdepth: 1

   getting-started
   
.. toctree::
   :maxdepth: 1

   Cheat Sheet &lt;cheatsheet&gt;
   
.. toctree::
   :maxdepth: 2

   screencasts
   Tutorials &lt;tutorial&gt;
   Users Guide &lt;usersguide&gt;
   leoandotherprograms
   intermediatetopics
   appendices

.. toctree::
   :maxdepth: 1

   history
   FAQ
   glossary
   What's New &lt;what-is-new&gt;

.. toctree::
   :hidden:

   slides
   leoLinks
   screen-shots

`Leo's home page`_.

</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 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
    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.
    
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.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::

    '''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. See `this FAQ entry &lt;FAQ.html#what-about-code-that-looks-like-a-section-reference&gt;`_.</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::

    '''
        Print all headlines of the outline, properly indented,
        with the number of characters in each node's body text.
    '''
    # c.all_positions() is a python generator yielding all positions, in outline order.
    for p in c.all_positions():
        print('%3s %s %s' % (
            len(p.b),       # p.b is p's body text.
            ' '*p.level(),  # p.level() is p's indentation level.
            p.h,            # p.h is p's headline.
        )

.. _`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 in addition 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::

    @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() is a python generator yielding p and
    # all positions in p's subtree, in outline order.
    for p in p.self.and_subtree():
        print('%3s %s %s' % (
            len(p.b),       # p.b is position p's body text.
            ' '*p.level(),  # p.level() is p's indentation level.
            p.h,            # p.h is p's headline.
        )
        
.. index::
    pair: @test Node; Tutorial</t>
<t tx="ekr.20170217093640.3">**@test nodes** create unit tests. @test nodes automatically convert the body to a subclass of unittest.TestCase. Run these tests with one of Leo's ``run-unit-test-`` commands. ``&lt;Alt-X&gt;run&lt;tab&gt;`` gives the full list. Here one of Leo's actual unit tests::

    @test c.positionExists for all nodes # In the headline

    for p in c.all_positions():
        assert c.positionExists(p)
    
Within @test nodes, c, g, and p are predefined as usual. In addition, **self** is the instance of unittest.TestCase created by the @test node. For example::
  
    self.assertTrue(g)
    
For more details, see `Leo's unit-testing reference &lt;unitTesting.html&gt;`_.
</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;http://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">@language rest

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:
    
@language python

    def predicate(p):
        return p.isAnyAtFileNode() and p.h.strip().endswith('.py')
       
    roots = g.findRootsWithPredicate(c, root, predicate)
    
@language rest

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:

@language python

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}
</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.20170301013432.1">Test Driven Development (TDD) takes a bit of setup, but the initial investment repays itself many times over. To use TDD with Leo, start @test nodes with **preamble code**. As explained below, the preamble will do the following:

1. Optional: save the present outline if it has been changed.

2. Reload modules with imp.reload.

3. Create *new instances* of all objects under test.

Here is the actual preamble code used in Leo's import tests::

    if 0: # Preamble...
        # g.cls()
        if c.isChanged(): c.save()
        import leo.core.leoImport as leoImport
        import leo.plugins.importers.linescanner as linescanner
        import leo.plugins.importers.python
        import imp
        imp.reload(leo.plugins.importers.linescanner)
        imp.reload(leo.plugins.importers.python)
        imp.reload(leoImport)
        g.app.loadManager.createAllImporetersData()
        ic = leoImport.LeoImportCommands(c)
    else:
        ic = c.importCommands

    # run the test.
    ic.pythonUnitTest(p,s=s,showTree=True)
    
Let's look at this example in detail. These lines optionally clear the screen and save the outline::

    # g.cls()
    if c.isChanged(): c.save()

The next lines use imp.reload to re-import the affected modules::

    import leo.core.leoImport as leoImport
    import leo.plugins.importers.linescanner as linescanner
    import leo.plugins.importers.python
    import imp
    imp.reload(leo.plugins.importers.linescanner)
    imp.reload(leo.plugins.importers.python)
    imp.reload(leoImport)
    
Using imp.reload is usually not enough.  The preamble must *create new instances* of all objects under test. This can be a bit tricky. In the example above, the following lines create the new objects::

    g.app.loadManager.createAllImporetersData()
    ic = leoImport.LeoImportCommands(c)
    
The call to LM.createAllImporetersData() recomputes global tables describing importers. These tables must be updated to reflect possibly-changed importers. The call to leoImport.LeoImportCommands(c) creates a *new instance* of the c.importController. We want to use this new instance instead of the old instance, c.importController.

**Summary**
    
TDD makes a big difference when developing code. I can run tests repeatedly from the Leo outline that contains the code under test. TDD significantly improves my productivity.

Preamble code reload changed modules using imp.reload(). Preamble code must also create new instances of *all* objects that may have changed.

When creating several related unit tests, cutting and pasting the preamble from previous unit tests is usually good enough. @button scripts that create preamble code might be useful if you create lots of tests at once.
</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.20170311120214.1">- Use `imp.reload &lt;https://docs.python.org/3/library/imp.html&gt;`_ to reload all changed modules.
- Make sure to *instantiate* any changed objects.
- See `this section &lt;unitTesting.html#test-driven-development-in-leo&gt;`_ for full details.
</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 print out 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;pri&lt;Tab&gt;``

You will see ``print-`` in the minibuffer. This is the longest common prefix of all the command names that start with ``pri``. The Completion tab in the log pane shows all the commands that start with ``print-``.

Now just type ``c&lt;Tab&gt;`` You will see the ``print-commands`` command in the minibuffer.

Finally, ``&lt;Return&gt;`` executes the ``print-commands`` command. The output of the print-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">@language python

This script creates an outline node as the last top-level node::

    p = c.lastTopLevel().insertAfter()
    p.h = 'my new node'
    c.redraw(p) # Selects the new node.
    
This script creates multiple nodes, with different headlines::

    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::

    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::

    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::

    @first # -*- coding: utf-8 -*-
    '''whatever.py'''
    &lt;&lt; imports &gt;&gt;
    @others
    # That's all, folks
    @language python
    @tabwidth
    
Child nodes must define the &lt;&lt; import &gt;&gt; node and the methods of the Controller class.

When writing this file, Leo writes the first two lines::

    @first # -*- coding: utf-8 -*-
    '''whatever.py'''
    
followed by the *body text* of the &lt;&lt; imports&gt;&gt; node, followed by the body text of all *other* nodes, in outline order, followed by the comment # That's all, folks.
</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;http://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.20170314091501.1">Renders @jinja nodes.
</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.20170314164228.1">Scripts may safely assume that most names defined in Leo's core will never change. Names used outside their defining module *can't* be changed, because doing so would impact existing user scripts. This includes virtually everything in leoGlobals.py, and many names in leoCommands.py and other files. The only names that might change are unlikely every to be of use to scripts anyway. For example, helper functions.
</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;http://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, @test.

.. _`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 &lt;http://mutabit.com/offray/static/blog/output/posts/on-deepness-and-complexity-of-ipython-documents.html&gt;`_ describes this screen shot in detail.

|leo-thesis|
</t>
<t tx="ekr.20170403185500.1">**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.20170608071626.1">Leo 5.6 September 25, 2017

[Leo](http://leoeditor.com/) 5.6 is now available on [SourceForge](http://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](http://leoeditor.com/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](http://leoeditor.com)
- [Documentation](http://leoeditor.com/leo_toc.html)
- [Tutorials](http://leoeditor.com/tutorial.html)
- [Video tutorials](http://leoeditor.com/screencasts.html)
- [Forum](http://groups.google.com/group/leo-editor)
- [Download](http://sourceforge.net/projects/leo/files/)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [What people are saying about Leo](http://leoeditor.com/testimonials.html)
- [A web page that displays .leo files](http://leoeditor.com/load-leo.html)
- [More links](http://leoeditor.com/leoLinks.html)
</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.20170612101117.1">Leo recognizes section references *everywhere*, even inside strings or comments. If a source code line contains &lt;&lt; followed by &gt;&gt; on the same line, you must rewrite the line.  For example, suppose your C code contains::

    a = 1 &lt;&lt; 5 + 2 &gt;&gt; 3;
    
You could rewrite this as::

    a = 1 &lt;&lt; 5 + \
        2 &gt;&gt; 3;

.. Smart quotes are probably causing problems here:

g.angleBrackets(s) returns string s enclosed in angle brackets.

For example, h = g.anglebrackets(\"abc\") sets h to &lt;&lt;abc&gt;&gt;.
</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.20170618111245.1">1. Resize your console/terminal to a recommended minimum size of 100x35.
   **Leo will crash on startup if there are fewer than 34 rows**.

2. Launch Leo with the ``--gui=console`` command-line option::

    &gt;launchleo.py --gui=console [path to leo file\file_name.leo]

If no .leo file is given, Leo will open ~/.leo/workbook.leo (Leo's workbook file). Initially, this file contains Leo’s cheat sheet and an example from the rst3 tutorial.

**Only one outline can be open at a time**. The only way to load .leo files is from the command line. (There are no menus).
</t>
<t tx="ekr.20170618111248.3">Moving around the main window::

    Mouse clicks properly switch nodes.
    Arrow-up and Arrow-down keys switch panes (when not editing).
    Tab: moves down from pane to pane.
    Shift-Tab: moves up from pane to pane.

To edit a headline, select the node you wish to edit, then press e to edit the node headline (return to end)::

    i: to insert a new node.
    d:  delete node

To edit body text, use Tab to move down to the Body Pane, or Shift-Tab to move up to the Body Pane. Follow the prompts::

    e to edit line (return to start a new line)
    esc to end editing.
    d to delete line.
</t>
<t tx="ekr.20170618111248.5">Supported Ctrl commands::

    Ctrl-B (execute-script).
    Ctrl-F (find)
    Ctrl-Q (quit-leo)
    Ctrl-S (save) Works for windows cmd.exe, but not Consolez.

Unsupported Ctrl commands::

    Alt-S,
    Ctrl-Shift-S
    Ctrl-O
    Shift arrows
</t>
<t tx="ekr.20170618113437.1"></t>
<t tx="ekr.20170618113503.1">##################
Leo's Console Gui
##################

.. |ConsoleWindow| image:: screen-shots/console-window.png

This chapter describes Leo's console gui. This allows Leo to be run remotely.

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

Here is a screen shot:

|ConsoleWindow|

The area between colons in the Tree pane corresponds to Leo's icon box::

    +:    : node has unexpanded children.
    -:    : node is expanded.
     :    : node has no children.
     '*   : node is the selected node.
     : C  : node is a clone.
     :  M : node is marked.
     :   T: node has body text.
</t>
<t tx="ekr.20170618115228.1">The console gui sends the output of g.pr and g.trace to another console. To do this, you must start a socket listener in the *other* console, listening to the broadcaster on localhost::

    Leo Qt (listener) &lt;-- Leo console, (broadcaster)
    
To set this up:

1. In the **listener console**, start a regular Leo Qt session with the ``--listen-to-log`` command-line option. You can start a listener at any time with Leo's ``listen-to-log`` command. The ``kill-log-listener`` command kills the listener, if it exists.
  
2. In the **broadcast console**, start Leo with the console gui using the ``--gui=console`` command-line option. This automatically starts the broadcaster.

If the listener is active, the log output from the curses gui console will be displayed in the listener's console.
</t>
<t tx="ekr.20170618115641.1">This plugin suffers from fundamental limitations, as discussed in the following sections...

</t>
<t tx="ekr.20170618162705.1">To exit Leo: click "Quit Leo" button and &lt;Enter&gt;. Ctrl-Q also works. **There is no way to cancel Ctrl-Q**. A dialog box will appear. Press Enter to select "No". Press arrow keys to move between "Yes" and "No". "Yes" saves, then exits. "No" Exits without saving.
</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.

d4f481 on ​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 print-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: http://leoeditor.com/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.69">55b2037ac3a: 2016-11-22 06:33:17 Removed importer;; abbreviation(!!)


Restored the abbreviation from f10fa02b8cb681, the previous commit.
</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.2">Here are step-by-step instructions for developing code in Leo without having to reload Leo.

1. Create a **dev node** as a test harness.

This node (in the Leo outline) defines your development environment. You can use an @test node, an @button node, or an @command node. Using a plain outline node would be less convenient because you won't be able to execute it so easily.

The **dev script** is the script in the dev node itself.  The **code under development** is the code exercised by the dev script.

This is the most important step! Once you say to yourself, "Ok, I'm going to be clever and develop my code using a dev script, everything else will happen naturally. That is, the programming process itself will lead you to the next action. If you don't create a custom dev environment you will have to reload Leo to test your new code. That will be much slower.

2. Set up your dev node so you can execute it with a single keystroke.

You can do any of the following:

- Use a marked @test node and use run-marked-unit-tests-locally.
- Disable or ignore all other @test nodes and then use run-all-unit-tests-locally.
- Bind a keystroke to an @button or @command node.
- Run an @button or @command node the first time from the minibuffer, and then re-execute it with Ctrl-P (repeat-complex-command.

3. Define or access the code under development.

There are two main ways to do this:

A. Clone the code under test and move the clones so they are children of the dev node. Access the code under test using @others in the top-level node.

B. Import one or more modules containing the code under test. Access the code using imp.reload to ensure that all imported modules are up-to-date.

4. Create new instances of objects

**You must not use existing Leo objects when testing Leo code.**  This includes all objects accessible via c, g and p, either directly or indirectly.  For example, you must not use c, c.frame, c.frame.body, etc., etc., even if you have reloaded all of Leo's modules!

You will seldom need to worry about reloading code if you use @others to define the code under test.

5. Run the test, edit, repeat

After creating the dev node you simply run the dev script until everything works :-)  The details depend on the code being developed.  Otoh, we can safely assume that devs can handle problems as they arise.

Summary

@test, @command or @button can be thought of as defining an (almost) pristine dev environment. This is another way of describing the Stupendous Aha. The initial cost of creating dev nodes pays off immediately.

Dev scripts should create a new, pristine environment every time it they are executed, using imp.reload as needed. Dev scripts should always create new objects for testing.  Dev scripts may use Leo's core objects provided they have not been modified.

Dev scripts have many advantages.  They can:

- access code using clones.
- use outlines to organize the code under development.
- form a permanent record of completed work.
- can morph into unit tests.
</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.20170815082542.1">Leo's Console minimal dependencies are:

- Python 2.6 or later, including all Python 3.x versions.
- Curses
  For windows, download and install curses from `this page &lt;http://www.lfd.uci.edu/~gohlke/pythonlibs/#curses&gt;`_
  and then install using pip.
    
- PythonTk for clipboard handling
  For Linux use your system package manager, e.g. `sudo apt install python-tk`</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.20170906090516.1"></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: http://leoeditor.com/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 DemoBold
</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.20171130105248.1">The following sections discuss will be of interest *only* to those who want to enhance the cursesGui2.py plugin. All others can safely ignore this discussion.

The post: `Debugging npyscreen apps using two consoles &lt;https://groups.google.com/forum/#!topic/npyscreen/nk2pjj71bok&gt;`_ discusses the strategy used to bootstrap this plugin. It's easier to develop now that so much is working, but developing this code will always be difficult.

The console gui code stands "between" the npyscreen code and Leo's core code. With only very minor exceptions, **Leo's core and the npyscreen code must remain completely unchanged**.  Thus, the console gui wraps just about everything. This makes the plugin's code inherently complex, but this complexity can not be helped.

**Important**: It would pointless to describe the code in detail. Devs must come up to speed on their own by studying traces. Don't even *think* of trying to remember details. Instead, use cff to study the code.

</t>
<t tx="ekr.20171201034131.1">You *can not* use g.pdb to debug cursesGui2.py, for two reasons:

- g.pdb's output would overwrite the screen.
  Writing to the second console would not help because...

- There would be no way to get input to pdb.

As a result, **devs must uses traces** to figure out what is happening. The
`Broadcasting and listing &lt;console-gui.html#broadcasting-and-listening&gt;`_
section tells how to send traces to a *second* console. Use only g.pr and g.trace to create traces. **Do not use print statements in cursesGui2.py**.

</t>
<t tx="ekr.20171201034133.1">The following methods contain crucial traces:

- **IH.handle_input** (external/npyscreen/wgwidget.py) shows the raw input to npyscreen.
- **k.masterKeyHandler** (leoKeys.py) shows the keys passed to Leo's core.
- **k.masterCommand** (leoKeys.py) shows the Leo command (if any) bound to the raw key.

Other noteworthy methods and functions, all in cursesGui2.py:

- **CGui.createCursesTop** creates the main window by calling a helper for each part of the main window. The helpers handle the *extremely complex* details of setting and/or injecting ivars into various classes. Getting these ivars right is the heart of the plugin.

- **LeoMiniBuffer.h_return** contains a crucial hack that allows the minibuffer to be used both to enter commands and to enter find strings.

- The top-level **es, pr and trace functions** replace g.es, g.pr and g.trace functions so that they send their results to the second console.

- **CGui.monkeyPatch** contains some hacks needed to make the 'start-find' command work.

To enable tracing for these methods, and many others, set the trace variable at the start of the method.  Feel free to add your own traces in consoleGui2.py.
</t>
<t tx="ekr.20171201041242.1">**The curses module supports only simple control characters**. Ctrl-S will work, Alt-S, Ctrl-Shift-S etc. will not. These limitations can not be fixed.
</t>
<t tx="ekr.20171201041304.1">The npyscreen package defines widgets with limited capabilities:

- **npyscreen does not support selection ranges in text**! 

- Shift arrows are not supported, because there are no selection ranges.
  
- Cut/paste is theoretically supported, but in the absence of selections
  only paste might work. And paste may work only in limited contexts...

- Editing the log or body pane is a bit strange. You switch between tabs
  with tab or shift-tab. Type 'e' to edit edit mode, as shown on the
  on-screen prompts.

  Edit mode defines a *range* of lines that are being edited. Hitting
  return extends the range. Initially, the range consists of a single line,
  with the cursor at the end of the line. Moving outside the range with
  up/down arrow keys ends editing. Doing a more Leonine job would require a
  complete rewrite of the base classes.

- Deleting a line is not possible in edit mode. Use 'd' outside of edit
  mode to delete a line in the log or body panes.

- The body text is not syntax colored.
</t>
<t tx="ekr.20171201042151.1">**F4 runs all unit tests**. IH.handle_input binds F4 as a special case. All unit tests presently pass when run from the console gui. Devs *must* run all tests in the console gui before committing any changes to this plugin.
</t>
<t tx="ekr.20171204104344.1">The following bugs have resisted serious efforts to fix them. I will work on them further only if they cause *serious* difficulties to those who use the console gui.

- Shifting focus to the minibuffer after Ctrl-F works initially, but thereafter Tab and Shift-Tab don't work as expected until all widgets have been visited.  A workaround is to navigate to the minibuffer *before* using Ctrl-F, but this is not a perfect fix either.

- After startup, the output from g.es correctly goes to the log widget, but it is scrolled out of view!</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)
    
    # The system commands should be run from the folder containing the tex/cls/clo/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: http://leoeditor.com/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.20180124100723.1">- Leo scripting for scientists.
</t>
<t tx="ekr.20180124100723.2">Feature table

- Want Python and its libs.

- You develop software, including scientific software and scripts:
    Org-mode's script delims make it impossible to develop large software.
    
- You want to treat an outline as a programmable database.
    - Leo *is* a db. Outlines can represent db queries.

- You have hundreds of files to manage.
    - Leo has a fast caching scheme.
    
- You want clone-find commands

</t>
<t tx="ekr.20180124100723.3">
"A research project typically relies upon components such as:

    The data being studied;
    Details of calculations and code used in data analysis;
    Methodological conventions and assumptions;
    Decisions among alternate analytic paths.

However, the documents produced by a research project typically stand apart from the things they describe and rely upon, which makes it difficult for other researchers to reproduce the results and to understand fully the conclusions of the research project. This situation is problematic because reproducibility of results and accurate communication are both central to notions of good science.

A software solution to this problem was proposed by \citet{compendium}, who “introduce the concept of a compendium as both a container for the different elements that make up the document and its computations (i.e., text, code, data, …), and as a means for distributing, managing and updating the collection.”"
</t>
<t tx="ekr.20180124100723.4">They summarize the uses and implications of a compendium as follows:

    It encapsulates the actual work of the author, not just an abridged version suitable for publication;
    It can display different levels of detail in derived documents;
    The computations included in it can be re-run by an interested reader, potentially with different inputs;
    It contains explicit computational details that make it easier for an interested reader to adapt and extend the methods;
    It enables programmatic construction of plots and tables;
    Its components can be treated as data or inputs to software and manipulated programmatically in ways perhaps not envisioned by the author.

Reproducible research thus approaches mixed natural and computational language documents from a different direction than literate programming. Rather than adding prose to computational projects, reproducible research seeks to augment publications of scientific research with the computer code used to carry out the research. Whereas literate programming extracts embedded code into an external file used as input to a compiler or an interpreter, code embedded in a reproducible research document is intended to be executed as part of the document generation process. In this way the data, analysis, and figures supporting a publication can be generated from the publication itself.
</t>
<t tx="ekr.20180124100723.5">Show how scripts can invoke other scripts.

Show how to compose results:
    - With pickle?
</t>
<t tx="ekr.20180124100723.6">@language rest
@wrap





</t>
<t tx="ekr.20180124100723.7">Leo easily supports `Literate programming`_ (LP) and  `Reproducible Research`_ (RR) with unique, powerful underlying technology, not a mishmash of features.

**LP**: Leo redefines LP, showing that many kinds of comments are unnecessary in an outline environment. In LP terms, Leo supports *automatic* `tangling`_ and `weaving`_, but those terms are not used in Leo because they happen automatically.  More importantly, Leo supports `untangling`_, something entirely missing in org mode. Leo can update outlines corresponding to external files when those files change outside of Leo, preserving and updating outline structure as it does so. Untangling requires the `Mulder-Ream update algorithm`_, something entirely missing in org mode.
</t>
<t tx="ekr.20180124100723.8">@language rest
@wrap

Leo is fundamentally more powerful than org mode scripting:

1. Unlike org mode, Leo's outline nodes are true Python objects, *easily* accessible via Leo's Python `API`_. Furthermore, Leo scripting is based on Python and Python's standard library, not elisp and Emacs-specific code. Leo scripts can be run outside of Leo.

2. Leo can `compose`_ both external files and scripts using the same `markup`_. Unlike org mode, Leo's markup applies *everywhere* and is fully integrated with Leo's outline structure. As a result, it is complete natural to compose external files or scripts (experiments) from a suboutline. For example: this defines an external file::

    @first # -*- coding: utf-8 -*-
    '''whatever.py'''
    &lt;&lt; imports &gt;&gt;
    @others
    # That's all, folks
    @language python
    @tabwidth
    
And this this defines the top-level part of a script::

@language python

    @langauge python
    '''My script'''
    &lt;&lt; imports &gt;&gt;
    class Controller:
        # Child nodes define the methods of this class.
        @others
    Controller(c).run # Yes, c *is* defined.

@language rest
    
There is no need to put this inside wonky org-mode markup. The @language python directive tells Leo how to execute the script. More importantly, the `@others`_ directive includes *properly indented* code from descendant nodes. At the moment, I can't tell from the org mode docs whether anything like Leo's ``@others`` directive exists.
</t>
<t tx="ekr.20180124100723.9">Leo's underlying database is a `directed acyclic graph`_, (DAG) not a `tree`_ or, as in org-mode plain text with a collection of hacks that make that text look like a tree. The technology behind Leo's `clones`_ is based on the underlying DAG. It has been optimized over several decades. Org mode will likely never have clones.

Leo has a full-featured `Document Object Model`_ (DOM) consisting, among other things, of a collection of Python generators that traverse trees, subtrees or ancestor, visiting clones multiple times. Leo distinguishes between `positions`_ in a traversal and `vnodes`_, containing the actual data in each node.
</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 "http://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.20180124123920.1">The find-all-unique-regex pattern command creates a node that lists all matches of the given regex pattern.  Not the matching lines, just the matching text itself, discarding duplicates. In other words, only m.group(0) is shown, where m is the re match object.

For example, suppose there are multiple nodes containing each of the following::

    whatever # tag:important-script
    whatever # tag:important-setting

The find-all-unique-regex command with the pattern `tag:.*` will produce a
node whose headline is::

    Found Unique Regex:tag:.*

and whose body is::

    tag:important-script
    tag:important-setting

The command supports **tag patterns** of the form::

    #tag:&lt;kind&gt;
</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, http://leoeditor.com, is now available on [SourceForge](http://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](http://leoeditor.com/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: http://leoeditor.com
- [Documentation](http://leoeditor.com/leo_toc.html)
- [Tutorials](http://leoeditor.com/tutorial.html)
- [Video tutorials](http://leoeditor.com/screencasts.html)
- [Forum](http://groups.google.com/group/leo-editor)
- [Download](http://sourceforge.net/projects/leo/files/)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](http://leoeditor.com/testimonials.html)
- [A web page that displays .leo files](http://leoeditor.com/load-leo.html)
- [More links](http://leoeditor.com/leoLinks.html)
</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:
http://leoeditor.com/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
    find-all-unique-regex
    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.11">.. _`@test nodes`: tutorial-basics.html#test-nodes

`@test nodes`_ create unit tests. They automatically convert the body to a
subclass of unittest.TestCase. Leo's run-* commands execute unit tests.
</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 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.
- valuespace.py creates an outline-oriented spreadsheet.
- 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-leo command opens leoSettings.leo.
- The my-leo-settings-leo 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 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 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 a 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::
    
    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 script while developing it. For
example: put `@key=Alt-4` in headline. If your script grows to several
subnodes, you won't have to select top node every time you wish to run
script. It would be enough to just press your universal shortcut.</t>
<t tx="ekr.20180126061429.20">The g.trace function prints all its arguments to the console. It's great
for seeing 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. Searching
leoSettings.leo is thus a good way to find settings.</t>
<t tx="ekr.20180126061429.26">Use Alt-N to cycle through the clones of the present cloned node.
This 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 of 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 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 Log window to display results, it is
sometimes useful to clear Log window by inserting the following two lines
at the beginning of your script::

    c.frame.log.selectTab('Log')
    c.frame.log.clearLog()</t>
<t tx="ekr.20180126061429.4">Within scripts, use section references only when code must be placed
exactly. Here is a common pattern for @file nodes for python files::

    @first # -*- coding: utf-8 -*-
    &lt;&lt;imports&gt;&gt;
    @others</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 any errors are found::

    @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">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.

To install Leo do this from a console::

    pip install leo

The `Miniconda`_ environment includes just Python and the `conda` package management tool. Pick and choose from the full Anaconda ecosystem.

To install Leo do this from a console::

    conda install pyqt5
    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/installing/               
.. _`Install Python`:   http://python.org.
.. _`pip`:              https://pypi.python.org/pypi/pip

Python's `pip`_ tool will download *and* install Leo and all of Leo's dependencies automatically.

1. `Install Python`_ first, if necessary. If you are new to Python, install Python 3, not Python 2.

2. Check whether pip has been installed using the terminal window command below. If there's an error `Install pip`_:

    pip --version

3. Install Leo and all required packages:

**Python 3**

    pip install leo

**Python 2 with Anaconda**::

    conda install pyqt
    pip install leo

**Python 2 without Anaconda**

* Install `PyQt`_
* Install Leo::

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

Developers will typically execute the read-ref-file command after any git pull that changes any reference .leo file.  Similarly, devs will typically execute the update-ref-file command before doing a git commit that changes a reference .leo file.
</t>
<t tx="ekr.20180130105010.1">Leo's repository contains **reference .leo files**. These reference files should contain nothing but @file nodes. Reference files should change only when new external files get added to the project.

Leo's `git repository`_ and Leo distributions contain the following reference files: LeoPyRef.leo, LeoPluginsRef.leo and leoGuiPluginsRef.leo. Developers should use local copies of reference files for their own work. For example, instead of using LeoPyRef.leo directly, I use a copy called LeoPy.leo.</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='leoPlugins') # In leoPlugins.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-leo
    leo-unittest-leo
</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">@language rest

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::

@language python

    bpm = g.app.backgroundProcessManager
    bpm.start_process(c, command='ls', kind='ls', shell=True)

@language rest

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::

@language python

    import subprocess
    subprocess.Popen('ls', shell=True)

@language rest

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`` - start Leo in normal (qt) mode, and echo log messages to the starting shell

The launchers are installed in ``PYTHONHOME/Scripts``.
</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::

    os.chdir(base_dir)
    subprocess.Popen('npm run dev', shell=True)

The following hangs Leo until the command completes::

    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 commands that start with '&amp;'. Here it is::

    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::

    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:

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::

    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, http://leoeditor.com, is now available on
[GitHub](https://github.com/leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](http://leoeditor.com/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: http://leoeditor.com
- [Documentation](http://leoeditor.com/leo_toc.html)
- [Tutorials](http://leoeditor.com/tutorial.html)
- [Video tutorials](http://leoeditor.com/screencasts.html)
- [Forum](http://groups.google.com/group/leo-editor)
- [Download](http://sourceforge.net/projects/leo/files/)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](http://leoeditor.com/testimonials.html)
- [A web page that displays .leo files](http://leoeditor.com/load-leo.html)
- [More links](http://leoeditor.com/leoLinks.html)
</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.20180404015721.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, http://leoeditor.com, is now available on
[GitHub](https://github.com/leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](http://leoeditor.com/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: http://leoeditor.com
- [Documentation](http://leoeditor.com/leo_toc.html)
- [Tutorials](http://leoeditor.com/tutorial.html)
- [Video tutorials](http://leoeditor.com/screencasts.html)
- [Forum](http://groups.google.com/group/leo-editor)
- [Download](http://sourceforge.net/projects/leo/files/)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](http://leoeditor.com/testimonials.html)
- [A web page that displays .leo files](http://leoeditor.com/load-leo.html)
- [More links](http://leoeditor.com/leoLinks.html)
</t>
<t tx="ekr.20180411071648.1"></t>
<t tx="ekr.20180411071654.1">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 5.8.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:
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**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.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::

    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.2">.. 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`::


    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::

    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.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 a version of python's pdb debugger, https://docs.python.org/2/library/pdb.html, adapted to Leo's Qt gui.  I use g.pdb only rarely, when g.trace doesn't tell me enough.

**Using `@`button/command nodes as a testing framework**

This is the so-called stupendous Aha:
http://leoeditor.com/FAQ.html#what-is-the-stupendous-aha-and-why-does-it-matter
This can save you a lot of time.</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:

- 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.</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::

    c.recursiveImport(
        dir_ = &lt;&lt; path to root directory &gt;&gt;,
            # You must expand ~ yourself
        add_path=True,
        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, http://leoeditor.com, is now available on
[GitHub](https://github.com/leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](http://leoeditor.com/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: http://leoeditor.com
- [Documentation](http://leoeditor.com/leo_toc.html)
- [Tutorials](http://leoeditor.com/tutorial.html)
- [Video tutorials](http://leoeditor.com/screencasts.html)
- [Forum](http://groups.google.com/group/leo-editor)
- [Download](http://sourceforge.net/projects/leo/files/)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](http://leoeditor.com/testimonials.html)
- [A web page that displays .leo files](http://leoeditor.com/load-leo.html)
- [More links](http://leoeditor.com/leoLinks.html)
</t>
<t tx="ekr.20180509122603.1">@language rest

Added c.diff_file, c.diff_two_branches and c.git_diff. Examples:

@language python

# 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.5">https://github.com/leo-editor/leo-editor/issues/754
- [ ] Update the summary + news tabs on SourceForge:
    For example: Leo is now available on [GitHub](https://github.com/leo-editor/leo-editor). Follow the installation guide at leoeditor.com
      
    **Note**: the link above is to the master branch, even though there is no explicit branch url.

- [ ] Create a permanent devel branch.
- [ ] Update links on Leo's home page to these branches.

.</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/2/library/pdb.html), adapted to Leo's Qt gui.  I use g.pdb only rarely, when g.trace doesn't tell me enough.

**Using `@`button/command nodes as a testing framework**

This is the so-called [stupendous Aha](http://leoeditor.com/FAQ.html#what-is-the-stupendous-aha-and-why-does-it-matter). This can save you a lot of time.</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.20180528114703.1">
Leo 5.8 b2, http://leoeditor.com, is now available on
[GitHub](https://github.com/leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](http://leoeditor.com/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: http://leoeditor.com
- [Documentation](http://leoeditor.com/leo_toc.html)
- [Tutorials](http://leoeditor.com/tutorial.html)
- [Video tutorials](http://leoeditor.com/screencasts.html)
- [Forum](http://groups.google.com/group/leo-editor)
- [Download](http://sourceforge.net/projects/leo/files/)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](http://leoeditor.com/testimonials.html)
- [A web page that displays .leo files](http://leoeditor.com/load-leo.html)
- [More links](http://leoeditor.com/leoLinks.html)
</t>
<t tx="ekr.20180528114740.1"></t>
<t tx="ekr.20180528114754.1">https://github.com/leo-editor/leo-editor/issues/871

In fact, this setting has existed for a long time.
</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.20180601095122.1">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.20180601095134.1">https://github.com/leo-editor/leo-editor/issues/917
</t>
<t tx="ekr.20180608054147.1"></t>
<t tx="ekr.20180608054151.1">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.20180608054356.1">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.20180608055318.1">@language rest

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:

@language python

    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
            
@language rest

To see the stats, restart Leo, then do print-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:

@language python

# 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.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.20180626054937.1">https://github.com/leo-editor/leo-editor/issues/913
</t>
<t tx="ekr.20180702154446.1">https://github.com/leo-editor/leo-editor/issues/922</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.20180704130141.1">https://github.com/leo-editor/leo-editor/issues/938

The fix was in abbrev.init_tree_abbrev_helper.
</t>
<t tx="ekr.20180708030832.1">It now works in folders besides the leo-editor folder.
</t>
<t tx="ekr.20180708035251.1">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.20180708081949.1">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.20180708120421.1">This is for debugging only.</t>
<t tx="ekr.20180806043625.1">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.20180806054424.1">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.20180806085322.1"></t>
<t tx="ekr.20180806095812.1">https://groups.google.com/forum/#!topic/leo-editor/Nun7rRRhato
</t>
<t tx="ekr.20180821062022.32">https://github.com/leo-editor/leo-editor/issues/956

async is a new keyword.
</t>
<t tx="ekr.20180821062022.33">https://github.com/leo-editor/leo-editor/issues/961

Better tracing if the cursor gui fails to load.</t>
<t tx="ekr.20180821062022.35">https://github.com/leo-editor/leo-editor/issues/953
</t>
<t tx="ekr.20180821062022.38">See c.backup_helper.</t>
<t tx="ekr.20180821062022.4">This is an important simplification of the code.</t>
<t tx="ekr.20180821062138.107"></t>
<t tx="ekr.20180821062138.130"># 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.20180821062138.131"># 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.20180821062138.132">#
   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.20180821062138.133"># 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.20180821062138.134">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.20180821062138.15">https://github.com/leo-editor/leo-editor/issues/924
</t>
<t tx="ekr.20180821062138.16"></t>
<t tx="ekr.20180821062138.17">
         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.20180821062138.18">         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.20180821062138.19">         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.20180821062138.2">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.20180821062138.20">         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.20180821062138.21"> 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.20180821062138.22">    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.20180821062138.23"># 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.20180821062138.24"># 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.20180821062138.296"></t>
<t tx="ekr.20180821062138.301">https://groups.google.com/forum/#!topic/leo-editor/09H5wX1QRxw

Added .latex and *.sty files, would automatically be recognized as LaTeX. </t>
<t tx="ekr.20180821062138.38">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.20180821062138.89">https://github.com/leo-editor/leo-editor/issues/943

The fix was to getVnodeFromClipboard.
</t>
<t tx="ekr.20180821062419.1"></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.20180821155534.1"></t>
<t tx="ekr.20180822072454.2">https://github.com/leo-editor/leo-editor/issues/841
</t>
<t tx="ekr.20180822072454.4">https://github.com/leo-editor/leo-editor/issues/893
</t>
<t tx="ekr.20180822124637.1">https://github.com/leo-editor/leo-editor/issues/936

The change was to load_session.</t>
<t tx="ekr.20180822140501.1">https://github.com/leo-editor/leo-editor/issues/940

added update_nodes method.
</t>
<t tx="ekr.20180824085929.1">https://github.com/leo-editor/leo-editor/issues/967</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::

    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::

    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::

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation

2. Place the following at the end of the script::

    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.20180828032757.1">https://github.com/leo-editor/leo-editor/issues/966
</t>
<t tx="ekr.20180828033232.1"></t>
<t tx="ekr.20180828033450.1">Leo now redraws the screen only once during startup.

Removed qtree.update_appearance and qtree.update_appearance_idle.
</t>
<t tx="ekr.20180828095555.1"></t>
<t tx="ekr.20180828095605.1"></t>
<t tx="ekr.20180828095610.1">https://github.com/leo-editor/leo-editor/issues/969
The fix: call c.treeWantsFocusNow in tt.selectTab.
</t>
<t tx="ekr.20180829083210.1">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.20180829160908.1">https://github.com/leo-editor/leo-editor/issues/914
</t>
<t tx="ekr.20180930062351.1">
Leo 5.8 final, http://leoeditor.com, is now available on
[GitHub](https://github.com/leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](http://leoeditor.com/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: http://leoeditor.com
- [Documentation](http://leoeditor.com/leo_toc.html)
- [Tutorials](http://leoeditor.com/tutorial.html)
- [Video tutorials](http://leoeditor.com/screencasts.html)
- [Forum](http://groups.google.com/group/leo-editor)
- [Download](http://sourceforge.net/projects/leo/files/)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](http://leoeditor.com/testimonials.html)
- [A web page that displays .leo files](http://leoeditor.com/load-leo.html)
- [More links](http://leoeditor.com/leoLinks.html)
</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">@language rest

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:

@language python

    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
            
@language rest

To see the stats, restart Leo, then do print-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:

@language python

# 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.20180930062430.1"></t>
<t tx="ekr.20180930062538.1">This is the presently active commander, that is, g.app.log.c.
</t>
<t tx="matt.20180826201749.1">**Problem**

When installing Leo from GitHub with
``pip install https://github.com/leo-editor/leo-editor/archive/devel.zip``
numerous files are left out.

**Solution**

Installing from Github into a new environment must be done in discrete
steps: download, unpack, and install in editable mode.

Example::

   wget https://github.com/leo-editor/leo-editor/archive/devel.zip
   7z x devel.zip -o C:\apps
   pip install --editable C:\apps\leo-editor-devel

On Windows there are powershell versions of wget if needed.

For easier upgrading substitute ``git clone`` for ``wget`` &amp; ``7z``
steps::

   git clone --single-branch -b devel --depth=100 https://github.com/leo-editor/leo-editor.git
   pip install --editable leo-editor

Time passes, upgrade desired::

   pushd c:\apps\leo-editor
   git pull

``single-branch``, ``b`` and ``depth`` are all optional, but will
dramatically speed up download time as it only grabs the latest
development branch and skips all but the last couple weeks or months of
history.</t>
<t tx="peckj.20130813123907.6841" str_ctime="1376412039.0" str_mtime="1376412039.0" str_atime="1376414164.0">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 `ipython`). This allows the API docs to be automatically updated::

    :mod:`ipython` Module
    ---------------------
    
    .. automodule:: leo.plugins.ipython
        :members:
        :undoc-members:
        :show-inheritance:
</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="tbrown.20140412113009.50227">.zip snapshots can be downloaded directly from `GitHub &lt;https://github.com/leo-editor&gt;`_. No account is required.  The downloaded file will have a name like::

  leo-editor-50c070b715b9fec50c31be5853055a0ebc72cad5.zip

where the ``50c0...cad5`` part is the ID or fingerprint of the version you've downloaded.  Except "Latest", which is just ``leo-editor-master.zip``.

Here are direct download links for the "devel" branch, which changes frequently and contains all recent bug fixes:

  - `Latest devel &lt;https://github.com/leo-editor/leo-editor/archive/devel.zip&gt;`_
  - `devel: 1 day ago &lt;https://github.com/leo-editor/leo-editor/archive/devel@{1%20day%20ago}.zip&gt;`_
  - `devel: 2 days ago &lt;https://github.com/leo-editor/leo-editor/archive/devel@{2%20days%20ago}.zip&gt;`_
  - `devel: 5 days ago &lt;https://github.com/leo-editor/leo-editor/archive/devel@{5%20days%20ago}.zip&gt;`_
  - `devel: 10 days ago &lt;https://github.com/leo-editor/leo-editor/archive/devel@{10%20days%20ago}.zip&gt;`_
  - `devel: 30 days ago &lt;https://github.com/leo-editor/leo-editor/archive/devel@{30%20days%20ago}.zip&gt;`_
  - `devel: 90 days ago &lt;https://github.com/leo-editor/leo-editor/archive/devel@{90%20days%20ago}.zip&gt;`_


Here are direct download links for the "master" branch, which rarely changes and contains the most stable code:

  - `Latest master &lt;https://github.com/leo-editor/leo-editor/archive/master.zip&gt;`_
  - `master: 1 day ago &lt;https://github.com/leo-editor/leo-editor/archive/master@{1%20day%20ago}.zip&gt;`_
  - `master: 2 days ago &lt;https://github.com/leo-editor/leo-editor/archive/master@{2%20days%20ago}.zip&gt;`_
  - `master: 5 days ago &lt;https://github.com/leo-editor/leo-editor/archive/master@{5%20days%20ago}.zip&gt;`_
  - `master: 10 days ago &lt;https://github.com/leo-editor/leo-editor/archive/master@{10%20days%20ago}.zip&gt;`_
  - `master: 30 days ago &lt;https://github.com/leo-editor/leo-editor/archive/master@{30%20days%20ago}.zip&gt;`_
  - `master: 90 days ago &lt;https://github.com/leo-editor/leo-editor/archive/master@{90%20days%20ago}.zip&gt;`_
</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>
<t tx="vivainio.20080302174639.1">Leo's ``--ipython`` command-line option enables two-way communication (**ILeo**, the **IPython bridge**) between Leo and IPython: you can run Leo scripts from IPython, and IPython scripts from Leo.

The level of integration is much deeper than conventional integration in IDEs. Most notably, you are able to store and manipulate *data* in Leo nodes, in addition to mere program code--essentially making ILeo a hierarchical spreadsheet, albeit with non-grid view of the data. The possibilities of this are endless, and the approach can be applied in wide range of problem domains with very little actual coding.
</t>
<t tx="vivainio.20080302174639.2">.. _`run Leo in a console window`: installing.html#running-leo-from-a-console-window

To run Leo's IPython bridge:

1. Install IPython 4.0 and above and Jupyter.

2. `run Leo in a console window`_ with the ``--ipython`` command-line option enabled. This option starts an instance of the IPython shell in the console. Leo and IPython run simultaneously and independently. Their separate event loops do not interfere with each other. The ipython-new command launches new terminals connected to the same IPython kernel.
</t>
</tnodes>
</leo_file>
