<?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.20051031040240"><vh>Startup</vh>
<v t="ekr.20080412053100.5"><vh>@settings</vh>
<v t="ekr.20140902155015.18674"><vh>@bool qt-use-scintilla = False</vh></v>
<v t="ekr.20150531102337.1"><vh>@bool tidy-keep-blank-lines = False</vh></v>
<v t="ekr.20150617060607.1"><vh>@bool tidy_autobeautify = False</vh></v>
<v t="ekr.20150425145248.1"><vh>@data history-list</vh></v>
<v t="ekr.20190406193429.1"><vh>@enabled-plugins</vh></v>
<v t="ekr.20140920064112.17946"><vh>@int fts_max_hits = 100</vh></v>
<v t="ekr.20131111060930.18010"><vh>@shortcuts</vh></v>
<v t="ekr.20140916101314.19538"><vh>@string target_language = python</vh></v>
<v t="ekr.20160122104332.1"><vh>Buttons</vh>
<v t="ekr.20180324065741.1"><vh>@@button copy-to-next</vh></v>
<v t="ekr.20150507170849.1"><vh>@@button create decorators</vh>
<v t="ekr.20150508063538.1"><vh>create_d</vh></v>
<v t="ekr.20150508071622.1"><vh>create_decorator (@button)</vh></v>
<v t="ekr.20150508063412.1"><vh>create_decorators</vh></v>
<v t="ekr.20150508074623.1"><vh>create_fixups</vh></v>
<v t="ekr.20150508063926.1"><vh>find_class</vh></v>
<v t="ekr.20150507174711.1"><vh>find_next_clone</vh></v>
<v t="ekr.20150507175246.1"><vh>munge_lines</vh></v>
<v t="ekr.20150508062944.1"><vh>run</vh></v>
</v>
<v t="ekr.20150509183433.1"><vh>@@button make-decorators2</vh>
<v t="ekr.20150509183433.2"><vh>create_d</vh></v>
<v t="ekr.20150509183433.3"><vh>create_decorator (@button)</vh></v>
<v t="ekr.20150509183433.4"><vh>create_decorators V2</vh></v>
<v t="ekr.20150509183832.1"><vh>define_s (@button make-decorators2)</vh></v>
<v t="ekr.20150509183433.8"><vh>munge_lines</vh></v>
<v t="ekr.20150509183433.9"><vh>run V2</vh></v>
</v>
<v t="ekr.20150703061709.1"><vh>@@button run-pylint</vh></v>
<v t="ekr.20180824065751.1"><vh>@@button show-gnx</vh></v>
<v t="ekr.20131121084830.16362"><vh>@@button toggle-debug</vh></v>
<v t="ekr.20150502050609.1"><vh>@button backup</vh></v>
<v t="ekr.20170811173924.1"><vh>@button backup-repo</vh></v>
<v t="ekr.20150413091056.1"><vh>@button check-clones</vh></v>
<v t="ekr.20190406154306.1"><vh>@button open-pyzo</vh></v>
</v>
</v>
<v t="ekr.20140103105930.16446"><vh>@views</vh>
<v t="ekr.20140102162014.16438"><vh>@view added strip_comments keyword arg to two config.getData methods</vh></v>
</v>
<v t="ekr.20140808103117.18035"><vh>@persistence</vh>
<v t="ekr.20140808103117.18038"><vh>@data:@auto ../plugins/qt_main.py</vh>
<v t="ekr.20160425070345.1"><vh>@gnxs</vh></v>
</v>
<v t="ekr.20140808103117.18040"><vh>@data:@auto ../plugins/qt_main.ui</vh>
<v t="ekr.20160425070345.2"><vh>@gnxs</vh></v>
</v>
<v t="ekr.20140808103117.18042"><vh>@data:@auto ../plugins/qt_quicksearch.py</vh>
<v t="ekr.20160420054135.4"><vh>@gnxs</vh></v>
</v>
<v t="ekr.20140808103117.18044"><vh>@data:@auto ../plugins/qt_quicksearch.ui</vh>
<v t="ekr.20160420054135.5"><vh>@gnxs</vh></v>
</v>
<v t="ekr.20150604130353.1"><vh>@data:@auto test/unit_tests.py</vh>
<v t="ekr.20150604130353.2"><vh>@gnxs</vh></v>
</v>
</v>
<v t="ekr.20170427114412.1"><vh>scripts</vh>
<v t="ekr.20170427112302.1"><vh>check leoPy.leo</vh></v>
<v t="ekr.20170428084123.1"><vh>Recursive import script</vh>
<v t="ekr.20170428084123.2"><vh>&lt;&lt; old dir_ settings &gt;&gt;</vh></v>
</v>
<v t="ekr.20181102040815.1"><vh>script: warn about long lines</vh></v>
<v t="ekr.20180816105258.1"><vh>script: diff-branches (one file)</vh></v>
<v t="ekr.20190402091335.1"><vh>script: diff-revs</vh></v>
</v>
</v>
<v t="EKR.20040430162943"><vh>Notes</vh>
<v t="ekr.20190122185223.1"><vh>regex: find all kwargs</vh></v>
<v t="ekr.20170302123956.1"><vh>@file ../doc/leoAttic.txt</vh></v>
<v t="ekr.20031218072017.329"><vh>@file ../doc/leoNotes.txt</vh></v>
<v t="ekr.20100120072650.6089"><vh>@file ../doc/leoProjects.txt</vh></v>
<v t="ekr.20100119205347.6015"><vh>@file ../doc/leoToDo.txt</vh></v>
</v>
<v t="ekr.20031218072017.2406"><vh>Code</vh>
<v t="ekr.20140902032918.18591"><vh> About this file</vh>
<v t="ekr.20140831085423.18639"><vh>About widgets and wrappers</vh></v>
<v t="ekr.20140831085423.18630"><vh>Terminology</vh></v>
<v t="ekr.20140831085423.18631"><vh>Official ivars</vh></v>
</v>
<v t="ekr.20031218072017.2604"><vh>Core classes</vh>
<v t="ekr.20031218072017.2608"><vh>@file leoApp.py</vh></v>
<v t="ekr.20190515070742.1"><vh>@file leoAsciiDoctor.py</vh></v>
<v t="ekr.20141012064706.18389"><vh>@file leoAst.py</vh></v>
<v t="ekr.20150323150718.1"><vh>@file leoAtFile.py</vh></v>
<v t="ekr.20161026193447.1"><vh>@file leoBackground.py</vh></v>
<v t="ekr.20150521115018.1"><vh>@file leoBeautify.py</vh></v>
<v t="ekr.20070227091955.1"><vh>@file leoBridge.py</vh></v>
<v t="ekr.20100208065621.5894"><vh>@file leoCache.py</vh></v>
<v t="ekr.20070317085508.1"><vh>@file leoChapters.py</vh></v>
<v t="ekr.20150605175037.1"><vh>@file leoCheck.py</vh></v>
<v t="ekr.20031218072017.2794"><vh>@file leoColor.py</vh></v>
<v t="ekr.20140827092102.18574"><vh>@file leoColorizer.py</vh></v>
<v t="ekr.20031218072017.2810" descendentVnodeUnknownAttributes="7d7100580c000000302e312e31312e322e352e3771017d71025808000000616e6e6f7461746571037d71042858080000007072696f7269747971054d0f27580a000000707269736574646174657106580a000000323031382d30382d313871077573732e"><vh>@file leoCommands.py</vh></v>
<v t="ekr.20180212072657.2"><vh>@file leoCompare.py</vh></v>
<v t="ekr.20130925160837.11429"><vh>@file leoConfig.py</vh></v>
<v t="ekr.20130302121602.10208"><vh>@file leoDebugger.py</vh></v>
<v t="ekr.20160306114544.1"><vh>@file leoExternalFiles.py</vh></v>
<v t="ekr.20181202062518.1"><vh>@file leoFastRedraw.py</vh></v>
<v t="ekr.20031218072017.3018"><vh>@file leoFileCommands.py</vh></v>
<v t="ekr.20031218072017.3093" descendentVnodeUnknownAttributes="7d71005806000000302e31392e3171017d71025808000000616e6e6f7461746571037d710473732e"><vh>@file leoGlobals.py</vh></v>
<v t="ekr.20150514154159.1"><vh>@file leoHistory.py</vh></v>
<v t="ekr.20031218072017.3206"><vh>@file leoImport.py</vh></v>
<v t="ekr.20120401063816.10072"><vh>@file leoIPython.py</vh></v>
<v t="ekr.20031218072017.3320"><vh>@file leoNodes.py</vh></v>
<v t="ekr.20140821055201.18331"><vh>@file leoPersistence.py</vh></v>
<v t="ekr.20031218072017.3439"><vh>@file leoPlugins.py</vh></v>
<v t="ekr.20150419124739.1"><vh>@file leoPrinting.py</vh></v>
<v t="ekr.20061024060248.1"><vh>@file leoPymacs.py</vh></v>
<v t="ekr.20140810053602.18074"><vh>@file leoQt.py</vh></v>
<v t="ekr.20140526082700.18440"><vh>@file leoRope.py</vh></v>
<v t="ekr.20090502071837.3"><vh>@file leoRst.py</vh></v>
<v t="ekr.20120420054855.14241" descendentVnodeUnknownAttributes="7d7100285805000000302e332e3071017d71022858090000007374725f6374696d657103580c000000313331393439313330362e30710458090000007374725f6d74696d657105580d000000313331393439323330312e3532710658090000007374725f6174696d657107580d000000313331393534393339302e38397108755805000000302e332e3171097d710a2858090000007374725f6374696d65710b580c000000313331393436303438332e30710c58090000007374725f6d74696d65710d580d000000313331393436373033382e3235710e58090000007374725f6174696d65710f580c000000313332303432323637302e397110755805000000302e332e3271117d71122858090000007374725f6374696d657113580c000000313331393436303438332e30711458090000007374725f6d74696d657115580d000000313331393436373035302e3438711658090000007374725f6174696d657117580d000000313331393436373035302e34387118755805000000302e332e3371197d711a2858090000007374725f6374696d65711b580c000000313331393436303438332e30711c58090000007374725f6d74696d65711d580d000000313332303432323639302e3534711e58090000007374725f6174696d65711f580d000000313332303433343235372e33367120755805000000302e332e3471217d71222858090000007374725f6374696d657123580c000000313331393633383634382e30712458090000007374725f6d74696d657125580d000000313331393634313038352e3038712658090000007374725f6174696d657127580c000000313331393634353330362e327128755805000000302e332e3571297d712a2858090000007374725f6374696d65712b580c000000313331393633383634382e30712c58090000007374725f6d74696d65712d580c000000313331393634313131372e39712e58090000007374725f6174696d65712f580d000000313331393634313435352e3937713075752e"><vh>@file leoSessions.py</vh></v>
<v t="ekr.20080708094444.1"><vh>@file leoShadow.py</vh></v>
<v t="ekr.20031218072017.3446"><vh>@file leoTangle.py</vh></v>
<v t="ekr.20180121041003.1"><vh>@file leoTips.py</vh></v>
<v t="ekr.20031218072017.3603"><vh>@file leoUndo.py</vh></v>
<v t="ekr.20131109170017.16504"><vh>@file leoVim.py</vh></v>
</v>
<v t="ekr.20150514035207.1"><vh>Command classes</vh>
<v t="ekr.20150514035236.1"><vh>@file ../commands/abbrevCommands.py</vh></v>
<v t="ekr.20150514035943.1"><vh>@file ../commands/baseCommands.py</vh></v>
<v t="ekr.20150514035559.1"><vh>@file ../commands/bufferCommands.py</vh></v>
<v t="ekr.20161021090740.1"><vh>@file ../commands/checkerCommands.py</vh></v>
<v t="ekr.20171123135539.1"><vh>@file ../commands/commanderEditCommands.py</vh></v>
<v t="ekr.20171123095353.1"><vh>@file ../commands/commanderFileCommands.py</vh></v>
<v t="ekr.20171124072110.1"><vh>@file ../commands/commanderFindCommands.py</vh></v>
<v t="ekr.20171124073126.1"><vh>@file ../commands/commanderHelpCommands.py</vh></v>
<v t="ekr.20171124080430.1"><vh>@file ../commands/commanderOutlineCommands.py</vh></v>
<v t="ekr.20150514040100.1"><vh>@file ../commands/controlCommands.py</vh></v>
<v t="ekr.20160316095222.1"><vh>@file ../commands/convertCommands.py</vh></v>
<v t="ekr.20150514040118.1"><vh>@file ../commands/debugCommands.py</vh></v>
<v t="ekr.20150514035813.1"><vh>@file ../commands/editCommands.py</vh></v>
<v t="ekr.20150514041209.1"><vh>@file ../commands/editFileCommands.py</vh></v>
<v t="ekr.20150624112334.1"><vh>@file ../commands/gotoCommands.py</vh></v>
<v t="ekr.20150514040138.1"><vh>@file ../commands/helpCommands.py</vh></v>
<v t="ekr.20150514040140.1"><vh>@file ../commands/keyCommands.py</vh></v>
<v t="ekr.20150514040142.1"><vh>@file ../commands/killBufferCommands.py</vh></v>
<v t="ekr.20150514040146.1"><vh>@file ../commands/rectangleCommands.py</vh></v>
<v t="ekr.20150514040239.1"><vh>@file ../commands/spellCommands.py</vh></v>
</v>
<v t="ekr.20031218072017.3625"><vh>Gui base classes</vh>
<v t="ekr.20050721093241"><vh>&lt;&lt; about gui classes and gui plugins &gt;&gt;</vh></v>
<v t="ekr.20060123151617"><vh>@file leoFind.py</vh></v>
<v t="ekr.20031218072017.3655"><vh>@file leoFrame.py</vh></v>
<v t="ekr.20031218072017.3719"><vh>@file leoGui.py</vh></v>
<v t="ekr.20061031131434"><vh>@file leoKeys.py</vh></v>
<v t="ekr.20031218072017.3749"><vh>@file leoMenu.py</vh></v>
</v>
<v t="ekr.20110605121601.17862"><vh>Qt gui</vh>
<v t="ekr.20171031111403.1"><vh>Leo Edit Pane</vh>
<v t="tbrown.20171029210211.1"><vh>@file ../plugins/editpane/clicky_splitter.py</vh></v>
<v t="tbrown.20171028115144.6"><vh>@file ../plugins/editpane/editpane.py</vh></v>
<v t="tbrown.20171028115144.5"><vh>@file ../plugins/editpane/leotextedit.py</vh></v>
<v t="tbrown.20171028115144.4"><vh>@file ../plugins/editpane/markdownview.py</vh></v>
<v t="tbrown.20171028115144.3"><vh>@file ../plugins/editpane/pandownview.py</vh></v>
<v t="tbrown.20171028115144.2"><vh>@file ../plugins/editpane/plaintextedit.py</vh></v>
<v t="tbrown.20171028115144.1"><vh>@file ../plugins/editpane/plaintextview.py</vh></v>
<v t="tbrown.20171028115143.3"><vh>@file ../plugins/editpane/vanillascintilla.py</vh></v>
<v t="tbrown.20171028115143.2"><vh>@file ../plugins/editpane/webengineview.py</vh></v>
<v t="tbrown.20171028115143.1"><vh>@file ../plugins/editpane/webkitview.py</vh></v>
<v t="tbrown.20171028115144.8"><vh>@file ../plugins/editpane/__init__.py</vh></v>
<v t="tbrown.20171028115541.1"><vh>@file signal_manager.py</vh></v>
</v>
<v t="ekr.20120419093256.10048"><vh>@file ../plugins/free_layout.py</vh></v>
<v t="ekr.20110605121601.17954"><vh>@file ../plugins/nested_splitter.py</vh></v>
<v t="ekr.20110605121601.17996"><vh>@file ../plugins/qt_commands.py</vh></v>
<v t="ekr.20140907103315.18766"><vh>@file ../plugins/qt_events.py</vh></v>
<v t="ekr.20140907123524.18774"><vh>@file ../plugins/qt_frame.py</vh></v>
<v t="ekr.20140907085654.18699"><vh>@file ../plugins/qt_gui.py</vh></v>
<v t="ekr.20140907103315.18777"><vh>@file ../plugins/qt_idle_time.py</vh></v>
<v t="ekr.20140907123524.18777"><vh>@file ../plugins/qt_quickheadlines.py</vh></v>
<v t="ekr.20140831085423.18598"><vh>@file ../plugins/qt_text.py</vh></v>
<v t="ekr.20140907131341.18707"><vh>@file ../plugins/qt_tree.py</vh></v>
<v t="ekr.20110605121601.18002"><vh>@file ../plugins/qtGui.py</vh></v>
<v t="ekr.20161223152017.1"><vh>@edit ../plugins/qt_quicksearch.py</vh></v>
<v t="ekr.20161223152353.1"><vh>@edit ../plugins/qt_quicksearch_sub.py</vh></v>
</v>
<v t="ekr.20180225010644.1"><vh>Other files</vh>
<v t="ekr.20180225010707.1"><vh>In leo-editor directory</vh>
<v t="maphew.20180224170853.1"><vh>@file ../../setup.py</vh></v>
<v t="ekr.20150304125314.4"><vh>@clean ../../leo_to_html.xsl</vh>
<v t="ekr.20150304130753.5"><vh>&lt;&lt;style&gt;&gt;</vh></v>
<v t="ekr.20150304130753.6"><vh>&lt;&lt;scripts&gt;&gt;</vh></v>
</v>
<v t="ekr.20181009072707.1"><vh>@clean ../../run_travis_unit_tests.py</vh>
<v t="ekr.20181009084156.1"><vh>&lt;&lt; imports &gt;&gt;</vh></v>
<v t="ekr.20181009084245.1"><vh>&lt;&lt; compute path &gt;&gt;</vh></v>
<v t="ekr.20181009084323.1"><vh>&lt;&lt; run tests &gt;&gt;</vh></v>
</v>
<v t="ekr.20181014073705.1"><vh>@file ../../run_pytest_tests.py</vh></v>
<v t="ekr.20150304130753.4"><vh>leo-viewer/leo_to_html.xsl</vh></v>
</v>
<v t="ekr.20180225010913.1"><vh>In leo/core</vh>
<v t="ekr.20031218072017.2605"><vh>@file runLeo.py</vh></v>
</v>
<v t="ekr.20180225010743.1"><vh>In leo/external</vh>
<v t="ekr.20190607124533.1"><vh>@nopylint</vh>
<v t="ekr.20160123142722.1"><vh>@clean ../external/make_stub_files.cfg</vh></v>
<v t="ekr.20180708145905.1"><vh>@clean ../external/py2cs_theory.md</vh>
<v t="ekr.20180708152000.1"><vh>The problem</vh></v>
<v t="ekr.20180708152018.1"><vh>Design</vh></v>
<v t="ekr.20180708145905.6"><vh>Using TokenSync class</vh></v>
<v t="ekr.20180708145905.7"><vh>Summary</vh></v>
</v>
<v t="ekr.20110310091639.14254"><vh>@file ../external/codewise.py</vh></v>
<v t="ekr.20130805134749.12436"><vh>@file ../external/edb.py</vh></v>
<v t="ekr.20120519121124.9919"><vh>@file ../external/leosax.py</vh></v>
<v t="ekr.20170429161422.1"><vh>@file ../external/log_broadcast.py</vh></v>
<v t="ekr.20170429153135.1"><vh>@file ../external/log_listener.py</vh></v>
<v t="ville.20091010232339.6117"><vh>@file ../external/lproto.py</vh></v>
<v t="ekr.20160317054700.1"><vh>@file ../external/make_stub_files.py</vh></v>
<v t="ekr.20160316091132.1"><vh>@file ../external/py2cs.py</vh></v>
<v t="ekr.20170428085201.1"><vh>npyscreen</vh>
<v t="ekr.20170428084207.3"><vh>@file ../external/npyscreen/apNPSApplication.py</vh></v>
<v t="ekr.20170428084207.11"><vh>@file ../external/npyscreen/apNPSApplicationAdvanced.py</vh></v>
<v t="ekr.20170428084207.15"><vh>@file ../external/npyscreen/apNPSApplicationEvents.py</vh></v>
<v t="ekr.20170428084207.29"><vh>@file ../external/npyscreen/apNPSApplicationManaged.py</vh></v>
<v t="ekr.20170428084207.50"><vh>@file ../external/npyscreen/apOptions.py</vh></v>
<v t="ekr.20170428084207.111"><vh>@file ../external/npyscreen/eveventhandler.py</vh></v>
<v t="ekr.20170428084207.121"><vh>@file ../external/npyscreen/fmActionForm.py</vh></v>
<v t="ekr.20170428084207.131"><vh>@file ../external/npyscreen/fmActionFormV2.py</vh></v>
<v t="ekr.20170428084207.153"><vh>@file ../external/npyscreen/fmFileSelector.py</vh></v>
<v t="ekr.20170428084207.174"><vh>@file ../external/npyscreen/fmForm.py</vh></v>
<v t="ekr.20170428084207.223"><vh>@file ../external/npyscreen/fmFormMultiPage.py</vh></v>
<v t="ekr.20170428084207.248"><vh>@file ../external/npyscreen/fmFormMutt.py</vh></v>
<v t="ekr.20170428084207.258"><vh>@file ../external/npyscreen/fmFormMuttActive.py</vh></v>
<v t="ekr.20170428084207.285"><vh>@file ../external/npyscreen/fmFormWithMenus.py</vh></v>
<v t="ekr.20170428084207.303"><vh>@file ../external/npyscreen/fmPopup.py</vh></v>
<v t="ekr.20170428084207.311"><vh>@file ../external/npyscreen/fm_form_edit_loop.py</vh></v>
<v t="ekr.20170428084207.322"><vh>@file ../external/npyscreen/globals.py</vh></v>
<v t="ekr.20170428084207.324"><vh>@file ../external/npyscreen/muMenu.py</vh></v>
<v t="ekr.20170428084207.332"><vh>@file ../external/npyscreen/muNewMenu.py</vh></v>
<v t="ekr.20170428084207.351"><vh>@file ../external/npyscreen/npysGlobalOptions.py</vh></v>
<v t="ekr.20170428084207.353"><vh>@file ../external/npyscreen/npysNPSFilteredData.py</vh></v>
<v t="ekr.20170428084207.364"><vh>@file ../external/npyscreen/npyspmfuncs.py</vh></v>
<v t="ekr.20170428084207.370"><vh>@file ../external/npyscreen/npyssafewrapper.py</vh></v>
<v t="ekr.20170428084207.377"><vh>@file ../external/npyscreen/npysThemeManagers.py</vh></v>
<v t="ekr.20170428084207.390"><vh>@file ../external/npyscreen/npysThemes.py</vh></v>
<v t="ekr.20170428084207.399"><vh>@file ../external/npyscreen/npysTree.py</vh></v>
<v t="ekr.20170428084207.422"><vh>@file ../external/npyscreen/proto_fm_screen_area.py</vh></v>
<v t="ekr.20170428084207.434"><vh>@file ../external/npyscreen/stdfmemail.py</vh></v>
<v t="ekr.20170428084207.464"><vh>@file ../external/npyscreen/utilNotify.py</vh></v>
<v t="ekr.20170428084207.477"><vh>@file ../external/npyscreen/util_viewhelp.py</vh></v>
<v t="ekr.20170428084207.480"><vh>@file ../external/npyscreen/wgannotatetextbox.py</vh></v>
<v t="ekr.20170428084207.494"><vh>@file ../external/npyscreen/wgautocomplete.py</vh></v>
<v t="ekr.20170428084207.503"><vh>@file ../external/npyscreen/wgboxwidget.py</vh></v>
<v t="ekr.20170428084207.524"><vh>@file ../external/npyscreen/wgbutton.py</vh></v>
<v t="ekr.20170428084207.536"><vh>@file ../external/npyscreen/wgcheckbox.py</vh></v>
<v t="ekr.20170428084207.561"><vh>@file ../external/npyscreen/wgcombobox.py</vh></v>
<v t="ekr.20170428084207.575"><vh>@file ../external/npyscreen/wgdatecombo.py</vh></v>
<v t="ekr.20170428084207.586"><vh>@file ../external/npyscreen/wgeditmultiline.py</vh></v>
<v t="ekr.20170428084207.611"><vh>@file ../external/npyscreen/wgfilenamecombo.py</vh></v>
<v t="ekr.20170428084207.618"><vh>@file ../external/npyscreen/wgFormControlCheckbox.py</vh></v>
<v t="ekr.20170428084208.1"><vh>@file ../external/npyscreen/wggrid.py</vh></v>
<v t="ekr.20170428084208.36"><vh>@file ../external/npyscreen/wggridcoltitles.py</vh></v>
<v t="ekr.20170428084208.43"><vh>@file ../external/npyscreen/wgmonthbox.py</vh></v>
<v t="ekr.20170428084208.68"><vh>@file ../external/npyscreen/wgmultiline.py</vh></v>
<v t="ekr.20170428084208.157"><vh>@file ../external/npyscreen/wgmultilineeditable.py</vh></v>
<v t="ekr.20170428084208.173"><vh>@file ../external/npyscreen/wgmultilinetree.py</vh></v>
<v t="ekr.20170428084208.213"><vh>@file ../external/npyscreen/wgmultilinetreeselectable.py</vh></v>
<v t="ekr.20170428084208.225"><vh>@file ../external/npyscreen/wgmultiselect.py</vh></v>
<v t="ekr.20170428084208.245"><vh>@file ../external/npyscreen/wgmultiselecttree.py</vh></v>
<v t="ekr.20170428084208.253"><vh>@file ../external/npyscreen/wgNMenuDisplay.py</vh></v>
<v t="ekr.20170428084208.285"><vh>@file ../external/npyscreen/wgpassword.py</vh></v>
<v t="ekr.20170428084208.290"><vh>@file ../external/npyscreen/wgselectone.py</vh></v>
<v t="ekr.20170428084208.297"><vh>@file ../external/npyscreen/wgslider.py</vh></v>
<v t="ekr.20170428084208.318"><vh>@file ../external/npyscreen/wgtextbox.py</vh></v>
<v t="ekr.20170428084208.354"><vh>@file ../external/npyscreen/wgtextboxunicode.py</vh></v>
<v t="ekr.20170428084208.359"><vh>@file ../external/npyscreen/wgtextbox_controlchrs.py</vh></v>
<v t="ekr.20170428084208.366"><vh>@file ../external/npyscreen/wgtexttokens.py</vh></v>
<v t="ekr.20170428084208.381"><vh>@file ../external/npyscreen/wgtitlefield.py</vh></v>
<v t="ekr.20170428084208.398"><vh>@file ../external/npyscreen/wgwidget.py</vh></v>
<v t="ekr.20170428084208.436"><vh>@file ../external/npyscreen/wgwidget_proto.py</vh></v>
<v t="ekr.20170428084208.443"><vh>@@file ../external/npyscreen/__init__.py</vh>
<v t="ekr.20170428084208.444"><vh>Declarations</vh></v>
</v>
</v>
</v>
</v>
<v t="ekr.20180225010850.1"><vh>In leo/modes</vh>
<v t="ekr.20150326145530.1"><vh>@clean ../modes/forth.py</vh>
<v t="ekr.20150326145530.2"><vh>&lt;&lt; define mode rules &gt;&gt;</vh></v>
<v t="ekr.20150326145530.3"><vh>&lt;&lt; define mode data &gt;&gt;</vh></v>
<v t="ekr.20150326145530.4"><vh>&lt;&lt; define extendForth class &gt;&gt;</vh>
<v t="ekr.20150326145530.5"><vh>ctor</vh></v>
<v t="ekr.20150326145530.6"><vh>init &amp; helper</vh>
<v t="ekr.20150326145530.7"><vh>splitList</vh></v>
</v>
<v t="ekr.20150326145530.8"><vh>createBracketRules &amp; helper</vh></v>
<v t="ekr.20150326145530.9"><vh>createDefiningWordRules &amp; helper</vh></v>
<v t="ekr.20150326145530.10"><vh>createKeywords</vh></v>
<v t="ekr.20150326145530.11"><vh>createStringRule</vh></v>
<v t="ekr.20150326145530.12"><vh>extendRulesDict</vh></v>
</v>
</v>
</v>
<v t="ekr.20181013081645.1"><vh>In leo/core/test</vh></v>
</v>
<v t="ekr.20080730161153.8"><vh>Testing</vh>
<v t="ekr.20160517182239.1"><vh>@file ../../flake8-leo.py</vh></v>
<v t="ekr.20160518000549.1"><vh>@file ../../pyflakes-leo.py</vh></v>
<v t="ekr.20100221142603.5638"><vh>@file ../../pylint-leo.py</vh></v>
<v t="ekr.20170805060844.1"><vh>@file ../test/leo-bridge-test.py</vh></v>
<v t="ekr.20080730161153.2"><vh>@file leoBridgeTest.py</vh></v>
<v t="ekr.20080730161153.5"><vh>@file leoDynamicTest.py</vh></v>
<v t="ekr.20051104075904"><vh>@file leoTest.py</vh></v>
</v>
<v t="ekr.20090802181029.5988"><vh>Version</vh>
<v t="ekr.20090717092906.12765"><vh>@file leoVersion.py</vh></v>
</v>
</v>
</vnodes>
<tnodes>
<t tx="EKR.20040430162943">@nosearch
</t>
<t tx="ekr.20031218072017.2406" _bklnk="7d71002858010000007971014b0058010000007871024b00580400000074797065710358080000006e6f646552656374710458050000006c696e6b7371055d7106752e"># This file contains almost all of Leo's sources.

# See the "About this file" node for important notes.
@language python
</t>
<t tx="ekr.20031218072017.2604"></t>
<t tx="ekr.20031218072017.3625">&lt;&lt; about gui classes and gui plugins &gt;&gt;
</t>
<t tx="ekr.20050721093241">@nobeautify
@nocolor

The following are notes for anyone who is interested in writing
alternate gui's for Leo.

Rule 1: Leo's core is (or should be) free of gui-specific code.

Core code calls 'gui wrapper methods' defined by gui-specific classes.
The base classes for these gui-specific classes are in the node
Code--&gt;Gui Base classes.

Rule 2: Gui-specific code should be localized.

The @file nodes contained in the node 'Code--&gt;Gui Tkinter classes' in
leoPy.leo contain all of Leo's Tkinter-specific code. Gui plugins
would typically put all similar code in a single file.

Rule 3: Gui-specific code can call gui methods directly.

There are no restrictions about the code in the gui-specific classes.

Rule 4: Gui-specific classes must implement the 'gui wrapper methods'
specified in the gui base classes.

This is the way that gui-specific classes provide gui-specific
services to Leo's core.

The alternative would be to implement all gui-specific commands
directly in the gui-specific code.  But this would be much more work
than needed.  For example, only a few gui-specific wrappers are needed
to implement all commands that deal with body text.  Implementing each
of these commands 'from scratch' would duplicate a lot of code
unnecessarily.

Using the gui wrapper methods is a bit messy for two reasons:

1. It requires defining enough wrappers (both in the base gui classes
   and subclasses) so that all gui-specific services needed by Leo's
   core are available.  Adding a wrapper to a gui base class involves
   adding it to all gui-specific subclasses.  It's easy to forget to
   add a wrapper.  The gui base class defines all wrappers as a
   function that just calls oops().  This prints a warning that the
   wrapper should be defined in a subclass.

2. The original wrappers assumed Tkinter-like indices.  Wrappers that
   were defined later assume Python indices (see Rule 5 below).  The
   newer style wrappers that use Python indices have 'Python' in their
   name.  Having two sets of wrappers is one of the ugliest features
   of the present code.  I find it hard to remember which wrappers
   exist and what exactly they do :-)

Rule 5: Leo's core should use Python indices, not gui-specific
indices.

Leo's core mostly follows this rule: there may be a few exceptions.

A Python index is an int that runs from 0 (beginning of text) to
len(s) (end of text s).  That is, there are exactly len(s) + 1 valid
indices.  In contrast, Tkinter indices run from "1.0" to "x.y" where
text s has x lines and where the length of the last line is y-1.

Two (recently written) functions in leoGlobals.py support conversions
from Python indices to the row/column indices used by Tkinter.

- g.convertPythonIndexToRowCol converts a Python index to a row/column
  index used by Tkinter.

- g.convertRowColToPythonIndex does the reverse.

Important: the first Tkinter index is '1.0', not '0.0', but the row
returned by g.convertPythonIndexToRowCol is zero based, so the code
that actually creates Tkinter indices from row/col must add 1 to the
row.  Similar remarks apply when going in the reverse direction.
</t>
<t tx="ekr.20051031040240"></t>
<t tx="ekr.20080412053100.5">@language rest
</t>
<t tx="ekr.20080730161153.8"></t>
<t tx="ekr.20090802181029.5988"></t>
<t tx="ekr.20110605121601.17862"># These files are true plugins, but it is more convenient to put them here.
</t>
<t tx="ekr.20131111060930.18010"># Standard bindings...
# run-selected-unit-tests-externally = Alt-4 
# run-marked-unit-tests-externally = Alt-5
# run-marked-unit-tests-locally = Alt-6
run-selected-unit-tests-locally = Alt-4
do-nothing = Alt-5
run-marked-unit-tests-locally = Alt-6
</t>
<t tx="ekr.20131121084830.16362">@language python

# Toggle the settings.
g.app.debug_app = not g.app.debug_app
g.app.debug_widgets = not g.app.debug_widgets
# Report the new settings.
print('g.app.debug_app: %s' % g.app.debug_app)
print('g.app.debug_widgets: %s' % g.app.debug_widgets)
</t>
<t tx="ekr.20140102162014.16438">unl: Code--&gt;Core classes--&gt;@file leoConfig.py--&gt;class LocalConfigManager--&gt;c.config.Getters--&gt;c.config.Getters--&gt;c.config.getData
unl: Code--&gt;Core classes--&gt;@file leoConfig.py--&gt;class GlobalConfigManager--&gt;gcm.Getters...--&gt;gcm.getData &amp; getOutlineData
unl: Code--&gt;Core classes--&gt;@file leoConfig.py--&gt;&lt;&lt; class ParserBaseClass &gt;&gt;--&gt;kind handlers (ParserBaseClass)--&gt;doData
@language rest
The parser for @data nodes, doData, no longer strips *anything*.</t>
<t tx="ekr.20140103105930.16446"></t>
<t tx="ekr.20140808103117.18035"></t>
<t tx="ekr.20140808103117.18038">gnx: ekr.20110605121601.18698
</t>
<t tx="ekr.20140808103117.18040">gnx: ekr.20110605121601.18703
</t>
<t tx="ekr.20140808103117.18042">gnx: ekr.20110605121601.18704
</t>
<t tx="ekr.20140808103117.18044">gnx: ekr.20110605121601.18709
</t>
<t tx="ekr.20140831085423.18630">This outline contains all of Leo's core source code.

Leo's code uses the following conventions throughout:

c:  a commander.
ch: a character.
d:  a dialog or a dict.
f:  an open file.
fn: a file name.
g:  the leoGlobals module.
i, j, k: indices into a string.
p:  a Position.
s:  a string.
t:  a text widget.
u:  an undoer.
w:  a gui widget.
v:  a Vnode
z:  a local temp.

In more limited contexts, the following conventions apply:

si:     a g.ShortcutInfo object.
ks:     a g.KeyStroke object
stroke: a KeyStroke object.

btw:    leoFrame.BaseTextWrapper
stw:    leoFrame.StringTextWrapper

bqtw:   qt_text.BaseQTextWrapper
lqtb:   qt_text.LeoQTextBrowser
qhlw:   qt_text.QHeadlineWrapper
qmbw:   qt_text.QMinibufferWrapper
qlew:   qt_text.QLineEditWrapper
qsciw:  qt_text.QScintiallaWrapper
qtew:   qt_text.QTextEditWrapper</t>
<t tx="ekr.20140831085423.18631">The following 'official' ivars will always exist:

c.frame                 The frame containing the log,body,tree, etc.
c.frame.body            The body pane.
c.frame.body.widget     The gui widget for the body pane.
c.frame.body.wrapper    The high level interface for the body widget.
c.frame.iconBar         The icon bar.
c.frame.log             The log pane.
c.frame.log.widget      The gui widget for the log pane.
c.frame.log.wrapper     The high-level inteface for the log pane.
c.frame.tree            The tree pane.

The following were official ivars that no longer exist:

c.frame.body.bodyCtrl   Use c.frame.body.wrapper instead.
c.frame.log.logCtrl     Use c.frame.log.wrapper instead.
</t>
<t tx="ekr.20140831085423.18639">Here is what you *must know* to understand Leo's core:

1. A **widget** is an actual Qt widget.

Leo's core seldom accesses widgets directly.  Instead...

2. A **wrapper class** defines a standard api that hides the details
   of the underlying gui **text** widgets.

Leo's core uses this api almost exclusively. That is, Leo's core code treats wrappers *as if* they were only text widgets there are!

There is, however, a back door for (hopefully rare!) special cases. All wrapper classes define an official ``widget`` ivar, so core or plugin code can gain access to the real Qt widget using wrapper.widget. Searching for wrapper.widget will find all gui-dependent snippets of code in Leo's core.
</t>
<t tx="ekr.20140902032918.18591">@
@language rest
@wrap

Leo uses a model/view/controller architecture.

- Controller: The Commands class and its helpers in leoCommands.py and leoEditCommands.py.

- Model: The VNode and Position classes in leoNodes.py.

- View: The gui-independent base classes are in the node "Gui Base Classes". The Qt-Specific subclasses are in the node "Qt gui".

**Important**: The general organization of these classes have changed hardly at all in Leo's 20+ year history.  The reason is that what each class does is fairly obvious.  How the gets the job done may have changed drastically, but *that's an internal implementation detail of the class itself*.  This is the crucial design principle that allows Leo's code to remain stable.  *Classes do not know or meddle in the internal details of other classes*.  As a result, nobody, including EKR, needs to remember internal details.
@c
</t>
<t tx="ekr.20140902155015.18674"></t>
<t tx="ekr.20140916101314.19538">The default language if no @language or @comment is in effect.

Valid values are (case is ignored):

actionscript,c,csharp,css,cweb,elisp,html,java,latex,
pascal,perl,perlpod,php,plain,plsql,python,rapidq,rebol,shell,tcltk.</t>
<t tx="ekr.20140920064112.17946"></t>
<t tx="ekr.20150304125314.4">@tabwidth -2
@killbeautify
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

&lt;xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/&gt;

&lt;!-- The default setting. Not needed unless there is a strip-space element. --&gt;
  &lt;!-- &lt;xsl:preserve-space elements='leo_file nodes t'/&gt; --&gt;

&lt;xsl:template match ='leo_file'&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;!--
    &lt;link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/styles/default.min.css"&gt;
    &lt;script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/8.9.1/highlight.min.js"&gt;&lt;/script&gt;
    --&gt;
    &lt;&lt;style&gt;&gt;
    &lt;&lt;scripts&gt;&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;xsl:apply-templates select='tnodes'/&gt;
    &lt;div class="outlinepane"&gt;
      &lt;!-- &lt;h4&gt;Outline Pane&lt;/h4&gt; --&gt;
      &lt;xsl:apply-templates select='vnodes'/&gt;
    &lt;/div&gt;
    &lt;div class="bodypane"&gt;
      &lt;!-- &lt;h4&gt;Body Pane&lt;/h4&gt; --&gt;
      &lt;pre class="body-text"&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;
&lt;/xsl:template&gt;

&lt;xsl:template match = 'tnodes'&gt;
&lt;div class="tnodes"&gt;
  &lt;xsl:for-each select = 't'&gt;
    &lt;div class="tnode"&gt;
      &lt;xsl:attribute name="id"&gt;&lt;xsl:value-of select='@tx'/&gt;&lt;/xsl:attribute&gt;
      &lt;xsl:value-of select='.'/&gt;
    &lt;/div&gt;
  &lt;/xsl:for-each&gt;
&lt;/div&gt;
&lt;/xsl:template&gt;

&lt;xsl:template match = 'vnodes'&gt;
  &lt;xsl:for-each select = 'v'&gt;
    &lt;xsl:apply-templates select ='.'/&gt;
  &lt;/xsl:for-each&gt;
&lt;/xsl:template&gt;

&lt;xsl:template match='v'&gt;
  &lt;div class="node"&gt;
    &lt;xsl:attribute name="id"&gt;&lt;xsl:value-of select='@t'/&gt;&lt;/xsl:attribute&gt;
    &lt;xsl:choose&gt;
      &lt;xsl:when test ='./v' &gt;
        &lt;xsl:attribute name="has-children"&gt;1&lt;/xsl:attribute&gt;
        &lt;h1&gt;+ &lt;xsl:value-of select='vh'/&gt;&lt;/h1&gt;
        &lt;xsl:apply-templates select = 'v'/&gt;
      &lt;/xsl:when&gt;
      &lt;xsl:when test ='vh' &gt;
        &lt;h1&gt;- &lt;xsl:value-of select='vh'/&gt;&lt;/h1&gt;
      &lt;/xsl:when&gt;
      &lt;!--
      &lt;xsl:otherwise&gt;
        &lt;h1&gt;- &lt;xsl:value-of select='vh'/&gt;&lt;/h1&gt;
      &lt;/xsl:otherwise&gt;
      --&gt;
    &lt;/xsl:choose&gt;
  &lt;/div&gt;
&lt;/xsl:template&gt;

&lt;/xsl:stylesheet&gt;
</t>
<t tx="ekr.20150304130753.4">&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"&gt;

&lt;xsl:output method="html" version="1.0" encoding="UTF-8" indent="yes"/&gt;

&lt;!-- The default setting. Not needed unless there is a strip-space element. --&gt;
  &lt;!-- &lt;xsl:preserve-space elements='leo_file nodes t'/&gt; --&gt;

&lt;xsl:template match ='leo_file'&gt;
&lt;html&gt;
  &lt;head&gt;
    &lt;&lt;style&gt;&gt;
    &lt;&lt;scripts&gt;&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;xsl:apply-templates select='tnodes'/&gt;
    &lt;div class="outlinepane"&gt;
      &lt;xsl:apply-templates select='vnodes'/&gt;
    &lt;/div&gt;
    &lt;div class="bodypane"&gt;
      &lt;h1&gt;Body Pane&lt;/h1&gt;
      &lt;pre class="body-text"&gt;body&lt;/pre&gt;
    &lt;/div&gt;
  &lt;/body&gt;
&lt;/html&gt;
&lt;/xsl:template&gt;

&lt;xsl:template match = 'tnodes'&gt;
&lt;div class="tnodes"&gt;
  &lt;xsl:for-each select = 't'&gt;
    &lt;div class="tnode"&gt;
      &lt;xsl:attribute name="id"&gt;&lt;xsl:value-of select='@tx'/&gt;&lt;/xsl:attribute&gt;
      &lt;xsl:value-of select='.'/&gt;
    &lt;/div&gt;
  &lt;/xsl:for-each&gt;
&lt;/div&gt;
&lt;/xsl:template&gt;

&lt;xsl:template match = 'vnodes'&gt;
  &lt;xsl:for-each select = 'v'&gt;
    &lt;xsl:apply-templates select ='.'/&gt;
  &lt;/xsl:for-each&gt;
&lt;/xsl:template&gt;

&lt;xsl:template match='v'&gt;
  &lt;div class="node"&gt;
    &lt;xsl:attribute name="id"&gt;&lt;xsl:value-of select='@t'/&gt;&lt;/xsl:attribute&gt;
    &lt;h1&gt;&lt;xsl:value-of select='vh'/&gt;&lt;/h1&gt;
    &lt;xsl:if test ='./v' &gt;
      &lt;xsl:apply-templates select = 'v'/&gt;
    &lt;/xsl:if&gt;
  &lt;/div&gt;
&lt;/xsl:template&gt;

&lt;/xsl:stylesheet&gt;
</t>
<t tx="ekr.20150304130753.5">&lt;style&gt;
    /* pre { background:#FFE7C6; } */
    /* Must use h1 for nodes: see below. */
    h1 {
      font-size: 12pt;
      font-style: normal;
      font-weight: normal;
    }
    div.outlinepane {
      position: absolute;
      background: #ffffec; /* Leo yellow */
      top: 10px;
      height: 300px;
      width: 700px;
      overflow: scroll;
      line-height: 0.8;

    }
    div.bodypane {
      position: absolute;
      top: 310px;
      height: 300px;
      width: 700px;
      overflow: scroll;
    }
    div.tnode {
        visibility: hidden;
        height: 0;
    }
    div.node {
        position: relative;
        left: 20px;
    }
    div.node[has-children] &gt; h1 {
        &lt;!-- works --&gt;
        &lt;!-- background: red; --&gt;
    }
&lt;/style&gt;
</t>
<t tx="ekr.20150304130753.6">@language javascript

&lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"&gt;&lt;/script&gt;
&lt;script&gt;

  $(document).ready(function(){
    if (true) {
        // Toggle all but top-level nodes.
        // This requires an indication
        $(".node").toggle()
        $(".outlinepane").children(".node").toggle()
    } else {
        // Toggle all second-level nodes.
        // Safer, until we can see which nodes have children.
        $(".outlinepane").children(".node").children(".node").toggle()
    }
    $("h1").click(function(){
      $(this).parent().children("div.node").toggle();
      // The parent div's id is v.x.
      // Find the tnode div whose id is t.x.
      console.clear();
      parent_id=$(this).parent().attr("id");
      if (parent_id) {
        target=$(this).parent().attr("id").substring(2);
          console.log("clicked:"+$(this).text())
          // console.log("parent:"+$(this).parent())
          // console.log("target:"+target)
        $(".tnode").each(function(){
          console.log($(this).attr("id"))
          target2=$(this).attr("id").substring(2);
          if (target === target2) {
            console.log("found:"+target2)
            // $("pre.body-text").text($(this).text());
            $("code").text($(this).text());
          };
        }); // end .each.
      };
    });
  });
@language html
&lt;/script&gt;
</t>
<t tx="ekr.20150326145530.1"># Hand-written Leo colorizer control file for forth mode.
# This file is in the public domain.
@killbeautify
import leo.core.leoGlobals as g
&lt;&lt; define mode rules &gt;&gt;
&lt;&lt; define mode data &gt;&gt;
&lt;&lt; define extendForth class &gt;&gt;
e = extendForth()

def pre_init_mode(c):
    e.c = c
    e.init()
    e.createKeywords()
    e.createBracketRules()
    e.createDefiningWordRules()
</t>
<t tx="ekr.20150326145530.10">def createKeywords(self):
    '''Create the mode keyword table and
    entries in the rulesDict for the forth_keyword_rule'''
    # global forth_main_keywords_dict
    # global forth_keyword_rule
    table = (
        (self.keywords, 'keyword1'),
      # (self.definingwords,    'keyword2'), # Done in createDefiningWordRules.
        (self.boldwords, 'keyword3'),
        (self.bolditalicwords, 'keyword4'),
        (self.italicwords, 'keyword5'),
        (self.stringwords, 'string'),
    )
    d = forth_main_keywords_dict
    for keywordList, kind in table:
        for z in keywordList:
            # Create the entry in the keyword table.
            if kind == 'string':
                func = self.createStringRule(d, z)
            else:
                func = forth_keyword_rule
            # Always make the entry.
            d[z] = kind
            self.extendRulesDict(ch=z[0], func=func)
</t>
<t tx="ekr.20150326145530.11">def createStringRule(self, d, pair):
    '''Create an entry in d for a string keyword.'''
    aList = pair.split(' ')
    if len(aList) != 2:
        g.trace('can not happen: expecting pair of forth strings:', pair)
        return None
    begin, end = aList

    def forth_string_word_rule(colorer, s, i):
        return colorer.match_span(s, i, kind="literal1", begin=begin.strip(), end=end.strip(),
            at_line_start=False, at_whitespace_end=False, at_word_start=True, # Require word.
            delegate="", exclude_match=False,
            no_escape=False, no_line_break=False, no_word_break=False) # Don't require ending word.

    return forth_string_word_rule
</t>
<t tx="ekr.20150326145530.12">def extendRulesDict(self, ch, func):
    global rulesDict
    # Extend the rulesDict entry for the first character of z.
    aList = rulesDict.get(ch, [])
    if func not in aList:
        aList.append(func)
        rulesDict[ch] = aList
</t>
<t tx="ekr.20150326145530.2"># Rules for forth_main ruleset.

def forth_block_comment_rule(colorer, s, i):
    return colorer.match_span(s, i, kind="comment2", begin="(", end=")",
        at_line_start=False, at_whitespace_end=False, at_word_start=True, # Require word.
        delegate="", exclude_match=False,
        no_escape=False, no_line_break=False, no_word_break=False)

def forth_comment_rule(colorer, s, i):
    return colorer.match_eol_span(s, i, kind="comment1", seq="\\",
        at_line_start=False, at_whitespace_end=False, at_word_start=True, # Require word
        delegate="", exclude_match=False)

def forth_keyword_rule(colorer, s, i):
    return colorer.match_keywords(s, i)

def forth_string_rule(colorer, s, i):
    return colorer.match_span(s, i, kind="literal1", begin="\"", end="\"",
        at_line_start=False, at_whitespace_end=False, at_word_start=True, # Require word
        delegate="", exclude_match=False,
        no_escape=False, no_line_break=False, no_word_break=False)
# ==========================

if 0:

    def forth_rule0(colorer, s, i):
        return colorer.match_eol_span(s, i, kind="comment1", seq="#",
            at_line_start=False, at_whitespace_end=False, at_word_start=False,
            delegate="", exclude_match=False)

    def forth_rule1(colorer, s, i):
        return colorer.match_span(s, i, kind="literal2", begin="\"\"\"", end="\"\"\"",
            at_line_start=False, at_whitespace_end=False, at_word_start=False,
            delegate="", exclude_match=False,
            no_escape=False, no_line_break=False, no_word_break=False)

    def forth_rule2(colorer, s, i):
        return colorer.match_span(s, i, kind="literal2", begin="'''", end="'''",
            at_line_start=False, at_whitespace_end=False, at_word_start=False,
            delegate="", exclude_match=False,
            no_escape=False, no_line_break=False, no_word_break=False)

    def forth_rule3(colorer, s, i):
        return colorer.match_span(s, i, kind="literal1", begin="\"", end="\"",
            at_line_start=False, at_whitespace_end=False, at_word_start=False,
            delegate="", exclude_match=False,
            no_escape=False, no_line_break=False, no_word_break=False)

    def forth_rule4(colorer, s, i):
        return colorer.match_span(s, i, kind="literal1", begin="'", end="'",
            at_line_start=False, at_whitespace_end=False, at_word_start=False,
            delegate="", exclude_match=False,
            no_escape=False, no_line_break=False, no_word_break=False)

    def forth_rule5(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="=",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule6(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="!",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule7(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="&gt;=",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule8(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="&lt;=",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule9(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="+",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule10(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="-",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule11(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="/",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule12(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="*",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule13(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="&gt;",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule14(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="&lt;",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule15(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="%",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule16(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="&amp;",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule17(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="|",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule18(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="^",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule19(colorer, s, i):
        return colorer.match_seq(s, i, kind="operator", seq="~",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, delegate="")

    def forth_rule20(colorer, s, i):
        return colorer.match_mark_previous(s, i, kind="function", pattern="(",
            at_line_start=False, at_whitespace_end=False, at_word_start=False, exclude_match=True)

    def forth_rule21(colorer, s, i):
        return colorer.match_keywords(s, i)
</t>
<t tx="ekr.20150326145530.3"># Properties for forth mode.
properties = {
    # "indentNextLines": "\\s*[^#]{3,}:\\s*(#.*)?",
    "lineComment": "\\",
}
# Attributes dict for forth_main ruleset.
forth_main_attributes_dict = {
    "default": "null",
    "digit_re": "",
    # "escape": "\\",
    "highlight_digits": "false",
    "ignore_case": "false",
    "no_word_sep": "",
}
# Dictionary of attributes dictionaries for forth mode.
attributesDictDict = {
    "forth_main": forth_main_attributes_dict,
}
# Keywords dict for forth_main ruleset.
forth_main_keywords_dict = {} # Created by extendForth class.
# Dictionary of keywords dictionaries for forth mode.
keywordsDictDict = {
    "forth_main": forth_main_keywords_dict,
}
# Rules dict for forth_main ruleset.
# This is extended by extendForth.
rulesDict = {
    '(': [forth_block_comment_rule],
    '\\': [forth_comment_rule],
    '"': [forth_string_rule],
}
# x.rulesDictDict for forth mode.
rulesDictDict = {
    "forth_main": rulesDict,
}
# Import dict for forth mode.
importDict = {}
</t>
<t tx="ekr.20150326145530.4">class extendForth:
    '''A helper class to extend the mode tables from @data forth-x settings.'''
    @others
</t>
<t tx="ekr.20150326145530.5">def __init__(self):
    self.c = None # set by pre_init_mode function.
    #
    # Default forth keywords: extended by @data forth-words
    # Forth words to be rendered in boldface: extended by @data forth-bold-words
    self.boldwords = []
    #
    # Forth bold-italics words: extended by @data forth-bold-italic-words
    # Note: on some boxen, bold italics may show in plain bold.
    self.bolditalicwords = []
    #
    # Forth words that define brackets: extended by @data forth-delimiter-pairs
    self.brackets = [] # Helper: a list of tuples.
    self.brackets1 = []
    self.brackets2 = []
    #
    # Words which define other words: extended by forth-defwords
    self.definingwords = []
    #
    # Forth words to be rendered in italics: extended by forth-italic-words
    self.italicwords = []
    #
    # Default keywords: extended by @data forth-keywords
    self.keywords = []
        # "variable", "constant", "code", "end-code",
        # "dup", "2dup", "swap", "2swap", "drop", "2drop",
        # "r&gt;", "&gt;r", "2r&gt;", "2&gt;r",
        # "if", "else", "then",
        # "begin", "again", "until", "while", "repeat",
        # "v-for", "v-next", "exit",
        # "meta", "host", "target", "picasm", "macro",
        # "needs", "include",
        # "'", "[']",
        # # ":", # Now a defining word.
        # ";",
        # "@", "!", ",", "1+", "+", "-",
        # "&lt;", "&lt;=", "=", "&gt;=", "&gt;",
        # "invert", "and", "or",
    #
    # Forth words which start strings: extended by @data forth-string-word-pairs
    self.stringwords = []
    self.stringwords1 = []
    self.stringwords2 = []
    self.verbose = False # True: tell when extending forth words.

</t>
<t tx="ekr.20150326145530.6">def init(self):
    '''Set our ivars from settings.'''
    c = self.c
    assert(c)
    table = (
        (self.definingwords, "forth-defwords"),
        (self.brackets, "forth-delimiter-pairs"),
        (self.keywords, "forth-words"),
        (self.stringwords, "forth-string-word-pairs"),
        (self.boldwords, "forth-bold-words"),
        (self.bolditalicwords, "forth-bold-italic-words"),
        (self.italicwords, "forth-italic-words"),
    )
    # Add entries from @data nodes (if they exist) to the corresponding lists.
    for(ivarList, setting) in table:
        extras = []
        aList = c.config.getData(setting)
        if aList:
            for s in aList:
                s = s.strip()
                if s and s[0] != '\\':
                    extras.append(s)
            if extras:
                if self.verbose:
                    if not g.app.unitTesting and not g.app.batchMode:
                        g.pr("Found extra forth: %s" % " ".join(extras))
                ivarList.extend(extras)
    # Create brackets1/2 and stringwords1/2 lists.
    table2 = (
        ("brackets", "@data forth-delimiter-pairs"),
        ("stringwords", "@data forth-string-word-pairs"),
    )
    for(ivar, setting) in table2:
        self.splitList(ivar, setting)
</t>
<t tx="ekr.20150326145530.7">def splitList(self, ivar, setting):
    '''Process lines containing pairs of entries
    in a list whose *name* is ivar.
    Put the results in ivars whose names are ivar1 and ivar2.'''
    result1 = []; result2 = []
    aList = getattr(self, ivar)
    # Look for pairs.  Comments have already been removed.
    for s in aList:
        pair = s.split(' ')
        if len(pair) == 2 and pair[0].strip() and pair[1].strip():
            result1.append(pair[0].strip())
            result2.append(pair[1].strip())
        else:
            g.es_print('%s: ignoring line: %s' % (setting, s))
    # Set the ivars.
    name1 = '%s1' % ivar
    name2 = '%s2' % ivar
    setattr(self, name1, result1)
    setattr(self, name2, result2)
</t>
<t tx="ekr.20150326145530.8">def createBracketRules(self):
    for z in self.brackets1:
        func = self.createBracketRule(z)
        self.extendRulesDict(ch=z[0], func=func)

def createBracketRule(self, begin):
    i = self.brackets1.index(begin)
    end = self.brackets2[i]

    def forth_bracket_rule(colorer, s, i):
        return colorer.match_span(s, i, kind="bracketRange", begin=begin, end=end,
            at_line_start=False, at_whitespace_end=False, at_word_start=True, # Require word.
            delegate="", exclude_match=False,
            no_escape=False, no_line_break=False, no_word_break=True) # Require word.

    return forth_bracket_rule
</t>
<t tx="ekr.20150326145530.9">def createDefiningWordRules(self):
    for z in self.definingwords:
        func = self.createDefiningWordRule(z)
        self.extendRulesDict(ch=z[0], func=func)

def createDefiningWordRule(self, word):

    def forth_defining_word_rule(colorer, s, i):

        return colorer.match_word_and_regexp(s, i,
            kind1="keyword2", # defining word
            word=word,
            kind2="keyword3", # bold
            pattern=r'(\s)*(\S)+',
            at_line_start=False, at_whitespace_end=False, at_word_start=False,
            exclude_match=False)

    return forth_defining_word_rule
</t>
<t tx="ekr.20150413091056.1">'''Warn if leoProjects.txt or leoToDo.txt contain any clones.'''

clones,nodes,seen = 0,0,set()
table = (
  '@file ../doc/leoProjects.txt',
  '@file ../doc/leoToDo.txt',
)

def check_clone(c,p0,root):
    '''Warn if p appears in any @&lt;file&gt; node outside of root's tree.'''
    global nodes,seen
    v = p0.v
    for p in c.all_positions():
        nodes += 1
        if p.v == v:
            # Check *all* ancestors, not just the nearest one.
            for parent in p.self_and_parents():
                nodes += 1
                if parent.isAnyAtFileNode() and parent.v != root.v:
                    if parent.v not in seen:
                        seen.add(parent.v)
                        g.es_print('%s and %s contain clone: %s' % (
                            root.h,parent.h,p0.h))

for h in table:
    root = g.findNodeAnywhere(c,h)
    if root:
        for p in root.self_and_subtree():
            nodes += 1
            if p.isCloned():
                clones += 1
                check_clone(c,p,root)
    else:
        g.es_print('not found',h,color='red')
print('done: %s nodes, %s clones' % (nodes,clones))

@tabwidth -4
@language python
</t>
<t tx="ekr.20150425145248.1">run-pylint
clone-to-at-spot
beautify-tree
cfa-code
sort-lines
# show-data
# test-ptb
check-clones
expand-log-pane
contract-log-pane</t>
<t tx="ekr.20150502050609.1">c.backup_helper(sub_dir='leoPy')
</t>
<t tx="ekr.20150507170849.1">g.cls()

print('===== Start =====')

class CreateDecorators:
    '''
    A class to create decorators from tables in getPublicCommands.
    
    Note: the node "Found: getPublicCommands" must exist.
    '''
    def __init__(self,c,make_changes):
        self.c = c
        self.fixups = self.create_fixups()
        self.n = 0
        self.n_fail = 0
        self.make_changes=make_changes
        self.suppress = [
            'c.frame.body and c.frame.body.addEditor',
            'cls','cloneFindParents','cycleTabFocus',
            'k and k.keyboardQuit',
            'menuShortcutPlaceHolder','removeBlankLines',
            'saveBuffersKillLeo',
        ]
    @others

CreateDecorators(c,make_changes=False).run()
</t>
<t tx="ekr.20150507174711.1">def find_next_clone(self,p):
    v = p.v
    p = p.copy()
    p.moveToThreadNext()
    wrapped = False
    while 1:
        # g.trace(p.v,p.h)
        if p and p.v == v:
            break
        elif p:
            p.moveToThreadNext()
        elif wrapped:
            break
        else:
            wrapped = True
            p = c.rootPosition()
    return p
</t>
<t tx="ekr.20150507175246.1">def munge_lines(self,root,publicCommands):
    '''Return munged lines of '''
    s = publicCommands.b
    i,j = s.find('{'),s.find('}')
    s = s[i+1:j]
    lines = sorted([z.strip() for z in g.splitLines(s) if z.strip()])
    lines = [z for z in lines if not z.startswith('#')]
    lines = [z[:z.find('#')] if z.find('#') &gt; -1 else z for z in lines]
    lines = [z.rstrip().rstrip(',') for z in lines]
    lines = [z[1:] for z in lines]
    lines = [z.replace("':",' ') for z in lines]
    self.n += len(lines)
    return lines
</t>
<t tx="ekr.20150508062944.1">def run(self):
    '''Top-level code.'''
    self.n = 0
    found = g.findNodeAnywhere(c,'Found: getPublicCommands')
    assert found
    for child in found.children():
        publicCommands = self.find_next_clone(child)
        root = self.find_class(publicCommands)
        if root:
            lines = self.munge_lines(root,publicCommands)
            d = self.create_d(lines,publicCommands)
            self.create_decorators(d,root)
    print('\n%s commands %s failed' % (self.n,self.n_fail))
</t>
<t tx="ekr.20150508063412.1">def create_decorators(self,d,root):
    '''Create decorators for all items in d in root's tree.'''
    # print('***** %s' % root.h)
    if root.h in self.fixups:
        roots = []
        aList = self.fixups.get(root.h)
        for root2_h in aList:
            root2 = g.findNodeAnywhere(self.c,root2_h)
            if root2:
                # g.trace(root.h,'=====&gt;',root2.h)
                roots.append(root2)
            else:
                g.trace('===== not found',root2_h)
    else:
        roots = [root]
    for f_name in sorted(d.keys()):
        found = False
        for root in roots:
            c_name = d.get(f_name)
            found = self.create_decorator(c_name,f_name,root)
            if found: break
        if not found and f_name not in self.suppress:
            print('===== not found: %30s %s' % (root.h,f_name))
            self.n_fail += 1
</t>
<t tx="ekr.20150508063538.1">def create_d(self,lines,publicCommands):
    '''Create a dict. keys are method names; values are command names.'''
    trace = False
    if trace:
        g.trace('\n', publicCommands.h)
    d = {}
    for s in lines:
        aList = s.split()
        if len(aList) &gt; 2:
            aList = [aList[0],' '.join(aList[1:])]
        c_name,f_name = aList[0].strip(),aList[1].strip()
        if ' ' not in f_name:
            f_name = f_name.split('.')[-1]
        # if '(' in f_name:
            # f_name = f_name[:f_name.find('(')]
        if trace: g.trace('%45s %s' % (c_name,f_name))
        d [f_name] = c_name
    return d
</t>
<t tx="ekr.20150508063926.1">def find_class(self,p):
    '''Return the position of the class enclosing p.'''
    for p2 in p.parents():
        if p2.h.lower().find('class') &gt; -1 and p2.b.find('class') &gt; -1:
            return p2
    else:
        g.trace('*** no class for p.h')
        return None
</t>
<t tx="ekr.20150508071622.1">def create_decorator(self,c_name,f_name,root):
    '''
    Search root for a definition of f_name.
    If found, insert @cmd(f_name) before the definition.
    '''
    # g.trace('%45s %s' % (c_name,f_name))
    trace = False
    found = False
    decorator = "@cmd('%s')\n" % (c_name)
    for p in root.self_and_subtree(copy=False):
        changed,result = False,[]
        for s in g.splitLines(p.b):
            if g.match_word(s,0,'def ' + f_name):
                if found:
                    if f_name not in self.suppress:
                        g.trace('duplicate def',f_name)
                else:
                    changed,found = True,True
                    result.append(decorator)
                    # print('%s%s' % (decorator,s))
            result.append(s)
        # if changed and self.make_changes:
            # new_body = ''.join(result)
            # # use git as our undo :-)
            # p.b = new_body
    return found
</t>
<t tx="ekr.20150508074623.1">def create_fixups(self):
    '''
    Return a fixup dict.
    Keys are headlines for classes.
    Values are new headlines of nodes containing the actual class.
    '''
    return {
        'ChapterCommandsClass': ['class ChapterController'],
        'EditCommandsClass': [
            'EditCommandsClass',
            'class Commands',
            'class LeoQtFrame',
            'class LeoBody',
        ],
        'class SearchCommandsClass': ['class LeoFind (LeoFind.py)'],
        'KeyHandlerCommandsClass (add docstrings)': [
            'class KeyHandlerClass',
            'class AutoCompleterClass',
        ]
    }
</t>
<t tx="ekr.20150509183433.1">g.cls()

# Changed files:
# leoApp.py
# leoAtFile.py
# leoCommands.py
# leoFileCommands.py
# leoFrame.py
# leoUndo.py
# qt_frame.py

make_changes = True
    # True, actually make the change

class CreateDecorators:
    '''
    A class to create decorators from tables in getPublicCommands.
    
    Note: the node "Found: getPublicCommands" must exist.
    '''
    def __init__(self):
        self.n = 0
        self.n_fail = 0
        self.s = self.define_s()
    @others

CreateDecorators().run()
</t>
<t tx="ekr.20150509183433.2">def create_d(self,lines):
    '''Create a dict. keys are method names; values are command names.'''
    trace = False
    d = {}
    for s in lines:
        aList = s.split()
        if len(aList) &gt; 2:
            aList = [aList[0],' '.join(aList[1:])]
        c_name,f_name = aList[0].strip(),aList[1].strip()
        if ' ' not in f_name:
            f_name = f_name.split('.')[-1]
        # if '(' in f_name:
            # f_name = f_name[:f_name.find('(')]
        if trace: g.trace('%45s %s' % (c_name,f_name))
        d [f_name] = c_name
    return d
</t>
<t tx="ekr.20150509183433.3">def create_decorator(self,c_name,f_name,root):
    '''
    Search root for a definition of f_name.
    If found, insert @cmd(f_name) before the definition.
    '''
    trace = True
    found = False
    decorator = "@cmd('%s')\n" % (c_name)
    for p in root.self_and_subtree(copy=False):
        changed,result = False,[]
        for s in g.splitLines(p.b):
            if g.match_word(s,0,'def ' + f_name):
                if found:
                    if f_name not in self.suppress:
                        g.trace('duplicate def',f_name)
                else:
                    changed,found = True,True
                    result.append(decorator)
                    # print('%s%s' % (decorator,s))
            result.append(s)
        if changed and make_changes:
            new_body = ''.join(result)
            print('%40s %s' % (p.h[:40],decorator.rstrip()))
            # use git as our undo :-)
            # p.b = new_body
    return found
</t>
<t tx="ekr.20150509183433.4">def create_decorators(self,d):
    '''Create decorators for all items in d in root's tree.'''
    table = (
        'class Commands', # c.
        'class LeoQtFrame', # f.
        'class LeoFrame', # f.
        'class LeoApp', # g.app.
        '@file leoAtFile.py', # c.atFileCommands
        '@file leoFileCommands.py', # c.fileCommands
        'class Undoer', # c.undoer
    )
    roots = []
    for h in table:
        root = g.findNodeAnywhere(c,h)
        assert root,h
        roots.append(root)
    for f_name in sorted(d.keys()):
        found = False
        for root in roots:
            c_name = d.get(f_name)
            found = self.create_decorator(c_name,f_name,root)
            if found: break
        if not found and f_name not in self.suppress:
            print('===== not found: %s' % (f_name))
            self.n_fail += 1
</t>
<t tx="ekr.20150509183433.8">def munge_lines(self,s):
    '''Return munged lines of s. '''
    lines = sorted([z.strip() for z in g.splitLines(s) if z.strip()])
    lines = [z for z in lines if not z.startswith('#')]
    lines = [z[:z.find('#')] if z.find('#') &gt; -1 else z for z in lines]
    lines = [z.rstrip().rstrip(',') for z in lines]
    lines = [z[1:] for z in lines]
    lines = [z.replace("':",' ') for z in lines]
    self.n += len(lines)
    return lines
</t>
<t tx="ekr.20150509183433.9">def run(self):
    '''Top-level code.'''
    lines = self.munge_lines(self.s)
    d = self.create_d(lines)
    self.create_decorators(d)
    print('%s commands %s failed' % (self.n,self.n_fail))
</t>
<t tx="ekr.20150509183832.1"># 'check-all-python-code':      c.checkAllPythonCode,
# 'check-python-code':          c.checkPythonCode,
# 'extract-python-method':        c.extractPythonMethod,
# 'extract-section':              c.extractSection,
# 'import-at-file':               c.importAtFile,
# 'import-at-root':               c.importAtRoot,
# 'import-cweb-files':            c.importCWEBFiles,
# 'import-derived-file':          c.importDerivedFile,
# 'import-flattened-outline':     c.importFlattenedOutline,
# 'import-noweb-files':           c.importNowebFiles,
# 'mark-changed-roots':           c.markChangedRoots,
# 'mark-clones':                c.markClones,
# 'open-compare-window':        c.openCompareWindow,
# 'open-online-tutorial':       c.leoTutorial,
# 'reformat-body':              c.reformatBody, # 2013/10/02.
def define_s(self):
    return '''
'abort-edit-headline':          f.abortEditLabelCommand,
'about-leo':                    c.about,
'add-comments':                 c.addComments,     
'beautify':                     c.beautifyPythonCode,
'beautify-all':                 c.beautifyAllPythonCode,
'beautify-c':                   c.beautifyCCode,
'beautify-tree':                c.beautifyPythonTree,
'cascade-windows':              f.cascade,
'check-derived-file':           c.atFileCommands.checkDerivedFile,
'check-leo-file':               c.fileCommands.checkLeoFile,
'check-outline':                c.fullCheckOutline,
'clean-recent-files':           c.cleanRecentFiles,
'clear-recent-files':           c.clearRecentFiles,
'clone-node':                   c.clone,
'clone-node-to-last-node':      c.cloneToLastNode,
'close-window':                 c.close,
'contract-all':                 c.contractAllHeadlines,
'contract-all-other-nodes':     c.contractAllOtherNodes,
'contract-node':                c.contractNode,
'contract-or-go-left':          c.contractNodeOrGoToParent,
'contract-parent':              c.contractParent,
'convert-all-blanks':           c.convertAllBlanks,
'convert-all-tabs':             c.convertAllTabs,
'convert-blanks':               c.convertBlanks,
'convert-tabs':                 c.convertTabs,
'copy-node':                    c.copyOutline,
'copy-text':                    f.copyText,
'cut-node':                     c.cutOutline,
'cut-text':                     f.cutText,
'de-hoist':                     c.dehoist,
'delete-comments':              c.deleteComments,
'delete-node':                  c.deleteOutline,
'demote':                       c.demote,
'dump-outline':                 c.dumpOutline,
'edit-headline':                c.editHeadline,
'end-edit-headline':            f.endEditLabelCommand,
'equal-sized-panes':            f.equalSizedPanes,
'execute-script':               c.executeScript,
'exit-leo':                     g.app.onQuit,
'expand-all':                   c.expandAllHeadlines,
'expand-all-subheads':          c.expandAllSubheads,
'expand-ancestors-only':        c.expandOnlyAncestorsOfNode,
'expand-and-go-right':          c.expandNodeAndGoToFirstChild,
'expand-next-level':            c.expandNextLevel,
'expand-node':                  c.expandNode,
'expand-or-go-right':           c.expandNodeOrGoToFirstChild,
'expand-prev-level':            c.expandPrevLevel,
'expand-to-level-1':            c.expandLevel1,
'expand-to-level-2':            c.expandLevel2,
'expand-to-level-3':            c.expandLevel3,
'expand-to-level-4':            c.expandLevel4,
'expand-to-level-5':            c.expandLevel5,
'expand-to-level-6':            c.expandLevel6,
'expand-to-level-7':            c.expandLevel7,
'expand-to-level-8':            c.expandLevel8,
'expand-to-level-9':            c.expandLevel9,
'export-headlines':             c.exportHeadlines,
'extract':                      c.extract,
'extract-names':                c.extractSectionNames,
'find-next-clone':              c.findNextClone,
'flatten-outline':              c.flattenOutline,
'flatten-outline-to-node':      c.flattenOutlineToNode,
'go-back':                      c.goPrevVisitedNode,
'go-forward':                   c.goNextVisitedNode,
'goto-first-node':              c.goToFirstNode,
'goto-first-sibling':           c.goToFirstSibling,
'goto-first-visible-node':      c.goToFirstVisibleNode,
'goto-last-node':               c.goToLastNode,
'goto-last-sibling':            c.goToLastSibling,
'goto-last-visible-node':       c.goToLastVisibleNode,
'goto-next-changed':            c.goToNextDirtyHeadline,
'goto-next-clone':              c.goToNextClone,
'goto-next-history-node':       c.goToNextHistory,
'goto-next-marked':             c.goToNextMarkedHeadline,
'goto-next-node':               c.selectThreadNext,
'goto-next-sibling':            c.goToNextSibling,
'goto-next-visible':            c.selectVisNext,
'goto-parent':                  c.goToParent,
'goto-prev-history-node':       c.goToPrevHistory,
'goto-prev-node':               c.selectThreadBack,
'goto-prev-sibling':            c.goToPrevSibling,
'goto-prev-visible':            c.selectVisBack,
'hide-invisibles':              c.hideInvisibles,
'hoist':                        c.hoist,
'import-file':                  c.importAnyFile,
'indent-region':                c.indentBody,
'insert-body-time':             c.insertBodyTime,
'insert-child':                 c.insertChild,
'insert-node':                  c.insertHeadline,
'insert-node-before':           c.insertHeadlineBefore,
'mark':                         c.markHeadline,
'mark-changed-items':           c.markChangedHeadlines,
'mark-subheads':                c.markSubheads,
'match-brackets':               c.findMatchingBracket,
'minimize-all':                 f.minimizeAll,
'move-outline-down':            c.moveOutlineDown,
'move-outline-left':            c.moveOutlineLeft,
'move-outline-right':           c.moveOutlineRight,
'move-outline-up':              c.moveOutlineUp,
'new':                          c.new,
'open-cheat-sheet-leo':         c.openCheatSheet,
'open-leoDocs-leo':             c.leoDocumentation,
'open-leoPlugins-leo':          c.openLeoPlugins,
'open-leoSettings-leo':         c.openLeoSettings,
'open-local-settings':          c.selectAtSettingsNode,
'open-myLeoSettings-leo':       c.openMyLeoSettings,
'open-offline-tutorial':        f.leoHelp,
'open-online-home':             c.leoHome,
'open-online-toc':              c.openLeoTOC,
'open-online-tutorials':        c.openLeoTutorials,
'open-online-videos':           c.openLeoVideos,
'open-outline':                 c.open_outline,
'open-python-window':           c.openPythonWindow,
'open-quickstart-leo':          c.leoQuickStart,
'open-scripts-leo':             c.openLeoScripts,
'open-users-guide':             c.openLeoUsersGuide,
'open-with':                    c.openWith,
'outline-to-cweb':              c.outlineToCWEB,
'outline-to-noweb':             c.outlineToNoweb,
'paste-node':                   c.pasteOutline,
'paste-retaining-clones':       c.pasteOutlineRetainingClones,
'paste-text':                   f.pasteText,
'pretty-print-all-python-code': c.prettyPrintAllPythonCode,
'pretty-print-python-code':     c.prettyPrintPythonCode,
'promote':                      c.promote,
'read-at-auto-nodes':           c.readAtAutoNodes,
'read-at-file-nodes':           c.readAtFileNodes,
'read-at-shadow-nodes':         c.readAtShadowNodes,
'read-file-into-node':          c.readFileIntoNode,
'read-outline-only':            c.readOutlineOnly,
'redo':                         c.undoer.redo,
'reformat-paragraph':           c.reformatParagraph,
'refresh-from-disk':            c.refreshFromDisk,
'remove-sentinels':             c.removeSentinels,
'resize-to-screen':             f.resizeToScreen,
'revert':                       c.revert,
'save-all':                     c.saveAll,
'save-file':                    c.save,
'save-file-as':                 c.saveAs,
'save-file-as-unzipped':        c.saveAsUnzipped,
'save-file-as-zipped':          c.saveAsZipped,
'save-file-to':                 c.saveTo,
'set-colors':                   c.colorPanel,
'set-font':                     c.fontPanel,
'settings':                     c.preferences,
'show-invisibles':              c.showInvisibles,
'sort-children':                c.sortChildren,
'sort-recent-files':            c.sortRecentFiles,
'sort-siblings':                c.sortSiblings,
'tangle':                       c.tangle,
'tangle-all':                   c.tangleAll,
'tangle-marked':                c.tangleMarked,
'toggle-active-pane':           f.toggleActivePane,
'toggle-angle-brackets':        c.toggleAngleBrackets,
'toggle-invisibles':            c.toggleShowInvisibles,
'toggle-sparse-move':           c.toggleSparseMove,
'toggle-split-direction':       f.toggleSplitDirection,
'undo':                         c.undoer.undo,
'unformat-paragraph':           c.unformatParagraph,
'unindent-region':              c.dedentBody,
'unmark-all':                   c.unmarkAll,
'untangle':                     c.untangle,
'untangle-all':                 c.untangleAll,
'untangle-marked':              c.untangleMarked,
'weave':                        c.weave,
'write-at-auto-nodes':          c.atFileCommands.writeAtAutoNodes,
'write-at-file-nodes':          c.fileCommands.writeAtFileNodes,
'write-at-shadow-nodes':        c.fileCommands.writeAtShadowNodes,
'write-dirty-at-auto-nodes':    c.atFileCommands.writeDirtyAtAutoNodes,
'write-dirty-at-file-nodes':    c.fileCommands.writeDirtyAtFileNodes,
'write-dirty-at-shadow-nodes':  c.fileCommands.writeDirtyAtShadowNodes,
'write-file-from-node':         c.writeFileFromNode,
'write-missing-at-file-nodes':  c.fileCommands.writeMissingAtFileNodes,
'write-outline-only':           c.fileCommands.writeOutlineOnly,
'''
</t>
<t tx="ekr.20150514035207.1"></t>
<t tx="ekr.20150531102337.1"></t>
<t tx="ekr.20150604130353.1">gnx: ekr.20150604130223.363
</t>
<t tx="ekr.20150604130353.2"></t>
<t tx="ekr.20150617060607.1"></t>
<t tx="ekr.20150703061709.1">@language python

'''myLeoSettings.py: save the outline and run the pylint command'''

# print('@button run-pylint: %s' % c.shortFileName())
if c.isChanged():
    c.save()
c.k.simulateCommand('pylint')
</t>
<t tx="ekr.20160122104332.1">@language python
</t>
<t tx="ekr.20160123142722.1"># An example configuration file for make_stub_files.py.
# By default, this is ~/stubs/make_stub_files.cfg.
# Can be changed using the --config=path command-line option.

[Global]

files:

    # Files to be used *only* if no files are given on the command line.
    # glob.glob wildcards are supported.

    # c:/leo.repo/leo-editor/leo/core/leoAst.py
    # c:/leo.repo/leo-editor/leo/core/*.py
    # c:/leo.repo/leo-editor/plugins/*.py

output_directory: ~/stubs

prefix_lines:
    # Lines to be inserted at the start of each stub file.
    from typing import TypeVar, Iterable, Tuple
    T = TypeVar('T', int, float, complex)

[Def Name Patterns]

[General Patterns]
</t>
<t tx="ekr.20160420054135.4">gnx: ekr.20160412193816.5
unl: qt_quicksearch declarations
gnx: ekr.20160412193816.6
unl: class Ui_LeoQuickSearchWidget
gnx: ekr.20160412193816.7
unl: class Ui_LeoQuickSearchWidget--&gt;setupUi
gnx: ekr.20160412193816.8
unl: class Ui_LeoQuickSearchWidget--&gt;retranslateUi
</t>
<t tx="ekr.20160420054135.5"></t>
<t tx="ekr.20160425070345.1">gnx: ekr.20160412193816.1
unl: qt_main declarations
gnx: ekr.20160412193816.2
unl: class Ui_MainWindow
gnx: ekr.20160412193816.3
unl: class Ui_MainWindow--&gt;setupUi
gnx: ekr.20160412193816.4
unl: class Ui_MainWindow--&gt;retranslateUi
</t>
<t tx="ekr.20160425070345.2"></t>
<t tx="ekr.20170427112302.1">g.cls()
import glob
files = glob.glob(g.os_path_join(g.app.loadDir, '*.py'))
files = [z for z in files if g.os_path_basename(z).startswith('leo')]
if 0:
    g.printList(files)
found = set()
for p in c.all_unique_positions():
    name = p.isAnyAtFileNode()
    if name and name.startswith('leo'):
        path = g.os_path_join(g.app.loadDir, name)
        found.add(path)
if 0:
    print('found')
    g.printList(list(found))
else:
    missing = set(files) - found
    if missing:
        print('not found...')
        g.printList(list(sorted(missing)))
    else:
        print('done')
        </t>
<t tx="ekr.20170427114412.1"></t>
<t tx="ekr.20170428084123.1">'''Recursively import all python files in a directory and clean the result.'''
if 0:
    &lt;&lt; old dir_ settings &gt;&gt;
g.cls()
dir_ = r'C:\leo.repo\leo-editor\leo\core\editpane'
# dir_ = r'C:\leo.repo\leo-editor\leo\external\npyscreen'
c.recursiveImport(
    dir_ = dir_,
    kind = '@file', # '@clean', #'@nosent','@auto','@file',
    recursive = True,
    safe_at_file = False,
    theTypes = ['.py',],
)
</t>
<t tx="ekr.20170428084123.2">dir_ = r'C:\prog\yoton',
dir_ = r'c:\leo.repo\ace\lib'
# Tests: 2017/04/07
dir_ = r'c:\leo.repo\ace\demo\kitchen-sink\dev_util.js' # pass.
dir_ = r'c:\leo.repo\ace\demo\static-highlighter\server.js' # Perfect import fails.
dir_ = r'c:\leo.repo\ace\lib\ace\mode\asciidoc_highlight_rules.js' # undefined sections.
dir_ = r'c:\leo.repo\ace\lib\ace\mode\abap.js' # pass.
dir_ = r'c:\leo.repo\ace\lib\ace\lib\event.js' # pass.
dir_ = r'c:\leo.repo\ace\lib\ace\lib' # pass.
dir_ = r'c:\leo.repo\ace\demo' # All pass except server.js
dir_ = r'c:\test\js-import-test.js' # pass.
dir_ = r'c:\leo.repo\ace\lib\ace\mode\coffee\coffee.js'
# Perfect import fails. Compressed code. Maybe will never pass.
dir_ = r'c:\leo.repo\ace\lib\ace\mode\behaviour' # All pass
dir_ = r'c:\leo.repo\ace\lib\ace\mode' # One failure.
dir_ = r'c:\leo.repo\ace\lib\ace\mode\xquery\xqlint.js' # perfect import fails.
dir_ = r'c:\prog\brython-home.html'</t>
<t tx="ekr.20170428084208.443">#!/usr/bin/python
# This file generates pyflakes warnings for *all* imported symbols.
@others
@language python
@tabwidth -4
</t>
<t tx="ekr.20170428084208.444">from .globals                   import DEBUG, DISABLE_RESIZE_SYSTEM

from .wgwidget                  import TEST_SETTINGS, ExhaustedTestInput, add_test_input_from_iterable, add_test_input_ch

from .npyssafewrapper           import wrapper, wrapper_basic

from   .npysThemeManagers       import ThemeManager, disableColor, enableColor
from   . import npysThemes      as     Themes
from   .apNPSApplication        import NPSApp
from   .apNPSApplicationManaged import NPSAppManaged
from   .proto_fm_screen_area    import setTheme
from   .fmForm                  import FormBaseNew, Form, TitleForm, TitleFooterForm, SplitForm, FormExpanded, FormBaseNewExpanded, blank_terminal
from   .fmActionForm            import ActionForm, ActionFormExpanded
from   .fmActionFormV2          import ActionFormV2, ActionFormExpandedV2, ActionFormMinimal
from   .fmFormWithMenus         import FormWithMenus, ActionFormWithMenus, \
                                       FormBaseNewWithMenus, SplitFormWithMenus, \
                                       ActionFormV2WithMenus
from   .fmPopup                 import Popup, MessagePopup, ActionPopup, PopupWide, ActionPopupWide
from   .fmFormMutt              import FormMutt, FormMuttWithMenus
from   .fmFileSelector          import FileSelector, selectFile

from .fmFormMuttActive          import ActionControllerSimple, TextCommandBox, \
                                       FormMuttActive, FormMuttActiveWithMenus
from .fmFormMuttActive          import FormMuttActiveTraditional, FormMuttActiveTraditionalWithMenus


from .fmFormMultiPage           import FormMultiPage, FormMultiPageAction,\
                                       FormMultiPageActionWithMenus, FormMultiPageWithMenus

from .npysNPSFilteredData       import NPSFilteredDataBase, NPSFilteredDataList

from .wgbutton                  import MiniButton
from .wgbutton                  import MiniButtonPress
from .wgbutton                  import MiniButton      as Button
from .wgbutton                  import MiniButtonPress as ButtonPress

from .wgtextbox                 import Textfield, FixedText
from .wgtitlefield              import TitleText, TitleFixedText
from .wgpassword                import PasswordEntry, TitlePassword
from .wgannotatetextbox         import AnnotateTextboxBase
from .wgannotatetextbox         import AnnotateTextboxBaseRight

from .wgslider                  import Slider, TitleSlider
from .wgslider                  import SliderNoLabel, TitleSliderNoLabel
from .wgslider                  import SliderPercent, TitleSliderPercent

from .wgwidget                  import DummyWidget, NotEnoughSpaceForWidget
from . import wgwidget as widget

from .wgmultiline               import MultiLine, Pager, TitleMultiLine, TitlePager, MultiLineAction, BufferPager, TitleBufferPager
from .wgmultiselect             import MultiSelect, TitleMultiSelect, MultiSelectFixed, \
                                       TitleMultiSelectFixed, MultiSelectAction
from .wgeditmultiline           import MultiLineEdit
from .wgcombobox                import ComboBox, TitleCombo
from .wgcheckbox                import Checkbox, RoundCheckBox, CheckBoxMultiline, RoundCheckBoxMultiline, CheckBox, CheckboxBare
from .wgFormControlCheckbox     import FormControlCheckbox
from .wgautocomplete            import TitleFilename, Filename, Autocomplete
from .muMenu                    import Menu
from .wgselectone               import SelectOne, TitleSelectOne
from .wgdatecombo               import DateCombo, TitleDateCombo

from .npysTree import TreeData
from .wgmultilinetree           import MLTree, MLTreeAnnotated, MLTreeAction, MLTreeAnnotatedAction
from .wgmultilinetreeselectable import MLTreeMultiSelect, TreeLineSelectable
from .wgmultilinetreeselectable import MLTreeMultiSelectAnnotated, TreeLineSelectableAnnotated


# The following are maintained for compatibility with old code only. ##########################################

from .compatibility_code.oldtreeclasses import MultiLineTree, SelectOneTree
from .compatibility_code.oldtreeclasses import MultiLineTreeNew, MultiLineTreeNewAction, TreeLine, TreeLineAnnotated # Experimental
from .compatibility_code.oldtreeclasses import MultiLineTreeNewAnnotatedAction, MultiLineTreeNewAnnotated # Experimental
from .compatibility_code.npysNPSTree import NPSTreeData

# End compatibility. ###########################################################################################

from .wgfilenamecombo           import FilenameCombo, TitleFilenameCombo
from .wgboxwidget               import BoxBasic, BoxTitle
from .wgmultiline               import MultiLineActionWithShortcuts
from .wgmultilineeditable       import MultiLineEditable, MultiLineEditableTitle, MultiLineEditableBoxed

from .wgmonthbox                import MonthBox
from .wggrid                    import SimpleGrid
from .wggridcoltitles           import GridColTitles

from .muNewMenu                 import NewMenu, MenuItem
from .wgNMenuDisplay            import MenuDisplay, MenuDisplayScreen

from .npyspmfuncs               import CallSubShell

from .utilNotify                 import notify, notify_confirm, notify_wait, notify_ok_cancel, notify_yes_no

# Base classes for overriding:

# Standard Forms:
from . import stdfmemail

# Experimental Only
from .wgtextboxunicode import TextfieldUnicode
from .wgtexttokens     import TextTokens, TitleTextTokens

# Very experimental. Don't use for anything serious
from .apOptions import SimpleOptionForm
from .apOptions import OptionListDisplay, OptionChanger, OptionList, OptionLimitedChoices, OptionListDisplayLine
from .apOptions import OptionFreeText, OptionSingleChoice, OptionMultiChoice, OptionMultiFreeList, \
                       OptionBoolean, OptionFilename, OptionDate, OptionMultiFreeText


# This really is about as experimental as it gets
from .apNPSApplicationEvents import StandardApp
from .eveventhandler import Event


</t>
<t tx="ekr.20170428085201.1">@nosearch</t>
<t tx="ekr.20170811173924.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.20171031111403.1"></t>
<t tx="ekr.20180225010644.1"></t>
<t tx="ekr.20180225010707.1"></t>
<t tx="ekr.20180225010743.1">@nosearch</t>
<t tx="ekr.20180225010850.1"></t>
<t tx="ekr.20180225010913.1"></t>
<t tx="ekr.20180324065741.1">'''Copy the selected text to the next node.'''
w = c.frame.body.wrapper
s = w.getSelectedText()
if s.strip():
    w.deleteTextSelection()
    c.p.b = w.getAllText()
    w.setInsertPoint(0)
    p = c.insertHeadline()
    c.selectPosition(p)
    p.b = s
    c.editHeadline()
else:
    g.es_print('no text selected')
</t>
<t tx="ekr.20180708145905.1">@language rest
@wrap

This is the theory of operation document for py2cs.py. The most interesting aspect of this script is the TokenSync class. This class provides a reliable way of associating tokenizer tokens with ast nodes.

@others
</t>
<t tx="ekr.20180708145905.6">
### Using the TokenSync class

The present code is driven by ast trees, but each visitor of the CoffeeScriptTraverser class takes care to preserve **otherwise-ignored tokens**. These are tokens that would otherwise be ignored: namely blank lines and comments, both entire-line comments and trailing comments.

The visitor for each statement intersperses otherwise ignored tokens using calls to the TokenSync class.  The simplest cases are like this:

    def do_Break(self, node):
        head = self.leading_string(node)
        tail = self.trailing_comment(node)
        return head + self.indent('break') + tail

The leading_string and trailing_comment methods simply redirect to the corresponding methods in the TokenSync class.  Saves a bit of typing. Compound statements are a bit more bother, but not overly so. For example:

    def do_If(self, node):

        result = self.leading_lines(node)
        tail = self.trailing_comment(node)
        s = 'if %s:%s' % (self.visit(node.test), tail)
        result.append(self.indent(s))
        for z in node.body:
            self.level += 1
            result.append(self.visit(z))
            self.level -= 1
        if node.orelse:
            tail = self.tail_after_body(node.body, node.orelse, result)
            result.append(self.indent('else:' + tail))
            for z in node.orelse:
                self.level += 1
                result.append(self.visit(z))
                self.level -= 1
        return ''.join(result)

The line:

        tail = self.tail_after_body(node.body, node.orelse, result)

is a hack needed to compensate for the lack of an actual ast.Else node.
</t>
<t tx="ekr.20180708145905.7">
### Summary

The TokenSync class is, a new, elegant, unexpected and happy development. It is a relatively easy-to-use helper that allows parser-based code to preserve data that is not easily accessible in parse trees.

The TokenSync class avoids [problems with the col_offset field](
http://stackoverflow.com/questions/16748029/how-to-get-source-corresponding-to-a-python-ast-node) in ast nodes. The TokenSync class depends only on the ast.lineno field and the tokenize module. We can expect it to be rock solid.

Edward K. Ream
February 20 to 25, 2016



</t>
<t tx="ekr.20180708152000.1">
### The problem

The initial version of py2cs.py (the script) used only tokens. This solved all token-related problems, but made parsing difficult. Alas, it is [difficult](http://stackoverflow.com/questions/16748029/how-to-get-source-corresponding-to-a-python-ast-node) to associate tokens with ast nodes.

The script needs the following token-related data:

- The **ignored lines** (comment lines and blank lines) that precede any statement.

- The **trailing comment** strings that might follow any line.

- Optionally, the **line breaks** occurring within lines. At present, this script does not preserve such breaks, and it's probably not worth doing. Indeed, automatically breaking long lines seems more useful, especially considering that coffeescript lines may be substantially shorter than the corresponding python lines.

- The **exact spelling** of all strings.

The [ast_utils module](
https://bitbucket.org/plas/thonny/src/3b71fda7ac0b66d5c475f7a668ffbdc7ae48c2b5/thonny/ast_utils.py?at=master) purports to solve this problem with convoluted adjustments to the col_offset field. This approach is subject to subtle Python bugs, and subtle differences between Python 2 and Python 3. There is a better way...
</t>
<t tx="ekr.20180708152018.1">
### Design

The main idea is to use *only* the ast.lineno fields and the tokenizer module to recreate token data. The design assumes only that both the ast.lineno field and Python's tokenizer module are solid. This is a much more reasonable assumption than assuming that the col_offset field always tells the truth. In short, this design *ignores* the ast.col_offset field.

At startup, the TokenSync ctor assigns all the incoming tokens to various lists.  These lists are indexed by lineno:

    ts.line_tokens[i]: all the tokens on line i
    ts.string_tokens[i]: all string tokens on line i
    st.ignored_lines: the blank or comment line on line i

It is very easy to create these lists. The code does not depend on any arcane details.

#### Recovering the exact spelling of stings.

ts.synch_string returns the *next* string on the line. Here it is, stripped of defensive code:

    def sync_string(self, node):
        '''Return the spelling of the string at the given node.'''
        tokens = self.string_tokens[node.lineno-1]
        token = tokens.pop(0)
        self.string_tokens[node.lineno-1] = tokens
        return self.token_val(token)

Stripped of defensive code, the do_Str visitor is just:

    def do_Str(self, node):
        '''A string constant, including docstrings.'''
        return self.sync_string(node)

#### Recovering otherwise ignored nodes

**ts.leading_lines(node)** returns a list of otherwise ignored lines that
precede the node's line that have not already been returned.
**ts.leading_string(node)** is a convenience method that returns ''.join(ts.leading_lines(node)). The visitors of the CoffeeScriptTraverser class show how to use these methods.
</t>
<t tx="ekr.20180816105258.1">import leo.commands.editFileCommands as efc

efc.GitDiffController(c).diff_two_branches(
    branch1='devel', # old branch
    branch2='dock', # new branch
    fn='leo/plugins/qt_frame.py',
    directory=None,
)
</t>
<t tx="ekr.20180824065751.1">print(p.gnx)</t>
<t tx="ekr.20181009072707.1">@first # -*- coding: utf-8 -*-
&lt;&lt; imports &gt;&gt;
&lt;&lt; compute path &gt;&gt;
controller = leoBridge.controller(gui='nullGui',
    loadPlugins=False, readSettings=True,
    silent=False, verbose=False)
g = controller.globals()
c = controller.openLeoFile(path)
try:
    # Run all unit tests locally.
    root = g.findTopLevelNode(c, 'Active Unit Tests', exact=True)
    assert root, 'Not found: Active Unit Tests'
    c.selectPosition(root)
    &lt;&lt; run tests &gt;&gt;
except Exception as e:
    print('Unexpected exception 2', e)
    sys.exit(1)
</t>
<t tx="ekr.20181009084156.1">import leo.core.leoBridge as leoBridge
import os
import sys
# import pdb ; pdb.set_trace()
import unittest

</t>
<t tx="ekr.20181009084245.1">load_dir = os.path.abspath(os.path.dirname(__file__))
test_dir = os.path.join(load_dir, 'leo', 'test')
path = os.path.join(test_dir, 'unitTest.leo')
assert os.path.exists(path), repr(path)
</t>
<t tx="ekr.20181009084323.1">tm = c.testManager
g.unitTesting = g.app.unitTesting = True
suite = unittest.makeSuite(unittest.TestCase)
aList = tm.findAllUnitTestNodes(all=False, marked=False)
setup_script = None
found = False
for p in aList:
    if tm.isTestSetupNode(p):
        setup_script = p.b
        test = None
    elif tm.isTestNode(p):
        test = tm.makeTestCase(p, setup_script)
    elif tm.isSuiteNode(p):
        test = tm.makeTestSuite(p, setup_script)
    elif tm.isTestClassNode(p):
        test = tm.makeTestClass(p)
    else:
        test = None
    if test:
        suite.addTest(test)
        found = True
if not found:
    print('No unit tests')
    sys.exit(1)
runner = unittest.TextTestRunner(
    failfast=True, verbosity=1)
try:
    result = runner.run(suite)
    if result.errors or result.failures:
        print('errors: %s, failures: %s' % (
            len(result.errors), len(result.failures)))
        sys.exit(1)
    else:
        print('Travis unit tests all passed.')
        sys.exit(0)
except Exception:
    print('Unexpected exception')
    g.es_exception()
    sys.exit(1)
</t>
<t tx="ekr.20181013081645.1">@path test</t>
<t tx="ekr.20181102040815.1">files = [
    'test/unittest.leo',
]
for fn in files:
    path = g.os_path_finalize_join(g.app.loadDir, '..', fn)
    assert g.os_path_exists(path), repr(path)
    with open(path, 'r') as f:
        s = f.read()
        for line in g.splitLines(s):
            if len(line) &gt; 150:
                print(line)</t>
<t tx="ekr.20190122185223.1">@language text

Find all kwargs using regex:

^\s*(def\s+\w+\s*\(.*\=.*\))

found 1154 nodes

^\s*(def\s+\w+\s*\(.*\=.*\=.*\))

found 284 nodes
</t>
<t tx="ekr.20190402091335.1">import leo.commands.editFileCommands as efc

efc.GitDiffController(c).diff_two_revs(
    rev1='0505d8c9cabbd3', # Much better alignment
    rev2='588a192fa7a026', # Latest
    directory=None,
)
</t>
<t tx="ekr.20190406154306.1">g.openWithFileName(r'C:\apps\pyzo\pyzo.leo')</t>
<t tx="ekr.20190406193429.1" __node_tags="635f5f6275696c74696e5f5f0a7365740a7100285d7101580700000073657474696e677102617471035271042e"># Extra plugins, for this file only.

# Essential...
plugins_menu.py
free_layout.py
    # Now loaded automatically.
    # Disabled for testing bug 882824.
mod_scripting.py
viewrendered.py

# Testing only...
# nodetags.py
# python_terminal.py
# multifile.py
# livecode.py

# Others...
# bookmarks.py
# demo.py
# mod_http.py
# richtext.py

# Standard plugins

# backlink.py
# bigdash.py
# contextmenu.py
# line_numbering.py
# nav_qt.py
# nodetags.py
# quicksearch.py
# screen_capture.py
# todo.py
# valuespace.py
# xdb_pane.py
</t>
<t tx="ekr.20190607124533.1"></t>
</tnodes>
</leo_file>
