<?xml version="1.0" encoding="utf-8"?>
<!-- Created by Leo: http://leoeditor.com/leo_toc.html -->
<leo_file xmlns:leo="http://leoeditor.com/namespaces/leo-python-editor/1.1" >
<leo_header file_format="2"/>
<globals/>
<preferences/>
<find_panel_settings/>
<vnodes>
<v t="ekr.20050315084904"><vh>Startup</vh>
<v t="ekr.20141117135127.2"><vh>@settings</vh>
<v t="ekr.20141117135127.3"><vh>@bool wikiview-active = False</vh></v>
</v>
<v t="ekr.20070325123540"><vh>@chapters</vh></v>
<v t="ekr.20101025095431.1517"><vh>Installer/Distribution bugs &amp; to-do</vh>
<v t="ekr.20101025095431.1518"><vh>Fixed Bug 514656 Uninstall operation does not work as expected</vh>
<v t="ekr.20090901092556.1576"><vh>genUninstallData &amp; helpers</vh>
<v t="ekr.20090901121423.1568"><vh>getDeleteDirectories</vh></v>
<v t="ekr.20090901121423.1569"><vh>getDeleteFiles</vh></v>
<v t="ekr.20090901121423.1567"><vh>getUninstallVariableData</vh></v>
</v>
</v>
<v t="ekr.20101026142031.1516"><vh>Registry Keys</vh></v>
</v>
<v t="ekr.20170911061827.1"><vh>@button check .leo files</vh>
<v t="ekr.20170911062209.1"><vh>&lt;&lt; define files &gt;&gt;</vh></v>
</v>
<v t="ekr.20190429113053.1"><vh>@@button make leo</vh>
<v t="ekr.20190429113053.2"><vh>&lt;&lt; includes &gt;&gt;</vh></v>
<v t="ekr.20190429113053.3"><vh>&lt;&lt; define global paths and file names &gt;&gt;</vh></v>
<v t="ekr.20190429113053.4"><vh>class LeoMaker</vh>
<v t="ekr.20190429113053.5"><vh>run &amp; helpers</vh>
<v t="ekr.20190429113053.6"><vh>clean_manifest</vh></v>
<v t="ekr.20190429113053.7"><vh>clean_spellpyx</vh></v>
<v t="ekr.20190429113053.8"><vh>copy_nsi_files (Not used)</vh></v>
<v t="ekr.20190429113053.9"><vh>copy_ref_files (Not used)</vh></v>
<v t="ekr.20190429113053.10"><vh>create_install_files</vh></v>
<v t="ekr.20190429113053.11"><vh>create_uninstall_files</vh></v>
<v t="ekr.20190429113053.12"><vh>directoryList</vh></v>
<v t="ekr.20190429113053.13"><vh>filterLines &amp; helpers</vh>
<v t="ekr.20190429113053.14"><vh>delete...</vh></v>
</v>
<v t="ekr.20190429113053.15"><vh>make_manifest</vh></v>
<v t="ekr.20190429113053.16"><vh>make_zip</vh></v>
<v t="ekr.20190429113053.17"><vh>makeDicts</vh></v>
<v t="ekr.20190429113053.18"><vh>printMissing</vh></v>
<v t="ekr.20190429113053.19"><vh>remove_commit_timestamp_json (Not used)</vh></v>
</v>
<v t="ekr.20190429113053.20"><vh>utils...</vh>
<v t="ekr.20190429113053.21"><vh>openFile</vh></v>
<v t="ekr.20190429113053.22"><vh>put</vh></v>
<v t="ekr.20190429113053.23"><vh>unlink</vh></v>
</v>
</v>
</v>
<v t="DSR.20181126072740.2"><vh>@file git_install.py</vh></v>
<v t="ekr.20150416081546.1"><vh>Scripts</vh>
<v t="ekr.20150416081546.2"><vh>Catch mixed newlines in distribution files</vh>
<v t="ekr.20150416081546.3"><vh>check</vh></v>
</v>
<v t="ekr.20150416081546.4"><vh>Catch mixed tab &amp; space in derived files</vh>
<v t="ekr.20150416081546.5"><vh>check</vh></v>
</v>
<v t="ekr.20150416081546.6"><vh>Check all colorizer files for problem regex's</vh></v>
<v t="ekr.20150416081546.7"><vh>Clean ekr-spellpyx.txt</vh></v>
<v t="ekr.20150416081546.8"><vh>Linux install script</vh></v>
<v t="ekr.20150416081546.9"><vh>Warn if leoProjects.txt or leoToDo.txt contain clones</vh></v>
</v>
</v>
<v t="ekr.20161024113526.1"><vh>Notes</vh>
<v t="ekr.20161024113542.1"><vh>#106 Homebrew (MacOS) notes</vh>
<v t="ekr.20161025114444.1"><vh>The latest formula</vh></v>
<v t="ekr.20161025114433.1"><vh>Posts</vh>
<v t="ekr.20161024113553.1"><vh>Post 1: Winn Dixie</vh></v>
<v t="ekr.20161024113810.1"><vh>Post 2: ludwigschwardt</vh></v>
<v t="ekr.20161024114150.1"><vh>Post 3: me April 15, 2015</vh></v>
<v t="ekr.20161025091538.1"><vh>Post 4: me April 24, 2015</vh></v>
<v t="ekr.20161025091621.1"><vh>Post 5: ludwidswardt April 24, 2015</vh></v>
<v t="ekr.20161024115114.1"><vh>Post 4: me May 1, 2015</vh></v>
</v>
<v t="ekr.20161024115257.1"><vh>How to compute the sha256 hash</vh></v>
</v>
<v t="EKR.20040519091259.1"><vh>Download statistics from SourceForge</vh></v>
<v t="maphew.20180128212042.1"><vh>How to build Leo's PyPi Package</vh>
<v t="maphew.20180128212042.3"><vh>Create an PyPi.org account</vh></v>
<v t="maphew.20180128212042.2"><vh>Build requirements</vh></v>
<v t="maphew.20180128212042.4"><vh>Build &amp; publish a release</vh></v>
<v t="maphew.20180128213245.1"><vh>Not recommended: Test with TestPyPI</vh></v>
<v t="maphew.20180128212042.5"><vh>Caveats</vh></v>
</v>
<v t="ekr.20141118074110.3"><vh>How to Install Leo on Linux</vh></v>
<v t="ekr.20101027160251.1500"><vh>NSIS Notes</vh>
<v t="ekr.20101027135430.1492"><vh>@url nsi new ui readme</vh></v>
<v t="ekr.20101027135430.1493"><vh>@url about pages</vh></v>
<v t="ekr.20101027160251.1497"><vh>@url nsDialogs</vh></v>
</v>
<v t="ekr.20101027131034.1490"><vh>Obsolete: NSIS source files</vh>
<v t="ekr.20160510090441.1"><vh>@@file ../../leo_assoc.nsi</vh>
<v t="ekr.20160510090943.1"><vh>&lt;&lt; assoc prolog &gt;&gt;</vh></v>
<v t="ekr.20160510091130.1"><vh>&lt;&lt; assoc pages &gt;&gt;</vh></v>
<v t="ekr.20160510093344.1"><vh>LeoAssoc</vh></v>
<v t="ekr.20160510093411.1"><vh>Section FileAssociation</vh></v>
<v t="ekr.20160510093822.1"><vh>Section Desktop Shortcut</vh></v>
<v t="ekr.20160510093859.1"><vh>Section Start Menu</vh></v>
<v t="ekr.20160510095724.1"><vh>Section Uninstall</vh></v>
<v t="ekr.20160510095711.1"><vh>Section -Post</vh></v>
</v>
<v t="ekr.20101027054254.1590"><vh>@@file ../../leo.nsi</vh>
<v t="ekr.20161017094430.1"><vh>&lt;&lt; defines &gt;&gt;</vh></v>
<v t="ekr.20161017094235.2"><vh>&lt;&lt; prolog &gt;&gt;</vh></v>
<v t="ekr.20161017094235.3"><vh>&lt;&lt; pages &gt;&gt;</vh></v>
<v t="ekr.20161017094235.4"><vh>onInit</vh></v>
<v t="ekr.20161017094235.5"><vh>Section Leo</vh></v>
<v t="ekr.20161017094235.6"><vh>Section File Association</vh></v>
<v t="ekr.20161017094235.7"><vh>Section Desktop Shortcut</vh></v>
<v t="ekr.20161017094235.8"><vh>Section Start Menu</vh></v>
<v t="ekr.20161017094235.9"><vh>Section -Post</vh></v>
<v t="ekr.20161017094235.10"><vh>Section Uninstall</vh></v>
</v>
</v>
<v t="ekr.20100202061222.1494"><vh>Obsolete: SourceForce distribution checklist</vh>
<v t="ekr.20161015091353.2"><vh>Files</vh></v>
<v t="ekr.20161015091353.1"><vh>Web docs</vh></v>
<v t="ekr.20161015091350.1"><vh>Pre-testing</vh></v>
<v t="ekr.20161015092224.1"><vh>Create distribution</vh></v>
<v t="ekr.20161020040946.1"><vh>Test</vh></v>
<v t="ekr.20161020041000.1"><vh>Create git tag</vh></v>
<v t="ekr.20170316104916.1"><vh>Publish release</vh></v>
<v t="ekr.20161015091353.3"><vh>Announcements</vh></v>
<v t="ekr.20180301115911.1"><vh>Create python wheel</vh></v>
<v t="ekr.20150326055410.1"><vh>Update versions</vh></v>
</v>
<v t="EKR.20040519091259.2"><vh>Quotes of the month</vh>
<v t="ekr.20080901114425.2"><vh>Sept 2008</vh></v>
<v t="ekr.20070425092712"><vh>April 2007</vh></v>
<v t="ekr.20070101093904"><vh>January 2007</vh></v>
<v t="ekr.20060823090437"><vh>August 2006</vh></v>
<v t="ekr.20060213160806"><vh>February 2005</vh></v>
<v t="ekr.20040828084148"><vh>August 2004</vh></v>
<v t="ekr.20040630210818"><vh>July 2004</vh></v>
<v t="EKR.20040519091259.3"><vh>November 2003</vh></v>
<v t="EKR.20040519091259.4"><vh>October 2003</vh></v>
</v>
<v t="matt.20181004031246.1"><vh>Travis Continual Integration</vh>
<v t="maphew.20181010205346.1"><vh>Troubleshooting</vh></v>
</v>
</v>
<v t="EKR.20040519090846"><vh>Distribution files</vh>
<v t="ekr.20141016105045.2119"><vh>@asis ../../.gitattributes</vh></v>
<v t="ekr.20130809141000.1990"><vh>@asis ../../INSTALL.TXT</vh>
<v t="ekr.20130809141000.1991"><vh>System requirements</vh></v>
<v t="ekr.20130809141000.1992"><vh>Leo's HOME directory</vh></v>
<v t="ekr.20130809141000.1993"><vh>Linux installation</vh></v>
<v t="ekr.20130809141000.1994"><vh>Windows installation</vh></v>
<v t="ekr.20130809141000.1995"><vh>Running Leo</vh></v>
<v t="ekr.20130809141000.1996"><vh>Creating file associations</vh></v>
<v t="ekr.20130809141000.1997"><vh>Adding Leo to your path</vh></v>
<v t="ekr.20130809141000.1998"><vh>Running Leo for the first time</vh></v>
</v>
<v t="matt.20190205105334.1"><vh>@asis ../../.travis.yml</vh></v>
<v t="EKR.20040519090846.1"><vh>@asis ../../LICENSE</vh></v>
<v t="EKR.20040519090846.8"><vh>@asis ../../PKG-INFO.TXT</vh></v>
<v t="EKR.20040519090846.9"><vh>@asis ../../README.md</vh></v>
<v t="ekr.20151227063335.1"><vh>@asis ../../About leo.exe.TXT</vh></v>
<v t="ekr.20150425135153.1"><vh>homebrew install script</vh>
<v t="ekr.20150425135153.2"><vh>brew install formula</vh></v>
</v>
<v t="mhw-nc.20190126223741.1"><vh>Pip</vh>
<v t="maphew.20180224170853.1"><vh>@file ../../setup.py</vh></v>
<v t="maphew.20190208135916.1"><vh>@asis ../../setup.cfg</vh></v>
<v t="maphew.20190206032329.1"><vh>@asis ../../pyproject.toml</vh></v>
<v t="maphew.20190208142757.1"><vh>@clean ../../optional-tools.txt</vh></v>
</v>
<v t="mhw.20190718140254.1"><vh>Travis</vh>
<v t="mhw.20190718140259.1"><vh>@clean ../../.travis.yml</vh></v>
</v>
</v>
<v t="ekr.20180405171433.1"><vh>Distribution checklist (GitHub Only)</vh>
<v t="ekr.20180405171433.2"><vh>Files</vh></v>
<v t="ekr.20180405171433.3"><vh>Web docs</vh></v>
<v t="ekr.20180405171433.4"><vh>Pre-testing</vh></v>
<v t="ekr.20180828095749.1"><vh>Create a -rel *branch* late.</vh></v>
<v t="ekr.20180828095843.1"><vh>Update verions.py in the -rel branch</vh></v>
<v t="ekr.20190618104430.1"><vh>Merge -rel branch into master</vh></v>
<v t="ekr.20180405171433.7"><vh>Create git tag in master</vh></v>
<v t="ekr.20190618104609.1"><vh>Merge git *tag* into devel</vh></v>
<v t="ekr.20181001112218.1"><vh>Update version in devel branch</vh></v>
<v t="ekr.20190618104622.1"><vh>Publish release</vh></v>
<v t="ekr.20190618104704.1"><vh>Announcements</vh></v>
</v>
</vnodes>
<tnodes>
<t tx="EKR.20040519090846">@language rest
@wrap
</t>
<t tx="EKR.20040519090846.1">MIT License

Copyright (c) 1997-2019 by Edward K. Ream.

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

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

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

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

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

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

    Copyright (c) Jupyter Development Team.
    Distributed under the terms of the Modified BSD License.
    
Portions of Leo's pyzo interface uses code from pyzo:

    Copyright (C) 2013-2019, the Pyzo development team
    
    Pyzo is distributed under the terms of the (new) BSD License.
    The full license can be found in 'license.txt'.
    
    Yoton is distributed under the terms of the (new) BSD License.
    The full license can be found in 'license.txt'.

</t>
<t tx="EKR.20040519090846.8">Metadata-Version: 1.0
Name: leo
Version: 6.0
Summary: An IDE, PIM and Outliner. See leoeditor.com/preface.html.
Description: See users own descriptions of Leo at leoeditor.com/testimonials.html.
Home-page: http://leoeditor.com/
Author: Edward K. Ream
Author-email: edreamleo@gmail.com
License: MIT
Keywords: Outliner, IDE, PIM, DAG, Scripting
Platform: Windows, Linux, MaxOS
Classifier: Development Status :: 6 - Mature
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python
Classifier: Topic :: Software Development
Classifier: Topic :: Text Processing
Download-URL: http://sourceforge.net/projects/leo/files/
</t>
<t tx="EKR.20040519090846.9">Leo 6.0 final, http://leoeditor.com, is now available on
[GitHub](https://github.com/leo-editor/leo-editor).

Leo is an IDE, outliner and PIM, as described [here](http://leoeditor.com/preface.html).

**The highlights of Leo 6.0**

- Leo now requires python 3.6 or above.
  This greatly simplifies Leo's code.
- Leo's default gui uses Qt Docks.
  Use --no-dock to use Leo's legacy gui.
- Several commands now generate clickable links in the Log pane.
  This greatly speeds navigation.
- The usual assortment of bug fixes and minor improvements.

**Links**

- Leo's home page: http://leoeditor.com
- [Documentation](http://leoeditor.com/leo_toc.html)
- [Tutorials](http://leoeditor.com/tutorial.html)
- [Video tutorials](http://leoeditor.com/screencasts.html)
- [Forum](http://groups.google.com/group/leo-editor)
- [Download](http://sourceforge.net/projects/leo/files/)
- [Leo on GitHub](https://github.com/leo-editor/leo-editor)
- [LeoVue](https://github.com/kaleguy/leovue#leo-vue)
- [What people are saying about Leo](http://leoeditor.com/testimonials.html)
- [A web page that displays .leo files](http://leoeditor.com/load-leo.html)
- [More links](http://leoeditor.com/leoLinks.html)
</t>
<t tx="EKR.20040519091259.1">5.1:        setup: 1,114    zip: 2,912
5.0:        setup: 552      zip: 1,617
4.4.5       setup: 547   zip: 379  2007-12-11
4.4.4       setup: 856  zip: 539  2007-11-02
4.4.3.1     setup: 1092 zip: 743  2007-7-03
4.4.3       setup: 363  zip: 282  2007-6-26
4.4.2.1     setup: 2847 zip: 2044 2006-10-19
4.4.1.1     setup: 1041 zip: 813  2006-9-3
4.4         setup: 1318 zip: 1075 2006-5-11
3.3.3       setup: 1503 zip: 1145 2005-9-19
4.3.2 final setup: 409  zip: 222
4.3.1 final setup: 2168 zip: 1781
4.3 final   setup: 942  zip: 686
4.2.1 final setup: 413  zip: 490
4.2-final   setup: 1828 zip: 1508
4.2b3       setup: 563, zip: 338
4.1rc3      setup: 870  zip: 630
4.1 b5      setup: 195, zip: 128
4.0.4       setup: 340, zip: 385
4.0                     zip: 382
3.12        setup: 953  zip: 592
3.11                    zip: 102
3.10                    zip: 1193</t>
<t tx="EKR.20040519091259.2"></t>
<t tx="EKR.20040519091259.3">I like Leo more the more I use it...It's an unexpected pleasure to
see my (linearly written) code outlined in Leo. I can't wait to use
Leo to start a new project, going from outline to code...Thanks again
for providing the computing community with such a fine piece of
software. -- Jim Shapiro, Ph.D.

If you think you have used all possible programmer's editors, but
have not yet tried Leo, you are wrong...I rate Leo as a "must have"
for Python programmers. The code makes for a good read.
-- John Tobler  http://weblogs.asp.net/Jtobler/
</t>
<t tx="EKR.20040519091259.4">I've written documentation in WordPerfert, Ventura, Word, PageMaker, and
FrameMaker and even though they create wonderfully looking and useful
documents, they've never been able to do what I've been looking for. HTML,
compiled help files, and later PDF came closer, but still not there. I think
I've found it in LEO, a way to make a "living" document. A document built out
of discrete parts that can be re-organized on the fly to meet the needs of a
varying audience...Being a convert for less than a day I've still got a lot to
learn, but just the possibility of keeping system maintenance scripts in the IT
manual is mind boggling.  -- David Nichols dnichols@amci.com</t>
<t tx="ekr.20040630210818">HTML Editing in Leo is soooo much easier then with NoNodeEditors. Ive
had a blast working on a web page. Usually I had to look at a bunch of
gunk all at once. Now I can look at little pieces of gunk! :) 

-Anon (for now)

Before leo, I try to avoid or refactor long functions. With leo, I am
very tempted not to. Being able to view and slice my code at a higher
level in pretty much anyway I want, I feel like a commanding master in
my own mess...Leo lets me be lazy and get away with it. ;)

Mark Ng

[Quote] I have just finished a little embedded system for someone, written in
C using leo as the editor. I told the customer he _had_ to use leo for
ongoing maintenance, after I looked at one of the main state machines:
600 lines in the derived file, but trivially easy to get your head
around in Leo...

The good news is that having been forced to meet leo he thinks it'll
solve many other problems that his company has with code maintenance.
Another step to world domination!

Leo allows you to do things that you'd never consider with another editor. 

BTW: in a real-time embedded system like I was working on, not having
the overhead of a function call (which you'd have had if you'd split
the case statement as you would with a normal editor) saves time, and
makes the system more flexible...
[End Quote]</t>
<t tx="ekr.20040828084148">Leo is the best IDE that I have had the pleasure to use. I have been using it
now for about 2 -- 3 months. It has totally changed not only the way that I
program, but also the way that I store and organize all of the information that
I need for the job that I do. -- Ian Mulvany</t>
<t tx="ekr.20050315084904"></t>
<t tx="ekr.20060213160806">"Thanks for a wonderful program – everybody should be using it! It blows the
socks off that Java Mind mapping software that won project of the month a while
back on sourceforge!" -- Derick van Niekerk.
</t>
<t tx="ekr.20060823090437">Thanks for creating the most useful and amazing application that
I've come across in years. I use Leo every day.</t>
<t tx="ekr.20070101093904">Leo is THE BEST THING to ever had happened to me. I've done in two
weeks what would have taken me years (not exaggerating!). Thanks Ed
for a terrific tool!!!!
 
Julian S. Fecteau 
</t>
<t tx="ekr.20070325123540"></t>
<t tx="ekr.20070425092712">Leo--especially with its feature of user-controllable outlining and
overview--has for the last 4-5 years had the greatest positive effect
on my overall programming quality of life than anything else out there
in the software world (apart maybe from the Python language itself,
and those who contribute Python modules to the world). -- David McNab
</t>
<t tx="ekr.20080901114425.2">For me Squeak and Leo have been two of the most significant technologies to
redefine my personal computer experience and the ideas behind computing.</t>
<t tx="ekr.20090901092556.1576">def genUninstallData(self,dirs,dirDict,filesDict):

    '''Generate the manifest-specific uninstall data.'''

    trace = True

    s = r'''
Section Uninstall

    DeleteRegKey HKEY_LOCAL_MACHINE "${hkey_local_machine}"

    ; Delete files &amp; directories only if we own them!
    ReadRegStr $$1 HKCR "${ext}" ""
    StrCmp $$1 "${name}File" 0 FinishUninstall

    ; Delete files &amp; directories only if there is no backup_val key.
    ReadRegStr $$1 HKCR "${ext}" "backup_val"
    StrCmp $$1 "" 0 DeleteLeoKeysAndFiles
      DeleteRegKey HKCR "${ext}"
    Goto FinishUninstall

DeleteLeoKeysAndFiles:
    WriteRegStr HKCR "${ext}" "" $$1
    DeleteRegValue HKCR "${ext}" "backup_val"

    ; ---- Start of manifest-related data...
'''

    self.put(s,substitute=True)

    # Does all the hard work.
    s = self.getUninstallVariableData(dirs,dirDict,filesDict)
    if trace: g.trace('\n',s)
    self.put(s,adjust = False)

    s = r'''
    ; ---- End of manifest related data.

FinishUninstall:
    ; MessageBox MB_YESNO|MB_ICONQUESTION \
    ;    "Delete all files in ${INSTDIR}?" IDNO NoDelete
; NoDelete:

  Delete "${SMPROGRAMS}\${name}\Uninstall.lnk"
  RMDir "${SMPROGRAMS}\${name}-${version}"
  Delete "${DESKTOP}\${name}.lnk"

  DeleteRegKey ${uninst_root_key} "${uninst_key}"
  SetAutoClose false

; end Uninstall section
SectionEnd
'''

    self.put(s,substitute=True)
</t>
<t tx="ekr.20090901121423.1567">def getUninstallVariableData(self,dirs,dirDict,filesDict):

    s1 = self.getDeleteFiles(dirs,dirDict,filesDict)
    s2 = self.getDeleteDirectories(dirs,dirDict)
    return '%s\n%s' % (s1,s2)
</t>
<t tx="ekr.20090901121423.1568">def getDeleteDirectories (self,dirs,dirDict):

    reverseDirs = dirs[:]
    reverseDirs.reverse()

    result = []

    if 1:
        result.append('; Recursively delete the leo directory and everything in it.\n')
        result.append('RMDir /r "$INSTDIR\\leo"\n\n')
    else:
        result.append('; Uninstall directories in reverse order\n')
        for theDir in reverseDirs:
            # Delete the directory even if it has files.
            if theDir and theDir != '**top':
                if not theDir.startswith('.bzr'):
                    result.append('RMDir "$INSTDIR\\%s"\n' % (
                        theDir.replace('/','\\')))

    # top-level folder.
    result.append('; Delete the top-level directory.\n')
    result.append('RMDir "$INSTDIR"\n')

    result = [self.indent(z) for z in result]
    return ''.join(result)
</t>
<t tx="ekr.20090901121423.1569">def getDeleteFiles (self,dirs,dirDict,filesDict):

    result = []
    result.append('\n')
    result.append('; Uninstall files...\n\n')

    # top-level files.
    result.append('; Delete top-level files...\n')
    aList = dirDict.get('**top',[])
    # Add *.py, *.pyo, *.pyc and *.leo, the most common added files.
    if 0: # This seems way too drastic, and not needed.
        for fn in ('*.py','*.pyo','*.pyc','*.leo',):
            aList.append(fn)
    # special case.
    aList.append('uninst.exe')
    # Warning: **never** delete all files in the top-level directory.
    for fn in aList:
        result.append('Delete "$INSTDIR\\%s"\n' % fn)

    if 0:
        wildcard_delete = True
        if wildcard_delete:
            result.append('\n')
        # Use the \r option to recursively delete everything in the leo directory.

        for theDir in dirs:
            if theDir:
                dir2 = theDir.replace('/','\\')
                if wildcard_delete:
                    result.append('Delete "$INSTDIR\\%s\\*.*"\n' % (dir2))
                else:
                    aList = dirDict.get(theDir,[])
                    if aList:
                        result.append('\n')
                        result.append('Delete "$INSTDIR\\%s\\*.pyc"\n' % (dir2))
                        result.append('Delete "$INSTDIR\\%s\\*.pyo"\n' % (dir2))
                    for fn in aList:
                        result.append('Delete "$INSTDIR\\%s\\%s"\n' % (
                            dir2,fn))

    result = [self.indent(z) for z in result]
    return ''.join(result)
</t>
<t tx="ekr.20100202061222.1494">@language rest

This checklist is obsolete, for the following reasons:

1. There never was a SourceForge release for Leo 5.8.
2. Matt's distribution script creates a more standard way of releasing Leo.</t>
<t tx="ekr.20101025095431.1517">@language rest</t>
<t tx="ekr.20101025095431.1518">https://bugs.launchpad.net/leo-editor/+bug/514656
</t>
<t tx="ekr.20101026142031.1516">@nocolor-node

HKEY_CURRENT_USER\Software\Classes\Applications\python.exe
HKEY_CURRENT_USER\Software\Classes\Applications\python.exe\shell\open\command
    val = c:\Python26\python.exe %1
HKCU
HKEY_CURRENT_USER\Software\Classes\Applications\pythonw.exe
HKEY_CURRENT_USER\Software\Classes\Applications\pythonw.exe\shell\open\command
    val = c:\Python26\pythonw.exe %1

HKEY_CURRENT_USER\Software\Classes\Applications\py_auto_file\shell\open\command
    val = c:\Python26\python.exe %1
    
HKEY_CURRENT_USER\Software\Classes\Installer\Products\nnnnnn

HKLM
HKEY_LOCAL_MACHINE\SOFTWARE\Python
HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore
HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.7\InstallPath
    val = c:\python27\
HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonPath
    val = c:\Python27\Lib;\Python27\DLLs;C:\Python27\Lib\lib-tk
</t>
<t tx="ekr.20101027054254.1590">@language nsi

&lt;&lt; defines &gt;&gt;

;;; !include nsi-boilerplate.txt

; RequestExecutionLevel highest
; RequestExecutionLevel admin

&lt;&lt; prolog &gt;&gt;
&lt;&lt; pages &gt;&gt;

; Language should follow pages.
!insertmacro MUI_LANGUAGE "English"

; The order of sections *does* matter slightly.
; It determines the order of items in the components dialog.
; It may also have some other very subtle effects.

@others
</t>
<t tx="ekr.20101027131034.1490">@color
</t>
<t tx="ekr.20101027135430.1492">http://nsis.sourceforge.net/Docs/Modern%20UI%202/Readme.html</t>
<t tx="ekr.20101027135430.1493">http://nsis.sourceforge.net/Docs/Chapter4.html#4.5</t>
<t tx="ekr.20101027160251.1497">http://nsis.sourceforge.net/Docs/nsDialogs/Readme.html</t>
<t tx="ekr.20101027160251.1500"></t>
<t tx="ekr.20130809141000.1990">@language rest
</t>
<t tx="ekr.20130809141000.1991">System requirements
-------------------

Leo requires the `Python`_ and `PyQt_` package.
The `PyEnchant`_ package is optional. 

**Python**: Leo will work on any platform that supports Python 2.6 or
above, including Python 3.0 and above. To install Python, see
http://python.org.

**PyQt**: PyQt provides Leo's widgets. To install PyQt, get the binary
package from: http://www.riverbankcomputing.co.uk/software/pyqt/download
The PyQt version must match your installed Python version. Remember that
Leo requires Python 2.6 or later, or Python 3.0 or later. Now run the
binary PyQt installer.

**PyEnchant**: You must install the PyEnchant package if you want to use
Leo's Spell tab. Download and install the PyEnchant package from
http://pythonhosted.org/pyenchant/download.html There is an executable
installer for Windows users.

</t>
<t tx="ekr.20130809141000.1992">
Leo's HOME directory
--------------------

Python's HOME environment variable specifies Leo's HOME directory.
See http://docs.python.org/lib/os-procinfo.html for details.

Leo puts several files in your HOME/.leo directory:
.leoID.txt, .leoRecentFiles.txt, and myLeoSettings.leo.
There are various fallback directories if there is no home directory.
</t>
<t tx="ekr.20130809141000.1993">
Installing Leo on Linux
-----------------------

You may download Leo's sources in one of three ways, as described at:
http://leoeditor.com/download.html If the sources are zipped, unzip them
into a folder in your home directory, say ~/leo-5.2 (or /usr/bin, etc.)

To gain access to Leo, you have two choices:

A. Add  ~/leo-5.2 to your path.
B. Create alias for Leo.

I prefer using aliases because they allow me to start Leo using Python 2 or 3,
or other distributions, like Anaconda 2 or 3.

See `Running Leo`_ for how to run Leo after installing it.
</t>
<t tx="ekr.20130809141000.1994">
Installing Leo on Windows
--------------------------

Install Python and Qt, as described above.

You may download Leo's sources in one of three ways, as described at:
http://leoeditor.com/download.html If the sources are zipped, unpack them
into a temp folder. You may place the sources anywhere you like, including
Python's *site-packages* folder, for example, C:\Python36\Lib\site-packages.

</t>
<t tx="ekr.20130809141000.1995">
Running Leo
-----------

You can run Leo from a Python interpreter as follows::

    import leo
    leo.run() # runs Leo, opening a new outline or,
    leo.run(fileName=aFileName) # runs Leo, opening the given file name.

Another way to run Leo is as follows::

    cd &lt;path-to-launchLeo.py&gt;
    python launchLeo.py
</t>
<t tx="ekr.20130809141000.1996">
Creating File Associations
--------------------------

**Linux**

The following shell script will allow you to open foo.leo files by typing leo foo::

    #!/bin/sh 
    python &lt;leopath&gt;launchLeo.py $1

where &lt;leopath&gt; is the path to the directory *containing* the leo directory. 

**Windows**

*Important*: Leo's binary Windows installer sets file associations
automatically, so this section is needed only if you are installing Leo
from a .zip file or other sources.

There are two ways of associating .leo files with Leo. The first uses the
Windows control panel, the second, the Windows console.

**Method 1: Using the Windows Control Panel**

The goal is that you want to associate .leo files with the following command::

    "&lt;path to python&gt;\python.exe" "&lt;path to launchLeo.py&gt;\launchLeo.py" "%1"
    
Before Windows 7, you do this with using the Folder Options control panel.
In Windows 7, you do this with the Default Programs control panel.

*Note*: "%1" passes just the file being clicked on, quoted for spaces etc.
The quotation marks are needed to handle file paths containing spaces.

*Warning:* In a batch file, %1 passes just the first command line parameter.
It is logical to expect %* to work for file associations just as in batch
files. Alas, it does not.

**Method 2: Using the Windows Console**

Open a Windows console with administrator privileges, then type::

    ftype LeoFile="&lt;path to python&gt;\pythonw.exe" "&lt;path to launchLeo.py&gt;\launchLeo.py" "%1" %*
    assoc .leo=LeoFile

And put this leo.bat in %PATH%::

    @start /b "Leo" "&lt;path to python&gt;\python.exe" "&lt;path to launchLeo.py&gt;\launchLeo.py" %*
    
You may omit the /b option if you want to create a separate console window for Leo.
</t>
<t tx="ekr.20130809141000.1997">
Adding Leo to Your Path
-----------------------

After you have installed Leo, you should add the location of your leo/core folder to your python path.
One way to do this is adding something like the following to python/Lib/sitecustomize.py:

    import sys
    sys.path.append(r'&lt;path-to-leo&gt;leo\core')

Another way is to append &lt;path-to-leo&gt; to the Windows PYTHONPATH environment variable.
</t>
<t tx="ekr.20130809141000.1998">
Running Leo for the first time
------------------------------

The first time you start Leo, a dialog will ask you for a unique identifier. If
you are using cvs, use your cvs login name. Otherwise your initials will do. Leo
stores this identifier in the file ``.leoID.txt``. Leo attempts to create
``leoID.txt`` in the .leo sub-directory of your home directory, then in Leo's config directory, and
finally in Leo's core directory. You can change this identifier at any time by
editing ``.leoID.txt``.
</t>
<t tx="ekr.20141016105045.2119"># .gitattributes file for Leo distribution

# Commit this file after changing it!

.gitattributes                  export-ignore
.gitignore                      export-ignore

git-manifest.txt                export-ignore
MakeFile                        export-ignore
MANIFEST.in                     export-ignore

leoStandAloneGlobals.py         export-ignore
stand_alone_globals.leo         export-ignore
# setup.cfg                     export-ignore
# setup.py                      export-ignore

# Do not include the top-level docs folder in distributions
docs/                           export-ignore
docs/*                          export-ignore

# Do not include various local files.
leo/core/leoPy.leo              export-ignore
leo/core/ekrLeoPy.leo           export-ignore
leo/test/unittest/.leo_shadow/  export-ignore
</t>
<t tx="ekr.20141117135127.2"></t>
<t tx="ekr.20141117135127.3"></t>
<t tx="ekr.20141118074110.3">https://groups.google.com/forum/#!topic/leo-editor/VvnDYjV4aIk</t>
<t tx="ekr.20150326055410.1">@language rest

1. Search for ##version

    **Note**: The final version in PKG-INFO.TXT must be called 5.x, not 5.x-final.
    See Pep 440: https://www.python.org/dev/peps/pep-0440/

2. Search for copyright

    Latest copyright date: 2019.

    Note: install.txt file embeds a copyright message in the nsi installer.</t>
<t tx="ekr.20150416081546.1"></t>
<t tx="ekr.20150416081546.2">import glob

@others

verbose = False

# extraFiles = ('..\\install','..\\uninstall','test\\unittest\\perfectImport\\formatter.py',)
extraFiles = () # 'test\\test-line-ending.py',)

baseDir = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..'))
n = 0
dirs = ('','src','scripts','plugins',)
# dirs = ('src',)

if 1:
    for dir2 in dirs:
        theDir = g.os_path_abspath(g.os_path_join(baseDir,dir2))
        print theDir
        files1 = glob.glob('%s\*.py' % theDir)
        files2 = glob.glob('%s\*.leo' % theDir)
        files = files1
        files.extend(files2)
        for name in files:
            f = file(name)
            lines = f.readlines()
            # print '%5d %s' % (len(lines),name)
            f.close()
            check(name,lines)
            n += 1

for z in extraFiles:
    name = g.os_path_abspath(g.os_path_join(baseDir,z))
    f = file(name)
    lines = f.readlines()
    # print '%5d %s' % (len(lines),name)
    f.close()
    check(name,lines)
    n += 1

print 'done.  checked %d files' % (n)
</t>
<t tx="ekr.20150416081546.3">def check(name,lines):

    cr = 0 ; nl = 0

    for s in lines:
       for ch in s:
        if ch == '\r': cr += 1
        if ch == '\n': nl += 1

    if verbose or cr &gt; 0:
        print "%55s %s cr's %4s nl's" % (name,cr,nl)
</t>
<t tx="ekr.20150416081546.4">import glob

@others

baseDir = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..'))
n = 0
for dir2 in ('','src','scripts','plugins',):

    theDir = g.os_path_abspath(g.os_path_join(baseDir,dir2))
    print theDir
    files = glob.glob('%s\*.py' % theDir)
    for name in files:
        f = file(name)
        lines = f.readlines()
        # print '%5d %s' % (len(lines),name)
        f.close()
        check(name,lines)
        n += 1

print 'done.  checked %d files' % (n)
</t>
<t tx="ekr.20150416081546.5">def check(name,lines):

    n = 0
    for line in lines:
        n += 1
        i = g.skip_ws(line,0)
        lws = line[0:i]
        if lws:
            if lws.find(' ') &gt; -1 and lws.find('\t') &gt; -1:
                print '%20s %5d %s' % (name,n,repr(line))
</t>
<t tx="ekr.20150416081546.6">import glob
pattern = g.os_path_finalize_join(g.app.loadDir,'..','modes','*.py')
for fn in glob.glob(pattern):
    sfn = g.shortFileName(fn)
    f = open(fn)
    s = f.read()
    f.close()
    if s.find(r'regexp="\\') &gt; -1:
        g.es(sfn)

@ found: Rules indicated are dubious or broken

md.py:
    [ \t]   leadins: 8,20,24,25(?),50,51
    space   leadins: 23,46,49
    [=-]    leadins: 21,47
    [\\_]   leadins: 54,55
    #       leadins: 22
    other   leadins: 7,12,19,53

moin.py:
    [ \t]           rule 3.
    single-quote    rule 6.

erlang.py:  no obvious problem.
lilypond.py:no obvious problem.
perl.py:    no obvious problem.
pl1.py:     no obvious problem.
rest.py:    no obvious problem.
rtf.py:     no obvious problem.
scala.py:   no obvious problem.
yaml.py:    fixed</t>
<t tx="ekr.20150416081546.7">'''
Regularize newlines in ekr-spellpyx.txt.

Replaces sorts the file, removes duplicate lines and ensuring a trailing newline.
'''
fn = g.os_path_finalize_join(g.app.loadDir,'..','..','ekr-spellpyx.txt')
with open(fn) as f:
    s = ''.join(sorted(set(g.splitLines(f.read().strip()+'\n'))))
with open(fn,'w') as f:
    f.write(s)
</t>
<t tx="ekr.20150416081546.8">@first

"""
A simple script to install Leo on Linux.

Contributed by David McNab &lt;david@rebirthing.co.nz&gt;
"""

import commands,os,sys # commands module is for Unix only.

# We must be root to use this script.
if os.getuid() != 0:
    print "You need to run this install script as root"
    sys.exit(1)

# Create /usr/lib/leo and copy all files there.
print "***** Installing Leo to /usr/lib/leo..."
commands.getoutput("mkdir -p /usr/lib/leo")
commands.getoutput("cp -rp * /usr/lib/leo")

# Create user's 'leo' command script into /usr/bin/leo
print "***** Creating Leo startup script -&gt; /usr/bin/leo"
fd = open("/usr/bin/leo", "w")
fd.write("""#!/usr/bin/python
import commands,sys
files = " ".join(sys.argv[1:])
print commands.getoutput("python /usr/lib/leo/leo.py %s" % files)
""")
fd.close()
commands.getoutput("chmod 755 /usr/bin/leo")
print "***** Leo installed successfully - type 'leo filename.leo' to use it."
</t>
<t tx="ekr.20150416081546.9">@language python

# This script must be run from leoPy.leo.

'''Warn if leoProjects.txt or leoToDo.txt contain any clones.'''

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

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

for h in table:
    root = g.findNodeAnywhere(c,h)
    if root:
        for p in root.self_and_subtree():
            nodes += 1
            if p.isCloned():
                clones += 1
                check_clone(c,p,root)
    else:
        g.es_print('not found',h,color='red')
print('done: %s nodes, %s clones' % (nodes,clones))
</t>
<t tx="ekr.20150425135153.1">@language ruby
@tabwidth -2
</t>
<t tx="ekr.20150425135153.2">class Leo &lt; Formula

  homepage "http://leoeditor.com/"
  url "http://sourceforge.net/projects/leo/files/Leo/5.0-final/Leo-5.0-final.zip"
  sha256 "2d742f9825959ba5c7624d1179b9f3065e14e055c90272fbce199f91770de826"
  head "https://github.com/leo-editor/leo-editor", :using =&gt; :git

  depends_on "pyqt"
  depends_on "enchant" =&gt; :recommended
  depends_on :python if MacOS.version &lt;= :snow_leopard

  def install
    (lib+"python2.7/site-packages").install "leo"
    bin.install "launchLeo.py" =&gt; "leo" 
  end

  test do
    system bin/"python", "-c", "import leo"
  end
end
</t>
<t tx="ekr.20151227063335.1">leo.exe contains everything you need to run Leo on Windows without
installing *anything* else. It contains all needed libraries, including
Python itself, PyQt, pylint and other packages. It also contains many data
files, including Leo's source code and various .leo files.

Notes:

1. leo.exe was created by PyInstaller: http://pythonhosted.org/PyInstaller

2. Before Leo starts, PyInstaller unpacks all libraries and data files to a
   temp folder: ~\AppData\Local\Temp\_MEInnn. As a result, starting leo.exe
   is slower than usual.

3. *Warning*: You can open Leo files from the "Files:Open Leo File" menu,
   but these files will be in the temp folder. They will be *destroyed*
   when you exit leo.exe. If you want to do real work with Leo you must
   create .leo files in a permanent folder on your machine.
</t>
<t tx="ekr.20160510090441.1">@language nsi

;#version # No longer used
!define version         "5.9"

!include MUI2.nsh
!include nsDialogs.nsh
!include LogicLib.nsh

; Globals.
Var PythonDirectory
    ; Directory containing Python.exe
Var PythonExe
    ; "python.exe" or "pythonw.exe"
Var PythonExecutable
    ; $PythonDirectory/$PythonExe

!define app_icon        "leo\Icons\LeoApp.ico"
!define doc_icon        "leo\Icons\LeoDoc.ico"
!define ext             ".leo"
!define leo_hklm        "SOFTWARE\EKR\Leo"
!define license         "LICENSE"
!define name            "Leo"
!define publisher       "Edward K. Ream"
!define site            "http://leoeditor.com/"
!define target_file     "LeoAssoc.exe"
!define uninst_key      "Software\Microsoft\Windows\CurrentVersion\Uninstall\leo"

; Locations
Name "Leo Associations"
OutFile "LeoAssoc.exe"
InstallDir "$PROGRAMFILES\Leo-${version}"

; Icons
!define MUI_ICON "${app_icon}"

&lt;&lt; assoc prolog &gt;&gt;
&lt;&lt; assoc pages &gt;&gt;
@others
; Language should follow pages.
!insertmacro MUI_LANGUAGE "English"
</t>
<t tx="ekr.20160510090943.1">

!addincludedir C:\leo.repo\leo-editor\leo\dist

; Boilerplate
SetCompressor bzip2
Caption "Leo File Associations Installer"
AutoCloseWindow false 
SilentInstall normal
CRCCheck on
SetCompress auto
SetDatablockOptimize on
WindowIcon on
ShowInstDetails show
ShowUnInstDetails show
</t>
<t tx="ekr.20160510091130.1">@language nsi

Var StartMenuFolder

!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE       ${license}
!insertmacro MUI_PAGE_COMPONENTS

; Define these here so the back button works.
!define MUI_PAGE_HEADER_TEXT "Choose Installed Location"
!define MUI_PAGE_HEADER_SUBTEXT "Choose the folder in which Leo has been installed."
!define MUI_DIRECTORYPAGE_TEXT_TOP "Setup installs file associations for Leo in the Windows registry."
!define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Select the top-level leo-editor Folder"
!insertmacro MUI_PAGE_DIRECTORY

; It's so easy: just set these *before* creating another directory page!
!define MUI_PAGE_HEADER_TEXT "Choose Python Location"
!define MUI_PAGE_HEADER_SUBTEXT "Select the top-level Python directory"
!define MUI_DIRECTORYPAGE_TEXT_TOP "Choose the top-level Python folder."
!define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Python Folder"
!define MUI_DIRECTORYPAGE_VARIABLE $PythonDirectory
!insertmacro MUI_PAGE_DIRECTORY

!insertmacro MUI_PAGE_STARTMENU "Application" $StartMenuFolder
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH

; ----- uninstaller pages -----

!insertmacro MUI_UNPAGE_WELCOME
!insertmacro MUI_UNPAGE_DIRECTORY
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
</t>
<t tx="ekr.20160510093344.1">; The name of this section must be "Leo".
Section "LeoAssoc" SEC01
    ; This section is required, but does not need any contents.
    ; It must have the name of the .exe file.
SectionEnd
</t>
<t tx="ekr.20160510093411.1">Section "${ext} File Association" SEC02
    MessageBox MB_YESNO "Launch Leo in Python console? (recommended for Python 3)" IDYES true IDNO false
    true:
        StrCpy $PythonExe "python.exe"
        goto next
    false:
        StrCpy $PythonExe "pythonw.exe"
    next:
    StrCpy $PythonExecutable "$PythonDirectory\$PythonExe"
        ; Set for all other sections.
    SectionIn 1 2 3 4
    WriteRegStr HKCR "${ext}" "" "Leo File"
    WriteRegStr HKCR "LeoFile" "" "Leo File"
    WriteRegStr HKCR "LeoFile\shell" "" "open"
    ; The single quotes below appear to be required.
    WriteRegStr HKCR "LeoFile\DefaultIcon" "" '"$INSTDIR\${app_icon}"'
        ; https://github.com/leo-editor/leo-editor/issues/24
    WriteRegStr HKCR "LeoFile\shell\open\command" "" '"$PythonExecutable" "$INSTDIR\launchLeo.py %*"'
SectionEnd
</t>
<t tx="ekr.20160510093822.1">
Section "Leo Desktop Shortcut" SEC03
  ; This sets the "Start in folder" box!!!"
  SetOutPath "$INSTDIR\leo"
  ;This is **tricky**.  We need single quotes to handle paths containing spaces.
  ;Add single quotes around PythonExecutable and launchLeo.py args, but *not* the app_icon arg.
  CreateShortCut "$DESKTOP\Leo.lnk" '"$PythonExecutable"' '"$INSTDIR\launchLeo.py"' "$INSTDIR\${app_icon}"
SectionEnd
</t>
<t tx="ekr.20160510093859.1">
Section "Leo Start Menu" SEC04
  ; This is **tricky**.
  ; We need single quotes to handle paths containing spaces.
  ; Add single quotes around PythonExecutable and launchLeo.py args,
  ; but *not* the app_icon arg.
  CreateShortCut "$SMPROGRAMS\Leo\Leo.lnk" '"$PythonExecutable"' '"$INSTDIR\launchLeo.py"' "$INSTDIR\${app_icon}"
  CreateShortCut "$SMPROGRAMS\Leo\Uninstall.lnk" '"$INSTDIR\uninst.exe"'
SectionEnd
</t>
<t tx="ekr.20160510095711.1">
Section -Post
  WriteRegStr HKLM ${leo_hklm} "" "$INSTDIR"
  WriteUninstaller "$INSTDIR\uninst.exe"
  WriteRegStr HKLM "${uninst_key}" "DisplayName" "Leo File Associations (remove only)"
  WriteRegStr HKLM "${uninst_key}" "UninstallString" "$INSTDIR\uninst.exe"
  WriteRegStr HKLM "${uninst_key}" "DisplayVersion" "Leo File Associations"
  WriteRegStr HKLM "${uninst_key}" "URLInfoAbout" "${site}"
  WriteRegStr HKLM "${uninst_key}" "Publisher" "${publisher}"
SectionEnd
</t>
<t tx="ekr.20160510095724.1">
Section Uninstall
    DeleteRegKey HKLM "${leo_hklm}"
    DeleteRegKey HKCR "${ext}"
    DeleteRegKey HKCR "LeoFile"
    ; Remove links.
    Delete "$SMPROGRAMS\Leo\Uninstall.lnk"
    Delete "$SMPROGRAMS\Leo.lnk"
    Delete "$DESKTOP\Leo.lnk"
    DeleteRegKey HKLM "${uninst_key}" 
    SetAutoClose false

SectionEnd ; end Uninstall section
</t>
<t tx="ekr.20161015091350.1">- Make sure no distributed .leo file contains xml-stylesheet elements.
  Run @button check .leo files in leo-dist.leo.
- Make sure Leo looks good without myLeoSettings.leo.
- Run the "check-bindings" button in leoSettings.leo.
- Run all unit tests with *both* Python 2 and 3.
- Run ll -a with *both* Python 2 and 3.</t>
<t tx="ekr.20161015091353.1">- Regenerate all .html files.
- Copy files to web, including leo/doc/html/index.html
  Do **not** copy searchindex.js.
</t>
<t tx="ekr.20161015091353.2">LeoDocs.leo:
- Make sure copyright dates are correct.
- Update the "last updated" text in index.html.
- Update version numbers in html/conf.py
- Update the release notes.
- Remove @language rest where possible in new notes.
- Create new "what's new" section.
- Remove top-level clones.
- Spell check entire file.
- Copy release notes to leoDist.leo.
- Copy release notes to LeoReleaseNotes.leo
- Select the readme node.

LeoDist.leo:
- Make sure copyright dates are correct.
- Update version numbers: search leoDist.leo for ##version.
- Update readme.md.
- Check readme.md spelling.
- Check 'PKG-INFO.TXT'

leoVersion.py:
- Update version constant.

LeoPyRef.leo and LeoPluginsRef.leo:
- Regenerate from corresponding local file.
- Remove top-level clones.
</t>
<t tx="ekr.20161015091353.3">- Update the *GitHub* release at https://github.com/leo-editor/leo-editor/releases
   This must be done *soon* after the release's actual commit.
   There is a "Draft New Release" button at the top-right of the page.

- Update version number on Leo's wikipedia site:
  http://en.wikipedia.org/wiki/Leo_%28editor%29
  - Edit with the 'Edit this page' *tab* (not a link)
  - Update version number on web site.

- Announce to SourceForge:  http://sourceforge.net/projects/leo/
   **Markdown accepted, so paste release notes in LeoDocs.leo.**.

- Announce to leo-editor: **Paste source-forge announcement**.

- Announce to Python-announce-list using email:
   mailto:python-announce-list@python.org
   **Paste source-forge or leo-editor announcement**.

  - Check it by visiting the archive:
  https://mail.python.org/pipermail/python-announce-list/

- Register Leo at https://pypi.python.org/pypi/leo

- My blog: http://edreamleo.blogspot.com/
  **Paste source-forge or leo-editor announcement**.
  **To get HTML, just use html tab**.
</t>
<t tx="ekr.20161015092224.1">Run make-leo.
- Commit all files before running make-leo.
- Run make-leo button in leoDist.leo.
- Commit any changed files.
- If any files change, rerun make-leo.

Create the executable installer:
- Double-click leo.nsi. (Run with makeNSIS.exe)

Run pyinstaller on Windows:
- Delete leo-editor/dist and leo-editor/build folders.
- Run [a32]&gt; pyinstaller --clean --win-private-assemblies launchLeo-unified.spec
- Test a *copy* of the result so .pyo files are not added to the package)
- Rename leo/dist/LeoAppFolder to LeoApp (fixes windows naming problem).
- Compress the LeoApp folder to Leo_&lt;version&gt;_Win.zip.
    
Run pyinstaller on Linux:
- (optional) Delete leo-editor/dist and leo-editor/build folders.
- Run pyinstaller2 launchLeo-unified.spec
- Test a *copy* of the result so .pyo files are not added to the package)
- Compress the folder to Leo_&lt;version&gt;_Linux_64_bit.tar.gz.
</t>
<t tx="ekr.20161017094235.10">
Section Uninstall

    DeleteRegKey HKLM "${leo_hklm}"
    DeleteRegKey HKCR "${ext}"
    DeleteRegKey HKCR "${name}File"
    ; Safely removes all files and directories, including $INSTDIR.
    ; The make-leo button creates nsi-uninstall-files.txt.
    !include nsi-uninstall-files.txt
    ; Remove links.
    Delete "$SMPROGRAMS\${name}\Uninstall.lnk"
    Delete "$SMPROGRAMS\${name}.lnk"
    ; RMDir  "$SMPROGRAMS\${name}-${version}"
    RMDir  "$SMPROGRAMS\${name}"
    Delete "$DESKTOP\${name}.lnk"
    DeleteRegKey HKLM "${uninst_key}" 
    SetAutoClose false

SectionEnd ; end Uninstall section
</t>
<t tx="ekr.20161017094235.2">; Globals.
Var PythonDirectory
    ; Directory containing Pythonw.exe
    ; Set by onInit.  May be set in Python Directory page.

!define PythonExecutable "$PythonDirectory\pythonw.exe"
    ;;; Always use pythonw.exe here.
    ;;; To debug, set the target to python.exe in the desktop icon properties.

!addincludedir C:\leo.repo\leo-editor\leo\dist

; Boilerplate
SetCompressor bzip2
Caption "${name}-${version} Installer"
AutoCloseWindow false 
SilentInstall normal
CRCCheck on
SetCompress auto
SetDatablockOptimize on
WindowIcon on
ShowInstDetails show
ShowUnInstDetails show

; Locations
Name "${name}"
OutFile "${target_file}"
InstallDir "$PROGRAMFILES\${name}-${version}"

; Icons
!define MUI_ICON "${app_icon}"
</t>
<t tx="ekr.20161017094235.3">@language nsi

Var StartMenuFolder

; Define the TEXT_TOP for both the MUI_PAGE_DIRECTORY pages.
; "${s1a} ${s2} ${s3}" is the TEXT_TOP for the Install Location page.
; "${s2b} ${s2} ${s3}" is the TEXT_TOP for the Choose Python Folder page.
!define s1a "Setup will install ${name} in the following folder."
!define s1b "Setup will use the following folder as the Python location."
!define s2 "To install in a different folder, click Browse and select another folder."
!define s3 "Click next to continue."

!insertmacro MUI_PAGE_WELCOME
!insertmacro MUI_PAGE_LICENSE       ${license}
!insertmacro MUI_PAGE_COMPONENTS

; These are the defaults, but defined them here so the back button works.
!define MUI_PAGE_HEADER_TEXT "Choose Install Location"
!define MUI_PAGE_HEADER_SUBTEXT "Choose the folder in which to install ${name}"
!define MUI_DIRECTORYPAGE_TEXT_TOP "${s1a} ${s2} ${s3}"
!define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Destination Folder"
!insertmacro MUI_PAGE_DIRECTORY

; It's so easy: just set these *before* creating another directory page!
!define MUI_PAGE_HEADER_TEXT "Choose Python Location"
!define MUI_PAGE_HEADER_SUBTEXT "Select the top-level Python directory"
!define MUI_DIRECTORYPAGE_TEXT_TOP "${s1b} ${s2} ${s3}"
!define MUI_DIRECTORYPAGE_TEXT_DESTINATION "Python Folder"
!define MUI_DIRECTORYPAGE_VARIABLE $PythonDirectory
!insertmacro MUI_PAGE_DIRECTORY

!insertmacro MUI_PAGE_STARTMENU     "Application" $StartMenuFolder
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH

; ----- uninstaller pages -----

!insertmacro MUI_UNPAGE_WELCOME
; !insertmacro MUI_UNPAGE_LICENSE   ${license}
; !insertmacro MUI_UNPAGE_CONFIRM
; !insertmacro MUI_UNPAGE_COMPONENTS ; doesn't actually list components.
!insertmacro MUI_UNPAGE_DIRECTORY
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_FINISH
</t>
<t tx="ekr.20161017094235.4">
; Set PythonDirectory to the top-level Python path.
; For now, prefer Python 2.x to Python 3.x.
Function .onInit
    ;try27:
        SetRegView 64
        ReadRegStr $9 HKLM Software\Python\PythonCore\2.7\InstallPath ""
        StrCmp $9 "" try26 ok
    try26:
        ReadRegStr $9 HKLM SOFTWARE\Python\PythonCore\2.6\InstallPath ""
        StrCmp $9 "" try35 ok
    try35:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.5\InstallPath ""
        StrCmp $9 "" try34 ok
    try34:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.4\InstallPath ""
        StrCmp $9 "" try33 ok
    try33:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.3\InstallPath ""
        StrCmp $9 "" try32 ok
    try32:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.2\InstallPath ""
        StrCmp $9 "" try31 ok
    try31:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.1\InstallPath ""
        StrCmp $9 "" try30 ok
    try30:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.0\InstallPath ""
        StrCmp $9 "" tryReg32 ok
    ; Entries not found in 64-bit registry: try 32-bit registry...
    tryReg32:
        SetRegView 32
        ReadRegStr $9 HKLM Software\Python\PythonCore\2.7\InstallPath ""
        StrCmp $9 "" try26_32 ok
    try26_32:
        ReadRegStr $9 HKLM Software\Python\PythonCore\2.6\InstallPath ""
        StrCmp $9 "" try35_32 ok
    try35_32:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.5\InstallPath ""
        StrCmp $9 "" try34_32 ok
    try34_32:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.4\InstallPath ""
        StrCmp $9 "" try33_32 ok
    try33_32:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.3\InstallPath ""
        StrCmp $9 "" try32_32 ok
    try32_32:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.2\InstallPath ""
        StrCmp $9 "" try31_32 ok
    try31_32:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.1\InstallPath ""
        StrCmp $9 "" try30_32 ok
    try30_32:
        ReadRegStr $9 HKLM Software\Python\PythonCore\3.0\InstallPath ""
        StrCmp $9 "" oops ok
    oops:
        MessageBox MB_OK "Python not found"
        StrCpy $PythonDirectory ""
        Goto done
    ok:
        StrCpy $PythonDirectory $9
    done:
FunctionEnd ; End .onInit
</t>
<t tx="ekr.20161017094235.5">
; The name of this section must be "Leo".
Section "Leo" SEC01
    ; Add all files and directories.
    ; The make-leo button creates nsi-install-files.txt.
    !include nsi-install-files.txt
SectionEnd
</t>
<t tx="ekr.20161017094235.6">
Section "${ext} File Association" SEC02
    SectionIn 1 2 3 4
    WriteRegStr HKCR "${ext}" "" "${name}File"
    WriteRegStr HKCR "${name}File" "" "${name} File"
    WriteRegStr HKCR "${name}File\shell" "" "open"
    ; The single quotes below appear to be required.
    WriteRegStr HKCR "${name}File\DefaultIcon" "" '"$INSTDIR\${app_icon}"'
    ; https://github.com/leo-editor/leo-editor/issues/24
    WriteRegStr HKCR "${name}File\shell\open\command" "" '"${PythonExecutable}" "$INSTDIR\launchLeo.py %*"'
SectionEnd
</t>
<t tx="ekr.20161017094235.7">
Section "${name} Desktop Shortcut" SEC03
  ; This sets the "Start in folder" box!!!"
  SetOutPath "$INSTDIR\leo"
  ;;; This is **tricky**.  We need single quotes to handle paths containing spaces.
  ;;; Add single quotes around PythonExecutable and launchLeo.py args, but *not* the app_icon arg.
  CreateShortCut "$DESKTOP\${name}.lnk" '"${PythonExecutable}"' '"$INSTDIR\launchLeo.py"' "$INSTDIR\${app_icon}"
SectionEnd
</t>
<t tx="ekr.20161017094235.8">
Section "${name} Start Menu" SEC04
  CreateDirectory "$SMPROGRAMS\${name}"
  ;;; This is **tricky**.  We need single quotes to handle paths containing spaces.
  ;;; Add single quotes around PythonExecutable and launchLeo.py args, but *not* the app_icon arg.
  CreateShortCut "$SMPROGRAMS\${name}\${name}.lnk" '"${PythonExecutable}"' '"$INSTDIR\launchLeo.py"' "$INSTDIR\${app_icon}"
  CreateShortCut "$SMPROGRAMS\${name}\Uninstall.lnk" '"$INSTDIR\uninst.exe"'
SectionEnd
</t>
<t tx="ekr.20161017094235.9">
Section -Post
  WriteRegStr HKLM ${leo_hklm} "" "$INSTDIR"
  WriteUninstaller "$INSTDIR\uninst.exe"
  WriteRegStr HKLM "${uninst_key}" "DisplayName" "${name}-${version} (remove only)"
  WriteRegStr HKLM "${uninst_key}" "UninstallString" "$INSTDIR\uninst.exe"
  WriteRegStr HKLM "${uninst_key}" "DisplayVersion" "${version}"
  WriteRegStr HKLM "${uninst_key}" "URLInfoAbout" "${site}"
  WriteRegStr HKLM "${uninst_key}" "Publisher" "${publisher}"
SectionEnd
</t>
<t tx="ekr.20161017094430.1">;;; This doesn't work.
;;; !addincludedir C:\leo.repo\leo-editor\leo\dist

!include MUI2.nsh
!include nsDialogs.nsh
!include LogicLib.nsh

;#version
!define version         "5.9"

; These are *not* Python strings--backslashes are fine.

!define app_icon        "leo\Icons\LeoApp.ico"
!define doc_icon        "leo\Icons\LeoDoc.ico"
; This works, but the icon is too small.
;!define icon            "C:\leo.repo\trunk\leo\Icons\SplashScreen.ico"
!define ext             ".leo"
!define leo_hklm        "SOFTWARE\EKR\Leo"
!define license         "LICENSE"
!define name            "Leo"
!define publisher       "Edward K. Ream"
!define site            "http://leoeditor.com/"
!define target_file     "LeoSetup-${version}.exe"
!define uninst_key      "Software\Microsoft\Windows\CurrentVersion\Uninstall\leo"
</t>
<t tx="ekr.20161020040946.1">Test files in installed folder:

- Run all unit tests in the installed folder, with the installed Leo.

- Make sure the following open without errors:
    - leoPlugins.leo
    - leoPy.leo
    - LeoDocs.leo
</t>
<t tx="ekr.20161020041000.1">- Create a full (annotated) tag:
  - Do not use the -f option.
  - Make sure the tag does not conflict with the release branch.
    Release *branches* should end with "-rel"
    Tags should start with "v".
    Tags should *not* end with "-rel"

git tag -a v5.9.x -m "Added v5.9.x tag"
git push --follow-tags
</t>
<t tx="ekr.20161024113526.1">@language rest
@wrap

See LeoDocs.leo for all previous release notes.</t>
<t tx="ekr.20161024113542.1">@language rest
@wrap

https://github.com/leo-editor/leo-editor/issues/106

How to Create and Maintain a Tap
https://github.com/Homebrew/brew/blob/master/docs/How-to-Create-and-Maintain-a-Tap.md

How To Open a Homebrew Pull Request (and get it merged)
https://github.com/Homebrew/brew/blob/master/docs/How-To-Open-a-Homebrew-Pull-Request-(and-get-it-merged).md
</t>
<t tx="ekr.20161024113553.1">From: Winn Dixie incredible0n3@gmail.com

Would be stellar to have a brew install leo. http://brew.sh/

Homebrew formulae are simple Ruby scripts::

require "formula"

class Wget &lt; Formula
  homepage "http://www.gnu.org/software/wget/"
  url "http://ftp.gnu.org/gnu/wget/wget-1.15.tar.gz"
  sha1 "f3c925f19dfe5ed386daae4f339175c108c50574"

  def install
    system "./configure", "--prefix=#{prefix}"
    system "make", "install"
  end
end

To install homebrew, paste this in a terminal::

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

The script explains what it will do and then pauses before it does it.
</t>
<t tx="ekr.20161024113810.1">https://github.com/ludwigschwardt

I've made a first draft of this many moons ago (1 Oct 2013, to be exact :-)).

It still installs Leo 4.10 final. That is if it still works, as I haven't tested it in a while...

You can try it out like this from my tap:

brew tap ska-sa/tap
brew install leo

You are more than welcome to copy it from [here](https://github.com/ska-sa/homebrew-tap/blob/master/leo.rb) and tinker with it.
</t>
<t tx="ekr.20161024114150.1">Whew. Added this pull request: https://github.com/Homebrew/legacy-homebrew/pull/38980
We'll see what happens...

Here is the updated leo.rb file that passes brew audit --strict Leo:

@language ruby

class Leo &lt; Formula
  homepage "http://leoeditor.com/"
  url "https://downloads.sourceforge.net/projects/leo/files/Leo/5.1-final/Leo-5.1-final.zip"
  sha256 "2d742f9825959ba5c7624d1179b9f3065e14e055c90272fbce199f91770de826"

  depends_on "pyqt"
  depends_on "enchant" =&gt; :recommended

  def install
    # Obtain information on Python installation
    python_xy = "python" + `%x(python -c "import sys;print(sys.version[:3])")`.chomp
    python_site_packages = lib + "#{python_xy}/site-packages"
    python_site_packages.install "leo"
    bin.install ["launchLeo.py", "profileLeo.py"]
    ln_s "#{bin}/launchLeo.py", "#{bin}/leo"
  end

  test do
    # Create, run in and delete a temporary directory.
    if system "python" "-c" "import leo"
      onoe "Leo FAILED"
    else
      ohai "Leo OK"
    end
  end
end

@language rest

It took quite awhile to grok what was going on. Here are my notes:

brew update
  # updates formulae.
brew doctor
# Clone homebrew into ~/leo.repo/homebrew
cd ~/leo.repo
git clone https://github.com/leo-editor/homebrew.git
brew create http://sourceforge.net/projects/leo/files/Leo/5.1-final/Leo-5.1-final.zip
    # This Downloaded the file and opened vim:
    # ==&gt; Downloading http://sourceforge.net/projects/leo/files/Leo/5.1-final/Leo-5.1-
    # The second time I did this I simply replaced the file with the proper leo.rb.
brew audit --strict Leo
  # Caught various problems.
cd homebrew
  # Not part of the instructions.
git checkout -b Leo
  # Switched to a new branch 'Homebrew-Leo'
git add Library/Formula/leo.rb
  # Not part of the instructions.
git commit Library/Formula/leo.rb ### &amp;&amp; git push
git push
  # (within SourceTree) using my normal GitHub username and password.

</t>
<t tx="ekr.20161024115114.1">Here is the latest leo.rb:

@language ruby

class Leo &lt; Formula
  homepage "http://leoeditor.com/"
  url "http://sourceforge.net/projects/leo/files/Leo/5.0-final/Leo-5.0-final.zip"
  sha256 "2d742f9825959ba5c7624d1179b9f3065e14e055c90272fbce199f91770de826"
  head "https://github.com/leo-editor/leo-editor", :using =&gt; :git

  depends_on "pyqt"
  depends_on "enchant" =&gt; :recommended
  depends_on :python if MacOS.version &lt;= :snow_leopard

  def install
    (lib+"python2.7/site-packages").install "leo"
    bin.install "launchLeo.py" =&gt; "leo"
  end

  test do
    system bin/"python", "-c", "import leo"
  end
end

@language rest


This passes the following::

    brew audit --strict Leo
    brew install --verbose --debug Leo

However, after:

    brew uninstall Leo
    brew install Leo

I get the following:

    sh: -c: line 0: syntax error near unexpected token `python'
    sh: -c: line 0: `%x(python -c "import sys;print(sys.version[:3])")'

This looks like an old version of leo.rb is being used, but a thorough search shows no such file. Any help would be appreciated.</t>
<t tx="ekr.20161024115257.1">*Note*: Brew create now computes the hash automatically.

http://stackoverflow.com/questions/32673943/how-to-update-homebrew-sha256

After editing the formula, you can run:

    brew fetch your-formula --build-from-source

to fetch the tarball and display the new checksum.

If you've already downloaded the tarball somewhere, you can calculate the hash with:

    openssl sha256 &lt; some_tarball.tar.gz

or:

    shasum -a 256 some_tarball.tar.gz
</t>
<t tx="ekr.20161025091538.1">Here, I'd like to add to the previous post, to show the big picture. Creating a pull request is actually pretty simple, as the homebrew readme suggests:

1. Fork Homebrew.
2. brew create http://example.com/foo-0.1.tar.gz
3. git checkout -b foo
4. git commit Library/Formula/foo.rb &amp;&amp; git push
5. Pull Request: links to https://github.com/Homebrew/homebrew/pulls

This kind of abbreviated list strikes a good balance for those who know the big picture. But for those who don't, a few more details would be helpful:

Directories

The instructions don't mention directories, which was confusing:

    I forked homebrew in ~/leo.repo, my standard place for repos. This created all kinds of stuff in /usr/local, but those places don't matter. Everything actually should happen in ~/leo.repo/homebrew. It took me awhile to realize I could ignore everything in /usr/local.

    Steps 2, 3 and 4 happened, iirc, in ~/leo.repo or in ~/leo.repo/homebrew, which, in retrospect, makes sense, but did not at the time.

Pushing &amp; the pull request

The following may be blindingly obvious to those with more experience with git, but this was the first time I had used git in a more collaborative way:

    The push happens in my fork, so I can (must) use my own GitHub credentials to do the push. I'm simply modifying my own fork.
    The link in the step 5, pull request, isn't really helpful. Instead, after the push, a button in my fork of homebrew appeared called something like "submit pull request". I pressed the button, added a few comments, and off we went. Next time, I'll add a link to Leo's home page. The email link was redundant, but it may have encouraged the helpful comments that I received...

Changing the pull request

The first pull request had problems, so I assume it won't be pulled. I also assume that I can simply make the changes in leo.rb in my already existing branch, push them, and then issue a new pull request.

Summary: This is actually a straightforward process, but nobody knows better than I that describing a straightforward process is anything but straightforward!
</t>
<t tx="ekr.20161025091621.1">he Formula Cookbook, https://github.com/Homebrew/brew/blob/master/docs/Formula-Cookbook.md, is a must-read, especially the Python-related parts!)

These instructions for contributing to Homebrew (specifically calling brew commands) assume that you are actually *using* Homebrew, and normally the Homebrew repo then lives in /usr/local. I normally work in that repo and would then copy the formula elsewhere for pushing (typically to my tap repo).

You don't have to issue a new pull request. Just add your changes to the same branch and push them, and they will remain associated with the same pull request. This is a great feature of the PR: you can commit and discuss until everyone is happy and the PR then gets accepted.

I would rename the pull request "leo 5.1 (new formula)". :-)
</t>
<t tx="ekr.20161025114433.1"></t>
<t tx="ekr.20161025114444.1">@language ruby

class LeoEditor &lt; Formula
  desc "The Leo IDE/Outliner/PIM"
  homepage "http://leoeditor.com/"
  url "https://github.com/leo-editor/leo-editor/archive/5.4.1.tar.gz"
  sha256 "2cf0f598aa46e8ced6dd7da0229157e7b523704d0a03604a4da14b715c0a232f"

  depends_on :python if MacOS.version &lt;= :snow_leopard
  depends_on "pyqt"
  depends_on "enchant" =&gt; :recommended

  def install
    bin.install "leo"
    bin.install ["launchLeo.py", "profileLeo.py"]
    ln_s "#{bin}/launchLeo.py", "#{bin}/leo"
  end

  test do
    if system "python", "-c", "import", "leo"
      onoe "Leo FAILED"
    else
      ohai "Leo OK"
    end
  end
end</t>
<t tx="ekr.20170316104916.1">- Create Release on SourceForge: http://sourceforge.net/projects/leo/
    - Make sure to upload readme.md and Readme-quick-install.txt.
</t>
<t tx="ekr.20170911061827.1">'''Make sure no distributed .leo file contains xml-stylesheet elements.'''
# g.cls()
&lt;&lt; define files &gt;&gt;
for fn in files:
    path = g.os_path_finalize_join(g.app.loadDir, '..', fn)
    if g.os_path_exists(path):
        with open(path, 'rb') as f:
            s = f.read()
        s = g.toUnicode(s)
        if s.find('&lt;xml-stylesheet') &gt; -1:
            g.es_print('contains xml-stylesheet element: %s' % (path))
    else:
        g.es_print('does not exist: %s' % path)
g.es_print('done')
</t>
<t tx="ekr.20170911062209.1">files = (
    'config/exampleSettings.leo',
    'config/leoSettings.leo',
    'core/leoPyRef.leo',
    'dist/leoDist.leo',
    'doc/LeoReleaseNotes.leo',
    'doc/cheatSheet.leo',
    'doc/default_workbook.leo',
    'doc/leoDocs.leo',
    'doc/leoSlideShows.leo',
    'doc/quickstart.leo',
    'external/leo2html.leo',
    'plugins/leoGuiPluginsRef.leo',
    'plugins/leoPluginsRef.leo',
    'scripts/scripts.leo',
    'test/test.leo',
)</t>
<t tx="ekr.20180301115911.1">- git checkout {release-tag}
- python setup.py bdist_wheel
- twine upload dist/leo*.whl
</t>
<t tx="ekr.20180405171433.1">@language rest

Overview:

1. Do as much work as possible in "devel".
2. Update leoVersion.py *after* creating -rel branch.
</t>
<t tx="ekr.20180405171433.2">LeoDocs.leo:
- Make sure copyright dates are correct.
- Update the "last updated" text in index.html.
- Update version numbers in html/conf.py
- Update the release notes.
- Remove @language rest where possible in new notes.
- Create new "what's new" section.
- Remove top-level clones.
- Spell check entire file.
- Copy release notes to leoDist.leo.
- Copy release notes to LeoReleaseNotes.leo

LeoDist.leo:
- Make sure copyright dates are correct.
- Update readme.md.
- Check readme.md spelling.
- Check 'PKG-INFO.TXT'

LeoPyRef.leo and LeoPluginsRef.leo:
- Regenerate from corresponding local file.
- Remove top-level clones.
</t>
<t tx="ekr.20180405171433.3">- Regenerate all .html files.
- Copy files to web, including leo/doc/html/index.html
  Do **not** copy searchindex.js.
</t>
<t tx="ekr.20180405171433.4">- Make sure no distributed .leo file contains xml-stylesheet elements.
  Run @button check .leo files in leo-dist.leo.
- Make sure Leo looks good without myLeoSettings.leo.
- Run the "check-bindings" button in leoSettings.leo.
- Run all unit tests with Python 3.
- Run ll -a with with Python 3.</t>
<t tx="ekr.20180405171433.7">Merge the -rel branch into master.
- Run all unit tests.
- Run pylint on all files.

Create a git tag **last**

- Create a full (annotated) tag:
  - Do not use the -f option.
  - Make sure the tag does not conflict with the release branch.
    Release *branches* should end with "-rel"
    Tags should start with "v".
    Tags should *not* end with "-rel"

git tag -a v5.9.x -m "Added v5.9.x tag"
git push --follow-tags
</t>
<t tx="ekr.20180828095749.1">git checkout -b x.y-final-rel
git push origin x.y-final-rel
</t>
<t tx="ekr.20180828095843.1">leoVersion.py:
- Update version constant.
</t>
<t tx="ekr.20181001112218.1">Matt: After merge create dev tag that matches static version added to leoversion.py 4 steps ago.  
    #static version = '6.0-b2-devel'

git checkout devel
git tag -a v6.0-b2-dev -m "Added v6.0-b2-dev tag"
git push --follow-tags
</t>
<t tx="ekr.20190429113053.1"># Commit all files before running this script.

'''
This script is OBSOLETE. It used NSIS to create a full distribution to SourceForge.

Also, pyinstaller is no longer used: See the obsolete SourceForce distribution checklist.

Make these files in the top-level folder::

    git-manifest.txt
    nsi-install-files.txt
    nsi-uninstall-files.txt
    leo.zip.
'''

version = '5.7 final' ##version
&lt;&lt; includes &gt;&gt;
&lt;&lt; define global paths and file names &gt;&gt;

@others

LeoMaker().run()
g.es_print('done') # '@button make-leo done')
</t>
<t tx="ekr.20190429113053.10">def create_install_files(self,dirs,dirDict,filesDict):
    '''Create leo/dist/nsi-install-files.txt'''
    global install_fn,rootDir
    put = self.put
    self.f = self.openFile(install_fn)
    if not self.f: return
    # Top level
    theDir = '**top'
    put('\n')
    put('; top-level\n')
    put('SetOutPath "$INSTDIR"\n')
    put('SetOverwrite ifnewer\n')
    aList = dirDict.get(theDir,[])
    for fn in aList:
        put('File "%s"\n' % fn)
    for theDir in dirs:
        if theDir != '**top':
            aList = dirDict.get(theDir,[])
            if aList:
                theDir2 = theDir.replace('/','\\').rstrip('\\')
                put('\n')
                put('SetOutPath $INSTDIR\\%s\n' % theDir2)
                for fn in aList:
                    # Fix bug 425369: quote file names.
                    put('File "%s\\%s\\%s"\n' % (
                        rootDir,theDir2,fn))
    self.f.close()
</t>
<t tx="ekr.20190429113053.11">def create_uninstall_files(self,dirs,dirDict,filesDict):
    '''Create leo/dist/nsi-uninstall-files.txt'''
    def clean(s):
        return s.replace('/','\\')
    put = self.put
    self.f = self.openFile(uninstall_fn)
    if not self.f: return
    # Part 1: Delete top-level files.
    put('\n')
    put('; Uninstall files...\n\n')
    put('SetOutPath $Temp\n')
    # Get the list of top-level files.
    aList = dirDict.get('**top',[])
    # Add some special cases:
    for fn in ('*.pyo','*.pyc',
        'uninst.exe',
        # 'setup.py',
            # setup.py is now allowed at the top level.
        'git-manifest.txt'
    ):
        if fn not in aList:
            aList.append(fn)
    for fn in aList:
        # Always delete individual files.
        put('Delete "$INSTDIR\\%s"\n' % fn)
    if 1:
        # Just delete the leo folder with /r option.
        # This should be completely safe.
        put('RMDir /r "$INSTDIR\\leo"\n')
    else:
        # Part 2: Delete files in lower directories.
        for theDir in dirs:
            if theDir:
                dir2 = clean(theDir)
                aList = dirDict.get(theDir,[])
                if aList:
                    put('\n')
                    put('Delete "$INSTDIR\\%s\\*.pyc"\n' % (dir2))
                    put('Delete "$INSTDIR\\%s\\*.pyo"\n' % (dir2))
                    # Delete all files in any __pycache__ subdirectory.
                    put('Delete "$INSTDIR\\%s\\__pycache__\\*.pyc"\n' % (dir2))
                for fn in aList:
                    put('Delete "$INSTDIR\\%s\\%s"\n' % (dir2,fn))
        # Part 3: Delete directories.
        reverseDirs = dirs[:]
        reverseDirs.reverse()
        put('\n')
        put('; Uninstall directories in reverse order\n')
        for theDir in reverseDirs:
            # Delete the directory even if it has files.
            if theDir and theDir != '**top':
                if not theDir.startswith('.bzr'):
                    put('RMDir "$INSTDIR\\%s\\__pycache__"\n' % (clean(theDir)))
                    put('RMDir "$INSTDIR\\%s"\n' % (clean(theDir)))
    # Delete the op-level folder.
    put('\n')
    put('; Delete the top-level directory.\n')
    put('RMDir "$INSTDIR"\n')
        # Important: the /r option is not safe here!
    self.f.close()
</t>
<t tx="ekr.20190429113053.12">def directoryList (self,rootDir):
    '''
    Compute a top-down list of all directories.
    These directories start at the top-level directory.
    '''
    trace = False
    ignoreDirs = ('.bzr','.git','docs')
    # Important: this adds all directories on EKR's machine,
    # regardless of whether they appear in the manifest!
    result = [] ; n = len(rootDir)
    for z in os.walk(rootDir): # top-down traversal.
        dirpath, dirnames, filenames = z
        assert dirpath.startswith(rootDir),z
        if len(dirpath) &gt; n:
            path = dirpath[n+1:].replace('\\','/')
            result.append(path)
    for z2 in ignoreDirs:
        result = [ z for z in result if not z.startswith(z2)]
    if trace:
        g.trace('-' * 40)
        g.trace(g.listToString(result))
    return result
</t>
<t tx="ekr.20190429113053.13">def filterLines (self,lines):
    '''Filter lines from the input manifest file.'''
    trace = False
    # Remove blank lines, comments, and .pyc and .pyo files.
    lines = self.deleteBlankLines(lines)
    lines = self.deleteComments(lines)
    lines = self.deleteTempFiles(lines)
    lines = self.deleteExt(lines,'.pyc')
    lines = self.deleteExt(lines,'.pyo')
    lines = self.deleteExt(lines,'.zip') # Don't include the zip file.
    lines = self.deleteExt(lines,'.exe') # Don't include the installer.
    # Remove specific files.
    deleteList = (
        '.bzrignore',
        '.gitignore',
        # 'bzr-manifest.txt',
        'git-manifest.txt',
        # 'bzr-small-manifest.txt',
        # 'setup.py',
        'stand_alone_globals.leo',
        'leoStandAloneGlobals',
        'leo/test/unittest/.leo_shadow/',
        'nsi.log.txt', # Can't write log while we are creating it.
        'leo/core/leoPy.leo',
        'leo/core/ekrLeoPy.leo',
    )
    lines = self.deleteFiles(lines,deleteList)
    # Delete all files in the top-level docs/ directory
    lines = [z for z in lines if not z.startswith('docs/')]
    if trace:
        g.trace('=' * 40)
        g.trace(g.listToString(lines))
    return lines
</t>
<t tx="ekr.20190429113053.14">def deleteBlankLines (self,lines):

    return [z.strip() for z in lines if z.strip()]

def deleteComments (self,lines):

    return [z for z in lines if not z.startswith('#')]

def deleteExt (self,lines,ext):

    return [z for z in lines if not z.endswith(ext)]

def deleteFiles (self,lines,deleteList):

    return [z for z in lines if not z in deleteList]

def deleteTempFiles (self,lines):

    for i in range(1,10):
        lines = [z for z in lines if not z.endswith('~%s~' % i)]
    return lines
</t>
<t tx="ekr.20190429113053.15">def make_manifest(self):
    '''Create git-manifest.txt.'''
    os.chdir(rootDir) # Can't be done below.
    commands = (
        r'del git-manifest.txt',
        r'c:\apps\Git\bin\git.exe ls-files &gt; git-manifest.txt',
        # r'&amp;ed git-manifest.txt',
    )
    g.execute_shell_commands(commands,trace=True)
</t>
<t tx="ekr.20190429113053.16">def make_zip(self):
    '''
    Create the zip file.
    
    The archive will not contain the .git directory, but will contain
    .gitignore, .gitattributes, etc. To suppress these files, use the
    export-ignore attribute in a .gitattributes file. Commit this before
    doing git archive.
    '''
    for z in (zipFile,zipFile2):
        if exists(z): self.unlink(z)
    os.chdir(rootDir) # Required.
    commands = (
        # This commit ensures the proper files are included in the distribution.
        # r'git commit -m "commit doc files during make"',
        ##version
        r'%s archive --format zip --output "%s" --prefix=Leo-5.7-final/ master' % (
            r'c:\apps\Git\bin\git.exe',zipFile),
    )
    g.execute_shell_commands(commands,trace=True)
    if not g.os_path_exists(zipFile):
        print('does not exist: %s' % zipFile)
    # Remove the temporary zip file.
    if exists(zipFile2):
        self.unlink(zipFile2)</t>
<t tx="ekr.20190429113053.17">def makeDicts (self,dirs,lines):

    trace = False ; verbose = True
    # Create the dirDict.
    # Keys are directories.
    # Values are files contained in each directory.
    dirDict = {}
    dirDict['**top'] = [] # Create an entry for the root directory.
    for z in dirs:
        dirDict[z] = []
        # Leo 5.4: Add leo/core/commit_timestamp.json
        # This file is in .gitignore, but we must write it here.
        if 0:
            if z == 'leo/core':
                # g.trace(z)
                # g.trace('Adding commit_timestamp.json')
                dirDict[z].append('commit_timestamp.json')
    # Assign files to dirDict.
    for line in lines:
        line = line.strip().replace('\\','/')
        if line in dirDict.keys():
            path,fn = None,None
        elif line.startswith('leo/'):
            path,fn = g.os_path_split(line)
        else:
            path,fn = '**top',line.strip()
        # Don't include top-level leo directory,
        # Do include leo/scripts/leo file.
        if fn and (path != '**top**' or fn != 'leo'):
            aList = dirDict.get(path,[])
            assert line not in aList,repr(line)
            aList.append(fn)
            dirDict[path]=aList
    # Trace the result.
    for theDir in sorted(dirDict):
        aList = dirDict.get(theDir)
        if aList and trace:
            if verbose:
                print() ; print(theDir)
                print(g.listToString(aList))
            else:
                print(theDir)
    # Create the inverse dict.
    filesDict = {}
    for theDir in sorted(dirDict):
        aList = dirDict.get(theDir)
        for fn in aList:
            path = g.choose(theDir=='**top',
                fn,'%s/%s' % (theDir,fn))
            filesDict[path] = theDir
            # if fn == 'wikiview.py': g.trace(fn,path)
    return dirDict,filesDict
</t>
<t tx="ekr.20190429113053.18">def printMissing (self,files,dirDict,filesDict):
    '''A crucial check.'''
    errors = 0
    for fn in files:
        fn = fn.rstrip('/')
        if fn and fn not in dirDict and fn not in filesDict:
            g.es_print('missing',fn,color='red')
            errors += 1
    if errors:
        g.es_print('%s errors' % (errors),color='red')
    return errors
</t>
<t tx="ekr.20190429113053.19">def remove_commit_timestamp_json(self):
    '''Remove leo/core/commit_timestamp.json.'''
    path = g.os_path_finalize_join(
        g.app.loadDir, '..', 'core', 'commit_timestamp.json')
    if g.os_path_exists(path):
        os.remove(path)
    else:
        g.trace('not found', path)
</t>
<t tx="ekr.20190429113053.2">import os
import shutil
# import string
# import struct
# import subprocess
# import sys
# import time
# import leo.core.leoVersion as leoVersion
</t>
<t tx="ekr.20190429113053.20"></t>
<t tx="ekr.20190429113053.21">def openFile (self,fn,mode='w'):

    try:
        f = open(fn,mode)
        return f
    except IOError:
        g.error('can not open',fn)
        return None
</t>
<t tx="ekr.20190429113053.22">def put (self,s):

    # g.trace(s.rstrip())
    self.f.write(s)
</t>
<t tx="ekr.20190429113053.23">def unlink (self,fn):

    # print('command: unlink: %s' % fn)
    os.remove(fn)
</t>
<t tx="ekr.20190429113053.3"># Globals...
abspath,exists,join = g.os_path_abspath,g.os_path_exists,g.os_path_join

# First.
# bzrRoot     = join('Lib','site-packages','Leo-%s' % (version))

    # Don't use abspath!
distDir     = abspath(join(g.app.loadDir,'..','dist'))
rootDir     = abspath(join(g.app.loadDir,'..','..')) # Same as top.
pluginsDir  = abspath(join(g.app.loadDir,'..','plugins'))

# Next.
coreDir =       abspath(join(g.app.loadDir,'..','core'))
docDir =        abspath(join(g.app.loadDir,'..','doc'))
docsDir =       abspath(join(g.app.loadDir,'..','..','docs'))
manifest_fn =   abspath(join(rootDir,'git-manifest.txt'))
# install_fn =    abspath(join(distDir,'nsi-install-files.txt'))
# uninstall_fn =  abspath(join(distDir,'nsi-uninstall-files.txt'))
install_fn =    abspath(join(rootDir,'nsi-install-files.txt'))
uninstall_fn =  abspath(join(rootDir,'nsi-uninstall-files.txt'))
zipFile =       abspath(join(rootDir,'Leo-%s.zip' % (version)))
zipFile2 =      abspath(join(rootDir,'Leo-%s-temp.zip' % (version)))

# assert g.os_path_exists(manifest)</t>
<t tx="ekr.20190429113053.4">class LeoMaker:
    '''
    A class to make these files in the leo-editor folder:

    - git-manifest.txt.
    - nsi-install-files.txt
    - nsi-uninstall-files.txt
    - leo.zip
    '''

    @others
</t>
<t tx="ekr.20190429113053.5">def run (self):
    '''The top-level logic.'''
    g.cls()
    # No longer exists. Done by git hooks.
        # leoVersion.create_commit_timestamp_json()
            # Create leo/core/commit_timestamp.json.
    self.clean_spellpyx()
    self.make_manifest()
    files = self.clean_manifest()
    dirs = self.directoryList(rootDir)
        # Compute the list of all the directories.
    dirDict,filesDict = self.makeDicts(dirs,files)
        # Compute dictionaries of directories and files.
    errors = self.printMissing(files,dirDict,filesDict)
        # Print manifest lines not in either dict.
        # This is a crucial check.
    if not errors:
        self.create_install_files(dirs,dirDict,filesDict)
        self.create_uninstall_files(dirs,dirDict,filesDict)
        self.make_zip()
        # self.copy_nsi_files()
        # self.remove_commit_timestamp_json()
</t>
<t tx="ekr.20190429113053.6">def clean_manifest(self):
    '''Create and filter the list of files from the manifest.'''
    f = open(manifest_fn)
    s = f.read()
    f.close()
    lines = g.splitLines(s)
    lines = self.filterLines(lines)
    # Write the file back.
    f = open(manifest_fn,'w')
    f.write('\n'.join(lines))
    f.close()
    return lines
</t>
<t tx="ekr.20190429113053.7">def clean_spellpyx (self):
    '''Clean ekr-spellpyx.txt.'''
    fn = g.os_path_finalize_join(pluginsDir,'ekr-spellpyx.txt')
    if not g.os_path_exists(fn):
        return
    f = self.openFile(fn,mode='rb')
    s = f.read()
    f.close()
    s2 = s.replace(b'\r',b'')
    if s != s2:
        g.es_print('cleaning',fn)
        f = self.openFile(fn,mode='wb')
        f.write(s2)
        f.close()
</t>
<t tx="ekr.20190429113053.8">def copy_nsi_files(self):
    '''
    Copy these files from the leo\dist folder to the leo-editor folder::

        nsi-install-files.txt
        nsi-uninstall-files.txt
    '''
    assert False, g.callers()
    names = (
        'nsi-install-files.txt',
        'nsi-uninstall-files.txt',
        # 'nsi-boilerplate.txt',
    )
    for fn in names:
        src = g.os_path_join(distDir,fn)
        dst = g.os_path_join(rootDir,fn)
        assert g.os_path_exists(src),src
        shutil.copyfile(src,dst)
</t>
<t tx="ekr.20190429113053.9">def copy_ref_files (self):
    '''Copy reference copies of .leo files.'''
    if 0:
        # There seems to be no need for this.
        # Furthermore, this changes the ref files.
        table = (
            (pluginsDir,'leoGuiPlugins.leo','leoGuiPluginsRef.leo'),
            (pluginsDir,'leoPlugins.leo','leoPluginsRef.leo'),
            (coreDir,'leoPy.leo','leoPyRef.leo'),
        )
        for d,src,dst in table:
            src_path = join(d,src)
            dst_path = join(d,dst)
            if not exists(src_path):
                g.error('does not exist',src_path)
            if not exists(dst_path):
                g.error('does not exist',dst_path)
            if exists(src_path) and exists(dst_path):
                shutil.copyfile(src_path,dst_path)
</t>
<t tx="ekr.20190618104430.1">From rel branch:
    
- git merge master
- Fix any conflicts and push.
- git checkout master
- git merge devel</t>
<t tx="ekr.20190618104609.1">Matt: When a release tag is created on Master it should be merged to Devel quickly.

git checkout devel
git merge master (will update leoVersion.py, so tags are also updated)
git push</t>
<t tx="ekr.20190618104622.1">Update the *GitHub* release at https://github.com/leo-editor/leo-editor/releases

This must be done *soon* after the release's actual commit.
There is a "Draft New Release" button at the top-right of the page.
</t>
<t tx="ekr.20190618104704.1">- Announce to SourceForge:  http://sourceforge.net/projects/leo/
   **Markdown accepted, so paste release notes in LeoDocs.leo.**.

- Announce to Python-announce-list using email:
   python-announce-list@python.org
   **Paste source-forge or leo-editor announcement**.

  - Check it by visiting the archive:
  https://mail.python.org/pipermail/python-announce-list/

- [Matt] Register Leo at https://pypi.python.org/pypi/leo

- My blog: http://edreamleo.blogspot.com/
  **Paste source-forge or leo-editor announcement** as text, not html.
</t>
<t tx="maphew.20180128212042.1">@language md
@wrap

Written by Matt Wilkie. Slightly revised by EKR.

PyPi is the Python Package Index Page: https://pypi.python.org/pypi

See https://github.com/leo-editor/leo-editor/issues/562

Once published to pypi Leo can be installed with:

    pip install leo

Developers should install from git as some files are left out when using pip (see Caveats):

    git clone --depth=500 https://github.com/leo-editor/leo-editor.git
    pip install -e .\leo-editor

nb: Optional `--depth=500` fetches the last 3-4 months of activity and is
    orders of magnitude faster than a full clone. If needed later use `git pull
    --unshallow` to grab everything that was missed.
</t>
<t tx="maphew.20180128212042.2">Install using pip if needed:

 - Wheel: for building cross platform binaries (might be installed already)
 - Setuptools: because ...setup!
 - Twine: for secure upload to pypi.org
 - Setupext-janitor: extend clean command (e.g. `python setup.py clean --all`)

    pip install setuptools twine wheel setupext-janitor
</t>
<t tx="maphew.20180128212042.3">A PyPi account is needed to update Leo's pypi reference. Contact one of the
package index owners to be added as a maintainer if needed. See end of
https://pypi.python.org/pypi/leo

Verify access Leo package edit page at:
https://pypi.python.org/pypi?%3Aaction=pkg_edit&amp;name=leo
</t>
<t tx="maphew.20180128212042.4">## Overview

_All of this is now handled in Travis Continual Integration build system. This recipe kept here for troubleshooting if something goes wrong in Travis._


* Remove stale distribution files &amp; folders.  
* Optionally set local checkout to specific version tag.  
* Build redistributable source and binary wheel package.  
* Upload to PyPi (assumes account registration already completed).  
* Test download and install from PyPi. Best to uninstall old Leo first or run in clean virtual env.

## Example

Windows syntax. 'Activate/deactivate' assume using virtual environments; skip those lines if not:

    activate leo-build
    
    rmdir /s/q dist build leo.egg-info
    git checkout tags/5.7
    python setup.py sdist bdist_wheel
    
    :: Optional, test install locally
    pip install dist\*.whl
    leo-console --version
    pip uninstall leo
    
    twine upload dist\*
    
    :: Optional, inspect public page for problems
    start https://pypi.python.org/pypi/leo
    
    deactivate
    
    :: For fuller test `conda create --name py3-clean` first instead of re-using
    activate py3-clean
    
    pip install leo
    leo-console --version

Twine upload will use username and password stored in `.pypirc`, or will prompt
if that doesn't exist.
</t>
<t tx="maphew.20180128212042.5">`pip install leo` only installs the contents of `leo` folder.
So links to files in the project root or other folders will be broken. (Background https://github.com/leo-editor/leo-editor/issues/573)

    ./leo-editor/*         --&gt; left out
    ./leo-editor/docs/*    --&gt; left out
    ./leo-editor/leo/*/*/* --&gt; PYTHONHOME/Lib/site-packages/leo

Docs: of little concern. These can regenerated from sources in ./leo (leoDocs.leo), and are on the website: http://leoeditor.com

Root: these files should only be involved in building installers and similar activities (e.g. leoDist.leo). Work from a git checkout or source tarball instead: https://github.com/leo-editor/leo-editor</t>
<t tx="maphew.20180128213245.1">TestPyPI: https://packaging.python.org/guides/using-testpypi/
is a separate instance of the Python Package Index (PyPI) that allows
trying out the distribution tools and process without worrying about affecting
the real index.

I (Matt) don't recommend using Test PyPi for Leo unless problems with the
package on the PyPi side are anticipated. It's too much of a pain to switch back
and forth between test and production when testing installs. In practice most
problems will be found and encountered when testing an install straight from the
whl file on disk:

    pip install dist\Leo-*.whl

That said, here's my recipe for packaging a new release for Test PyPi:
(Windows syntax)

    ::Verify integrity and Build (see leo\dist\build-*.bat)
    python setup.py check
    python setup.py bdist_wheel

    ::Test default install locally
    pip install dist\leo-5.7.dev344-py2.py3-none-any.whl
    leo-c --version
    pip uninstall leo

    ::Upload
    twine upload --repository-url https://test.pypi.org/legacy/ dist/leo-5.7.dev344-py2.py3-none-any

    ::Install from remote
    pip install --pre --index-url https://test.pypi.org/simple/ leo
    leo-c --version

Remove broken releases (still can't re-use identical version numbers and file names though):
https://testpypi.python.org/pypi?%3Aaction=pkg_edit&amp;name=leo
</t>
<t tx="maphew.20181010205346.1">**Pushed a commit but nothing is happening in the dashboard?**
Check the _requests_ log: https://travis-ci.org/leo-editor/leo-editor/requests
The link is hidden under [more options] at right.

**"Could not parse .travis.yml" requests error**
Debug with `travis lint` local client.

**Clarification on using `travis encrypt` for passwords**
https://github.com/travis-ci/travis-ci/issues/10051

**fatal: No names found, cannot describe anything**
The git clone is too shallow and `git describe --tags` doesn't include a tag. Increase the depth in `.travis.yml`:

    git:
      depth: 100

Or from command line:

    git fetch --depth=100

**Build only dependencies don't get installed**
Signified by error like `('\n', ImportError('No module named
semantic_version',))` in Travis report log even though module is listed in
`pyproject.toml`. Is because travis pip version in Oct 2018 is v9 and v10+ is
needed to leverage PEP-518. Fix: upgrade pip in `.travis.yml`

    python -m pip install --upgrade pip

</t>
<t tx="maphew.20190206032329.1">[build-system]
requires = ["setuptools&gt;=38.6.0",
    "setupext-janitor&gt;=1.1",
    "wheel&gt;=0.31.0",
    "twine&gt;=1.11.0"]
</t>
<t tx="maphew.20190208135916.1">[bdist_wheel]
# This flag says that the code is written to work on both Python 2 and Python
# 3. If at all possible, it is good practice to do this. If you cannot, you
# will need to generate wheels for each Python version that you support.
universal=1
</t>
<t tx="maphew.20190208142757.1">@language python
# A list of pip installable tools and libraries in the Requirements File Format
# https://pip.pypa.io/en/stable/reference/pip_install/#requirements-file-format
#
# Install with:
#   
#       pip install -r optional-tools.txt
#

pyenchant  # spell check support. No wheels for some platforms, e.g. amd64
pyxml; python_version &lt; "3.0"   # Used for XML import. Appears to be only python 2 package
</t>
<t tx="matt.20181004031246.1">@language md

_Initiating issue: https://github.com/leo-editor/leo-editor/issues/672_

Everything is controlled by `.travis.yml`. With this file present every commit
triggers a travis build and test. Build status and history can be viewed at
https://travis-ci.org/leo-editor/leo-editor

As currently configured if the commit is a tag AND the branch is `master` travis
will also attempt to deploy a release automatically to PyPi.org.
- Deploying to PyPi, https://docs.travis-ci.com/user/deployment/pypi/

Command line client: https://github.com/travis-ci/travis.rb
Not essential, but useful. Note: using `travis` command line client in a way
that updates yml file will delete any comments within it. (e.g. `travis encrypt
...`)

</t>
<t tx="matt.20190205105334.1">language: python
git:
    ## Clone depth, must be big enough to include a tag
    depth: 100
install:
    ## Using PEP-518 (pypoject.toml) requires pip &gt;v10 
    - python -m pip install --upgrade pip
    - pip --version
script:
    ## Test: Unit tests
    - python run_travis_unit_tests.py

    # There are no travis tests after checking out release tag
    #- pytest travis_tests/*
deploy:
  provider: pypi
  user: maphew
  password:
    secure: pZeDQzNu1XKDcGVEELttI/NqXMP5b5e99DgNzgTG+DVWU76sQ2wf4Jb1opIriHFQhN1etlndxVxp6YkugHDnu/B5rRklx+6WdAgHrIKcmbKzw86BsCzIwWqn1BqRlNT3mHo6uz1eQwQfJ/0/wptB5nougn8Z/E+hEIWbNgpu4CYr2TTa+9aWEpkg2h2ogOzZ1brp4hW2bJ0xW6XWBj+/bOsrgVKEmBvTZHkqFQSlODgHMJwsU3BWe/ntZ0J4QvLxseBSZM5tJTIG3w0pvGydGqxxAzbg1IY/4HZZFAttLGTr5ZJPBI2gPmz9FxmvJrWeV2iqkmMo8/OACqzSKYnMc2s8ACwUILNEZMSW+Z3IzFIUmomee3XKkkCCfbMi6eGHGYH2SFJLMnH11hGbr3yKY60FlWx8Hhds/aliGeEUdd6VqKfFeUgxcA4eDVSaAZCDFO9UWaFgrWdxEsi5aK+ElvrV/WYstouCOeMsfPIQREN8CPhQyvL4Q/gndLW904pmUkRQb9QMDzevL0gsBcP2I0mq742MmX3Kwk2gDyVxu1KafF1J6lFCBTWNyWqE18+CJxW/Qe7t1Qx7PPpDMf5kJwGtgOwg4hLELvSrA2hDL5h2kRtDoE1jkX0U5OLK2XWSHzFLLKt1VBNAal2JtJB1ii/7pC38jxFm/ZFRnOtJU0I=
  on:
    #tags: true
    branch: master, travis
</t>
<t tx="mhw-nc.20190126223741.1"></t>
<t tx="mhw.20190718140254.1"></t>
<t tx="mhw.20190718140259.1">language: python
python:
  - "3.6"
git:
    ## Clone depth, must be big enough to include a tag
    depth: 500
install:
    ## Using PEP-518 (pypoject.toml) requires pip &gt;v10 
    - python -m pip install --upgrade pip
    - pip --version
    - pip install setupext-janitor
script:
    ## Test: Unit tests
    - python run_travis_unit_tests.py

    ## Test: Build python wheel, install, and run Leo in console mode
    - python setup.py --quiet bdist_wheel
    - pip install dist/*.whl
    - leo-console --version
    
deploy:
  - provider: pypi
    user: maphew
    password:
      secure: pZeDQzNu1XKDcGVEELttI/NqXMP5b5e99DgNzgTG+DVWU76sQ2wf4Jb1opIriHFQhN1etlndxVxp6YkugHDnu/B5rRklx+6WdAgHrIKcmbKzw86BsCzIwWqn1BqRlNT3mHo6uz1eQwQfJ/0/wptB5nougn8Z/E+hEIWbNgpu4CYr2TTa+9aWEpkg2h2ogOzZ1brp4hW2bJ0xW6XWBj+/bOsrgVKEmBvTZHkqFQSlODgHMJwsU3BWe/ntZ0J4QvLxseBSZM5tJTIG3w0pvGydGqxxAzbg1IY/4HZZFAttLGTr5ZJPBI2gPmz9FxmvJrWeV2iqkmMo8/OACqzSKYnMc2s8ACwUILNEZMSW+Z3IzFIUmomee3XKkkCCfbMi6eGHGYH2SFJLMnH11hGbr3yKY60FlWx8Hhds/aliGeEUdd6VqKfFeUgxcA4eDVSaAZCDFO9UWaFgrWdxEsi5aK+ElvrV/WYstouCOeMsfPIQREN8CPhQyvL4Q/gndLW904pmUkRQb9QMDzevL0gsBcP2I0mq742MmX3Kwk2gDyVxu1KafF1J6lFCBTWNyWqE18+CJxW/Qe7t1Qx7PPpDMf5kJwGtgOwg4hLELvSrA2hDL5h2kRtDoE1jkX0U5OLK2XWSHzFLLKt1VBNAal2JtJB1ii/7pC38jxFm/ZFRnOtJU0I=
    distributions: sdist bdist_wheel
    on:
      tags: true
      branch: master
</t>
</tnodes>
</leo_file>
