<?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.20160122104302.1"><vh>Startup</vh>
<v t="ekr.20160510132151.1"><vh>@button backup</vh></v>
<v t="ekr.20170811173231.1"><vh>@button backup-repo</vh></v>
<v t="ekr.20170203054655.1"><vh>@ignore unused buttons</vh>
<v t="ekr.20161122014821.1"><vh>@button make-importer</vh>
<v t="ekr.20161122020451.1"><vh>&lt;&lt; define run &amp; helpers &gt;&gt;</vh>
<v t="ekr.20161122020932.1"><vh>copy_tree</vh></v>
<v t="ekr.20161122021006.1"><vh>make_substitutions</vh></v>
<v t="ekr.20161122023427.1"><vh>run</vh></v>
<v t="ekr.20161122021342.1"><vh>substitue</vh></v>
</v>
<v t="ekr.20161122023554.1"><vh>@@file importers/{{name}}.py</vh>
<v t="ekr.20161122023554.2"><vh>class {{cap_name}}_Importer</vh>
<v t="ekr.20161122023554.3"><vh>{{name}}.Overrides</vh>
<v t="ekr.20161122023554.4"><vh>{{name}}.clean_headline</vh></v>
<v t="ekr.20161122023554.5"><vh>{{name}}.clean_nodes</vh></v>
</v>
</v>
<v t="ekr.20161122023554.6"><vh>class {{cap_name}}_ScanState</vh>
<v t="ekr.20161122023554.7"><vh>{{name}}_state.level</vh></v>
<v t="ekr.20161122023554.8"><vh>{{name}}_state.update</vh></v>
</v>
</v>
</v>
<v t="ekr.20161030154232.1"><vh>@button pep8 @key=Ctrl-5</vh>
<v t="ekr.20161031124905.1"><vh>class Pep8</vh>
<v t="ekr.20161031053537.1"><vh>change_all &amp; helpers</vh>
<v t="ekr.20161031074727.1"><vh>change_body</vh></v>
<v t="ekr.20161031075018.1"><vh>change_headline</vh></v>
</v>
<v t="ekr.20161031051319.1"><vh>get_name</vh></v>
<v t="ekr.20161031125119.1"><vh>run</vh></v>
<v t="ekr.20161031051342.1"><vh>to_pep8</vh></v>
</v>
<v t="ekr.20161031065339.1"><vh>clear</vh></v>
</v>
<v t="ekr.20160412101845.1"><vh>@button test-jup-export</vh></v>
<v t="ekr.20160412101537.1"><vh>@button test-jup-import</vh></v>
</v>
<v t="ekr.20160122104400.1"><vh>@settings</vh>
<v t="ekr.20170709095709.1"><vh>@@bool minibuffer_find_mode = True</vh></v>
<v t="ekr.20160122104357.1"><vh>@data history-list</vh></v>
</v>
<v t="ekr.20170420085814.1"><vh>Recursive import script</vh></v>
<v t="ekr.20181017164437.1"><vh>script: regularize settings</vh></v>
</v>
<v t="ekr.20090430075506.4"><vh>Notes</vh>
<v t="ekr.20090430075506.3"><vh>@file leoPluginNotes.txt</vh></v>
</v>
<v t="edream.110203113231.618"><vh>Plugins</vh>
<v t="EKR.20040517090508"><vh>  Enable plugins using @enabled-plugins nodes</vh></v>
<v t="ekr.20050303051035"><vh>  Templates</vh>
<v t="ekr.20041114102139"><vh>Notes for plugin writers</vh></v>
<v t="ekr.20050306071629"><vh>Template for plugins that override commander methods</vh>
<v t="ekr.20050306071629.1"><vh>&lt;&lt; docstring &gt;&gt;</vh></v>
<v t="ekr.20050306071629.3"><vh>&lt;&lt; imports &gt;&gt;</vh></v>
<v t="ekr.20050306071629.4"><vh>init</vh></v>
<v t="ekr.20050306071540"><vh>onStart2</vh></v>
</v>
<v t="ekr.20050303051035.2"><vh>Template for plugins with per-commander controller class</vh>
<v t="ekr.20050303051035.5"><vh>&lt;&lt; imports &gt;&gt;</vh></v>
<v t="ekr.20050303051101"><vh>init</vh></v>
<v t="ekr.20050303051150"><vh>onCreate</vh></v>
<v t="ekr.20050303051222"><vh>class pluginController</vh>
<v t="ekr.20050303051222.1"><vh>__init__</vh></v>
</v>
</v>
</v>
<v t="ekr.20100103093121.5365"><vh>Auto completion</vh>
<v t="ekr.20091118065749.5261"><vh>@file ctagscompleter.py</vh></v>
</v>
<v t="edream.110203113231.667"><vh>Commands &amp; directives</vh>
<v t="edream.110203113231.741"><vh>@file add_directives.py</vh></v>
<v t="ekr.20101110084839.5682"><vh>@file bzr_qcommands.py</vh></v>
<v t="EKR.20040517080049.1"><vh>@file empty_leo_file.py</vh></v>
<v t="edream.110203113231.669"><vh>@file import_cisco_config.py</vh></v>
<v t="ekr.20101110092851.5812"><vh>@file initinclass.py</vh></v>
<v t="ekr.20101110091234.5700"><vh>@file leo_interface.py</vh></v>
<v t="ekr.20040419105219"><vh>@file lineNumbers.py</vh></v>
<v t="ekr.20040916084945"><vh>@file macros.py</vh></v>
<v t="edream.110203113231.724"><vh>@file mod_autosave.py</vh></v>
<v t="ekr.20050301083306"><vh>@file mod_read_dir_outline.py</vh></v>
<v t="edream.110203113231.727"><vh>@file mod_timestamp.py</vh></v>
<v t="TL.20090225102340.32"><vh>@file nodeActions.py</vh></v>
<v t="edream.110203113231.720"><vh>@file outline_export.py</vh></v>
<v t="danr7.20060912105041.1"><vh>@file paste_as_headlines.py</vh></v>
<v t="ekr.20041021120118"><vh>@file pretty_print.py</vh></v>
<v t="tbrown.20070117104409"><vh>@file quickMove.py</vh></v>
<v t="ekr.20081214160729.1"><vh>@file setHomeDirectory.py</vh></v>
<v t="danr7.20061010105952.1"><vh>@file word_count.py</vh></v>
</v>
<v t="edream.110203113231.729"><vh>Debugging</vh>
<v t="ekr.20101110091234.5689"><vh>@file debugger_pudb.py</vh></v>
<v t="edream.110203113231.730"><vh>@file dump_globals.py</vh></v>
<v t="edream.110203113231.732"><vh>@file enable_gc.py</vh></v>
<v t="edream.110203113231.734"><vh>@file quit_leo.py</vh></v>
<v t="edream.110203113231.735"><vh>@file trace_gc_plugin.py</vh></v>
<v t="edream.110203113231.736"><vh>@file trace_keys.py</vh></v>
<v t="edream.110203113231.738"><vh>@file trace_tags.py</vh></v>
</v>
<v t="ekr.20041030092101"><vh>Dyna plugins by e</vh></v>
<v t="ekr.20040722141148"><vh>Examples</vh>
<v t="edream.110203113231.916"><vh>@file examples/override_classes.py</vh></v>
<v t="edream.110203113231.919"><vh>@file examples/override_commands.py</vh></v>
<v t="edream.110203113231.921"><vh>@file examples/redefine_put.py</vh></v>
<v t="ekr.20060621123339"><vh>@file examples/print_cp.py</vh></v>
<v t="ekr.20040828105233"><vh>@file examples/chinese_menu.py</vh></v>
<v t="EKR.20040517080202.3"><vh>@file examples/french_fm.py</vh></v>
<v t="ekr.20180119164431.1"><vh>@file patch_python_colorizer.py</vh></v>
</v>
<v t="ekr.20101110150056.9457"><vh>Experimental</vh>
<v t="ekr.20090704103932.5160"><vh>@file leo_pdf.py</vh></v>
<v t="danr7.20060902083957"><vh>@file leo_to_rtf.py</vh></v>
<v t="ekr.20040205071616"><vh>@file mnplugins.py</vh></v>
<v t="ekr.20101110094759.5843"><vh>@file mod_speedups.py</vh></v>
<v t="ekr.20190410171646.1"><vh>@file pyzo_support.py</vh></v>
<v t="ekr.20040910070811.1"><vh>@file run_nodes.py</vh></v>
<v t="ekr.20100103093121.5339"><vh>@file stickynotes_plus.py</vh></v>
<v t="ekr.20140225222704.16748"><vh>@file viewrendered2.py</vh></v>
<v t="ekr.20040331071919"><vh>Leo to AsciiDoc</vh>
<v t="ekr.20101110093449.5822"><vh>@file mod_leo2ascd.py</vh></v>
<v t="ekr.20101110150056.9445"><vh>@file mod_leo2ascd.txt</vh></v>
</v>
</v>
<v t="EKR.20040517075715"><vh>External programs</vh>
<v t="ekr.20110125103904.12504"><vh>@file gitarchive.py</vh></v>
<v t="EKR.20040517080049.4"><vh>@file open_shell.py</vh></v>
<v t="ville.20090503124249.1"><vh>@file tomboy_import.py</vh></v>
<v t="EKR.20040517075715.10"><vh>@file vim.py</vh></v>
<v t="EKR.20040517075715.12"><vh>@file xemacs.py</vh></v>
<v t="EKR.20040517075715.13"><vh>Word export</vh>
<v t="EKR.20040517075715.14"><vh>@file word_export.py</vh></v>
<v t="EKR.20040517075715.20"><vh>@file-nosent word_export.ini</vh></v>
</v>
</v>
<v t="edream.110203113231.872"><vh>Files and nodes</vh>
<v t="tbrown.20080613095157.2"><vh>@file active_path.py</vh></v>
<v t="edream.110203113231.873"><vh>@file at_folder.py</vh></v>
<v t="ekr.20040915085351"><vh>@file at_produce.py</vh></v>
<v t="ktenney.20041211072654.1"><vh>@file at_view.py</vh></v>
<v t="ekr.20170619151859.2"><vh>@file auto_colorize2_0.py</vh></v>
<v t="tbrown.20081223111325.3"><vh>@file backlink.py</vh></v>
<v t="tbrown.20070322113635"><vh>@file bookmarks.py</vh></v>
<v t="ekr.20060807103814.1"><vh>@file datenodes.py</vh></v>
<v t="ajones.20070122153625"><vh>@file expfolder.py</vh></v>
<v t="ekr.20040915105758.13"><vh>@file FileActions.py</vh></v>
<v t="ekr.20110110105526.5463"><vh>@file ftp.py</vh></v>
<v t="tbrown.20091214233510.5347"><vh>@file geotag.py</vh></v>
<v t="tbrown.20100228141752.5691"><vh>@file leocursor.py</vh></v>
<v t="ville.20120503224623.3574"><vh>@file leomylyn.py</vh></v>
<v t="ekr.20101110092851.5742"><vh>@file leoOPML.py</vh></v>
<v t="dan.20090217132953.1"><vh>@file mime.py</vh></v>
<v t="mork.20041018204908.1"><vh>@file multifile.py</vh></v>
<v t="ekr.20040331151007"><vh>@file niceNosent.py</vh></v>
<v t="edream.110203113231.876"><vh>@file read_only_nodes.py</vh></v>
<v t="ekr.20040828103325"><vh>@file startfile.py</vh></v>
<v t="ekr.20130808211520.15893"><vh>@file timestamp.py</vh></v>
<v t="tbrown.20110428144124.29061"><vh>@file xml_edit.py</vh></v>
<v t="mork.20041010095009"><vh>@file xsltWithNodes.py</vh></v>
</v>
<v t="ekr.20181030041436.1"><vh>Gui</vh>
<v t="ekr.20150107090324.1"><vh>@file cursesGui.py</vh></v>
<v t="ekr.20170419092835.1"><vh>@file cursesGui2.py</vh></v>
<v t="ekr.20181103094900.1"><vh>@file leoflexx.py</vh></v>
<v t="ekr.201811100000000.1"><vh>@file leoflexx_js.py</vh></v>
</v>
<v t="ekr.20140723122936.17925"><vh>Importer plugins</vh>
<v t="ekr.20140723122936.18139"><vh>@file importers/__init__.py</vh></v>
<v t="ekr.20140723122936.17926"><vh>@file importers/c.py</vh></v>
<v t="ekr.20160505094722.1"><vh>@file importers/coffeescript.py</vh></v>
<v t="ekr.20140723122936.18140"><vh>@file importers/csharp.py</vh></v>
<v t="tbrown.20140801105909.47549"><vh>@file importers/ctext.py</vh></v>
<v t="ekr.20141116100154.1"><vh>@file importers/dart.py</vh></v>
<v t="ekr.20140723122936.18141"><vh>@file importers/elisp.py</vh></v>
<v t="ekr.20140723122936.18138"><vh>@file importers/html.py</vh></v>
<v t="ekr.20140723122936.18142"><vh>@file importers/ini.py</vh></v>
<v t="ekr.20160412101008.1"><vh>@file importers/ipynb.py</vh></v>
<v t="ekr.20140723122936.18143"><vh>@file importers/java.py</vh></v>
<v t="ekr.20140723122936.18144"><vh>@file importers/javascript.py</vh></v>
<v t="ekr.20160504080826.1"><vh>@file importers/leo_json.py</vh></v>
<v t="ekr.20140723122936.18151"><vh>@file importers/leo_rst.py</vh></v>
<v t="ekr.20161108125620.1"><vh>@file importers/linescanner.py</vh></v>
<v t="ekr.20170530024520.2"><vh>@file importers/lua.py</vh></v>
<v t="ekr.20140725190808.18066"><vh>@file importers/markdown.py</vh></v>
<v t="ekr.20140723122936.18146"><vh>@file importers/org.py</vh></v>
<v t="ekr.20140723122936.18150"><vh>@file importers/otl.py</vh></v>
<v t="ekr.20140723122936.18147"><vh>@file importers/pascal.py</vh></v>
<v t="ekr.20161027100313.1"><vh>@file importers/perl.py</vh></v>
<v t="ekr.20140723122936.18148"><vh>@file importers/php.py</vh></v>
<v t="ekr.20140723122936.18149"><vh>@file importers/python.py</vh></v>
<v t="ekr.20170615153639.2"><vh>@file importers/tcl.py</vh></v>
<v t="ekr.20180201203240.2"><vh>@file importers/treepad.py</vh></v>
<v t="ekr.20140723122936.18152"><vh>@file importers/typescript.py</vh></v>
<v t="ekr.20140723122936.18137"><vh>@file importers/xml.py</vh></v>
</v>
<v t="ekr.20180504192522.1"><vh>leo_babel</vh>
<v t="ekr.20180504191650.34"><vh>@clean leo_babel/__init__.py</vh></v>
<v t="ekr.20180504191650.36"><vh>examples</vh>
<v t="bob.20170716135108.2"><vh>@file leo_babel/examples/slowOut.py</vh></v>
<v t="bob.20170716135108.3"><vh>@file leo_babel/examples/slowOutNoFlush.py</vh></v>
</v>
<v t="ekr.20180504191650.42"><vh>tests</vh>
<v t="ekr.20180504191650.68"><vh>@clean leo_babel/tests/__init__.py</vh></v>
<v t="bob.20180206123613.1"><vh>@file leo_babel/tests/idle_time.py</vh></v>
<v t="bob.20180205135005.1"><vh>@file leo_babel/tests/lib_test.py</vh></v>
<v t="bob.20180125160225.1"><vh>@file leo_babel/tests/tests.py</vh></v>
</v>
</v>
<v t="ekr.20130927050813.13031"><vh>Obsolete</vh>
<v t="ajones.20070122160142"><vh>@file textnode.py</vh></v>
<v t="ekr.20050817132814"><vh>rst3</vh>
<v t="ekr.20050805162550"><vh>@@file rst3.py</vh>
<v t="ekr.20050805162550.1"><vh>&lt;&lt; docstring &gt;&gt;</vh></v>
<v t="ekr.20050805162550.2"><vh>&lt;&lt; imports &gt;&gt;</vh></v>
<v t="ekr.20050806162146"><vh>&lt;&lt; to do &gt;&gt;</vh>
<v t="ekr.20050804081215"><vh>More options</vh></v>
</v>
<v t="ekr.20050805162550.4"><vh>Module level</vh>
<v t="ekr.20050805162550.5"><vh> init</vh></v>
<v t="ekr.20050805162550.6"><vh>onCreate</vh></v>
<v t="ekr.20050806101253"><vh>code_block</vh></v>
<v t="ekr.20090429055156.63"><vh>runUnitTests</vh></v>
</v>
<v t="ekr.20050805162550.39"><vh>html parser classes</vh>
<v t="ekr.20050805162550.40"><vh> &lt;&lt; class linkAnchorParserClass &gt;&gt; (subclass of HTMLParser.HTMLParser)</vh>
<v t="ekr.20050805162550.41"><vh>__init__</vh></v>
<v t="ekr.20050805162550.42"><vh>is_anchor</vh></v>
<v t="ekr.20050805162550.43"><vh>is_link</vh></v>
<v t="ekr.20050815164715"><vh>is_node_marker</vh></v>
</v>
<v t="ekr.20050805162550.44"><vh>class htmlParserClass (linkAnchorParserClass)</vh>
<v t="ekr.20050805162550.45"><vh>__init__</vh></v>
<v t="ekr.20050805162550.46"><vh>handle_starttag</vh>
<v t="ekr.20050815164715.1"><vh>&lt;&lt; trace the unknownAttribute &gt;&gt;</vh></v>
</v>
<v t="ekr.20050805162550.47"><vh>handle_endtag</vh></v>
<v t="ekr.20050805162550.49"><vh>feed</vh></v>
</v>
<v t="ekr.20050805162550.50"><vh>class anchor_htmlParserClass (linkAnchorParserClass)</vh>
<v t="ekr.20050805162550.51"><vh> __init__</vh></v>
<v t="ekr.20050805162550.52"><vh>handle_starttag</vh></v>
</v>
<v t="ekr.20050805162550.53"><vh>class link_htmlParserClass (linkAnchorParserClass)</vh>
<v t="ekr.20050805162550.54"><vh>__init__</vh></v>
<v t="ekr.20050805162550.55"><vh>handle_starttag</vh></v>
<v t="ekr.20050805162550.56"><vh>get_replacements</vh></v>
</v>
</v>
<v t="ekr.20050805162550.8"><vh>class rstClass</vh>
<v t="ekr.20050805162550.9"><vh> Birth &amp; init</vh>
<v t="ekr.20050805162550.10"><vh> ctor (rstClass)</vh>
<v t="ekr.20050805162550.11"><vh>&lt;&lt; init ivars &gt;&gt;</vh></v>
</v>
<v t="ekr.20050805162550.12"><vh>addMenu (rstClass, rst3.py)</vh></v>
<v t="ekr.20050813083007"><vh>initHeadlineCommands</vh></v>
<v t="ekr.20050813085236"><vh>initSingleNodeOptions</vh></v>
<v t="ekr.20050808072943"><vh>munge</vh></v>
</v>
<v t="ekr.20050812122236"><vh>options...</vh>
<v t="ekr.20050808064245"><vh>createDefaultOptionsDict</vh></v>
<v t="ekr.20050812120933"><vh>dumpSettings (debugging)</vh></v>
<v t="ekr.20050814134351"><vh>getOption</vh></v>
<v t="ekr.20071015110830"><vh>initCodeBlockString</vh></v>
<v t="ekr.20050807120331.1"><vh>preprocessTree &amp; helpers</vh>
<v t="ekr.20051204070141"><vh>preprocessNode</vh></v>
<v t="ekr.20050808072943.1"><vh>parseOptionLine</vh></v>
<v t="ekr.20050808070018.2"><vh>scanForOptionDocParts</vh></v>
<v t="ekr.20050811173750"><vh>scanHeadlineForOptions</vh></v>
<v t="ekr.20050807120331.2"><vh>scanNodeForOptions</vh></v>
<v t="ekr.20050808070018"><vh>scanOption</vh></v>
<v t="ekr.20050808070018.1"><vh>scanOptions</vh></v>
</v>
<v t="ekr.20050808142313.28"><vh>scanAllOptions &amp; helpers</vh>
<v t="ekr.20050805162550.13"><vh>initOptionsFromSettings</vh></v>
<v t="ekr.20050810103731"><vh>handleSingleNodeOptions</vh></v>
</v>
<v t="ekr.20050811135526"><vh>setOption</vh></v>
</v>
<v t="ekr.20050809074827"><vh>write methods</vh>
<v t="ekr.20050809082854"><vh> Top-level write code</vh>
<v t="ekr.20050809075309"><vh>initWrite</vh></v>
<v t="ekr.20050809080925"><vh>writeNormalTree</vh></v>
<v t="ekr.20051121102358"><vh>processTopTree</vh></v>
<v t="ekr.20050805162550.17"><vh>processTree</vh></v>
<v t="ekr.20050805162550.21"><vh>writeSpecialTree</vh></v>
<v t="ekr.20050809082854.1"><vh>writeToDocutils (sets argv) &amp; helper</vh>
<v t="ekr.20090428082801.64"><vh>handleMissingStyleSheetArgs</vh></v>
</v>
<v t="ekr.20060525102337"><vh>writeNodeToString (New in 4.4.1)</vh></v>
</v>
<v t="ekr.20050811154552"><vh>getDocPart</vh>
<v t="ekr.20060610104435"><vh>&lt;&lt; Append whatever follows @doc or @space to result &gt;&gt;</vh></v>
</v>
<v t="ekr.20050811102607"><vh>skip_literal_block</vh></v>
<v t="ekr.20050811101550.1"><vh>writeBody &amp; helpers</vh>
<v t="ekr.20050811150541"><vh>handleCodeMode &amp; helper</vh>
<v t="ekr.20050811152104"><vh>formatCodeModeLine</vh></v>
<v t="ekr.20050813155021"><vh>rstripList</vh></v>
<v t="ekr.20050813160208"><vh>finishCodePart</vh></v>
</v>
<v t="ekr.20060608094815"><vh>handleDocOnlyMode</vh></v>
<v t="ekr.20060608094815.1"><vh>isAnyDocPart</vh></v>
<v t="ekr.20050811153208"><vh>isSpecialDocPart</vh></v>
<v t="ekr.20050811163802"><vh>isAnySpecialDocPart</vh></v>
<v t="ekr.20050811105438"><vh>removeLeoDirectives</vh></v>
<v t="ekr.20050811105438.1"><vh>handleSpecialDocParts</vh></v>
<v t="ekr.20050805162550.30"><vh>replaceCodeBlockDirectives</vh></v>
</v>
<v t="ekr.20050805162550.26"><vh>writeHeadline &amp; helper</vh>
<v t="ekr.20060608102001"><vh>writeHeadlineHelper</vh></v>
</v>
<v t="ekr.20050810083057"><vh>writeNode</vh></v>
<v t="ekr.20071115061253"><vh>writePreformat</vh></v>
<v t="ekr.20050805162550.23"><vh>writeTree</vh></v>
</v>
<v t="ekr.20050810083314"><vh>Utils</vh>
<v t="ekr.20051202070028"><vh>computeOutputFileName</vh></v>
<v t="ekr.20050805162550.16"><vh>encode</vh></v>
<v t="ekr.20050805162550.20"><vh>report</vh></v>
<v t="ekr.20050810083856"><vh>rstComment</vh></v>
<v t="ekr.20050805162550.19"><vh>underline</vh></v>
<v t="ekr.20050809080031"><vh>write</vh></v>
</v>
<v t="ekr.20050805162550.33"><vh>Support for http plugin</vh>
<v t="ekr.20050815091008.1"><vh>http_addNodeMarker</vh></v>
<v t="ekr.20050805162550.34"><vh>http_endTree &amp; helpers</vh>
<v t="ekr.20050805162550.36"><vh>set_initial_http_attributes</vh></v>
<v t="ekr.20050805162550.38"><vh>find_anchors</vh></v>
<v t="ekr.20050805162550.37"><vh>relocate_references</vh></v>
<v t="ekr.20050805162550.35"><vh>http_attribute_iter</vh></v>
</v>
</v>
</v>
</v>
</v>
<v t="ekr.20181028052650.1"><vh>@file leowapp.py</vh></v>
</v>
<v t="ekr.20041001210557"><vh>Scripting</vh>
<v t="tbrown.20100226095909.12777"><vh>@file leoscreen.py</vh></v>
<v t="tbrown.20140806084727.30174"><vh>@file livecode.py</vh></v>
<v t="ekr.20060328125248"><vh>@file mod_scripting.py</vh></v>
<v t="edream.110203113231.925"><vh>@file script_io_to_body.py</vh></v>
</v>
<v t="ekr.20120309073937.9878"><vh>Searching</vh>
<v t="ekr.20120309073748.9872"><vh>@file bigdash.py</vh></v>
<v t="peckj.20140804114520.9427"><vh>@file nodetags.py</vh></v>
<v t="peckj.20131130132659.5964"><vh>@file nodewatch.py</vh></v>
</v>
<v t="ekr.20050111122605"><vh>Servers &amp; web stuff</vh>
<v t="ekr.20170925083314.1"><vh>@auto leo_cloud.py</vh></v>
<v t="ekr.20170925083853.1"><vh>@auto leo_cloud_server.py</vh></v>
<v t="ville.20110206142055.10640"><vh>@file leofeeds.py</vh></v>
<v t="ville.20110125222411.10536"><vh>@file leomail.py</vh></v>
<v t="ville.20091009202416.10040"><vh>@file leoremote.py</vh></v>
<v t="EKR.20040517080250.1"><vh>@file mod_http.py</vh></v>
<v t="ekr.20131004162848.11444"><vh>@file rss.py</vh></v>
<v t="peckj.20140811080604.9496"><vh>@file sftp.py</vh></v>
</v>
<v t="ekr.20101004082701.5674"><vh>Slideshows, screencasts &amp; screenshots</vh>
<v t="ekr.20170128213103.1"><vh>@file demo.py</vh></v>
<v t="ekr.20120913110135.10579"><vh>@file screencast.py</vh></v>
<v t="ekr.20101121031443.5330"><vh>@file screenshots.py</vh></v>
<v t="ekr.20060831165821"><vh>@file slideshow.py</vh></v>
</v>
<v t="ekr.20071113084440"><vh>Testing</vh>
<v t="ekr.20080214092357"><vh>@file test/ekr_test.py</vh></v>
<v t="ekr.20050130120433"><vh>@@file test/failed_import.py</vh></v>
<v t="ekr.20071113085315"><vh>@file test/failed_to_load_plugin.py</vh></v>
<v t="ekr.20051016160700"><vh>@file testRegisterCommand.py</vh></v>
</v>
<v t="ekr.20050306081349"><vh>Text formatting</vh>
<v t="timo.20050213160555"><vh>@file bibtex.py</vh></v>
<v t="ekr.20070119094733.1"><vh>@file dtest.py</vh></v>
<v t="ville.20110409151021.5699"><vh>@file jinjarender.py</vh></v>
<v t="danr7.20060902215215.1"><vh>@file leo_to_html.py</vh></v>
<v t="tbrown.20130930160706.23451"><vh>@file markup_inline.py</vh></v>
<v t="peckj.20140113150237.7083"><vh>@file nodediff.py</vh></v>
<v t="tbrown.20130813134319.11942"><vh>@file richtext.py</vh></v>
<v t="ekr.20170217164004.1"><vh>@file tables.py</vh></v>
</v>
<v t="ekr.20121126102050.10134"><vh>Threading</vh>
<v t="ekr.20121126095734.12418"><vh>@file threadutil.py</vh></v>
</v>
<v t="ekr.20040915073259"><vh>User interface</vh>
<v t="ekr.20101110150056.9453"><vh> Qt only plugins</vh>
<v t="tbrown.20091029123555.5319"><vh>@file attrib_edit.py</vh></v>
<v t="ville.20090310191936.10"><vh>@file colorize_headlines.py</vh></v>
<v t="ekr.20090701111504.5294"><vh>@file contextmenu.py</vh></v>
<v t="tbrown.20090206153748.1"><vh>@file graphcanvas.py</vh></v>
<v t="ville.20090518182905.5419"><vh>@file nav_qt.py</vh></v>
<v t="ville.20120604212857.4215"><vh>@file notebook.py</vh></v>
<v t="ekr.20090622063842.5264"><vh>@file projectwizard.py</vh></v>
<v t="ekr.20160928073518.1"><vh>@file pyplot_backend.py</vh></v>
<v t="ville.20090314215508.4"><vh>@file quicksearch.py</vh></v>
<v t="tbrown.20130420091241.44181"><vh>@file screen_capture.py</vh></v>
<v t="ville.20090815203828.5235"><vh>@file spydershell.py</vh></v>
<v t="ekr.20100103093121.5329"><vh>@file stickynotes.py</vh></v>
<v t="tbrown.20090119215428.2" descendentVnodeUnknownAttributes="7d71005808000000302e362e31332e3071017d71025808000000616e6e6f7461746571037d71042858080000007072696f7269747971054d0f27580a000000707269736574646174657106580a000000323031382d30382d313871077573732e"><vh>@file todo.py</vh></v>
<v t="ville.20110403115003.10348"><vh>@file valuespace.py</vh></v>
<v t="tbrown.20100318101414.5990"><vh>@file viewrendered.py</vh></v>
</v>
<v t="ekr.20061023142737"><vh> UNL plugin</vh>
<v t="ekr.20061023142737.1"><vh>Tests</vh>
<v t="rogererens.20041130095659"><vh>@url 'file: ./../../plugins/leoPlugins.leo#Plugins--&gt;UNL plugin--&gt;To do'</vh></v>
<v t="ekr.20061023141638"><vh>@url 'file:./../doc/leoDocs.leo#Users Guide--&gt;Basics--&gt;Customizing Leo'</vh></v>
</v>
</v>
<v t="ekr.20160519123329.1"><vh>@edit QNCalendarWidget.py</vh></v>
<v t="ekr.20060328125925"><vh>@file chapter_hoist.py</vh></v>
<v t="ville.20110115234843.8742"><vh>@file dragdropgoodies.py</vh></v>
<v t="tbrown.20090513125417.5244"><vh>@file interact.py</vh></v>
<v t="vitalije.20170727201534.1"><vh>@file line_numbering.py</vh></v>
<v t="ekr.20040915073259.1"><vh>@file maximizeNewWindows.py</vh></v>
<v t="ekr.20101110093301.5818"><vh>@file mod_framesize.py</vh></v>
<v t="EKR.20040517080555.2"><vh>@file plugins_menu.py</vh></v>
<v t="peckj.20150428142633.1"><vh>@file python_terminal.py</vh></v>
<v t="edream.110203113231.924"><vh>@file redirect_to_log.py</vh></v>
<v t="EKR.20040517080555.36"><vh>@file scripts_menu.py</vh></v>
<v t="ekr.20170313020320.1"><vh>@file settings_finder.py</vh></v>
<v t="ville.20110304230157.6513"><vh>@file systray.py</vh></v>
<v t="tbrown.20141101114322.1"><vh>@file wikiview.py</vh></v>
<v t="ekr.20181004143535.1"><vh>@file xdb_pane.py</vh></v>
<v t="ekr.20101110095202.5882"><vh>@file zenity_file_dialogs.py</vh></v>
</v>
<v t="ekr.20140726091031.18071"><vh>Writer plugins</vh>
<v t="ekr.20140726091031.18152"><vh>@file writers/__init__.py</vh></v>
<v t="ekr.20140726091031.18143"><vh>@file writers/basewriter.py</vh></v>
<v t="tbrown.20140804103545.29975"><vh>@file writers/ctext.py</vh></v>
<v t="ekr.20141116100154.2"><vh>@file writers/dart.py</vh></v>
<v t="ekr.20160412101901.1"><vh>@file writers/ipynb.py</vh></v>
<v t="ekr.20160504083330.1"><vh>@file writers/leo_json.py</vh></v>
<v t="ekr.20180202053206.1"><vh>@file writers/treepad.py</vh></v>
<v t="ekr.20140726091031.18080"><vh>@file writers/leo_rst.py</vh></v>
<v t="ekr.20140726091031.18073"><vh>@file writers/markdown.py</vh></v>
<v t="ekr.20140726091031.18079"><vh>@file writers/org.py</vh></v>
<v t="ekr.20140726091031.18078"><vh>@file writers/otl.py</vh></v>
</v>
</v>
</vnodes>
<tnodes>
<t tx="EKR.20040517075715"></t>
<t tx="EKR.20040517075715.13"></t>
<t tx="EKR.20040517075715.20">[Main]
use_styles = Yes
use_section_numbers = Yes
use_current_document = Yes
max_headings = 6
header_style = Heading
</t>
<t tx="EKR.20040517090508">@nocolor-node

Enable plugins by creating@enabled-plugins nodes in leoSettings files,
typically myLeoSettings.leo.See the node

Users Guide-- &gt; Chapter 8: Customizing Leo-- &gt;@rst
html\customizing.html-- &gt; Specifying settings-- &gt; Complex settings nodes

in LeoDocs.leo for full details.

**Important**: Leo no longer uses pluginsManager.txt to enable or disable plugins.
</t>
<t tx="edream.110203113231.618">@language python
@tabwidth -4
@pagewidth 80
</t>
<t tx="edream.110203113231.667"></t>
<t tx="edream.110203113231.729"></t>
<t tx="edream.110203113231.872">@nocolor-node

These plugins create new kinds of nodes, some of which affect the file system.</t>
<t tx="ekr.20040331071919"></t>
<t tx="ekr.20040722141148">@nocolor-node
@

You would typically not enable any of the following "plugins".

These plugins contain example code only.
</t>
<t tx="ekr.20040915073259">@nocolor-node

These plugins add buttons and other widgets to the icon area or
affect Leo's panes and windows in various ways.

</t>
<t tx="ekr.20041001210557"></t>
<t tx="ekr.20041030092101">@Notes by EKR: The dyna plugin is a remarkable body of work by 'e'. Have fun with it.

You may download the latest version at: http: // rclick.netfirms.com / dyna_menu.py.html
</t>
<t tx="ekr.20041114102139">@nocolor

Comments
--------

Most of the comments in the style guide are comments*about*the style guide.
You would replace these comments with your own, or eliminate them entirely in
your plugin.

Docstrings
----------

Several plugins show the docstring, so please take care to do a good job of
describing what the plugin does and how to use it.

Directives
----------

Please put the following at the end of the plugin's top-level node.

    @language python
    @tabwidth-4

Imports
-------

-Do* not*assume that modules like Qt are always available.

-Do* not*use from m import*

-Your code should test whether modules have been imported only if those modules
  may not be available on all platforms.

-To fail gracefully if the Qt gui is not in effect, put the following at
  the top level::

      g.assertUi('qt')

Exceptions
----------

It is usually best* not*to catch exceptions in plugins: doHook catches all
exceptions and disables further calls to plugins.

If a plugin catches exceptions during startup it should do either raise the
exception again or provide an init function at the top level that reports the
failure by returning False.

Use separate nodes
------------------

**Please**define each class, function or method in a separate node!To
make this work, just put@others in the root of your plugin as shown.Note
that@others may be nested, as shown in class myClass.
</t>
<t tx="ekr.20050111122605"></t>
<t tx="ekr.20050130120433">'''A plugin to test import problems.'''

import leo.core.leoGlobals as g

def onStart(tag,keywords):
    pass

# pylint: disable=unused-import
try:
    import xyzzy
except ImportError:
    g.cantImport('xyzzy',pluginName='failed_import')

def init():
    '''Return True if the plugin has loaded successfully.'''
    g.registerHandler("start2", onStart)
    g.plugin_signon(__name__)
    return True
</t>
<t tx="ekr.20050303051035">@nocolor-node

The following nodes show recommended style when writing plugins.</t>
<t tx="ekr.20050303051035.2">'''
A docstring describing your plugin and how to use it.
If it's long, you might put it in a separate section.
'''
&lt;&lt; imports &gt;&gt;
@others
@language python
@tabwidth-4
</t>
<t tx="ekr.20050303051035.5">import leo.core.leoGlobals as g

# Whatever other imports your plugins uses.
</t>
<t tx="ekr.20050303051101">def init():
    '''Return True if the plugin has loaded successfully.'''
    ok=g.app.gui.guiName() in('qt','qttabs')
    if ok:
        if 1: # Use this if you want to create the commander class before the frame is fully created.
            g.registerHandler('before-create-leo-frame',onCreate)
        else: # Use this if you want to create the commander class after the frame is fully created.
            g.registerHandler('after-create-leo-frame',onCreate)
    return ok</t>
<t tx="ekr.20050303051150">def onCreate(tag, keys):

    c=keys.get('c')
    if not c: return

    thePluginController=pluginController(c)
</t>
<t tx="ekr.20050303051222">class pluginController:

    @others</t>
<t tx="ekr.20050303051222.1">def __init__(self,c):

    self.c=c
    # Warning: hook handlers must use keywords.get('c'), NOT self.c.
</t>
<t tx="ekr.20050306071540">def onStart2(tag, keywords):

    """
    Showing how to define a global hook that affects all commanders.
    """

    log=c.frame.log.__class__

    # Replace frame.put with newPut (not shown).
    g.funcToMethod(newPut,log,"put")</t>
<t tx="ekr.20050306071629">'''
A docstring describing your plugin and how to use it.
If it's long, you might put it in a separate section.
'''
&lt;&lt; imports &gt;&gt;
@others
@language python
@tabwidth-4</t>
<t tx="ekr.20050306071629.1">'''This docstring should be a clear, concise description of
what the plugin does and how to use it.
'''
</t>
<t tx="ekr.20050306071629.3">import leo.core.leoGlobals as g

# Whatever other imports your plugins uses.
</t>
<t tx="ekr.20050306071629.4">def init():
    '''Return True if the plugin has loaded successfully.'''
    ok=True # This might depend on imports, etc.
    if ok:
        g.registerHandler('start2',onStart2)
    return ok</t>
<t tx="ekr.20050306081349"></t>
<t tx="ekr.20050804081215">@nocolor
@
http://sourceforge.net/forum/message.php?msg_id=3276408

Leo has great potential for smoothing some of the bumps
outside of learning the details of the markup.
Here is my wish list;

(done) - Section level handling.
  - one of the problems with using rst comes when a new
    section level is inserted into a document. Leo can
    take care of this effortlessly, providing a correct
   underline character for each section heading.

    Other than the section management, I want Leo to
    assume that I'm writing rst, and should be rendered
    as-is. If I want to include some pretty Python, I put
    it in a ..  python-code:: block (or some such)

    On top of this base could be built special case
    handling.

- Assist in viewing rendered output
  - easy access to the command to render a tree to  html.
  - I would like an option which automatically inserted
    a @url node which pointed to the rendered file, or
    some other trick to make switching between source
    and output painless.

- Assist in working with the CSS file
  - a CSS file is now required by docutils. A @setting
    could specify the file. I would like some kind of
    sugar which made it easy to edit the CSS file, maybe
    an option to create a @file node automatically,
    like the @url node above. Again, I want to be able
    to effortlessly edit the CSS and see the results.

- The third file of interest when writing rst is the config
   file which controls many behaviours of the renderer.
   Again, some intelligence which located it, made it
   convenient to edit it, maybe even linked to
   documentation for it, would be very nice.

(done) - I would like a setting which would save the file with the
  rst markup and make it easy to examine and edit.

- On the someday/maybe list would be a @publish
  feature, which configured a directory to ftp the rendered
  file to.
</t>
<t tx="ekr.20050805162550">&lt;&lt; docstring &gt;&gt;

# Original rst code by Josef Dalcolmo:
# contributed under the same licensed as Leo.py itself.
# rst3.py based on rst2.py v2.4.
# This has largely been superceded by leo.core.leoRst.

&lt;&lt; imports &gt;&gt;
&lt;&lt; to do &gt;&gt;

bwm_file = None
if 0:
    bwm_file = open("bwm_file", "w")
controllers = {} # For use by @button rst3 code.

@others
</t>
<t tx="ekr.20050805162550.1">''' Creates output files from Leo outlines containing rST (reStructuredText)
markup. This plugin has been superseded by Leo's core rst3 command.

This is a powerful plugin with many options.  The full documentation is at:
http://leoeditor.com//rstplugin3.html

The rst3 plugin adds the Write Restructured Text command to Leo's Edit menu. This
command searches the selected outline looking for **rst root nodes** whose
headline have the form @rst &lt;filename&gt;. The plugin then creates the named file
in various ways depending which rst3 options are in effect.

By default, the rst3 plugin creates rST headings automatically from outlines, so
the higher-level nodes in the outline correspond to higher-level sections in the
output. Creating rST headings automatically eliminates one of the most tedious
chores associated with rST markup.

To use this plugin effectively, Python's docutils module must be installed. The
rst3 plugin will use the SilverCity syntax coloring package if it installed.

This plugin sends .htm, .html or .tex files to the docutils module for further
processing. Docutils generates HTML files or LaTeX files depending on the file's
extension. HTML files generated by docutils refer to three .css (cascading style
sheet) files that should exist in the same directory as the generated HTML file.
You can control the formatting of the HTML file by altering these .css files.

rst3 options control most aspects of this plugin's operations. You can set
options in @settings trees, in headlines and in body text. There are too many
details to discuss here. For full details see:
http://leoeditor.com//rstplugin3.html

'''
</t>
<t tx="ekr.20050805162550.10">def __init__ (self,c):

    global SilverCity
    self.c = c
    &lt;&lt; init ivars &gt;&gt;

    self.createDefaultOptionsDict()
    self.initOptionsFromSettings() # Still needed.
    self.initHeadlineCommands() # Only needs to be done once.
    self.initSingleNodeOptions()
    self.addMenu()
</t>
<t tx="ekr.20050805162550.11">self.silverCityWarningGiven = False

# The options dictionary.
self.optionsDict = {}
self.option_prefix = '@rst-option'

# Formatting...
self.code_block_string = ''
self.node_counter = 0
self.toplevel = 0
self.topNode = None
self.use_alternate_code_block = SilverCity is None

# Http support...
self.nodeNumber = 0
# All nodes are numbered so that unique anchors can be generated.

self.http_map = {}
# Keys are named hyperlink targets.  Value are positions.
# The targets mark the beginning of the html code specific
# for this position.

self.anchor_map = {}
# Maps anchors (generated by this module) to positions

self.rst3_all = False
# Set to True by the button which processes all @rst trees.

# For writing.
self.defaultEncoding = 'utf-8'
self.leoDirectivesList = g.globalDirectiveList
self.encoding = self.defaultEncoding
self.ext = None # The file extension.
self.outputFileName = None # The name of the file being written.
self.outputFile = None # The open file being written.
self.path = '' # The path from any @path directive.
self.source = None # The written source as a string.
</t>
<t tx="ekr.20050805162550.12">def addMenu (self):

    c = self.c ; editMenu = c.frame.menu.getMenu('Edit')

    def rst3PluginCallback (event=None):
        self.processTopTree(c.p)

    c.k.registerCommand('write-restructured-text', rst3PluginCallback)
    table = (
        ("-",None,None),
        # ("Write Restructed Text","",rst3PluginCallback),
        '&amp;write-restructured-text',
    )
    c.frame.menu.createMenuEntries(editMenu,table,dynamicMenu=True)
</t>
<t tx="ekr.20050805162550.13">def initOptionsFromSettings (self):
    '''Init all options from settings.'''
    c = self.c
    d = self.defaultOptionsDict
    for key in sorted(d.keys()):
        for getter,kind in (
            (c.config.getBool,'@bool'),
            (c.config.getString,'@string'),
            (d.get,'default'),
        ):
            val = getter(key)
            if kind == 'default' or val is not None:
                self.setOption(key,val,'initOptionsFromSettings')
                break
    # Special case.
    if self.getOption('http_server_support') and not mod_http:
        g.error('No http_server_support: can not import mod_http plugin')
        self.setOption('http_server_support',False,tag='initOptionsFromSettings')
</t>
<t tx="ekr.20050805162550.16">def encode (self,s):

    return g.toEncodedString(s,encoding=self.encoding,reportErrors=True)
</t>
<t tx="ekr.20050805162550.17">def processTree(self,p,ext,toString,justOneFile):

    '''Process all @rst nodes in a tree.'''

    self.preprocessTree(p)
    found = False ; self.stringOutput = ''
    p = p.copy() ; after= p.nodeAfterTree()
    while p and p != after:
        h = p.h.strip()
        if g.match_word(h,0,"@rst"):
            self.outputFileName = h[4:].strip()
            if (
                (self.outputFileName and self.outputFileName[0] != '-') or
                (toString and not self.outputFileName)
            ):
                found = True
                self.toplevel = p.level() # Define toplevel separately for each rst file.
                if toString:
                    self.ext = ext
                else:
                    self.ext = g.os_path_splitext(self.outputFileName)[1].lower()
                if self.ext in ('.htm','.html','.tex','.pdf'):
                    ok = self.writeSpecialTree(p,toString=toString,justOneFile=justOneFile)
                else:
                    ok = self.writeNormalTree(p,toString=toString)
                self.scanAllOptions(p) # Restore the top-level verbose setting.
                if toString:
                    return p.copy(),self.stringOutput
                else:
                    if ok: self.report(self.outputFileName)
                p.moveToNodeAfterTree()
            else:
                p.moveToThreadNext()
        else: p.moveToThreadNext()
    if not found:
        g.warning('No @rst nodes in selected tree')
    return None,None
</t>
<t tx="ekr.20050805162550.19">def underline (self,s,p):
    '''Return the underlining string to be used at the given level for string s.'''
    u = self.getOption('underline_characters') #  '''#=+*^~"'`-:&gt;&lt;_'''
    level = max(0,p.level()-self.toplevel)
    level = min(level+1,len(u)-1) # Reserve the first character for explicit titles.
    ch = u [level]
    n = max(4,len(s))
    return ch * n + '\n'
</t>
<t tx="ekr.20050805162550.2">import leo.core.leoGlobals as g

import html.parser as HTMLParser
import os
import pprint
import io
StringIO = io.StringIO
import sys

# Make sure the present directory in in sys.path.
dir,junk = os.path.split(__file__)
if dir not in sys.path: sys.path.append(dir)

try:
    import leo.plugins.mod_http as mod_http
except ImportError:
    mod_http = None

try:
    import docutils
    import docutils.parsers.rst
    import docutils.core
    import docutils.io
except ImportError:
    # This message given in init.
    # g.pr('rst3 plugin: can not import docutils')
    docutils = None

try:
    import SilverCity
except ImportError:
    if '--silent' not in sys.argv and not g.unitTesting and not g.app.batchMode:
        g.pr('rst3 plugin: SilverCity not loaded')
    SilverCity = None
</t>
<t tx="ekr.20050805162550.20">def report (self,name):

    if self.getOption('verbose'):

        name = g.os_path_finalize(name)

        g.blue('wrote: %s' % (name))
</t>
<t tx="ekr.20050805162550.21">def writeSpecialTree (self,p,toString,justOneFile):

    c = self.c
    isHtml = self.ext in ('.html','.htm')
    if isHtml and not SilverCity:
        if not self.silverCityWarningGiven:
            self.silverCityWarningGiven = True
            g.es('SilverCity not present so no syntax highlighting')

    self.initWrite(p)
        # was ,encoding=g.choose(isHtml,'utf-8','iso-8859-1'))
    self.outputFile = StringIO()
    self.writeTree(p)
    self.source = self.outputFile.getvalue()
    self.outputFile = None

    if not toString:
        # Compute this here for use by intermediate file.
        self.outputFileName = self.computeOutputFileName(self.outputFileName)

        # Create the directory if it doesn't exist.
        theDir, junk = g.os_path_split(self.outputFileName)
        theDir = c.os_path_finalize(theDir)
        if not g.os_path_exists(theDir):
            ok = g.makeAllNonExistentDirectories(theDir,c=c,force=False)
            if not ok:
                g.error('did not create:',theDir)
                return False

        # if not os.access(theDir,os.F_OK):
            # os.mkdir(theDir)

        if self.getOption('write_intermediate_file'):
            name = self.outputFileName + '.txt'
            f = open(name,'w')
            f.write(self.source)
            f.close()
            self.report(name)

    try:
        output = self.writeToDocutils(self.source)
        ok = True
    except Exception:
        g.pr('Exception in docutils')
        g.es_exception()
        ok = False

    if ok:
        if isHtml:
            import re
            idxTitle = output.find('&lt;title&gt;&lt;/title&gt;')
            if idxTitle &gt; -1:
                m = re.search('&lt;h1&gt;([^&lt;]*)&lt;/h1&gt;', output)
                if not m:
                    m = re.search('&lt;h1&gt;&lt;[^&gt;]+&gt;([^&lt;]*)&lt;/a&gt;&lt;/h1&gt;', output)
                if m:
                    output = output.replace(
                        '&lt;title&gt;&lt;/title&gt;',
                        '&lt;title&gt;%s&lt;/title&gt;' % m.group(1)
                    )


        if toString:
            self.stringOutput = output
        else:
            # Write the file to the directory containing the .leo file.
            f = open(self.outputFileName,'w')
            f.write(output)
            f.close()
            self.http_endTree(self.outputFileName, p, justOneFile=justOneFile)

    return ok
</t>
<t tx="ekr.20050805162550.23">def writeTree(self,p):
    '''Write p's tree to self.outputFile.'''
    self.scanAllOptions(p)
    if self.getOption('generate_rst'):
        if self.getOption('generate_rst_header_comment'):
            self.write(self.rstComment(
                'rst3: filename: %s\n\n' % self.outputFileName))
    # We can't use an iterator because we may skip parts of the tree.
    p = p.copy() # Only one copy is needed for traversal.
    self.topNode = p.copy() # Indicate the top of this tree.
    after = p.nodeAfterTree()
    while p and p != after:
        self.writeNode(p)
</t>
<t tx="ekr.20050805162550.26">def writeHeadline (self,p):

    '''Generate an rST section if options permit it.
    Remove headline commands from the headline first,
    and never generate an rST section for @rst-option and @rst-options.'''

    docOnly             =  self.getOption('doc_only_mode')
    ignore              = self.getOption('ignore_this_headline')
    showHeadlines       = self.getOption('show_headlines')
    showThisHeadline    = self.getOption('show_this_headline')
    showOrganizers      = self.getOption('show_organizer_nodes')

    if (
        p == self.topNode or
        ignore or
        docOnly or # handleDocOnlyMode handles this.
        not showHeadlines and not showThisHeadline or
        # docOnly and not showOrganizers and not thisHeadline or
        not p.h.strip() and not showOrganizers or
        not p.b.strip() and not showOrganizers
    ):
        return

    self.writeHeadlineHelper(p)
</t>
<t tx="ekr.20050805162550.30">def replaceCodeBlockDirectives (self,lines):

    '''Replace code-block directive, but not in literal blocks.'''

    n = 0 ; result = []
    while n &lt; len(lines):
        s = lines [n] ; n += 1
        if s.strip().endswith('::'):
            n, lit = self.skip_literal_block(lines,n-1)
            result.extend(lit)
        else:
            i = g.skip_ws(s,0)
            if g.match(s,i,'..'):
                i = g.skip_ws(s,i+2)
                if g.match_word(s,i,'code-block'):
                    if 1: # Create a literal block to hold the code.
                        result.append('::\n')
                    else: # This 'annotated' literal block is confusing.
                        result.append('%s code::\n' % s[i+len('code-block'):])
                else:
                    result.append(s)
            else:
                result.append(s)

    return result
</t>
<t tx="ekr.20050805162550.33"></t>
<t tx="ekr.20050805162550.34"># Was http_support_main

def http_endTree (self,filename,p,justOneFile):

    '''Do end-of-tree processing to support the http plugin.'''

    if (
        self.getOption('http_server_support') and
        self.getOption('generate_rst')
    ):
        self.set_initial_http_attributes(filename)
        self.find_anchors(p)
        if justOneFile:
            self.relocate_references(p.self_and_subtree)

        g.blue('html updated for http plugin')

        if self.getOption('clear_http_attributes'):
            g.es_print("http attributes cleared")
</t>
<t tx="ekr.20050805162550.35">def http_attribute_iter (self, p):
    """
    Iterator for all the nodes which have html code.
    Look at the descendents of p.
    Used for relocation.
    """

    for p1 in p.self_and_subtree():
        attr = mod_http.get_http_attribute(p1)
        if attr:
            yield (p1.copy(),attr)
</t>
<t tx="ekr.20050805162550.36">def set_initial_http_attributes (self,filename):

    f = open(filename)
    parser = htmlParserClass(self)

    for line in f.readlines():
        parser.feed(line)

    f.close()
</t>
<t tx="ekr.20050805162550.37">@ Relocate references here if we are only running for one file.

Otherwise we must postpone the relocation until we have processed all files.
@c

def relocate_references (self, iterator_generator):

    for p in iterator_generator():
        attr = mod_http.get_http_attribute(p)
        if not attr:
            continue
        if bwm_file:
            print &gt;&gt; bwm_file
            print &gt;&gt; bwm_file, "relocate_references(1): Position, attr:"
            pprint.pprint((p, attr), bwm_file)
        # http_lines = attr [3:]
        parser = link_htmlparserClass(self,p)
        for line in attr [3:]:
            try:
                parser.feed(line)
            except Exception:
                line = ''.join([ch for ch in line if ord(ch) &lt;= 127])
                parser.feed(line)
        replacements = parser.get_replacements()
        replacements.reverse()
        if not replacements:
            continue
        if bwm_file:
            print &gt;&gt; bwm_file, "relocate_references(2): Replacements:"
            pprint.pprint(replacements, bwm_file)
        for line, column, href, href_file, http_node_ref in replacements:
            if bwm_file:
                print &gt;&gt; bwm_file, ( "relocate_references(3): line:",
                    line, "Column:", column, "href:", href,
                    "href_file:", href_file, "http_node_ref:", http_node_ref)
            marker_parts = href.split("#")
            if len(marker_parts) == 2:
                marker = marker_parts [1]
                replacement = "%s#%s" % (http_node_ref,marker)
                try:
                    attr [line + 2] = attr [line + 2].replace(
                        'href="%s"' % href,'href="%s"' % replacement)
                except Exception:
                    g.es("Skipped ", attr[line + 2])
            else:
                # filename = marker_parts [0]
                try:
                    attr [line + 2] = attr [line + 2].replace(
                        'href="%s"' % href,
                        'href="%s"' % http_node_ref)
                except Exception:
                    g.es("Skipped", attr[line+2])
</t>
<t tx="ekr.20050805162550.38">def find_anchors (self, p):

    '''Find the anchors in all the nodes.'''

    for p1, attrs in self.http_attribute_iter(p):
        html = mod_http.reconstruct_html_from_attrs(attrs)
        parser = anchor_htmlParserClass(self, p1)
        for line in html:
            try:
                parser.feed(line)
            except Exception:
                line = ''.join([ch for ch in line if ord(ch) &lt;= 127])
                # filter out non-ascii characters.
                # bwm: not quite sure what's going on here.
                parser.feed(line)
</t>
<t tx="ekr.20050805162550.39">@
The parser classes are used to construct the html code for nodes. The algorithm has two phases:
    1. In the first phase, the html code for each node is identified.
    2. The second phase identifies all links and checks if these links need to be modified.
The first phase of scanning is done by the anchor_hmlParserClass. The second phase of this algorithm is
done with the link_htmlParserClass.
@code

&lt;&lt; class linkAnchorParserClass &gt;&gt;

@others
</t>
<t tx="ekr.20050805162550.4"></t>
<t tx="ekr.20050805162550.40">class linkAnchorParserClass (HTMLParser.HTMLParser):

    '''
    A class to recognize anchors and links in HTML documents.
    A special marker is the "node_marker" which demarkates the border between
    node and the next.
    '''

    @others
</t>
<t tx="ekr.20050805162550.41">def __init__(self,rst):

    super().__init__()
    self.rst = rst

    # Set ivars from options.  This works only if we don't change nodes!
    self.node_begin_marker      = rst.getOption('node_begin_marker')
    self.clear_http_attributes  = rst.getOption('clear_http_attributes')
    self.current_file = rst.outputFileName
</t>
<t tx="ekr.20050805162550.42">def is_anchor(self, tag, attrs):
    """
    Check if the current tag is an anchor.
    Returns *all* anchors.
    Works with docutils 0.4
    """

    if tag == 'a':
        return True

    if self.is_node_marker(attrs):
        return True
    return tag == "span"
</t>
<t tx="ekr.20050805162550.43">def is_link(self, tag, attrs):
    '''
    Return True if tag, attrs is represents a link.
    '''

    if tag != 'a':
        return False

    result = 'href' in dict(attrs)
    return result
</t>
<t tx="ekr.20050805162550.44">class htmlParserClass (linkAnchorParserClass):

    '''
    The responsibility of the html parser is:
        1. Find out which html code belongs to which node.
        2. Keep a stack of open tags which apply to the current node.
        3. Keep a list of tags which should be included in the nodes, even
           though they might be closed.
           The &lt;style&gt; tag is one example of that.

    Later, we have to relocate inter-file links: if a reference to another location
    is in a file, we must change the link.

    '''

    @others
</t>
<t tx="ekr.20050805162550.45">def __init__ (self,rst):

    super().__init__(rst) # Init the base class.

    self.stack = None
    # The stack contains lists of the form:
        # [text1, text2, previous].
        # text1 is the opening tag
        # text2 is the closing tag
        # previous points to the previous stack element

    self.node_marker_stack = []
    # self.node_marker_stack.pop() returns True for a closing
    # tag if the opening tag identified an anchor belonging to a vnode.

    self.node_code = []
        # Accumulated html code.
        # Once the hmtl code is assigned a vnode, it is deleted here.

    self.deleted_lines = 0 # Number of lines deleted in self.node_code

    self.endpos_pending = False
    # Do not include self.node_code[0:self.endpos_pending] in the html code.

    self.last_position = None
    # Last position; we must attach html code to this node.

    self.last_marker = None
</t>
<t tx="ekr.20050805162550.46">def handle_starttag (self,tag,attrs):
    '''
    1. Find out if the current tag is an achor.
    2. If it is an anchor, we check if this anchor marks the beginning of a new
       node
    3. If a new node begins, then we might have to store html code for the previous
       node.
    4. In any case, put the new tag on the stack.
    '''
    is_node_marker = False
    if self.is_anchor(tag,attrs) and self.is_node_marker(attrs):
        is_node_marker = self.is_node_marker(attrs)
        line, column = self.getpos()
        if self.last_position:
            lines = self.node_code [:]
            lines [0] = lines [0] [self.startpos:]
            del lines [line-self.deleted_lines-1:]
            mod_http.get_http_attribute(self.last_position).extend(lines)
            &lt;&lt; trace the unknownAttribute &gt;&gt;
        if self.deleted_lines &lt; line-1:
            del self.node_code [: line-1-self.deleted_lines]
            self.deleted_lines = line-1
            self.endpos_pending = True
    starttag = self.get_starttag_text()
    self.stack = [starttag, None, self.stack]
    self.node_marker_stack.append(is_node_marker)
</t>
<t tx="ekr.20050805162550.47">def handle_endtag(self, tag):
    '''
    1. Set the second element of the current top of stack.
    2. If this is the end tag for an anchor for a node,
       store the current stack for that node.
    '''
    self.stack[1] = "&lt;/" + tag + "&gt;"

    if self.endpos_pending:
        line, column = self.getpos()
        self.startpos = self.node_code[0].find("&gt;", column) + 1
        self.endpos_pending = False

    is_node_marker = self.node_marker_stack.pop()

    if is_node_marker and not self.clear_http_attributes:
        self.last_position = self.rst.http_map[is_node_marker]
        if is_node_marker != self.last_marker:
            if bwm_file: print &gt;&gt; bwm_file, "Handle endtag:", is_node_marker, self.stack
            mod_http.set_http_attribute(self.rst.http_map[is_node_marker], self.stack)
            self.last_marker = is_node_marker
            #bwm: last_marker is not needed?

    self.stack = self.stack[2]
</t>
<t tx="ekr.20050805162550.49">def feed(self, line):

    self.node_code.append(line)

    HTMLParser.HTMLParser.feed(self, line) # Call the base class's feed().
</t>
<t tx="ekr.20050805162550.5">def init ():
    '''Return True if the plugin has loaded successfully.'''
    ok = docutils is not None # Ok for unit testing.
    if ok:
        g.registerHandler('after-create-leo-frame', onCreate)
        g.plugin_signon(__name__)
    else:
        g.error('rst3 plugin not loaded: can not load docutils')
    return ok
</t>
<t tx="ekr.20050805162550.50">class anchor_htmlParserClass (linkAnchorParserClass):

    '''
    This htmlparser does the first step of relocating: finding all the anchors within the html nodes.

    Each anchor is mapped to a tuple:
        (current_file, position).

    Filters out markers which mark the beginning of the html code for a node.
    '''

    @others
</t>
<t tx="ekr.20050805162550.51">def __init__ (self,rst,p):

    super().__init__(rst)

    self.p = p.copy()
    self.anchor_map = rst.anchor_map
</t>
<t tx="ekr.20050805162550.52">def handle_starttag(self, tag, attrs):
    '''
    1. Find out if the current tag is an achor.
    2. If the current tag is an anchor, update the mapping;
         anchor -&gt; (filename, p)
    '''
    if not self.is_anchor(tag, attrs):
        return

    if self.current_file not in self.anchor_map:
        self.anchor_map[self.current_file] = (self.current_file, self.p)
        simple_name = g.os_path_split(self.current_file)[1]
        self.anchor_map[simple_name] = self.anchor_map[self.current_file]
        if bwm_file: print &gt;&gt; bwm_file, (
            "anchor(1): current_file:", self.current_file,
            "position:", self.p,
            "Simple name:", simple_name,
        )
        # Not sure what to do here, exactly. Do I need to manipulate
        # the pathname?

    for name, value in attrs:
        if name == 'name' or tag == 'span' and name == 'id':
            if not value.startswith(self.node_begin_marker):
                if bwm_file: print &gt;&gt; bwm_file, "anchor(2):", value, self.p
                self.anchor_map[value] = (self.current_file, self.p.copy())
</t>
<t tx="ekr.20050805162550.53">class link_htmlparserClass (linkAnchorParserClass):

    '''This html parser does the second step of relocating links:
    1. It scans the html code for links.
    2. If there is a link which links to a previously processed file
       then this link is changed so that it now refers to the node.
    '''

    @others
</t>
<t tx="ekr.20050805162550.54">def __init__ (self,rst,p):

    super().__init__(rst)

    self.p = p.copy()
    self.anchor_map = rst.anchor_map
    self.replacements = []
</t>
<t tx="ekr.20050805162550.55">def handle_starttag(self, tag, attrs):
    '''
    1. Find out if the current tag is an achor.
    2. If the current tag is an anchor, update the mapping;
         anchor -&gt; p
        Update the list of replacements for the document.
    '''
    if bwm_file: print &gt;&gt; bwm_file, "Is link?", tag, attrs
    if not self.is_link(tag, attrs):
        return

    marker = self.node_begin_marker
    for name, value in attrs:
        if name == 'href':
            href = value
            href_parts = href.split("#")
            if len(href_parts) == 1:
                href_a = href_parts[0]
            else:
                href_a = href_parts[1]
            if bwm_file: print &gt;&gt; bwm_file, "link(1):", name, value, href_a
            if not href_a.startswith(marker):
                if href_a in self.anchor_map:
                    href_file, href_node = self.anchor_map[href_a]
                    http_node_ref = mod_http.node_reference(href_node)
                    line, column = self.getpos()
                    if bwm_file: print &gt;&gt; bwm_file, "link(2):", line, column, href, href_file, http_node_ref
                    self.replacements.append((line, column, href, href_file, http_node_ref))
</t>
<t tx="ekr.20050805162550.56">def get_replacements(self):

    return self.replacements
</t>
<t tx="ekr.20050805162550.6">def onCreate(tag, keywords):

    c = keywords.get('new_c') or keywords.get('c')
    if c:
        global controllers
        controllers[c] = rstClass(c)
        # Warning: Do not return anything but None here!
        # Doing so suppresses the loading of other 'new' or 'open2' hooks!
</t>
<t tx="ekr.20050805162550.8">class rstClass:

    '''A class to write rst markup in Leo outlines.'''

@ This plugin optionally stores information for the http plugin.

Each node can have one additional attribute, with the name rst_http_attributename, which is a list.

The first three elements are stack of tags, the rest is html code.

[&lt;tag n start&gt;, &lt;tag n end&gt;, &lt;other stack elements&gt;, &lt;html line 1&gt;, &lt;html line 2&gt;, ...]

&lt;other stack elements has the same structure:
    [&lt;tag n-1 start&gt;, &lt;tag n-1 end&gt;, &lt;other stack elements&gt;]
@c

    @others
</t>
<t tx="ekr.20050805162550.9"></t>
<t tx="ekr.20050806101253">def code_block (name,arguments,options,content,lineno,content_offset,block_text,state,state_machine):

    '''Implement the code-block directive for docutils.'''

    try:
        language = arguments [0]
        # See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/252170
        module = SilverCity and getattr(SilverCity,language)
        generator = module and getattr(module,language+"HTMLGenerator")
        if generator:
            io = StringIO()
            generator().generate_html(io,'\n'.join(content))
            html = '&lt;div class="code-block"&gt;\n%s\n&lt;/div&gt;\n' % io.getvalue()
        else:
            html = '&lt;div class="code-block"&gt;\n%s\n&lt;/div&gt;\n' % '&lt;br&gt;\n'.join(content)
        raw = docutils.nodes.raw('',html,format='html')
        return [raw]
    except Exception: # Return html as shown.  Lines are separated by &lt;br&gt; elements.
        g.es_trace('exception in rst3:code_block()')
        g.es_exception()
        return [None]

# See http://docutils.sourceforge.net/spec/howto/rst-directives.html
code_block.arguments = (
    1, # Number of required arguments.
    0, # Number of optional arguments.
    0) # True if final argument may contain whitespace.

# A mapping from option name to conversion function.
if docutils:
    code_block.options = {
        'language':
        docutils.parsers.rst.directives.unchanged # Return the text argument, unchanged.
    }
    code_block.content = 1 # True if content is allowed.

    # Register the directive with docutils.
    docutils.parsers.rst.directives.register_directive('code-block',code_block)
else:
    code_block.options = {}

</t>
<t tx="ekr.20050806162146">@nocolor
@

- Specify option for the spelling of special doc parts.
    - The present code assumes to much about these commands.
- Warn if option gets set twice in same vnode.

Later or never:
    - show_context option.
    - encoding option: can override @encoding directives
    - Support docutils config files.

@c

@others
</t>
<t tx="ekr.20050807120331.1">def preprocessTree (self,root):

    self.tnodeOptionDict = {}

    # Bug fix 12/4/05: must preprocess parents too.
    for p in root.parents():
        self.preprocessNode(p)

    for p in root.self_and_subtree():
        self.preprocessNode(p)

    if 0:
        g.trace(root.h)
        for key in self.tnodeOptionDict.keys():
            g.trace(key)
            g.printDict(self.tnodeOptionDict.get(key))
</t>
<t tx="ekr.20050807120331.2">def scanNodeForOptions (self,p):
    '''
    Return a dictionary containing all the option-name:value entries in p.

    Such entries may arise from @rst-option or @rst-options in the headline,
    or from @ @rst-options doc parts.
    '''
    d = self.scanHeadlineForOptions(p)
    d2 = self.scanForOptionDocParts(p,p.b)
    # A fine point: body options over-ride headline options.
    d.update(d2)
    return d
</t>
<t tx="ekr.20050808064245">def createDefaultOptionsDict(self):

    # Warning: changing the names of options changes the names of the corresponding ivars.

    self.defaultOptionsDict = {
        # Http options...
        'rst3_clear_http_attributes':   False,
        'rst3_http_server_support':     False,
        'rst3_http_attributename':      'rst_http_attribute',
        'rst3_node_begin_marker':       'http-node-marker-',
        # Path options...
        'rst3_default_path': None, # New in Leo 4.4a4 # Bug fix: must be None, not ''.
        'rst3_stylesheet_name': 'default.css',
        'rst3_stylesheet_path': None, # Bug fix: must be None, not ''.
        'rst3_publish_argv_for_missing_stylesheets': None,
        # Global options...
        'rst3_code_block_string': '',
        'rst3_number_code_lines': True,
        'rst3_underline_characters': '''#=+*^~"'`-:&gt;&lt;_''',
        'rst3_verbose':True,
        'rst3_write_intermediate_file': False, # Used only if generate_rst is True.
        # Mode options...
        'rst3_code_mode': False, # True: generate rst markup from @code and @doc parts.
        'rst3_doc_only_mode': False, # True: generate only from @doc parts.
        'rst3_generate_rst': True, # True: generate rst markup.  False: generate plain text.
        'rst3_generate_rst_header_comment': True,
            # True generate header comment (requires generate_rst option)
        # Formatting options that apply to both code and rst modes....
        'rst3_show_headlines': True,  # Can be set by @rst-no-head headlines.
        'rst3_show_organizer_nodes': True,
        'rst3_show_options_nodes': False,
        'rst3_show_sections': True,
        'rst3_strip_at_file_prefixes': True,
        'rst3_show_doc_parts_in_rst_mode': True,
        # Formatting options that apply only to code mode.
        'rst3_show_doc_parts_as_paragraphs': False,
        'rst3_show_leo_directives': True,
        'rst3_show_markup_doc_parts': False,
        'rst3_show_options_doc_parts': False,
        # *Names* of headline commands...
        'rst3_code_prefix':             '@rst-code',     # Enter code mode.
        'rst3_doc_only_prefix':         '@rst-doc-only', # Enter doc-only mode.
        'rst3_rst_prefix':              '@rst',          # Enter rst mode.
        'rst3_ignore_headline_prefix':  '@rst-no-head',
        'rst3_ignore_headlines_prefix': '@rst-no-headlines',
        'rst3_ignore_node_prefix':      '@rst-ignore-node',
        'rst3_ignore_prefix':           '@rst-ignore',
        'rst3_ignore_tree_prefix':      '@rst-ignore-tree',
        'rst3_option_prefix':           '@rst-option',
        'rst3_options_prefix':          '@rst-options',
        'rst3_preformat_prefix':        '@rst-preformat',
        'rst3_show_headline_prefix':    '@rst-head',
    }
</t>
<t tx="ekr.20050808070018">def scanOption (self,p,s):
    '''
    Return { name:val } if s is a line of the form name=val.
    Otherwise return {}
    '''
    if not s.strip() or s.strip().startswith('..'):
        return {}
    data = self.parseOptionLine(s)
    if data:
        name,val = data
        fullName = 'rst3_' + self.munge(name)
        if fullName in self.defaultOptionsDict.keys():
            if   val.lower() == 'true': val = True
            elif val.lower() == 'false': val = False
            return { self.munge(name): val }
        else:
            g.error('ignoring unknown option: %s' % (name))
            return {}
    else:
        g.trace(repr(s))
        g.error('bad rst3 option in %s: %s' % (p.h,s))
        return {}
</t>
<t tx="ekr.20050808070018.1">def scanOptions (self,p,s):

    '''Return a dictionary containing all the options in s.'''

    d = {}

    for line in g.splitLines(s):
        d2 = self.scanOption(p,line)
        if d2: d.update(d2)

    return d
</t>
<t tx="ekr.20050808070018.2">def scanForOptionDocParts (self,p,s):

    '''Return a dictionary containing all options from @rst-options doc parts in p.
    Multiple @rst-options doc parts are allowed: this code aggregates all options.
    '''

    d = {} ; n = 0 ; lines = g.splitLines(s)
    while n &lt; len(lines):
        line = lines[n] ; n += 1
        if line.startswith('@'):
            i = g.skip_ws(line,1)
            for kind in ('@rst-options','@rst-option'):
                if g.match_word(line,i,kind):
                    # Allow options on the same line.
                    line = line[i+len(kind):]
                    d.update(self.scanOption(p,line))
                    # Add options until the end of the doc part.
                    while n &lt; len(lines):
                        line = lines[n] ; n += 1 ; found = False
                        for stop in ('@c','@code', '@'):
                            if g.match_word(line,0,stop):
                                found = True ; break
                        if found:
                            break
                        else:
                            d.update(self.scanOption(p,line))
                    break
    return d
</t>
<t tx="ekr.20050808072943">def munge (self,name):

    '''Convert an option name to the equivalent ivar name.'''

    i = 3 if name.startswith('rst') else 0

    while i &lt; len(name) and name[i].isdigit():
        i += 1

    if i &lt; len(name) and name[i] == '_':
        i += 1

    s = name[i:].lower()
    s = s.replace('-','_')

    return s
</t>
<t tx="ekr.20050808072943.1">def parseOptionLine (self,s):
    '''
    Parse a line containing name=val and return (name,value) or None.
    If no value is found, default to True.
    '''
    s = s.strip()
    if s.endswith(','): s = s[:-1]
    # Get name.  Names may contain '-' and '_'.
    i = g.skip_id(s,0,chars='-_')
    name = s [:i]
    if not name:
        return None,'False'
    j = g.skip_ws(s,i)
    if g.match(s,j,'='):
        val = s [j+1:].strip()
        return name,val
    else:
        return name,'True'
</t>
<t tx="ekr.20050808142313.28"># Once an option is seen, no other related options in ancestor nodes have any effect.

def scanAllOptions(self,p):

    '''Scan position p and p's ancestors looking for options,
    setting corresponding ivars.
    '''

    self.initOptionsFromSettings()
        # Must be done on every node.
    self.handleSingleNodeOptions(p)
    seen = self.singleNodeOptions[:]
        # Suppress inheritance of single-node options.
    for p in p.self_and_parents():
        d = self.tnodeOptionDict.get(p.v,{})
        for key in d.keys():
            ivar = self.munge(key)
            if ivar not in seen:
                seen.append(ivar)
                val = d.get(key)
                self.setOption(key,val,p.h)
    # self.dumpSettings()
    if self.rst3_all:
        self.setOption("generate_rst", True, "rst3_all")
        self.setOption("generate_rst_header_comment",True, "rst3_all")
        self.setOption("http_server_support", True, "rst3_all")
        self.setOption("write_intermediate_file", True, "rst3_all")
</t>
<t tx="ekr.20050809074827"></t>
<t tx="ekr.20050809075309">def initWrite (self,p):

    self.initOptionsFromSettings() # Still needed.

    # Set the encoding from any parent @encoding directive.
    # This can be overridden by @rst-option encoding=whatever.
    c = self.c
    d = c.scanAllDirectives(p)
    self.encoding = d.get('encoding') or self.defaultEncoding
    self.path = d.get('path') or ''
</t>
<t tx="ekr.20050809080031">def write (self,s):

    s = self.encode(s)

    self.outputFile.write(s)
</t>
<t tx="ekr.20050809080925">def writeNormalTree (self,p,toString=False):

    self.initWrite(p)

    # Always write to a string first.
    self.outputFile = StringIO()
    self.writeTree(p)
    self.source = self.stringOutput = self.outputFile.getvalue()

    # Copy to a file if requested.
    if not toString:
        # Comput the output file name *after* calling writeTree.
        self.outputFileName = self.computeOutputFileName(self.outputFileName)
        self.outputFile = open(self.outputFileName,'w')
        self.outputFile.write(self.stringOutput)
        self.outputFile.close()

    return True
</t>
<t tx="ekr.20050809082854"></t>
<t tx="ekr.20050809082854.1">def writeToDocutils (self,s):
    '''
    Send s to docutils using the writer implied by self.ext and return the
    result.
    '''
    # openDirectory = self.c.frame.openDirectory
    overrides = {'output_encoding': self.encoding }
    # Compute the args list if the stylesheet path does not exist.
    styleSheetArgsDict = self.handleMissingStyleSheetArgs()
    writer = None
    for ext,writer in (
        ('.html','html'),
        ('.htm','html'),
        ('.tex','latex'),
        ('.pdf','leo_pdf'),
    ):
        if self.ext == ext:
            break
    else:
        g.error('unknown docutils extension: %s' % (self.ext))
        return ''

    # Make the stylesheet path relative to the directory containing the output file.
    rel_stylesheet_path = self.getOption('stylesheet_path') or ''

    # New in Leo 4.5: The rel_stylesheet_path is relative to the open directory.
    stylesheet_path = g.os_path_finalize_join(
        self.c.frame.openDirectory,rel_stylesheet_path)

    path = g.os_path_finalize_join(
        stylesheet_path,self.getOption('stylesheet_name'))

    res = ""
    if g.os_path_exists(path):
        if self.ext != '.pdf':
            overrides['stylesheet'] = path
            overrides['stylesheet_path'] = None
    elif styleSheetArgsDict:
        g.es_print('using publish_argv_for_missing_stylesheets',
            styleSheetArgsDict)
        overrides.update(styleSheetArgsDict)
            # MWC add args to settings
    elif rel_stylesheet_path == stylesheet_path:
        g.error('stylesheet not found: %s' % (path))
    else:
        g.error('stylesheet not found\n',path)
        if self.path:g.es_print('@path:', self.path)
        g.es_print('open path:',self.c.frame.openDirectory)
        if rel_stylesheet_path:
            g.es_print('relative path:', rel_stylesheet_path)
    try:
        # All paths now come through here.
        res = docutils.core.publish_string(source=s,
                reader_name='standalone',
                parser_name='restructuredtext',
                writer_name=writer,
                settings_overrides=overrides)
    except docutils.ApplicationError as error:
        g.es_print('Error (%s): %s' % (error.__class__.__name__, error))
    return res
</t>
<t tx="ekr.20050810083057">def writeNode (self,p):

    '''Format a node according to the options presently in effect.'''

    self.initCodeBlockString(p)
    self.scanAllOptions(p)

    if 0:
        g.trace('%24s code_mode %s' % (p.h,self.getOption('code_mode')))

    h = p.h.strip()

    if self.getOption('preformat_this_node'):
        self.http_addNodeMarker(p)
        self.writePreformat(p)
        p.moveToThreadNext()
    elif self.getOption('ignore_this_tree'):
        p.moveToNodeAfterTree()
    elif self.getOption('ignore_this_node'):
        p.moveToThreadNext()
    elif g.match_word(h,0,'@rst-options') and not self.getOption('show_options_nodes'):
        p.moveToThreadNext()
    else:
        self.http_addNodeMarker(p)
        self.writeHeadline(p)
        self.writeBody(p)
        p.moveToThreadNext()
</t>
<t tx="ekr.20050810083314"></t>
<t tx="ekr.20050810083856">def rstComment (self,s):

    return '.. %s' % s
</t>
<t tx="ekr.20050810103731">def handleSingleNodeOptions (self,p):

    '''Init the settings of single-node options from the tnodeOptionsDict.

    All such options default to False.'''

    d = self.tnodeOptionDict.get(p.v, {} )

    for ivar in self.singleNodeOptions:
        val = d.get(ivar,False)
        self.setOption(ivar,val,p.h)

</t>
<t tx="ekr.20050811101550.1">def writeBody (self,p):

    # remove trailing cruft and split into lines.
    lines = p.b.rstrip().split('\n')

    if self.getOption('code_mode'):
        if not self.getOption('show_options_doc_parts'):
            lines = self.handleSpecialDocParts(lines,'@rst-options',
                retainContents=False)
        if not self.getOption('show_markup_doc_parts'):
            lines = self.handleSpecialDocParts(lines,'@rst-markup',
                retainContents=False)
        if not self.getOption('show_leo_directives'):
            lines = self.removeLeoDirectives(lines)
        lines = self.handleCodeMode(lines)
    elif self.getOption('doc_only_mode'):
        # New in version 1.15
        lines = self.handleDocOnlyMode(p,lines)
    else:
        lines = self.handleSpecialDocParts(lines,'@rst-options',
            retainContents=False)
        lines = self.handleSpecialDocParts(lines,'@rst-markup',
            retainContents=self.getOption('generate_rst'))
        if self.getOption('show_doc_parts_in_rst_mode') is True:
            pass  # original behaviour, treat as plain text
        elif self.getOption('show_doc_parts_in_rst_mode'):
            # use value as class for content
            lines = self.handleSpecialDocParts(lines,None,
                retainContents=True, asClass=self.getOption('show_doc_parts_in_rst_mode'))
        else:  # option evaluates to false, cut them out
            lines = self.handleSpecialDocParts(lines,None,
                retainContents=False)
        lines = self.removeLeoDirectives(lines)
        if self.getOption('generate_rst') and self.getOption('use_alternate_code_block'):
            lines = self.replaceCodeBlockDirectives(lines)

    s = '\n'.join(lines).strip()
    if s:
        self.write('%s\n\n' % s)
</t>
<t tx="ekr.20050811102607">def skip_literal_block (self,lines,n):

    s = lines[n] ; result = [s] ; n += 1
    indent = g.skip_ws(s,0)

    # Skip lines until a non-blank line is found with same or less indent.
    while n &lt; len(lines):
        s = lines[n]
        indent2 = g.skip_ws(s,0)
        if s and not s.isspace() and indent2 &lt;= indent:
            break # We will rescan lines [n]
        n += 1
        result.append(s)

    # g.printList(result,tag='literal block')
    return n, result
</t>
<t tx="ekr.20050811105438">def removeLeoDirectives (self,lines):

    '''Remove all Leo directives, except within literal blocks.'''

    n = 0 ; result = []
    while n &lt; len(lines):
        s = lines [n] ; n += 1
        if s.strip().endswith('::'):
            n, lit = self.skip_literal_block(lines,n-1)
            result.extend(lit)
        elif s.startswith('@') and not self.isAnySpecialDocPart(s):
            for key in self.leoDirectivesList:
                if g.match_word(s,0,key):
                    break
            else:
                result.append(s)
        else:
            result.append(s)

    return result
</t>
<t tx="ekr.20050811105438.1">def handleSpecialDocParts (self,lines,kind,retainContents,asClass=None):

    result = [] ; n = 0
    while n &lt; len(lines):
        s = lines [n] ; n += 1
        if s.strip().endswith('::'):
            n, lit = self.skip_literal_block(lines,n-1)
            result.extend(lit)
        elif self.isSpecialDocPart(s,kind):
            n, lines2 = self.getDocPart(lines,n)
            if retainContents:
                result.extend([''])
                if asClass:
                    result.extend(['.. container:: '+asClass, ''])
                    if 'literal' in asClass.split():
                        result.extend(['  ::', ''])
                    for l2 in lines2: result.append('    '+l2)
                else:
                    result.extend(lines2)
                result.extend([''])
        else:
            result.append(s)

    return result
</t>
<t tx="ekr.20050811135526">def setOption (self,name,val,tag):

    ivar = self.munge(name)
    self.optionsDict [ivar] = val
</t>
<t tx="ekr.20050811150541">def handleCodeMode (self,lines):

    '''Handle the preprocessed body text in code mode as follows:

    - Blank lines are copied after being cleaned.
    - @ @rst-markup lines get copied as is.
    - Everything else gets put into a code-block directive.'''

    result = [] ; n = 0 ; code = []
    while n &lt; len(lines):
        s = lines [n] ; n += 1
        if (
            self.isSpecialDocPart(s,'@rst-markup') or
            (self.getOption('show_doc_parts_as_paragraphs') and self.isSpecialDocPart(s,None))
        ):
            if code:
                self.finishCodePart(result,code)
                code = []
            result.append('')
            n, lines2 = self.getDocPart(lines,n)
            result.extend(lines2)
        elif not s.strip() and not code:
            pass # Ignore blank lines before the first code block.
        elif not code: # Start the code block.
            result.append('')
            result.append(self.code_block_string)
            code.append(s)
        else: # Continue the code block.
            code.append(s)

    if code:
        self.finishCodePart(result,code)
        code = []
    return self.rstripList(result)
</t>
<t tx="ekr.20050811152104">def formatCodeModeLine (self,s,n,numberOption):

    if not s.strip(): s = ''

    if numberOption:
        return '\t%d: %s' % (n,s)
    else:
        return '\t%s' % s
</t>
<t tx="ekr.20050811153208">def isSpecialDocPart (self,s,kind):

    '''Return True if s is a special doc part of the indicated kind.

    If kind is None, return True if s is any doc part.'''

    if s.startswith('@') and len(s) &gt; 1 and s[1].isspace():
        if kind:
            i = g.skip_ws(s,1)
            result = g.match_word(s,i,kind)
        else:
            result = True
    elif not kind:
        result = g.match_word(s,0,'@doc') or g.match_word(s,0,'@')
    else:
        result = False

    return result
</t>
<t tx="ekr.20050811154552">def getDocPart (self,lines,n):

    result = []
    &lt;&lt; Append whatever follows @doc or @space to result &gt;&gt;
    while n &lt; len(lines):
        s = lines [n] ; n += 1
        if g.match_word(s,0,'@code') or g.match_word(s,0,'@c'):
            break
        result.append(s)
    return n, result
</t>
<t tx="ekr.20050811163802">def isAnySpecialDocPart (self,s):

    for kind in (
        '@rst-markup',
        '@rst-option',
        '@rst-options',
    ):
        if self.isSpecialDocPart(s,kind):
            return True

    return False
</t>
<t tx="ekr.20050811173750">def scanHeadlineForOptions (self,p):

    '''Return a dictionary containing the options implied by p's headline.'''

    h = p.h.strip()

    if p == self.topNode:
        return {} # Don't mess with the root node.
    elif g.match_word(h,0,self.getOption('option_prefix')): # '@rst-option'
        s = h [len(self.option_prefix):]
        return self.scanOption(p,s)
    elif g.match_word(h,0,self.getOption('options_prefix')): # '@rst-options'
        return self.scanOptions(p,p.b)
    else:
        # Careful: can't use g.match_word because options may have '-' chars.
        i = g.skip_id(h,0,chars='@-')
        word = h[0:i]

        for prefix,ivar,val in (
            ('code_prefix','code_mode',True), # '@rst-code'
            ('doc_mode_prefix','doc_only_mode',True), # @rst-doc-only.
            ('default_path_prefix','default_prefix',''), # '@rst-default-path'
            ('rst_prefix','code_mode',False), # '@rst'
            ('ignore_headline_prefix','ignore_this_headline',True), # '@rst-no-head'
            ('show_headline_prefix','show_this_headline',True), # '@rst-head'
            ('ignore_headlines_prefix','show_headlines',False), # '@rst-no-headlines'
            ('ignore_prefix','ignore_this_tree',True),      # '@rst-ignore'
            ('ignore_node_prefix','ignore_this_node',True), # '@rst-ignore-node'
            ('ignore_tree_prefix','ignore_this_tree',True), # '@rst-ignore-tree'
            ('preformat_prefix','preformat_this_node',True), # '@rst-preformat
        ):
            prefix = self.getOption(prefix)
            if prefix and word == prefix: # Do _not_ munge this prefix!
                d = { ivar: val }
                if ivar != 'code_mode':
                    d ['code_mode'] = False # Enter rst mode.
                    d ['doc_only_mode'] = False
                # Special case: Treat a bare @rst like @rst-no-head
                if h == self.getOption('rst_prefix'):
                    d ['ignore_this_headline'] = True
                return d

        if h.startswith('@rst'):
            g.trace('word',word,'rst_prefix',self.getOption('rst_prefix'))
            g.trace('unknown kind of @rst headline',p.h)

        return {}
</t>
<t tx="ekr.20050812120933">def dumpSettings (self):

    d = self.optionsDict
    keys = list(d.keys())
    keys.sort()

    g.pr('present settings...')
    for key in keys:
        g.pr('%20s %s' % (key,d.get(key)))
</t>
<t tx="ekr.20050812122236"></t>
<t tx="ekr.20050813083007">def initHeadlineCommands (self):

    '''Init the list of headline commands used by writeHeadline.'''

    self.headlineCommands = [
        self.getOption('code_prefix'),
        self.getOption('doc_only_prefix'),
        self.getOption('default_path_prefix'),
        self.getOption('rst_prefix'),
        self.getOption('ignore_headline_prefix'),
        self.getOption('ignore_headlines_prefix'),
        self.getOption('ignore_node_prefix'),
        self.getOption('ignore_tree_prefix'),
        self.getOption('option_prefix'),
        self.getOption('options_prefix'),
        self.getOption('show_headline_prefix'),
        # # Suggested by Hemanth P.S.: prevent @file nodes from creating headings.
        # self.getOption('keep_at_file_prefix'),
        # self.getOption('strip_at_file_prefix'),
    ]
</t>
<t tx="ekr.20050813085236">def initSingleNodeOptions (self):

    self.singleNodeOptions = [
        'ignore_this_headline',
        'ignore_this_node',
        'ignore_this_tree',
        'preformat_this_node',
        'show_this_headline',
    ]
</t>
<t tx="ekr.20050813155021">def rstripList (self,theList):

    '''Removed trailing blank lines from theList.'''

    s = '\n'.join(theList).rstrip()
    return s.split('\n')
</t>
<t tx="ekr.20050813160208">def finishCodePart (self,result,code):

    numberOption = self.getOption('number_code_lines')
    code = self.rstripList(code)
    i = 0
    for line in code:
        i += 1
        result.append(self.formatCodeModeLine(line,i,numberOption))
</t>
<t tx="ekr.20050814134351">def getOption (self,name):

    bwm = False
    if bwm:
        g.trace("bwm: getOption self:%s, name:%s, value:%s" % (
            self, name, self.optionsDict.get(name)))

    return self.optionsDict.get(name)
</t>
<t tx="ekr.20050815091008.1">def http_addNodeMarker (self,p):

    if (
        self.getOption('http_server_support') and
        self.getOption('generate_rst')
    ):
        self.nodeNumber += 1
        anchorname = "%s%s" % (self.getOption('node_begin_marker'),self.nodeNumber)
        s = "\n\n.. _%s:\n\n" % anchorname
        self.write(s)
        self.http_map [anchorname] = p.copy()
        if bwm_file: print &gt;&gt; bwm_file, "addNodeMarker", anchorname, p
</t>
<t tx="ekr.20050815164715">def is_node_marker (self,attrs):
    '''
    Return the name of the anchor, if this is an anchor for the beginning of a node,
    False otherwise.
    '''

    d = dict(attrs)
    result = 'id' in d and d['id'].startswith(self.node_begin_marker)
    if result:
        return d['id']
    return result
</t>
<t tx="ekr.20050815164715.1">if 0:
    g.pr("rst3: unknownAttributes[self.http_attributename]")
    g.pr("For:", self.last_position)
    pprint.pprint(mod_http.get_http_attribute(self.last_position))
</t>
<t tx="ekr.20050817132814">@nocolor-node

Important: the rst3 plugin has largely been superceded by similar
commands built into Leo's core.

To activate the rst3 plugin, do the following:

1. Go to http://silvercity.sourceforge.net/.
- Follow the link 'SilverCity Releases'.
- Download the release that fits to your Python version.
- Double-klick on the downloaded file.

2. Go to http://docutils.sourceforge.net/.
- Have a look for item 'Download'
- Get, as the editor says, the latest snapshot by following the link
  'docutils-snapshot.tgz'.
- Make sure you have a application that can handle this format. 7zip is doing this great.
- Unpack it to a temporary folder.
- Open a console window, go to the temporary folder and type 'setup.py install'
  or '&lt;path_to_python.exe&gt;\python setup.py install'.

3. Start up Leo
- Check in the menu 'Edit' for item 'Write-Restructured-Text'.
</t>
<t tx="ekr.20051121102358">def processTopTree (self,p,justOneFile=False):

    current = p.copy()
    for p in current.self_and_parents():
        h = p.h
        if h.startswith('@rst') and not h.startswith('@rst-'):
            self.processTree(p,
                ext=None,
                toString=False,
                justOneFile=justOneFile,
            )
            break
    else:
        self.processTree(current,
            ext=None,
            toString=False,
            justOneFile=justOneFile,
        )
    g.blue('done')
</t>
<t tx="ekr.20051202070028">def computeOutputFileName (self,fileName):

    openDirectory = self.c.frame.openDirectory
    default_path = self.getOption('default_path')
    if default_path:
        path = g.os_path_finalize_join(self.path,default_path,fileName)
    elif self.path:
        path = g.os_path_finalize_join(self.path,fileName)
    elif openDirectory:
        path = g.os_path_finalize_join(self.path,openDirectory,fileName)
    else:
        path = g.os_path_finalize_join(fileName)

    return path
</t>
<t tx="ekr.20051204070141">def preprocessNode (self,p):

    d = self.tnodeOptionDict.get(p.v)
    if d is None:
        d = self.scanNodeForOptions(p)
        self.tnodeOptionDict [p.v] = d
</t>
<t tx="ekr.20060525102337">def writeNodeToString (self,p=None,ext=None):
    '''
    Scan p's tree (defaults to presently selected tree) looking for @rst nodes.
    Convert the first node found to an ouput of the type specified by ext.

    The @rst may or may not be followed by a filename; the filename is *ignored*,
    and its type does not affect ext or the output generated in any way.

    ext should start with a period:  .html, .tex or None (specifies rst output).

    Returns p, s, where p is the position of the @rst node and s is the converted text.
    '''
    c = self.c
    current = p or c.p
    for p in current.self_and_parents():
        if p.h.startswith('@rst'):
            return self.processTree(p,ext=ext,toString=True,justOneFile=True)
    return self.processTree(current,ext=ext,toString=True,justOneFile=True)
</t>
<t tx="ekr.20060608094815">def handleDocOnlyMode (self,p,lines):
    '''
    Handle the preprocessed body text in doc_only mode as follows:

    - Blank lines are copied after being cleaned.
    - @ @rst-markup lines get copied as is.
    - All doc parts get copied.
    - All code parts are ignored.
    '''
    # ignore            = self.getOption('ignore_this_headline')
    showHeadlines       = self.getOption('show_headlines')
    showThisHeadline    = self.getOption('show_this_headline')
    showOrganizers      = self.getOption('show_organizer_nodes')
    result = [] ; n = 0
    while n &lt; len(lines):
        s = lines [n] ; n += 1
        if self.isSpecialDocPart(s,'@rst-options'):
            n, lines2 = self.getDocPart(lines,n) # ignore.
        elif self.isAnyDocPart(s):
            # Handle any other doc part, including @rst-markup.
            n, lines2 = self.getDocPart(lines,n)
            if lines2: result.extend(lines2)
    if not result: result = []
    if showHeadlines:
        if result or showThisHeadline or showOrganizers or p == self.topNode:
            self.writeHeadlineHelper(p)
    return result
</t>
<t tx="ekr.20060608094815.1">def isAnyDocPart (self,s):

    if s.startswith('@doc'):
        return True
    elif not s.startswith('@'):
        return False
    else:
        return len(s) == 1 or s[1].isspace()
</t>
<t tx="ekr.20060608102001">def writeHeadlineHelper (self,p):

    h = p.h.strip()

    # Remove any headline command before writing the
    i = g.skip_id(h,0,chars='@-')
    word = h [:i]
    if word:
        # Never generate a section for @rst-option or @rst-options.
        if word in (self.getOption('option_prefix'),self.getOption('options_prefix')):
            return
        # Remove all other headline commands from the headline.
        for prefix in self.headlineCommands:
            if word == prefix:
                h = h [len(word):].strip()
                break

        # New in Leo 4.4.4.
        if word.startswith('@'):
            if self.getOption('strip_at_file_prefixes'):
                for s in ('@auto','@file','@nosent','@thin',):
                    if g.match_word(word,0,s):
                        h = h [len(s):].strip()

    if not h.strip(): return

    if self.getOption('show_sections'):
        if self.getOption('generate_rst'):
            self.write('%s\n%s\n' % (h,self.underline(h,p)))
        else:
            self.write('\n%s\n' % h)
    else:
        self.write('\n**%s**\n\n' % h.replace('*',''))
</t>
<t tx="ekr.20060610104435">if n &gt; 0:
    line = lines[n-1]
    if line.startswith('@doc'):
        s = line[4:].lstrip()
    elif line.startswith('@'):
        s = line[1:].lstrip()
    else:
        s = ''

    # New in Leo 4.4.4: remove these special tags.
    for tag in ('@rst-options','@rst-option','@rst-markup'):
        if g.match_word(s,0,tag):
            s = s[len(tag):].strip()

    if s.strip():
        result.append(s)
</t>
<t tx="ekr.20061023141638"></t>
<t tx="ekr.20061023142737"></t>
<t tx="ekr.20061023142737.1"></t>
<t tx="ekr.20071015110830">def initCodeBlockString(self,p):

    # New in Leo 4.4.4: do this here, not in initWrite:
    c = self.c
    d = c.scanAllDirectives(p)
    language = d.get('language')
    if language is None:
        language = 'python'
    else:
        language = language.lower()
    syntax = SilverCity is not None
    s = self.getOption('code_block_string')
    if s:
        self.code_block_string = s.replace('\\n','\n')
    elif syntax and language in ('python','ruby','perl','c'):
        self.code_block_string = '**code**:\n\n.. code-block:: %s\n' % language.title()
    else:
        self.code_block_string = '**code**:\n\n.. class:: code\n..\n\n::\n'
</t>
<t tx="ekr.20071113084440"># These plugins are for testing Leo's own plugin loading logic.
# There is no reason ever to enable these plugins.</t>
<t tx="ekr.20071115061253">def writePreformat (self,p):

    '''Write p's body text lines as if preformatted.

     ::

        line 1
        line 2 etc.
    '''
    lines = p.b.split('\n')
    lines = [' '*4 + z for z in lines]
    lines.insert(0,'::\n')
    s = '\n'.join(lines)
    if s.strip():
        self.write('%s\n\n' % s)
</t>
<t tx="ekr.20090428082801.64">def handleMissingStyleSheetArgs (self,s=None):

    '''Parse the publish_argv_for_missing_stylesheets option,
    returning a dict containing the parsed args.'''

    d = {}
    if not s:
        s = self.getOption('publish_argv_for_missing_stylesheets')
    if not s: return d

    args = s.strip()
    if args.find(',') == -1:
        args = [args]
    else:
        args = args.split(',')

    for arg in args:
        data = arg.split('=')
        if len(data) == 1:
            key = data[0]
            d[str(key)] = ""
        elif len(data) == 2:
            key,value = data
            d[str(key)] = str(value)
        else:
            g.error('bad option: %s' % s)
            break

    return d
</t>
<t tx="ekr.20090429055156.63">def runUnitTests(c):

    rstClass(c)
    p = g.findNodeAnywhere(c,'UnitTests')
    if p:
        c.selectPosition(p)
        c.testManager.doTests(all=None, marked=None, verbosity=1)
</t>
<t tx="ekr.20090430075506.4">@nosearch</t>
<t tx="ekr.20100103093121.5365"># These are experimental plugins.
</t>
<t tx="ekr.20101004082701.5674"></t>
<t tx="ekr.20101110150056.9453"># Some of the most important recent plugins work only with the Qt gui.
</t>
<t tx="ekr.20101110150056.9457"></t>
<t tx="ekr.20120309073937.9878"></t>
<t tx="ekr.20121126102050.10134"></t>
<t tx="ekr.20130927050813.13031"></t>
<t tx="ekr.20140723122936.17925"># Leo loads these plugins automatically.  Do not add them to @enabled-plugins nodes.

# These plugins now contain the importer code for all kinds of @auto nodes.
# Each plugin must define a top-level importer_dict dictionary describing the plugin.
@language python
</t>
<t tx="ekr.20140726091031.18071"># Leo loads these plugins automatically.  Do not add them to @enabled-plugins nodes.

# These plugins now contain the write code for all kinds special @auto nodes.
# Each plugin must define a top-level writer_dict dictionary describing the plugin.
@language python
</t>
<t tx="ekr.20160122104302.1">@nosearch</t>
<t tx="ekr.20160122104357.1">pylint
beautify-node
beautify-tree
</t>
<t tx="ekr.20160122104400.1"></t>
<t tx="ekr.20160412101537.1">'''Imports c:\prog\Julia.ipynb to the node import-Julia.ipynb'''
import nbformat
@others
g.cls()
if 0:
    # fn = r'c:\test\Julia.ipynb'
    fn = r'c:\test\export-neural-networds.ipynb'
    h = 'import-Julia.ipynb'
else:
    h = fn = r'c:\test\04_Neural_Networks.ipynb'
root = g.findTopLevelNode(c, h)
if root:
    while root.hasChildren():
        root.lastChild().doDelete()
else:
    p = c.lastTopLevel()
    root = p.insertAfter()
    root.h = h
x = Import_IPYNB(c)
x.import_file(fn, root)
if not g.unitTesting:
    # These don't work when running unit tests.
    c.selectPosition(root)
    # c.expandAllSubheads()
    c.redraw() 
    g.es_print('done')
</t>
<t tx="ekr.20160412101845.1"># g.cls()
import re
import sys
if 1:
    h = 'import-neural-networks.ipynb'
    fn = r'c:\test\export-neural-networds.ipynb'
else:
    h = 'import-Julia.ipynb'
    fn = r'c:\test\export-julia.ipynb'
p = g.findTopLevelNode(c, h)
assert p, h
@others
Export_IPYNB(c).export_outline(p, fn=fn)
</t>
<t tx="ekr.20160510132151.1">c.backup_helper(sub_dir='leoPlugins')
</t>
<t tx="ekr.20161030154232.1">'''Converts the word at the cursor to pep8 style throughout a given tree.'''
# aTestExample notFoundExample.
import re
# clear()
table = (
    # 'BLS.new_scan',
    # 'BLS.Code generation',
    # 'class Importer',
)
@others
Pep8(table, change=True).run()
</t>
<t tx="ekr.20161031051319.1">def get_name(self):
    i, j = c.editCommands.extendToWord(event=None, select=False)
    w = c.frame.body.wrapper
    s = w.getAllText()
    name = s[i:j]
    return name
</t>
<t tx="ekr.20161031051342.1">def to_pep8(self, s):
    
    if len(s) &gt; 1 and s[0].islower() and s.lower() != s:
        result = []
        for ch in s:
            result.append(ch)
            if ch.isupper():
                result.pop()
                result.append('_%s' % (ch.lower()))
        return ''.join(result)
    else:
        return name</t>
<t tx="ekr.20161031053537.1">def change_all(self, name, new_name, root):
    '''Change name to new_name throughout root's tree.'''
    u = c.undoer
    bunch = u.beforeChangeTree(root)
    found = False
    self.pattern = re.compile(r'\b%s\b' % name)
    for p in root.self_and_subtree():
        found = self.change_headline(name, new_name, p) or found
        found = self.change_body(name, new_name, p) or found
    if found:
        u.afterChangeTree(root, 'pep8', bunch)
    return found
</t>
<t tx="ekr.20161031065339.1">def clear():
    g.cls()
    c.k.simulateCommand('clear-log')
</t>
<t tx="ekr.20161031074727.1">def change_body(self, name, new_name, p):
    indices = []
    for m in self.pattern.finditer(p.b):
        indices.append(str(m.start()))
    if indices:
        n = len(indices)
        g.es_print('%s change%s: %s' % (n, g.plural(n), p.h))
        s = p.b
        for i in reversed(indices):
            i = int(i)
            s = s[:i] + new_name + s[i+len(name):]
        if self.change:
            p.b = s
            p.setDirty()
        else:
            g.es_print(s)
    return bool(indices)</t>
<t tx="ekr.20161031075018.1">def change_headline(self, name, new_name, p):
    m = self.pattern.search(p.h)
    if m:
        i = m.start()
        s = p.h
        s = s[:i] + new_name + s[i+len(name):]
        if self.change:
            p.h = s
            p.setDirty()
            g.es_print('changed headline', s)
        else:
            g.es_print('headline', s)
    return bool(m)
</t>
<t tx="ekr.20161031124905.1">class Pep8:
    '''
    Convert the word under the cursor to pep8 style in all subtrees in
    table.
    '''
    
    def __init__ (self, table, change=False):
        '''Ctor for Pep8 class.'''
        self.change = change
        self.table = table
        
    @others
</t>
<t tx="ekr.20161031125119.1">def run(self):
    # self.clear()
    name = self.get_name()
    new_name = self.to_pep8(name)
    if len(name) &lt; 2:
        g.es_print('name too short:', name)
    elif new_name == name:
        g.es_print('already pep8:', name)
    else:
        g.es_print('%s -&gt; %s' % (name, new_name))
        c.findCommands.ftm.setFindText(new_name)
            # Preload the replacement text.
        found = False
        for target in table:
            root = g.findNodeAnywhere(c, target)
            if root:
                found = self.change_all(name, new_name, root) or found
            else:
                g.es_print('not found: %s' % target)
        if found:
            c.redraw()
        else:
            g.es_print('not found:', name)
</t>
<t tx="ekr.20161122014821.1">g.cls()
# define constants that describe the new language.
name = 'php'
    # The name of the file, and the prefix for classes.
language = 'php'
    # The name of the language, case doesn't matter.
extensions = ['.php',]
    # A list of file extensions supported by this importer.
strict = False
    # True if leading whitespace is particularly significant.
state_ivar = 'self.curlies'
    # 'self.indent' for python, coffeescript.
    # 'self.curlies' for many other languages
    # '(self, curlies, self.parens)' for more complex comparisons
&lt;&lt; define run &amp; helpers &gt;&gt;
run(extensions, language, name, state_ivar)
</t>
<t tx="ekr.20161122020451.1">@others</t>
<t tx="ekr.20161122020932.1">def copy_tree(source, root, h):
    '''Copy the source tree to the node after p, with headline h.'''
    p2 = root.insertAfter()
    source.copyTreeFromSelfTo(p2)
    p2.h = h
    return p2
 </t>
<t tx="ekr.20161122021006.1">def make_substitutions(destination, patterns):
    '''Make all substitutions in the destination tree.'''
    for p in destination.self_and_subtree():
        h = substitute(p.h, patterns)
        if p.h != h:
            # g.trace('CHANGED:', p.h, '==&gt;', h)
            p.h = h
        b = substitute(p.b, patterns)
        if p.b != b:
            # g.trace('CHANGED:', p.b, '==&gt;', b)
            p.b = b
</t>
<t tx="ekr.20161122021342.1">def substitute(s, patterns):
    '''Make all substitutions in s.'''
    for pattern in patterns:
        find = '{{%s}}' % pattern
        replace = patterns.get(pattern)
        i = 0
        while i &lt; len(s):
            progress = i
            j = s.find(find, i)
            if j == -1: break
            s = s[:j] + replace + s[j+len(find):]
            i = j+len(replace)
            assert progress &lt; i
    return s
</t>
<t tx="ekr.20161122023427.1">def run(extensions, language, name, state_ivar):
    '''The driver for this script.'''
    patterns = {
        'cap_name': name.capitalize(),
        'extensions': '[%s]' % ', '.join(["'%s'" % (z) for z in extensions]),
        'language': language.lower(),
        'name': name.lower(),
        'strict': 'True' if strict else 'False',
        'state_ivar': state_ivar,
    }
    h = '@button make-importer'
    root = g.findNodeAnywhere(c, h)
    assert root, h
    h = '@@file importers/{{name}}.py'
    source = g.findNodeInTree(c, root, h)
    assert source, h
    destination = copy_tree(source, root, h)
    make_substitutions(destination, patterns)
    c.contractAllHeadlines()
    c.redraw()</t>
<t tx="ekr.20161122023554.1">'''The @auto importer for the {{name}} language.'''
import leo.plugins.importers.linescanner as linescanner
Importer = linescanner.Importer
@others
importer_dict = {
    'class': {{cap_name}}_Importer,
    'extensions': {{extensions}},
}
@language python
@tabwidth -4


</t>
<t tx="ekr.20161122023554.2">class {{cap_name}}_Importer(Importer):
    '''The importer for the {{name}} lanuage.'''

    def __init__(self, importCommands, atAuto):
        '''{{cap_name}}_Importer.__init__'''
        # Init the base class.
        Importer.__init__(self,
            importCommands,
            atAuto = atAuto,
            language = '{{language}}',
            state_class = {{cap_name}}_ScanState,
            strict = {{strict}},
        )
        
    @others
</t>
<t tx="ekr.20161122023554.3"># These can be overridden in subclasses.
</t>
<t tx="ekr.20161122023554.4">### Define an override if desired...

if 0: # The base class
    def clean_headline(self, s):
        '''Return a cleaned up headline s.'''
        return s.strip()
        
if 0: # A more complex example, for the C language.
    def clean_headline(self, s):
        '''Return a cleaned up headline s.'''
        import re
        type1 = r'(static|extern)*'
        type2 = r'(void|int|float|double|char)*'
        class_pattern = r'\s*(%s)\s*class\s+(\w+)' % (type1)
        pattern = r'\s*(%s)\s*(%s)\s*(\w+)' % (type1, type2)
        m = re.match(class_pattern, s)
        if m:
            prefix1 = '%s ' % (m.group(1)) if m.group(1) else ''
            return '%sclass %s' % (prefix1, m.group(2))
        m = re.match(pattern, s)
        if m:
            prefix1 = '%s ' % (m.group(1)) if m.group(1) else ''
            prefix2 = '%s ' % (m.group(2)) if m.group(2) else ''
            h = m.group(3) or '&lt;no c function name&gt;'
            return '%s%s%s' % (prefix1, prefix2, h)
        else:
            return s
</t>
<t tx="ekr.20161122023554.5">def clean_nodes(self, parent):
    '''
    Clean all nodes in parent's tree.
    Subclasses override this as desired.
    See perl_i.clean_nodes for an examplle.
    '''
    pass
</t>
<t tx="ekr.20161122023554.6">class {{cap_name}}_ScanState:
    '''A class representing the state of the {{name}} line-oriented scan.'''
    
    def __init__(self, d=None):
        '''{{cap_name}}_ScanState.__init__'''
        if d:
            prev = d.get('prev')
            self.context = prev.context
            ### Adjust these by hand.
            self.curlies = prev.curlies
        else:
            self.context = ''
            ### Adjust these by hand.
            self.curlies = 0

    def __repr__(self):
        '''{{cap_name}}_ScanState.__repr__'''
        ### Adjust these by hand.
        return "{{cap_name}}_ScanState context: %r curlies: %s" % (
            self.context, self.curlies)

    __str__ = __repr__

    @others
</t>
<t tx="ekr.20161122023554.7">def level(self):
    '''{{cap_name}}_ScanState.level.'''
    return {{state_ivar}}

</t>
<t tx="ekr.20161122023554.8">def update(self, data):
    '''
    {{cap_name}}_ScanState.update

    Update the state using the 6-tuple returned by v2_scan_line.
    Return i = data[1]
    '''
    context, i, delta_c, delta_p, delta_s, bs_nl = data
    # All ScanState classes must have a context ivar.
    self.context = context
    self.curlies += delta_c  
    ### Update {{cap_name}}_ScanState ivars
    # self.bs_nl = bs_nl
    # self.parens += delta_p
    # self.squares += delta_s
    return i
</t>
<t tx="ekr.20170203054655.1"></t>
<t tx="ekr.20170420085814.1">'''Recursively import all python files in a directory and clean the result.'''
dir_ = r'C:\leo.repo\leo-editor\leo\plugins\leo_babel'
g.cls()
c.recursiveImport(
    dir_ = dir_,
    kind = '@file', # '@clean', #'@nosent','@auto','@file',
    recursive = True,
    safe_at_file = False,
    theTypes = ['.py',],
)
</t>
<t tx="ekr.20170709095709.1">**Temporary**: So I can fix #516 without going crazy.</t>
<t tx="ekr.20170811173231.1">@language python
import os
import subprocess
import sys
import time
win = sys.platform.startswith('win')
old_dir = g.os_path_abspath('.')
if win:
    new_dir = r'C:\leo.repo\leo-editor'
    path = r'C:\Users\edreamleo\Backup'
else:
    new_dir = '/home/edward/leo.repo/leo-editor'
    path = '/home/edward/Backup'
assert g.os_path_exists(new_dir), repr(new_dir)
assert g.os_path_exists(path), repr(path)
stamp = time.strftime("%Y%m%d-%H%M%S")
fn = g.os_path_finalize_join(path, 'leo-bundle-all-%s' % (stamp))
bundle_command = 'git bundle create %s --all' % fn
print(bundle_command)
os.chdir(new_dir)
# os.system(bundle_command)
proc = subprocess.Popen(bundle_command, shell=True)
proc.wait()
os.chdir(old_dir)
print('done! wrote %s' % fn)
</t>
<t tx="ekr.20180504191650.34"></t>
<t tx="ekr.20180504191650.36"></t>
<t tx="ekr.20180504191650.42"></t>
<t tx="ekr.20180504191650.68"></t>
<t tx="ekr.20180504192522.1"></t>
<t tx="ekr.20181017164437.1"># Replace underscore by - in settings names.
g.cls()
import re
kinds = (
    'Bool', 'Color',
    'Directory', 'Encoding', # Not found.
    'Float', 'Int',
    'Path', 'Ratio', # Not found.
    'String',
)
for kind in kinds:
    print('===== %s =====\n' % kind)
    pat = re.compile(r"get%s\s*\([\'\"]([\w_]+)[\'\"][,)]" % kind)
    for p in c.all_positions():
        s = p.b
        i, found = 0, False
        while True:
            m = pat.search(s[i:])
            if not m:
                break
            start, end = m.start(1), m.end(1)
            all = s[i+m.start(0):i+m.end(0)]
            word = s[i+start:i+end]
            if '_' in word:
                found = True
                print('')
                print('-----', p.h)
                print(all)
                s = s[:i+start] + word.replace('_','-') + s[i+end:]
                print(s[i+m.start(0):i+m.end(0)])
            i += end
        if found:
            assert p.b != s, p.h
            # print(s)
            p.b = s
            p.v.setDirty()
c.setChanged()
c.redraw()     </t>
<t tx="ekr.20181030041436.1"></t>
<t tx="rogererens.20041130095659">@ It is possible to link to nodes within the same file.  However clones might be better.
</t>
</tnodes>
</leo_file>
