<?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" tnodes="0" max_tnode_index="0" clone_windows="0"/>
<globals body_outline_ratio="0.48" body_secondary_ratio="0.65">
	<global_window_position top="148" left="367" height="826" width="1010"/>
	<global_log_window_position top="0" left="0" height="0" width="0"/>
</globals>
<preferences/>
<find_panel_settings/>
<vnodes>
<v t="ekr.20070416075121"><vh>Startup</vh>
<v t="ekr.20070224123943"><vh>@settings</vh>
<v t="ekr.20150618075639.1"><vh>@bool minibuffer_find_mode = True</vh></v>
<v t="ekr.20150619071508.1"><vh>@bool use_find_dialog = False</vh></v>
<v t="ekr.20140808094008.3549"><vh>@bool vim_mode = False</vh></v>
<v t="ekr.20091230064146.1911"><vh>@data import_xml_tags</vh></v>
<v t="ekr.20071025193940"><vh>@@enabled-plugins</vh></v>
<v t="ekr.20110510110227.2439"><vh>Autocompleter settings</vh>
<v t="ekr.20110512085154.2447"><vh>@bool auto_tab_complete = True</vh></v>
<v t="ekr.20110511061102.5232"><vh>@bool enable_autocompleter_initially = False</vh></v>
<v t="ekr.20110512225930.2456"><vh>@bool enable_calltips_initially = False</vh></v>
<v t="ekr.20110510110227.2440"><vh>@bool use_qcompleter = False</vh></v>
</v>
<v t="ekr.20100118190256.2014"><vh>Chapters</vh>
<v t="ekr.20070604100125"><vh>@bool use_chapter_tabs = True</vh></v>
<v t="ekr.20070503085527"><vh>@bool use_chapters = True</vh></v>
</v>
<v t="ekr.20110521072459.2463"><vh>colorizer colors</vh>
<v t="ekr.20110521072459.2464"><vh>@@color keyword3_color = orange</vh></v>
<v t="ekr.20110521072459.2465"><vh>@@color keyword4_color = pink</vh></v>
</v>
<v t="ekr.20120928143821.3161"><vh>Log pane colors</vh>
<v t="ekr.20120928143821.3162"><vh>@@color log_error_color = orange</vh></v>
<v t="ekr.20120928143821.3168"><vh>@@color log_warning_color = purple</vh></v>
<v t="ekr.20120928143821.3163"><vh>@@color log_text_foreground_color = pink</vh></v>
<v t="ekr.20120928143821.3164"><vh>@@color log_text_background_color = None</vh></v>
</v>
<v t="ekr.20100118190256.2015"><vh>Files &amp; directories</vh>
<v t="ekr.20101009105505.2295"><vh>@bool put_expansion_bits_in_leo_files = False</vh></v>
<v t="ekr.20080822153619.1"><vh>@string shadow_subdir = .leo/shadow</vh></v>
<v t="ekr.20080922164255.1"><vh>@string test = c:\leo.repo\trunk\leo\test</vh></v>
</v>
<v t="ekr.20080729153237.1"><vh>Gc settings</vh>
<v t="ekr.20080729153237.2"><vh>@bool trace_gc = False</vh></v>
<v t="ekr.20080729153237.3"><vh>@bool trace_gc_calls = False</vh></v>
<v t="ekr.20080729153237.4"><vh>@bool trace_gc_verbose = False</vh></v>
</v>
<v t="ekr.20080529111617.1"><vh>Plugins</vh>
<v t="ekr.20070723091227"><vh>http plugin</vh>
<v t="ekr.20070723091227.1"><vh>@bool http_active = True</vh></v>
<v t="ekr.20070723091227.2"><vh>@int</vh>
<v t="ekr.20090316115500.1"><vh>port = 8080</vh></v>
</v>
<v t="ekr.20070723091227.3"><vh>@string rst_http_attributename = 'rst_http_attribute'</vh></v>
</v>
<v t="ekr.20080529111617.2"><vh>cleo</vh>
<v t="ekr.20080529111617.3"><vh>@color cleo_color_prog_green =</vh></v>
<v t="ekr.20080529111617.4"><vh>@color cleo_color_prog_red =</vh></v>
<v t="ekr.20080529111617.5"><vh>@data cleo_color_file_node_list</vh></v>
<v t="ekr.20080529111617.6"><vh>@int cleo_prog_width = 18</vh></v>
<v t="ekr.20080529111617.7"><vh>@float cleo_time_init = 1.0</vh></v>
<v t="ekr.20080529111617.8"><vh>@int cleo_prog_scale = 1</vh></v>
<v t="ekr.20080529111617.9"><vh>@float cleo_prog_extra = 4</vh></v>
<v t="ekr.20080529111617.10"><vh>@string cleo_time_name = 'days'</vh></v>
</v>
<v t="ekr.20100910124218.2257"><vh>screenshot settings</vh>
<v t="ekr.20100910124218.2258"><vh>@bool edit-screenshots = True</vh></v>
<v t="ekr.20100910124218.2259"><vh>@string screenshot-bin = "c:\Program Files (x86)\Inkscape\inkscape.exe"</vh></v>
</v>
<v t="ekr.20110321213552.2500"><vh>viewrendered settings</vh>
<v t="ekr.20110321213552.2497"><vh>@bool view-rendered-auto-create = False</vh></v>
<v t="ekr.20110526180653.2467"><vh>@bool view-rendered-auto-hide = True</vh></v>
<v t="ekr.20110321213552.2499"><vh>@bool scrolledmessage_use_viewrendered = True</vh></v>
</v>
</v>
<v t="ekr.20100118190256.2012"><vh>Syntax coloring</vh>
<v t="ekr.20100118141712.2011"><vh>@@int qt_tab_width = 80</vh></v>
<v t="ekr.20100118122048.2003"><vh>@@font python keyword1 fonts</vh></v>
<v t="ekr.20100118133026.2008"><vh>@@font python keyword3 fonts</vh></v>
<v t="ekr.20100119095312.2041"><vh>@@font rest keyword2 fonts</vh></v>
<v t="ekr.20100119100926.2046"><vh>@@font rest keyword4 fonts</vh></v>
<v t="ekr.20100330084954.2125"><vh>@color pseudoplain_operator_color = blue</vh></v>
</v>
<v t="ekr.20100118190256.2016"><vh>Vim</vh>
<v t="ekr.20090815161520.1815"><vh>@string vim_trigger_event = select2</vh></v>
<v t="ekr.20080604104453.5"><vh>@strings [command,insert, overwrite] top_level_unbound_key_action = insert</vh></v>
</v>
<v t="ekr.20100118190256.2013"><vh>Windows</vh>
<v t="ekr.20100507151756.2123"><vh>@string qt-toolbar-location=top</vh></v>
<v t="ekr.20090629105832.1790"><vh>@@bool big_outline_pane = True</vh></v>
<v t="ekr.20080412082246.1"><vh>@bool fixedWindow = False</vh></v>
</v>
</v>
<v t="ekr.20041001211817"><vh>Buttons</vh>
<v t="ekr.20070531102813"><vh>@ignore Disabled buttons</vh>
<v t="ekr.20071002150320"><vh>@button create-canvas</vh></v>
<v t="ekr.20100812102648.2193"><vh>@button format-code</vh>
<v t="ekr.20100812102648.2195"><vh>&lt;&lt; options &gt;&gt;</vh></v>
<v t="ekr.20100812114823.2176"><vh>The code-to-rst command</vh>
<v t="ekr.20100812114823.2177"><vh>code_to_rst_command &amp; helpers</vh>
<v t="ekr.20100812114823.2178"><vh>write_code_body &amp; helpers</vh>
<v t="ekr.20100812114823.2179"><vh>split_parts</vh></v>
<v t="ekr.20100812114823.2180"><vh>write_code_block</vh></v>
</v>
<v t="ekr.20100812114823.2181"><vh>write_code_headline &amp; helper</vh>
<v t="ekr.20100812114823.2182"><vh>write_code_headline_helper</vh></v>
</v>
<v t="ekr.20100812114823.2183"><vh>write_code_node</vh></v>
<v t="ekr.20100812114823.2184"><vh>write_code_tree</vh></v>
</v>
<v t="ekr.20100812114823.2185"><vh>Changed methods</vh>
<v t="ekr.20100812114823.2186"><vh>getOption &amp; setOption</vh></v>
<v t="ekr.20100812114823.2187"><vh>initOptionsFromSettings</vh></v>
<v t="ekr.20100812114823.2188"><vh>writeSpecialTree</vh></v>
</v>
</v>
</v>
<v t="ekr.20090701125834.1765"><vh>@button insert-inst-icon</vh></v>
<v t="ekr.20061030041200"><vh>@button iron-py</vh></v>
<v t="ekr.20110414063538.2372"><vh>@button json r/w</vh>
<v t="ekr.20110414063538.2385"><vh>&lt;&lt; imports &gt;&gt;</vh></v>
<v t="ekr.20110414063538.2383"><vh>TestClass</vh>
<v t="ekr.20110414073628.2389"><vh> utils</vh></v>
<v t="ekr.20110414063538.2384"><vh>main</vh></v>
<v t="ekr.20110414094917.2406"><vh>Reading...</vh>
<v t="ekr.20110414094917.2420"><vh>Not used</vh>
<v t="ekr.20110414094917.2415"><vh>readSaxFile</vh></v>
<v t="ekr.20110414094917.2418"><vh>setPositionsFromVnodes &amp; helper</vh>
<v t="ekr.20110414094917.2419"><vh>archivedPositionToPosition</vh></v>
</v>
<v t="ekr.20110414094917.2416"><vh>resolve_tnode_lists</vh></v>
<v t="ekr.20110414094917.2417"><vh>resolve_archived_position</vh></v>
</v>
<v t="ekr.20110414185051.2435"><vh>create_v_dict</vh></v>
<v t="ekr.20110414094917.2422"><vh>read_json_data &amp; helper</vh>
<v t="ekr.20110414094917.2432"><vh>create_t_dict</vh></v>
</v>
<v t="ekr.20110414094917.2408"><vh>create_json_children</vh></v>
<v t="ekr.20110414094917.2409"><vh>create_json_vnode &amp; helpers</vh>
<v t="ekr.20110414094917.2410"><vh>handle_json_tnode_attributes</vh></v>
<v t="ekr.20110414094917.2411"><vh>handle_json_vnode_attributes</vh></v>
</v>
<v t="ekr.20110414094917.2413"><vh>get_json_ua</vh></v>
</v>
<v t="ekr.20110414094917.2391"><vh>Writing...</vh>
<v t="ekr.20110414063538.2373"><vh>putFile</vh></v>
<v t="ekr.20110414063538.2374"><vh>putTnode</vh></v>
<v t="ekr.20110414063538.2375"><vh>putTnodes</vh>
<v t="ekr.20110414063538.2376"><vh>&lt;&lt; write only those tnodes that were referenced &gt;&gt;</vh></v>
</v>
<v t="ekr.20110414063538.2377"><vh>putVnode</vh>
<v t="ekr.20110414063538.2378"><vh>&lt;&lt; Set gnx = vnode index &gt;&gt;</vh></v>
<v t="ekr.20110414063538.2379"><vh>&lt;&lt; Append attribute bits to attrs &gt;&gt;</vh></v>
<v t="ekr.20110414063538.2380"><vh>&lt;&lt; Append unKnownAttributes to attrs&gt;&gt; fc.put</vh></v>
<v t="ekr.20110414063538.2381"><vh>&lt;&lt; issue informational messages &gt;&gt;</vh></v>
</v>
<v t="ekr.20110414063538.2382"><vh>putVnodes</vh></v>
</v>
</v>
</v>
<v t="ekr.20080806145258.14"><vh>@button Leo2DHTML</vh>
<v t="ekr.20080806145258.15"><vh>&lt;&lt; about LeoToHTML &gt;&gt;</vh></v>
<v t="ekr.20080806145258.16"><vh>&lt;&lt; define dhtml stuff &gt;&gt;</vh></v>
<v t="ekr.20080806145258.17"><vh>escape</vh></v>
<v t="ekr.20080806145258.18"><vh>writeAll</vh></v>
<v t="ekr.20080806145258.19"><vh>writeBody</vh></v>
<v t="ekr.20080806145258.20"><vh>writeHead</vh></v>
<v t="ekr.20080806145258.21"><vh>writeContents</vh></v>
<v t="ekr.20080806145258.22"><vh>writePreamble</vh></v>
<v t="ekr.20080806145258.23"><vh>writePostamble</vh></v>
</v>
<v t="ekr.20101103135707.2439"><vh>@button move head to prev</vh></v>
<v t="ekr.20101103170034.2445"><vh>@button move tail to next</vh></v>
<v t="ekr.20080105115712"><vh>@button pylint</vh>
<v t="ekr.20080115085447"><vh>harmless warnings, errors</vh></v>
<v t="ekr.20080105130903"><vh>warnings</vh></v>
<v t="ekr.20080105120559"><vh>&lt;&lt; define data &gt;&gt;</vh></v>
</v>
<v t="ekr.20090715064044.1782"><vh>@button render-as-sphinx</vh></v>
<v t="ekr.20080807114145.2"><vh>@button run-windows-script</vh>
<v t="ekr.20080807115344.5"><vh>&lt;&lt; imports &gt;&gt;</vh></v>
<v t="ekr.20080807115344.2"><vh>class MySite</vh></v>
<v t="ekr.20080807115344.3"><vh>class Application</vh></v>
<v t="ekr.20080807115344.4"><vh>RunCode</vh></v>
</v>
<v t="ekr.20070115092430"><vh>@button winpdb</vh></v>
<v t="ekr.20080815073750.1"><vh>@button write-nosent-files</vh></v>
<v t="ekr.20070929122956.1"><vh>buttons for networkx</vh>
<v t="ekr.20070929070426"><vh>@button print link</vh></v>
<v t="ekr.20070927175908"><vh>@button leo2graph</vh></v>
<v t="ekr.20070929062147.1"><vh>@button at-graph2graph</vh></v>
<v t="ekr.20070929062147.2"><vh>@button at-networkx2graph</vh>
<v t="ekr.20070929081505"><vh>error</vh></v>
<v t="ekr.20070929074830"><vh>parse</vh></v>
<v t="ekr.20070929072506.2"><vh>parseNodes</vh></v>
<v t="ekr.20070929074830.1"><vh>parseEdges</vh></v>
</v>
<v t="ekr.20070929082546"><vh>@button at-networkx2at-graph</vh>
<v t="ekr.20070929120541"><vh>createEdges</vh></v>
<v t="ekr.20070929120541.1"><vh>createNodes</vh></v>
<v t="ekr.20070929115302"><vh>createTree</vh></v>
<v t="ekr.20070929114410.2"><vh>error</vh></v>
<v t="ekr.20070929114410.3"><vh>parse</vh></v>
<v t="ekr.20070929114410.5"><vh>parseEdges</vh></v>
<v t="ekr.20070929114410.4"><vh>parseNodes</vh></v>
</v>
</v>
<v t="ekr.20110320205650.2495"><vh>Movie buttons</vh>
<v t="ekr.20101014040509.2318"><vh>@@button play/pause (OLD)</vh></v>
<v t="ekr.20101014040509.2321"><vh>@button crash test</vh></v>
<v t="ekr.20101014040509.2316"><vh>@button load video</vh>
<v t="ekr.20101014040509.2317"><vh>run</vh></v>
</v>
<v t="ekr.20110321012354.2495"><vh>@button pause-play</vh></v>
<v t="ekr.20101014040509.2320"><vh>@button show-stack</vh></v>
<v t="ekr.20101014040509.2319"><vh>@button vid-stop</vh></v>
</v>
<v t="ekr.20060904110922"><vh>OPML buttons</vh>
<v t="ekr.20060904111037.1"><vh>@button opml-write</vh></v>
<v t="ekr.20060904111037"><vh>@button opml-read</vh></v>
</v>
<v t="ekr.20090620063706.1826"><vh>Prototype of rendering commands</vh>
<v t="ekr.20090619103402.1818"><vh>@button render-as-html</vh></v>
<v t="ekr.20090619103402.1821"><vh>@button render-as-text</vh></v>
</v>
<v t="ekr.20091013153026.2721"><vh>Prototype of using patternmatch library</vh>
<v t="ekr.20091011110344.1853"><vh>@button find script a</vh></v>
<v t="ekr.20091010091628.1836"><vh>@button create find button</vh>
<v t="ekr.20091010104145.1840"><vh>class patController</vh>
<v t="ekr.20091010104145.1842"><vh>ctor</vh></v>
<v t="ekr.20091010104145.1843"><vh>setup</vh></v>
<v t="ekr.20091010104145.1844"><vh>driver</vh></v>
<v t="ekr.20091010104145.1845"><vh>find</vh></v>
<v t="ekr.20091010104145.1846"><vh>findr</vh></v>
</v>
</v>
<v t="ekr.20091010091628.1837"><vh>find pat a</vh></v>
</v>
<v t="ekr.20100109084336.1996"><vh>Prototypes of gui-dependent cursor move helpers</vh>
<v t="ekr.20100109081612.1984"><vh>@button up</vh></v>
<v t="ekr.20100109081746.1990"><vh>@button up-extend</vh></v>
<v t="ekr.20100109081746.1993"><vh>@button up-page-extend</vh></v>
<v t="ekr.20100109081746.1988"><vh>@button down</vh></v>
<v t="ekr.20100109081746.1992"><vh>@button down-extend</vh></v>
</v>
<v t="ekr.20110526180653.2468"><vh>viewrendered buttons</vh>
<v t="ekr.20110321012354.2496"><vh>@button toggle-renderer</vh></v>
<v t="ekr.20110321073942.2490"><vh>@button lock-unlock-renderer</vh></v>
<v t="ekr.20110321213439.2495"><vh>@button update-renderer</vh></v>
</v>
<v t="ekr.20120923105702.3128"><vh>@button tutorial</vh></v>
<v t="ekr.20120925084214.3144"><vh>@button show-vpos</vh></v>
</v>
</v>
<v t="ekr.20070410063214"><vh>Commands</vh>
<v t="ekr.20111020134534.2594"><vh>@ignore disabled commands</vh>
<v t="ekr.20071128122043"><vh>@command create-shell-tab</vh></v>
<v t="ekr.20060924180049"><vh>@command clones-tab</vh>
<v t="ekr.20060924180049.1"><vh>class cloneNavigator</vh>
<v t="ekr.20060924180049.2"><vh>init</vh></v>
<v t="ekr.20060924180049.3"><vh>getAllClones</vh></v>
<v t="ekr.20060924180049.4"><vh>displayClones</vh>
<v t="ekr.20060924180049.5"><vh>&lt;&lt;Fill listbox with clone parent headlines&gt;&gt;</vh></v>
<v t="ekr.20060924180049.6"><vh>&lt;&lt;Goto selected position when listbox selection changes&gt;&gt;</vh></v>
</v>
</v>
</v>
<v t="ekr.20080823154546.1"><vh>@command parse-python</vh></v>
<v t="edward.20081127113749.2"><vh>@command complete-previous</vh>
<v t="edward.20081127113749.3"><vh>WordCompleter</vh>
<v t="edward.20081127113749.4"><vh>complete_word</vh>
<v t="edward.20081127113749.5"><vh>&lt;&lt;backward search&gt;&gt;</vh>
<v t="edward.20081127113749.6"><vh>&lt;&lt;counter check&gt;&gt;</vh></v>
</v>
<v t="edward.20081127113749.7"><vh>&lt;&lt;forward search&gt;&gt;</vh>
<v t="edward.20081127113749.6"></v>
</v>
<v t="edward.20081127113749.8"><vh>&lt;&lt;clean up and exit&gt;&gt;</vh></v>
</v>
<v t="edward.20081127113749.9"><vh>acceptable_word</vh></v>
<v t="edward.20081127113749.10"><vh>undo_replacement</vh></v>
<v t="edward.20081127113749.11"><vh>redo_replacement</vh></v>
<v t="edward.20081127113749.12"><vh>exit</vh></v>
<v t="edward.20081127113749.13"><vh>run</vh></v>
<v t="edward.20081127113749.14"><vh>adjust</vh></v>
</v>
<v t="edward.20081127113749.15"><vh>getCurrentWord</vh></v>
</v>
<v t="edward.20081127113749.16"><vh>@command complete-next</vh>
<v t="edward.20081127113749.3"></v>
<v t="edward.20081127113749.15"></v>
</v>
</v>
</v>
<v t="ekr.20071026102420.3"><vh>Scripts</vh>
<v t="ekr.20100127111425.2062"><vh>search script (do not delete)</vh>
<v t="ekr.20100731123441.2155"><vh>searchDir</vh></v>
</v>
<v t="ekr.20090309064612.2"><vh> Example scripts</vh>
<v t="ekr.20080701130406.1"><vh>Run pylint on plugins</vh></v>
<v t="ekr.20080617170334.1"><vh>Determining key values</vh></v>
<v t="ekr.20080920101658.1"><vh>getInput</vh></v>
<v t="ekr.20080917063615.1"><vh>getSettingSource</vh></v>
<v t="ekr.20081205104320.1"><vh>run bash script</vh></v>
</v>
<v t="ekr.20071129103842"><vh>create-at-auto-nodes</vh></v>
<v t="ekr.20090428081009.1"><vh>patching auto-completion table</vh></v>
<v t="ekr.20090205070715.1"><vh>print colorer stats</vh></v>
<v t="ekr.20121011100948.4582"><vh>Recursive import script (with cleanups)</vh>
<v t="ekr.20121011100948.4601"><vh>class ImportController</vh>
<v t="ekr.20121011100948.4583"><vh>Pass 1: import_dir</vh></v>
<v t="ekr.20121011100948.4584"><vh>Pass 2: clean_all &amp; helpers</vh>
<v t="ekr.20121011100948.4585"><vh>clean</vh></v>
<v t="ekr.20121011100948.4586"><vh>clean_blank_lines</vh></v>
<v t="ekr.20121011100948.4587"><vh>merge_comment_nodes</vh></v>
<v t="ekr.20121011100948.4588"><vh>merge_extra_nodes</vh></v>
<v t="ekr.20121011100948.4589"><vh>move_decorator_lines</vh></v>
<v t="ekr.20121011100948.4590"><vh>move_doc_string</vh></v>
<v t="ekr.20121011100948.4591"><vh>move_shebang_line</vh></v>
<v t="ekr.20121011100948.4592"><vh>rename_decls</vh></v>
</v>
<v t="ekr.20121011100948.4593"><vh>Pass 3: post_process &amp; helpers</vh>
<v t="ekr.20121011100948.4594"><vh>clear_dirty_bits</vh></v>
<v t="ekr.20121011100948.4595"><vh>dump_headlines</vh></v>
<v t="ekr.20121011100948.4596"><vh>fix_back_slashes</vh></v>
<v t="ekr.20121011100948.4597"><vh>minimize_headlines</vh></v>
<v t="ekr.20121011100948.4598"><vh>remove_empty_nodes</vh></v>
<v t="ekr.20121011100948.4599"><vh>munge_at_file (not used)</vh></v>
</v>
<v t="ekr.20121011100948.4600"><vh>run</vh></v>
</v>
</v>
<v t="ekr.20070517070854"><vh>run script in nullGui</vh></v>
<v t="ekr.20070517071510"><vh>run script with leoBridge</vh></v>
<v t="ekr.20080206055658"><vh>Script to print font settings</vh></v>
</v>
</v>
<v t="ekr.20160420153653.1"><vh>Examples</vh>
<v t="ekr.20131128115544.3333"><vh>display xml as Leo outlines using css</vh>
<v t="ekr.20131106150237.3641"><vh>@button display css</vh>
<v t="ekr.20131106150237.3642"><vh>&lt;&lt; define css &gt;&gt;</vh></v>
<v t="ekr.20131106192510.3643"><vh>css utils</vh></v>
<v t="ekr.20131106150237.3643"><vh>escapeHtml</vh></v>
<v t="ekr.20131106150237.3644"><vh>headlineToHtml</vh></v>
</v>
<v t="ekr.20131106150237.3648" a="M"><vh>test</vh>
<v t="ekr.20131106150237.3651"><vh>child</vh>
<v t="ekr.20131106150237.3652"><vh>grandchild</vh></v>
</v>
<v t="ekr.20131106150237.3651"></v>
</v>
<v t="ekr.20131106150237.3648" a="M"></v>
<v t="ekr.20131106145203.3636"><vh>@html display</vh></v>
</v>
<v t="ekr.20100108090658.1958"><vh>generate key events</vh>
<v t="ekr.20100108090658.1959"><vh>Reference</vh></v>
<v t="ekr.20100108111728.2077"><vh>Binding dicts</vh></v>
<v t="ekr.20100108102030.1962"><vh>&lt;&lt; imports&gt;&gt;</vh></v>
<v t="ekr.20100108102030.1963"><vh>&lt;&lt; constants &gt;&gt;</vh></v>
<v t="ekr.20100108111728.2076"><vh>adjustBindings</vh></v>
<v t="ekr.20100108102217.1966"><vh>overrideCommand</vh></v>
<v t="ekr.20100108102217.1967"><vh>setKeyAndMods</vh></v>
<v t="ekr.20100108102217.1968"><vh>testKeys</vh></v>
</v>
<v t="ekr.20110416065515.2437"><vh>jinja2</vh></v>
<v t="ekr.20101110190130.2451"><vh>leoremote client</vh></v>
<v t="ekr.20121011195530.3405"><vh>pyv8</vh></v>
<v t="ekr.20110325142419.2337"><vh>QCompleter example</vh>
<v t="ekr.20110325142419.2338"><vh>class DictionaryCompleter(QCompleter)</vh></v>
<v t="ekr.20110325142419.2339"><vh>class CompletionTextEdit(QTextEdit)</vh>
<v t="ekr.20110325142419.2340"><vh>ctor</vh></v>
<v t="ekr.20110325142419.2341"><vh>setCompleter</vh></v>
<v t="ekr.20110325142419.2342"><vh>insertCompletion</vh></v>
<v t="ekr.20110325142419.2343"><vh>textUnderCursor</vh></v>
<v t="ekr.20110325144059.2351"><vh>focusInEvent</vh></v>
<v t="ekr.20110325144059.2352"><vh>keyPressEvent</vh></v>
</v>
<v t="ekr.20110325144059.2350"><vh>main</vh></v>
</v>
<v t="ekr.20110511140347.2445"><vh>QTimer</vh></v>
<v t="ekr.20090630141519.1793"><vh>rClick script</vh></v>
<v t="ekr.20120923110028.3131"><vh>Screencasts</vh>
<v t="ekr.20120914093811.2824"><vh>@command start next screencast @key=alt-9</vh></v>
<v t="ekr.20120918103721.2944"><vh>@ignore-tree Text nodes</vh>
<v t="ekr.20120918144251.2965"><vh>@text Intro</vh></v>
<v t="ekr.20120918144251.2964"><vh>@text</vh></v>
<v t="ekr.20120918143835.2964"><vh>@text</vh></v>
<v t="ekr.20120918113531.2956"><vh>@text Intro</vh></v>
<v t="ekr.20120918113531.2957"><vh>@text Motivation</vh></v>
<v t="ekr.20120918111016.2955"><vh>@text How it works</vh></v>
<v t="ekr.20120918121401.2957"><vh>@text Showing nodes</vh></v>
</v>
<v t="ekr.20120914093811.2825"><vh>@screencast common keys</vh>
<v t="ekr.20120914093811.2826"><vh>ctrl-i</vh></v>
<v t="ekr.20120915073533.2862"><vh>typing...</vh>
<v t="ekr.20120914174750.2853"><vh>Black border</vh></v>
<v t="ekr.20120914104624.2829"><vh>ctrl-h</vh></v>
<v t="ekr.20120914182320.2853"><vh>typing</vh></v>
<v t="ekr.20120914104624.2832"><vh>return</vh></v>
<v t="ekr.20120914104624.2833"><vh>tying in body</vh></v>
</v>
<v t="ekr.20120914104624.2834"><vh>another inserted node</vh></v>
<v t="ekr.20120914104624.2835"><vh>Ctrl-R</vh></v>
<v t="ekr.20120914104624.2836"><vh>Up</vh></v>
<v t="ekr.20120914104624.2837"><vh>Left</vh></v>
<v t="ekr.20120914104624.2838"><vh>Right</vh></v>
<v t="ekr.20120914174750.2850"><vh>That's all</vh></v>
<v t="ekr.20120914174750.2851"><vh>clean up and quit</vh></v>
</v>
<v t="ekr.20120915181136.2907"><vh>@screencast Ctrl-F</vh>
<v t="ekr.20120916063628.2912"><vh>find intro</vh></v>
<v t="ekr.20120916065229.2916"><vh>Ctrl-F</vh></v>
<v t="ekr.20120916140331.2916"><vh>Return</vh></v>
<v t="ekr.20120916184840.2920"><vh>The search succeeds</vh></v>
<v t="ekr.20120916063628.2913"><vh>cleanup and quit</vh></v>
<v t="ekr.20120916184021.2918"><vh>spam</vh></v>
</v>
<v t="ekr.20120917200834.2928"><vh>@screencast How to make screencasts</vh>
<v t="ekr.20120918170946.2994"><vh>Intro</vh>
<v t="ekr.20120918164428.2968"><vh>Nodes</vh></v>
<v t="ekr.20120918170133.2973"><vh>Scripts</vh></v>
<v t="ekr.20120918170946.2976"><vh>Most nodes are hiddeen</vh></v>
<v t="ekr.20120918170133.2974"><vh>Show nodes</vh></v>
</v>
<v t="ekr.20120918174346.3024"><vh>The program counter</vh>
<v t="ekr.20120918170133.2975"><vh>m.p</vh></v>
<v t="ekr.20120918170946.2979"><vh>m.p 2</vh></v>
</v>
<v t="ekr.20120918174346.3026"><vh>Organizing nodes</vh>
<v t="ekr.20120918174346.3018"><vh>organizing screencasts</vh></v>
<v t="ekr.20120918174346.3019"><vh>empty nodes</vh></v>
<v t="ekr.20120918174346.3020"><vh>ignored nodes</vh></v>
<v t="ekr.20120918174346.3021"><vh>example @ignore-node</vh>
<v t="ekr.20120918174346.3022"><vh>@ignore-node whatever</vh></v>
</v>
<v t="ekr.20120918174346.3027"><vh>ignored trees</vh></v>
</v>
<v t="ekr.20120918174346.3025"><vh>m methods</vh>
<v t="ekr.20120918170946.2989"><vh>m.redraw</vh></v>
<v t="ekr.20120918170946.2990"><vh>m.redraw 2</vh></v>
<v t="ekr.20120918170946.2991"><vh>m.redraw 3</vh></v>
<v t="ekr.20120918174346.3028"><vh>captions</vh>
<v t="ekr.20120918170946.2981"><vh>m.log</vh></v>
<v t="ekr.20120918170946.2982"><vh>m.caption</vh></v>
<v t="ekr.20120918170946.2986"><vh>m.body</vh></v>
<v t="ekr.20120918170946.2987"><vh>m.body 2</vh></v>
<v t="ekr.20120918170946.2983"><vh>m.tree</vh></v>
<v t="ekr.20120918170946.2984"><vh>m.tree 2</vh></v>
</v>
<v t="ekr.20120918174346.3029"><vh>images</vh>
<v t="ekr.20120918170946.2992"><vh>m.image</vh></v>
<v t="ekr.20120918170946.2993"><vh>m.image 2</vh></v>
</v>
<v t="ekr.20120918170946.2997"><vh>key handling</vh>
<v t="ekr.20120918170946.2998"><vh>m.head_keys</vh></v>
<v t="ekr.20120918170946.2999"><vh>m.head_keys 2</vh></v>
<v t="ekr.20120918170946.3000"><vh>restore previous headline</vh></v>
<v t="ekr.20120918174346.3014"><vh>m.body_keys</vh></v>
<v t="ekr.20120918174346.3015"><vh>m.body_keys_ 2</vh>
<v t="ekr.20120918174346.3016"><vh>@ignore-node child</vh></v>
</v>
</v>
</v>
<v t="ekr.20120918174346.3023"><vh>more normal examples</vh></v>
<v t="ekr.20120918115916.2954"><vh>m.quit</vh></v>
<v t="ekr.20120918103721.2948"><vh>quit</vh></v>
</v>
<v t="ekr.20120921072549.3028"><vh>@screencast menus</vh>
<v t="ekr.20120922191243.3126"><vh>@ignore-node comments</vh></v>
<v t="ekr.20120922123519.3032"><vh>file</vh>
<v t="ekr.20120922123519.3037"><vh>openwith</vh></v>
<v t="ekr.20120922123519.3033"><vh>recentfiles</vh></v>
<v t="ekr.20120922123519.3034"><vh>read/write</vh></v>
<v t="ekr.20120922123519.3035"><vh>export</vh></v>
</v>
<v t="ekr.20120922123519.3038"><vh>edit</vh>
<v t="ekr.20120922123519.3039"><vh>edit-body</vh></v>
<v t="ekr.20120922123519.3040"><vh>edit-headline</vh></v>
<v t="ekr.20120922123519.3041"><vh>find</vh></v>
</v>
<v t="ekr.20120922124750.3050"><vh>outline</vh>
<v t="ekr.20120922124750.3051"><vh>check</vh></v>
<v t="ekr.20120922124750.3052"><vh>expand/contract</vh></v>
<v t="ekr.20120922124750.3053"><vh>move</vh></v>
<v t="ekr.20120922124750.3054"><vh>mark</vh></v>
<v t="ekr.20120922124750.3055"><vh>goto</vh></v>
</v>
<v t="ekr.20120922124750.3058"><vh>plugins</vh>
<v t="ekr.20120922124750.3059"><vh>core</vh></v>
</v>
<v t="ekr.20120922124750.3057"><vh>cmds</vh>
<v t="ekr.20120922124750.3063"><vh>abbrev</vh></v>
<v t="ekr.20120922124750.3064"><vh>bodyeditors</vh></v>
<v t="ekr.20120922124750.3065"><vh>buffers</vh></v>
<v t="ekr.20120922124750.3066"><vh>chapters</vh></v>
<v t="ekr.20120922124750.3067"><vh>cursorselection</vh>
<v t="ekr.20120922124750.3068"><vh>cursorback</vh></v>
<v t="ekr.20120922124750.3069"><vh>cursorbackextendselection</vh></v>
<v t="ekr.20120922124750.3070"><vh>cursorbackextendto</vh></v>
<v t="ekr.20120922124750.3071"><vh>cursorforward</vh></v>
<v t="ekr.20120922124750.3072"><vh>cursorforwardextendselection</vh></v>
</v>
<v t="ekr.20120922124750.3073"><vh>debugging</vh></v>
<v t="ekr.20120922124750.3074"><vh>filesanddirectories</vh></v>
<v t="ekr.20120922124750.3075"><vh>focus</vh></v>
<v t="ekr.20120922124750.3076"><vh>icons</vh></v>
<v t="ekr.20120922124750.3077"><vh>macros</vh></v>
<v t="ekr.20120922124750.3078"><vh>minibuffer</vh></v>
<v t="ekr.20120922124750.3079"><vh>pickers</vh></v>
<v t="ekr.20120922124750.3080"><vh>rectangles</vh></v>
<v t="ekr.20120922124750.3081"><vh>registers</vh></v>
<v t="ekr.20120922124750.3082"><vh>rstcommands</vh></v>
<v t="ekr.20120922124750.3084"><vh>runscripttests</vh></v>
<v t="ekr.20120922124750.3085"><vh>scrolling</vh></v>
<v t="ekr.20120922124750.3086"><vh>shell</vh></v>
<v t="ekr.20120922124750.3087"><vh>spellcheck</vh></v>
<v t="ekr.20120922124750.3088"><vh>textcommands</vh></v>
<v t="ekr.20120922124750.3089"><vh>togglesettings</vh></v>
<v t="ekr.20120922124750.3090"><vh>yankandkill</vh></v>
</v>
<v t="ekr.20120922124750.3060"><vh>window</vh></v>
<v t="ekr.20120922124750.3061"><vh>help</vh>
<v t="ekr.20120922124750.3062"><vh>helpcommands</vh></v>
</v>
</v>
<v t="ekr.20120915162554.2882"><vh>@screencast minibuffer</vh>
<v t="ekr.20120915162554.2883"><vh>mb intro</vh></v>
<v t="ekr.20120915164308.2886"><vh>mb typing</vh></v>
<v t="ekr.20120915170516.2888"><vh>mb tab </vh></v>
<v t="ekr.20120915173000.2894"><vh>mb no tab</vh></v>
<v t="ekr.20120917133405.2948"><vh>mb backspace</vh></v>
<v t="ekr.20120917133405.2950"><vh>mb backspace</vh></v>
<v t="ekr.20120917133405.2952"><vh>mb backspace</vh></v>
<v t="ekr.20120917133405.2953"><vh>mb e tab</vh></v>
<v t="ekr.20120917133405.2955"><vh>mb 6 backspaces</vh></v>
<v t="ekr.20120916185527.2922"><vh>mb o tab</vh></v>
<v t="ekr.20120915173000.2895"><vh>mb Return</vh></v>
<v t="ekr.20120915174321.2898"><vh>mb inserted node</vh></v>
<v t="ekr.20120915175727.2905"><vh>mb last slide</vh></v>
<v t="ekr.20120916065229.2914"><vh>mb quit</vh></v>
</v>
<v t="ekr.20120914183137.2850"><vh>@screencast the parts of the screen</vh>
<v t="ekr.20120918123030.2960"><vh>Intro</vh></v>
<v t="ekr.20120915122112.2868"><vh>panes</vh>
<v t="ekr.20120914183137.2851"><vh>This is the tree pane</vh></v>
<v t="ekr.20120914183137.2853"><vh>This is the log pane</vh></v>
<v t="ekr.20120914183137.2855"><vh>This is the body pane</vh></v>
<v t="ekr.20120914183137.2856"><vh>The minibuffer</vh></v>
<v t="ekr.20120914183137.2857"><vh>The icon area</vh></v>
</v>
<v t="ekr.20120915122112.2873"><vh>icon box</vh></v>
<v t="ekr.20120915114713.2866"><vh>node icon</vh></v>
<v t="ekr.20120915112650.2864"><vh>dirty icon</vh></v>
<v t="ekr.20120915122112.2871"><vh>text icon</vh></v>
<v t="ekr.20120915122112.2869"><vh>marked icon</vh></v>
<v t="ekr.20120915122112.2870"><vh>clone icon</vh></v>
<v t="ekr.20120915122112.2872"><vh>full icon</vh></v>
<v t="ekr.20120915122112.2874"><vh>save command clears dirty bits</vh></v>
<v t="ekr.20120916063628.2922"><vh>quit</vh></v>
</v>
<v t="ekr.20120913105857.2914"><vh>@screencast Tutorial</vh>
<v t="ekr.20120923110028.3133"><vh>@ignore-tree completed @text nodes</vh>
<v t="ekr.20120913105857.2915"><vh>@text Welcome to Leo!</vh></v>
</v>
<v t="ekr.20120923063534.3130"><vh>Intro</vh></v>
<v t="ekr.20120923115619.3155"><vh>@ignore-tree not yet</vh>
<v t="ekr.20120913105857.2918"><vh>External files</vh>
<v t="ekr.20120913105857.2919"><vh>Thin nodes (explanation &amp; exercise)</vh>
<v t="ekr.20120913105857.2920"><vh>@path ~</vh>
<v t="ekr.20120913105857.2921"><vh>@@thin myfile_thin.py</vh>
<v t="ekr.20120913105857.2922"><vh>imports &amp; setup routines</vh>
<v t="ekr.20120913105857.2923"><vh>imports</vh></v>
<v t="ekr.20120913105857.2924"><vh>init1, init2</vh></v>
</v>
<v t="ekr.20120913105857.2925"><vh>class Foo</vh>
<v t="ekr.20120913105857.2926"><vh>&lt;&lt; docstring &gt;&gt;</vh></v>
<v t="ekr.20120913105857.2927"><vh>spam</vh></v>
<v t="ekr.20120913105857.2928"><vh>eggs</vh></v>
</v>
</v>
</v>
</v>
<v t="ekr.20120913105857.2929"><vh>Auto nodes</vh>
<v t="ekr.20120913105857.2930"><vh>@path ~</vh>
<v t="ekr.20120913105857.2931"><vh>@@auto myfile_auto.py</vh>
<v t="ekr.20120913105857.2932"><vh>imports &amp; setup routines</vh>
<v t="ekr.20120913105857.2933"><vh>imports</vh></v>
<v t="ekr.20120913105857.2934"><vh>init1, init2</vh></v>
</v>
<v t="ekr.20120913105857.2935"><vh>class Foo</vh>
<v t="ekr.20120913105857.2936"><vh>&lt;&lt; docstring &gt;&gt;</vh></v>
<v t="ekr.20120913105857.2937"><vh>spam</vh></v>
<v t="ekr.20120913105857.2938"><vh>eggs</vh></v>
</v>
</v>
</v>
</v>
<v t="ekr.20120913105857.2939"><vh>Shadow nodes</vh>
<v t="ekr.20120913105857.2940"><vh>@path ~</vh>
<v t="ekr.20120913105857.2941"><vh>@@shadow myfile_shadow.py</vh>
<v t="ekr.20120913105857.2942"><vh>imports &amp; setup routines</vh>
<v t="ekr.20120913105857.2943"><vh>imports</vh></v>
<v t="ekr.20120913105857.2944"><vh>init1, init2</vh></v>
</v>
<v t="ekr.20120913105857.2945"><vh>class Foo</vh>
<v t="ekr.20120913105857.2946"><vh>&lt;&lt; docstring &gt;&gt;</vh></v>
<v t="ekr.20120913105857.2947"><vh>spam</vh></v>
<v t="ekr.20120913105857.2948"><vh>eggs</vh></v>
</v>
</v>
</v>
</v>
<v t="ekr.20120913105857.2949"><vh>reStructuredText (@auto-rst)</vh>
<v t="ekr.20120913105857.2950"><vh>@path ~</vh>
<v t="ekr.20120913105857.2951"><vh>@@auto-rst myfile_rst.txt</vh>
<v t="ekr.20120913105857.2952"><vh>Main heading</vh>
<v t="ekr.20120913105857.2953"><vh>subheading 1</vh></v>
<v t="ekr.20120913105857.2954"><vh>subheading 2</vh></v>
</v>
</v>
</v>
</v>
</v>
<v t="ekr.20120913105857.2955"><vh>Configuration (enabling plugins etc.)</vh>
<v t="ekr.20120913105857.2956"><vh>Find out your ~/.leo directory (script)</vh></v>
<v t="ekr.20120913105857.2957"><vh>@@settings</vh>
<v t="ekr.20120913105857.2958"><vh>@enabled-plugins</vh></v>
<v t="ekr.20120913105857.2959"><vh>@@string initial_split_orientation = horizontal</vh></v>
<v t="ekr.20120913105857.2960"><vh>suggested style sheets</vh>
<v t="ekr.20120913105857.2961"><vh>default look (Linux)</vh>
<v t="ekr.20120913105857.2962"><vh>@@data qt-gui-plugin-style-sheet</vh></v>
</v>
<v t="ekr.20120913105857.2963"><vh>A mac look</vh>
<v t="ekr.20120913105857.2964"><vh>@@data qt-gui-plugin-style-sheet</vh></v>
</v>
</v>
<v t="ekr.20120913105857.2965"><vh>@int qt_max_colorized_chars = 200000</vh></v>
<v t="ekr.20120913105857.2966"><vh>@data contextmenu_commands</vh></v>
<v t="ekr.20120913105857.2967"><vh>@bool use_body_focus_border = False</vh></v>
</v>
</v>
<v t="ekr.20120913105857.2968"><vh>Search and replace</vh></v>
<v t="ekr.20120913105857.2969"><vh>Minibuffer</vh></v>
<v t="ekr.20120913105857.2970"><vh>Scripting Leo</vh>
<v t="ekr.20120913105857.2971"><vh>Executing scripts with ctrl+b</vh>
<v t="ekr.20120913105857.2972"><vh>Press ctrl+b here</vh></v>
</v>
<v t="ekr.20120913105857.2973"><vh>Creating script buttons</vh>
<v t="ekr.20120913105857.2974"><vh>@button example-btn</vh></v>
</v>
</v>
</v>
<v t="ekr.20120923110028.3132"><vh>Last slide</vh></v>
<v t="ekr.20120923110028.3136"><vh>Example Tree</vh>
<v t="ekr.20120923110028.3137"><vh>Example outline</vh>
<v t="ekr.20120923110028.3138"><vh>Node b</vh></v>
</v>
</v>
</v>
</v>
<v t="ekr.20100516140428.2135"><vh>sha1 hashes</vh></v>
<v t="ekr.20120311074029.2727"><vh>URL examples</vh>
<v t="ekr.20120312075951.2740"><vh>@url file://{{c.openDirectory}}/../doc/LeoDocs.leo</vh></v>
<v t="ekr.20120311074029.2728"><vh>@url file://C:/prog/test.sh</vh></v>
<v t="ekr.20120311074029.2729"><vh>@url file://C:/prog</vh></v>
<v t="ekr.20120311074029.2730"><vh>@url http://writemonkey.com/index.php</vh></v>
<v t="ekr.20120311074029.2731"><vh>@url file://C:\leo.repo\trunk\leo\doc\LeoDocs.leo#Leo 4.10 Release notes</vh></v>
<v t="ekr.20120311074029.2732"><vh>@url file://../doc/LeoDocs.leo#Leo 4.10 Release notes</vh></v>
<v t="ekr.20120311074029.2733"><vh>@url #--&gt;Before 4.10 b1</vh></v>
<v t="ekr.20120311074029.2734"><vh>@url file://~/ekr.leo</vh></v>
<v t="ekr.20120311074029.2735"><vh>@url file://~/ekr.html</vh></v>
<v t="ekr.20120311074029.2736"><vh>@url file://c:/users/edreamleo/ekr.html</vh></v>
<v t="ekr.20120320072350.2731"><vh>@url ../doc/LeoDocs.leo#Leo 4.10 Release notes</vh></v>
</v>
<v t="ekr.20160401061847.1"><vh>viewrendered examples</vh>
<v t="ekr.20160401073951.1"><vh>Python code</vh></v>
<v t="ekr.20160401061847.2"><vh>@graphics-script</vh></v>
<v t="ekr.20160401061847.3"><vh>@html display Leo tree (cool)</vh></v>
<v t="ekr.20160401061847.4"><vh>@html Leo's home page</vh></v>
<v t="ekr.20160401061847.5"><vh>@image LeoSplash</vh></v>
<v t="ekr.20160401061847.6"><vh>@image splash screen</vh></v>
<v t="ekr.20160401063704.1"><vh>@movie Gayane Ballet (Local file)</vh></v>
<v t="ekr.20160401061847.8"><vh>@movie Gayane Ballet (Url)</vh></v>
<v t="ekr.20160401061847.7"><vh>@movie Sample video (Local file)</vh></v>
<v t="ekr.20160401062424.1"><vh>@movie Sample video (Url)</vh></v>
<v t="ekr.20160401061847.9"><vh>@networkx my network</vh></v>
<v t="ekr.20160401061847.10" a="M"><vh>@svg bubbles sources</vh></v>
<v t="ekr.20160401061847.11"><vh>@svg bubbles.svg</vh></v>
<v t="ekr.20160401061847.12"><vh>@url Leo's home page (md default)</vh></v>
<v t="ekr.20160401065134.1"><vh>@url Leo's home page (md explicit)</vh></v>
<v t="ekr.20160401061847.13"><vh>@url Leo's home page (rST default)</vh></v>
<v t="ekr.20160401065154.1"><vh>@url Leo's home page (rST explicit)</vh></v>
<v t="ekr.20160401061847.15"><vh>@url weather (md default)</vh></v>
<v t="ekr.20160401065735.1"><vh>@url weather (rst default)</vh></v>
<v t="ekr.20160401061847.16"><vh>docstring test</vh></v>
<v t="ekr.20160401061847.17" a="M"><vh>markdown test (including url)</vh></v>
<v t="ekr.20160401061847.18" a="M"><vh>rst test (including url)</vh></v>
</v>
<v t="ekr.20100127111116.2059"><vh>wrapping</vh></v>
</v>
<v t="ekr.20100205114630.2091"><vh>Files</vh>
<v t="ekr.20100204062222.2035"><vh>@@@auto C:\leo.repo\trunk\leo\extensions\Pmw\Pmw_1_3\lib</vh></v>
<v t="ekr.20090706044257.1784"><vh>@@auto ../../install</vh></v>
<v t="ekr.20091230064146.1912"><vh>@@auto xml-tags-test.xml</vh>
<v t="ekr.20100110172917.1943"><vh>xml</vh></v>
<v t="ekr.20100110172917.1944"><vh>test.a</vh></v>
<v t="ekr.20100110172917.1945"><vh>test-b</vh></v>
</v>
<v t="ekr.20100110151049.2004"><vh>@@auto-rst unicode-headline-test.txt</vh>
<v t="ekr.20100110172917.1961"><vh>section 1: Ę</vh></v>
</v>
<v t="ekr.20100203233053.2033"><vh>@@file at-path-in-body-test.py</vh></v>
</v>
<v t="ekr.20070517160058.1"><vh>Prototypes</vh>
<v t="ekr.20080531131542.1"><vh>Prototype of mxTextTools</vh>
<v t="ekr.20080531141227.1"><vh>&lt;&lt; define s &gt;&gt;</vh></v>
<v t="ekr.20080531131542.2"><vh>&lt;&lt; define scan4 tables &gt;&gt;</vh></v>
<v t="ekr.20080531131542.4"><vh>printItem</vh></v>
</v>
<v t="ekr.20100521101729.2148"><vh>Prototype of template</vh></v>
<v t="ekr.20080806145258.12"><vh>Prototype of Leo in Ajax</vh>
<v t="ekr.20080806145258.13"><vh>To do</vh></v>
<v t="ekr.20080806145258.24"><vh>@@file server.py</vh></v>
<v t="ekr.20080806145258.25"><vh>@@file hello.html</vh></v>
<v t="ekr.20080806145258.26"><vh>@@file cgi-bin/edward.py</vh>
<v t="ekr.20080806145702.1"><vh>&lt;&lt; imports &gt;&gt;</vh></v>
<v t="ekr.20080806145258.27"><vh>&lt;&lt; define dhtml stuff &gt;&gt;</vh></v>
<v t="ekr.20080806145258.28"><vh>escape</vh></v>
<v t="ekr.20080806145258.29"><vh>print_all</vh></v>
<v t="ekr.20080806145258.30"><vh>print_body</vh></v>
<v t="ekr.20080806145258.31"><vh>print_head</vh></v>
<v t="ekr.20080806145258.32"><vh>print_leo_dot_js</vh></v>
<v t="ekr.20080806145258.33"><vh>print_tree</vh></v>
</v>
<v t="ekr.20080806145258.1"><vh>@@thin cgi-bin/leo.js</vh></v>
<v t="ekr.20080806145258.34"><vh>@@thin jqueryTest.html</vh></v>
</v>
<v t="ekr.20070929062147"><vh>Prototype of networkx graph tools</vh>
<v t="ekr.20070929122956"><vh>Data trees</vh>
<v t="ekr.20070929114617"><vh>@graph-target</vh></v>
<v t="ekr.20070929072043"><vh>@networkx</vh>
<v t="ekr.20070929072506.1"><vh>@nodes</vh></v>
<v t="ekr.20070929072506"><vh>@edges</vh></v>
</v>
<v t="ekr.20070929070257"><vh>@graph</vh>
<v t="ekr.20070929070257.1"><vh>@node child1</vh>
<v t="ekr.20070929070632"><vh>@link ('ekr', '20070929070257', 2): @node child2</vh></v>
</v>
<v t="ekr.20070929070257.2"><vh>@node child2</vh>
<v t="ekr.20070929070632.1"><vh>@link ('ekr', '20070929070257', 1): @node child1</vh></v>
</v>
</v>
<v t="ekr.20070928095102"><vh>root-node</vh>
<v t="ekr.20070928095102.1"><vh>child1</vh></v>
<v t="ekr.20070928095102.2"><vh>child2</vh></v>
</v>
</v>
</v>
<v t="ekr.20070630142904"><vh>Prototype of pyrex</vh>
<v t="ekr.20070630142904.2"><vh>gcc build docs</vh></v>
<v t="ekr.20070630142904.3"><vh>pyrexc command-line options</vh></v>
<v t="ekr.20070630142904.4"><vh>@@file myModule.pyx</vh></v>
<v t="ekr.20070630142904.5"><vh>Make myModule.c</vh></v>
</v>
<v t="ekr.20090728090618.2837"><vh>pydiction-1.0</vh>
<v t="ekr.20090728090618.2846"><vh>pydiction.vim</vh></v>
<v t="ekr.20090728090618.2847"><vh>README.txt</vh></v>
<v t="ekr.20090728090618.2838"><vh>pydiction.py</vh>
<v t="ekr.20090728090618.2849"><vh>&lt;&lt; docstring &gt;&gt;</vh></v>
<v t="ekr.20090728090618.2839"><vh>&lt;&lt; declarations &gt;&gt;</vh></v>
<v t="ekr.20090728090618.2848"><vh>&lt;&lt; process command line &gt;&gt;</vh></v>
<v t="ekr.20090728090618.2840"><vh>get_submodules</vh></v>
<v t="ekr.20090728090618.2841"><vh>write_dictionary</vh></v>
<v t="ekr.20090728090618.2842"><vh>my_import</vh></v>
<v t="ekr.20090728090618.2843"><vh>remove_duplicates</vh></v>
<v t="ekr.20090728090618.2844"><vh>get_yesno</vh></v>
<v t="ekr.20090728090618.2845"><vh>main</vh></v>
</v>
</v>
<v t="ekr.20080503202744.3"><vh>Rope</vh></v>
<v t="ekr.20071026102420.2"><vh>Screen capture with Wink</vh>
<v t="ekr.20070528111805"><vh>FrontWindowCapture.pyw</vh></v>
<v t="ekr.20070609085533"><vh>@@url c:\prog\wink\ChangeViewMenu.htm</vh></v>
</v>
</v>
<v t="ekr.20090309064612.3"><vh>Tests</vh>
<v t="ekr.20120925073640.3143"><vh>&lt;&lt; docstring &gt;&gt; (scrolling test)</vh></v>
<v t="ekr.20100615095815.2189"><vh>activate/deactivate events</vh></v>
<v t="ekr.20100205074729.2085"><vh>Clone battle test</vh>
<v t="ekr.20100205074729.2086"><vh>node a</vh></v>
<v t="ekr.20100205074729.2087"><vh>@@thin clone-battle-test.txt</vh>
<v t="ekr.20100205074729.2086"></v>
</v>
</v>
<v t="ekr.20100616085524.2191"><vh>config iter</vh></v>
<v t="ekr.20090309064612.4"><vh>Decorator tests</vh>
<v t="ekr.20080628094340.1"><vh>Decorator test</vh></v>
<v t="edward.20081221145716.1"><vh>decorator test 2</vh></v>
</v>
<v t="ekr.20080930114036.1"><vh>Icon stuff</vh>
<v t="ekr.20100824124015.2195"><vh>print icons</vh></v>
<v t="ekr.20080930080501.1"><vh>Add icon row</vh></v>
<v t="ekr.20080930083052.1"><vh>hide icon rows</vh></v>
<v t="ekr.20080930083052.2"><vh>show icon rows</vh></v>
<v t="ekr.20080930085514.1"><vh>clear icon bar</vh></v>
</v>
<v t="ekr.20100103112623.1951"><vh>Insert form-feed</vh></v>
<v t="ekr.20090128131130.1"><vh>posList tests</vh></v>
<v t="ekr.20090128112453.1"><vh>Property tests</vh></v>
<v t="ekr.20100330082345.2120"><vh>pseudoplain</vh></v>
<v t="ekr.20100130095415.2023"><vh>Simulate startup code for non-ascii directories</vh></v>
<v t="ekr.20120426175039.2682"><vh>Socket test</vh>
<v t="ekr.20120426175039.2683"><vh>class Server</vh>
<v t="ekr.20120426175039.2684"><vh>__init__</vh></v>
<v t="ekr.20120426175039.2685"><vh>handle_accept</vh></v>
</v>
<v t="ekr.20120426175039.2686"><vh>class RequestHandler</vh></v>
</v>
<v t="ekr.20090507082111.1904"><vh>test creation of gnx's</vh></v>
<v t="ekr.20120928085003.3150"><vh>Test g.error, g.warning, g.note</vh></v>
<v t="ekr.20121005071615.3175"><vh>test g.importFromPath</vh></v>
<v t="ekr.20090601093755.1802"><vh>Test of @g.command decorator</vh></v>
<v t="ekr.20080924081821.1"><vh>test of autoCompleter.getExternalCompletions (do not deletes)</vh></v>
<v t="ekr.20100911195503.2426"><vh>tests of os.path.relpath</vh></v>
<v t="ekr.20080922164656.1"><vh>Tests of path expressions</vh>
<v t="ekr.20080921144924.1"><vh>Tests of g.os_path_finalize</vh></v>
<v t="ekr.20080922142953.1"><vh>test os_pathExpression</vh></v>
<v t="ekr.20080922164255.1"></v>
<v t="ekr.20080922164255.2"><vh>@@shadow {{c.config.getString('test')}}/eval-shadow-test.txt</vh></v>
<v t="ekr.20080923073240.2"><vh>@path {{c.config.getString('test')}}</vh>
<v t="ekr.20080923073240.1"><vh>@@thin eval-thin-test.txt</vh></v>
</v>
</v>
<v t="ekr.20080531080812.1"><vh>tracer tests</vh></v>
<v t="ekr.20081003094737.1"><vh>Unicode tests</vh>
<v t="ekr.20080701101740.1"><vh>locale tests</vh></v>
<v t="ekr.20080821111715.1"><vh>Standard print test (only works for Latin-1 and ascii)</vh></v>
<v t="ekr.20090525090210.1940"><vh>Unicode characters: La Peña</vh></v>
<v t="ekr.20090617083033.1814"><vh>Test of copy/paste of unicode</vh>
<v t="ekr.20090617083033.1813"><vh>Unicode characters: La Peña תּ</vh></v>
</v>
<v t="ekr.20090618102458.1816"><vh>Converting QString to unicode</vh></v>
<v t="ekr.20100127122240.2063"><vh>Terry's unicode problem</vh></v>
<v t="ekr.20100202115249.2023"><vh>@@thin qttexttest.py</vh></v>
<v t="ekr.20091230081322.1919"><vh>unicode categories</vh></v>
</v>
<v t="ekr.20090514103332.1929"><vh>Unit tests</vh>
<v t="ekr.20090218112656.1"><vh>@test self.assertEqual</vh></v>
<v t="ekr.20090514101216.1927"><vh>@test self.assertNotEqual</vh></v>
<v t="ekr.20100203174233.2032"><vh>@test paste-script</vh></v>
<v t="ekr.20090201192257.1"><vh>@@test macro ab</vh></v>
</v>
<v t="ekr.20120925105035.3146"><vh>Vertical scroll position probe</vh></v>
</v>
<v t="ekr.20160421054609.1"><vh>@clean leo-bridge-test.py</vh></v>
<v t="ekr.20160421123215.1"><vh>kill all output</vh></v>
</vnodes>
<tnodes>
<t tx="edward.20081127113749.10">def undo_replacement(self):
    u = self.c.undoer; c=self.c; p=u.p
    bunch = u.getBead(u.bead)
    c.setBodyString(p, bunch.oldBody)
    c.frame.body.setInsertPoint(bunch.insertPos)</t>
<t tx="edward.20081127113749.11">def redo_replacement(self):
    c = self.c; u=c.undoer; bunch=u.getBead(u.bead+1)
    c.setBodyString(bunch.p, bunch.newBody)
    c.frame.body.setInsertPoint(bunch.insertPos)</t>
<t tx="edward.20081127113749.12">def exit(self):
    #g.app.config.set(c,word_completer_key,'WordCompleter',None)
    #g.app.config.set(c,'next_word_completer','WordCompleter',None)
    self.pos = -1</t>
<t tx="edward.20081127113749.13">def run(self):
    self.adjust(self.p, c.frame.body.getInsertPoint())
    self.complete_word()
</t>
<t tx="edward.20081127113749.14">def adjust(self, p, pos):
    if p != self.p or pos != self.pos:
        self.p = p.copy()
        self.pos = pos
        bs = p.bodyString()
        word = getCurrentWord(bs, pos)
        self.word = word
        self.before = bs[:pos-len(word)]
        self.after = bs[pos:]
        self.search_pos = p.copy()
        if self.back:
            self.chunk = self.before
        else:
            self.chunk = self.after
        self.tried = {word:1}</t>
<t tx="edward.20081127113749.15">def getCurrentWord(s, pos):
    i = pos-1
    while i&gt;=0 and wordsep.find(s[i]) &lt; 0:
         i -= 1
    return s[i+1:pos]</t>
<t tx="edward.20081127113749.16">wordsep = u'., -+\n\r[]{}&lt;&gt;=-+*&amp;%$#@!"\'?/\\|^()~`:;'
word_completer_key = 'next_word_completer'
@others
completer = g.app.config.get(c,word_completer_key,'WordCompleter')
if completer is None:
    completer = WordCompleter(p, c, back=False)
    g.app.config.set(c, word_completer_key, 'WordCompleter', completer)
    completer.run()
else:
    completer.adjust(p, c.frame.body.getInsertPoint())
    completer.complete_word()

</t>
<t tx="edward.20081127113749.2">wordsep = u'., -+\n\r[]{}&lt;&gt;=-+*&amp;%$#@!"\'?/\\|^()~`:;'
word_completer_key = 'back_word_completer'
@others
completer = g.app.config.get(c,word_completer_key,'WordCompleter')
if completer is None:
    completer = WordCompleter(p,c,back=True)
    g.app.config.set(c,word_completer_key,'WordCompleter',completer)
    completer.run()
else:
    completer.adjust(p, c.frame.body.getInsertPoint())
    completer.complete_word()
</t>
<t tx="edward.20081127113749.3">class WordCompleter:
    def __init__(self, p, c, back=True):
        self.p = p.copy()
        self.c = c
        self.back = back
        self.pos = -1
    @others
</t>
<t tx="edward.20081127113749.4">def complete_word(self):
    txt = self.chunk
    word = self.word
    try:
        if self.back:
            &lt;&lt;backward search&gt;&gt;
        else:
            &lt;&lt;forward search&gt;&gt;
        &lt;&lt;clean up and exit&gt;&gt;
    except:
        self.exit()
        g.es_exception()</t>
<t tx="edward.20081127113749.5">p = self.search_pos
start = -1
counter = 0
while p:
    &lt;&lt;counter check&gt;&gt;
    i = txt.rfind(word, 0, start)
    if i == -1:
        p.moveToThreadBack()
        if p:self.chunk = txt = p.bodyString()
        start = -1
    else:
        if self.acceptable_word(i, txt, word):
            self.chunk = txt[:i+len(word)-1]
            return
        start = i+len(word)-1</t>
<t tx="edward.20081127113749.6">counter+=1
if counter &gt; 10000:
    g.es_trace("counter max")
    break</t>
<t tx="edward.20081127113749.7">p = self.search_pos
start = 0
counter = 0
while p:
    &lt;&lt;counter check&gt;&gt;
    i = txt.find(word, start)
    if i == -1:
        p.moveToThreadNext()
        if p:self.chunk = txt = p.bodyString()
        start = 0
    else:
        if self.acceptable_word(i, txt, word):
            self.chunk = txt[i+1:]
            return
        start = i+1</t>
<t tx="edward.20081127113749.8">if len(self.tried) &gt; 1:
    # there was some tries so we need to restore
    self.c.setBodyString(self.p, self.before+self.word+self.after)
    self.c.frame.body.setInsertPoint(self.pos)
return self.exit()</t>
<t tx="edward.20081127113749.9">@ if found word for the first time then try it
@c
def acceptable_word(self, i, txt, word):
    if i == 0 or wordsep.find(txt[i-1]) != -1:
        j = i+len(word)
        while j &lt; len(txt) and wordsep.find(txt[j]) &lt; 0:
            j += 1
        nword = txt[i:j]
        if nword not in self.tried:
            self.tried[nword] = 1
            u = self.c.undoer
            bunch = u.createCommonBunch(p)
            bunch.oldBody = p.bodyString()
            bunch.insertPos = self.pos
            # Set the type &amp; helpers.
            bunch.kind = 'node'
            bunch.undoType = 'complete word'
            bunch.undoHelper = self.undo_replacement
            bunch.redoHelper = self.redo_replacement
            bunch.newBody = newBody = self.before+nword+self.after

            self.c.setBodyString(self.p, newBody)
            self.c.frame.body.setInsertPoint(self.pos)

            bunch.dirtyVnodeList = [p.v]
            bunch.newChanged = u.c.isChanged()
            bunch.newDirty = p.isDirty()
            bunch.newMarked = p.isMarked()

            u.pushBead(bunch)

            return True
    return False
</t>
<t tx="edward.20081221145716.1">def debug(f,*args,**keys):
    if 1:
        def debugCallback(*args,**keys):
            print f.__name__,args,keys
            f(*args,**keys)
            print 'after',f.__name__
        return debugCallback
    else:
        print 'in debug'
        return f
@debug
def spam(a=5):
    g.trace(a,g.callers(4))

spam(3)
spam(a=4)
</t>
<t tx="ekr.20041001211817">import os

g.pr(os.path.exists(os.path.normpath("C:\\Progra~1\\Eclipse")))</t>
<t tx="ekr.20060904110922"></t>
<t tx="ekr.20060904111037">if hasattr(c,'opmlCommands'):
    c.opmlCommands.readOpmlCommand()
else:
    g.es_print('opml plugin not loaded')</t>
<t tx="ekr.20060904111037.1">if hasattr(c,'opmlCommands'):
    c.opmlCommands.writeOpmlCommand()
else:
    g.es_print('opml plugin not loaded')</t>
<t tx="ekr.20060924180049">@
Ever have a clone that is difficult to understand outside the context of its
original parent? Here's some code to help. It displays the headline of the
current node plus the headlines of all the parents of all the clones of the
current node. Selecting a displayed parent headline moves the current node to
the corresponding clone in the outline.

The idea is to be able to quickly see the context of all the clones of the
current node and to be able to easily navigate from one clone instance to the
next.
@c

@others
c.cn = cloneNavigator(c)
c.cn.displayClones(c)
</t>
<t tx="ekr.20060924180049.1">class cloneNavigator:
    '''
       Displays the headline of the current node plus the headlines of
       all the parents of all the clones of the current node.  Selecting
       a displayed parent headline moves the current node to the
       corresponding clone in the outline.
       
       The idea is to be able to quickly see the context of all the clones
       of the current node and to be able to easily navigate from one clone
       instance to the next.
    '''
    @others</t>
<t tx="ekr.20060924180049.2">def __init__ (self,c):
    self.c = c
    import Tkinter as Tk
    if 0:
        f = Tk.Toplevel()
    else:
        log = c.frame.log
        log.selectTab('Clones')
        f = log.tabFrame
        for w in f.winfo_children():
            w.destroy()
    
    # Create and pack empty label and listbox
    self.title = Tk.Label(f)
    self.title.pack(anchor="nw")
    self.lb = Tk.Listbox(f)
    self.lb.pack(expand=1,fill="both")</t>
<t tx="ekr.20060924180049.3">def getAllClones(self,p):
    c = self.c
    def clonesOf(p,p1=p):
        return p.v.t == p1.v.t
    return filter(clonesOf, c.allNodes_iter(copy=True))</t>
<t tx="ekr.20060924180049.4">def displayClones(self,c):
    '''Displays the parent headline for all the clones of the current position'''
    cp = c.currentPosition()
    
    # "Title" is the headline of the current node
    self.title.configure(text=cp.headString())
    
    # Initialize listbox and clone list
    clones = self.getAllClones(cp)
    self.lb.delete(0,self.lb.size()-1)
    
    &lt;&lt;Fill listbox with clone parent headlines&gt;&gt;    
    &lt;&lt;Goto selected position when listbox selection changes&gt;&gt;
</t>
<t tx="ekr.20060924180049.5"># Add the headlines of all the clone parents to the listbox
for p in clones:
    if p.parent():
        text = p.parent().headString()
    else:
        text = "&lt;root&gt;"
    self.lb.insert(self.lb.size(),text)
    
    # Initial listbox selection corresponds to current position
    if p.v == cp.v:
        self.lb.selection_set(self.lb.size()-1)</t>
<t tx="ekr.20060924180049.6"># Callback for when a listbox entry is selected            
def gotoSelectedPosition(event,lb=self.lb,c=c,positions=clones):
    idx = int(lb.curselection()[0])
    p = positions[idx]
    c.frame.tree.expandAllAncestors(p)
    c.selectPosition(p)
    return
self.lb.bind(g.angleBrackets("ListboxSelect"), gotoSelectedPosition)</t>
<t tx="ekr.20061030041200">import os, sys

if 1: # Executes Iron Python in the console. (But not from the tutorials directory).
    path = r'c:\prog\IronPython-1.0.1\ipy.exe'
    args = ['-i']
        
    if 1: # Use present environment.
        os.spawnv(os.P_NOWAIT, path, args)
    else: # Use a pristine environment.
        os.spawnve(os.P_NOWAIT, path, args, os.environ)</t>
<t tx="ekr.20070115092430"># Invoke winpdb for general scripts **not** containing the predefined g, p or d constants.

# This is essentially the same as using the debug command.

import os,subprocess,sys

# Important: scriptFile2 must be different from scriptFile.
filename = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..','test','scriptFile2'))
f = open(filename,'w') 
f.write(p.bodyString()) 
f.close() 
python = sys.executable
pythonDir = g.os_path_dirname(python) 
#winpdb = g.os_path_join(pythonDir,'Scripts','_winpdb.py') # For older versions of winpdb.
winpdb = g.os_path_join(pythonDir,'Lib','site-packages','winpdb.py') # For version 1.1.2 and newer.
os.chdir(g.app.loadDir)
cmdline = '%s %s -t %s' % (python,winpdb,filename) 
subprocess.Popen(cmdline)
</t>
<t tx="ekr.20070224123943"></t>
<t tx="ekr.20070410063214"></t>
<t tx="ekr.20070416075121" str_leo_pos="5"></t>
<t tx="ekr.20070503085527"></t>
<t tx="ekr.20070517070854">import leoGui
oldGui = g.app.gui
g.app.gui = leoGui.nullGui(guiName='testGui')
try:
    fileName = g.os_path_abspath(g.os_path_join(
        g.app.loadDir,'..','doc','LeoDocs.leo'))
    ok,frame = g.openWithFileName(fileName,old_c=c)
    if ok:
        c2 = frame.c
        for p in c2.allNodes_iter():
            g.pr('.'*p.level(),p.headString())
        g.app.closeLeoWindow(frame)
finally:
    g.app.gui = oldGui</t>
<t tx="ekr.20070517071510">import leoBridge

path = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..','doc','LeoDocs.leo'))

if 0: # This can not be run locally: leoBridge.controller starts a Tk event loop.

    controller = leoBridge.controller(gui='nullGui')
    g = controller.globals()
    c = controller.openLeoFile(path)
    n = 0
    for p in c.allNodes_iter():
        n += 1
    g.pr('%d nodes in %s' % (n,path))
    # g.app.closeLeoWindow(c.frame)</t>
<t tx="ekr.20070517160058.1">@language python
</t>
<t tx="ekr.20070528111805"># FrontWindowCapture.pyw
# Version 0.1
# Date    20070526
# Author  Roger Erens (roger AT erens-krekels.net)
"""
        Purpose:
        Capture the image of the front-most window into a fixed-name
        (_front_window), max-size (default MAX_WIDTH is 640 pixels), and
        fixed-format (PNG) file that can easily be used when creating
        documentation for an application on a wiki or in some HTML-docs.
        This script does _not_ copy the captured image to the clipboard (handy
        when creating MS Word or OpenOffice documents) since MS Windows already
        has ALT-PRTSCR to do so.

        Dependencies:
        Fairly recent versions of Python, wxPython, and PIL should be installed

        Start:
        Double click FrontWindowCapture.pyw; an icon appears in the Task Bar (lower right of
        the screen).

        Use:
        Bring a window to the front and then left-click on the
        icon in the Task Bar. A file named '_front_window.png' will be saved
        in the current directory.
        A pictures wider than MAXWIDTH is scaled down in order to make it easily
        used in wikis or HTML-documentation.
        Usually, human intelligence is needed to rename that file; this is also
        why this script does not copy the image to the clipboard.

        End:
        Close the application by right-clicking the icon in the Task Bar.

        Note:
        Make sure that your system is fast enough to find the frontmost
        window. That is, when a virusscanner is running or virtual memory is
        low, this script will choke. You can see what happens by enabling the
        print statements and running this script from a console (change the
        extension from .pyw to .py).
"""
import wx
import sys
import win32ui
import win32gui
import win32con
import time
from PIL import Image, ImageGrab

Image.init()

MAX_WIDTH = 640
BLINK_STATE = 0

class TaskBarApp(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, -1, title, size = (1, 1),
            style=wx.FRAME_NO_TASKBAR| wx.NO_FULL_REPAINT_ON_RESIZE)
        self.tbicon = wx.TaskBarIcon()
        icon = wx.Icon('LeoApp16.ico', wx.BITMAP_TYPE_ICO)
        self.tbicon.SetIcon(icon, 'Click to capture the foremost window')
        self.tbicon.Bind(wx.EVT_TASKBAR_LEFT_UP, self.OnTaskBarLeftClick)
        self.tbicon.Bind(wx.EVT_TASKBAR_RIGHT_UP, self.OnTaskBarRightClick)
        self.Show(True)

    def OnTaskBarLeftClick(self, evt):

        self.FlashIcon(evt)

        def _MyCallback(hwnd, extra ):
            extra.append(hwnd)

        windows = []
        win32gui.EnumWindows(_MyCallback, windows)

        winList = []
        for i in windows:
            if win32gui.IsWindowVisible(i):
                winList.append(i)
                #g.pr(i)

        win32gui.SetForegroundWindow(winList[1])    # found by trial and error
                                                    # that I need the second
                                                    # window from the list
        time.sleep(0.1)  # give the previous command some time to finish

        fgwindow = win32ui.GetForegroundWindow()
        #g.pr("(C)lick!")

        bbox = fgwindow.GetWindowRect()
        img = ImageGrab.grab( bbox)
        width = bbox[2] - bbox[0]
        if width &gt; MAX_WIDTH:
            coeff = MAX_WIDTH * 1. / width
            height = bbox[3] - bbox[1]
            newHeight = int( coeff * height)
            #g.pr(width, height, "scaled down to", MAX_WIDTH, newHeight)
            img = img.resize((MAX_WIDTH,newHeight), Image.ANTIALIAS)
        img = img.convert("P", dither=Image.NONE,
                              palette=Image.ADAPTIVE, colors=256)
        img.save("_front_window.png", "PNG", optimize=1)
        #img.show() # show the image in an image viewer

        self.FlashIcon(evt)

    def OnTaskBarRightClick(self, evt):
        #g.pr("Auta..." # that's about it...)
        self.tbicon.Destroy()
        self.Close(True)
        wx.GetApp().ProcessIdle()

    def FlashIcon(self, evt):
        global BLINK_STATE
        if BLINK_STATE == 0:
            icon = wx.Icon('LeoApp16lick.ico', wx.BITMAP_TYPE_ICO)
            self.tbicon.SetIcon(icon, 'Window is being captured...')
            BLINK_STATE = 1
            return
        else:
            icon = wx.Icon('LeoApp16.ico', wx.BITMAP_TYPE_ICO)
            self.tbicon.SetIcon(icon, 'Click to capture the foremost window')
            BLINK_STATE = 0
            return

class MyApp(wx.App):
    def OnInit(self):
        frame = TaskBarApp(None, -1, ' ')
        frame.Center(wx.BOTH)
        frame.Show(False)
        return True

def main():
    app = MyApp(0)
    app.MainLoop()

if __name__ == '__main__':
    main()

""" CREDITS

    Thanks to
    Roger Upole:
    http://groups.google.com/group/comp.lang.python/
    browse_thread/thread/ff39ec79f7c3248a/
    e600c892772bf52a?lnk=gst&amp;q=screen+capture&amp;rnum=6#e600c892772bf52a
    for his time.sleep() Aha (This took me a year and a half to note!)

    Christian Wyglendowski, Werner Bruhin, and Xavier Morel for the
    http://wiki.wxpython.org/index.cgi/FlashingTaskbarIcon
    discussion

    'Rob aspn at msolutionsinc.com '
    http://mail.python.org/pipermail/python-win32/2003-June/001129.html
    for his suggestion to find out the foremost window

    and of course the usual suspects that created/maintain
    wxPython,
    PIL,
    pywin32,
    LEO,
    gvim,
    and Python itself.
"""</t>
<t tx="ekr.20070531102813"></t>
<t tx="ekr.20070604100125"></t>
<t tx="ekr.20070609085533"></t>
<t tx="ekr.20070630142904"></t>
<t tx="ekr.20070630142904.2">@nocolor

To build your module using GCC is a three step process on Unix:

1. Use Pyrex to translate mymodule.pyx to mymodule.c::

    python pyrexc mymodule.pyx

mymodule.pyx is the name of the Pyrex module you are writing.

2. Compile mymodule.c to mymodule.o::

    gcc -c -fPIC -I/usr/include/python2.2/ mymodule.c

-c  Produces a .o file instead of an executable. 
-fPIC Produces position independent code, so we can dynamically link against it later. 
-I/usr/include/python2.2/ is the location of the Python 2.2 include file.
 The location of your Python include file may differ from /usr/include/python2.2/. 

3 Link the mymodule.o into a mymodule.so::
    
    gcc -shared mymodule.o -lxosd -o mymodule.so

-shared produces a shared-object file, instead of an executable. 
-lxosd links against a C-library, with the name of the library given as the argument. 
</t>
<t tx="ekr.20070630142904.3">@nocolor

The pyrexc command supports the following options:

  Short Long              Argument    Description
  ----- ----              --------    -----------
  -v    --version                     Display version number of pyrex compiler
  -l    --create-listing              Write error messages to a .lis file
  -I    --include-dir     &lt;directory&gt; Search for include files in named 
                                      directory (may be repeated)
  -o    --output-file     &lt;filename&gt;  Specify name of generated C file (only
                                      one source file allowed if this is used)

Anything else is taken as the name of a Pyrex source file and compiled
to a C source file. Multiple Pyrex source files can be specified
(unless -o is used), in which case each source file is treated as the
source of a distinct extension module and compiled separately to
produce its own C file.
</t>
<t tx="ekr.20070630142904.4">def spam(int i, char *s):
    if 1:
        g.pr(i,s)</t>
<t tx="ekr.20070630142904.5"># Use pyrexc to create myModule.c from myModule.pyx.

import os,sys
python = sys.executable
theFile = r'C:\prog\tigris-cvs\leo\test\myModule.pyx'
pyrexc = r'c:\prog\Pyrex-0.9.6.4\pyrexc.py'
os.system(r'%s %s %s' % (python,pyrexc,theFile))

# Use pyrex/Demos/setup.py to create module on Linux.</t>
<t tx="ekr.20070723091227">
        
        
        </t>
<t tx="ekr.20070723091227.1"></t>
<t tx="ekr.20070723091227.2"></t>
<t tx="ekr.20070723091227.3"></t>
<t tx="ekr.20070927175908">'''Convert a normal Leo tree to a networkx graph'''
import networkx as nx
import sys

x = nx.Graph()

def node_id(p):
    return '%s: %s' % (id(p.v.t),p.headString())

def addTree(p):
    x.add_node(node_id(p))
    for child in p.children_iter():
        addTree(child)
        x.add_edge(node_id(p),node_id(child))

addTree(p)

g.pr('nodes...\n', g.listToString(x.nodes(),sort=True))
g.pr('edges...\n', g.listToString(x.edges(),sort=True))
g.pr('yaml...\n')
nx.write_yaml(x,sys.stdout) # 'graph.yaml')
</t>
<t tx="ekr.20070928095102">@ This is a plain Leo tree.

You can convert it to a networkx graph using the leo2graph button.
</t>
<t tx="ekr.20070928095102.1"></t>
<t tx="ekr.20070928095102.2"></t>
<t tx="ekr.20070929062147">@nocolor

The following scripts convert between Leo trees and NetworkX graphs.

- leo2graph:            convert a normal Leo tree to a NetworkX graph.
- at-graph2graph:       convert an @graph tree to a Networkx graph.
- at-networkx2graph:    convert an @networkx tree to a Networkx graph
- at-networkx2at-graph: create an @graph tree from an @networkx tree.

Not ready yet:

- tree2pict: convert a Leo @graph tree to a picture of the corresponding graph.

@color</t>
<t tx="ekr.20070929062147.1">'''Convert an @graph tree to a networkx graph.'''
import networkx as nx
import sys

x = nx.Graph()

def node_id(p):
    return '%s: %s' % (str(p.v.t.fileIndex),p.headString())

def addTree(p):
    tag = '@link'
    h = p.headString()
    if h.startswith('@graph'):
        for child in p.children_iter():
            addTree(child)
    elif h.startswith('@node'):
        x.add_node(node_id(p))
        for child in p.children_iter():
            h = child.headString()
            if h.startswith(tag):
                link = h[len(tag):].strip()
                if link: x.add_edge(node_id(p),link)
            elif child.headString().startswith('@node'):
                addTree(child)
                x.add_edge(node_id(p),node_id(child))

addTree(p)

g.pr('nodes...\n', g.listToString(x.nodes(),sort=True))
g.pr('edges...\n', g.listToString(x.edges(),sort=True))
g.pr('yaml...\n')
nx.write_yaml(x,sys.stdout) # 'graph.yaml')</t>
<t tx="ekr.20070929062147.2">'''Convert an @networkx node to a networkx graph.'''
import networkx as nx
import sys

@others

x = nx.Graph()

edges,nodes = parse(p)

for z in nodes:
    x.add_node(z)

for z in edges:
    a,b = z
    x.add_edge(a,b)

g.pr('\nnodes...\n', g.listToString(x.nodes(),sort=True))
g.pr('\nedges...\n', g.listToString(x.edges(),sort=True))
g.pr('\nyaml...\n')
nx.write_yaml(x,sys.stdout) # 'graph.yaml')
</t>
<t tx="ekr.20070929070257">@ This is an @graph tree.

You can convert it to a networkx graph using the at-graph2graph button.</t>
<t tx="ekr.20070929070257.1"></t>
<t tx="ekr.20070929070257.2"></t>
<t tx="ekr.20070929070426">g.es('@link %s: %s' % (str(p.v.t.fileIndex),p.headString()))</t>
<t tx="ekr.20070929070632"></t>
<t tx="ekr.20070929070632.1"></t>
<t tx="ekr.20070929072043">@ This node defines a networkx graph using nodes and edges.

You can create an @graph tree from this node using the graph2at-graph button.
</t>
<t tx="ekr.20070929072506"># Each edge is represented as two lines.

# child1 --&gt; child2
('ekr', '20070929070257', 1): @node child1
('ekr', '20070929070257', 2): @node child2

# child2 --&gt; child1
('ekr', '20070929070257', 2): @node child2
('ekr', '20070929070257', 1): @node child1

</t>
<t tx="ekr.20070929072506.1"># Each node is on a separate line.

('ekr', '20070929070257', 1): @node child1
('ekr', '20070929070257', 2): @node child2
</t>
<t tx="ekr.20070929072506.2">def parseNodes (p):

    s = p.bodyString()
    lines = [str(z).strip() for z in g.splitLines(s) if z.strip() and not z.startswith('#')]
    # g.trace(g.listToString(lines))
    return lines
</t>
<t tx="ekr.20070929074830">def parse (p):

    tag = '@networkx'
    if not p.headString().startswith(tag):
        p = g.findNodeAnywhere(c,tag)
        if not p.headString().startswith(tag):
            error('No %s node in the outline' % tag)
            return [],[]

    nodes = []
    for tag in ('@edges','@nodes'):
        node = g.findNodeInTree(c,p,tag)
        if node:
            nodes.append(node)
        else:
            error('No %s node in @networkx tree' % tag)
            return [],[]
    edgesNode,nodesNode = nodes
    edges = parseEdges(edgesNode)
    nodes = parseNodes(nodesNode)
    return edges,nodes
</t>
<t tx="ekr.20070929074830.1">def parseEdges (p):

    s = p.bodyString()
    lines = [str(z).strip() for z in g.splitLines(s) if z.strip() and not z.startswith('#')]
    # g.trace(len(lines),lines)
    if (len(lines) % 2) == 0:
        i = 0 ; edges = []
        while i &lt; len(lines):
            data = lines[i],lines[i+1]
            edges.append(data)
            i += 2
        # g.trace(g.listToString(edges))
        return edges
    else:
        error('edges node must have even number of lines')
        return []

</t>
<t tx="ekr.20070929081505">def error (s):

    g.es_print(s,color='red')
</t>
<t tx="ekr.20070929082546">'''Convert an @networkx node to an @graph tree.
Create the tree as the child of the @graph-target node,
or the current position if no such node.'''

import networkx as nx
import sys

@others

g.pr('=' * 10)

p,edges,nodes = parse(p)

createTree(p,edges,nodes)
</t>
<t tx="ekr.20070929114410.2">def error (s):

    g.es_print(s,color='red')
</t>
<t tx="ekr.20070929114410.3">def parse (p):

    tag = '@graph-target'
    if not p.headString().startswith(tag):
        p = g.findNodeAnywhere(c,tag)
    if not (p and p.headString().startswith(tag)):
        p = c.currentPosition() # Use the presently selected node.

    nodes = [] ; tag = '@networkx'
    data = g.findNodeAnywhere(c,tag)
    if not data:
        error('No %s tree' % tag)
        return None,[],[]
    for tag in ('@edges','@nodes'):
        node = g.findNodeInTree(c,data,tag)
        if node:
            nodes.append(node)
        else:
            error('No %s node in @networkx tree' % tag)
            return None,[],[]
    edgesNode,nodesNode = nodes
    edges = parseEdges(edgesNode)
    nodes = parseNodes(nodesNode)
    return p,edges,nodes
</t>
<t tx="ekr.20070929114410.4">def parseNodes (p):

    s = p.bodyString()
    lines = [str(z).strip() for z in g.splitLines(s) if z.strip() and not z.startswith('#')]
    # g.trace(g.listToString(lines))
    return lines
</t>
<t tx="ekr.20070929114410.5">def parseEdges (p):

    s = p.bodyString()
    lines = [str(z).strip() for z in g.splitLines(s) if z.strip() and not z.startswith('#')]
    # g.trace(len(lines),lines)
    if (len(lines) % 2) == 0:
        i = 0 ; edges = []
        while i &lt; len(lines):
            data = lines[i],lines[i+1]
            edges.append(data)
            i += 2
        # g.trace(g.listToString(edges))
        return edges
    else:
        error('edges node must have even number of lines')
        return []

</t>
<t tx="ekr.20070929114617">@ This will be the root node for the @graph tree produced by the at-networkx2at-graph button.</t>
<t tx="ekr.20070929115302">def createTree (parent,edges,nodes):

    if 0:
        g.trace('nodes...\n', g.listToString(nodes,sort=True))
        g.trace('edges...\n', g.listToString(edges,sort=True))

    c.beginUpdate()
    try:
        p = parent.insertAsLastChild()
        p.setHeadString('@graph')
        d = createNodes(p,nodes)
        createEdges(d,edges)
        c.selectPosition(p)
    finally:
        c.endUpdate()
</t>
<t tx="ekr.20070929120541">def createEdges (d,edges):

    for edge in edges:
        a,b = edge
        g.trace('\n%s --&gt; %s' % (a,b))
        p = d.get(a)
        if p:
            p2 = p.insertAsLastChild()
            p2.setHeadString('@link %s' % (b))
        else:
            error('@node not found: %s' % (a))
</t>
<t tx="ekr.20070929120541.1">def createNodes (parent,nodes):

    d = {}

    for node in nodes:
        # g.trace(node)
        p = parent.insertAsLastChild()
        p.setHeadString('@node %s' % (node))
        d[node] = p.copy()

    return d
</t>
<t tx="ekr.20070929122956"></t>
<t tx="ekr.20070929122956.1"></t>
<t tx="ekr.20071002150320">log = c.frame.log
tag = 'my-canvas'

w = log.canvasDict.get(tag)
if not w:
    w = log.createCanvas(tag)
    w.configure(bg='yellow')

log.selectTab(tag)
</t>
<t tx="ekr.20071025193940"># Standard plugins
free_layout.py
mod_scripting.py
nav_qt.py
plugins_menu.py
quicksearch.py
viewrendered.py

# testing
# active_path.py
screencast.py
vim.py

### UNL.py # moved to core.
### scrolledmessage.py is broken at present.

# Other useful plugins...

# attrib_edit.py
# codewisecompleter.py
# contextmenu.py
# ctagscompleter.py
# graphed.py
# ipython.py
# leoOPML.py
# leo_to_html.py
# leoremote.py
# mod_autosave.py
# nodenavigator.py
# open_with.py
# pydeeshell.py
# rst3.py
# screenshots.py
# stickynotes.py # requires Python 3.0
# stickynotes_plus.py
# templates.py
# vim.py
# xemacs.py

# test of @bool warn_when_plugins_fail_to_load
# xyzzy.py 
</t>
<t tx="ekr.20071026102420.2"></t>
<t tx="ekr.20071026102420.3"></t>
<t tx="ekr.20071128122043">log = c.frame.log ; tag = 'Shell'
frame1 = log.frameDict.get(tag)
shellKind = 'text' # in ('plain','text','canvas')

if frame1:
    log.selectTab(tag)
elif shellKind == 'plain':
    log.selectTab (tag,createText=False)
    frame = log.frameDict.get(tag)
elif shellKind == 'text':
    log.selectTab (tag,createText=True)
    frame = log.textDict.get(tag)
elif shellKind == 'canvas':
    log.createCanvas(tag)
    log.selectTab(tag)
    frame = log.canvasDict.get(tag)
else:
    frame = None
    g.es('bad shellKind',shellKind)

if frame and not frame1:
    frame.configure(bg='white')
    g.pr('logFrame',log.frameDict.get(tag))
</t>
<t tx="ekr.20071129103842"># A script to create @auto nodes from all .py files in a directory.

import glob,os

reallyCreate = True
baseDir = r'c:\leo.repo\pythoscope\lib2to3\pgen2'
dirs = (r'',)
g.pr('-----')

for theDir in dirs:
    pattern = g.os_path_join(baseDir,theDir,'*.py')
    files = glob.glob(pattern)
    g.pr(pattern)
    # g.pr(g.listToString(files))
    for name in files:
        h = '@auto %s' % (name[len(baseDir) + 1:].strip())
        g.pr('creating',h)
        if reallyCreate:
            child = p.insertAsLastChild()
            child.initHeadString(h)</t>
<t tx="ekr.20080105115712"># This hangs Leo while pylint is running.
import pylint.lint as lint
import sys

rcFile = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..','test','pylint-leo-rc.txt'))
rcArg = '--rcfile=%s' % rcFile
&lt;&lt; define data &gt;&gt;

# We expect only one W104 error, in leoGlobals.py
g.pr('\n','=' * 40)
for name,s in data:
    name2 = g.os_path_abspath(g.os_path_join(g.app.loadDir,name))
    args = [name2,rcArg]
    if s.strip():
        args.append('--disable-msg=%s' % s)
    g.pr(name,s)
    lint.Run(args)
g.pr('\n' + 'End of pylint run')</t>
<t tx="ekr.20080105120559">data = (
    ('leoAtFile.py',''), 
    ('leoChapters.py',''),
    ('leoCommands.py',''), 
    ('leoEditCommands.py','E1101'),
    ('leoFileCommands.py',''), 
    ('leoFind.py',''),
    ('leoFrame.py',''),
    ('leoGlobals.py','E0602,E1101'),
    ('leoGui.py',''),
    ('leoImport.py',''),
    ('leoMenu.py',''),
    ('leoNodes.py',''),
    ('leoPlugins.py',''),
    ('leoTangle.py',''),
    ('leoUndo.py','W0102'),
    ('leoTkinterDialog.py',''),
    ('leoTkinterFind.py',''),
    ('leoTkinterGui.py',''),
    ('leoTkinterFrame.py','W0221'),
    ('leoTkinterKeys.py',''), 
    ('leoTkinterMenu.py',''), 
    ('leoTkinterTree.py',''),
)
</t>
<t tx="ekr.20080105130903">@nocolor
@
C0111 Missing docstring
C0301 Line too long
C0311 Bad indentation
C0321 More than one statement on a single line
C0322 Operator not preceded by a space
C0323 Operator not followed by a space
C0324 Comma not followed by a space

R0201 Method could be a function.
R0903 Too few public methods (0/1)

W0102 Dangerous default value [] as argument
W0104 Statement seems to have no effect
W0106 Unnecessary semicolon
W0107 Unnecessary pass statement
W0122 Use of the exec statement
W0141 Used builtin function 'map'
W0142 Used * or * magic*
W0201 Attribute defined outside __init__
W0212 Access to a protected member of a client class
W0231 __init__ method from base class is not called
W0232 Class has no __init__ method
W0401 Wildcard import (pychecker)
W0402 Uses of a deprecated module (like string)
W0404 Reimport &lt;module&gt;: let pychecker do this.
W0406 Module import itself
W0602 Using global for x but no assigment is done (leoEditCommands defines classList after all classes).
W0603 Using the global statement
W0612 Unused variable
W0613 Unused argument (sometimes used for debugging)
W0621 Redefining &lt;name&gt; from outer scope: especially __pychecker__
W0622 Redefining built-in
W0631 Using possibly undefined loop variable
W0702 No exception type specified
W0703 Catch "Exception"
W0704 Except doesn't do anything (Except: pass)
W1111 Assigning to a function call that only returns None</t>
<t tx="ekr.20080115085447">@nocolor
@

************* Module leoGlobals
W0104:3871: Statement seems to have no effect
</t>
<t tx="ekr.20080206055658">g.pr('settings...')
for z in ('body','button','headline','log','menu','outline'):
    for z2 in ('family','size','slant','weight',):
        setting = '%s_text_font_%s' % (z,z2)
        g.pr(setting,c.config.get(setting,z2))

g.pr('default sizes...')
for z in ('Body','Log','Menu','Tree'):
    setting = 'default%sFontSize' % z
    g.pr(setting,getattr(c.config,setting))

g.pr('actual fonts...')
for z in ('body','button','headline','log','menu','outline'):
    kind = ('family','size','slant','weight')
    arg0,arg1,arg2,arg3 = args = ['%s_text_font_%s' % (z,z2) for z2 in kind]
    setting = '%s_text_font' % (z)
    g.pr('%20s' % (setting),c.config.getFontFromParams(arg0,arg1,arg2,arg3,defaultSize=12))
</t>
<t tx="ekr.20080412082246.1"></t>
<t tx="ekr.20080503202744.3">import rope.base.project
import rope.contrib.codeassist as codeassist
import leo.core.leoGlobals as g
import leo.core.leoCommands as leoCommands
c2 = leoCommands.Commands(frame=c.frame,fileName='xyz-file')

class leoFSCommands (object):
    def create_file(self,path):         g.trace(path)
    def create_folder(self,path):       g.trace(path)
    def move (self,path,new_location):  g.trace(path,new_location)
    def remove (self,path):             g.trace(path)
    def write (self,path,data):         g.trace(path,data)

path = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..','..'))
    # Make the trunk folder a project
project = rope.base.project.Project(path,fscommands=leoFSCommands)
s = p.bodyString() # Could simulate a write to allow @others.

g.pr('*' * 40)
for pattern in (
    # 'g.', # works.
    # 'g.trace(', # weird.
    # 'rope.base.', # works.
    'g.list', # works: gives g.listToString
    'c2.de', # works.
):
    i = s.find(pattern)
    if i &gt; -1:
        proposals = codeassist.code_assist(project,s,i+len(pattern))
        g.pr('-' * 20)
        g.pr('pattern:',pattern)
        g.pr(g.listToString(proposals))</t>
<t tx="ekr.20080529111617.1"></t>
<t tx="ekr.20080529111617.10">The name of time unit (e.g. days, weeks, hours)</t>
<t tx="ekr.20080529111617.2"></t>
<t tx="ekr.20080529111617.3">The colour used instead of green in progress bars</t>
<t tx="ekr.20080529111617.4">The colour used instead of red in progress bars</t>
<t tx="ekr.20080529111617.5"># list of @file node types to color.
# Uncomment these to enable coloring for these kinds of nodes.
# @asis
# @file
# @auto
# @thin
@auto</t>
<t tx="ekr.20080529111617.6">The base width of progress bars, in pixels.</t>
<t tx="ekr.20080529111617.7">The default number of time units.</t>
<t tx="ekr.20080529111617.8">0: no progress bars
1: unscaled progress bars
2: scaled progress bars</t>
<t tx="ekr.20080529111617.9">pixels per time unit to add to width of scaled progress bars</t>
<t tx="ekr.20080531080812.1">def eggs():
    g.trace()

def spam():
    g.trace()
    eggs()

t = g.startTracer()
spam()
t.stop()
</t>
<t tx="ekr.20080531131542.1">import mx.TextTools as tt

&lt;&lt; define scan4 tables &gt;&gt;
&lt;&lt; define s &gt;&gt;

@others

g.pr('*' * 60)
ok,taglist,nextindex = tt.tag(s,lineTable)
# g.pr(g.listToString(taglist))
for z in taglist:
    printItem(z,level=0)
g.pr('ok:',ok)
</t>
<t tx="ekr.20080531131542.2">from mx.TextTools import * # Required for tags.

ws_charset   = CharSet(' \t')
name_charset = CharSet(alpha)

gnxTable = (
    (None,Is,':',MatchFail),
    (None,AllNotIn,':',MatchFail),
    (None,Is,':',MatchFail,MatchOk),
)

sentinelNameTable = (
    (None,Is,'@',+1,+3),
    (None,Is,'+',+1,+2),
    (None,Is,'-',+1),
    (None,AllInCharSet,name_charset,MatchFail,MatchOk),
)

sentinelTable = (
    # Start of another line.
    # Skip ws.
    (None,AllInCharSet,ws_charset,+1),
    # Require sentinel comment.
    (None,Word,'#@',MatchFail),
    ('kind',Table,sentinelNameTable,MatchFail),
    ('gnx',Table,gnxTable,+1),
    # Everything else is the sentinel value
    ('extra',AllNotIn,'\n',+1),
    (None,Is,'\n',MatchOk,MatchOk),
)

normalLineTable = (
    (None,AllNotIn,'\n',+1),
    (None,Is,'\n',MatchOk,MatchOk),
)

lineTable = (
    ('sent',Table,sentinelTable,+1,+2),
    ('line',Table,normalLineTable,+1,+1),
    ('eof',EOF,Here,-2),
)</t>
<t tx="ekr.20080531131542.4">def printItem(aList,level):

    obj,lt_index,rt_index,subtag = aList
    g.pr('  '*level,obj,repr(s[lt_index:rt_index]))
    if subtag:
        for z in subtag:
            printItem(z,level+1)
</t>
<t tx="ekr.20080531141227.1">path = r'c:\leo.repo\trunk\leo\core\runLeo.py'
f = file(path)
s = f.read()
f.close()</t>
<t tx="ekr.20080604104453.5">@nocolor

This setting determines the initial binding for otherwise-unbound keystrokes
when no mode is in effect.  Note: the keyboard-quit command exits all modes.

The valid values are::

command:  Leo ignores the key (like Vim).
insert:  Leo inserts the key at the cursor (like Emacs)
overwrite: Leo replaces the character at the cursor.</t>
<t tx="ekr.20080617170334.1">@first # -*- coding: utf-8 -*-

import Tkinter as Tk

top = Tk.Toplevel()
w = Tk.Text(top)
w.pack()

def key(event):
    if event.char: g.pr('state',event.state,'char', repr(event.char), repr(event.keysym))

def after():
    g.trace()
    w.event_generate('&lt;Key&gt;',keysym='a')
    w.event_generate('A')
    w.event_generate(g.toEncodedString('Á',encoding='utf8'))
    # w.event_generate('&lt;Key-Control_L&gt;')
    # w.event_generate('c')
    # w.event_generate('Shift-Control-a')

w.bind('&lt;Key&gt;',key)
w.focus_set()
w.update()
# top.after_idle(after)
top.mainloop()
</t>
<t tx="ekr.20080628094340.1">if 0:
    # Called when func is **defined**
    def leo_command(func):
        g.trace(func.__name__)
        return func
else:
    class leo_command:
        def __init__(self,func,c=c):
            self.c = c
            self.func = func
            self.name = func.__name__
            g.pr("registering",self.name)

        def __call__(__self,*__args,**__kw):
            g.pr("before", __self.name)
            try:
                return __self.func(*__args,**__kw)
            finally:
                g.pr("after ", __self.name)
                g.pr('c',c)
                c.outerUpdate()


@leo_command
def hello():
    g.pr("Hello, world!")

hello()
</t>
<t tx="ekr.20080701101740.1">import locale
aList = dir(locale)
# g.pr(g.listToString(aList))

g.pr(g.getpreferredencoding())
# import os
# g.pr(dir(os))
</t>
<t tx="ekr.20080701130406.1">import glob

aList = glob.glob(r'c:\leo.repo\trunk\leo\plugins\*.py')
for z in aList:
    name = g.shortFileName(z)
    if not name.startswith('_'):
        g.pr('echo .')
        g.pr('echo',name)
        g.pr('call pylint.bat core\%s' % name)</t>
<t tx="ekr.20080729153237.1"></t>
<t tx="ekr.20080729153237.2"># True: calls to the garbage collector.</t>
<t tx="ekr.20080729153237.3"># True (recommended): print a message when Leo calls gc.collect explicitly.</t>
<t tx="ekr.20080729153237.4"># True: verbose trace the garbage collector.</t>
<t tx="ekr.20080806145258.1"></t>
<t tx="ekr.20080806145258.12">@nocolor

Notes:
    
- button Leo2dHTML creates leo\test\x.htm, where x is the name of the .leo file
  containing the script. The file contains javascript that allows a browser to
  expand and contract headlines.  Leo2DHTML is *unrelated* to the other files.
    
- leo\test\server.py is a minimal Python server.  Invoke from a console with::
    
    python server.py

To use this server, type this url in a web browser: http://localhost:8080/
The server will print the contents of the directory from which it was invoked.
Choose hello.html to see the 'Hello World' test page.

- leo\test\hello.html is a test page.  It uses leo\test\cgi-bin\edward.py

- leo\test\cgi-bin\edward.py is the script called from hello.leo when the user
  hits the 'Submit Query button.
  This is recompiled (as needed) for every query, which makes testing it easier.
  
  **Important** edward.py returns its result by printing (in a special format):
  Thus, everything you print will be part of the returned form(!). You **can**
  print debug info: just make sure you don't mess up the special conventions:
  the best place to print debugging info is in print_all.

@color</t>
<t tx="ekr.20080806145258.13">@

edward.py:
    
How can we get the content of an input form?</t>
<t tx="ekr.20080806145258.14">@first # -*- coding: utf-8 -*-
@language python
@tabwidth -4

&lt;&lt; about LeoToHTML &gt;&gt;
import leo.core.leoGlobals as g
&lt;&lt; define dhtml stuff &gt;&gt;
@others

fileName = c.frame.shortFileName() # Get current outline file name
if fileName.endswith('.leo'): fileName = fileName[:-4] # Remove .leo suffix
path = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..','test',fileName)) + '.htm'

# Write the file.
f=open(path, 'w')
writeAll(f)
f.close() 
g.es('wrote: %s' % (path),color="turquoise4") 
</t>
<t tx="ekr.20080806145258.15">@

LeoToHTML by Dan Rahmel, modified by EKR.

This @button script creates an .htm file containing the contents of the selected tree.
The file is called x.htm, where x is the name of the .leo file containing the script.
This file is written to the leo/test folder.

The script inserts javascript into the page so that nodes can be expanded and contracted.

The script presently works well.  This script may become the basis for a facebook app.

The generated html passes html-tidy: http://www.w3.org/People/Raggett/tidy/
</t>
<t tx="ekr.20080806145258.16">division = """
&lt;div STYLE="margin-left:3em;text-indent:0em;margin-top:0em; margin-bottom:0em;"&gt;
&lt;h3 onClick="expandcontent('sc%d')" style="cursor:hand; cursor:pointer; margin-top:0em; margin-bottom:0em"&gt;+ %s&lt;/h3&gt;
    &lt;div id="sc%d" class="switchcontent" style="margin-top:0em; margin-bottom:0em;"&gt;
"""

javascript  = """
&lt;script src="cgi-bin/leo.js" type="text/javascript"&gt;&lt;/script&gt;
"""

style = '''
&lt;STYLE type="text/css"&gt;
    BODY {font:x-medium 'Verdana'; margin-right:1.5em}
    PRE {margin:0px; display:inline}
&lt;/STYLE&gt;
'''
</t>
<t tx="ekr.20080806145258.17">def escape (s):

    return s.replace('&amp;','&amp;amp;').replace('&lt;','&amp;lt;').replace('&gt;','&amp;gt;')
</t>
<t tx="ekr.20080806145258.18">def writeAll(f):

    f.write('&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"&gt;')
    f.write('&lt;html&gt;')
    writeHead(f)
    writeBody(f)
    f.write("&lt;/html&gt;")
</t>
<t tx="ekr.20080806145258.19">def writeBody(f):

    f.write('&lt;body class="st" onload="format()"&gt;')
    writeContents(f)
    f.write("&lt;/body&gt;")
</t>
<t tx="ekr.20080806145258.20">def writeHead(f):

    f.write('&lt;head&gt;')
    f.write(style)
    f.write(javascript)
    f.write('&lt;title&gt;%s&lt;/title&gt;' % c.shortFileName())
    f.write('&lt;/head&gt;')
</t>
<t tx="ekr.20080806145258.21">def writeContents(f):

    div = "&lt;div class='c' STYLE='margin-left:4em;margin-top:0em; margin-bottom:0em;'&gt;\n&lt;pre&gt;\n%s\n&lt;/pre&gt;\n&lt;/div&gt;"
    end_div = "&lt;/div&gt;\n&lt;/div&gt;\n"
    n = 1 # The node number
    current = c.currentPosition()
    prev_level = current.level()
    open_divs = 0
    for p in current.self_and_subtree_iter():
        h = p.headString()
        while prev_level &gt;= p.level() and open_divs &gt; 0:
            f.write(end_div)
            prev_level -= 1
            open_divs -= 1
        body = p.bodyString().encode( "utf-8" )
        body = body.rstrip().rstrip("\n")
        f.write(division % (n,escape(h),n))
        open_divs += 1
        if body:
            f.write(div % escape(body))
        prev_level = p.level()
        n += 1

    # Close all divisions.
    while open_divs &gt; 0:
        f.write(end_div)
        open_divs -= 1
</t>
<t tx="ekr.20080806145258.22"># def writePreamble(f):

    # '''Write HTML header information.'''

    # header_start = '''\


# &lt;body class="st" onload="format()"&gt;
# '''

    # for s in (header_start,style,javascript,header_end):
        # # f.write(g.adjustTripleString(s,c.tab_width))
        # f.write(s)
</t>
<t tx="ekr.20080806145258.23"># def writePostamble (f):

    # pass

</t>
<t tx="ekr.20080806145258.24"># A minimal python server for testing.
# To access this server, type this url in a web browser: http://localhost:8080/
# The server will print the contents of the directory from which it was invoked.
# Choose hello.html to see the 'Hello World' test page.

import CGIHTTPServer
import SocketServer

port = 8080

Handler = CGIHTTPServer.CGIHTTPRequestHandler
s = SocketServer.TCPServer(("", port), Handler)

s.server_name = '127.0.0.1' # represents local host.
s.server_port = port

# import os ; print 'cwd', os.getcwd()

print "server.py: serving at port", port
s.serve_forever()
</t>
<t tx="ekr.20080806145258.25">@language html

&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"&gt;
&lt;html&gt;
&lt;head&gt;
&lt;title&gt;&lt;/title&gt;

&lt;!-- Used by edward.old.py
&lt;script language="JavaScript" type="text/javascript"&gt;
   var openImg = new Image();
   openImg.src = "open.gif";
   var closedImg = new Image();
   closedImg.src = "closed.gif";

   function showNode(node) {
      var objBranch = 
         document.getElementById(node).style;
      if(objBranch.display=="block")
         objBranch.display="none";
      else
         objBranch.display="block";
   }

   function swapFolder(img) {
      objImg = document.getElementById(img);
      if(objImg.src.indexOf('closed.gif')&gt;-1)
         objImg.src = openImg.src;
      else
         objImg.src = closedImg.src;
   }
&lt;/script&gt;
--&gt;

&lt;/head&gt;
&lt;body&gt;
&lt;form action="cgi-bin/edward.py" method="GET"&gt;
&lt;input type="submit" name="George"&gt;
&lt;/form&gt;

&lt;p&gt;This is the hello world test page.
The server in server.py should be running when using this page.

&lt;p&gt;The button (form) above should cause the server to send a "GET" request
to the edward.py script, which will respond with a new page.

&lt;/body&gt;
&lt;/html&gt;
</t>
<t tx="ekr.20080806145258.26">@first #! c:\python25\python.exe
@first # -*- coding: utf-8 -*-

'''This is the cgi script called from hello.html when the user hits the button.'''

### Print statements are used to return results (return the form).
### You *can* use print statement for tracing, but only in print_all.
# To do: use cgi.FieldStorage.

@language python
@tabwidth -4
&lt;&lt; imports &gt;&gt;
&lt;&lt; define dhtml stuff &gt;&gt;
@others

if 1: # Open the bridge.
    path = os.path.abspath(os.path.join(leoParentDir,'leo','test','test.leo')) # c does not exist!
    b = leoBridge.controller(gui='nullGui',loadPlugins=False,readSettings=False,verbose=False)
    g = b.globals()
    c = b.openLeoFile(path)
    p = c.rootPosition()
else:
    c = None

# import pdb ; pdb.Pdb() # Doesn't work.
print_all(c)</t>
<t tx="ekr.20080806145258.27">division = """
&lt;div STYLE="margin-left:3em;text-indent:0em;margin-top:0em; margin-bottom:0em;"&gt;
&lt;h3 onClick="expandcontent('sc%d')" style="cursor:hand; cursor:pointer; margin-top:0em; margin-bottom:0em"&gt;+ %s&lt;/h3&gt;
    &lt;div id="sc%d" class="switchcontent" style="margin-top:0em; margin-bottom:0em;"&gt;
"""

style = """
&lt;STYLE type="text/css"&gt;
    BODY {font:x-medium 'Verdana'; margin-right:1.5em}
    PRE {margin:0px; display:inline}
&lt;/STYLE&gt;
"""</t>
<t tx="ekr.20080806145258.28">def escape (s):

    return s.replace('&amp;','&amp;amp;').replace('&lt;','&amp;lt;').replace('&gt;','&amp;gt;')
</t>
<t tx="ekr.20080806145258.29">def print_all(c):

    # This line is required (with extra newline), but does not show on the page.
    print "Content-type:text/html\n"

    print '&lt;!DOCTYPE html PUBLIC "-//W3C//DTD HTML 3.2//EN"&gt;'
    print '&lt;html&gt;'
    if c:
        # Print the page.
        print_head(c)
        print_body(c)
    else:
        # Print the debugging info.
        print '__file__',__file__
        print 'os.getcwd()',os.getcwd()

    print '&lt;/html&gt;'
</t>
<t tx="ekr.20080806145258.30">def print_body(c):

    print '&lt;body class="st" onload="format()"&gt;'

    if 0:
        # Debugging info.
        form = cgi.FieldStorage()
        print repr(form)
        # if form.has_key('name'):
            # print 'name',form['name'].value
        # else:
            # print 'no name'
    print_tree(c)
    print '&lt;/body&gt;'
</t>
<t tx="ekr.20080806145258.31">def print_head(c):

    print '&lt;head&gt;'

    if 1: # Copy the entire leo.js file into the page.
        print '&lt;script type="text/javascript"&gt;'
        print_leo_dot_js(c)
        print '&lt;/script&gt;'

    else: # Possible bug in the python server??
        # The Python says leo.js is not executable(!)
        print '&lt;script src="leo.js" type="text/javascript"&gt;&lt;/script&gt;'

    print '&lt;title&gt;%s&lt;/title&gt;' % (c.shortFileName())
    print '&lt;/head&gt;'
</t>
<t tx="ekr.20080806145258.32">def print_leo_dot_js(c):

    path = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..','test','cgi-bin','leo.js'))

    try:
        f = file(path)
    except IOError:
        print 'can not open',path
        return

    for line in f.readlines():
        print line,

    f.close()
</t>
<t tx="ekr.20080806145258.33">def print_tree(c):

    div = "&lt;div class='c' STYLE='margin-left:4em;margin-top:0em; margin-bottom:0em;'&gt;\n&lt;pre&gt;\n%s\n&lt;/pre&gt;\n&lt;/div&gt;"
    end_div = "&lt;/div&gt;\n&lt;/div&gt;\n"
    n = 1 # The node number
    prev_level = 0
    open_divs = 0
    for p in c.allNodes_iter():
        h = p.headString()
        while prev_level &gt;= p.level() and open_divs &gt; 0:
            print end_div
            prev_level -= 1
            open_divs -= 1
        body = p.bodyString().encode( "utf-8" )
        body = body.rstrip().rstrip("\n")
        print division % (n,escape(h),n)
        open_divs += 1
        if body: print div % escape(body)
        prev_level = p.level()
        n += 1

    # Close all divisions.
    while open_divs &gt; 0:
        print end_div
        open_divs -= 1
</t>
<t tx="ekr.20080806145258.34"></t>
<t tx="ekr.20080806145702.1">import os
import sys

# Add the *parent* of the leo directory to sys.path.
leoParentDir = os.path.abspath(os.path.join(os.path.dirname(__file__),'..','..','..'))

if leoParentDir not in sys.path:
    sys.path.append(leoParentDir)

import leo.core.leoBridge as leoBridge

import cgi
import cgitb ; cgitb.enable()
</t>
<t tx="ekr.20080807114145.2">@
A script button to run any body text as a Windows Script.
See: http://en.wikipedia.org/wiki/Windows_Script_Host

You need the win32 extensions and you must enable the script engine.
Adapted from Active State examples:ch21_active_scripting:ActiveApp.py
http://python.net/crew/mhammond/win32/
@c

&lt;&lt; imports &gt;&gt;

@others

RunCode("python",p.bodyString())
</t>
<t tx="ekr.20080807115344.2">class MySite(axsite.AXSite):
    # Our error handler will simply print to the console.
    def OnScriptError(self, activeScriptError):
        exc = activeScriptError.GetExceptionInfo()
        print "Exception:", exc[1]
        try:
            sourceText = activeScriptError.GetSourceLineText()
        except pythoncom.com_error:
            sourceText = None
        if sourceText is not None: 
            context, lineNo, charNo = activeScriptError.GetSourcePosition()
            print sourceText
            indent = " " * (charNo-1)
            print indent + "^"
        return winerror.S_OK
</t>
<t tx="ekr.20080807115344.3"># A named object for our namespace
# A normal Python COM object (minus registration info)
class Application:
    _public_methods_ = [ 'Echo' ]
    def Echo(self, *args):
        print string.join(map(str, args))

</t>
<t tx="ekr.20080807115344.4"># Create the site and the engine and runs the code.
def RunCode(engineName, code):

    app = win32com.server.util.wrap( Application() )

    # Create a dictionary holding our object model.
    model = {'Application' : app,}

    # Create the scripting site.
    site = MySite(model)
    # Create the engine and add the code.
    engine = site.AddEngine(engineName)
    engine.AddCode(code)

    # Run the code.
    engine.Start()
</t>
<t tx="ekr.20080807115344.5">import string
import sys
from win32com.axscript import axscript
from win32com.axscript.server import axsite
import pythoncom
import win32com.server.util</t>
<t tx="ekr.20080815073750.1">n = 0
for p in c.allNodes_iter():
    if p.isAtNoSentFileNode():
        c.atFileCommands.write(p,nosentinels=True)
        n += 1
g.es('done: %s files written' %(n))</t>
<t tx="ekr.20080821111715.1">@first # -*- coding: utf-8 -*-

# Important: see http://webpages.charter.net/edreamleo/FAQ.html#unicode-issues

import sys

print '=' * 40

e = sys.getdefaultencoding()
assert e.lower() == 'utf-8'
print 'encoding',e

table = (
    'La Peña',
    unicode('La Peña','utf-8'),
    u'La Peña',
    u'La Pe\xf1a',
    # u'AA \u0102 BB',
)

for s in table:
    print type(s)
    g.es_print('g.es_print',s)
    if type(s) != type(u'a'):
        s = unicode(s,e)
    print      'print     ',s
    print      'repr(s)   ',repr(s)
</t>
<t tx="ekr.20080822153619.1"></t>
<t tx="ekr.20080823154546.1">p2 = p.insertAfter()
p2.setHeadString('inserted node')
s = p.bodyString()

# Remove Leo directives.
directives = ['@'+z for z in g.globalDirectiveList]
def isDirective(s):
    for z in directives:
        if s.startswith(z):
            return True
    else: return False
aList = [z for z in g.splitLines(s) if not isDirective(z)]
s = ''.join(aList)
if not s.endswith('\n'): s = s + '\n'

c.importCommands.scanPythonText(s,p2.copy(),atAuto=True)
c.redraw_now()
g.pr('done')</t>
<t tx="ekr.20080917063615.1">aList = (
'aspellbindir',
'wholeword',
'Whole-Word',
'vimcmd',
'huh',
)

for name in aList:
    kind, val = c.config.getSettingSource(name)
    print '%-20s %-20s %s' % (name,repr(val),kind)
</t>
<t tx="ekr.20080920101658.1">def getInput (event=None):

    '''Evaluate a Python Expression entered in the minibuffer.'''

    stateName = 'get-input'
    k = c.k ; state = k.getState(stateName)

    if state == 0:
        k.setLabelBlue('Input: ',protect=True)
        k.getArg(event,stateName,1,getInput)
    else:
        k.clearState()
        g.es_print('input:',k.arg)

getInput()
</t>
<t tx="ekr.20080921144924.1">print(g.os_path_finalize(r'~/.leo/notebook.leo'))
print(g.os_path_finalize(g.os_path_join(g.app.loadDir,r'~/.leo/notebook.leo')))
print(g.os_path_finalize_join(g.app.loadDir,r'~/.leo/notebook.leo'))</t>
<t tx="ekr.20080922142953.1"># @string default_leo_file = ~/.leo/workbook.leo
path = "{{c.config.getString('default_leo_file')}}"
# print g.os_path_expandExpression(path,c=c)
print g.os_path_finalize(path,c=c)</t>
<t tx="ekr.20080922164255.1"></t>
<t tx="ekr.20080922164255.2"></t>
<t tx="ekr.20080922164656.1"></t>
<t tx="ekr.20080923073240.1">{{c.config.getString('test')}}/eval-test.txt
=
c:\leo.repo\trunk\leo\test\eval-test.txt</t>
<t tx="ekr.20080923073240.2"></t>
<t tx="ekr.20080924081821.1"># c.k.ab

# Test this code using the execute-script command.

s = p.bodyString()
lines = g.splitLines(s)
s = lines[0]

theObject,aList = c.k.autoCompleter.getExternalCompletions(s)

print '='*20
print 'theObject',theObject and theObject.__class__
print 'len(completions)',len(aList)
print g.listToString(aList, tag='completion list', sort=True, indent='')
</t>
<t tx="ekr.20080930080501.1">c.frame.iconBar.addRow()
c.frame.addIconButton(text="New")</t>
<t tx="ekr.20080930083052.1">c.frame.hideIconBar()</t>
<t tx="ekr.20080930083052.2">c.frame.showIconBar()</t>
<t tx="ekr.20080930085514.1">c.frame.clearIconBar()</t>
<t tx="ekr.20080930114036.1"></t>
<t tx="ekr.20081003094737.1"></t>
<t tx="ekr.20081205104320.1"># import os
tag = '#!/bin/bash\n'
s = g.getScript(c,p,
    useSelectedText=False,
    forcePythonSentinels=False,
    useSentinels=True)
if not s.startswith(tag):
    s = tag + s
print s
os.system(s)
</t>
<t tx="ekr.20090128112453.1"># print p.b
# p.b = p.b + '\n# new'
# p.h = p.h + 'z'

print c.p

if 0:
    print p.v.u
    print p.v.u.get('key')
    p.v.u['key'] = 'abc'
    print p.v.u.get('key')
    p.v.u = {'key':'xyz'}
    # p.v.u = 'abc'
    print p.v.u

if 0:
    print p.v.t.u
    print p.v.t.u.get('t-key')
    p.v.t.u['t-key'] = 'pdq'
    print p.v.t.u.get('t-key')
    # p.v.t.u = {'key':'pdq'}
    # # p.v.t.u = 'pdq'
    # print p.v.t.u</t>
<t tx="ekr.20090128131130.1">aList = g.posList(c) # Start with all positions
print len(aList)
aList2 = aList.select('plugin',regex=False,removeClones=True)
print aList2.dump(sort=True)
aList3 = aList2.select('http')
print aList3.dump()

# To see the docstring, enable auto-completion and type g.posList?
# g.posList</t>
<t tx="ekr.20090201192257.1">b = p.b
try:
    w = c.frame.body.bodyCtrl
    w.setInsertPoint(0)
    m = c.macroCommands
    fn = g.os_path_finalize_join(g.app.loadDir,'..','..','ekr-macros.txt')
    f = open(fn)
    m.loadMacros(f)
    macro = m.namedMacros.get('ab')
    assert macro
    m.executeMacro(macro)
finally:
    assert p.b =='ab' + b,p.b
    p.b = b
</t>
<t tx="ekr.20090205070715.1">#colorer = c.frame.body.colorizer.highlighter.colorer
g.es ('total characters: %s, keywords: %s, leo_keywords: %s' % (
    colorer.totalChars,
    colorer.totalKeywordsCalls,
    colorer.totalLeoKeywordsCalls))</t>
<t tx="ekr.20090218112656.1"># 'self' is now defined in @test and @suite nodes.
self.assertEqual(1,1)</t>
<t tx="ekr.20090309064612.2"></t>
<t tx="ekr.20090309064612.3"></t>
<t tx="ekr.20090309064612.4"></t>
<t tx="ekr.20090316115500.1"></t>
<t tx="ekr.20090428081009.1">import PyQt4.QtCore as QtCore
import PyQt4.QtGui as QtGui
from PyQt4 import uic

table = (
    (['QtGui'],'object',QtGui),
    (['QtCore'],'object',QtCore),
)

c.k.autoCompleter.defineObjectDict(table)
print c.k.autoCompleter.objectDict.keys()

# print c.k.autoCompleter.objectDict.get('QtCore')</t>
<t tx="ekr.20090507082111.1904">print "---- inserting ----"
p2 = p.insertAsLastChild().copy()
p3 = p.insertAsLastChild().copy()

print [p2.gnx, p3.gnx]

children = p.children_iter()
print [p.gnx for p in children]

c.redraw()</t>
<t tx="ekr.20090514101216.1927"># 'self' is now defined in @test and @suite nodes.
self.assertNotEqual(1,2)</t>
<t tx="ekr.20090514103332.1929">@language python</t>
<t tx="ekr.20090525090210.1940">La Peña</t>
<t tx="ekr.20090601093755.1802">bookmarks = []

@g.command('bookmark')
def bookmark(event):
    c = event.get('c')
    p = c.currentPosition()
    bookmarks.append(p.gnx)
    g.es('bookmarked') </t>
<t tx="ekr.20090617083033.1813">La Peña תּ
</t>
<t tx="ekr.20090617083033.1814"></t>
<t tx="ekr.20090618102458.1816">@first # -*- coding: utf-8 -*-

import PyQt4.QtCore as QtCore

s0 = unicode('La Peña','utf-8')
print s0
e = s0.encode('utf-8',"strict")
print e,repr(e)
s2 = QtCore.QString(s0)
print s2,repr(s2)
s3 = unicode(s2,'utf-8')
print s3
# s4 = QtCore.QString(e)
# print s4</t>
<t tx="ekr.20090619103402.1818"># Warning: this *replaces* the text.

bodyCtrl = c.frame.body.bodyCtrl
w = bodyCtrl.widget # A QTextEdit
s = bodyCtrl.getAllText()
w.setHtml(s)

try:
    # Lock out onTextChanged
    w.changingText = True
    w.setHtml(s)
finally:
    w.changingText = False</t>
<t tx="ekr.20090619103402.1821">bodyCtrl = c.frame.body.bodyCtrl
w = bodyCtrl.widget # A QTextEdit
s = bodyCtrl.getAllText()
w.setPlainText(s)</t>
<t tx="ekr.20090620063706.1826"></t>
<t tx="ekr.20090629105832.1790"></t>
<t tx="ekr.20090630141519.1793">#Example popup handler
from PyQt4 import QtCore

def test_acts(c,p,menu):

   # 'menu' is QMenu instance that was jsut created
   a1 = menu.addAction("Display " + p.h)
   a2 = menu.addAction("Es " + p.h)

   def a1_func():
       g.es("a1 from " + p.h)

   def a2_func():
       g.es("a2 from " + p.h)

   a1.connect(a1, QtCore.SIGNAL("triggered()"), a1_func)
   a2.connect(a2, QtCore.SIGNAL("triggered()"), a2_func)

def test_acts_handler2(c, p, menu):
   a = menu.addAction("Hello from handler 2")
   def f():
       g.es("Hello: " + p.h)

   a.connect(a, QtCore.SIGNAL("triggered()"), f)

def register():
   # the idea is just to append to the normal list g.tree_popup_handlers
   g.tree_popup_handlers.append(test_acts)
   g.tree_popup_handlers.append(test_acts_handler2)

register()</t>
<t tx="ekr.20090701125834.1765">fn = g.os_path_finalize_join(g.app.loadDir,'..','Icons','leo_inst.ico')
assert g.os_path_exists(fn)
c.editCommands.insertIconFromFile(path=fn)
c.bodyWantsFocusNow()</t>
<t tx="ekr.20090706044257.1784">@language unknown_language
#!/bin/sh
#@+leo-ver=4-thin
#@+node:EKR.20040519082027.33:@file-thin ../../install
#@@first

# This script installs Leo on *nix.
# Initial version by by Frank Merenda (fmerenda@yahoo.com)

# Variables...
LEO_PREFIX=${LEO_PREFIX:-/usr/local}
LEO_RUN_SCRIPT_OUTPUT="${LEO_PREFIX}/bin/leo"

# Bug fix: 2008/4/8: replace /lib/leo by /lib.
LEO_LIB_DIR="${LEO_PREFIX}/lib"

echo ""
echo "Prefix directory set to \"$LEO_PREFIX\""

# Make the directory structure
if [ ! -d $LEO_LIB_DIR ] ; then
    echo ""
    echo Making directory structure $LEO_LIB_DIR

    RESULTS=`mkdir -p -m755 $LEO_LIB_DIR 2&gt;&amp;1`
    if [ $? -ne 0 ]; then
        echo Failure making directory $LEO_LIB_DIR!
        exit 1;
    fi
fi

if [ ! -d $LEO_PREFIX/bin ] ; then
    echo ""
    echo Making directory structure $LEO_PREFIX/bin
    RESULTS=`mkdir -p -m755 $LEO_PREFIX/bin 2&gt;&amp;1`
    if [ $? -ne 0 ]; then
        echo Failure making directory $LEO_PREFIX/bin!
        exit 1;
    fi
fi

# Copy the files
cp -rp leo $LEO_LIB_DIR
chown -R root:root $LEO_LIB_DIR

echo "PYTHONPATH=${LEO_PREFIX}/lib python ${LEO_PREFIX}/lib/leo/core/runLeo.py \"\$@\"" &gt; $LEO_RUN_SCRIPT_OUTPUT

RESULTS=`chmod 755 $LEO_RUN_SCRIPT_OUTPUT`   

echo ""
echo "Leo installed successfully"
echo "Make sure ${LEO_PREFIX}/bin is in your path then"
echo "type 'leo filename.leo' to use it."   
echo ""

exit 0;
#@-node:EKR.20040519082027.33:@file-thin ../../install
#@-leo
</t>
<t tx="ekr.20090715064044.1782">@language python

b = p.b
p2 = g.findNodeAnywhere(c,'@sphinx')
if p2:
    c.selectPosition(p2)
else:
    c.insertHeadline(op_name='Create @sphinx node')
    p2 = c.p
    p2.h = '@sphinx'
    c.redraw()

w = c.frame.body.bodyCtrl.widget
w.setHtml(b)
</t>
<t tx="ekr.20090728090618.2837"></t>
<t tx="ekr.20090728090618.2838">@first #!/usr/bin/env python

# Last modified: July 15th, 2009

@language python
@tabwidth -4

&lt;&lt; docstring &gt;&gt;
&lt;&lt; declarations &gt;&gt;

# Path/filename of the vim dictionary file to write to:
PYDICTION_DICT = r'complete-dict'
# Path/filename of the vim dictionary backup file:
PYDICTION_DICT_BACKUP = r'complete-dict.last'

@others

if __name__ == '__main__':
    &lt;&lt; process command line &gt;&gt;
</t>
<t tx="ekr.20090728090618.2839">__author__ = "Ryan Kulla (rkulla AT gmail DOT com)"
__version__ = "1.0"
__copyright__ = "Copyright (c) 2003-2009 Ryan Kulla"

import os
import sys
import types
import shutil
</t>
<t tx="ekr.20090728090618.2840">def get_submodules(module_name, submodules):
    """Build a list of all the submodules of modules."""

    # Try to import a given module, so we can dir() it:
    try:
        imported_module = my_import(module_name)
    except ImportError, err:
        return submodules

    mod_attrs = dir(imported_module)

    for mod_attr in mod_attrs:
        if type(getattr(imported_module, mod_attr)) is types.ModuleType:
            submodules.append(module_name + '.' + mod_attr)

    return submodules


</t>
<t tx="ekr.20090728090618.2841">def write_dictionary(module_name):
    """Write to module attributes to the vim dictionary file."""

    try:
        imported_module = my_import(module_name)
    except ImportError, err:
        return

    mod_attrs = dir(imported_module)

    # Generate fully-qualified module names: 
    write_to.write('\n--- %(x)s module with "%(x)s." prefix ---\n' % 
                   {'x': module_name})
    for mod_attr in mod_attrs:
        if callable(getattr(imported_module, mod_attr)):
            # If an attribute is callable, show an opening parentheses:
            prefix_on = '%s.%s('
        else:
            prefix_on = '%s.%s'
        write_to.write(prefix_on % (module_name, mod_attr) + '\n')

    # Generate non-fully-qualified module names: 
    write_to.write('\n--- %(x)s module without "%(x)s." prefix ---\n' % 
                   {'x': module_name})
    for mod_attr in mod_attrs:
        if callable(getattr(imported_module, mod_attr)):
            prefix_off = '%s('
        else:
            prefix_off = '%s'
        write_to.write(prefix_off % mod_attr + '\n')
</t>
<t tx="ekr.20090728090618.2842">def my_import(name):
    """Make __import__ import "package.module" formatted names."""
    mod = __import__(name)
    components = name.split('.')
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod


</t>
<t tx="ekr.20090728090618.2843">def remove_duplicates(seq, keep=()):
    """

    Remove duplicates from a sequence while perserving order.

    The optional tuple argument "keep" can be given to specificy 
    each string you don't want to be removed as a duplicate.
    """
    seq2 = []
    seen = set();
    for i in seq:
        if i in (keep):
            seq2.append(i)
            continue
        elif i not in seen:
            seq2.append(i)
        seen.add(i)
    return seq2


</t>
<t tx="ekr.20090728090618.2844">def get_yesno(msg="[Y/n]?"):
    """

    Returns True if user inputs 'n', 'Y', "yes", "Yes"...
    Returns False if user inputs 'n', 'N', "no", "No"...
    If they enter an invalid option it tells them so and asks again.
    Hitting Enter is equivalent to answering Yes.
    Takes an optional message to display, defaults to "[Y/n]?".

    """
    while True:
        answer = raw_input(msg)
        if answer == '':
            return True
        elif len(answer):
            answer = answer.lower()[0]
            if answer == 'y':
                return True
                break
            elif answer == 'n':
                return False
                break
            else:
                print "Invalid option. Please try again."
                continue


</t>
<t tx="ekr.20090728090618.2845">def main(write_to):
    """Generate a dictionary for Vim of python module attributes."""
    submodules = []

    for module_name in sys.argv[1:]:
        try:
            imported_module = my_import(module_name)
        except ImportError, err:
            print "Couldn't import: %s. %s" % (module_name, err)
            sys.argv.remove(module_name)

    cli_modules = sys.argv[1:]

    # Step through each command line argument:
    for module_name in cli_modules:
        print "Trying module: %s" % module_name
        submodules = get_submodules(module_name, submodules)

        # Step through the current module's submodules:
        for submodule_name in submodules:
            submodules = get_submodules(submodule_name, submodules)

    # Add the top-level modules to the list too:
    for module_name in cli_modules:
        submodules.append(module_name)

    submodules.sort()

    # Step through all of the modules and submodules to create the dict file:
    for submodule_name in submodules:
        write_dictionary(submodule_name)

    # Close and Reopen the file for reading and remove all duplicate lines:
    write_to.close()
    print "Removing duplicates..."
    f = open(PYDICTION_DICT, 'r')
    file_lines = f.readlines()
    file_lines = remove_duplicates(file_lines, ('\n'))
    f.close()

    # Delete the original file:
    os.unlink(PYDICTION_DICT)

    # Recreate the file, this time it won't have any duplicates lines:
    f = open(PYDICTION_DICT, 'w')
    for attr in file_lines:
        f.write(attr)
    f.close()
    print "Done."
</t>
<t tx="ekr.20090728090618.2846">@language vim
" ============================================================================
" python_pydiction.vim - Module and Keyword completion for Python
" ============================================================================
"
" Author: Ryan Kulla (rkulla AT gmail DOT com)
" Version: 1.0, for Vim 7
" URL: http://www.vim.org/scripts/script.php?script_id=850
" Last Modified: July 18th, 2009
" Installation: On Linux, put this file in ~/.vim/after/ftplugin/
"               On Windows, put this file in C:\vim\vimfiles\ftplugin\
"                        (assuming you installed vim in C:\vim\).
"               You may install the other files anywhere. 
"               In .vimrc, add the following:
"                   filetype plugin on
"                   let g:pydiction_location = 'path/to/complete-dict'
"               Optionally, you set the completion menu height like:
"                   let g:pydiction_menu_height = 20
"               The default menu height is 15
"               To do case-sensitive searches, set noignorecase (:set noic).
" License: BSD
" Copyright: Copyright (c) 2003-2009 Ryan Kulla
"            All rights reserved.
"
"            Redistribution and use in source and binary forms, with or without
"            modification, are permitted provided that the following conditions
"            are met:
"            1. Redistributions of source code must retain the above copyright
"               notice, this list of conditions and the following disclaimer.
"            2. Redistributions in binary form must reproduce the above
"               copyright notice, this list of conditions and the following
"               disclaimer in the documentation and/or other materials provided
"               with the distribution.
"            3. The name of the author may not be used to endorse or promote 
"               products derived from this software without specific prior 
"               written permission.
"
"            THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
"            OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
"            WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
"            ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
"            DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
"            DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
"            GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
"            INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
"            WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
"            NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
"            THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"
"

if v:version &lt; 700
    echoerr "Pydiction requires vim version 7 or greater."
    finish
endif


" Make the Tab key do python code completion:
inoremap &lt;silent&gt; &lt;buffer&gt; &lt;Tab&gt; 
         \&lt;C-R&gt;=&lt;SID&gt;SetVals()&lt;CR&gt;
         \&lt;C-R&gt;=&lt;SID&gt;TabComplete()&lt;CR&gt;
         \&lt;C-R&gt;=&lt;SID&gt;RestoreVals()&lt;CR&gt;


if !exists("*s:TabComplete")
    function! s:TabComplete()
        " Check if the char before the char under the cursor is an 
        " underscore, letter, number, dot or opening parentheses.
        " If it is, and if the popup menu is not visible, use 
        " I_CTRL-X_CTRL-K ('dictionary' only completion)--otherwise, 
        " use I_CTRL-N to scroll downward through the popup menu.
        " If the char is some other character, insert a normal Tab:
        if searchpos('[_a-zA-Z0-9.(]\%#', 'nb') != [0, 0] 
            if !pumvisible()
                return "\&lt;C-X&gt;\&lt;C-K&gt;"
            else
                return "\&lt;C-N&gt;"
            endif
        else
            return "\&lt;Tab&gt;"
        endif
    endfunction
endif


if !exists("*s:SetVals") 
    function! s:SetVals()
        " Save and change any config values we need.

        " Temporarily change isk to treat periods and opening 
        " parenthesis as part of a keyword -- so we can complete
        " python modules and functions:
        let s:pydiction_save_isk = &amp;iskeyword
        setlocal iskeyword +=.,(

        " Save any current dictionaries the user has set:
        let s:pydiction_save_dictions = &amp;dictionary
        " Temporarily use only pydiction's dictionary:
        let &amp;dictionary = g:pydiction_location

        " Save the ins-completion options the user has set:
        let s:pydiction_save_cot = &amp;completeopt
        " Have the completion menu show up for one or more matches:
        let &amp;completeopt = "menu,menuone"

        " Set the popup menu height:
        let s:pydiction_save_pumheight = &amp;pumheight
        if !exists('g:pydiction_menu_height')
            let g:pydiction_menu_height = 15
        endif
        let &amp;pumheight = g:pydiction_menu_height

        return ''
    endfunction
endif


if !exists("*s:RestoreVals")
    function! s:RestoreVals()
        " Restore the user's initial values.

        let &amp;dictionary = s:pydiction_save_dictions
        let &amp;completeopt = s:pydiction_save_cot
        let &amp;pumheight = s:pydiction_save_pumheight
        let &amp;iskeyword = s:pydiction_save_isk

        return ''
    endfunction
endif
</t>
<t tx="ekr.20090728090618.2847">@nocolor
Pydiction 1.0 by Ryan Kulla (http://www.vim.org/scripts/script.php?script_id=850)
-------------

Pydiction is a filetype plugin for python files to be able to tab-complete Python code, including Python's keywords, standard library and even third-party libraries.  

It consists of three main files: 
    python_pydiction.vim -- This is the ftplugin you put in your non-system ftplugin directory. (i.e., ~/.vim/after/ftplugin/, on Unix or C:\vim\vimfiles\ftplugin\, on Windows)
    complete-dict -- This is a vim dictionary file that consists of Python keywords and modules. This is what python_pydiction.vim looks at to know which things are completeable.
    pydiction.py -- This is a Python script that was used to generate complete-dict. You can optionally run this script to add more modules to complete-dict to be able to complete them.


Installing
----------
Unix/Linux: Put python_pydiction.vim in ~/.vim/after/ftplugin/   (if that directory doesn't exist, create it. Vim will know to look there automatically.)
Windows: Put python_pydiction.vim in C:\vim\vimfiles\ftplugin  (assuming you installed vim in C:\vim\).

You may install the other files (complete-dict and pydiction.py) anywhere you want. For this example, we'll assume you put them in "C:\vim\vimfiles\ftplugin\pydiction\" (Do not put any file but python_pydiction.vim in the ftplugin\ directory, only .vim files should go there. It's ok to make a subdirectory in it though, like I just did.)

In your .vimrc file, first add the following line to enable filetype plugins:

    filetype plugin on

then make sure you set "g:pydiction_location" to the full path of where yo uinstalled complete-dict. Ie:

    let g:pydiction_location = 'C:/vim/vimfiles/ftplugin/pydiction/complete-dict'

You can optionally set the height of the completion menu by setting "g:pydiction_menu_height" in your vimrc. The default height is 15:

    let g:pydiction_menu_height = 20

By default, pydiction ignores case while doing Tab-completion. If you want it to do case-sensitive searches, then set noignorecase (:set noic).


Pydiction versus other forms of completion 
------------------------------------------
Pydiction can complete Python Keywords, as well as Python module names, and their attributes and methods. It can also complete both the fully-qualified module names such as "module.method(", as well as non-fully qualified names such as "method(".

Pydiction only uses the Tab-key to complete, uses a special dictionary file to complete from, and only attempts to do it on python files. This has the advantages of only requiring one keystroke to do completion and of not polluting all of your completion menus that you may be using for other types of completion, such as Vim's regular omni-completion, or other completion scripts that you may be running.

Since pydiction uses a dictionary file of possible completion items, it can complete 3rd party modules much more accurately than other ways. You have full control over what it can and can't complete. If it's unable to complete anything you can either use pydiction.py to automatically add a new module's contents to the dictionary or you can even manually add them using a text editor. The dictionary is just a normal text file, which also makes it portable across all platforms.  For example, if you're a PyQT user, you can add all the PyQT related modules to the dictionary file (complete-dict) by using pydiction.py.

Also, because pydiction uses a dictionary file, You don't have to import a module before you can complete it. Nor do you even have to have the module installed. This frees you up to use pydiction as a way of looking up what a module attribute is called without having to install it first.

Pydiction is smart enough to know when you're completing callable method or not and if you are, it will automatically insert an opening parentheses for you.

The Tab key will work as normally expected for everything else. Pydiction will only try to use it to complete python code if you're editing a python file and you first type part of some python code, as specified in complete-dict.

Pydiction doesn't even require that python support be compiled into your version of vim!

python_pydiction.vim
--------------------
Pydiction will make it so your the Tab key on your keyboard is able to complete python code (as long as the functionality has been added to complete-dict).

Version 1.0 of pydiction uses a new file called python_pydiction.vim, which is an ftplugin that only activates when you're editing a python file (e.g., you're editing a file with a ".py" extension or you've manually typed ":set filetype=python").  Past versions of pydiction didn't use a plugin and instead just required you to change the value of "isk" in your .vimrc, which was not desirable. Version 1.0 and greater do not require you to manually change the value of isk, it changes it for you safely by only setting it while you're doing tab completion (of python code only), and automatically changes isk back to its original value whenever tab completion isn't being activated.

Pydiction works by using Vim's omni-completion functionality by temporarily remapping the Tab key to do the same thing as I_CTRL-X_CTRL_K (dictionary only completion). This means, whenever you're editing a Python file and you start typing the name of a python keyword or module, you can press the Tab key to complete it. For example, if you type "os.pa" and then press Tab, pydiction will pop up a completion menu in vim that will look like:
    os.pardir
    os.path
    os.pathconf(
    os.pathconf_names
    os.path.
    os.path.__all__
    os.path.__builtins__
    os.path.__doc__
    ...
Pressing Tab again while the menu is open will scroll down the menu so you can choose whatever item you want to go with, using the normal omni-completion keys:
    &lt;Ctrl-y&gt; will accept the current word.
    &lt;Space&gt; will accept the current word and insert a space.
    &lt;Ctrl-e&gt; will close the menu and not accept any word.

pydiction.py
------------
This is the Python script used to create the "complete-dict" vim dictionary file.  I have created and bundled a default complete-dict for your use. I created it in Ubuntu 9.04 Linux, so there won't be any win32 specific support in it. You're free to run pydiction.py to add as many more modules as you want.  The dictionary file will still work if you're using windows, but it won't complete win32 related modules unless you tell it to.      

Usage: In a command prompt, run: 
    $ python pydiction.py &lt;module&gt; ... [-v]
You have to have python 2.x installed.


Say you wanted to add a module called "mymodule" to complete-dict, do the following:
    $ python pydiction.py mymodule

You can input more than one module name on the command-line, just separate them by spaces:
    $ python pydiction.py mymodule1 mymodule2 mymodule3

The -v option will just write the results to stdout (standard output) instead of the complete-dict file.

If the backfup file "complete-dict.last" doesn't exist in the current directory, pydiction.py will create it for you. You should always keep a backup of your last working dictionary in case anything goes wrong, as it can get tedious having to recreate the file from scratch.

If complete-dict.last already exists, pydiction will ask you if you want to overwrite your old backup with the new backup.

If you try to add a module that already exists in complete-dict, pydiction will tell you it already exists, so don't worry about adding duplicates. In fact, you can't add duplicates, everytime pydiction.py runs it looks for and removes any duplicates in the file.

When pydiction adds new modules to complete-dict, it does so in two phases. First, it adds the fully-qualified name of the module. For example:
    module.attribute
    module.method(

then it adds the non-fully qualified name:
    attribute
    method(

this allows you to complete your python code the way that you imported it in the first place. E.g.:
    import module
or:
    from module import method

Say you want to complete "pygame.display.set_mode". If you imported Pygame using "import pygame", then you can Tab-complete using:
    pygame.di&lt;Tab&gt;
to expand to "pygame.display.". Then type:
    se&lt;Tab&gt; 
to expand to "pygame.display.set_mode("

Now say you imported using "from pygame import display". To expand to "display.set_mode(" just type:
    display.se&lt;Tab&gt;

And if you imported using "from pygame.display import set_mode" just type:
    se&lt;Tab&gt;

Keep in mind that if you don't use fully-qualified module names that you may get a lot of possible menu options popping up and so you may want to use more than just two letters to try to narrow it down. 


complete-dict
-------------
Again, this is the vim dictionary file that python_pydiction.vim reads from and pydiction.py writes to. Without this file, pydiction wouldn't know what python keywords and modules it can Tab-complete.

complete-dict is only an optional file in the sense that you can create your own if you don't want to use the default one that is bundled with pydiction.  The default complete-dict gives you a major headstart as far as what you can Tab-complete because I did my best to put all of the Python keywords, standard library and some popular third party modules in it for you. 

It currently contains:

    Python keywords:

        and       del       for       is        raise    
        assert    elif      from      lambda    return   
        break     else      global    not       try      
        class     except    if        or        while    
        continue  exec      import    pass      yield    
        def       finally   in        print
    
    Most of the standard library and builtins:  __builtin__, __future__, os, sys, time, re, sets, string, math, Tkinter, hashlib, urllib, etc... 

    It also contains some popular third-party libraries: pygame, wxPython, twisted, numarray and OpenGL.

If you open complete-dict in your text editor you'll see sections in it for each module, such as:
 
    --- os module with "os." prefix ---
    os.EX_CANTCREAT
    os.EX_CONFIG
    os.EX_DATAERR
    ...

    --- os module without "os." prefix ---
    EX_CANTCREAT
    EX_CONFIG
    EX_DATAERR
    ...

if certain attributes seem to be missing, it's probably because pydiction removed them because they were duplicates. This mainly happens with the non-fully qualified module sections. So first try searching the entire file for whatever string you assume is missing before you try adding it. For example, if you don't see "__doc__" under "--- sys module without "sys." prefix ---", it's because a previous module, such as "os" already has it.
    
If you try to recreate complete-dict from scratch, you'll need to manually add the Python keywords back to it, as those aren't generated with pydiction.py.

</t>
<t tx="ekr.20090728090618.2848">"""Process the command line."""

if sys.version_info[0:2] &lt; (2, 3):
    sys.exit("You need a Python 2.x version of at least Python 2.3")

if len(sys.argv) &lt;= 1:
    sys.exit("%s requires at least one argument. None given." % 
              sys.argv[0])

if '-v' in sys.argv:
    write_to = sys.stdout
    sys.argv.remove('-v')
elif os.path.exists(PYDICTION_DICT):
        # See if any of the given modules have already been pydiction'd:
        f = open(PYDICTION_DICT, 'r')
        file_lines = f.readlines()
        for module_name in sys.argv[1:]:
            for line in file_lines:
                if line.find('--- %s module with' % module_name) != -1:
                    print '"%s" already exists in %s. Skipping...' % \
                           (module_name, PYDICTION_DICT)
                    sys.argv.remove(module_name)
                    break
        f.close()

        if len(sys.argv) &lt; 2:
            # Check if there's still enough command-line arguments:
            sys.exit("Nothing new to do. Aborting.")

        if os.path.exists(PYDICTION_DICT_BACKUP):
            answer = get_yesno('Overwrite existing backup "%s" [Y/n]? ' % \
                                PYDICTION_DICT_BACKUP)
            if (answer):
                print "Backing up old dictionary to: %s" % \
                       PYDICTION_DICT_BACKUP
                try:
                    shutil.copyfile(PYDICTION_DICT, PYDICTION_DICT_BACKUP)
                except IOError, err:
                    print "Couldn't back up %s. %s" % (PYDICTION_DICT, err)
            else:
                print "Skipping backup..."

            print 'Appending to: "%s"' % PYDICTION_DICT
        else:
            print "Backing up current %s to %s" % \
                   (PYDICTION_DICT, PYDICTION_DICT_BACKUP)
            try:
                shutil.copyfile(PYDICTION_DICT, PYDICTION_DICT_BACKUP)
            except IOError, err:
                print "Couldn't back up %s. %s" % (PYDICTION_DICT, err)
else:
    print 'Creating file: "%s"' % PYDICTION_DICT

write_to = open(PYDICTION_DICT, 'a')

main(write_to)</t>
<t tx="ekr.20090728090618.2849">"""

pydiction.py 1.0 by Ryan Kulla (rkulla AT gmail DOT com).

Description: Creates a Vim dictionary of Python module attributes for Vim's 
             completion feature.  The created dictionary file is used by
             the Vim ftplugin "python_pydiction.vim".

Usage: pydiction.py &lt;module&gt; ... [-v]
Example: The following will append all the "time" and "math" modules'
         attributes to a file, in the current directory, called "pydiction"
         with and without the "time." and "math." prefix:
             $ python pydiction.py time math
         To print the output just to stdout, instead of appending to the file, 
         supply the -v option: 
             $ python pydiction.py -v time math

License: BSD.
"""
</t>
<t tx="ekr.20090815161520.1815">Reasonable values are iconclick2, icondclick2 and select2.

When using select2, you may want to use the detach-editor-toggle command.
</t>
<t tx="ekr.20091010091628.1836">@language python

'''Create a script button that will search for the icon-like
pattern in the selected node'''

from leo.plugins import mod_scripting as scripting

script = p.b + '\n'

sc = g.app.gui.ScriptingControllerClass(c)

shortcut = sc.getShortcut(p.h)
statusLine = 'pattern find button'
if shortcut: statusLine = '%s = %s' % (statusLine,shortcut)

patC = patController(c,script)
script = patC.setup() # Modify the script

sc.createAtButtonHelper(p,p.h,statusLine,shortcut,verbose=False)
</t>
<t tx="ekr.20091010091628.1837"># This will be done automatically.
import sys
import string
path = r'c:\python25\lib\site-customize\matching'
if path not in sys.path: sys.path.append(path)
from matching.patterns_b import *
from matching.textpatterns_b import *
from matching.MatchingInput import *

print '*' * 20
subject = MatchingInput (p.b) #"abcdefgh23;ijklmn")
while True:
    if subject ^ AnyOfP (string.letters) [4] &gt;&gt; "four letters":
       print "found four letters: \"" + subject ["four letters"] + "\""
    elif subject ^ AnyOfP (string.digits) [2:] &gt;&gt; "the digits" &amp; IsP (";"):
       print "found two or more digits followed by a semicolon: \"" + \
             subject ["the digits"] + "\""
    elif subject ^ AnyOfP (string.letters) [1:3] &gt;&gt; "1 2 3 letters":
       print "found less than four letters: \"" + \
             subject ["1 2 3 letters"] + "\""
    else: break
</t>
<t tx="ekr.20091010104145.1840">class patController:
    
    '''A class supporting icon-like find scripts using
    a very-slightly modified version of library at
    http://www.wilmott.ca/python/patternmatching.html'''
    
    @others</t>
<t tx="ekr.20091010104145.1842">def __init__ (c,script,forward=True):
    
    self.c = c
    self.v = c.p.v # The node containing the find-script to be applied.
    self.script = script # Will be modified in setup.</t>
<t tx="ekr.20091010104145.1843">def setup(self):
    
    pass</t>
<t tx="ekr.20091010104145.1844">def driver (self,forward=True):
    
    '''Search for the pattern in p and all following nodes
    until a match is found.'''
    
    if forward:
        while p:
            i = self.find(p)
            if i == -1:
                p.moveToThreadNext()
            else:
                self.select(p,i) ; break
    else:
        while p:
            i = self.findr(p)
            if i == -1:
                p.moveToThreadBack()
            else:
                self.select(p,i) ; break</t>
<t tx="ekr.20091010104145.1845">def find (self,p):
    
    '''Search for self.pattern in p.
    If p is the presently selected node, start at the cursor position.
    Otherwise, start at the start of the node.
    '''</t>
<t tx="ekr.20091010104145.1846"></t>
<t tx="ekr.20091011110344.1853">import string
import sys
path = r'c:\python25\lib\site-customize\matching'
if path not in sys.path: sys.path.append(path)
from matching.patterns_b import *
from matching.textpatterns_b import *
from matching.MatchingInput import *

def find(p):
    s = MatchingInput (p.b)
    while True:
        g.trace(s.Pos)
        if s ^ AnyOfP (string.letters) [4] &gt;&gt; 'pat':
            found = 'AnyOfP (letters) [4]'
        elif s ^ AnyOfP (string.digits) [2:] &gt;&gt; 'pat' &amp; IsP (';'):
            found = 'AnyOfP(digits)[2:]'
        elif s ^ AnyOfP (string.letters) [1:3] &gt;&gt; 'pat':
            found = 'AnyOfP (letters) [1:3]'
        else:
            found = False
        if found:
            pat = s['pat']
            print ('found: %s --&gt; %s' % (found,pat))
            yield s.Pos,pat
        else:
            raise StopIteration

print '*'*20
while p:
    print '----- searching',p.h
    for pos,pat in find(p):
        print pos,pat
    p.moveToThreadNext()
print('done')
</t>
<t tx="ekr.20091013153026.2721">@
This work has been mostly abandoned.

The idea was to use icon-like patterns, based on
http://www.wilmott.ca/python/patternmatching.html

There are several problems with this approach:
    
1. This library, while elegant, isn't necessarily so useful.
   Indeed, the typical "find script" in scripts.leo uses
   either the string method s.find (or s.findr) or similar
   g.match methods.
   
2. Unlike the python regex module, there do not appear to
   be the equivalent of search or findall methods.  This
   means that the search code must either
   a) step through the search string explicitly or 
   b) use more complicated search patterns that match anywhere.
   
3. Search scripts are typically more complex than other @button scripts.
   The search scripts in scripts.leo avoid this problem by doing all
   the replacements at once, without prompts.
   
State of the prototype code:
    
- \@button find script a kinda works, but it only finds patterns at
  the start of body text.  It does shows that generators are useful.
  
- \@button create find button doesn't do anything, and it's not clear
  that is can ever be extended to be useful.
  
  The idea of this button was that clicking on a node, say "pat a",
  containing an icon-like script, would create *another* @button node,
  say "@button pat-find pat a" that would (interactively?) find all
  nodes matched by the script in "pat a".  This isn't going to be easy.</t>
<t tx="ekr.20091230064146.1911"># For xml-tags-test.xml
xml
test.a
test-b

# For layout.html
html
body
head
py:if
py:match
script
</t>
<t tx="ekr.20091230064146.1912">@language xml
@tabwidth -4
@others
</t>
<t tx="ekr.20091230081322.1919">import unicodedata as u
table = ('a','9','_',':','.',)
table2 = (
    (0xc0,0xd6),(0xd8,0xf6),(0xf8,0x2ff),(0x370,0x37d),(0x37f,0x1fff),
    (0x200c,0x200d),(0x2070,0x218f),(0x2c00,0x2fef),(0x3001,0xd7ff),
    (0xf900,0xfdcf),(0xfdf0,0xfffd),(0x10000,0xeffff),
    # Valid only after the start of a word.
    (0xb7,0xb7+1),(0x0300,0x036f),(0x203f,0x2040),
)
for ch in table:
    ch = g.u(ch)
    g.es(ch,u.category(ch))
for i,j in table2:
    g.es('*** range %xd %xd' % (i,j))
    for n in range(i,min(i+5,j)):
        if g.isPython3: ch = chr(n)
        else: ch = unichr(n)
        g.es(ch,u.category(ch))</t>
<t tx="ekr.20100103112623.1951"># This script insert a raw form-feed into the Leo outline.
# Leo's atFile write code should remove this.
s = p.b
p.b = s + '\n#\f'

# 
#</t>
<t tx="ekr.20100108090658.1958">&lt;&lt; imports&gt;&gt;
&lt;&lt; constants &gt;&gt;

@others

ec = editCommands.EditCommandsClass
table = (
    (ec,'next-line','Down'),
    (ec,'previous-line','Up'),
    (ec,'next-line-extend-selection','Shift+Down'),
    (ec,'previous-line-extend-selection','Shift+Up'),
)

for theClass,command,stroke in table:
    overrideCommand(command,theClass,stroke)

# testKeys()

# aa
</t>
<t tx="ekr.20100108090658.1959">@nocolor-node
@

For a list of official key symbols, see
http://doc.trolltech.com/4.4/qt.html#Key-enum

QKeyEvent::QKeyEvent (
    Type type, int key,
    Qt::KeyboardModifiers modifiers,
    const QString &amp; text = QString(),
    bool autorep = false, ushort count = 1 )

Modifiers
Qt::NoModifier	0x00000000	    No modifier key.
Qt::ShiftModifier	0x02000000	  A Shift key on the keyboard.
Qt::ControlModifier	0x04000000  A Ctrl key on the keyboard.
Qt::AltModifier	0x08000000	  An Alt key on the keyboard.
Qt::MetaModifier	0x10000000	  A Meta key on the keyboard.
</t>
<t tx="ekr.20100108102030.1962">import PyQt4.QtCore as QtCore
import PyQt4.QtGui as QtGui
Qt = QtCore.Qt

import leo.commands.editCommands as editCommands</t>
<t tx="ekr.20100108102030.1963">noMod = Qt.NoModifier
shift = Qt.ShiftModifier
ctrl  = Qt.ControlModifier
alt   = Qt.AltModifier
meta  = Qt.MetaModifier</t>
<t tx="ekr.20100108102217.1966">def overrideCommand(command,theClass,stroke): # mods,key):

    qtKey,qtMods = setKeyAndMods(stroke)

    # Do the actual override
    f = c.commandsDict.get(command)
    if f:
        # Capture the lambda bindings.
        def qt_command_callback(self,event=None,qtKey=qtKey,qtMods=qtMods):
            g.trace(event,command,stroke)
            text=''
            qtKey = QtGui.QKeyEvent(QtCore.QEvent.KeyPress,qtKey,qtMods,text)
            w = c.frame.body.bodyCtrl.widget ### should be event.widget
            QtCore.QCoreApplication.sendEvent(w,qtKey)

        callback = qt_command_callback
        # g.trace(id(f),command,stroke)
        adjustBindings(command,callback,f,stroke,theClass)

    else:
        g.trace('no such command:',command)



</t>
<t tx="ekr.20100108102217.1967">def setKeyAndMods(stroke):

    d = {'Up':Qt.Key_Up,'Down':Qt.Key_Down,}

    mods = stroke.split('+')
    key = mods[-1]
    mods = mods[:-1]

    qtMods = Qt.NoModifier
    if mods:
        for mod in mods:
            mod = mod.lower()
            if mod.startswith('s'):
                qtMods |= Qt.ShiftModifier
            elif mod.startswith('c'):
                qtMods |= Qt.ControlModifier
            elif mod.startswith('a'):
                qtMods |= Qt.AltModifier
            elif mod.startswith('m'):
                qtMods |= Qt.MetaModifier
            else:
                tags.append('Unknown modifier: %s' % mod)

    qtKey = d.get(key,key)
    return qtKey,qtMods
</t>
<t tx="ekr.20100108102217.1968">def testKeys():

    table = (
        (ord('a'),noMod,'a'),
        (Qt.Key_Up,shift,''),
    )

    # Put new characters at end.
    w = c.frame.body.bodyCtrl
    w.setInsertPoint('end')

    for key,mod,text in table:
        key = QtGui.QKeyEvent(QtCore.QEvent.KeyPress,key,mod,text)
        for w in (
            # c.frame.top, # a DynamicWindow. Nothing happens.
            c.frame.body.bodyCtrl.widget,
            # c.frame.log.logCtrl.widget, # works
        ):
            QtCore.QCoreApplication.sendEvent(w,key)
</t>
<t tx="ekr.20100108111728.2076"># This will become something like k.replaceCommand

def adjustBindings (command,callback,f,stroke,theClass):

    # f is the *old* function, to be replaced by callback.
    trace = True and not g.unitTesting
    k = c.k
    g.funcToMethod(callback,theClass,name=f.__name__)
    if trace: g.trace('=====',command,id(f),f.__name__)
    stroke = c.k.strokeFromSetting(stroke)
    bindStroke = c.k.tkbindingFromStroke(stroke)

    # Replace all entries for command in all bindings dicts...
    c.commandsDict [command] = None ### callback

    # k.masterGuiBindingsDict:
    # Keys are strokes; value is a list of widgets for which stroke is bound.
    k.masterGuiBindingsDict[bindStroke] = []

    # k.bindingsDict:
    # Keys are shortcuts;
    # values are *lists* of g.bunch(func,name,warningGiven)
    d = k.bindingsDict
    aList = d.get(stroke,[])
    if aList:
        result = []
        for b in aList:
            # g.trace(id(b.func),b.func.__name__)
            if b.func == f:
                if trace: g.trace('*** removing k.bindingsDict',stroke)
                ### b.func = callback
            else:
                result.append(b)
        d[stroke] = result

    # k.masterBindingsDict:
    # Keys are scope names: 'all','text',etc. or mode names.
    # Values are dicts:  keys are strokes,
    # values are g.Bunch(commandName,func,pane,stroke)
    d = k.masterBindingsDict
    for key in list(k.masterBindingsDict.keys()):
        d2 = k.masterBindingsDict.get(key,{})
        b = d2.get(stroke,None)
        if b:
            # g.trace(b.pane,id(b.func),b.func.__name__)
            if b.func == f:
                if trace: g.trace('*** removing k.masterBindingsDict',stroke)
                b.func = callback
                d2[stroke] = None ### b
</t>
<t tx="ekr.20100108111728.2077">@nocolor-node

@
c.commandsDict:
    Keys are emacs command names; values are functions f.

k.inverseCommandsDict:
    Keys are f.__name__; values are emacs command names.

k.bindingsDict:
    Keys are shortcuts; values are *lists* of g.bunch(func,name,warningGiven)

k.masterBindingsDict:
    Keys are scope names: 'all','text',etc. or mode names.
    Values are dicts:  keys are strokes, values are g.Bunch(commandName,func,pane,stroke)

k.masterGuiBindingsDict:
    Keys are strokes; value is a list of widgets for which stroke is bound.

k.settingsNameDict:
    Keys are lowercase settings; values are 'real' Tk key specifiers.
    Important: this table has no inverse.

not an ivar (computed by k.computeInverseBindingDict):

inverseBindingDict
    Keys are emacs command names; values are *lists* of shortcuts.
</t>
<t tx="ekr.20100109081612.1984">import PyQt4.QtGui as QtGui

w = c.frame.body.bodyCtrl.widget
w.moveCursor(QtGui.QTextCursor.Up)
c.bodyWantsFocusNow()</t>
<t tx="ekr.20100109081746.1988">import PyQt4.QtGui as QtGui

w = c.frame.body.bodyCtrl.widget
w.moveCursor(QtGui.QTextCursor.Down)
c.bodyWantsFocusNow()</t>
<t tx="ekr.20100109081746.1990">import PyQt4.QtGui as QtGui

w = c.frame.body.bodyCtrl.widget
w.moveCursor(QtGui.QTextCursor.Up,QtGui.QTextCursor.KeepAnchor)
c.bodyWantsFocusNow()</t>
<t tx="ekr.20100109081746.1992">import PyQt4.QtGui as QtGui

w = c.frame.body.bodyCtrl.widget
w.moveCursor(QtGui.QTextCursor.Down,QtGui.QTextCursor.KeepAnchor)
c.bodyWantsFocusNow()</t>
<t tx="ekr.20100109081746.1993">import PyQt4.QtGui as QtGui

w = c.frame.body.bodyCtrl.widget
cursor = w.textCursor()
cursor.movePosition(QtGui.QTextCursor.Up,QtGui.QTextCursor.KeepAnchor,15)
w.setTextCursor(cursor)
c.bodyWantsFocusNow()</t>
<t tx="ekr.20100109084336.1996"></t>
<t tx="ekr.20100110151049.2004">@language rest
@tabwidth -4
@others

.. Warning: this node is ignored when writing this file.
.. However, @ @rst-options are recognized in this node.
</t>
<t tx="ekr.20100110172917.1943">&lt;xml&gt;
&lt;/xml&gt;
</t>
<t tx="ekr.20100110172917.1944">&lt;test.a&gt;
a
&lt;/test.a&gt;
</t>
<t tx="ekr.20100110172917.1945">&lt;test-b&gt;
b
&lt;/test-b&gt;
</t>
<t tx="ekr.20100110172917.1961">Section 1: Ę

</t>
<t tx="ekr.20100118122048.2003"># For new colorizer

python_keyword1_font_family = DejaVu Sans Mono
python_keyword1_font_size = 12
python_keyword1_font_slant = roman
    # roman, italic
python_keyword1_font_weight = bold
    # normal, bold</t>
<t tx="ekr.20100118133026.2008">python_keyword3_font_family = DejaVu Sans Mono
python_keyword3_font_size = 12
python_keyword3_font_slant = italic
    # roman, italic
python_keyword3_font_weight = bold
    # normal, bold
</t>
<t tx="ekr.20100118141712.2011">@nocolor-node

Use 40 for @tabwidth 4
Use 80 for @tabwidth 8</t>
<t tx="ekr.20100118190256.2012"></t>
<t tx="ekr.20100118190256.2013"></t>
<t tx="ekr.20100118190256.2014"></t>
<t tx="ekr.20100118190256.2015"></t>
<t tx="ekr.20100118190256.2016"></t>
<t tx="ekr.20100119095312.2041"># bold

rest_keyword2_font_size = 14
rest_keyword2_font_family = Bitstream Charter
rest_keyword2_font_slant = roman
rest_keyword2_font_weight = bold</t>
<t tx="ekr.20100119100926.2046"># Italics
rest_keyword4_font_size = 14
rest_keyword4_font_family = Bitstream Charter
rest_keyword4_font_slant = italic
    # roman, italic
rest_keyword4_font_weight = normal
    # normal, bold</t>
<t tx="ekr.20100127111116.2059">@nowrap

aaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccc ddddddddddddddddddddddd eeeeeeeeeeeeeeeeeee fffffffffffffffffffffff
aaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccc ddddddddddddddddddddddd eeeeeeeeeeeeeeeeeee fffffffffffffffffffffff
aaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbb cccccccccccccccccccccc ddddddddddddddddddddddd eeeeeeeeeeeeeeeeeee fffffffffffffffffffffff</t>
<t tx="ekr.20100127111425.2062"># Searching on Windows 7 is absolutely wretched.
import glob
import os

@others

pattern = "idxTitle = output.find('&lt;title&gt;&lt;/title&gt;')"
ignoreCase = True
paths = (
    # r'C:\Python31\Lib\site-packages\docutils',
    # r'C:\Python26\Lib\site-packages\pylint-0.19.0-py2.6.egg\pylint',
    # r'C:\Python31\Lib\site-packages\docutils',
    r'C:\Python26\Lib\site-packages\docutils-0.6-py2.6.egg\docutils',
)

os.system('CLS')
print('\n%s pattern: %s' % ('-'*20,pattern))
for path in paths:
    searchDir(path,pattern)
</t>
<t tx="ekr.20100127122240.2063">@nocolor

Select the following string: वादक.
Typing and undo now work.</t>
<t tx="ekr.20100130095415.2023"># @first # -*- coding: mbcs -*-
# @first # -*- coding: utf-8 -*-

path = 'c:\prog\Leo Stuff\chinese脖folder'

for encoding in ('mbcs','utf-8'):
    valid = g.isValidEncoding(encoding)
    theDir = g.os_path_finalize(path,encoding='utf-8')
    g.es(encoding,valid,theDir)
    print(encoding,valid,g.os_path_exists(theDir))</t>
<t tx="ekr.20100202115249.2023">@first # -*- coding: utf-8 -*-
@language python
import sys
from PyQt4 import Qt

isPython3 = sys.version_info &gt;= (3,0,0)
if isPython3:
    def gu(s): return s
else:
    def gu(s): return unicode(s)

s = gu('''Select the following string: वादक.
This string consists of 4 characters, followed by a period.
Hit do, then undo.
Notice that the selection range now includes the period.
''')

n1,n2 = None,None # The selection range.
app = Qt.QApplication(sys.argv) 
f = Qt.QFrame()
f.setLayout(Qt.QVBoxLayout())
w = Qt.QTextEdit()
w.setPlainText(s)

b1 = Qt.QPushButton("Do")
b2 = Qt.QPushButton("Undo")

f.layout().addWidget(w)
f.layout().addWidget(b1)
f.layout().addWidget(b2)
f.show()

def showselect():
    tc = w.textCursor()
    s = w.toPlainText()
    su = gu(s)
    n1,n2 = tc.selectionStart(),tc.selectionEnd()
    print(n1,n2,'length',abs(n2-n1),len(s),len(su),gu(s[n1:n2]).encode('utf-8'))

def do():
    # w.textCursor().removeSelectedText() # works
    global n1,n2,w
    tc = w.textCursor()
    n1,n2 = tc.selectionStart(),tc.selectionEnd()
    tc = w.textCursor()
    tc.removeSelectedText()
    w.setTextCursor(tc) # Has no effect.

def undo():
    global n1,n2,s,w
    w.setPlainText(s)
    tc = w.textCursor()
    if n1 &gt; n2: n1,n2 = n2,n1
    tc.setPosition(n1)
    tc.setPosition(n2,tc.KeepAnchor)
    # tc.movePosition(tc.Right,tc.KeepAnchor,n2-n1)
    w.setTextCursor(tc)

app.connect(w, Qt.SIGNAL("selectionChanged()"), showselect)
app.connect(b1, Qt.SIGNAL("clicked()"), do)
app.connect(b2, Qt.SIGNAL("clicked()"), undo)
app.exec_()
</t>
<t tx="ekr.20100203174233.2032"># My problem: the node that is being created by c.pasteOutline() has an
# empty body. If after running the test I type 'paste-node' in the
# minibuffer, a new node appears, it has 'foo' in the body.

root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode = None)
try:
    p1 = p.insertAsLastChild()
    body = 'foo'
    p1.setBodyString(body)
    c.selectPosition(p1)
    c.copyOutline()
    c.pasteOutline()
finally:
    while p.hasChildren():
        p.firstChild().doDelete(newNode = None)
   c.redraw_now()</t>
<t tx="ekr.20100203233053.2033">@language python

#@path aPathaab

# This is a test2</t>
<t tx="ekr.20100204062222.2035">This crashed Leo in path.py during startup</t>
<t tx="ekr.20100205074729.2085"></t>
<t tx="ekr.20100205074729.2086">line 1: node a changed 2</t>
<t tx="ekr.20100205074729.2087">@all</t>
<t tx="ekr.20100205114630.2091"></t>
<t tx="ekr.20100330082345.2120">@language pseudoplain

This is a [[test]] of something.</t>
<t tx="ekr.20100330084954.2125"></t>
<t tx="ekr.20100507151756.2123"></t>
<t tx="ekr.20100516140428.2135">import base64
import getpass
import hashlib

print(getpass.getuser())

m = hashlib.sha1()
m.update("Nobody inspect2s")
key = m.digest()
key = base64.urlsafe_b64encode(str(key))
print(key)
</t>
<t tx="ekr.20100521101729.2148"># Just playing with part of a template system, the (partial) mock up for "range()" is:

def tabStopNaming (event=None):

  stateName = 'naming'
  k = c.k
  state = k.getState(stateName)

  help = ('start-value -- optional, -&gt; fill-in or tab eliminate.  ',
           'end-value -- required, -&gt; fill-in.  ',
           'step -- optional, -&gt;fill-in or tab to eliminate.  ')
  tabStop = ('start-value', 'end-value', 'step')

  if state == 0:
      k.setLabelBlue(help[0],protect=True)
      k.getArg(event,stateName,1,tabStopNaming)
      # g.es('does this ever executed?') # yes, imediately!
  else:
      k.clearState()
      g.es_print('%s : %s' % (tabStop[0], k.arg))
      k.setLabelBlue('')

tabStopNaming()</t>
<t tx="ekr.20100615095815.2189">import leo.core.leoPlugins as leoPlugins

def on_deactivate(tag,keys):
    c = keys.get('c')
    g.trace(c)

def on_activate(tag,keys):
    c = keys.get('c',keys)
    g.trace(c)

leoPlugins.registerHandler("deactivate", on_deactivate)
leoPlugins.registerHandler("activate", on_activate)

print('window events activated')</t>
<t tx="ekr.20100616085524.2191">for name,val,c,letter in g.app.config.config_iter(c):
    print('%45s %s %s' % (name,letter,val))</t>
<t tx="ekr.20100731123441.2155">def searchDir(path,pattern):
    print('\ndir',path)
    paths = glob.glob(g.os_path_join(path,'*'))
    files = [z for z in paths if not g.os_path_isdir(z)]
    dirs  = [z for z in paths if g.os_path_isdir(z)]
    for fn in files:
        if not fn.endswith('.pyc'):
            print(g.shortFileName(fn))
            found = False
            s,e = g.readFileIntoString(fn)
            if ignoreCase:
                s = s.lower()
                pattern = pattern.lower()
            i = 0
            while i &lt; len(s):
                i = s.find(pattern,i)
                if i == -1: break
                n1,n2 = g.getLine(s,i)
                i = n2
                if not found:
                    g.pr('\n','-' * 10,g.shortFileName(fn))
                    found = True
                g.pr(s[n1:n2-1])
    for fn in dirs:
        searchDir(g.os_path_join(path,fn),pattern)</t>
<t tx="ekr.20100812102648.2193">@ @rst-markup
########################
Leo's code markup script
########################
@c
'''A script showing how to convert code in Leo outlines to rST/Sphinx code.

The defaultOptions dict specifies default options.

This script uses leoRst.py:code_to_rst_command.'''

if 1: # Format a particular node.
    h = '@button format-code'
    p = g.findNodeAnywhere(c,h)

&lt;&lt; options &gt;&gt;

if p:
    c.rstCommands.code_to_rst_command(scriptSettingsDict=scriptSettingsDict)
else:
    print('not found',h)
</t>
<t tx="ekr.20100812102648.2195">@ Here are the options
@c
fn = '%s.html' % (g.sanitize_filename(p.h))

# g.es('output file',repr(fn))

scriptSettingsDict = {
    'output-file-name': 'format-code-output.html', # fn,
    'call-docutils': True,
    'number-code-lines': True,
    'show_doc_parts_as_paragraphs': True,
    'stylesheet_name': 'default.css',
    # 'stylesheet_path': '../doc', # Must be None, not ''.
    'write-intermediate-file': True,
    'write_intermediate_extension': 'txt'
}

# old_dict = {

    # # The following options are definitely used in the script.
    # 'generate-rst-header-comment': True,
    # 'output-file-name': fn,
    # 'show_headlines': True,
    # 'show_options_nodes': False,
    # 'show_organizer_nodes': True,
    # 'show_sections': True,
    # 'underline_characters': '''#=+*^~"'`-:&gt;&lt;_''',
    # 'verbose': True,

    # # The following are not used, but probably should be used.
    # 'code_block_string': '::',
    # 'default_path': None, # Must be None, not ''.
    # 'encoding': 'utf-8',
    # 'publish_argv_for_missing_stylesheets': None,
    # 'stylesheet_embed': True,
    # 'stylesheet_name': 'default.css',
    # 'stylesheet_path': None, # Must be None, not ''.

    # # The following are not used. Their status is unclear.
    # 'show_leo_directives': False,
# }
</t>
<t tx="ekr.20100812114823.2176"></t>
<t tx="ekr.20100812114823.2177">def code_to_rst_command (self,event=None,p=None,scriptSettingsDict=None):

    '''Format the presently selected node as computer code.

    When run from the minibuffer, initial settings come from the outline, as usual.

    When called from a script, initial setting may come from scriptSettingsDict.

    Return true and set self.source and self.output if all requested files were written.
    '''

    trace = False and not g.unitTesting
    c = self.c
    if p: p = p.copy()
    else: p = c.p

    # **Important**: This command works as much like the rst3 command as possible.
    # Difference arise because there is no @rst node to specify a filename.
    # Instead we get the filename from scriptSettingsDict, or use 'code_to_rst.html'

    # Capture the settings, munging all settings.
    self.scriptSettingsDict = {}
    d = scriptSettingsDict
    if d:
        for key in d.keys():
            self.scriptSettingsDict[self.munge(key)] = d.get(key)

    # From processTree...
    self.topLevel = p.level() # Define toplevel separately for each rst file.
    self.preprocessTree(p)
    self.scanAllOptions(p) # So we can get the next options.

    # getOption will not work until scanAllOptions::initOptionsFromSettings has been called.
    callDocutils = self.getOption('call_docutils')
    writeIntermediateFile = self.getOption('write_intermediate_file')
    g.trace(self.getOption('output-file-name'))
    outputFileName = self.getOption('output-file-name') or 'code_to_rst.html'
    junk,self.ext = g.os_path_splitext(outputFileName)
    isHtml = self.ext in ('.html','.htm')

    # From writeSpecialTree...
    self.initWrite(p)
    self.outputFile = StringIO()
    self.write_code_tree(p)
    self.source = self.outputFile.getvalue()
    self.outputFile = None

    if callDocutils or writeIntermediateFile:
        # **Note**: self.outputFileName does not exist.
        self.outputFileName = self.computeOutputFileName(outputFileName)

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

    if writeIntermediateFile:
        ext = self.getOption('write_intermediate_extension') or '.txt' # .txt by default.
        if not ext.startswith('.'): ext = '.' + ext
        name = self.outputFileName.rsplit('.',1)[0] + ext
        if trace: g.trace('intermediate file',name)
        if g.isPython3:
            f = open(name,'w',encoding=self.encoding)
        else:
            f = open(name,'w')
        f.write(self.source)
        f.close()
        self.report(name)

    if callDocutils:
        if trace: g.trace('calling docutils')
        try:
            output = self.writeToDocutils(self.source)
            if g.isBytes(output):
                output = g.toUnicode(output)
        except Exception:
            g.pr('Exception in docutils')
            g.es_exception()
            return False

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

        self.stringOutput = output # Always useful for scripts.

        # Write the file to the directory containing the .leo file.
        f = open(self.outputFileName,'w')
        f.write(output)
        f.close()
        self.report(self.outputFileName)

    return True
</t>
<t tx="ekr.20100812114823.2178">def write_code_body (self,p):

    trace = False
    self.p = p.copy() # for traces.
    if not p.b.strip():
        return # No need to write any more newlines.

    showDocsAsParagraphs = self.getOption('show_doc_parts_as_paragraphs')
    lines = g.splitLines(p.b)
    parts = self.split_parts(lines,showDocsAsParagraphs)
    result = []
    for kind,lines in parts:
        if trace: g.trace(kind,len(lines),p.h)
        if kind == '@rst-option': # Also handles '@rst-options'
            pass # The prepass has already handled the options.
        elif kind == '@rst-markup':
            lines.extend('\n')
            result.extend(lines)
        elif kind == '@doc':
            if showDocsAsParagraphs:
                result.extend(lines)
                result.append('\n')
            else:
                result.extend(self.write_code_block(lines))
        elif kind == 'code':
            result.extend(self.write_code_block(lines))
        else:
            g.trace('Can not happen',kind)

    # Write the lines with exactly two trailing newlines.
    s = ''.join(result).rstrip() + '\n\n'
    self.write(s)
</t>
<t tx="ekr.20100812114823.2179">def split_parts (self,lines,showDocsAsParagraphs):

    '''Split a list of body lines into a list of tuples (kind,lines).'''

    kind,parts,part_lines = 'code',[],[]
    for s in lines:
        if g.match_word(s,0,'@ @rst-markup'):
            if part_lines: parts.append((kind,part_lines[:]),)
            kind = '@rst-markup'
            n = len('@ @rst-markup')
            after = s[n:].strip()
            part_lines = g.choose(after,[after],[])
        elif s.startswith('@ @rst-option'):
            if part_lines: parts.append((kind,part_lines[:]),)
            kind,part_lines = '@rst-option',[s] # part_lines will be ignored.
        elif s.startswith('@ ') or s.startswith('@\n') or s.startswith('@doc'):
            if showDocsAsParagraphs:
                if part_lines: parts.append((kind,part_lines[:]),)
                kind = '@doc'
                # Put only what follows @ or @doc
                n = g.choose(s.startswith('@doc'),4,1)
                after = s[n:].lstrip()
                part_lines = g.choose(after,[after],[])
            else:
                part_lines.append(s) # still in code mode.
        elif g.match_word(s,0,'@c') and kind != 'code':
            if kind == '@doc' and not showDocsAsParagraphs:
                    part_lines.append(s) # Show the @c as code.
            parts.append((kind,part_lines[:]),)
            kind,part_lines = 'code',[]
        else:
            part_lines.append(s)

    if part_lines:
        parts.append((kind,part_lines[:]),)

    return parts
</t>
<t tx="ekr.20100812114823.2180">def write_code_block (self,lines):

    result = ['::\n\n'] # ['[**code block**]\n\n']

    if self.getOption('number-code-lines'):
        i = 1
        for s in lines:
            result.append('    %d: %s' % (i,s))
            i += 1
    else:
        result.extend(['    %s' % (z) for z in lines])

    s = ''.join(result).rstrip()+'\n\n'
    return g.splitLines(s)
</t>
<t tx="ekr.20100812114823.2181">def write_code_headline (self,p):

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


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

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

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

    h = p.h.strip()

    # Remove any headline command before writing the headline.
    i = g.skip_ws(h,0)
    i = g.skip_id(h,0,chars='@-')
    word = h [:i].strip()
    if word:
        # Never generate a section for @rst-option or @rst-options or @rst-no-head.
        if word in ('@rst-option','@rst-options','@rst-no-head','@rst-no-headlines'):
            return

        for prefix in ('@rst-ignore-node','@rst-ignore-tree','@rst-ignore'):
            if word == prefix:
                h = h [len(word):].strip()
                break

    if not h.strip(): return

    if self.getOption('show_sections'):
        self.write(self.underline(h,p))
    else:
        self.write('\n**%s**\n\n' % h.replace('*',''))
</t>
<t tx="ekr.20100812114823.2183">def write_code_node (self,p):

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

    Side effect: advance p'''

    h = p.h.strip()
    self.scanAllOptions(p)

    if self.getOption('ignore_this_tree'):
        p.moveToNodeAfterTree()
    elif self.getOption('ignore_this_node'):
        p.moveToThreadNext()
    elif g.match_word(h,0,'@rst-options') and not self.getOption('show_options_nodes'):
        p.moveToThreadNext()
    else:
        self.write_code_headline(p)
        self.write_code_body(p)
        p.moveToThreadNext()
</t>
<t tx="ekr.20100812114823.2184">def write_code_tree (self,p):

    '''Write p's tree as code to self.outputFile.'''

    self.scanAllOptions(p) # So we can get the next option.

    if self.getOption('generate_rst_header_comment'):
        self.write('.. rst3: filename: %s\n\n' % self.outputFileName)

    # We can't use an iterator because we may skip parts of the tree.
    p = p.copy() # Only one copy is needed for traversal.
    self.topNode = p.copy() # Indicate the top of this tree.
    after = p.nodeAfterTree()
    while p and p != after:
        self.write_code_node(p) # Side effect: advances p.
</t>
<t tx="ekr.20100812114823.2185"></t>
<t tx="ekr.20100812114823.2186">def getOption (self,name):

    # 2010/08/12: munging names here is safe because setOption munges.
    return self.optionsDict.get(self.munge(name))

def setOption (self,name,val,tag):

    self.optionsDict [self.munge(name)] = val
</t>
<t tx="ekr.20100812114823.2187">def initOptionsFromSettings (self):

    c = self.c

    d = self.defaultOptionsDict
    keys = sorted(d)

    for key in keys:
        for getter,kind in (
            (c.config.getBool,'@bool'),
            (c.config.getString,'@string'),
            (d.get,'default'),
        ):
            val = getter(key)
            if kind == 'default' or val is not None:
                self.setOption(key,val,'initOptionsFromSettings')
                break

    # 2010/08/12: Script settings override everything else.
    d2 = self.scriptSettingsDict or {}
    for key in d2.keys():
        val = d2.get(key)
        # g.trace(key,val)
        self.setOption(key,val,'initOptionsFromSettings')

    # Special case.
    if self.getOption('http_server_support') and not mod_http:
        g.es('No http_server_support: can not import mod_http plugin',color='red')
        self.setOption('http_server_support',False)
</t>
<t tx="ekr.20100812114823.2188">def writeSpecialTree (self,p,toString,justOneFile):

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

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

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

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

        if self.getOption('write_intermediate_file'):
            ext = self.getOption('write_intermediate_extension')
            if not ext.startswith('.'): ext = '.' + ext
            name = self.outputFileName.rsplit('.',1)[0] + ext 
            if g.isPython3: # 2010/04/21
                f = open(name,'w',encoding=self.encoding)
            else:
                f = open(name,'w')
            f.write(self.source)
            f.close()
            self.report(name)

    # g.trace('call_docutils',self.getOption('call_docutils'))
    if not self.getOption('call_docutils'):
        return False

    try:
        output = self.writeToDocutils(self.source)
        if g.isBytes(output):
            output = g.toUnicode(output)
        ok = output is not None
    except Exception:
        g.pr('Exception in docutils')
        g.es_exception()
        ok = False

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

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

    return ok
</t>
<t tx="ekr.20100824124015.2195">for p in c.allNodes_iter():
    v = p.v
    icons = v.u and v.u.get('icons')
    if icons:
        for d in icons:
            fn = d.get('file')
            icon = g.app.gui.getIconImage(fn)
            print('v %s icon %s %s' % (id(v),id(icon),fn))
print('done')
</t>
<t tx="ekr.20100910124218.2257"></t>
<t tx="ekr.20100910124218.2258"></t>
<t tx="ekr.20100910124218.2259"></t>
<t tx="ekr.20100911195503.2426">import os

cd = os.path.normcase(g.os_path_finalize(os.getcwd())) # .replace('c:','C:')
ld = os.path.normcase(g.os_path_finalize(g.app.loadDir))
doc = os.path.normcase(g.os_path_finalize_join(ld,'..','doc'))
ss = os.path.normcase(g.os_path_finalize_join(ld,'..','doc','html','screen-shots'))
fn = g.os_path_finalize(c.fileName())
fd,junk = g.os_path_split(fn)
fd = os.path.normcase(fd)

table = (
    (cd,doc),
    (ld,doc),
    #(fd,doc),
    (cd,ss),
    (ld,ss),
)
for start,path in table:
    print(start,path,'--&gt;',os.path.relpath(path,start).replace('\\','/'))</t>
<t tx="ekr.20101009105505.2295">True (recommended):
    Write "E" attribute bits in &lt;v&gt; elements.
    Leo outlines will record the expansion state of all nodes.
    
False:
    (Good for files like unitTest.leo)
    Suppress "E" attribute bits in &lt;v&gt; elements.
    Only the ancestors of the presently selected node will
    be expanded when Leo opens an outline.</t>
<t tx="ekr.20101014040509.2316">import PyQt4.phonon as phonon
phonon = phonon.Phonon

top = c.frame.top # A DynamicWindow
sw = top.stackedWidget # QStackedWidget

@others

run(p)
</t>
<t tx="ekr.20101014040509.2317">def run(p):

    tag = '@movie'

    if not g.match_word(p.h,0,tag):
        return g.es('Not an %s node' % (tag))

    if p.b.strip():
        fn = p.b.strip()
    else:
        fn = p.h[len(tag):].strip()
    path = g.os_path_finalize_join(g.app.loadDir,fn)
    if not g.os_path_exists(path):
        return g.es('Not found: %s' % (fn))
        
    g.trace(path)

    if hasattr(top,'video_player'):
        vp = top.video_player
    else:
        # This call creates a big problem later.
        top.video_player = vp = phonon.VideoPlayer(phonon.VideoCategory)
    vw = vp.videoWidget()
    vp.load(phonon.MediaSource(path))
    sw.addWidget(vw)
    sw.setCurrentWidget(vw)
    sw.show()
    vp.play()
</t>
<t tx="ekr.20101014040509.2318">top = c.frame.top
sw = top.stackedWidget

if hasattr(top,'video_player'):
    vp = top.video_player
    vw = vp.videoWidget()
    sw.setCurrentWidget(vw)
    sw.show()
    if vp.isPlaying():
        vp.pause()
    else:
        vp.play()
</t>
<t tx="ekr.20101014040509.2319">top = c.frame.top
sw = top.stackedWidget

if hasattr(top,'video_player'):
    vp = top.video_player
    vp.stop()
    # vp.deleteLater()
    delattr(top,'video_player')

sw.setCurrentWidget(top.text_page)
sw.show()</t>
<t tx="ekr.20101014040509.2320">top = c.frame.top
sw = top.stackedWidget

g.es('stacked widgets...')
for i in range(sw.count()):
    g.es(i,sw.widget(i))</t>
<t tx="ekr.20101014040509.2321">import PyQt4.phonon as phonon
phonon = phonon.Phonon

top = c.frame.top # A DynamicWindow
sw = top.stackedWidget # QStackedWidget

def run(p):
    
    tag = '@movie'

    if not g.match_word(p.h,0,tag):
        return g.es('Not an %s node' % (tag))

    if p.b.strip():
        fn = p.b.strip()
    else:
        fn = p.h[len(tag):].strip()
    path = g.os_path_finalize_join(g.app.loadDir,fn)
    if not g.os_path_exists(path):
        return g.es('Not found: %s' % (fn))

    if hasattr(top,'video_player'):
        vp = top.video_player
    else:
        # This call creates a big problem later.
        vp = phonon.VideoPlayer(phonon.VideoCategory)
    
    top.video_player = vp
    vw = vp.videoWidget()
    if 0:
        sw.addWidget(vw)
        sw.setCurrentWidget(vw)
        sw.show()
    vp.load(phonon.MediaSource(path))
    vp.play()

if 0:
    vp = phonon.VideoPlayer(phonon.VideoCategory)
    # top.video_player = vp
    # delattr(top,'video_player')
else:
    run(p)
g.es('crash test done')
</t>
<t tx="ekr.20101103135707.2439">import leo.core.leoImport as leoImport

leoImport.headToPrevNode(event={'c':c})
</t>
<t tx="ekr.20101103170034.2445">import leo.core.leoImport as leoImport

leoImport.tailToNextNode(event={'c':c})
</t>
<t tx="ekr.20101110190130.2451">from leo.external import lproto
import os

addr = open(os.path.expanduser('~/.leo/leoserv_sockname')).read()
print("will connect to",addr)
pc  = lproto.LProtoClient(addr)
pc.send("""

g.es("hello world from remote") 
c = g.app.commanders()[0]

""")

# note how c persists between calls
pc.send("""
c.k.simulateCommand('stickynote')
""")</t>
<t tx="ekr.20110320205650.2495"></t>
<t tx="ekr.20110321012354.2495">c.executeMinibufferCommand('pause-play-movie')</t>
<t tx="ekr.20110321012354.2496">c.executeMinibufferCommand('toggle-rendering-pane')</t>
<t tx="ekr.20110321073942.2490">c.executeMinibufferCommand('lock-unlock-rendering-pane')
</t>
<t tx="ekr.20110321213439.2495">c.executeMinibufferCommand('update-rendering-pane')
</t>
<t tx="ekr.20110321213552.2497"># This should be done only for selected files.</t>
<t tx="ekr.20110321213552.2499"></t>
<t tx="ekr.20110321213552.2500"></t>
<t tx="ekr.20110325142419.2337"># This has been superceded by Autocompleter test node in this file.

from PyQt4 import QtGui, QtCore

@others

if __name__ == "__main__":
    main()</t>
<t tx="ekr.20110325142419.2338">if 0: # Not used:  We'll use QCompleter instead.

    class DictionaryCompleter(QtGui.QCompleter):
    
        def __init__(self, parent=None):
            words = []
            try:
                f = open("/usr/share/dict/words","r")
                for word in f:
                    words.append(word.strip())
                f.close()
            except IOError:
                print "dictionary not in anticipated location"
    
            QtGui.QCompleter.__init__(self, words, parent)
</t>
<t tx="ekr.20110325142419.2339">if 0: # Not used:  We'll use LeoQTextBrowser instead.

    STARTTEXT = ('This TextEdit provides autocompletions for words that have ' +
    'more than 3 characters.\nYou can trigger autocompletion using %s\n\n'''% (
    QtGui.QKeySequence("Ctrl+E").toString(QtGui.QKeySequence.NativeText)))
    
    
    class CompletionTextEdit(QtGui.QTextEdit):
        
        @others</t>
<t tx="ekr.20110325142419.2340">def __init__(self, parent=None):
    super(CompletionTextEdit, self).__init__(parent)
    self.setMinimumWidth(400)
    self.setPlainText(STARTTEXT)
    self.completer = None
    self.moveCursor(QtGui.QTextCursor.End)

</t>
<t tx="ekr.20110325142419.2341">def setCompleter(self, completer):
    if self.completer:
        self.disconnect(self.completer, 0, self, 0)
    if not completer:
        return

    completer.setWidget(self)
    completer.setCompletionMode(QtGui.QCompleter.PopupCompletion)
    completer.setCaseSensitivity(QtCore.Qt.CaseInsensitive)
    self.completer = completer
    self.connect(self.completer,
        QtCore.SIGNAL("activated(const QString&amp;)"), self.insertCompletion)

</t>
<t tx="ekr.20110325142419.2342">def insertCompletion(self, completion):

    tc = self.textCursor()
    extra = (completion.length() -
        self.completer.completionPrefix().length())
    
    tc.movePosition(QtGui.QTextCursor.Left)
    tc.movePosition(QtGui.QTextCursor.EndOfWord)
    tc.insertText(completion.right(extra))
    self.setTextCursor(tc)

</t>
<t tx="ekr.20110325142419.2343">def textUnderCursor(self):

    tc = self.textCursor()
    tc.select(QtGui.QTextCursor.WordUnderCursor)
    return tc.selectedText()

</t>
<t tx="ekr.20110325144059.2350">def main():
    
    app = QtGui.QApplication([])
    completer = DictionaryCompleter()
    te = CompletionTextEdit()
    te.setCompleter(completer)
    te.show()
    app.exec_()
</t>
<t tx="ekr.20110325144059.2351">def focusInEvent(self, event):

    if self.completer:
        self.completer.setWidget(self);

    QtGui.QTextEdit.focusInEvent(self, event)
</t>
<t tx="ekr.20110325144059.2352">def keyPressEvent(self, event):
    if self.completer and self.completer.popup().isVisible():
        if event.key() in (
        QtCore.Qt.Key_Enter,
        QtCore.Qt.Key_Return,
        QtCore.Qt.Key_Escape,
        QtCore.Qt.Key_Tab,
        QtCore.Qt.Key_Backtab):
            event.ignore()
            return

    ## has ctrl-E been pressed??
    isShortcut = (event.modifiers() == QtCore.Qt.ControlModifier and
                  event.key() == QtCore.Qt.Key_E)
    if (not self.completer or not isShortcut):
        QtGui.QTextEdit.keyPressEvent(self, event)

    ## ctrl or shift key on it's own??
    ctrlOrShift = event.modifiers() in (QtCore.Qt.ControlModifier ,
            QtCore.Qt.ShiftModifier)
    if ctrlOrShift and event.text().isEmpty():
        # ctrl or shift key on it's own
        return

    eow = QtCore.QString("~!@#$%^&amp;*()_+{}|:\"&lt;&gt;?,./;'[]\\-=") #end of word

    hasModifier = ((event.modifiers() != QtCore.Qt.NoModifier) and
                    not ctrlOrShift)

    completionPrefix = self.textUnderCursor()

    if (not isShortcut and (hasModifier or event.text().isEmpty() or
    completionPrefix.length() &lt; 3 or
    eow.contains(event.text().right(1)))):
        self.completer.popup().hide()
        return

    if (completionPrefix != self.completer.completionPrefix()):
        self.completer.setCompletionPrefix(completionPrefix)
        popup = self.completer.popup()
        popup.setCurrentIndex(
            self.completer.completionModel().index(0,0))

    cr = self.cursorRect()
    cr.setWidth(self.completer.popup().sizeHintForColumn(0)
        + self.completer.popup().verticalScrollBar().sizeHint().width())
    self.completer.complete(cr) ## popup it up!</t>
<t tx="ekr.20110414063538.2372">@first # -*- coding: utf-8 -*-

'''A script that writes/reads .leo files in JSON format.'''

&lt;&lt; imports &gt;&gt;

# To do:
# Create putDescendentVnodeUas, putDescendentAttributes.
# Write "marked" item if the node is marked.
# Decide on the final names for all items.

@others

# os.system('cls')

TestClass(c).main()
</t>
<t tx="ekr.20110414063538.2373">def putFile(self):
    
    self.put('[\n')
    self.putVnodes()
    self.put(',\n')
    self.putTnodes()
    self.put(']\n')
    return ''.join(self.result)
</t>
<t tx="ekr.20110414063538.2374">def putTnode (self,v):

    # Call put just once.
    gnx = g.app.nodeIndices.toString(v.fileIndex)
    ua = hasattr(v,'unknownAttributes') and self.putUnknownAttributes(v) or ''
    b = v.b or ''

    if self.json:
        comma = g.choose(self.needJsonComma,',\n','')
        if ua:
            self.put('%s{"id":%s,"head":%s,"ua":%s,"body":%s}' % (
                comma,self.escape(gnx),self.escape(v.h),self.escape(ua),self.escape(b)))
        else:
            self.put('%s{"id":%s,"head":%s,"body":%s}' % (
                comma,self.escape(gnx),self.escape(v.h),self.escape(b)))
        self.needJsonComma = True
    else:
        body = xml.sax.saxutils.escape(b)
        self.put('&lt;t tx="%s"%s&gt;%s&lt;/t&gt;\n' % (gnx,ua,body))
</t>
<t tx="ekr.20110414063538.2375">def putTnodes (self):

    """Puts all tnodes as required for copy or save commands"""

    c = self.c
    
    if self.json:
        self.needJsonComma = False
        self.put('{"tnodes":[\n')
    else:
        self.put("&lt;tnodes&gt;\n")
    &lt;&lt; write only those tnodes that were referenced &gt;&gt;
    if self.json:
        self.put('\n]}\n')
    else:
        self.put("&lt;/tnodes&gt;\n")
</t>
<t tx="ekr.20110414063538.2376">if self.usingClipboard: # write the current tree.
    theIter = c.p.self_and_subtree()
else: # write everything
    theIter = c.all_unique_positions()

# Populate tnodes
tnodes = {}
nodeIndices = g.app.nodeIndices
for p in theIter:
    # Make *sure* the file index has the proper form.
    # g.trace(p.v.fileIndex)
    try:
        theId,t,n = p.v.fileIndex
    except ValueError:
        try:
            theId,t,n = p.v.fileIndex,''
        except Exception:
            raise BadLeoFile('bad p.v.fileIndex' % repr(p.v.fileIndex))

    if n is None:
        n = g.u('0')
    elif g.isPython3:
        n = str(n)
    else:
        n = unicode(n)
    index = theId,t,n
    tnodes[index] = p.v

# Put all tnodes in index order.
for index in sorted(tnodes):
    # g.trace(index)
    v = tnodes.get(index)
    if v:
        # Write only those tnodes whose vnodes were written.
        if v.isWriteBit():
            self.putTnode(v)
    else:
        g.trace('can not happen: no vnode for',repr(index))
        # This prevents the file from being written.
        raise BadLeoFile('no vnode for %s' % repr(index))
</t>
<t tx="ekr.20110414063538.2377">def putVnode (self,p,isIgnore=False):

    """Write a &lt;v&gt; element corresponding to a vnode."""

    fc = self ; c = fc.c ; v = p.v
    json = fc.json
    isAuto = p.isAtAutoNode() and p.atAutoNodeName().strip()
    isEdit = p.isAtEditNode() and p.atEditNodeName().strip() and not p.hasChildren()
        # 2010/09/02: @edit nodes must not have children.
        # If they do, the entire tree is written to the outline.
    isFile   = p.isAtFileNode()
    isShadow = p.isAtShadowFileNode()
    isThin   = p.isAtThinFileNode()
    isOrphan = p.isOrphan()
    if not isIgnore: isIgnore = p.isAtIgnoreNode()

    # 2010/10/22: force writes of orphan @edit, @auto and @shadow trees.
    if   isIgnore: forceWrite = True      # Always write full @ignore trees.
    elif isAuto:   forceWrite = isOrphan  # Force write of orphan @auto trees.
    elif isEdit:   forceWrite = isOrphan  # Force write of orphan @edit trees.
    elif isFile:   forceWrite = isOrphan  # Force write of orphan @file trees.
    elif isShadow: forceWrite = isOrphan  # Force write of @shadow trees.
    elif isThin:   forceWrite = isOrphan  # Force write of  orphan @thin trees.
    else:          forceWrite = True      # Write all other @&lt;file&gt; trees.

    &lt;&lt; Set gnx = vnode index &gt;&gt;
    attrs = []
    &lt;&lt; Append attribute bits to attrs &gt;&gt;
    &lt;&lt; Append unKnownAttributes to attrs &gt;&gt;
    attrs = ''.join(attrs)

    if json:
        comma = g.choose(self.needJsonComma,',\n','')
        if attrs:
            v_head = '%s%s{"id":"%s","%s"' % (comma,self.indent(),gnx,attrs)
        else:
            v_head = '%s%s{"id":"%s"' % (comma,self.indent(),gnx)
        self.needJsonComma = True
    else:
        v_head = '&lt;v t="%s"%s&gt;' % (gnx,attrs)
        
    h = xml.sax.saxutils.escape(p.v.headString()) or ''
    if gnx in fc.vnodesDict:
        if json:
            fc.put('%s}' % v_head)
        else:
            fc.put(v_head+'&lt;/v&gt;\n')
    else:
        fc.vnodesDict[gnx]=True
        
        if json:
            pass
        else:
            v_head += '&lt;vh&gt;%s&lt;/vh&gt;' % (h)
        # The string catentation is faster than repeated calls to fc.put.
        if not self.usingClipboard:
            &lt;&lt; issue informational messages &gt;&gt;
        # New in 4.2: don't write child nodes of @file-thin trees (except when writing to clipboard)
        if p.hasChildren() and (forceWrite or self.usingClipboard):
            if json:
                fc.put('%s,"children":[\n' % v_head) # Newline is good here.
            else:
                fc.put('%s\n' % v_head)
            # This optimization eliminates all "recursive" copies.
            p.moveToFirstChild()
            oldNeedComma = self.needJsonComma
            self.needJsonComma = False
            self.level += 1
            while 1:
                fc.putVnode(p,isIgnore)
                if p.hasNext(): p.moveToNext()
                else:           break
            self.level -= 1
            p.moveToParent() # Restore p in the caller.
            self.needJsonComma = oldNeedComma
            if json:
                fc.put(']}')
            else:
                fc.put('&lt;/v&gt;\n')
        else:
            if json:
                fc.put('%s}' % v_head)
            else:
                fc.put('%s&lt;/v&gt;\n' % v_head) # Call put only once.
</t>
<t tx="ekr.20110414063538.2378">gnx = g.app.nodeIndices.toString(v.fileIndex)

if forceWrite or self.usingClipboard:
    v.setWriteBit() # 4.2: Indicate we wrote the body text.
</t>
<t tx="ekr.20110414063538.2379"># These string catenations are benign because they rarely happen.
attr = ""
# New in Leo 4.5: support fixed .leo files.
if not c.fixed:
    if v.isExpanded() and v.hasChildren() and c.putBitsFlag:
        attr += "E"
    if v.isMarked():   attr += "M"
    if v.isOrphan():   attr += "O"
    if attr:
        if json:
            attrs.append(',a="%s"' % attr)
        else:
            attrs.append(' a="%s"' % attr)

# Put the archived *current* position in the *root* positions &lt;v&gt; element.
if p == self.rootPosition:
    aList = [str(z) for z in self.currentPosition.archivedPosition()]
    d = v.u
    str_pos = ','.join(aList)
    if d.get('str_leo_pos'):
        del d['str_leo_pos']
    # Don't write the current position if we can cache it. 
    if g.enableDB and c.mFileName:
        c.cacher.setCachedStringPosition(str_pos)
    elif c.fixed:
        pass
    else:
        d['str_leo_pos'] = str_pos
    v.u = d
elif hasattr(v,"unknownAttributes"):
    d = v.unknownAttributes
    if d and not c.fixed and d.get('str_leo_pos'):
        # g.trace("clearing str_leo_pos",v)
        del d['str_leo_pos']
        v.unknownAttributes = d
</t>
<t tx="ekr.20110414063538.2380"># v.unknownAttributes are now put in &lt;t&gt; elements.

if p.hasChildren() and not forceWrite and not self.usingClipboard:
    # We put the entire tree when using the clipboard, so no need for this.
    if not isAuto: # Bug fix: 2008/8/7.
        attrs.append(self.putDescendentVnodeUas(p)) # New in Leo 4.5.
        attrs.append(self.putDescendentAttributes(p))
</t>
<t tx="ekr.20110414063538.2381">if isOrphan and isThin:
    g.es("writing erroneous:",p.h,color="blue")
    p.clearOrphan()
</t>
<t tx="ekr.20110414063538.2382">def putVnodes (self):

    """Puts all &lt;v&gt; elements in the order in which they appear in the outline."""

    c = self.c
    c.clearAllVisited()

    if self.json:
        self.needJsonComma = False
        self.put('{"vnodes":[\n')
    else:
        self.put("&lt;vnodes&gt;\n")

    # Make only one copy for all calls.
    self.currentPosition = c.p 
    self.rootPosition    = c.rootPosition()
    # self.topPosition     = c.topPosition()
    self.vnodesDict = {}

    if self.usingClipboard:
        self.putVnode(self.currentPosition) # Write only current tree.
    else:
        for p in c.rootPosition().self_and_siblings():
            # New in Leo 4.4.2 b2 An optimization:
            self.putVnode(p,isIgnore=p.isAtIgnoreNode()) # Write the next top-level node.

    if self.json:
        self.put('\n]}')
    else:
        self.put("&lt;/vnodes&gt;\n")
</t>
<t tx="ekr.20110414063538.2383">class TestClass:
    
    def __init__(self,c):

        # These ivars are from the fileCommands class.
        self.c = c
        self.usingClipboard = True # True: write only the current tree.
        
        # Read ivars.
        self.t_dict = {} # Keys are id strings, values are tnodes.
        self.v_dict = {} # Keys are id strings, values are vnodes.
        
        # Ivars added for this class.
        self.json = True
        self.level = 0
        self.needJsonComma = False
        self.result = []

    @others
</t>
<t tx="ekr.20110414063538.2384">def main (self):
    
    trace = False
    tc = self
    
    tag = '@input-tree'
    p = g.findNodeAnywhere(self.c,tag)
    assert p,'not found: %s' % tag
    c.selectPosition(p)
    
    s = tc.putFile()
    if trace: g.trace(repr(s))
    aList = json.loads(s)
    if trace: pprint.pprint(aList)
    
    if 1: # A consistency check.
        s2 = json.dumps(aList)
        if trace: print(s2)
        aList2 = json.loads(s2)
        assert(aList==aList2)
    
    tc.create_v_dict()
    tc.read_json_data(aList)
    c.redraw_now()</t>
<t tx="ekr.20110414063538.2385">import leo.core.leoNodes as leoNodes

import json
import pprint
import xml.sax
import xml.sax.saxutils
import os</t>
<t tx="ekr.20110414073628.2389">def escape(self,s):
    '''Perform the json string escapes on s, enclosing the result in double quotes.'''
    return json.dumps(s)

def indent(self):
    return ' '*self.level

def put(self,s):
    self.result.append(s)

def putUnknownAttributes(self,v):
    pass
</t>
<t tx="ekr.20110414094917.2391"></t>
<t tx="ekr.20110414094917.2406"></t>
<t tx="ekr.20110414094917.2408">def create_json_children (self,json_node,parent_v):

    c = self.c
    trace = False and not g.unitTesting
    children = []
    json_children = json_node.get('children',[])

    for json_child in json_children:
        gnx = json_child.get('id')
        v = self.v_dict.get(gnx)

        if v: # A clone.
            if trace: g.trace('**clone',v)
            v = self.create_json_vnode(json_child,parent_v,v=v)   
        else:
            v = self.create_json_vnode(json_child,parent_v)
            self.create_json_children(json_child,v)

        children.append(v)

    parent_v.children = children
    for child in children:
        child.parents.append(parent_v)
        if trace:
            g.trace('*** added parent %s to %s len(child.parents) %s' % (
                parent_v,child,len(child.parents)))

    return children
</t>
<t tx="ekr.20110414094917.2409">def create_json_vnode (self,json_node,parent_v,v=None):

    c = self.c
    trace = False and not g.unitTesting
    gnx = json_node.get('id','')
    json_tnode = self.t_dict.get(gnx)
    assert json_tnode
    assert json_tnode.get('id') == gnx
    h = json_tnode.get('head','')
    b = json_tnode.get('body','')

    if v:
        # The body of the later node overrides the earlier.
        if v.b != b:
            if trace: g.trace('***update\nold: %s\nnew: %s' % (v.b,b))
            v.b = b 
    else:
        v = leoNodes.vnode(context=c)
        v.setBodyString(b)
        v.setHeadString(h)
        v.fileIndex = g.app.nodeIndices.scanGnx(gnx,0)
        self.v_dict [gnx] = v

    if trace:
        g.trace('gnx: %-22s v: %s len(body): %-4d %s' % (
            gnx,id(v),len(b),h))

    self.handle_json_tnode_attributes(json_node,v)
    self.handle_json_vnode_attributes(json_node,v)
    return v
</t>
<t tx="ekr.20110414094917.2410">def handle_json_tnode_attributes (self,json_node,v):

    trace = False and not g.unitTesting
    d = json_node.get('tnodeAttributes',{})
    if trace and d: g.trace(json_node,list(d.keys()))

    aDict = {}
    for key in d:
        val = g.toUnicode(d.get(key)) # 2011/02/22
        val2 = self.get_json_ua(key,val)
        # g.trace(key,val,val2)
        aDict[key] = val2

    if aDict:
        if trace: g.trace('uA',v,list(aDict.keys()))
        v.unknownAttributes = aDict
</t>
<t tx="ekr.20110414094917.2411"># The native attributes of &lt;v&gt; elements are a, t, vtag, tnodeList,
# marks, expanded, and descendentTnodeUnknownAttributes.
# New in Leo 4.5: added descendentVnodeUnknownAttributes to native attributes.

def handle_json_vnode_attributes (self,sax_node,v):

    trace = False and not g.unitTesting
    d = sax_node.get('attributes',{})

    s = d.get('a')
    if s:
        if trace and 'E' in s: g.trace('expand',v)
        # g.trace('%s a=%s %s' % (id(sax_node),s,v.headString()))
        # 'C' (clone) and 'D' bits are not used.
        if 'M' in s: v.setMarked()
        if 'E' in s: v.expand()
        if 'O' in s: v.setOrphan()
        # if 'T' in s: self.topVnode = v
        if 'V' in s:
            # g.trace('setting currentVnode',v,color='red')
            self.currentVnode = v

    s = d.get('tnodeList','')
    tnodeList = s and s.split(',')
    if tnodeList:
        # This tnodeList will be resolved later.
        if trace: g.trace('found tnodeList',v.headString(),tnodeList)
        v.tempTnodeList = tnodeList

    s = d.get('descendentTnodeUnknownAttributes')
    if s: 
        aDict = self.getDescendentUnknownAttributes(s,v=v)
        if aDict:
            # g.trace('descendentTnodeUaDictList',aDict)
            self.descendentTnodeUaDictList.append(aDict)

    s = d.get('descendentVnodeUnknownAttributes')
    if s: 
        aDict = self.getDescendentUnknownAttributes(s,v=v)
        if aDict:
            # g.trace('descendentVnodeUaDictList',aDict)
            self.descendentVnodeUaDictList.append((v,aDict),)

    s = d.get('expanded')
    if s:
        aList = self.getDescendentAttributes(s,tag="expanded")
        # g.trace('expanded list',len(aList))
        self.descendentExpandedList.extend(aList)

    s = d.get('marks')
    if s:
        aList = self.getDescendentAttributes(s,tag="marks")
        # g.trace('marks list',len(aList))
        self.descendentMarksList.extend(aList)

    aDict = {}
    for key in d:
        if key in self.nativeVnodeAttributes:
            # This is not a bug.
            if False and trace: g.trace(
                '****ignoring***',key,d.get(key))
        else:
            val = d.get(key)
            val2 = self.getSaxUa(key,val)
            aDict[key] = val2
            # g.trace(key,val,val2)
    if aDict:
        # if trace: g.trace('uA',v,aDict)
        v.unknownAttributes = aDict
</t>
<t tx="ekr.20110414094917.2413">def get_json_ua(self,attr,val,kind=None): # Kind is for unit testing.

    """Parse an unknown attribute in a &lt;v&gt; or &lt;t&gt; element.
    The unknown tag has been pickled and hexlify'd.
    """

    try:
        # val = str(val)
        val = g.toEncodedString(val) # 2011/02/22.
    except Exception:
        g.es_print('unexpected exception converting hexlified string to string')
        g.es_exception()
        return None


    # New in 4.3: leave string attributes starting with 'str_' alone.
    if attr.startswith('str_') and type(val) == type(''):
        # g.trace(attr,val)
        return val

    # New in 4.3: convert attributes starting with 'b64_' using the base64 conversion.
    if 0: # Not ready yet.
        if attr.startswith('b64_'):
            try: pass
            except Exception: pass

    try:
        binString = binascii.unhexlify(val) # Throws a TypeError if val is not a hex string.
    except Exception:
        # Python 2.x throws TypeError
        # Python 3.x throws binascii.Error
        # Assume that Leo 4.1 wrote the attribute.
        if g.unitTesting:
            assert kind == 'raw','unit test failed: kind=' % repr(kind)
        else:
            g.trace('can not unhexlify %s=%s' % (attr,val))
        return val
    try:
        # No change needed to support protocols.
        val2 = pickle.loads(binString)
        # g.trace('v.3 val:',val2)
        return val2
    except (pickle.UnpicklingError,ImportError,AttributeError,ValueError):
        g.trace('can not unpickle %s=%s' % (attr,val))
        return val
</t>
<t tx="ekr.20110414094917.2415">def readSaxFile (self,theFile,fileName,silent,inClipboard,reassignIndices,s=None):

    dump = False and not g.unitTesting
    fc = self ; c = fc.c

    # Pass one: create the intermediate nodes.
    saxRoot = fc.parse_leo_file(theFile,fileName,
        silent=silent,inClipboard=inClipboard,s=s)

    if dump: fc.dumpSaxTree(saxRoot,dummy=True)

    # Pass two: create the tree of vnodes and tnodes from the intermediate nodes.
    if saxRoot:
        parent_v = c.hiddenRootNode
        children = fc.createSaxChildren(saxRoot,parent_v)
        assert c.hiddenRootNode.children == children
        v = children and children[0] or None
        return v
    else:
        return None
</t>
<t tx="ekr.20110414094917.2416">def resolve_tnode_lists (self):

    trace = False and not g.unitTesting
    c = self.c

    for p in c.all_unique_positions():
        if hasattr(p.v,'tempTnodeList'):
            # g.trace(p.v.headString())
            result = []
            for tnx in p.v.tempTnodeList:
                index = self.canonicalTnodeIndex(tnx)
                v = self.gnxDict.get(index)
                if v:
                    if trace: g.trace(tnx,v)
                    result.append(v)
                else:
                    g.trace('*** No vnode for %s' % tnx)
            if result:
                p.v.tnodeList = result
                # g.trace('*** tnodeList for',p.h,result)
            delattr(p.v,'tempTnodeList')
</t>
<t tx="ekr.20110414094917.2417">def resolve_archived_position(self,archivedPosition,root_v):

    '''Return a vnode corresponding to the archived position relative to root node root_v.'''

    def oops (message):
        if not g.app.unitTesting:
            g.es_print('bad archived position: %s' % (message),color='red')

    try:
        aList = [int(z) for z in archivedPosition.split('.')]
        aList.reverse()
    except Exception:
        return oops('"%s"' % archivedPosition)

    if not aList:
        return oops('empty')

    last_v = root_v
    n = aList.pop()
    if n != 0:
        return oops('root index="%s"' % n )

    while aList:
        n = aList.pop()
        children = last_v.children
        if n &lt; len(children):
            last_v = children[n]
        else:
            return oops('bad index="%s", len(children)="%s"' % (n,len(children)))

    return last_v
</t>
<t tx="ekr.20110414094917.2418">def setPositionsFromVnodes (self):

    trace = False and not g.unitTesting
    c = self.c ; p = c.rootPosition()
    current,str_pos = None,None

    use_db = g.enableDB and c.mFileName
    if use_db:
        str_pos = c.cacher.getCachedStringPosition()

    if not str_pos:
        d = hasattr(p.v,'unknownAttributes') and p.v.unknownAttributes
        if d: str_pos = d.get('str_leo_pos')
        if trace: g.trace('from p.v.u',str_pos)

    if str_pos:
        current = self.archivedPositionToPosition(str_pos)

    c.setCurrentPosition(current or c.rootPosition())
</t>
<t tx="ekr.20110414094917.2419">def archivedPositionToPosition (self,s):

    c = self.c
    s = g.toUnicode(s) # 2011/02/25
    aList = s.split(',')
    try:
        aList = [int(z) for z in aList]
    except Exception:
        # g.trace('oops: bad archived position. not an int:',aList,c)
        aList = None
    if not aList: return None
    p = c.rootPosition() ; level = 0
    while level &lt; len(aList):
        i = aList[level]
        while i &gt; 0:
            if p.hasNext():
                p.moveToNext()
                i -= 1
            else:
                # g.trace('oops: bad archived position. no sibling:',aList,p.h,c)
                return None
        level += 1
        if level &lt; len(aList):
            p.moveToFirstChild()
            # g.trace('level',level,'index',aList[level],p.h)
    return p
</t>
<t tx="ekr.20110414094917.2420">if 0:
    @others</t>
<t tx="ekr.20110414094917.2422">def read_json_data (self,json_list,reassignIndices=True):
    
    '''Create Leo's vnodes from data, a Python object created by json.loads.'''

    trace = True and not g.unitTesting
    fc = self ; c = fc.c ; tag = '@json-outline'
    if not json_list: return None
    
    vnodes,tnodes = json_list
    assert vnodes
    assert tnodes
    fc.create_t_dict(tnodes)

    parent_p = g.findNodeAnywhere(c,'@json-outline')
        ### parent_v = c.hiddenRootNode

    if not parent_p:
        return g.trace('not found: %s' % tag)
        
    aList = vnodes.get('vnodes',[])
    assert aList
    
    # Create a dummy node so all we have to do is call create_json_children.
    dummy_json_node = { "children":aList }
    parent_v = parent_p.v
    children = fc.create_json_children(dummy_json_node,parent_v)
        
    assert parent_v.children == children,'parent_p.children: %s, children: %s' % (
        parent_v.children,children)
        
    v = children and children[0] or None
    return v
</t>
<t tx="ekr.20110414094917.2432">def create_t_dict(self,json_node):
    
    tnodes = json_node.get('tnodes',[])
    assert tnodes
    
    for z in tnodes:
        gnx = z.get('id')
        assert gnx
        self.t_dict[gnx] = z
        </t>
<t tx="ekr.20110414185051.2435">def create_v_dict(self):
    
    '''A kludge so we can properly link nodes during testing.
    
    (In actual practice, this would not be needed because
    there would be no previously existing nodes.)'''
    
    c = self.c
    
    for v in c.all_unique_nodes():
        self.v_dict[v.gnx] = v
</t>
<t tx="ekr.20110416065515.2437">from jinja2 import Template
t = Template('Hello {{ name }}!')
s = t.render(name='Edward K. Ream')
print(s)
</t>
<t tx="ekr.20110510110227.2439"></t>
<t tx="ekr.20110510110227.2440"></t>
<t tx="ekr.20110511061102.5232">True:  enable autocompletion initially.
False: disable autocomopletion initially.

You can use the enable-autocompleter and disable-autocompleter
commands to enable or disable autocompletion at any time.

Note: The 'initially' prefix is needed to distinguish this setting from
enable-autocompleter command. Otherwised they would get 'munged' to the same
configuration value.</t>
<t tx="ekr.20110511140347.2445">from PyQt4 import QtCore

timer = QtCore.QTimer()
timer.setSingleShot(True)

def callBack():
    g.trace('atIdleCallBack')

# Use a QTimer with 0 timeout.
timer.connect(timer,QtCore.SIGNAL("timeout()"),callBack)
timer.start(0)
</t>
<t tx="ekr.20110512085154.2447"></t>
<t tx="ekr.20110512225930.2456"></t>
<t tx="ekr.20110521072459.2463"></t>
<t tx="ekr.20110521072459.2464">builtins, including cython builtins</t>
<t tx="ekr.20110521072459.2465">cython keywords</t>
<t tx="ekr.20110526180653.2467"></t>
<t tx="ekr.20110526180653.2468"></t>
<t tx="ekr.20111020134534.2594"></t>
<t tx="ekr.20120311074029.2727"></t>
<t tx="ekr.20120311074029.2728"></t>
<t tx="ekr.20120311074029.2729"></t>
<t tx="ekr.20120311074029.2730"></t>
<t tx="ekr.20120311074029.2731"></t>
<t tx="ekr.20120311074029.2732"></t>
<t tx="ekr.20120311074029.2733"></t>
<t tx="ekr.20120311074029.2734"></t>
<t tx="ekr.20120311074029.2735"></t>
<t tx="ekr.20120311074029.2736"></t>
<t tx="ekr.20120312075951.2740">print(c.openDirectory)</t>
<t tx="ekr.20120320072350.2731"></t>
<t tx="ekr.20120426175039.2682">import asyncore
import socket

@others

host,port = '127.0.0.1',24

try:
    s = socket.socket(socket.AF_INET)
    s.connect((host,port),)
    print('Leo already running') #  at %s:%s' % (host,port))

except socket.error:
    s = None
    
if not s:
    try:
        s=Server(host,port,RequestHandler)
        print('Starting Leo')
    except socket.error:
        g.es_exception()
</t>
<t tx="ekr.20120426175039.2683">class Server(asyncore.dispatcher):

    @others
</t>
<t tx="ekr.20120426175039.2684">def __init__ (self, host, port, handler):

    self.ip = host
    self.port = port
    self.handler=handler

    asyncore.dispatcher.__init__ (self)
    self.create_socket (socket.AF_INET,socket.SOCK_STREAM)

    self.set_reuse_addr()
    self.bind ((host,port),)
    self.listen (2)
    g.es_print('listening on %s:%s' % (host,port))
</t>
<t tx="ekr.20120426175039.2685">def handle_accept (self):
    
    try:
        conn, addr = self.accept()
        g.trace('accepted connection: %s' % (addr))
    except socket.error:
        self.log_info ('warning: server accept() threw an exception', 'warning')
        return
    except TypeError:
        self.log_info ('warning: server accept() threw EWOULDBLOCK', 'warning')
        return

    # creates an instance of the handler class to handle the request/response
    # on the incoming connexion
    self.handler(conn,addr,self)
</t>
<t tx="ekr.20120426175039.2686">class RequestHandler:
    
    pass
    
    if 0:
        def __init__(self,conn,addr,server):
            g.es_print('RequestHandler.ctor conn: %s addr: %s server: %s' % (
                conn,addr,server))
</t>
<t tx="ekr.20120913105857.2914"></t>
<t tx="ekr.20120913105857.2915">This is a brief tutorial for getting familiar with basic Leo
functionality. Click around and experiment.

Note that you probably want to save your own "working copy"
of this file before proceeding further. Do that by "File -&gt;
Save as".

This guide is intentionally quite brief and minimal -
therefore, it merely scratches the surface of what Leo can
do. You can begin leveraging Leo for mindmapping-like tasks
by just reading the node "Tree manipulation basics", and
moving on to other topics after acquiring some basic
familiarity. </t>
<t tx="ekr.20120913105857.2918">"External file" means a file that resides on your file
system. If you are programming, these are the files you
eventually want to create to get something useful out of
Leo, for example, your C++ or Python source code files.</t>
<t tx="ekr.20120913105857.2919">Remove the first @ from @thin in the subtree below and save
(ctrl+s) to create an "external" file which is directly
usable outside leo - try opening the resulting myfile.py in
a normal text editor (e.g. from right-click menu on the @thin node) 
to see what it looks like.

Note the @others directive, and the the lines that look like

#@-node:ville.20090627211608.10122:class Foo

These are called "sentinels", and they are needed to
preserve the tree structure in the external files. They
allow your tree structure to survive, even when someone else
edits the source (or you edit it yourself in an external
editor).</t>
<t tx="ekr.20120913105857.2920"> </t>
<t tx="ekr.20120913105857.2921">@language python
@others
</t>
<t tx="ekr.20120913105857.2922"></t>
<t tx="ekr.20120913105857.2923">import os
import sys

</t>
<t tx="ekr.20120913105857.2924">def init1():
    print "init1"

def init2():
    print "init2"</t>
<t tx="ekr.20120913105857.2925">class Foo:
    &lt;&lt; docstring &gt;&gt;
    @others


</t>
<t tx="ekr.20120913105857.2926">""" Some sort of useful class """

</t>
<t tx="ekr.20120913105857.2927">def spam(self):
    pass

</t>
<t tx="ekr.20120913105857.2928">def eggs(self):
    pass</t>
<t tx="ekr.20120913105857.2929">If the sentinels in thin nodes are unacceptable for your workflow 
(typically the case when you are the only one using Leo in a 
particular project), you can use @auto nodes to "play well with 
others". @auto nodes understand the structure of the source code
(parsers exist for popular languages), and create the "typical"
outline for the code when the file is loaded. When you save, the outline is 
written back.

Do the same thing you did with @@thin - i.e., 

- Remove the first @, and save. 
- Check the resulting file (`/myfile_auto.py) and observe that it has 
  no sentinels.   
- There is no "magic" involved. If you execute 'File -&gt; Read auto nodes" 
  (or right click on @auto node and choose "Refresh from disk", or reopen 
  this document), you'll note that  the outline structure was lost, 
  and the "parsed" structure is created instead. This is the cost
  of using @auto nodes.</t>
<t tx="ekr.20120913105857.2930"></t>
<t tx="ekr.20120913105857.2931">@language python
@others
</t>
<t tx="ekr.20120913105857.2932"></t>
<t tx="ekr.20120913105857.2933">import os
import sys

</t>
<t tx="ekr.20120913105857.2934">def init1():
    print "init1"

def init2():
    print "init2"</t>
<t tx="ekr.20120913105857.2935">class Foo:
    &lt;&lt; docstring &gt;&gt;
    @others


</t>
<t tx="ekr.20120913105857.2936">""" Some sort of useful class """

</t>
<t tx="ekr.20120913105857.2937">def spam(self):
    pass

</t>
<t tx="ekr.20120913105857.2938">def eggs(self):
    pass</t>
<t tx="ekr.20120913105857.2939">In this tree, you can experiment with @shadow. It combines the benefits
of @thin and @auto - namely, it publishes a file without sentinels, but
still allows the tree structure to survive, even if the external file
is edited outside Leo.

The cost is complexity - @shadow relies on a "shadow file" that remembers
the structure, and a sophisticated diff/patch algorithm that merges
the changes from the external file to the tree structure.

Experiment by editing the external file outside Leo and doing Right click
-&gt; refresh from disk on the @shadow node. </t>
<t tx="ekr.20120913105857.2940"></t>
<t tx="ekr.20120913105857.2941">@language python
@others
</t>
<t tx="ekr.20120913105857.2942"></t>
<t tx="ekr.20120913105857.2943">import os
import sys

</t>
<t tx="ekr.20120913105857.2944">def init1():
    print "init1"

def init2():
    print "init2"</t>
<t tx="ekr.20120913105857.2945">class Foo:
    &lt;&lt; docstring &gt;&gt;
    @others


</t>
<t tx="ekr.20120913105857.2946">""" Some sort of useful class """

</t>
<t tx="ekr.20120913105857.2947">def spam(self):
    pass

</t>
<t tx="ekr.20120913105857.2948">def eggs(self):
    pass</t>
<t tx="ekr.20120913105857.2949">reStructuredText (http://docutils.sourceforge.net/rst.html)
is an efficient way of authoring documentation as plain text.
Leo provides first-class support for RST authoring, including 
the unique feature of representing RST outline structure
as Leo tree. You can find an example in the tree below - again,
just remove the first @ character from @@auto-rst and save,
opening the external file afterwards.
</t>
<t tx="ekr.20120913105857.2950"></t>
<t tx="ekr.20120913105857.2951" rst-import="7d710028580b000000756e6465726c696e657332710158000000007102580b000000756e6465726c696e65733171036802752e">@language rest
@tabwidth -4
@others

.. Warning: this node is ignored when writing this file.
.. However, @ @rst-options are recognized in this node.

</t>
<t tx="ekr.20120913105857.2952">Observe the underlining style of the headings.
</t>
<t tx="ekr.20120913105857.2953">Some text in first other chapter.
</t>
<t tx="ekr.20120913105857.2954">More text in other chapter.</t>
<t tx="ekr.20120913105857.2955">If you are just starting, you should create your own myLeoSettings.leo in ~/.leo. We'll do that next.

Create the file first: 
  - File -&gt; New (or ctrl+N)
  - File -&gt; Save as
  - Navigate to ~/.leo
  - save as myLeoSettings.leo

In the current tree, there is @@settings subtree. We are
copying this to the new file. Go to node @@settings, and
copy the whole tree to clipboard (ctrl+shift+c).
  
Select the document that has myLeoSettings.leo (the one you
just created). Drop the settings tree there (ctrl+shift+v),
Remove extra @ from @@settings, and save again.

Now, you should be all set. Verify that it worked by Help-&gt;open myLeoSettings.leo
</t>
<t tx="ekr.20120913105857.2956"># execute this script by ctrl+b to find out where your ~/.leo is

g.es('Homedir is at ',g.app.homeLeoDir)

</t>
<t tx="ekr.20120913105857.2957"></t>
<t tx="ekr.20120913105857.2958"># Leo loads plugins in the order they appear here.
# File names may be indented as desired.

# Standard plugins enabled in official distributions....

plugins_menu.py
leo_to_html.py
mod_scripting.py
quicksearch.py
UNL.py
contextmenu.py
nav_qt.py

# The plugins manager plugin does not
# understand @enabled-plugins nodes.
# plugin_manager.py

# The rst3 plugin is no longer needed.
# It's code has been moved to Leo's core
# rst3.py

# These plugins used to be enabled when using the tk plugin.
# cleo.py
# hoist.py
# image.py
# nav_buttons.py
# threading_colorizer.py

# All other plugins.
# Order is important for enabled plugins that
# add items to the icon area.

# ConceptualSort.py
# EditAttributes.py
# FileActions.py
# Library.py
# nodeActions.py
# UASearch.py
# URLloader.py
# UniversalScrolling.py

# add_directives.py
# arrows.py
# at_folder.py
# at_view.py
# autotrees.py
# base64Packager.py
# bibtex.py
# chapter_hoist.py
# cleo.py
# color_markup.py
# datenodes.py
# detect_urls.py
# dyna_menu.py
# fastGotoNode.py
# footprints.py
# groupOperations.py
# hoist.py
# image.py
# import_cisco_config.py
# ipython.py
# keybindings.py
# leoOPML.py
# leo_to_html.py
# leo_to_rtf.py
# leoupdate.py
# macros.py
# mod_autosave.py
# mod_http.py
# mod_labels.py
# mod_read_dir_outline.py
# mod_shadow.py
# multifile.py
# nav_buttons.py
# newButtons.py
# niceNosent.py
# nodebar.py
# nodenavigator.py
# open_shell.py
# open_with.py
# paste_as_headlines.py
# pie_menus.py
# pretty_print.py
# print_cp.py
# quickMove.py
# rClick.py
# read_only_nodes.py
# rowcol.py
# run_nodes.py
# s_menu.py
# scheduler.py
# searchbox.py
# shortcut_button.py
# slideshow.py
# table.py
# templates.py
# trace_tags.py
# vim.py
# word_count.py
# word_export.py
# xcc_nodes.py
# xemacs.py
# xsltWithNodes.py
# zodb.py
# quicksearch.py
# tomboy_import.py
# ctagscompleter.py
# colorize_headlines.py</t>
<t tx="ekr.20120913105857.2959">horizontal: body pane to the left
vertical: body pane on the botton

vertical is the default; you may prefer horizontal for small but wide screens (e.g. on laptops)</t>
<t tx="ekr.20120913105857.2960">This tree containt some suggested "looks" for Leo.

To experiment, you may want to use a @button that applies
the stylesheet in current node; look for "@button set-style-sheet" 
in scripts.leo.

For information on stylesheets, see

http://doc.trolltech.com/stylesheet.html

Style contributions are welcome.</t>
<t tx="ekr.20120913105857.2961">Classic Leo colors. This should look good on Linux.</t>
<t tx="ekr.20120913105857.2962">/* Documentation of Qt stylesheets at http://doc.trolltech.com/stylesheet.html 

To experiment, you may want to use a @button that applies
the current stylesheet; look for "@button set-style-sheet" in
scripts.leo.

*/

/* Valid color names: http://www.w3.org/TR/SVG/types.html#ColorKeywords */

/* A QWidget: supports only background attributes.*/

QSplitter::handle {
    background-color: #CAE1FF; /* lightSteelBlue1 */
}

QStackedWidget {
    /* background-color:lightpink; */
    border-color: red;
    padding: 0px;
    /* border-width: 0px; */
    /* background-color: yellow; */
}

QSplitter {
    border-color: white;
    background-color: white;
    border-style: solid;
}

QTreeWidget {
    /* These apply to the selected item, but not to editing items.*/
    background-color: #ffffec; /* Leo's traditional tree color */
    selection-color: black; /* was white */
    selection-background-color: lightgrey;
    /* font-family: SansSerif; */
    font-family: DejaVu Sans Mono;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal, italic,oblique */
 }

/* Headline edit widgets */
QTreeWidget QLineEdit {
    background-color: cornsilk;
    selection-color: white;
    selection-background-color: blue;
    font-family: DejaVu Sans Mono;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal, italic,oblique */
}

/* The log panes */
QTextEdit {
    background-color: #f2fdff;
    selection-color: white;
    selection-background-color: blue;
    /* font-family: Courier New; */
    font-family: DejaVu Sans Mono;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal, italic,oblique */
}

/* The body pane */
QTextEdit#richTextEdit {
    background-color: #fdf5f5; /* A kind of pink. */
    selection-color: white;
    selection-background-color: lightgrey;
    font-family: DejaVu Sans Mono;
    /* font-family: Courier New; */
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal,italic,oblique */
}

QLabel {
    font-family: DejaVu Sans Mono;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal,italic,oblique */
}

/* Editor labels */
QLineEdit#editorLabel {
    background-color: #ffffec;
    font-family: DejaVu Sans Mono;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal,italic,oblique */
    border: 2px;
    margin: 2px;
}

/* The mini-buffer */
QLineEdit#lineEdit {
    selection-color: white;
    selection-background-color: lightgrey;
    font-family: DejaVu Sans Mono;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal,italic,oblique */
}

QLineEdit#status1 {
    background-color: lightgrey;
    border-width: 1px;
    border-style: solid;
    border-color: darkgrey;
}

QLineEdit#status2 {
    background-color: lightgrey;
    border-width: 1px;
    border-style: solid;
    border-color: darkgrey;
}

XXQPushButton {
    background-color: #fdf5f5; /* A kind of pink. */
    margin: 2px;
    padding; 4px;
    border-width: 2px;
    border-style: solid;
    border-color: darkgrey;
}

/* QMenuBar works, but not QMenu... */
XXQMenuBar {
    font-family: DejaVu Sans Mono;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal,italic,oblique */
}
</t>
<t tx="ekr.20120913105857.2963">This is the classic Leo look, but with fonts that
allegedly look better on Mac.</t>
<t tx="ekr.20120913105857.2964">/* Documentation of Qt stylesheets at http://doc.trolltech.com/4.2/stylesheet.html */

/* Valid color names: http://www.w3.org/TR/SVG/types.html#ColorKeywords */

/* A QWidget: supports only background attributes.*/

QSplitter::handle {
    background-color: #CAE1FF; /* lightSteelBlue1 */
}

QStackedWidget {
    /* background-color:lightpink; */
    border-color: red;
    padding: 0px;
    /* border-width: 0px; */
    /* background-color: yellow; */
}

QSplitter {
    border-color: white;
    background-color: white;
    border-style: solid;
}

QTreeWidget {
    /* These apply to the selected item, but not to editing items.*/
    background-color: #ffffec; /* Leo's traditional tree color */
    selection-color: black; /* was white */
    selection-background-color: lightgrey;
    /* font-family: SansSerif; */
    font-family: Lucida Grande;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal, italic,oblique */
 }

/* Headline edit widgets */
QTreeWidget QLineEdit {
    background-color: cornsilk;
    selection-color: white;
    selection-background-color: blue;
    font-family: Lucida Grande;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal, italic,oblique */
}

/* The log panes */
QTextEdit {
    background-color: #f2fdff;
    selection-color: white;
    selection-background-color: blue;
    font-family: Monaco;
    font-size: 10px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal, italic,oblique */
}

/* The body pane */
QTextEdit#richTextEdit {
    background-color: #fdf5f5; /* A kind of pink. */
    selection-color: white;
    selection-background-color: lightgrey;
    font-family: Monaco;
    /* font-family: Courier New; */
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal,italic,oblique */
}

QLabel {
    font-family: Lucida Grande;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal,italic,oblique */
}

/* Editor labels */
QLineEdit#editorLabel {
    background-color: #ffffec;
    font-family: Lucida Grande;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal,italic,oblique */
    border: 2px;
    margin: 2px;
}

/* The mini-buffer */
QLineEdit#lineEdit {
    selection-color: white;
    selection-background-color: lightgrey;
    font-family: Monaco;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal,italic,oblique */
}

QLineEdit#status1 {
    background-color: lightgrey;
    border-width: 1px;
    border-style: solid;
    border-color: darkgrey;
}

QLineEdit#status2 {
    background-color: lightgrey;
    border-width: 1px;
    border-style: solid;
    border-color: darkgrey;
}

XXQPushButton {
    background-color: #fdf5f5; /* A kind of pink. */
    margin: 2px;
    padding; 4px;
    border-width: 2px;
    border-style: solid;
    border-color: darkgrey;
}

/* QMenuBar works, but not QMenu... */
XXQMenuBar {
    font-family: Lucida Grande;
    font-size: 12px;
    font-weight: normal; /* normal,bold,100,..,900 */
    font-style: normal; /* normal,italic,oblique */
}</t>
<t tx="ekr.20120913105857.2965">If zero, all nodes are colorized, regardless of length of body text.
If &gt; 0, only nodes whose body text are smaller than this limit are colorized.</t>
<t tx="ekr.20120913105857.2966"># Add commands to contextmenu
# The format is &lt;command&gt; SPACE &lt;description&gt;

# stickynote Create a sticky note
# read-at-file-nodes Read file node</t>
<t tx="ekr.20120913105857.2967">Avoid red focus borders in body pane (if it's not in your aesthetic taste)</t>
<t tx="ekr.20120913105857.2968">Press ctrl + F to enter "minibuffer find" mode. Press F3 to
"find again".

For large scale searches (classic "find in files"
functionality for the whole tree), look for the "Nav" tab in
the log pane (in upper right of the screen). Enter your
search string and press enter, then click on the matches.

You can also activate the "Nav" functionality with ctrl+shift+f.

To perform find-and replace, press ctrl-f, enter the text
to search, then press ctrl+shift+r, and enter the text to replace
the matches with, and press Enter.

To limit the replace operations to particular external file,
you can use your external editor. That is, right click on
the @thin node (say, @thin myfile.py), choose "Edit
myfile.py in MYEDITOR", and perform the necessary operations.
After that, right click on the node and choose "Refresh from 
disk".
</t>
<t tx="ekr.20120913105857.2969">The minibuffer is the text input area at the bottom of the
screen, familiar to users of emacs and vi.

Press alt-x to enter a minibuffer command (e.g. alt-x
fill-paragraph). Press ctrl+p (repeat-complex-command)
folowed by Enter to re-run a previous minibuffer command.</t>
<t tx="ekr.20120913105857.2970">Eventually, you will want to add extra functionality to your
Leo documents. There are a few simple ways, and unlimited 
power for advanced users

</t>
<t tx="ekr.20120913105857.2971">You can write scripts in your document trees, and execute
them with ctrl+b. Try it on the child of this node - it
should display the list of nodes that have a headline
starting with @ in the log pane.

It will also append the summary as a new node under itself.

</t>
<t tx="ekr.20120913105857.2972">@language python
# c is "commander", central api object specific to current document 

# get a list of "position" objects
nodes = c.find_h('^@')

res = []
for n in nodes:
    # .b gets the body text, .h is headline
    body = n.b
    res.append("- " + n.h)
    
    res.append("   " + str(body.count('\n')) + " lines")
    
# 'p' is the 'current position'    
child = p.insertAsLastChild()    
child.b = "\n".join(res)
child.h = "Report"

c.redraw()    </t>
<t tx="ekr.20120913105857.2973">You can create buttons in the button bar by adding @button
nodes to your outline.

A button does not appear automatically when you add it - you
need to reopen the document to make it appear.

</t>
<t tx="ekr.20120913105857.2974"># p is current position

g.es("p.h is " + p.h)</t>
<t tx="ekr.20120914093811.2824">c.save()

m = c.screencast_controller
assert m

if 1:
    # Start at c.p
    m.start(c.p)   
else:
    # You can start a screencast anywhere:
    # it continues until the first node that contains a call to m.quit()
    # However, this automatic find feature is a convenience.
    p = m.find_screencast(p)
    assert p
    m.start(p)</t>
<t tx="ekr.20120914093811.2825"></t>
<t tx="ekr.20120914093811.2826"># Create a root node for the examples.

m.p1.contract()
c.redraw_now(m.p1)

# Speed up typing.
# m.n1 = m.n2 = 0.0

m.log('Ctrl-I inserts a new node')

# Put the new node after the @screencast node.
m.command('insert-node')
</t>
<t tx="ekr.20120914104624.2829">m.log('Ctrl-H begins editing')
m.command('edit-headline')
</t>
<t tx="ekr.20120914104624.2832">m.log('Return puts focus in the body pane')
m.focus('body')
</t>
<t tx="ekr.20120914104624.2833">m.log('Now we can type some text')
m.body_keys('This is some body text.\n')
m.body_keys('Some more body text.\n',n1=0.0,n2=0.0)
m.log(
    'The little square in the icon box\n' +
    'indicates that the node has body text')</t>
<t tx="ekr.20120914104624.2834">m.log("Let's insert a new node")
m.command('insert-node')
</t>
<t tx="ekr.20120914104624.2835">m.log('Ctrl-R moves the outline right')
m.command('move-outline-right')
</t>
<t tx="ekr.20120914104624.2836">m.log('UpArrow selects the previous node')
m.command('goto-prev-visible')
</t>
<t tx="ekr.20120914104624.2837">m.log('LeftArrow collapses the node')
m.command('contract-node')
</t>
<t tx="ekr.20120914104624.2838">m.log('RightArrow expands the node')
m.command('expand-node')</t>
<t tx="ekr.20120914174750.2850">m.log('That\'s all folks!')
</t>
<t tx="ekr.20120914174750.2851">p2 = m.p1.next()
if p2 and p2.h == 'Node 1':
    p2.doDelete()
    c.redraw_now(m.p1)
m.quit()</t>
<t tx="ekr.20120914174750.2853">m.log(
    'The new node has a black icon border '
    'indicating that the node has changed')
</t>
<t tx="ekr.20120914182320.2853">m.log("We'll type in the headline")
m.head_keys('Node 1')
</t>
<t tx="ekr.20120914183137.2850"></t>
<t tx="ekr.20120914183137.2851">m.tree('This is the tree pane')</t>
<t tx="ekr.20120914183137.2853">m.log('This is the log pane')</t>
<t tx="ekr.20120914183137.2855">m.body('This is the body pane')</t>
<t tx="ekr.20120914183137.2856">m.body('The minibuffer is below the body pane')</t>
<t tx="ekr.20120914183137.2857">m.tree('The icon area appears above the tree pane')</t>
<t tx="ekr.20120915073533.2862"></t>
<t tx="ekr.20120915112650.2864">m.log('The icon for a changed node has a black border.')
m.image('tree','box08.GIF',center=True,height=100)</t>
<t tx="ekr.20120915114713.2866">m.log('The icon for an empty, unchanged node has a gray border.')
m.image('tree','box00.GIF',center=True,height=100)</t>
<t tx="ekr.20120915122112.2868"></t>
<t tx="ekr.20120915122112.2869">m.log('A marked node has an icon with a red vertical line.')
m.image('tree','box02.GIF',center=True,height=100)</t>
<t tx="ekr.20120915122112.2870">m.log('A cloned node has an icon with a red arrow.')
m.image('tree','box04.GIF',center=True,height=100)</t>
<t tx="ekr.20120915122112.2871">m.log('A node with body text has a small blue square in its icon')
m.image('tree','box01.GIF',center=True,height=100)</t>
<t tx="ekr.20120915122112.2872">m.log('This changed, cloned, marked node has body text')
m.image('tree','box15.GIF',center=True,height=100)</t>
<t tx="ekr.20120915122112.2873">m.log('Each node has an oblong icon box to the left of its headline')
</t>
<t tx="ekr.20120915122112.2874">m.log('The save command clears all black borders')
m.image('tree','box07.GIF',center=True,height=100)</t>
<t tx="ekr.20120915162554.2882"></t>
<t tx="ekr.20120915162554.2883">m.body(
    'The minibuffer is an area at the bottom of the screen.\n'
    'You use the minibuffer to enter commands by name.\n'
    '&lt;Alt-X&gt; opens the minibuffer')
m.single_key('alt-x')

</t>
<t tx="ekr.20120915164308.2886">m.body(
    'We only need to type the start of long command names.\n'
    'Here we have typed "ins" to begin one of Leo\'s insert commands.')
m.plain_keys('ins')
</t>
<t tx="ekr.20120915170516.2888">m.body(
    'The &lt;Tab&gt; key does tab completion.\n'
    'The Completion tab shows all the valid completions.\n'
    'The minibuffer shows the longest common prefix.')
m.plain_keys('\t')
</t>
<t tx="ekr.20120915173000.2894">m.body(
    'Typing "no&lt;Tab&gt;" is enough to complete the command:\n'
    'only one command appears in the Completion tab.')
m.plain_keys('no\t')
</t>
<t tx="ekr.20120915173000.2895">m.body(
    'When only one item appears in the Completion list\n'
    'The &lt;Return&gt; key will execute the command'
)
</t>
<t tx="ekr.20120915174321.2898">m.body('A new node has been inserted')
m.plain_keys('\n')
</t>
<t tx="ekr.20120915175727.2905">m.body('Deleting the newly-inserted node concludes this slideshow.')

</t>
<t tx="ekr.20120915181136.2907"></t>
<t tx="ekr.20120916063628.2912">m.tree('This screencasts discusses Leo\'s basic Find/Change commands')</t>
<t tx="ekr.20120916063628.2913">
m.quit()</t>
<t tx="ekr.20120916063628.2922">m.quit()</t>
<t tx="ekr.20120916065229.2914">assert m.p1
p2 = m.p1.next()
assert p2
if p2.h == 'newHeadline' and not p2.b:
    p2.doDelete()

m.quit()</t>
<t tx="ekr.20120916065229.2916">m.tree(
    'Typing &lt;Ctrl-F&gt; starts the find command.\n'
    'Leo shows the Find Tab in the Log pane.\n'
    'The minibuffer prompts you for a Find string'
)

m.single_key('ctrl-f')
m.plain_keys('def spam')
</t>
<t tx="ekr.20120916140331.2916">m.tree('Typing &lt;Return&gt; starts the search')
</t>
<t tx="ekr.20120916184021.2918">def spam():
    pass</t>
<t tx="ekr.20120916184840.2920">m.tree('The search succeeds')

p2 = g.findNodeInTree(c,m.p1,'spam')
m.redraw(p2)

m.plain_keys('\n')
</t>
<t tx="ekr.20120916185527.2922">m.body('Typing o&lt;Tab&gt; gets us back to the insert-node command')
m.plain_keys('o\t')
</t>
<t tx="ekr.20120917133405.2948">m.body('Typing a single &lt;BackSpace&gt; shows the same completions')
m.plain_keys('\b')
</t>
<t tx="ekr.20120917133405.2950">m.body('Typing another &lt;BackSpace&gt; still shows the same completions')
m.plain_keys('\b')
</t>
<t tx="ekr.20120917133405.2952">m.body('Typing a third &lt;BackSpace&gt; shows more completions')
m.plain_keys('\b')
</t>
<t tx="ekr.20120917133405.2953">m.body('Typing "e" followed by &lt;Tab&gt; completes the insert-newline command')
m.plain_keys('e\t')</t>
<t tx="ekr.20120917133405.2955">m.body('Typing &lt;BackSpace&gt; six more times restores the previous completions')
m.plain_keys('\b\b\b\b\b\b')
</t>
<t tx="ekr.20120917200834.2928"></t>
<t tx="ekr.20120918103721.2944">@language rest</t>
<t tx="ekr.20120918103721.2948">m.quit()</t>
<t tx="ekr.20120918111016.2955">Let's go behind the scenes to see how this slidewhow works...</t>
<t tx="ekr.20120918113531.2956">This screencast discusses how to make screencasts with the screencasts
plugin. This screencasts goes "behind the scenes" to revealing the inner
workings of screencasts that are usually hidden. So this screencast is
**unusual**, much like a TeX document that discusses TeX will be unusual.

Indeed, this first "scene" of the screencast simply shows this particular
node. As we shall see, screencasts usually do more than just show text.

When you have finished reading this node, hit the Right Arrow key to to go
the next scene.
</t>
<t tx="ekr.20120918113531.2957">This is some *emphasized* motivation.</t>
<t tx="ekr.20120918115916.2954">m.log(
    'All screencasts should end with a call to m.quit(). '
    'For this last slide, we\'ll show the *next* slide '
    'by calling m.redraw(m.p.next()).')
m.redraw(m.p.next())</t>
<t tx="ekr.20120918121401.2957">It's easy to show the text of another node in the present slideshow whose
headline h is known::

    p2 = g.findNodeInTree(c,m.p1,h)
    m.redraw(p2)
    
This selects p2 in the outline and shows the body text of p2.
</t>
<t tx="ekr.20120918123030.2960">m.log('This screencast shows the different parts of Leo\'s screen')</t>
<t tx="ekr.20120918143835.2964">- Make it easy to demonstrate Leo's features.

- Generate graphics and comments easily.

- Easily scriptable.

- Easy to generate *finished* slides.</t>
<t tx="ekr.20120918144251.2964">The screencast plugin creates a **screencast**, a series of **slides** or **scenes**.
Slides are static; scenes may contain animations.

By default, a screencast is made up of an @screencast node and all its
descendants. Each node represents one slide or scene. The screencast moves
from node to node. Each node executes a **screencast script**. Typically,
the script in each node modifies some part of Leo's window by switching
nodes, show commands in action, or by displaying graphics or captions.</t>
<t tx="ekr.20120918144251.2965">The screencast plugin came about in order to make it easier to show Leo in
action, and to make it easier for Leo's users to show how they use Leo.

A screencast is composed of the nodes of an **@screencast tree**.

Each **screencast node** represents a **slide**. A slide is simply the
appearance of the Leo window.

Each screencast node contains a **screencast script**. Screencast scripts
are Leo scripts, so they can do anything, they alter the appearance of the
Leo main window in some way.

Screencast scripts have access to the 'c', 'g' and 'p' vars as usual.
Screencast scripts also have access to the 'm' variable, representing the
**screencast controller** for the commander c.  Methods of the screencast
controller make it easy to show graphics, including captions.

A **caption** is a text area that overlays part of Leo's screen.  By default,
captions have a distinctive yellow background.

When showing a screencast, the **presenter** moves from slide to slide
merely by typing the Right Arrow key.  This key executes the screencast nodes
in outline order.</t>
<t tx="ekr.20120918164428.2968">m.log(
    'A screencasts is made up of nodes. '
    'Like this one.')
m.redraw(m.p)</t>
<t tx="ekr.20120918170133.2973">m.log(
    'Nodes contain scripts. '
    'Within such scripts, '
    '"m" is bound to a ScreenShotController object.'
)
m.redraw(m.p)</t>
<t tx="ekr.20120918170133.2974">m.log('This screencast is different: it shows its own nodes by calling m.redraw(m.p)')
m.redraw(m.p)</t>
<t tx="ekr.20120918170133.2975">m.log('m.p is the "program counter" of the screencast.')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2976">m.log('Most screencasts do *not* show the nodes comprising the screencast.')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2979">m.log('m.p is the position of the node whose script is being executed')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2981">m.log('As we has seen, m.log puts "caption" text in the log pane')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2982">m.log('A caption is text that overlays one of Leo\'s panes')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2983">m.log('The m.tree method puts a caption in the outline (tree) pane')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2984">m.tree('Like this')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2986">m.log('The m.body method puts a caption in the body pane')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2987">m.body('Like this')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2989">m.log('The m.redraw(p) method selects node p and redraws the screen.')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2990">m.log("It's unusual for scripts to call attention to themselves by calling m.redraw(m.p)")
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2991">m.log('Most scripts call m.redraw(p) to show a node p outside the @screencast tree')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2992">m.log('The m.image method puts up an image in an indicated pane.')
m.redraw(m.p)
</t>
<t tx="ekr.20120918170946.2993">m.log('Like this.')
m.image('tree','box00.GIF',center=True,height=100)
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2994"></t>
<t tx="ekr.20120918170946.2997">m.log('Several methods deal with key handling.')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2998">m.log('m.head_keys simulates typing in a headline')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.2999">m.log('Like this')
m.head_keys('Typing in the headline')
m.redraw(m.p)</t>
<t tx="ekr.20120918170946.3000">m.log('Oops.  Let\'s restore the previous headline.')
m.p.back().back().h = 'm.head_keys'
m.redraw(m.p)</t>
<t tx="ekr.20120918174346.3014">m.log('Similarly, m.body keys simulates typing in the body pane')
m.redraw(m.p)</t>
<t tx="ekr.20120918174346.3015">m.log("We'll put the body text in the child node. ")

c.selectPosition(m.p.firstChild())
m.body_keys('This is body text')
m.redraw(m.p)
m.p.firstChild().b = ''</t>
<t tx="ekr.20120918174346.3016"></t>
<t tx="ekr.20120918174346.3018">m.log('You can organize screencasts in several ways')
m.redraw(m.p)</t>
<t tx="ekr.20120918174346.3019">m.log('Nodes without body text act as organizer nodes. ')
m.redraw(m.p)</t>
<t tx="ekr.20120918174346.3020">m.log(
    '@ignore-node nodes are also ignored. '
    'They can contain any kind of body text.'
)
m.redraw(m.p)</t>
<t tx="ekr.20120918174346.3021">m.log('In this example, well do m.redraw(m.p.firstChild()) to show the skipped node.')
m.redraw(m.p.firstChild())</t>
<t tx="ekr.20120918174346.3022">@language rest

This node can contain any kind of text.

It is *not* treated as a screencast script.
</t>
<t tx="ekr.20120918174346.3023">m.log('The other screencasts in this file give more typical examples '
    'of how to use the methods of the ScreenCastController object.'
)
m.redraw(m.p)</t>
<t tx="ekr.20120918174346.3024"></t>
<t tx="ekr.20120918174346.3025">m.log('There ScreenCastController object has several useful convenience methods')
m.redraw(m.p)</t>
<t tx="ekr.20120918174346.3026"></t>
<t tx="ekr.20120918174346.3027">m.log('All nodes in an @ignore-tree tree are completely ignored.')
m.redraw(m.p)</t>
<t tx="ekr.20120918174346.3028"></t>
<t tx="ekr.20120918174346.3029"></t>
<t tx="ekr.20120921072549.3028"></t>
<t tx="ekr.20120922123519.3032">menu = m.open_menu('file')
</t>
<t tx="ekr.20120922123519.3033">m.open_menu('recent-files')</t>
<t tx="ekr.20120922123519.3034">m.open_menu('read/write')</t>
<t tx="ekr.20120922123519.3035">m.open_menu('export')</t>
<t tx="ekr.20120922123519.3037">m.open_menu('openwith')
</t>
<t tx="ekr.20120922123519.3038">m.open_menu('edit')</t>
<t tx="ekr.20120922123519.3039">m.open_menu('edit-body')</t>
<t tx="ekr.20120922123519.3040">m.open_menu('edit-headline')</t>
<t tx="ekr.20120922123519.3041">m.open_menu('find')</t>
<t tx="ekr.20120922124750.3050">m.open_menu('outline')</t>
<t tx="ekr.20120922124750.3051">m.open_menu('check')</t>
<t tx="ekr.20120922124750.3052">m.open_menu('expand/contract')</t>
<t tx="ekr.20120922124750.3053">m.open_menu('move')</t>
<t tx="ekr.20120922124750.3054">m.open_menu('mark')</t>
<t tx="ekr.20120922124750.3055">m.open_menu('goto')</t>
<t tx="ekr.20120922124750.3057">m.open_menu('cmds')
</t>
<t tx="ekr.20120922124750.3058">m.open_menu('plugins')</t>
<t tx="ekr.20120922124750.3059">m.open_menu('core')</t>
<t tx="ekr.20120922124750.3060">m.open_menu('window')</t>
<t tx="ekr.20120922124750.3061">m.open_menu('help')</t>
<t tx="ekr.20120922124750.3062">m.open_menu('helpcommands')</t>
<t tx="ekr.20120922124750.3063">m.open_menu('abbrev')</t>
<t tx="ekr.20120922124750.3064">m.open_menu('bodyeditors')</t>
<t tx="ekr.20120922124750.3065">m.open_menu('buffers')</t>
<t tx="ekr.20120922124750.3066">m.open_menu('chapters')</t>
<t tx="ekr.20120922124750.3067">m.open_menu('cursorselection')</t>
<t tx="ekr.20120922124750.3068">m.open_menu('cursorback')</t>
<t tx="ekr.20120922124750.3069">m.open_menu('cursorbackextendselection')</t>
<t tx="ekr.20120922124750.3070">m.open_menu('cursorbackextendto')</t>
<t tx="ekr.20120922124750.3071">m.open_menu('cursorforward')</t>
<t tx="ekr.20120922124750.3072">m.open_menu('cursorforwardextendselection')</t>
<t tx="ekr.20120922124750.3073">m.open_menu('debugging')</t>
<t tx="ekr.20120922124750.3074">m.open_menu('filesanddirectories')</t>
<t tx="ekr.20120922124750.3075">m.open_menu('focus')</t>
<t tx="ekr.20120922124750.3076">m.open_menu('icons')</t>
<t tx="ekr.20120922124750.3077">m.open_menu('macros')</t>
<t tx="ekr.20120922124750.3078">m.open_menu('minibuffer')</t>
<t tx="ekr.20120922124750.3079">m.open_menu('pickers')</t>
<t tx="ekr.20120922124750.3080">m.open_menu('rectangles')</t>
<t tx="ekr.20120922124750.3081">m.open_menu('registers')</t>
<t tx="ekr.20120922124750.3082">m.open_menu('rstcommands')</t>
<t tx="ekr.20120922124750.3084">m.open_menu('runscripttests')</t>
<t tx="ekr.20120922124750.3085">m.open_menu('scrolling')</t>
<t tx="ekr.20120922124750.3086">m.open_menu('shell')</t>
<t tx="ekr.20120922124750.3087">m.open_menu('spellcheck')</t>
<t tx="ekr.20120922124750.3088">m.open_menu('textcommands')</t>
<t tx="ekr.20120922124750.3089">m.open_menu('togglesettings')</t>
<t tx="ekr.20120922124750.3090">m.open_menu('yankandkill')</t>
<t tx="ekr.20120922191243.3126">@nocolor-node

At present, opening a menu with m.open_menu "hangs" the screencast until
the presenter hits &lt;esc&gt; enough times to dismiss the menu.

I'd like to be able to call m.dismiss_menu_bar after waiting, say, 2
seconds, but the menu won't be shown until after the entire script is
executed!

For example, the following code does not work. The menu's outline is shown
after the redraws, but that is all. The calls to repaint have no effect.

    menu = m.open_menu('outline')
    menu.parent().repaint()
    menu.raise_()
    menu.repaint() # Doen't work.
    m.wait(1)
    m.dismiss_menu_bar()
</t>
<t tx="ekr.20120923063534.3130">p2 = g.findNodeAnywhere(c,'Example Tree')
p2.contract()
m.select_position(p2)

m.body(
    'This is a brief tutorial slideshow showing the basics of Leo.\n'''
    'The Right Arrow key goes to the next slide.\n'
    'The Ctrl-G key quits this tutorial.'
)</t>
<t tx="ekr.20120923105702.3128">c.screencast_controller.start(
    g.findNodeAnywhere(c,'@screencast Tutorial'))</t>
<t tx="ekr.20120923110028.3131"></t>
<t tx="ekr.20120923110028.3132">p2 = g.findNodeAnywhere(c,'Example Tree')
p3 = g.findNodeInTree(c,p2,'newHeadline')
if p3:
    p3.doDelete()
    m.redraw()
m.body(
    'Deleting the inserted node concludes the slideshow. '
    'We have merely scratched the surface of what Leo can do.\n'
)</t>
<t tx="ekr.20120923110028.3133"></t>
<t tx="ekr.20120923110028.3136"></t>
<t tx="ekr.20120923110028.3137"></t>
<t tx="ekr.20120923110028.3138"></t>
<t tx="ekr.20120923115619.3155"></t>
<t tx="ekr.20120925073640.3143">@language rest

'''

This is known to cause scrolling problems.

Scroll to end, either with mouse wheel or ctrl-end.
Then click:  the unwanted scroll happens.

Overview
========

This plugin is a tool for people wanting to demonstrate Leo or some Leonine
project to others. Using this plugin, a human demonstrator can prepare an
automated talk ahead of time. The talk is a series of slides created by Leo
itself. Each slide is simply Leo as it appears at a particular time. When
giving the talk, the presenter moves from one slide to the next by hitting
the RtArrow (Right Arrow) key. The presenter may also back up from the
present slide to the previous slide using the LtArrow (Left Arrow) key.

To create the presentation, the presenter creates an **@screencast** node.
This node, and all its descendants, is called the **controlling tree**.
Each node of this tree may contain a script in its body text; each script
creates a slide. Nodes without scripts can be used as organizer nodes as
usual. **@ignore-node** nodes and **@ignore-tree** trees are ignored.
Normally, the controlling tree will be hidden from view during the
presentation--the presentation will be about *other* parts of the tree.

The screencast-start command starts a screencast. This command shows the
first slide of the nearest \@screencast node. Thereafter, the plugin
executes the next script in controlling tree when the demonstrator types
the RtArrow key. These scripts are normal Leo scripts, except that they
also have access to an "m" variable that denotes a **ScreenCastController**
(SCC), an object created by this plugin. The term **screencast script**
denotes a script that has access to the "m" variable.

The SCC provides convenience methods that screencast scripts can use to
draw attention to various parts of Leo's screen. A typical script will
consist of just one or two of the following calls:

- **m.image(file_name)** overlays a scaled image on Leo's window. For
  example, a screencast could discuss Leo's icon box by shown greatly
  magnified images of various kinds of icon box.
  
- **m.body(text)** overlays a caption on Leo's body pane. By default,
  captions have a bright yellow background so that they clearly stand out
  from the normal appearance of Leo's screen. Similarly **m.log(text)** and
  **m.tree(text)** overlay captions on Leo's log and tree panes.
  
- **m.body_keys(text)** and **m.head_keys(text)** animate typing of text in
  body text and headlines respectively.

- **m.single_key(key_setting)** allows any key to be handled exactly as if
  the user had typed the key.
  
- **m.open_menu(menu_name)** opens a menu as if the demonstrator had opened it
  with a mouse click. **m.dismiss_menubar()** closes all open menus.

To summarize: the presenter moves from slide to slide using the RtArrow
key. The RtArrow key causes the SCC executes the next script in the
controlling tree. The script alters the screen, say by selecting inserting,
deleting, expanding and contracting nodes, or by inserting, deleting or
changing headline or body text. The script will typically also show images
or captions to highlight what the slide is supposed to be showing. In
short:

- A screencast is a sequence of slides.  A slide is the appearance
  of Leo after a screencast script is executed.

- The human presenter moves to the next slide using the RtArrow key.
  The LtArrow key moves back to the previous slide.
  
- Scripts in an \@screencast tree create slides. The 'm' variable allows
  such scripts to animate keystrokes or overlay images or captions on the
  screen.
  
Before reading further, please look at the example \@screencast trees in
test.leo. Then run those screencasts to see the what the scripts do.
  

Reference
=========

The screencast-start command
----------------------------

The screencast-start command starts a screencast. This command first
searches backwards for the nearest \@screencast node. If no such node is
found, the command searches forwards for the next \@screencast node. This
command then executes the script in the body text, and pauses. Thereafter,
the Right Arrow key executes the script in the next slide node (in outline
order). The Left Arrow key executes the script in the previous slide node.
The Escape or Ctrl-G keys terminate any screencast.

Screencast scripts
------------------

Screencast scripts are Leo scripts that have access to the 'm' variable,
which is bound to c.screencastController, and instance of
ScreenCastController. Such scripts typically use 'm' to access convenience
methods, but advanced scripts can use 'm' in other ways.

The ScreenCastController
------------------------

The ScreenCastController (SCC) controls key handling during screencasts and
executes screencast scripts as the screencast moves from node to node.

The SCC only traps the RtArrow and LtArrow keys during a screencast. The
SCC passes all other keys to Leo's key-handling code. This allows key
handling in key-states during the execution of a screencast. For example::
    
    m.single_key('Alt-X')
    m.plain_keys('ins\\tno\\t\\n')
    
actually executes the insert-node command!

SCC methods
-----------

The following paragraphs discuss the SCC methods that screencasts scripts
may use.

**m.body(s)**, **m.log(s)** and **m.tree(s)** create a caption with text s
in the indicated pane. A **caption** is a text area that overlays part of
Leo's screen. By default, captions have a distinctive yellow background.
The appearance of captions can be changed using Qt stylesheets. See below.

**m.body_keys(s,n1=None,n2=None)** Draws the string s in the body pane of
the presently selected node. n1 and n2 give the range of delays to be
inserted between typing. If n1 and n2 are both None, values are given that
approximate a typical typing rate.

**m.command(command_name)** Executes the named command.

**m.dismiss_menubar()** Dismisses the menu opened with m.open_menu.

**m.focus(pane)** Immediately forces focus to the indicated pane. Valid
values are 'bodly', 'log' or 'tree'.

**m.image(pane,fn,center=None,height=None,width=None)** Overlays an image
in a pane. The valid values for `pane` are 'body', 'log' or 'tree'. `fn` is
the path to the image file, resolved to the leo/Icons directory if fn is a
relative path. If `height` is given, the image is scaled so it is height
pixels high. If `width` is given, the image is scaled so it width pixels
wide. If `center` is True, the image is centered horizontally in the given
pane.

**m.head_keys(s,n1=None,n2=None)** Same as m.body_keys, except that the
keys are "typed" into the headline of the presently selected node.

**m.open_menu(menu_name)** Opens the menu whose name is given, ignoring
case and any non-alpha characters in menu_name. This method shows all
parent menus, so m.open_menu('cursorback') suffices to show the
"Cmds\:Cursor/Selection\:Cursor Back..." menu.

**m.plain_keys(s,n1=None,n2=None,pane='body')** Same as m.body_keys, except
that the keys are typed into the designated pane. The valid values for the
'pane' argument are 'body','log' or 'tree'.

**m.quit** ends the screencast. By definition, the last slide of screencast
is the screencast node that calls m.quit.

**m.redraw(p)** Forces an immediate redraw of the outline pane. If p is
given, that position becomes c.p, the presently selected node.

**m.selectPosition(p)** Same as m.redraw(p)

**m.single_key(setting)** generates a key event. Examples::
    
   m.single_key('Alt-X') # Activates the minibuffer
   m.single_key('Ctrl-F') # Activates Leo's Find command
   
The 'setting' arg can be anything that would be a valid key setting. The
following are equivalent: "ctrl-f", "Ctrl-f", "Ctrl+F", etc., but "ctrl-F"
is different from "ctrl-shift-f".

**m.start(p)** Starts a screencast at node p, regardless of whether p is an
\@screencast node. This is useful during development while testing the
script in node p.

The program counter, m.p
------------------------

Most presenters will want to keep the nodes of the presentation tree
hidden. Instead, presentation will make *other* nodes visible by calling
m.selectPosition(p) or m.redraw(p).

Thus, there must be a sharp distinction between the presently *selected*
node, c.p, and the present screencast node, m.p. You can think of m.p as
the program counter for the screencast.

By default, after executing a screencast script, the SCC advances m.p to
the next non-empty, non-ignored node in the \@screencast tree. However, if
the just-executed screencast script has set m.p to a new, non-empty value,
that value will be the new value of m.p.
  
Stylesheets
-----------

Presenters may alter the appearance of captions by using changing the
following stylesheet::

    QPlainTextEdit#screencastcaption {
        background-color: yellow;
        font-family: DejaVu Sans Mono;
        font-size: 18pt;
        font-weight: normal; /* normal,bold,100,..,900 */
        font-style: normal; /* normal,italic,oblique */
    }

You will find this stylesheet in the node @data
``qt-gui-plugin-style-sheet`` in leoSettings.leo or myLeoSettings.leo.


'''
</t>
<t tx="ekr.20120925084214.3144">w = c.frame.body.bodyCtrl.widget
print(w)


vsb = w.verticalScrollBar()
vpos = vsb.sliderPosition()
print(vpos)</t>
<t tx="ekr.20120925105035.3146">def sp(s=''):
    old = g._old_sp
    pos1 = c.frame.body.wrapper.getYScrollPosition()
    vsb = c.frame.body.wrapper.widget.verticalScrollBar()
    vmax = vsb.maximum()
    pos2 = vsb.sliderPosition()
    if s or old is None or old != pos1 or old != pos2:
        g._old_sp = pos2
        print(pos1,pos2,vmax)
    if g._force_vscroll is not None:
        vsb.setSliderPosition(g._force_vscroll)
        g._force_vscroll = None

g._force_vscroll = None
g._sp = sp
g._old_sp = None
g.registerHandler('idle', lambda a,b:g._sp())
g.cls()</t>
<t tx="ekr.20120928085003.3150">g.note('note')
g.warning('warning')
g.error('error')
g.es('pink',color='pink')
g.es_print('purple',color='purple')
g.es('default')</t>
<t tx="ekr.20120928143821.3161"></t>
<t tx="ekr.20120928143821.3162">Color for error messages written to the log window.</t>
<t tx="ekr.20120928143821.3163">Foreground color of log text.

</t>
<t tx="ekr.20120928143821.3164">Background color of log text.</t>
<t tx="ekr.20120928143821.3168"></t>
<t tx="ekr.20121005071615.3175">path = g.os_path_join(g.app.loadDir,'..','modes')

for language in ('rest','plain'):
    fileName = g.os_path_join(path,'%s.py' % (language))
    if g.os_path_exists(fileName):
        mode = g.importFromPath (language,path)
    else:
        mode = None
    print(language,mode)</t>
<t tx="ekr.20121011100948.4582">'''Recursively import all python files in theDir and clean the result.'''

import os
import time

safe_at_file = True # True: create @@file nodes instead of @file nodes.

# theTypes = ('.py',)
# theDir = r'C:\Python26\Lib\site-packages\rope'
theTypes = ('.ts',)
theDir = r'C:\prog\typescript-fe3bc0bfce1f\src\compiler'

@others

if g.os_path_exists(theDir):
    if 1: # Production.
        # Import all files in theDir after c.p.
        ImportController().run(c,p,theDir,theTypes)
    else: # Testing.
        p = g.findNodeAnywhere(c,'Imported files')
        ImportController().post_process(c,p,theDir,theTypes)
    c.redraw()
else:
    print('Does not exist: %s' % (theDir))
</t>
<t tx="ekr.20121011100948.4583">def import_dir(self,c,root,theDir,theTypes):

    g.es("dir: " + theDir,color="blue")
    dirs,files,files2 = [],os.listdir(theDir),[]
    for f in files:
        path = g.os_path_join(theDir,f)
        if g.os_path_isfile(path):
            name, ext = g.os_path_splitext(f)
            if not theTypes or ext in theTypes:
                files2.append(path)
        else: # elif recursive:
            dirs.append(path)
    if files2 or dirs:
        child = root.insertAsLastChild()
        child.h = theDir
        c.selectPosition(child,enableRedrawFlag=False)
    if files2:
        # files2 = [files2[0]] ### Just import one file.
        c.importCommands.importFilesCommand(files2,'@file',redrawFlag=False) # '@auto' causes problems.
    if dirs:
        for theDir in sorted(dirs):
            prefix = theDir
            self.import_dir(c,child,theDir,theTypes)
</t>
<t tx="ekr.20121011100948.4584">def clean_all (self,c,p):
    
    for p in p.self_and_subtree():
        if p.h.startswith('@file') or p.h.startswith('@@file'):
            self.clean(c,p)
</t>
<t tx="ekr.20121011100948.4585">def clean(self,c,p):
    
    '''
    - Move a shebang line from the first child to the root.
    - Move a leading docstring in the first child to the root.
    - Use a section reference for declarations.
    - Remove leading and trailing blank lines from all nodes.
    - Merge a node containing nothing but comments with the next node.
    - Merge a node containing no class or def lines with the previous node.
    '''

    root = p.copy()
    for tag in ('@@file','@file'):
        if p.h.startswith(tag):
            p.h = p.h[len(tag):].strip()
            break
            
    self.move_shebang_line(c,root)
    self.move_doc_string(c,root)
    self.rename_decls(c,root)

    for p in root.self_and_subtree():
        self.clean_blank_lines(c,p)
    for p in root.subtree():
        self.merge_comment_nodes(c,p)
    for p in root.subtree():
        self.merge_extra_nodes(c,p)
    for p in root.subtree():
        self.move_decorator_lines(c,p)
</t>
<t tx="ekr.20121011100948.4586">def clean_blank_lines(self,c,p):
    
    '''Remove leading and trailing blank lines from all nodes.
    '''
    
    s = p.b
    if not s.strip():
        return
    
    result = g.splitLines(s)
    for i in 0,-1:
        while result:
            if result[i].strip():
                break
            else:
                del result[i]
        
    s = ''.join(result)
    if not s.endswith('\n'): s = s + '\n'
    if s != p.b:
        p.b = s
        # p.setDirty()
        # p.setMarked()
        # c.setChanged(True)
        # self.changed += 1
</t>
<t tx="ekr.20121011100948.4587">def merge_comment_nodes(self,c,p):
    
    '''Merge a node containing nothing but comments with the next node.'''

    h = p.h
    
    if p.hasChildren() or not h.strip().startswith('#'):
        return
        
    p2 = p.next()
    if p2:
        b = p.b.lstrip()
        b = b + ('\n' if b.endswith('\n') else '\n\n')
        p2.b = b + p2.b
        p.doDelete(p2)
        # p2.setDirty()
        # p2.setMarked()
        # c.setChanged(True)
        # self.changed += 1
        # g.trace(h,' --&gt; ',p2.h)
</t>
<t tx="ekr.20121011100948.4588">def merge_extra_nodes(self,c,p):
    
    '''Merge a node containing no class or def lines with the previous node'''
    
    s = p.b
    if p.hasChildren() or p.h.strip().startswith('&lt;&lt;') or not s.strip():
        return
        
    for s2 in g.splitLines(s):
        if s2.strip().startswith('class') or s2.strip().startswith('def'):
            return

    p2 = p.back()
    if p2:
        nl = '\n' if s.endswith('\n') else '\n\n'
        p2.b = p2.b + nl + s
        h = p.h
        p.doDelete(p2)
        # p2.setDirty()
        # p2.setMarked()
        # c.setChanged(True)
        # self.changed += 1
        # g.trace(h,' --&gt; ',p2.h)
</t>
<t tx="ekr.20121011100948.4589">def move_decorator_lines (self,c,p):
    
    '''Move trailing decorator lines to the next node.'''
    
    trace = False
    p2 = p.next()
    if not p2: return False
    
    lines = g.splitLines(p.b)
    n = len(lines) -1
    while n &gt;= 0:
        s = lines[n]
        if s.startswith('@'):
            i = g.skip_id(s,1,chars='-')
            word = s[1:i]
            if word in g.globalDirectiveList:
                break
            else:
                n -= 1
        else:
            break
        
    head = ''.join(lines[:n+1])
    tail = ''.join(lines[n+1:])
    if not tail: return False

    assert head.endswith('\n')
    assert p.b == head+tail
    
    if trace:
        if tail not in seen:
            seen.append(tail)
            g.trace(tail.strip())
    
    if 1:
        nl = '' if tail.endswith('\n') else '\n'
        p.b = head
        p2.b = tail+nl+p2.b
        
    return True
    # p2.setDirty()
    # p2.setMarked()
    # c.setChanged(True)
    # self.changed += 1
</t>
<t tx="ekr.20121011100948.4590">def move_doc_string(self,c,root):

    '''Move a leading docstring in the first child to the root node.'''
    
    # To do: copy comments before docstring
    
    p = root.firstChild()
    s = p and p.b or ''
    if not s: return
    
    # if root.h.endswith('pgen.py'):
        # g.pdb()

    result = []
    for s2 in g.splitLines(s):
        delim = None
        s3 = s2.strip()
        if not s3:
            result.append(s2)
        elif s3.startswith('#'):
            result.append(s2)
        elif s3.startswith('"""'):
            delim = '"""'
            break
        elif s3.startswith("'''"):
            delim = "'''"
            break
        else:
            break
       
    if not delim:
        comments = ''.join(result)
        if comments:
            nl = '\n\n' if root.b.strip() else ''
            if root.b.startswith('@first #!'):
                lines = g.splitLines(root.b)
                root.b = lines[0] + '\n' + comments + nl + ''.join(lines[1:])
            else:
                root.b = comments + nl + root.b
            p.b = s[len(comments):]
        return

    i = s.find(delim)
    assert i &gt; -1
    i = s.find(delim,i+3)
    if i == -1:
        return
        
    doc = s[:i+3]
    p.b = s[i+3:].lstrip()
    
    # Move docstring to front of root.b, but after any shebang line.
    nl = '\n\n' if root.b.strip() else ''
    if root.b.startswith('@first #!'):
        lines = g.splitLines(root.b)
        root.b = lines[0] + '\n' + doc + nl + ''.join(lines[1:])
    else:
        root.b = doc + nl + root.b
        
    # p.setDirty()
    # p.setMarked()
    # root.setDirty()
    # root.setMarked()
    # c.setChanged(True)

    # self.changed += 1
    # g.trace('%s --&gt; %s' % (p.h,root.h))
</t>
<t tx="ekr.20121011100948.4591">def move_shebang_line (self,c,root):
    
    '''Move a shebang line from the first child to the root.'''
    
    p = root.firstChild()
    s = p and p.b or ''
    if not s.startswith('#!'):
        return
        
    lines = g.splitLines(s)
    nl = '\n\n' if root.b.strip() else ''
    root.b = '@first ' + lines[0] + nl + root.b
    p.b = ''.join(lines[1:])
    # p.setDirty()
    # p.setMarked()
    # root.setDirty()
    # root.setMarked()
    # c.setChanged(True)

    # self.changed += 1
    # g.trace('%s --&gt; %s' % (p.h,root.h))
</t>
<t tx="ekr.20121011100948.4592">def rename_decls (self,c,root):
    
    '''Use a section reference for declarations.'''
    
    p = root.firstChild()
    h = p and p.h or ''
    
    tag = 'declarations'
    if not h.endswith(tag):
        return
        
    if not p.b.strip():
        return # The blank node will be deleted.

    name = h[:-len(tag)].strip()
    decls = g.angleBrackets(tag)
    p.h = '%s (%s)' % (decls,name)
    
    i = root.b.find('@others')
    if i == -1:
        g.trace('can not happen')
        return
    else:
        nl = '' if i == 0 else '\n'
        root.b = root.b[:i] + nl + decls + '\n' + root.b[i:]

    # p.setDirty()
    # root.setDirty()
    # root.setMarked()
    # c.setChanged(True)

    # self.changed += 1
    #g.trace('%s --&gt; %s' % (p.h,root.h))
</t>
<t tx="ekr.20121011100948.4593">def post_process (self,c,p,prefix,theTypes):
    
    '''Traverse p's tree, replacing all nodes that start with prefix
       by the smallest equivalent @path or @file node.
    '''

    assert p
    root = p.copy()
    self.fix_back_slashes(root.copy())
    prefix = prefix.replace('\\','/')
    
    # self.dump_headlines(root.copy())
    self.remove_empty_nodes(c,root.copy())
    self.minimize_headlines(c,root.copy().firstChild(),prefix,theTypes)
    self.clear_dirty_bits(c,root.copy())
    
    ## self.munge_at_file(c,root.copy().firstChild())
</t>
<t tx="ekr.20121011100948.4594">def clear_dirty_bits (self,c,p):
    
    c.setChanged(False)
    for p in p.self_and_subtree():
        p.clearDirty()
</t>
<t tx="ekr.20121011100948.4595">def dump_headlines (self,p):
    
    # show all headlines.
    for p in p.self_and_subtree():
        print(p.h)
</t>
<t tx="ekr.20121011100948.4596">def fix_back_slashes (self,p):
    
    '''Convert backslash to slash in all headlines.'''

    for p in p.self_and_subtree():
        s = p.h.replace('\\','/')
        if s != p.h:
            p.h = s
</t>
<t tx="ekr.20121011100948.4597">def minimize_headlines (self,c,p,prefix,theTypes):
    
    '''Create @path nodes to minimize the paths required in descendant nodes.'''

    trace = False
    
    # This could only happen during testing.
    if p.h.startswith('@'):
        g.trace('** skipping: %s' % (p.h))
        return
        
    h2 = p.h[len(prefix):].strip()
    
    ends_with_ext = any([h2.endswith(z) for z in theTypes])
    
    if p.h == prefix:
        if trace: g.trace('@path %s' % (p.h))
        p.h = '@path %s' % (p.h)
        for p in p.children():
            self.minimize_headlines(c,p,prefix,theTypes)
    elif h2.find('/') &lt;= 0 and ends_with_ext:
            if h2.startswith('/'): h2 = h2[1:]
            if safe_at_file:
                if trace: g.trace('@@file %s' % (h2))
                p.h = '@@file %s' % (h2)
            else:
                if trace: g.trace('@file %s' % (h2))
                p.h = '@file %s' % (h2)
            # We never scan the children of @file nodes.
    else:
        if h2.startswith('/'): h2 = h2[1:]
        if trace:
            print('')
            g.trace('@path [%s/]%s' % (prefix,h2))
        p.h = '@path %s' % (h2)
        prefix2 = prefix if prefix.endswith('/') else prefix + '/'
        prefix2 = prefix2 + h2
        for p in p.children():
            self.minimize_headlines(c,p,prefix2,theTypes)
</t>
<t tx="ekr.20121011100948.4598">def remove_empty_nodes (self,c,p):
    
    root = p.copy()
    
    # Restart the scan once a node is deleted.
    changed = True
    while changed:
        changed = False
        for p in root.self_and_subtree():
            if not p.b and not p.hasChildren():
                # g.trace('** deleting',p.h)
                p.doDelete()
                c.selectPosition(root)
                changed = True
                break
                
</t>
<t tx="ekr.20121011100948.4599"># def munge_at_file (self,c,p):
    
    # for p in p.self_and_subtree():
        # if p.h.startswith('@@file'):
            # p.h = p.h[1:]
            # s = p.b
            # i = s.find('@tabwidth -4\n')
            # if i &gt; 0:
                # i = g.skip_line(s,i)
                # p.b = s[:i] + '@others\n' + s[i:]
            # else:
                # g.trace('@tabwidth not found')
</t>
<t tx="ekr.20121011100948.4600">def run (self,c,p,theDir,theTypes):
    
    '''Import all the .py files in theDir.'''

    try:
        t1 = time.time()
        p1 = p.copy()
        g.app.disable_redraw = True
        bunch = c.undoer.beforeChangeTree(p1)
        assert p == c.p
        root = p.insertAfter()
        # root.h = '@path %s' % (theDir)
        root.h = 'imported files'
        prefix = theDir
        self.import_dir(c,root.copy(),theDir,theTypes)
        n = 0
        for p in root.self_and_subtree():
            n += 1
        self.clean_all(c,root.copy())
        self.post_process(c,root.copy(),theDir,theTypes)
        c.undoer.afterChangeTree(p1,'recursive-import',bunch)
    finally:
        g.app.disable_redraw = False
        root.contract()
        c.redraw(root)
    
    t2 = time.time()
    g.trace('imported %s nodes in %2.2f sec' % (n,t2-t1))
</t>
<t tx="ekr.20121011100948.4601">class ImportController():
    
    # There is no ctor.

    @others
</t>
<t tx="ekr.20121011195530.3405">import PyV8

s = '''\
var Greeter = (function () {
    function Greeter(message) {
        this.greeting = message;
    }
    Greeter.prototype.greet = function () {
        return "Hello, " + this.greeting;
    };
    return Greeter;
})();
var greeter = new Greeter("world");
if (false) {
    var button = document.createElement('button');
    button.innerText = "Say Hello";
    button.onclick = function () {
        alert(greeter.greet());
    };
    document.body.appendChild(button);
}
'''

if 1:
    cx = PyV8.JSContext()   # create a context with an implicit global object
    cx.enter()              # enter the context (also support with statement)
    # print(cx.eval("1+2"))
    print(cx.eval(s))
    
if 0:

    class Global(PyV8.JSClass):
        def hello(self):
            print "Hello World"    
    
    cx = PyV8.JSContext(Global())
    cx.enter()                    
    cx.eval("hello()")
</t>
<t tx="ekr.20131106145203.3636">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;style&gt;
ul.leo-tree-example  {
    background-color: #ffffec;
    zoom: 150%;
}
ul.leo-tree-example li {
    background-repeat: no-repeat;
    background-position: 0px 5px;
    padding-left: 27px;
}
li {
    background-image:
url('https://raw.github.com/vivainio/leo/master/leo/Icons/box00.GIF');
    background-repeat: no-repeat;
    background-position: 0px 5px;
    padding-left: 27px;
}
li.selected {
    background-color: lightgrey;
}
li.leaf {
    list-style-type: none;
}
li.plus {
  list-style-image: url('http://leoeditor.com/plusnode.gif')
}
li.minus {
  list-style-image: url('http://leoeditor.com/minusnode.gif')
}
li.leaf {
  background-image: url('http://leoeditor.com/box00.GIF')
}
li.body {
  background-image: url('http://leoeditor.com/box01.GIF')
}
li.mark {
  background-image: url('http://leoeditor.com/box02.GIF')
}
li.mark-body {
  background-image: url('http://leoeditor.com/box03.GIF')
}
li.clone {
  background-image: url('http://leoeditor.com/box04.GIF')
}
li.clone-body {
  background-image: url('http://leoeditor.com/box05.GIF')
}
li.clone-mark {
  background-image: url('http://leoeditor.com/box06.GIF')
}
li.clone-mark-body {
  background-image: url('http://leoeditor.com/box07.GIF')
}
li.dirty {
  background-image: url('http://leoeditor.com/box08.GIF')
}
li.dirty-body {
  background-image: url('http://leoeditor.com/box09.GIF')
}
li.dirty-mark {
  background-image: url('http://leoeditor.com/box10.GIF')
}
li.dirty-mark-body {
  background-image: url('http://leoeditor.com/box11.GIF')
}
li.dirty-clone {
  background-image: url('http://leoeditor.com/box12.GIF')
}
li.dirty-clone-body {
  background-image: url('http://leoeditor.com/box13.GIF')
}
li.dirty-clone-mark {
  background-image: url('http://leoeditor.com/box14.GIF')
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;ul class="leo-tree-example"&gt;
&lt;li class='plus'&gt;
display xml as Leo outlines using css
&lt;/li&gt;
&lt;ul&gt;
  &lt;li class='minus body'&gt;
  @button display css
  &lt;/li&gt;
  &lt;li class='minus clone-mark'&gt;
  test
  &lt;/li&gt;
  &lt;li class='minus clone-mark'&gt;
  test
  &lt;/li&gt;
  &lt;li class='leaf dirty-body'&gt;
  @html display
  &lt;/li&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</t>
<t tx="ekr.20131106150237.3641"># Displays both the css and the html to the log pane.
# The viewrendered plugin doesn't display result properly:
# https://bugs.launchpad.net/leo-editor/+bug/782009

@language python
@others
&lt;&lt; define css &gt;&gt;
tag = '@html display'
p2 = g.findNodeAnywhere(c,tag)
if p2:
    html = [
        '&lt;!DOCTYPE html&gt;',
        '&lt;html&gt;',
        '&lt;head&gt;','&lt;style&gt;',
            base_css,plus_minus_css,boxes_css,
        '&lt;/style&gt;','&lt;/head&gt;',
        '&lt;body&gt;','&lt;ul class="leo-tree-example"&gt;',
    ]
    html.extend(headlineToHtml(p))
    html.extend(['&lt;/ul&gt;','&lt;/body&gt;','&lt;/html&gt;',])
    p2.b = '\n'.join(html)
    c.selectPosition(p2)
    c.redraw()
else:
    g.es('not found: %s' % tag)
</t>
<t tx="ekr.20131106150237.3642">base_css = \
r'''ul.leo-tree-example  {
    background-color: #ffffec;
    zoom: 150%;
}
ul.leo-tree-example li {
    background-repeat: no-repeat;
    background-position: 0px 5px;
    padding-left: 27px;
}
li {
    background-image:
url('https://raw.github.com/vivainio/leo/master/leo/Icons/box00.GIF');
    background-repeat: no-repeat;
    background-position: 0px 5px;
    padding-left: 27px;
}
li.selected {
    background-color: lightgrey;
}
li.leaf {
    list-style-type: none;
}'''

table = (
    ('plus','plusnode.gif'),
    ('minus','minusnode.gif'),
)
plus_minus_css = '\n'.join([
    'li.%s {\n  list-style-image: url(%s)\n}' % (kind,icon(image))
        for kind,image in table])

boxes_css = '\n'.join([css(n) for n in range(15)])
</t>
<t tx="ekr.20131106150237.3643">def escapeHtml(s):
    return s.replace('&amp;', '&amp;amp;').replace('&lt;', '&amp;lt;').replace('&gt;', '&amp;gt;')
</t>
<t tx="ekr.20131106150237.3644">def headlineToHtml(p,level=0):
    '''
        Returns html representation (unordered list)
        of the visible portions of the subtree rooted
        at position p. CSS classes corresponding to the
        expansion state and icon box are included in
        each list item. Combined with the proper CSS, the
        result can be made to look similar to leo's tree
        pane.
    '''
    pad = '  '*level
    if p.isExpanded(): box = 'plus'
    elif p.hasChildren(): box = 'minus'
    else: box = 'leaf'
    bits = []
    table = (
        (p.isDirty(),'dirty'),
        (p.isCloned(),'clone'),
        (p.isMarked(),'mark'),
        (bool(p.b),'body'),
    )
    for bit,kind in table:
        if bit: bits.append(kind)
    bits = '-'.join(bits)
    theClass = '%s %s' % (box,bits) if bits else box
    html = ["%s&lt;li class='%s'&gt;" % (pad,theClass)]
    html.append('%s%s' % (pad,escapeHtml(p.h)))
    html.append("%s&lt;/li&gt;" % pad)
    if p.isExpanded() and p.hasChildren():
        html.append("%s&lt;ul&gt;" % pad)
        for child in p.children():
            html.extend(headlineToHtml(child,level=level+1))
        html.append("%s&lt;/ul&gt;" % pad)
    return html</t>
<t tx="ekr.20131106150237.3648"></t>
<t tx="ekr.20131106150237.3651">This is a child. 
</t>
<t tx="ekr.20131106150237.3652">grandchild</t>
<t tx="ekr.20131106192510.3643">def box(n):
    return icon('box%02d.GIF' % n)

def css(n):
    return 'li.%s {\n  background-image: url(%s)\n}' % (selector(n),box(n))
    
def icon(s):
    url = 'http://leoeditor.com/%s' % s # not https
    return "'%s'" % url

def selector(n):
    table = ((8,'dirty'),(4,'clone'),(2,'mark'),(1,'body'))
    return '-'.join([s for (n2,s) in table if n &amp; n2]) or 'leaf'
</t>
<t tx="ekr.20131128115544.3333"></t>
<t tx="ekr.20140808094008.3549">import meta
print(meta)</t>
<t tx="ekr.20150618075639.1"></t>
<t tx="ekr.20150619071508.1"></t>
<t tx="ekr.20160401061847.1"></t>
<t tx="ekr.20160401061847.10">@nocolor-node
&lt;?xml version="1.0" standalone="no"?&gt;
&lt;!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd"&gt;
&lt;svg width="20cm" height="15cm" viewBox="0 0 800 600"
     xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlik/"
     baseProfile="tiny" version="1.2"&gt;
   &lt;title&gt;Spheres&lt;/title&gt;
   &lt;desc&gt;Semi-transparent bubbles on a colored background.&lt;/desc&gt;
     &lt;defs&gt;
       &lt;!-- Create radial gradients for each bubble. --&gt;
       &lt;radialGradient id="blueBubble" gradientUnits="userSpaceOnUse"
                       cx="0" cy="0" r="100" fx="-50" fy="-50"&gt;
         &lt;stop offset="0%" stop-color="white" stop-opacity="1" /&gt;
         &lt;stop offset="25%" stop-color="#cdcdff" stop-opacity=".65" /&gt;
         &lt;stop offset="100%" stop-color="#cdaacd" stop-opacity=".75" /&gt;
       &lt;/radialGradient&gt;
       &lt;radialGradient id="redBubble" gradientUnits="userSpaceOnUse"
                       cx="0" cy="0" r="100" fx="-50" fy="-50"&gt;
         &lt;stop offset="0%" stop-color="white" stop-opacity="1" /&gt;
         &lt;stop offset="25%" stop-color="#ffcdcd" stop-opacity=".65" /&gt;
         &lt;stop offset="100%" stop-color="#bbbb99" stop-opacity=".75" /&gt;
       &lt;/radialGradient&gt;
       &lt;radialGradient id="greenBubble" gradientUnits="userSpaceOnUse"
                       cx="0" cy="0" r="100" fx="-50" fy="-50"&gt;
         &lt;stop offset="0%" stop-color="white" stop-opacity="1" /&gt;
         &lt;stop offset="25%" stop-color="#cdffcd" stop-opacity=".65" /&gt;
         &lt;stop offset="100%" stop-color="#99aaaa" stop-opacity=".75" /&gt;
       &lt;/radialGradient&gt;
       &lt;radialGradient id="yellowBubble" gradientUnits="userSpaceOnUse"
                       cx="0" cy="0" r="100" fx="-50" fy="-50"&gt;
         &lt;stop offset="0%" stop-color="white" stop-opacity="1" /&gt;
         &lt;stop offset="25%" stop-color="#ffffcd" stop-opacity=".65" /&gt;
         &lt;stop offset="100%" stop-color="#bbbbaa" stop-opacity=".75" /&gt;
       &lt;/radialGradient&gt;
       &lt;radialGradient id="background" gradientUnits="userSpaceOnUse"
                       cx="0" cy="0" r="400" fx="250" fy="250"&gt;
         &lt;stop offset="0%" stop-color="#ffffee" /&gt;
         &lt;stop offset="100%" stop-color="#ccccaa" /&gt;
       &lt;/radialGradient&gt;
       &lt;linearGradient id="surface" gradientUnits="userSpaceOnUse"
                       x1="-100" y1="200" x2="400" y2="200"&gt;
         &lt;stop offset="0%" stop-color="#ffffcc" /&gt;
         &lt;stop offset="100%" stop-color="#bbbb88" /&gt;
       &lt;/linearGradient&gt;

       &lt;!-- Create radial gradients for each circle to make them look like
            spheres. --&gt;
       &lt;radialGradient id="blueSphere" gradientUnits="userSpaceOnUse"
                       cx="0" cy="0" r="100" fx="-50" fy="-50"&gt;
         &lt;stop offset="0%" stop-color="white" /&gt;
         &lt;stop offset="75%" stop-color="blue" /&gt;
         &lt;stop offset="100%" stop-color="#222244" /&gt;
       &lt;/radialGradient&gt;
       &lt;radialGradient id="redSphere" gradientUnits="userSpaceOnUse"
                       cx="0" cy="0" r="100" fx="-50" fy="-50"&gt;
         &lt;stop offset="0%" stop-color="white" /&gt;
         &lt;stop offset="75%" stop-color="red" /&gt;
         &lt;stop offset="100%" stop-color="#442222" /&gt;
       &lt;/radialGradient&gt;
       &lt;radialGradient id="greenSphere" gradientUnits="userSpaceOnUse"
                       cx="0" cy="0" r="100" fx="-50" fy="-50"&gt;
         &lt;stop offset="0%" stop-color="white" /&gt;
         &lt;stop offset="75%" stop-color="green" /&gt;
         &lt;stop offset="100%" stop-color="#113311" /&gt;
       &lt;/radialGradient&gt;
       &lt;radialGradient id="yellowSphere" gradientUnits="userSpaceOnUse"
                       cx="0" cy="0" r="100" fx="-50" fy="-50"&gt;
         &lt;stop offset="0%" stop-color="white" /&gt;
         &lt;stop offset="75%" stop-color="yellow" /&gt;
         &lt;stop offset="100%" stop-color="#444422" /&gt;
       &lt;/radialGradient&gt;
       &lt;radialGradient id="shadowGrad" gradientUnits="userSpaceOnUse"
                       cx="0" cy="0" r="100" fx="-50" fy="50"&gt;
         &lt;stop offset="0%" stop-color="black" stop-opacity="1.0" /&gt;
         &lt;stop offset="100%" stop-color="black" stop-opacity="0.0" /&gt;
       &lt;/radialGradient&gt;

       &lt;!-- Define a shadow for each sphere. --&gt;
       &lt;circle id="shadow" fill="url(#shadowGrad)" cx="0" cy="0" r="100" /&gt;
       &lt;g id="bubble"&gt;
         &lt;circle fill="black" cx="0" cy="0" r="50" /&gt;
         &lt;circle fill="#a6ce39" cx="0" cy="0" r="33" /&gt;
         &lt;path fill="black" d="M 37,50 L 50,37 L 12,-1 L 22,-11 L 10,-24 L -24,10
                               L -11,22 L -1,12 Z" /&gt;
         &lt;circle cx="0" cy="0" r="100" /&gt;
       &lt;/g&gt;
     &lt;/defs&gt;
   &lt;g&gt;
     &lt;rect fill="url(#background)" x="0" y="0" width="800" height="600" /&gt;
   &lt;/g&gt;

   &lt;g transform="translate(200,700)"&gt;
     &lt;use xlink:href="#bubble" fill="url(#blueBubble)" /&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="1s" dur="10s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;
   &lt;g transform="translate(315,700)"&gt;
     &lt;g transform="scale(0.5,0.5)"&gt;
       &lt;use xlink:href="#bubble" fill="url(#redBubble)" /&gt;
     &lt;/g&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="3s" dur="7s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;
   &lt;g transform="translate(80,700)"&gt;
     &lt;g transform="scale(0.65,0.65)"&gt;
       &lt;use xlink:href="#bubble" fill="url(#greenBubble)" /&gt;
     &lt;/g&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="5s" dur="9s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;
   &lt;g transform="translate(255,700)"&gt;
     &lt;g transform="scale(0.3,0.3)"&gt;
       &lt;use xlink:href="#bubble" fill="url(#yellowBubble)" /&gt;
     &lt;/g&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="2s" dur="6s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;
   &lt;g transform="translate(565,700)"&gt;
     &lt;g transform="scale(0.4,0.4)"&gt;
       &lt;use xlink:href="#bubble" fill="url(#blueBubble)" /&gt;
     &lt;/g&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="4s" dur="8s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;
   &lt;g transform="translate(715,700)"&gt;
     &lt;g transform="scale(0.6,0.6)"&gt;
       &lt;use xlink:href="#bubble" fill="url(#redBubble)" /&gt;
     &lt;/g&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="1s" dur="4s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;
   &lt;g transform="translate(645,700)"&gt;
     &lt;g transform="scale(0.375,0.375)"&gt;
       &lt;use xlink:href="#bubble" fill="url(#greenBubble)" /&gt;
     &lt;/g&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="0s" dur="11s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;
   &lt;g transform="translate(555,700)"&gt;
     &lt;g transform="scale(0.9,0.9)"&gt;
       &lt;use xlink:href="#bubble" fill="url(#yellowBubble)" /&gt;
     &lt;/g&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="3s" dur="7.5s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;

   &lt;g transform="translate(360,700)"&gt;
     &lt;g transform="scale(0.5,0.5)"&gt;
       &lt;use xlink:href="#bubble" fill="url(#blueBubble)" /&gt;
     &lt;/g&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="3s" dur="6s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;
   &lt;g transform="translate(215,700)"&gt;
     &lt;g transform="scale(0.45,0.45)"&gt;
       &lt;use xlink:href="#bubble" fill="url(#redBubble)" /&gt;
     &lt;/g&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="5.5s" dur="7s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;
   &lt;g transform="translate(420,700)"&gt;
     &lt;g transform="scale(0.75,0.75)"&gt;
       &lt;use xlink:href="#bubble" fill="url(#greenBubble)" /&gt;
     &lt;/g&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="1s" dur="9s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;
   &lt;g transform="translate(815,700)"&gt;
     &lt;g transform="scale(0.6,0.6)"&gt;
       &lt;use xlink:href="#bubble" fill="url(#yellowBubble)" /&gt;
     &lt;/g&gt;
     &lt;animateTransform attributeName="transform" type="translate" additive="sum"
         values="0,0; 0,-800" begin="2s" dur="9.5s" fill="freeze" repeatCount="indefinite" /&gt;
   &lt;/g&gt;

   &lt;g transform="translate(225,375)" &gt;
     &lt;g transform="scale(1.0,0.5)" &gt;
       &lt;path d="M 0 0 L 350 0 L 450 450 L -100 450 z"
             fill="url(#surface)" stroke="none" /&gt;
     &lt;/g&gt;
   &lt;/g&gt;
     &lt;g transform="translate(200,0)" &gt;
     &lt;g transform="translate(200,490) scale(2.0,1.0) rotate(45)" &gt;
       &lt;rect fill="#a6ce39" x="-69" y="-69" width="138" height="138" /&gt;
       &lt;circle fill="black" cx="0" cy="0" r="50" /&gt;
       &lt;circle fill="#a6ce39" cx="0" cy="0" r="33" /&gt;
       &lt;path fill="black" d="M 37,50 L 50,37 L 12,-1 L 22,-11 L 10,-24 L -24,10
                             L -11,22 L -1,12 Z" /&gt;
       &lt;animateTransform attributeName="transform"  type="rotate" additive="sum" values="0; 360"
                  begin="0s" dur="10s" fill="freeze" repeatCount="indefinite" /&gt;
     &lt;/g&gt;
     &lt;g transform="translate(200,375)"&gt;
       &lt;use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" /&gt;
       &lt;circle fill="url(#blueSphere)" cx="0" cy="0" r="100" /&gt;
     &lt;/g&gt;
     &lt;g transform="translate(315,440)"&gt;
       &lt;g transform="scale(0.5,0.5)"&gt;
         &lt;use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" /&gt;
         &lt;circle fill="url(#redSphere)" cx="0" cy="0" r="100" /&gt;
       &lt;/g&gt;
     &lt;/g&gt;
     &lt;g transform="translate(80,475)"&gt;
       &lt;g transform="scale(0.65,0.65)"&gt;
         &lt;use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" /&gt;
         &lt;circle fill="url(#greenSphere)" cx="0" cy="0" r="100" /&gt;
       &lt;/g&gt;
     &lt;/g&gt;
     &lt;g transform="translate(255,525)"&gt;
       &lt;g transform="scale(0.3,0.3)"&gt;
         &lt;use xlink:href="#shadow" transform="translate(25,55) scale(1.0,0.5)" /&gt;
         &lt;circle fill="url(#yellowSphere)" cx="0" cy="0" r="100" /&gt;
       &lt;/g&gt;
     &lt;/g&gt;
   &lt;/g&gt;
&lt;/svg&gt;</t>
<t tx="ekr.20160401061847.11">c:\leo.repo\leo-editor\leo\Icons\bubbles.svg
</t>
<t tx="ekr.20160401061847.12">[Leo's home page](http://leoeditor.com/)
</t>
<t tx="ekr.20160401061847.13">`Leo's home page &lt;http://leoeditor.com/&gt;`_

</t>
<t tx="ekr.20160401061847.15">[weather.com](http://www.weather.com/weather/today/Madison+WI+53705?from=hp_promolocator&amp;lswe=53705&amp;lwsa=Weather36HourHealthCommand)
</t>
<t tx="ekr.20160401061847.16">@language rest
@wrap

''' Creates a window for *live* rendering of rst, html, etc.  (Qt only).

Commands
========

viewrendered.py creates the following (``Alt-X``) commands:

``viewrendered``
    opens a new window where the current body text is rendered as HTML
    (if it starts with '&lt;'), or otherwise reStructuredText.
``viewrendered-big``
    as above, but zoomed in, useful for presentations
``viewrendered-html``
    displays the html source generated from reStructuredText, useful for
    debugging

``viewrendered`` sets the process current directory (os.chdir()) to the path
to the node being rendered, to allow relative paths to work in
``.. image::`` directives.

reStructuredText errors and warnings may be shown.  For example, both::

    Heading
    -------

    `This` is **really** a line of text.

and::

    &lt;h1&gt;Heading&lt;h1&gt;

    &lt;tt&gt;This&lt;/tt&gt; is &lt;b&gt;really&lt;/b&gt; a line of text.

will look something like:

**Heading**

`This` is **really** a line of text.

Settings
========

@string view-rendered-default-kind = rst
----------------------------------------

The default kind of rendering.  One of (big,rst,html)
    
@bool view-rendered-auto-create = False
---------------------------------------

When True, the plugin will create a rendering pane automatically.

'''
</t>
<t tx="ekr.20160401061847.17">@language md

# Title

This is **bold** and *italics*.

More info at [Leo's home page](&lt;http://leoeditor.com/).

### Section

- Bullet list
- Another item
- Third item.
</t>
<t tx="ekr.20160401061847.18">@language rest

#####
Title
#####

This is **bold** and *italics*.

More info at `Leo's home page &lt;http://leoeditor.com/&gt;`_.

Section
=======

- Bullet list
- Another item
- Third item.</t>
<t tx="ekr.20160401061847.2" _bklnk="7d71002858010000007971014b0058010000007871024b00580400000074797065710358080000006e6f646552656374710458050000006c696e6b7371055d7106752e">gs.clear()
gs.addText('\n%s\n%s' % (gv,gs))

if 0:
    for i in range(50):
        gs.addText('\n' * i +'More')
</t>
<t tx="ekr.20160401061847.3">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;style&gt;
ul.leo-tree-example  {
    background-color: #ffffec;
    zoom: 150%; # blurs icons a bit.
}
ul.leo-tree-example li {
    background-repeat: no-repeat;
    background-position: 0px 5px;
    padding-left: 27px;
}
li {
    background-image:
url('https://raw.github.com/vivainio/leo/master/leo/Icons/box00.GIF');
    background-repeat: no-repeat;
    background-position: 0px 5px;
    padding-left: 27px;
}
li.selected {
    background-color: lightgrey;
}
li.leaf {
    list-style-type: none;
}
li.plus {
  list-style-image: url('http://leoeditor.com/plusnode.gif')
}
li.minus {
  list-style-image: url('http://leoeditor.com/minusnode.gif')
}
li.leaf {
  background-image: url('http://leoeditor.com/box00.GIF')
}
li.body {
  background-image: url('http://leoeditor.com/box01.GIF')
}
li.mark {
  background-image: url('http://leoeditor.com/box02.GIF')
}
li.mark-body {
  background-image: url('http://leoeditor.com/box03.GIF')
}
li.clone {
  background-image: url('http://leoeditor.com/box04.GIF')
}
li.clone-body {
  background-image: url('http://leoeditor.com/box05.GIF')
}
li.clone-mark {
  background-image: url('http://leoeditor.com/box06.GIF')
}
li.clone-mark-body {
  background-image: url('http://leoeditor.com/box07.GIF')
}
li.dirty {
  background-image: url('http://leoeditor.com/box08.GIF')
}
li.dirty-body {
  background-image: url('http://leoeditor.com/box09.GIF')
}
li.dirty-mark {
  background-image: url('http://leoeditor.com/box10.GIF')
}
li.dirty-mark-body {
  background-image: url('http://leoeditor.com/box11.GIF')
}
li.dirty-clone {
  background-image: url('http://leoeditor.com/box12.GIF')
}
li.dirty-clone-body {
  background-image: url('http://leoeditor.com/box13.GIF')
}
li.dirty-clone-mark {
  background-image: url('http://leoeditor.com/box14.GIF')
}
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;ul class="leo-tree-example"&gt;
&lt;li class='plus clone-mark'&gt;
test
&lt;/li&gt;
&lt;ul&gt;
  &lt;li class='plus clone-body'&gt;
  child
  &lt;/li&gt;
  &lt;ul&gt;
    &lt;li class='leaf body'&gt;
    grandchild
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;li class='plus clone-body'&gt;
  child
  &lt;/li&gt;
  &lt;ul&gt;
    &lt;li class='leaf body'&gt;
    grandchild
    &lt;/li&gt;
  &lt;/ul&gt;
&lt;/ul&gt;
&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;</t>
<t tx="ekr.20160401061847.4">&lt;!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"&gt;
&lt;!--@+leo-ver=5-thin--&gt;
&lt;!--@+node:ekr.20100808060203.4273: * @thin html/front.html--&gt;
&lt;!--@@first--&gt;
&lt;!--@@first--&gt;

&lt;!--@@language html--&gt;
&lt;!--@@tabwidth -2--&gt;

&lt;html xmlns="http://www.w3.org/1999/xhtml"&gt;
&lt;head&gt;
    &lt;!--@+&lt;&lt; head &gt;&gt;--&gt;
    &lt;!--@+node:ekr.20100808060203.4274: ** &lt;&lt; head &gt;&gt;--&gt;
    &lt;meta http-equiv="Content-Type" content="text/html; charset=utf-8" /&gt;

    &lt;title&gt;Leo's Home Page&lt;/title&gt;
    &lt;link rel="stylesheet" href="_static/default.css" type="text/css" /&gt;
    &lt;link rel="stylesheet" href="_static/silver_city.css" type="text/css" /&gt;
    &lt;!--
    &lt;script type="text/javascript"&gt;
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '',
        VERSION:     '4.7-final',
        COLLAPSE_MODINDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  false
      };
    &lt;/script&gt;
    --&gt;
    &lt;!-- &lt;script type="text/javascript" src="_static/jquery.js"&gt;&lt;/script&gt;--&gt;
    &lt;!-- &lt;script type="text/javascript" src="_static/doctools.js"&gt;&lt;/script&gt;--&gt;
    &lt;link rel="top" title="Leo v4.7-final documentation" href="index.html" /&gt;
    &lt;link rel="Users Guide" title="Leo&amp;#8217;s Users Guide" href="leo_toc.html" /&gt;
    &lt;!-- &lt;link rel="prev" title="Chapter 5: Using LeoÃ¢â‚¬â„¢s Commands" href="commands.html" /&gt;--&gt; 
    &lt;!--@-&lt;&lt; head &gt;&gt;--&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;!--@+&lt;&lt; div top nav &gt;&gt;--&gt;
    &lt;!--@+node:ekr.20100808060203.4276: ** &lt;&lt; div top nav &gt;&gt;--&gt;
    &lt;div class="related"&gt;
      &lt;h3&gt;Navigation&lt;/h3&gt;
      &lt;ul&gt;
        &lt;li class="right" style="margin-right: 10px"&gt;
          &lt;a href="genindex.html" title="General Index"
             accesskey="I"&gt;index&lt;/a&gt;&lt;/li&gt;
        &lt;li class="right" &gt;
          &lt;a href="leo_toc.html" title="Leo&amp;#8217;s Users Guide"
             accesskey="N"&gt;contents&lt;/a&gt; |&lt;/li&gt;
        &lt;!--
        &lt;li class="right" &gt;
          &lt;a href="commands.html" title="Chapter 5: Using Leo&amp;#8217;s Commands"
             accesskey="P"&gt;previous&lt;/a&gt; |&lt;/li&gt;
        --&gt;
        &lt;li&gt;&lt;a href="leo_toc.html"&gt;Leo v4.7-final documentation&lt;/a&gt; &amp;raquo;&lt;/li&gt;

      &lt;/ul&gt;
    &lt;/div&gt;
    &lt;!--@-&lt;&lt; div top nav &gt;&gt;--&gt;
    &lt;div class="document"&gt;
      &lt;div class="documentwrapper"&gt;
        &lt;div class="bodywrapper"&gt;
          &lt;div class="body"&gt;
            &lt;!--@+&lt;&lt; div outer section &gt;&gt;--&gt;
            &lt;!--@+node:ekr.20100808060203.4286: ** &lt;&lt; div outer section &gt;&gt;--&gt;
            &lt;div class="section" id="Leo&amp;#8217;s Home page"&gt;

                &lt;h1&gt;Leo&amp;#8217;s Home Page&lt;/h1&gt;

                Leo is...

                &lt;!--@+&lt;&lt; what is Leo list &gt;&gt;--&gt;
                &lt;!--@+node:ekr.20100808060203.4288: *3* &lt;&lt; what is Leo list &gt;&gt;--&gt;
                &lt;li&gt;
                    An outline-oriented &lt;i&gt;browser&lt;/i&gt; and &lt;i&gt;project manager&lt;/i&gt; that organizes&lt;br&gt;
                    programs, web sites, URL's, pictures, movies or any other kind of data.&lt;br&gt;
                    You can organize your data in as many ways as you like within a &lt;i&gt;single&lt;/i&gt; outline.&lt;/li&gt;
                &lt;li&gt;
                    A &lt;i&gt;programmer's editor&lt;/i&gt; that fully integrates outline structure with programming.
                    &lt;!--
                    &lt;a HREF="http://www.eecs.harvard.edu/~nr/noweb/"&gt;noweb&lt;/a&gt; and
                    &lt;a HREF="http://www-cs-faculty.stanford.edu/~knuth/cweb.html"&gt;CWEB&lt;/a&gt; markup.&lt;/li&gt;
                    --&gt;
                &lt;li&gt;
                    &lt;i&gt;Fully scriptable&lt;/i&gt; using &lt;a HREF="http://www.python.org/"&gt;Python&lt;/a&gt;.
                    Leo's core is 100% pure Python.&lt;/li&gt;
                &lt;li&gt;
                    &lt;i&gt;Portable&lt;/i&gt;. Leo runs on Windows, Linux and MacOS X.&lt;br&gt;
                    Leo requires either the
                    &lt;a HREF="http://docs.python.org/library/tkinter.html"&gt;Tkinter&lt;/a&gt; or
                    &lt;a HREF="http://www.riverbankcomputing.co.uk/software/pyqt/intro"&gt;PyQt&lt;/a&gt; widget set.&lt;br&gt;
                    Leo's outline files are &lt;a HREF="http://www.w3.org/XML/"&gt;XML&lt;/a&gt; format.&lt;/li&gt;
                &lt;li&gt;
                    &lt;a href="http://www.opensource.org/"&gt;&lt;i&gt;Open Software&lt;/i&gt;&lt;/a&gt;,
                    distributed under the
                    &lt;a href="http://www.opensource.org/licenses/mit-license.php/"&gt;MIT License&lt;/a&gt;.&lt;/li&gt;
                &lt;!--@-&lt;&lt; what is Leo list &gt;&gt;--&gt;
                &lt;!-- div body toc --&gt;
                &lt;!-- &lt; &lt; inner sections &gt; &gt; --&gt;

                &lt;p&gt;Leo has an active community of helpful users and developers.&lt;br&gt;
                Please use the &lt;a href="http://groups.google.com/group/leo-editor"&gt;leo-editor&lt;/a&gt;
                group to ask questions and make suggestions.&lt;/p&gt;

                &lt;p&gt;Leo's author is &lt;a HREF="ekr.html"&gt;Edward K. Ream&lt;/a&gt;&lt;/p&gt;

            &lt;/div&gt;
            &lt;!--@-&lt;&lt; div outer section &gt;&gt;--&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;!--@+&lt;&lt; sidebar &gt;&gt;--&gt;
      &lt;!--@+node:ekr.20100808060203.4282: ** &lt;&lt; sidebar &gt;&gt;--&gt;
      &lt;div class="sphinxsidebar"&gt;
          &lt;div class="sphinxsidebarwrapper"&gt;
              &lt;!--@+&lt;&lt; sidebar contents &gt;&gt;--&gt;
              &lt;!--@+node:ekr.20100808060203.4283: *3* &lt;&lt; sidebar contents &gt;&gt;--&gt;
              &lt;p class="logo"&gt;&lt;a href="leo_toc.html"&gt;
                &lt;img class="logo" src="_static/Leo4-80-border.jpg" alt="Logo"/&gt;&lt;/a&gt;&lt;/p&gt;

              &lt;a class="reference external" href="intro.html"&gt;
                Read this tutorial first&lt;/a&gt;&lt;br&gt;
              &lt;a class="reference external" href="http://www.3dtree.com/ev/e/sbooks/leo/sbframetoc_ie.htm"&gt;
                Another tutorial&lt;/a&gt;&lt;br&gt;
              &lt;a class="reference external" href="http:screen-shots.html"&gt;
                Screen shots of Leo&lt;/a&gt;&lt;br&gt;
              &lt;a class="reference external" href="testimonials.html"&gt;
                Quotes from Leo&amp;#8217;s Users&lt;/a&gt;&lt;br&gt;
              &lt;a class="reference external"
                href="http://sourceforge.net/project/showfiles.php?group_id=3458&amp;amp;package_id=29106"&gt;
                Download Leo&lt;/a&gt;&lt;br&gt;
              &lt;a class="reference external" href="http://groups.google.com/group/leo-editor"&gt;
                leo-editor: Google Groups&lt;/a&gt;&lt;br&gt;
              &lt;a class="reference external" href="http://launchpad.net/leo-editor"&gt;
                leo-editor: Launchpad&lt;/a&gt;&lt;br&gt;
              &lt;a class="reference external" href="http://leo.zwiki.org"&gt;
                Leo&amp;#8217;s Wiki&lt;/a&gt;&lt;br&gt;
              &lt;a class="reference external" href="http://www.mind-mapping.org/"&gt;
                Mind Mapping&lt;/a&gt;&lt;br&gt;
              &lt;a class="reference external" href="leoLinks.html"&gt;
                More links...&lt;/a&gt;&lt;br&gt;

              &lt;!-- &lt;a class="reference external"  href="install.html"&gt;Installing Leo&lt;/a&gt;&lt;br&gt;--&gt; 
              &lt;!-- &lt;a class="reference external"  href="intro.html"&gt;Beginners Guide&lt;/a&gt;&lt;br&gt;--&gt;
              &lt;!-- &lt;a class="reference external"  href="leo_toc.html"&gt;Users Guide&lt;/a&gt;&lt;br&gt;--&gt;
              &lt;!-- &lt;a class="reference external"  href="FAQ.html"&gt;FAQ&lt;/a&gt;&lt;br&gt;--&gt;
              &lt;!--Leo&amp;#8217;s &lt;a class="reference external" href="http://www.greygreen.org/leo/"&gt;Daily snapshots&lt;/a&gt;&lt;br&gt;--&gt;
              &lt;!-- 
              &lt;h5&gt;Edward K. Ream&lt;/h5&gt;
              &lt;a class="reference external" href="ekr.html"&gt;Home&lt;/a&gt;&lt;br&gt;
              &lt;a class="reference external" href="mailto:edreamleo@gmail.com"&gt;Contact&lt;/a&gt;&lt;br&gt;
              --&gt; 
              &lt;!--@-&lt;&lt; sidebar contents &gt;&gt;--&gt;
          &lt;!-- &lt; &lt; sidebar links &gt; &gt; --&gt;
          &lt;!-- &lt; &lt; searchbox &gt; &gt; --&gt;
          &lt;/div&gt;
      &lt;/div&gt;
      &lt;!--@-&lt;&lt; sidebar &gt;&gt;--&gt;
      &lt;div class="clearer"&gt;&lt;/div&gt;
    &lt;/div&gt;
    &lt;!--@+&lt;&lt; div bottom nav &gt;&gt;--&gt;
    &lt;!--@+node:ekr.20100808060203.4277: ** &lt;&lt; div bottom nav &gt;&gt;--&gt;
    &lt;div class="related"&gt;
      &lt;h3&gt;Navigation&lt;/h3&gt;
      &lt;ul&gt;
        &lt;li class="right" style="margin-right: 10px"&gt;
          &lt;a href="genindex.html" title="General Index"
             &gt;index&lt;/a&gt;&lt;/li&gt;
        &lt;li class="right" &gt;
          &lt;a href="leo_toc.html" title="Leo&amp;#8217;s Users Guide"
             &gt;contents&lt;/a&gt; |&lt;/li&gt;
        &lt;!--
        &lt;li class="right" &gt;
          &lt;a href="commands.html" title="Chapter 5: Using Leo&amp;#8217;s Commands"
             &gt;previous&lt;/a&gt; |&lt;/li&gt;
        --&gt;
        &lt;li&gt;&lt;a href="leo_toc.html"&gt;Leo v4.7-final documentation&lt;/a&gt; &amp;raquo;&lt;/li&gt; 
      &lt;/ul&gt;
    &lt;/div&gt;
    &lt;!--@-&lt;&lt; div bottom nav &gt;&gt;--&gt;
    &lt;!--@+&lt;&lt; div footer &gt;&gt;--&gt;
    &lt;!--@+node:ekr.20100808060203.4278: ** &lt;&lt; div footer &gt;&gt;--&gt;
    &lt;div class="footer"&gt;
      &amp;copy; Copyright 2010, Edward K. Ream.
      Last updated on Aug 08, 2010.
      Created using &lt;a href="http://sphinx.pocoo.org/"&gt;Sphinx&lt;/a&gt; 0.6.3.
    &lt;/div&gt;
    &lt;!--@-&lt;&lt; div footer &gt;&gt;--&gt;
  &lt;/body&gt;
&lt;/html&gt;
&lt;!--@-leo--&gt;
</t>
<t tx="ekr.20160401061847.5">C:\leo.repo\leo-editor\leo\Icons\Leosplash.GIF

This is a comment</t>
<t tx="ekr.20160401061847.6">c:\leo.repo\leo-editor\leo\Icons\SplashScreen.ico

</t>
<t tx="ekr.20160401061847.7">C:\Users\edreamleo\SampleVideo_1280x720_1mb.mp4
</t>
<t tx="ekr.20160401061847.8">https://www.youtube.com/watch?v=EB3IokHelRk

# Doesn't play, probably because of https.</t>
<t tx="ekr.20160401061847.9"></t>
<t tx="ekr.20160401062424.1">http://www.sample-videos.com/video/mp4/720/big_buck_bunny_720p_1mb.mp4

# This *does* play.</t>
<t tx="ekr.20160401063704.1">C:\Users\edreamleo\Documents\Music\2001- A Space Odyssey [Rhino]\06 Gayane Ballet Suite.mp3</t>
<t tx="ekr.20160401065134.1">@language md
@wrap

[Leo's home page](http://leoeditor.com/)
</t>
<t tx="ekr.20160401065154.1">@language rest
@wrap

`Leo's home page &lt;http://leoeditor.com/&gt;`_

</t>
<t tx="ekr.20160401065735.1">`weather.com &lt;http://www.weather.com/weather/today/Madison+WI+53705?from=hp_promolocator&amp;lswe=53705&amp;lwsa=Weather36HourHealthCommand&gt;`_
</t>
<t tx="ekr.20160401073951.1">@language python

def spam():
    '''This is a docstring.'''
    pass</t>
<t tx="ekr.20160420153653.1"></t>
<t tx="ekr.20160421054609.1">'''A simple test bed for the leoBridge module.'''
import os
import sys

# Leo files.
files = [
    'c:/leo.repo/leo-editor/leo/test/unitTest.leo',
    'c:/leo.repo/leo-editor/leo/test/test.leo',
    'c:/xyzzy.xxx',
]

# Switches...
gui = 'nullGui'         # 'nullGui', 'qt',
kill_leo_output = False # True: kill all output produced by g.es_print.
loadPlugins = False     # True: attempt to load plugins.
readSettings = True     # True: read standard settings files.
silent = True           # True: don't print signon messages.
trace_sys_path = False  # True: trace imports here.
verbose = True          # True: verbose output.

# Import stuff...
dir_ = os.path.abspath('.')
if dir_ not in sys.path:
    if trace_sys_path: print('appending %s to sys.path' % dir_)
    sys.path.append(dir_)
if trace_sys_path:
    print('sys.path:...\n%s' % '\n'.join(sorted(sys.path)))
    print('sys.argv: %s %s' % (len(sys.argv), '\n'.join(sys.argv)))
if gui == 'qt':
    # Do this here to bypass leoQt g.in_bridge logic.
    import leo.core.leoQt as leoQt
import leo.core.leoBridge as leoBridge

controller = leoBridge.controller(
    gui=gui,
    loadPlugins=loadPlugins,
    readSettings=readSettings,
    silent=silent,
    verbose=verbose)
g = controller.globals()

# This kills all output from commanders.
if kill_leo_output:
    
    def do_nothing(*args, **keys):
        pass
        
    g.es_print = do_nothing
    
for path in files:
    if os.path.exists(path):
        c = controller.openLeoFile(path)
        if c:
            n = 0
            for p in c.all_positions():
                n += 1
            print('%s has %s nodes' % (c.shortFileName(), n))
    else:
        print('file not found: %s' % path)</t>
<t tx="ekr.20160421123215.1">def do_nothing(*args, **keys):
    pass
        
g.es_print = do_nothing
g.es = do_nothing

g.es('test')</t>
</tnodes>
</leo_file>
