#@+leo-ver=5-thin
#@+node:ekr.20070114140212: * @file activeUnitTests.txt
# All the following should pass when run locally (Alt-4).
#@@language python
#@+all
#@+node:ekr.20090703080553.5000: ** @suite run all doctests
import unittest
import leo.core.leoTest as leoTest
import sys

# WARNING: this causes strange problems when run externally.
if g.isPython3:
    # Some tests now fail on Python 2.x.
    path = g.os_path_join(g.app.loadDir,"..","core")
    if 0:
        << define exclude >>
    else:
        exclude = []
    modules = leoTest.importAllModulesInPath(path,exclude=exclude)
    suite = leoTest.createUnitTestsFromDoctests(modules)
    if suite: g.app.scriptDict['suite'] = suite
#@+node:ekr.20090703093925.5003: *3* << define exclude >>
exclude = [
    # These cause no problems, but will not have unit tests.
    'leo_Debugger.py',
    'leo_FileList.py',
    'leo_RemoteDebugger.py',
    'leo_run.py',
    'leo_Shell.py',
    'leoDynamicTest.py',
    'leoBridge.py',
    'leoBridgeTest.py',
    # 'leoApp.py','leoChapters.py',
    # 'leoAtFile.py',
    # 'leoColor.py',
    # 'leoCommands.py',
    # 'leoCompare.py',
    # 'leoConfig.py',
    # 'leoDebugger.py',
    # 'leoEditCommands.py',
    ####'leoFileCommands.py', # Causes problems!
    # 'leoFind.py',
    # 'leoFrame.py',
    # 'leoGlobals.py',
    # 'leoGui.py',
    # 'leoImport.py',
    # 'leoKeys.py',
    # 'leoMenu.py',
    # 'leoNodes.py',
    # 'leoPlugins.py',
    # 'leoPymacs.py',
    # 'leoRst.py',
    # 'leoShadow.py',
    # 'leoTangle.py',
    # 'leoTest.py',
    # 'leoUndo.py',
]
#@+node:ekr.20100210222021.5388: ** @test save new file
import os
c1 = c
fn = g.os_path_finalize_join(g.app.loadDir,'..','test','save-new-test.py')
# print(fn)
if g.os_path_exists(fn):
    os.remove(fn)
assert not g.os_path_exists(fn)
try:
    c = c1.new()
    assert c.cacher.db is None
    # Not a perfect unit test, but it similar to c.save.
    c.mFileName = fn
    c.openDirectory = c.frame.openDirectory = g.os_path_dirname(fn)
    c.fileCommands.save(c.mFileName)
    c.close()
    assert g.os_path_exists(fn)
finally:
    if g.os_path_exists(fn):
        os.remove(fn)
#@+node:ekr.20100208230953.5383: ** Cache tests
#@+node:ekr.20100208095817.5387: *3* @@test leoCache
# Disabled this test because it's best to open this file without caching.

import leo.core.leoCache as leoCache

cacher = leoCache.cacher(c)

assert cacher.test()
#@+node:ekr.20100131171342.5471: ** General
#@+node:ekr.20100131171342.5486: *3* @@test that all @test nodes in derived files start with if g.unitTesting
# print('-' * 30)

@others

# This can't be run externally,
# And it is no longer an effective test.

p = c.rootPosition()
ok = True
while p and ok:
    if p.isAnyAtFileNode():
        h = p.h
        if h.endswith('.py'):
            ok = checkFile(p)
        p.moveToNodeAfterTree()
    else:
        p.moveToThreadNext()
assert ok
#@+node:ekr.20100131171342.5487: *4* checkFile
def checkFile(p):

    print('checking',p.h)
    # Check all the descendant nodes.
    ok = True
    for p2 in p.subtree_iter():
        h = p2.h
        for tag in ('@test','@suite'):
            if h.startswith(tag):
                s = p2.b
                lines = g.splitLines(s)
                for line in lines:
                    # print('line',line)
                    if not line.strip() or line.startswith('#'):
                        continue
                    elif line.startswith('if g.unitTesting:'):
                        break
                    else:
                        print('in %s' % p.h)
                        print('missing "if g.unitTesting:" %s' % h)
                        ok = False
    return ok
#@+node:ekr.20100131171342.5485: *3* @test all commands have an event arg
import inspect

d = c.commandsDict ; keys = list(d.keys()) ; keys.sort()

for key in keys:
    f = d.get(key) ; name = f and f.__name__
    args, varargs, varkw, defaults = data = inspect.getargspec(f)
    # print('%-28s' % (name),data)
    arg0 = len(args) > 0 and args[0]
    arg1 = len(args) > 1 and args[1]
    assert arg0 == 'self' and arg1 == 'event' or arg0 == 'event',\
       'no event arg for %s, args: %s' % (name,data)
#@+node:ekr.20110613143220.3314: *3* @test All menus execute the proper command
@ We want to ensure that when masterMenuHandler does::
    
    event = g.app.gui.create_key_event(c,None,stroke,w)
    return k.masterKeyHandler(event)
    
that the effect will be to call commandName, where commandName
is the arg passed to masterMenuHandler.

createMenuEntries creates the association of stroke to commandName.
@c

trace = False # False: the unit test can fail.
k = c.k
d = g.app.unitTestMenusDict
d2 = k.bindingsDict ### c.k.masterGuiBindingsDict
d2name = 'k.bindingsDict'
commandNames = list(d.keys())
commandNames.sort()
exclude_strokes = ('Alt+F4','Ctrl+q','Ctrl+Shift+Tab',)

for name in commandNames:
    assert name in c.commandsDict,'unexpected command name: %s' % (
        repr(name))
    aSet = d.get(name)
    aList = list(aSet)
    aList.sort()
    for z in exclude_strokes:
        if z in aList:
            aList.remove(z)
    for stroke in aList:
        aList2 = d2.get(stroke)
        assert aList2,'stroke %s not in %s' % (
            repr(stroke),d2name)
        for b in aList2:
            if b.commandName == name:
                break
        else:
            if trace:
                inverseBindingDict = k.computeInverseBindingDict()
                print('%s: stroke %s not bound to %s in %s' % (
                    p.h,repr(stroke),repr(name),d2name))
                print('%s: inverseBindingDict.get(%s): %s' % (
                    p.h,name,inverseBindingDict.get(name)))
            else:
                assert False,'stroke %s not bound to %s in %s' % (
                    repr(stroke),repr(name),d2name)
#@+node:ekr.20100131171342.5483: *3* @test batch mode
import os
import sys

trace = False

python_interp = sys.executable
test_path = g.os_path_join(g.app.loadDir,"..","test","unittest")
src_path  = g.os_path_join(g.app.loadDir,"..","..")

leo_file   = g.os_path_join(src_path,"launchLeo.py")
batch_file = g.os_path_join(test_path,"batchTest.py")
test_file  = g.os_path_join(test_path,"createdFile.txt")

# Execute this command: python launchLeo.py --script test\unittest\batchTest.py

if 1:
    command = r"%s %s --silent --script %s" % (python_interp,leo_file,batch_file)
else:
    command = r"%s %s --script %s" % (python_interp,leo_file,batch_file)

@others

if trace:
    print('@test batch mode: loadDir: %s' % g.app.loadDir)

removeFile(test_file)
os.system(command)

assert(g.os_path_exists(test_file))
#@+node:ekr.20100131171342.5484: *4* removeFile
def removeFile(path):

    trace = False

    if os.path.exists(test_file):
        if trace:
            print("@test batch mode: removeFile: deleting",test_file)
        os.remove(test_file)
    else:
        if trace:
            print("@test batch mode: removeFile: not found:",test_file)
#@+node:ekr.20100131171342.5472: *3* Check base classes & ivars
#@+node:ekr.20100131171342.5473: *4* Tk gui tests
#@+node:ekr.20100131171342.5474: *5* @test leoBody is subset of leoTkBody
if g.app.gui.guiName() == 'tkinter':

    pc = g.app.pluginsController
    tkGui = pc.loadOnePlugin('leo.plugins.tkGui',verbose=False)
    assert(tkGui)

    import leo.core.leoFrame as leoFrame
    import inspect,sys

    baseClass = leoFrame.leoBody
    subClasses  = (tkGui.leoTkinterBody,leoFrame.nullBody)
    baseObject = c.frame.body

    methods = inspect.getmembers(baseClass,inspect.ismethod)
    methodNames = [z[0] for z in methods]

    for name in baseObject.mustBeDefinedOnlyInBaseClass:
        try:
            assert name in methodNames, 'not defined in base class %s.%s' % (baseClass.__name__,name)
        except AssertionError:
            exctype, value = sys.exc_info()[:2]
            print(value)
            raise

    for subClass in subClasses:
        subclassName = subClass.__name__
        for name in methodNames:
            base_func = getattr(baseClass,name)
            sub_func =  getattr(subClass,name)
            try:
                if name in baseObject.mustBeDefinedOnlyInBaseClass:
                    assert base_func.im_func == sub_func.im_func, 'defined in subclass %s.%s' % (subclassName,name)
                if name in baseObject.mustBeDefinedInSubclasses:
                    assert base_func.im_func != sub_func.im_func, 'not defined in subclass %s.%s' % (subclassName,name)
            except AssertionError:
                #raise
                exctype, value = sys.exc_info()[:2]
                print(value)
#@+node:ekr.20100131171342.5475: *5* @test leoFrame is subset of leoTkFrame
if g.app.gui.guiName() == 'tkinter':

    pc = g.app.pluginsController
    tkGui = pc.loadOnePlugin('leo.plugins.tkGui',verbose=False)

    import leo.core.leoFrame as leoFrame
    import inspect

    baseClass = leoFrame.leoFrame
    subClasses  = (tkGui.leoTkinterFrame,leoFrame.nullFrame)
    baseObject = c.frame

    methods = inspect.getmembers(baseClass,inspect.ismethod)
    methodNames = [z[0] for z in methods]

    for name in baseObject.mustBeDefinedOnlyInBaseClass:
        assert name in methodNames, 'not defined in base class %s.%s' % (baseClass.__name__,name)

    for subClass in subClasses:
        subclassName = subClass.__name__
        for name in methodNames:
            base_func = getattr(baseClass,name)
            sub_func =  getattr(subClass,name)
            if name in baseObject.mustBeDefinedOnlyInBaseClass:
                assert base_func.im_func == sub_func.im_func, 'defined in subclass %s.%s' % (subclassName,name)
            if name in baseObject.mustBeDefinedInSubclasses:
                assert base_func.im_func != sub_func.im_func, 'not defined in subclass %s.%s' % (subclassName,name)
#@+node:ekr.20100131171342.5476: *5* @test leoGui is subset of leoTkGui
if g.app.gui.guiName() == 'tkinter':

    pc = g.app.pluginsController
    tkGui = pc.loadOnePlugin('leo.plugins.tkGui',verbose=False)

    import leo.core.leoGui as leoGui
    import inspect

    baseClass = leoGui.leoGui
    subClasses  = (tkGui.tkinterGui,) # nullGui can inherit almost all leoGui dummy methods.
    baseObject = g.app.gui

    methods = inspect.getmembers(baseClass,inspect.ismethod)
    methodNames = [z[0] for z in methods]

    for name in baseObject.mustBeDefinedOnlyInBaseClass:
        assert name in methodNames, 'not defined in base class %s.%s' % (baseClass.__name__,name)

    for subClass in subClasses:
        subclassName = subClass.__name__
        for name in methodNames:
            base_func = getattr(baseClass,name)
            sub_func =  getattr(subClass,name)
            try:
                if name in baseObject.mustBeDefinedOnlyInBaseClass:
                    assert base_func.im_func == sub_func.im_func, 'defined in subclass %s.%s' % (subclassName,name)
                if name in baseObject.mustBeDefinedInSubclasses:
                    assert base_func.im_func != sub_func.im_func, 'not defined in subclass %s.%s' % (subclassName,name)
            except AssertionError:
                raise
#@+node:ekr.20100131171342.5477: *5* @test leoTree is subset of leoTkTree
if g.app.gui.guiName() == 'tkinter':

    pc = g.app.pluginsController
    tkGui = pc.loadOnePlugin('leo.plugins.tkGui',verbose=False)

    import leo.core.leoFrame as leoFrame
    import inspect

    baseClass = leoFrame.leoTree
    subClasses  = (tkGui.leoTkinterTree,leoFrame.nullTree)
    baseObject = c.frame.tree

    methods = inspect.getmembers(baseClass,inspect.ismethod)
    methodNames = [z[0] for z in methods]

    for name in baseObject.mustBeDefinedOnlyInBaseClass:
        assert name in methodNames, 'not defined in base class %s.%s' % (baseClass.__name__,name)

    for subClass in subClasses:
        subclassName = subClass.__name__
        for name in methodNames:
            base_func = getattr(baseClass,name)
            sub_func =  getattr(subClass,name)
            if name in baseObject.mustBeDefinedOnlyInBaseClass:
                assert base_func.im_func == sub_func.im_func, 'defined in subclass %s.%s' % (subclassName,name)
            if name in baseObject.mustBeDefinedInSubclasses:
                assert base_func.im_func != sub_func.im_func, 'not defined in subclass %s.%s' % (subclassName,name)
#@+node:ekr.20100131171342.5478: *4* @test that leoQtLog/Body implements high-level interface
if g.app.gui.guiName() == 'qt':

    logCtrl = c.frame.log.logCtrl

    table = (
        ('mustBeDefinedInSubclasses',logCtrl.mustBeDefinedInHighLevelSubclasses),
        ('mustBeDefinedInBaseClass',logCtrl.mustBeDefinedOnlyInBaseClass),
        ('mustBeDefined',logCtrl.mustBeDefined),
    )

    # Check existence.
    for tag,aList in table:
        for z in aList:
            assert hasattr(c.frame.log,z),'%s %s' % (tag,z)
            assert hasattr(c.frame.body,z),'%s %s' % (tag,z)

    # Check signatures.
    import inspect
    for tag,aList in table:
        for z in aList:
            func = getattr(c.frame.body.bodyCtrl,z)
            func2 = getattr(c.frame.log.logCtrl,z)
            assert func,z
            assert func2,z
            d1 = inspect.getargspec(func)
            d2 = inspect.getargspec(func2)
            assert d1==d2,'\n%s\n\nd1 %s\n\nd2 %s' % (z,d1,d2)
#@+node:ekr.20100131171342.5479: *4* @test official commander ivars
f = c.frame
assert(f.c==c)
assert(c.frame==f)

ivars = (
    # Subcommanders...
    'atFileCommands','fileCommands','importCommands','tangleCommands','undoer',
    # Positions...
    '_currentPosition','_topPosition',
    # '_rootPosition'
    # Data structures...
    'hoistStack','recentFiles',
    # Args...
    'output_doc_flag','page_width','tab_width',
    # 'tangle_directory',
    'tangle_errors','tangle_batch_flag','target_language',
    'untangle_batch_flag','use_header_flag',
    # Others...
    'mFileName',
)

for ivar in ivars:
    assert hasattr(c,ivar), 'missing commander ivar: %s' % ivar
    val = getattr(c,ivar)
    assert val is not None,'null commander ivar: %s'% ivar
#@+node:ekr.20100131171342.5480: *4* @test official frame ivars
f = c.frame
assert(f.c==c)
assert(c.frame==f)

if g.app.gui.guiName() == 'tkinter':
    ivars = (
        'bar1','bar2',
        'body',
        #'bodyBar','bodyXBar', # 2007: 10/31: There are now injected in c.frame.body.bodyCtrl.
        #'bodyCtrl', # 2007/10/27: this ivar is evil and has been removed.
        'canvas',
        'f1','f2',
        'iconBar','iconFrame',
        'log','outerFrame',
        'statusLine','statusFrame','statusLabel','statusText',
        'title','top','tree',
        #'treeBar', # leo_treeBar is now injected into frame.canvas.
    )
else: ivars = ()

for ivar in ivars:
    assert hasattr(f,ivar), 'missing frame ivar: %s' % ivar
    val = getattr(f,ivar)
    assert val is not None,'null frame ivar: %s'% ivar

# These do not have to be initied.
for ivar in ('findPanel',):
    assert hasattr(f,ivar), 'missing frame ivar: %s' % ivar
#@+node:ekr.20100131171342.5481: *4* @test official g.app directories
ivars = ('extensionsDir','globalConfigDir','loadDir','testDir')

for ivar in ivars:
    assert hasattr(g.app,ivar), 'missing g.app directory: %s' % ivar
    val = getattr(g.app,ivar)
    assert val is not None, 'null g.app directory: %s'% ivar
    assert g.os_path_exists(g.os_path_abspath(val)), 'non-existent g.app directory: %s' % ivar

assert hasattr(g.app,'homeDir') # May well be None.
#@+node:ekr.20100131171342.5482: *4* @test official g.app ivars

ivars = (
    # These are non-official and might be removed...
    'batchMode','config',
    'debug','debugSwitch','disableSave',
    'gui','hasOpenWithMenu','hookError','hookFunction',
    'idle_imported','idleTimeDelay','idleTimeHook','initing','killed',
    # 'loadedPlugins',
    'leoID','log','logIsLocked','logWaiting',
    'nodeIndices','numberOfWindows',
    'quitting','realMenuNameDict','searchDict','scriptDict',
    'trace','tracePositions','trace_list',
    'unitTestDict','unitTesting','use_psyco','windowList',
)

for ivar in ivars:
    assert hasattr(g.app,ivar), 'missing app ivar: %s' % ivar
    val = getattr(g.app,ivar)
    assert val is not None, 'null app ivar: %s'% ivar

# These do not have to be initied.
for ivar in (
    'commandName',
    'openWithFiles','openWithFileNum','openWithTable',
    'root',
):
    assert hasattr(g.app,ivar), 'missing app ivar: %s' % ivar
#@+node:ekr.20100205223124.5377: ** Syntax checking
#@+node:ekr.20040712101813: *3* @@test c.checkAllPythonCode
result = c.checkAllPythonCode(unittest=True,ignoreAtIgnore=True)

assert result=="ok", "checkPythonCode returns: %s" % result
#@+node:ekr.20100205231441.5386: *3* @test at.checkPythonSyntax
at = c.atFileCommands

s = '''
# no error
def spam():
    pass
'''

assert at.checkPythonSyntax(p,s),'fail 1'

s2 = '''
# syntax error
def spam:
    pass
'''

assert not at.checkPythonSyntax(p,s2,supress=True),'fail2'

if not g.unitTesting: # A hand test of at.syntaxError
    at.checkPythonSyntax(p,s2)
#@+node:ekr.20100205233116.5387: *3* @test at.tabNannyNode
@tabwidth -4

at = c.atFileCommands

s = '''
# no error
def spam():
    pass
'''

at.tabNannyNode (p,body=s,suppress=True)

s2 = '''
# syntax error
def spam:
    pass
  a = 2
'''

try:
    at.tabNannyNode(p,body=s2,suppress=True)
except IndentationError:
    pass
#@+node:ekr.20100205235740.5391: *3* @test c.checkPythonCode
c.checkPythonCode(event=None,
    unittest=True,ignoreAtIgnore=False,
    suppressErrors=True,checkOnSave=False)
#@+node:ekr.20100205223124.5378: *3* @test c.checkPythonNode
table = (
    ('syntax-error','error'),
)

for h,expected in table:
    p2 = g.findNodeInTree(c,p,h)
    assert p2,'node not found: %s' % h
    result = c.checkPythonCode(event=None,
        unittest=True,ignoreAtIgnore=True,
        suppressErrors=True,checkOnSave=False)
    assert result==expected, 'expected %s got %s' % (
        expected,result)
#@+node:ekr.20100205223124.5379: *4* syntax-error
def abc
    pass
#@+node:ekr.20100205234837.5390: *3* @test c.tabNannyNode
@tabwidth -4

s = '''
# no error
def spam():
    pass
'''

c.tabNannyNode(p,headline=p.h,body=s,unittest=True,suppressErrors=True)

s2 = '''
# syntax error
def spam:
    pass
  a = 2
'''

try:
    c.tabNannyNode(p,headline=p.h,body=s2,unittest=True,suppressErrors=True)
except IndentationError:
    pass
#@+node:ekr.20100206002004.5397: *3* @test g.es_exception
# This is just a hand test.
if not g.unitTesting:
    try:
        assert False
    except AssertionError:
        g.es_exception(full=True,c=None,color='red')
#@+node:ekr.20071113145804.20: *3* @@test g.es_exception (heroic)
if c.config.redirect_execute_script_output_to_log_pane:
    pass # Test doesn't work when redirection is on.
else:
    try:
        import sys
        # Catch the output of g.es_exception.
        # We catch the AssertionError, so nothing gets written to stderr.
        sys.stdout = fo = g.fileLikeObject()
        try: # Create an exception to catch.
            assert False, 'Assert False in test_g_es_exception'
        except AssertionError:
            g.es_exception(color='suppress')
            result = fo.get()
            s1 = 'Traceback (most recent call last):'
            s2 = 'AssertionError: Assert False in test_g_es_exception'
            assert result.find(s1) > -1, 'No traceback line: %s' % repr(result)
            assert result.find(s2) > -1, 'No AssertionError line: %s' % repr(result)
    finally:
        # Not needed unless we execute this script as selected text.
        sys.stdout = sys.__stdout__
#@+node:ekr.20100206001203.5395: *3* @test g.getLastTracebackFileAndLineNumber
try:
    assert False
except AssertionError:
    fn,n = g.getLastTracebackFileAndLineNumber()
assert fn == '<string>',repr(fn)
assert n == 4,repr(n)
#@+node:ekr.20100205230621.5383: *3* @test leoTest.checkFileSyntax
import leo.core.leoTest as leoTest

s = '''
# syntax error
def spam:
    pass
'''

try:
    leoTest.checkFileSyntax('<fileName>',s,suppress=True)
    assert False
except SyntaxError:
    pass
#@+node:ekr.20100205235740.5392: *3* @test syntax of all files
import leo.core.leoTest as leoTest
import os

tkPass = (
    'EditAttributes','Library',
    'URLloader','UniversalScrolling','UASearch',
    'autotrees','base64Packager','chapter_hoist','cleo','dump_globals',
    'expfolder','geotag','graphed','groupOperations',
    'hoist','import_cisco_config','leoupdate',
    'maximizeNewWindows', 'mnplugins','mod_labels',
    'mod_read_dir_outline','mod_tempfname','multifile',
    'nav_buttons','newButtons','nodeActions','nodebar','nodenavigator',
    'open_with','pie_menus','pluginsTest',
    'read_only_nodes','rClick','rClickBasePluginClasses',
    'scheduler','searchbar','searchbox','shortcut_button',
    'script_io_to_body','searchbox',
    'templates','textnode','tkGui','toolbar',
    'UNL','xcc_nodes',
)
passList = (
    '__init__','FileActions',
    'active_path','add_directives','attrib_edit',
    'backlink','baseNativeTree','bibtex','bookmarks',
    'codewisecompleter','colorize_headlines','contextmenu',
    'ctagscompleter','cursesGui','datenodes','debugger_pudb',
    'detect_urls','dtest','empty_leo_file','enable_gc','initinclass',
    'leo_to_html','leo_interface','leo_pdf','leo_to_rtf',
    # 'leoN',
    'leoOPML','leoremote','lineNumbers',
    'macros','mime','mod_autosave','mod_framesize','mod_leo2ascd',
    'mod_scripting','mod_speedups','mod_timestamp',
    'nav_qt','niceNosent','nodeActions',
    'open_shell','outline_export','quit_leo',
    'paste_as_headlines','plugins_menu','pretty_print','projectwizard',
    'qtGui','qt_main','qt_quicksearch','qtframecommands',
    'quickMove','quicksearch','redirect_to_log','rst3','run_nodes',
    'screenshots','scrolledmessage','setHomeDirectory','slideshow','spydershell','startfile',
    'testRegisterCommand','todo','trace_gc_plugin','trace_keys','trace_tags',
    'vim','xemacs',
)
core_files = (
    'leoApp','leoAtFile','leoCache','leoChapters','leoCommands',
    'leoEditCommands','leoFileCommands','leoFind','leoFrame',
    'leoGlobals','leoGui','leoImport','leoMenu','leoNodes',
    'leoPlugins','leoShadow','leoTangle','leoUndo',
)
external_files = (
    'ipy_leo','lproto',
)
recent = (
    #'leo_interface',
)
table = (
    ('plugins',recent),
    ('plugins',passList),
    # ('plugins',tkPass),
    ('core',core_files),
    ('external',external_files),
)
files = []
for theDir,aList in table:
    for z in aList:
        if not z.endswith('.py'): z = z + '.py'
        fn = os.path.abspath(os.path.join('leo',theDir,z))
        if os.path.exists(fn): files.append(fn)
        else: print('*** file not found:',fn)

failed = []
for z in files:
    fn = g.shortFileName(z)
    s,e = g.readFileIntoString(z)
    if not leoTest.checkFileSyntax(fn,s,reraise=False,suppress=False):
        failed.append(fn)

assert not failed,'failed %s\n' % g.listToString(failed,sort=True)
#@+node:ekr.20110612071416.3311: *3* @test syntax of setup.py
import leo.core.leoTest as leoTest
fn = g.os_path_finalize_join(g.app.loadDir,'..','..','setup.py')

# Only run this test if setup.py exists: it may not in the actual distribution.
if g.os_path_exists(fn):
    s,e = g.readFileIntoString(fn)
    leoTest.checkFileSyntax(fn,s,reraise=True,suppress=False)
#@+node:ekr.20050208051418: ** Unicode tests
#@+node:ekr.20050206201145: *3* @test % operator with unicode
@first # -*- coding: utf-8 -*-

s = "testᾹ(U+1FB9: Greek Capital Letter Alpha With Macron)"

s2 = 'test: %s' % s
#@+node:ekr.20050208051854: *3* @test atFile.printError
@first # -*- coding: utf-8 -*-

at = c.atFileCommands
at.errors = 0

if g.isPython3:
    # Do not call g.ue: it will crash.
    s = 'La Peña'
else:
    s = g.ue('La Peña','utf-8')

at.printError('test of at.printError:',s)

# important: this test will fail if sitecustomize.py
# does not contain sys.setdefaultencoding('utf-8')
#@+node:ekr.20050208051418.1: *3* @test can't open message in g.openWithFileName
@first # -*- coding: utf-8 -*-

old_c = c
filename = "testᾹ(U+1FB9: Greek Capital Letter Alpha With Macron)"
ok,frame = g.openWithFileName(filename,old_c)
assert(not ok)
#@+node:ekr.20050208111037: *3* @test failure to convert unicode characters to ascii
@first # -*- coding: utf-8 -*-

encoding = 'ascii'

if g.isPython3:
    s = '炰' # This is already unicode.
    s2,ok = g.toUnicodeWithErrorCode(s,encoding)
    assert ok, 'toUnicodeWithErrorCode returns False for %s with ascii encoding' % s

    s3,ok = g.toEncodedStringWithErrorCode(s,encoding)
    assert not ok, 'toEncodedStringWithErrorCode returns True for %s with ascii encoding' % s
else:
    s = '炰' # An encoded string.
    s2,ok = g.toUnicodeWithErrorCode(s,encoding)
    assert not ok, 'toUnicodeWithErrorCode returns True for %s with ascii encoding' % s

    s = g.ue('炰','utf-8') # Must use utf-8 encoding *here*
    s3,ok = g.toEncodedStringWithErrorCode(s,encoding)
    assert not ok, 'toEncodedStringWithErrorCode returns True for %s with ascii encoding' % s
#@+node:ekr.20071113143844.6: *3* @test failure with ascii encodings
@first # -*- coding: utf-8 -*-

encoding = 'ascii'

if g.isPython3:
    s = '炰'
    s2,ok = g.toUnicodeWithErrorCode(s,encoding)
    assert ok, 'toUnicodeWithErrorCode returns True for %s with ascii encoding' % s

    s3,ok = g.toEncodedStringWithErrorCode(s,encoding)
    assert not ok, 'toEncodedStringWithErrorCode returns True for %s with ascii encoding' % s
else:
    s = '炰'
    s2,ok = g.toUnicodeWithErrorCode(s,encoding)
    assert not ok, 'toUnicodeWithErrorCode returns True for %s with ascii encoding' % s

    s = g.ue('炰','utf-8')
    s3,ok = g.toEncodedStringWithErrorCode(s,encoding)
    assert not ok, 'toEncodedStringWithErrorCode returns True for %s with ascii encoding' % s
#@+node:ekr.20071113145804.23: *3* @test g.reportBadChars
@first # -*- coding: utf-8 -*-

if g.isPython3:
    table = (
        ('aĂbĂ',    'ascii'),
        ('炰',               'ascii'),
        ('aĂbĂ',            'utf-8'),
        ('炰',               'utf-8'),
    ) 
else:
    table = (
        ('aĂbĂ',                    'ascii'),
        (g.ue('aĂbĂ','utf-8'),      'ascii'),
        ('炰',                       'ascii'),
        (g.ue('炰','utf-8'),         'ascii'),
        ('aĂbĂ',                     'utf-8'),
        (g.ue('aĂbĂ','utf-8'),       'utf-8'),
        ('炰',                       'utf-8'),
        (g.ue('炰','utf-8'),         'utf-8'),
    )
for s,encoding in table:
    g.reportBadChars(s,encoding)
#@+node:ekr.20100204053330.5367: *3* @test koi8-r encoding
root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode = None)
try:
    p1 = p.insertAsLastChild()
    s = '\xd4\xc5\xd3\xd4' # the word 'test' in Russian, koi8-r
    if g.isPython3:
        assert g.isUnicode(s)
    else:
        s = unicode(s,'koi8-r')
    p1.setBodyString(s)
    c.selectPosition(p1)
    c.copyOutline()
    c.pasteOutline()
    p2 = p1.next()
    # self.assertEqual(p1.b, p2.b) # 'self' defined only when unit-testing.
    assert p1.b == p2.b
finally:
    if 1:
         while root.hasChildren():
              root.firstChild().doDelete(newNode = None)
    c.redraw_now(p)
#@+node:ekr.20050208104202: *3* @test of round-tripping toUnicode & toEncodedString
@first # -*- coding: utf-8 -*-

if not g.isPython3: # Does not work with Python 3.x

    for s,encoding in (
        ('a',    'utf-8'),
        ('a',    'ascii'),
        ('äöü',  'utf-8'),
        ('äöü',  'mbcs'),
        ('炰',    'utf-8'),
        ('炰',    'mbcs'),
    ):
        if g.isValidEncoding(encoding):
            s2,ok = g.toUnicodeWithErrorCode(s,encoding)
            assert ok, 'toUnicodeWithErrorCode fails for %s' %s
            s3,ok = g.toEncodedStringWithErrorCode(s2,encoding)
            assert ok, 'toEncodedStringWithErrorCode fails for %s' % s2
            assert s3 == s, 'Round-trip one fails for %s' %s

            s2 = g.toUnicode(s,encoding)
            s3 = g.toEncodedString(s2,encoding)
            assert s3 == s, 'Round-trip two fails for %s' %s
#@+node:ekr.20050206090416: *3* @test open non-existent non-ascii directory
@first # -*- coding: utf-8 -*-

if g.isPython3:
    # Do not call g.ue: it will crash.
    theFile = 'Ỗ'
else:
    theFile = g.ue('Ỗ','utf-8')

path = g.os_path_join('Ỗ','Ỗ')
# print(g.toEncodedString(theFile,'utf-8'))

ok,frame = g.openWithFileName(path,c)

assert not ok and not frame
#@+node:ekr.20071113145804.24: *3* @test round trip toUnicode toEncodedString
@first # -*- coding: utf-8 -*-

if not g.isPython3: # Does not work with Python 3.x

    table = [
        ('a',    'utf-8'),
        ('a',    'ascii'),
        ('äöü',  'utf-8'),
        ('äöü',  'mbcs'),
        ('炰',   'utf-8'),
    ]

    # __pychecker__ = '--no-reimport'
    import sys

    if sys.platform.startswith('win'):
        data = '炰','mbcs'
        table.append(data)

    for s,encoding in table:
        if g.isValidEncoding(encoding):
            s2,ok = g.toUnicodeWithErrorCode(s,encoding)
            assert ok, 'toUnicodeWithErrorCode fails for %s' %s
            s3,ok = g.toEncodedStringWithErrorCode(s2,encoding)
            assert ok, 'toEncodedStringWithErrorCode fails for %s' % s2
            assert s3 == s, 'Round-trip one failed for %s' %s

            s2 = g.toUnicode(s,encoding)
            s3 = g.toEncodedString(s2,encoding)
            assert s3 == s, 'Round-trip two failed for %s' %s
#@+node:ekr.20100421102506.6282: *3* @test rst.write with unicode character
@first # -*- coding: utf-8 -*-

rst = c.rstCommands

name = g.os_path_finalize_join(g.app.loadDir,'..','test','unittest','rst_write_test.txt')

s = "testᾹ(U+1FB9: Greek Capital Letter Alpha With Macron)"

if g.isPython3:
    f = open(name,'w',encoding='utf-8')
else:
    f = open(name,'w')
    s = rst.encode(s)

f.write(s)
f.close()

assert g.os_path_exists(name)
#@+node:ekr.20071113194858: ** Organized by file
# All the following files have problems when run with Alt-5.
#@+node:ekr.20100223123103.5382: *3* @test expand/contract-pane
# These commands are implemented by qtGui.py

def closeEnough(f1,f2):
    return abs(f1-f2) < 0.0001

f = c.frame
ratio,ratio2 = f.ratio,f.secondary_ratio

table = (
    c.bodyWantsFocusNow,
    c.logWantsFocusNow,
    c.treeWantsFocusNow,
)

for func in table:
    func()
    f.contractPane()
    if func == c.logWantsFocusNow:
        assert ratio2 != f.secondary_ratio,'fail 1'
    else:
        assert ratio != f.ratio,'fail 2: %s, %s' % (ratio,f.ratio)
    func()
    f.expandPane()
    assert closeEnough(ratio,f.ratio),'fail 3 %s != %s' % (
        ratio,f.ratio)
    assert closeEnough(ratio2,f.secondary_ratio),'fail 4 %s != %s' % (
        ratio2,f.secondary_ratio)
#@+node:ekr.20100131171342.5506: *3* leoApp
#@+node:ekr.20100131171342.5507: *4* @test consistency of leoApp tables
@
language_delims_dict 
    # Keys are languages, values are 1,2 or 3-tuples of delims. 
language_extension_dict
    # Keys are languages, values are extensions.
extension_dict = {
    # Keys are extensions, values are languages.
@c

delims_d    = g.app.language_delims_dict
lang_d      = g.app.language_extension_dict
ext_d       = g.app.extension_dict

for lang in lang_d:
    ext = lang_d.get(lang)
    assert lang in delims_d,'fail 1: %s' % lang
    assert ext in ext_d,'fail 2: %s' % ext
for ext in ext_d:
    lang = ext_d.get(ext)
    assert lang in lang_d,'fail 3: %s' % lang
#@+node:ekr.20050112095306.1: *3* leoAtFile
#@+node:ekr.20041021065844: *4* @test @asis
import leo.core.leoTest as leoTest

leoTest.runAtFileTest(c,p)
#@+node:ekr.20041021065903: *5* #@asis
# Test that @nosent generates no sentinels

<< section >>

@others

last line
#@+node:ekr.20041021065903.1: *6* << section >>
section line 1
#@+node:ekr.20041021065903.2: *6* unnamed node
unnamed node line 1
#@+node:ekr.20041021065844.1: *5* Output
# Test that @nosent generates no sentinels

<< section >>

@others

last line
section line 1
unnamed node line 1
#@+node:ekr.20090704085350.5044: *4* @test @asis: shape of tree
h = '@asis ../test/unittest/at-asis-test.py'
p = g.findNodeAnywhere(c,h)
assert p

table = (
    (p.firstChild(),'spam'),
    (p.firstChild().next(),'eggs')
)

assert not p.isDirty(),p.h # Do not ignore this failure!

for p2,h2 in table:
    assert p2.h == h2
    assert len(p2.b) > 10
#@+node:ekr.20090627070131.4971: *4* @test @auto (newlines at end of nodes)
import leo.core.leoTest as leoTest

leoTest.runAtFileTest(c,p)
#@+node:ekr.20090627070131.4975: *5* #@auto
@language python
@tabwidth -4
@others
#end
#@+node:ekr.20090627070131.4976: *6* spam
def spam(cheese):

    print(cheese)
#@+node:ekr.20090627070131.4977: *6* cheese
def cheese():

    pass
#@+node:ekr.20090627070131.4978: *5* Output
def spam(cheese):

    print(cheese)
def cheese():

    pass
#end
#@+node:ekr.20100801125533.5787: *4* @test @auto (no newline at end of nodes)
import leo.core.leoTest as leoTest

leoTest.runAtFileTest(c,p)
#@+node:ekr.20100801125533.5788: *5* #@auto
@language python
@tabwidth -4
@others
#end
#@+node:ekr.20100801125533.5789: *6* spam
def spam(cheese):

    print(cheese)
#@+node:ekr.20100801125533.5790: *6* cheese
def cheese():

    pass
#@+node:ekr.20100801125533.5791: *5* Output
def spam(cheese):

    print(cheese)
def cheese():

    pass
#end
#@+node:ekr.20090704085350.5052: *4* @test @auto: shape of tree
h = '@auto ../test/unittest/at-auto-test.py'
p = g.findNodeAnywhere(c,h)
assert p

table = (
    (p.firstChild(),'spam'),
    (p.firstChild().next(),'eggs')
)

assert not p.isDirty(),p.h # Do not ignore this failure!

for p2,h2 in table:
    assert p2.h == h2
    assert len(p2.b) > 10
#@+node:ekr.20090225102051.2: *4* @test @edit
import leo.core.leoTest as leoTest

leoTest.runAtFileTest(c,p)
#@+node:ekr.20090225102051.3: *5* #@edit
Line 1

Last line: no newline
#@+node:ekr.20090225102051.4: *5* Output
Line 1

Last line: no newline
#@+node:ekr.20110524120515.3489: *4* @test @raw
import leo.core.leoTest as leoTest

leoTest.runAtFileTest(c,p)
#@+node:ekr.20110524120515.3490: *5* #@file
# before

@raw

@c

<< ref >>

@end_raw

#after
#@+node:ekr.20110524120515.3491: *5* Output
#@verbatim
#@+leo-ver=5
#@verbatim
#@+node:#@file
# before

#@verbatim
#@@raw

@c

<< ref >>

#@verbatim
#@@end_raw

#after
#@verbatim
#@-leo
#@+node:ekr.20090704085350.5018: *4* @test @shadow: shape of tree
h = '@shadow ../test/unittest/at-shadow-test.py'
p = g.findNodeAnywhere(c,h)
assert p

table = (
    (p.firstChild(),'spam'),
    (p.firstChild().next(),'eggs')
)

assert not p.isDirty(),p.h # Do not ignore this failure!

for p2,h2 in table:
    assert len(p2.h) == len(h2)
#@+node:ekr.20040707141957.12: *4* @test @thin: @last
import leo.core.leoTest as leoTest

leoTest.runAtFileTest(c,p)
#@+node:ekr.20040707141957.13: *5* #@thin
Line 1

@last last line 1: no newline
#@+node:ekr.20040707141957.14: *5* Output
#@verbatim
#@+leo-ver=5-thin
#@verbatim
#@+node:ekr.20040707141957.13: * #@thin
Line 1

#@verbatim
#@@last
#@verbatim
#@-leo
last line 1: no newline
#@+node:ekr.20100731163237.5778: *4* @test @thin: html section references
@language python

# html uses block comments.  This is an important test.

h = '@thin ../test/unittest/at-thin-html-test.html'
p = g.findNodeAnywhere(c,h)
assert p

s = (
'@language html\n\n<< ' +
'a section reference >>\n\n' +
'after.\n')

# print(repr(p.b)) ; print(repr(s))

assert p.b == s,'body failure'
#@+node:ekr.20090704085350.5046: *4* @test @thin: shape of tree
h = '@thin ../test/unittest/at-thin-test.py'
p = g.findNodeAnywhere(c,h)
assert p

table = (
    (p.firstChild(),'spam'),
    (p.firstChild().next(),'eggs')
)

assert not p.isDirty(),p.h # Do not ignore this failure!

for p2,h2 in table:
    assert p2.h == h2
    assert len(p2.b) > 10
#@+node:ekr.20100802220019.5795: *4* @test at.deleteUnvistedNodes
def clone (p,parent,n):
    p2 = p.clone()
    p2.moveToNthChildOf(parent,n)
    return p2

def make (parent,n,h):
    child = parent.insertAsNthChild(n)
    child.h = h
    return child

def delete_r():
    '''Delete all 'Resurrected Nodes' nodes.'''
    while True:
        r = g.findNodeAnywhere(c,'Resurrected Nodes')
        if r: r.doDelete(newNode=p)
        else: break

def delete_children():
    # Delete all children of p.
    while p.hasChildren():
        p.firstChild().doDelete(newNode=p)

def test(p,h,tag):
    assert p,'p'
    assert p.h == 'From root','p.h %s' % tag
    assert p.numberOfChildren() == 1,'number of children %s' % tag
    assert p.firstChild().h == h,'child.h %s' % tag

delete_r()
delete_children()

# Create some children.
root = make(p,0,'root')
child1 = make(root,0,'child1')
child2 = make(root,1,'child2')
child3 = make(root,2,'child3')
child11 = make(child1,0,'child11')
child21 = make(child2,0,'child21')
child31 = make(child3,0,'child31')
# Create some clones.
child4 = clone(child31,root,3)

for z in root.self_and_subtree():
    z.setVisited()
for z in child2,child31: # These should be moved.
    z.clearVisited()

c.atFileCommands.deleteUnvisitedNodes(root)

if 1:
    r = g.findNodeAnywhere(c,'Resurrected Nodes')
    assert r,'r'
    r1 = r.firstChild()
    r2 = r1.next()
    r3 = r2.next()
    test(r1,'child2','r1')
    test(r2,'child31','r2')
    assert root.numberOfChildren() == 3,'root.n'
if 1:
    delete_r()
    delete_children()

c.redraw_now()
#@+node:ekr.20071113145804.8: *4* @test at.directiveKind4
at=c.atFileCommands
table = [
    ('@=',0,at.noDirective),
    ('@',0,at.atDirective),
    ('@ ',0,at.atDirective),
    ('@\t',0,at.atDirective),
    ('@\n',0,at.atDirective),
    ('@all',0,at.allDirective),
    ('    @all',4,at.allDirective),
    ("@c",0,at.cDirective),
    ("@code",0,at.codeDirective),
    ("@doc",0,at.docDirective),
    ("@end_raw",0,at.endRawDirective),
    ('@others',0,at.othersDirective),
    ('    @others',4,at.othersDirective),
    ("@raw",0,at.rawDirective),
]
for name in g.globalDirectiveList:
    # Note: entries in g.globalDirectiveList do not start with '@'
    if name not in ('all','c','code','doc','end_raw','others','raw',):
        table.append(('@' + name,0,at.miscDirective),)

for s,i,expected in table:
    result = at.directiveKind4(s,i)
    assert result == expected, '%d %s result: %s expected: %s' % (
        i,repr(s),at.sentinelName(result),at.sentinelName(expected))
#@+node:ekr.20100225094004.5385: *4* @test at.isFileLike
s1 = '''
#@verbatim
#@+leo-ver=4
#@verbatim
#@+node:#@file
Line 1
#@verbatim
#@-node:#@file
#@verbatim
#@-leo
'''

s2 = '''
#@verbatim
#@+leo-ver=4-thin
#@verbatim
#@+node:ekr.20040707141957.13:#@thin
#@verbatim
#@-node:ekr.20040707141957.13:#@thin
#@verbatim
#@-leo
'''

at = c.atFileCommands
assert at.isFileLike(s1),'fail1'
assert not at.isFileLike(s2),'fail2'
#@+node:ekr.20071113143844.5: *4* @test at.isSignificantTree
assert c.atFileCommands.isSignificantTree(p)

#@+node:ekr.20110524091618.3488: *4* @test at.massageDocPart
at = c.atFileCommands

# A mininimal test.

at.startSentinelComment = '<!--'
at.endSentinelComment = '-->'

s1 = '<!--\nline 2.\n-->\n'
s2 = at.massageAtDocPart(s1)

assert s2 == 'line 2.\n',repr(s2)
#@+node:ekr.20090529115704.4562: *4* @test at.open/closeStringFile
at = c.atFileCommands

# at.toString is set by the execute-script command.

f = at.openStringFile('abc')

assert f.__class__.__name__ == 'fileLikeObject'

s = 'abc'
f.write(s)
s2 = at.closeStringFile(f)

assert s == s2

# assert at.toString

#@+node:ekr.20090529115704.4563: *4* @test at.openForWrite: not a shadow file
at = c.atFileCommands
x = c.shadowController

filename = x.pathName('xyzzy')
assert not g.os_path_exists(filename)

try:
    kind,theFile = at.openForWrite(filename)
    assert kind == 'check'
    # print(repr(theFile))
    if theFile: theFile.close()

finally:
    if g.os_path_exists(filename):
        x.unlink(filename)
        assert not g.os_path_exists(filename)
#@+node:ekr.20090529115704.4564: *4* @test at.readOneAtShadowNode
at = c.atFileCommands
x = c.shadowController

changed = c.changed
child = p.firstChild()
s = child.b

try:
    fn = 'unittest/read_test.py'
    child.setHeadString('@shadow %s' % fn)
    # shadow_fn = x.shadowPathName(fn)
    at.writeOneAtShadowNode(child,toString=False,force=True)
    at.readOneAtShadowNode(fn,child)
finally:
    child.setHeadString('@@shadow %s' % fn)
    c.setChanged(changed)
    # c.redraw_now()
#@+node:ekr.20090529115704.4565: *5* @@shadow unittest/read_test.py
@language python
@tabwidth -4
@others
# body of @shadow test node
# The last line.
#@+node:ekr.20050105093136: *4* @test at.remove
import os

at = c.atFileCommands
exists = g.os_path_exists

path = g.os_path_join(g.app.testDir,'xyzzy')
if exists(path):
    os.remove(path)

assert not exists(path)
assert not at.remove(path,verbose=False)

f = open(path,'w')
f.write('test')
f.close()

assert exists(path)
assert at.remove(path)
assert not exists(path)
#@+node:ekr.20050105093524: *4* @test at.rename
import os

at = c.atFileCommands
exists = g.os_path_exists
path = g.os_path_join(g.app.testDir,'xyzzy')
path2 = g.os_path_join(g.app.testDir,'xyzzy2')

# Create both paths.
for p in (path,path2):
    if exists(p):
        os.remove(p)
    assert not exists(p)
    f = open(p,'w')
    f.write('test %s' % p)
    f.close()
    assert exists(p)

assert at.rename(path,path2,verbose=True)
assert exists(path2)
f = open(path2)
s = f.read()
f.close()
# print('Contents of %s: %s' % (path2,s))
assert s == 'test %s' % path
os.remove(path2)
assert not exists(path)
#@+node:ekr.20090529115704.4566: *4* @test at.replaceFileWithString
import os
s = 'abc'
fn = 'unitTestFile.py'
path = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..','test','unittest',fn))
try:
    c.atFileCommands.replaceFileWithString(path,s)
    f = open(path)
    s2 = f.read()
    f.close()
    assert s == s2
finally:
    if g.os_path_exists(path):
        os.unlink(path)
#@+node:ekr.20050105094311: *4* @test at.replaceTargetFileIfDifferent (different)
import os

at = c.atFileCommands
exists = g.os_path_exists

at.outputFileName = g.os_path_join(g.app.testDir,'xyzzy1')
at.targetFileName = g.os_path_join(g.app.testDir,'xyzzy2')

# Create both paths (different contents)
for p in (at.outputFileName,at.targetFileName):
    if exists(p):
        os.remove(p)
    assert not exists(p)
    f = open(p,'w')
    s = 'test %s' % p
    # print(repr(p),repr(s))
    f.write(s)
    f.close()
    assert exists(p) # , '%s does not exist' % repr(p)

at.toString = False # Set by execute script stuff.
at.shortFileName = at.targetFileName
root = at.root
assert at.replaceTargetFileIfDifferent(root), 'replaceTargetFileIfDifferent returns False'
if 0:
    print('%s exists %s' % (at.outputFileName,exists(at.outputFileName)))
    print('%s exists %s' % (at.targetFileName,exists(at.targetFileName)))
assert not exists(at.outputFileName), 'oops, output file exists'
assert exists(at.targetFileName), 'oops, target file does not exist'
f = open(at.targetFileName)
s = f.read()
f.close()
# print('Contents of %s: %s' % (at.targetFileName,s))
assert s == 'test %s' % at.outputFileName, 'unexpected contents of target file'
os.remove(at.targetFileName)
#@+node:ekr.20050105095743: *4* @test at.replaceTargetFileIfDifferent (identical)
import os

at = c.atFileCommands
exists = g.os_path_exists

at.outputFileName = g.os_path_join(g.app.testDir,'xyzzy1')
at.targetFileName = g.os_path_join(g.app.testDir,'xyzzy2')

# Create both paths (identical contents)
for p in (at.outputFileName,at.targetFileName):
    if exists(p):
        os.remove(p)
    assert not exists(p)
    f = open(p,'w')
    s = 'test %s' % at.outputFileName
    # print(repr(p),repr(s))
    f.write(s)
    f.close()
    assert exists(p)

at.toString = False # Set by execute script stuff.
at.shortFileName = at.targetFileName
root = at.root
assert not at.replaceTargetFileIfDifferent(root), 'replaceTargetFileIfDifferent returns True'
if 0:
    print('%s exists %s' % (at.outputFileName,exists(at.outputFileName)))
    print('%s exists %s' % (at.targetFileName,exists(at.targetFileName)))
assert not exists(at.outputFileName), 'oops, output file exists'
assert exists(at.targetFileName), 'oops, target file does not exist'
f = open(at.targetFileName)
s = f.read()
f.close()
# print('Contents of %s: %s' % (at.targetFileName,s))
assert s == 'test %s' % at.outputFileName, 'unexpected contents of target file'
os.remove(at.targetFileName)
#@+node:ekr.20050105100227: *4* @test at.replaceTargetFileIfDifferent (no target file)
import os

at = c.atFileCommands
exists = g.os_path_exists

at.outputFileName = g.os_path_join(g.app.testDir,'xyzzy1')
at.targetFileName = g.os_path_join(g.app.testDir,'xyzzy2')

# Remove both files, then create only the output file
for p in (at.outputFileName,at.targetFileName):
    if exists(p):
        os.remove(p)

for p in (at.outputFileName,):
    assert not exists(p)
    f = open(p,'w')
    s = 'test %s' % at.outputFileName
    # print(repr(p),repr(s))
    f.write(s)
    f.close()
    assert exists(p)

at.toString = False # Set by execute script stuff.
at.shortFileName = at.targetFileName
root = at.root
assert not at.replaceTargetFileIfDifferent(root), 'replaceTargetFileIfDifferent returns True'
if 0:
    print('%s exists %s' % (at.outputFileName,exists(at.outputFileName)))
    print('%s exists %s' % (at.targetFileName,exists(at.targetFileName)))
assert not exists(at.outputFileName), 'oops, output file exists'
assert exists(at.targetFileName), 'oops, target file does not exist'
f = open(at.targetFileName)
s = f.read()
f.close()
# print('Contents of %s: %s' % (at.targetFileName,s))
assert s == 'test %s' % at.outputFileName, 'unexpected contents of target file'
os.remove(at.targetFileName)
#@+node:ekr.20090529115704.4567: *4* @test at.writeOneAtShadowNode
at = c.atFileCommands
x = c.shadowController
changed = c.changed
child = p.firstChild()
s = child.b

try:
    child.setHeadString('@shadow unittest/test_1.py')
    fn = 'unittest/test_1.py'
    shadow_fn = x.shadowPathName(fn)
    shadow_dir = x.shadowDirName(fn)
    x.makeShadowDirectory(shadow_dir)
    if g.os_path_exists(shadow_fn):
        g.utils_remove(shadow_fn,verbose=True)
    at.writeOneAtShadowNode(child,toString=True,force=True)
    assert at.startSentinelComment == '#','startSentinelComment: %s' % (
        repr(at.startSentinelComment))
    assert at.endSentinelComment == '','endSentinelComment: %s' % (
        repr(at.endSentinelComment))
    if 0:
        print('public...\n',at.public_s)
        print('private...\n',at.private_s)
    at.writeOneAtShadowNode(child,toString=False,force=True)
    assert g.os_path_exists(shadow_fn),'not found: %s' % shadow_fn
    # No need to remove this: it's in the unittest directory.
    # g.utils_remove(shadow_fn,verbose=True)
finally:

    child.setHeadString('@@shadow unittest/test_1.py')
    c.setChanged(changed)
    # c.redraw_now()
#@+node:ekr.20090529115704.4568: *5* @@shadow unittest/test_1.py
# body of @shadow test node
# The last line.
#@+node:ekr.20071113145804.7: *4* @test parseLeoSentinel
s1 = '#@+leo-ver=4-thin-encoding=utf-8,.'  # 4.2 format.
s2 = '#@+leo-ver=4-thin-encoding=utf-8.' # pre-4.2 format.

at=c.atFileCommands # Self is a dummy argument.

for s in (s1,s2):
    valid,new_df,start,end,isThinDerivedFile = at.parseLeoSentinel(s)
    # g.trace('start',start,'end',repr(end),'len(s)',len(s))
    assert valid, 'not valid'
    assert new_df, 'not new_df'
    assert isThinDerivedFile, 'not thin'
    assert end == '', 'invalid end: %s' % repr(end)
    assert at.encoding == 'utf-8', 'bad encoding: %s' % repr(at.encoding)
#@+node:ekr.20060602195313: *4* @test reads/write using @comment
at = c.atFileCommands
child = p.firstChild()
child2 = child.next()
result = str(child2.b)
at.write(child,nosentinels=False,thinFile=False,scriptWrite=False,toString=True)
s = str(at.stringOutput)

if s != result:
    print('-' * 30)
    print(s)
    print('-' * 30)
    print(result)

assert s == result
#@+node:ekr.20060602195313.2: *5* root
@language c
#ifdef COMMENT
@comment /* */ 
#endif
@tabwidth 4
@lineending crlf

@others

<< Get LRR Task >>
<< Start LRR >>
#@+node:ekr.20060602195313.3: *6* << Get LRR Task >>
#@+node:ekr.20060602195313.4: *6* << Start LRR >>
#@+node:ekr.20060602195914: *5* Result
/*@+leo-ver=5*/
/*@+node:root*/
/*@@language c*/
#ifdef COMMENT
/*@@comment /* */ */
#endif
/*@@tabwidth 4*/
/*@@lineending crlf*/

/*@+others*/
/*@-others*/

/*@+<< Get LRR Task >>*/
/*@+node:<< Get LRR Task >>*/
/*@-<< Get LRR Task >>*/
/*@+<< Start LRR >>*/
/*@+node:<< Start LRR >>*/
/*@-<< Start LRR >>*/
/*@-leo*/
#@+node:ekr.20100131180007.5462: *4* @test verbatim sentinel
# Here is something that should generate a verbtim sentinel::

#@verbatim
#@+leo-encoding=iso-8859-1.

# The length of this node should remain constant.

assert len(p.b) == 175,len(p.b)
#@+node:ekr.20110615130436.3319: *4* @test writing a .leo file retains orphan bits
# Writing a .leo file must retain orphan bits of erroneous external files.

h = '@file nonexistent-directory/orphan-bit-test.txt'
p2 = g.findNodeAnywhere(c,h)
assert p2,'not found: %s' % (h)
assert p2.isOrphan(),'not an orphan originally'

# It's dangerous to do the write, but this does test the bug fix.
c.atFileCommands.clearAllOrphanBits(p2)
assert p2.isOrphan(),'not an orphan after calling at.clearAllOrphanBits'
#@+node:ekr.20071113201736: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

print('\nEnd of leoAtFile tests')
#@+node:ekr.20101021205258.6011: *4* at.Directives & directories
#@+node:ekr.20100131180007.5455: *5* @test at.fullDirectoryPath
at = c.atFileCommands

p2 = p.firstChild().firstChild()
path = at.fullPath(p2,simulate=True)
end = g.os_path_normpath('abc/xyz')
assert path.endswith(end),repr(path)
#@+node:ekr.20100131180007.5456: *6* @path abc
#@+node:ekr.20100131180007.5457: *7* xyz
#@+node:ekr.20100131180007.5454: *5* @test at.get/setPathUa
at = c.atFileCommands

at.setPathUa(p,'abc')
d = p.v.tempAttributes
d2 = d.get('read-path')
val1 = d2.get('path')
val2 = at.getPathUa(p)

table = (
    ('d2.get',val1),
    ('at.getPathUa',val2),
)
for kind,val in table:
    assert val == 'abc','kind %s expected %s got %s' % (
        kind,'abc',val)
#@+node:ekr.20100131180007.5461: *5* @test at.replaceFileWithString
at = c.atFileCommands

fn = 'does/not/exist'
assert not g.os_path_exists(fn)
assert not at.replaceFileWithString (fn,'abc')
#@+node:ekr.20100131180007.5458: *5* @test at.scanAllDirectives (minimal)
at = c.atFileCommands
d = at.scanAllDirectives(p)
#@+node:ekr.20071113090055.4: *5* @test at.scanAllDirectives
# This will work regardless of where this method is.
@language python
@tabwidth -4
# @path xyzzy # Creates folder called xyzzy: interferes with other unit tests.
@pagewidth 120

d = c.atFileCommands.scanAllDirectives(p)

assert d.get('language') == 'python'
assert d.get('tabwidth') == -4
# assert d.get('path').endswith('xyzzy')
assert d.get('pagewidth') == 120
#@+node:ekr.20101021210253.6018: *4* Unused
#@+node:ekr.20040712101754.103: *5* @@test @file no newline
import leo.core.leoTest as leoTest

leoTest.runAtFileTest(c,p)
#@+node:ekr.20040712101754.104: *6* #@file
Line 1

@last last line 1: no newline
#@+node:ekr.20040712101754.105: *6* Output
#@verbatim
#@+leo-ver=4
#@verbatim
#@+node:#@file
Line 1

#@verbatim
#@@last
#@verbatim
#@nonl
#@verbatim
#@-node:#@file
#@verbatim
#@-leo
last line 1: no newline
#@+node:ekr.20040712101754.106: *5* @@test @file one newline
import leo.core.leoTest as leoTest

leoTest.runAtFileTest(c,p)
#@+node:ekr.20040712101754.107: *6* #@file
Line 1

@last last line 1: newline
#@+node:ekr.20040712101754.108: *6* Output
#@verbatim
#@+leo-ver=4
#@verbatim
#@+node:#@file
Line 1

#@verbatim
#@@last
#@verbatim
#@-node:#@file
#@verbatim
#@-leo
last line 1: newline
#@+node:ekr.20040712101754.109: *5* @@test @file two newlines
import leo.core.leoTest as leoTest

leoTest.runAtFileTest(c,p)
#@+node:ekr.20040712101754.110: *6* #@file
Line 1

@last last line 1: two trailing newlines
#@+node:ekr.20040712101754.111: *6* Output
#@verbatim
#@+leo-ver=4
#@verbatim
#@+node:#@file
Line 1

#@verbatim
#@@last
#@verbatim
#@-node:#@file
#@verbatim
#@-leo
last line 1: two trailing newlines
#@+node:ekr.20090704085350.5010: *5* @@test @file: shape of tree
h = '@file ../test/unittest/at-file-test.py'
p = g.findNodeAnywhere(c,h)
assert p
assert not p.isDirty(),p.h # Do not ignore this failure!

table = (
    (p.firstChild(),'spam'),
    (p.firstChild().next(),'eggs')
)

for p2,h2 in table:
    assert p2.h == h2
    assert len(p2.b) > 10
#@+node:ekr.20100131171342.5508: *3* leoBridge
#@+node:ekr.20100131171342.5509: *4* @test leoBridge init logic
import leo.core.leoBridge as leoBridge

if 0: # This can not be run locally: it contains another Tk event loop.
    controller = leoBridge.controller(gui='nullGui',verbose=False)
    g = controller.globals()
#@+node:ekr.20090615053403.4876: *3* leoColor
#@+node:ekr.20090615053403.4877: *4* @test @comment after @language plain
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4878: *5* plain code
@language plain
@comment # /* */

This is plain text.

# This is a comment.

More plain text.

/* A block comment
continues */

More plain text.
#@+node:ekr.20090615053403.4879: *4* @test colorizer Actionscript
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4880: *5* actionscript test
@language actionscript

break
call, continue
delete, do
else
false, for, function
goto
if, in
new, null
return
true, typeof
undefined
var, void, while, with
#include
catch, constructor
prototype
this, try
_parent, _root, __proto__
// Jeeze hasn't anyone ever heard of namespaces??
ASnative, abs, acos, appendChild, asfunction, asin, atan, atan2, attachMovie, attachSound, attributes
BACKSPACE
CAPSLOCK, CONTROL, ceil, charAt, charCodeAt, childNodes, chr, cloneNode, close, concat, connect, cos, createElement, createTextNode
DELETEKEY, DOWN, docTypeDecl, duplicateMovieClip
END, ENTER, ESCAPE, enterFrame, entry, equal, eval, evaluate, exp
firstChild, floor, fromCharCode, fscommand, getAscii
getBeginIndex, getBounds, getBytesLoaded, getBytesTotal, getCaretIndex, getCode, getDate, getDay, getEndIndex, getFocus, getFullYear, getHours, getMilliseconds, getMinutes, getMonth, getPan, getProperty, getRGB, getSeconds, getTime, getTimer, getTimezoneOffset, getTransform, getURL, getUTCDate, getUTCDay, getUTCFullYear, getUTCHours, getUTCMilliseconds, getUTCMinutes, getUTCMonth, getUTCSeconds, getVersion, getVolume, getYear, globalToLocal, gotoAndPlay, gotoAndStop
HOME, haschildNodes, hide, hitTest
INSERT, Infinity, ifFrameLoaded, ignoreWhite, indexOf, insertBefore, int, isDown, isFinite, isNaN, isToggled
join
keycode, keyDown, keyUp
LEFT, LN10, LN2, LOG10E, LOG2E, lastChild, lastIndexOf, length, load, loaded, loadMovie, loadMovieNum, loadVariables, loadVariablesNum, localToGlobal, log
MAX_VALUE, MIN_VALUE, max, maxscroll, mbchr, mblength, mbord, mbsubstring, min, 
NEGATIVE_INFINITY, NaN, newline, nextFrame, nextScene, nextSibling, nodeName, nodeType, nodeValue
on, onClipEvent, onClose, onConnect, onData, onLoad, onXML, ord
PGDN, PGUP, PI, POSITIVE_INFINITY, parentNode, parseFloat, parseInt, parseXML, play, pop, pow, press, prevFrame, previousSibling, prevScene, print, printAsBitmap, printAsBitmapNum, printNum, push
RIGHT, random, release, removeMovieClip, removeNode, reverse, round
SPACE, SQRT1_2, SQRT2, scroll, send, sendAndLoad, set, setDate, setFocus, setFullYear, setHours, setMilliseconds, setMinutes, setMonth, setPan, setProperty, setRGB, setSeconds, setSelection, setTime, setTransform, setUTCDate, setUTCFullYear, setUTCHours, setUTCMilliseconds, setUTCMinutes, setUTCMonth, setUTCSeconds, setVolume, setYear, shift, show, sin, slice, sort, start, startDrag, status, stop, stopAllSounds, stopDrag, substr, substring, swapDepths, splice, split, sqrt
TAB, tan, targetPath, tellTarget, toggleHighQuality, toLowerCase, toString, toUpperCase, trace
UP, UTC, unescape, unloadMovie, unLoadMovieNum, unshift, updateAfterEvent
valueOf
xmlDecl, _alpha
_currentframe
_droptarget
_focusrect, _framesloaded
_height, _highquality
_name
_quality
_rotation
_soundbuftime
_target, _totalframes
_url
_visible
_width
_x, _xmouse, _xscale
_y, _ymouse, _yscale
and, add, eq, ge, gt, le, lt, ne, not, or, Array, Boolean, Color, Date, Key, Math, MovieClip, Mouse, Number, Object, Selection, Sound, String, XML, XMLSocket
#@+node:ekr.20090615053403.4881: *4* @test colorizer C
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4882: *5* c code
@language c
@comment /* */

@
@c

#define WIPEOUT 0 /* 
                   * Causes database card number & flags to be set to zero. 
                   * This is so I don't need an infinite supply of cards!
                   */
// Not colored (because of @language /* */)
#include "equ.h"
#include "cmn.h"
#include "ramdef.h"
#include "eeprom.h"
#include <hpc_ram.h>
#include <rlydef.h>
#@+node:ekr.20090615053403.4883: *4* @test colorizer C#
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4884: *5* c# code
@language csharp
@ comment
@c

/* block
comment */

// test

id // not a keyword

abstract as 
base bool break byte 
case catch char checked class const continue 
decimal default delegate do double 
else enum event explicit extern 
false finally fixed float for foreach 
get goto 
if implicit in int interface internal is 
lock long 
namespace new null 
object operator out override 
params partial private protected public 
readonly ref return 
sbyte sealed set short sizeof stackalloc 
static string struct switch 
this throw true try typeof 
uint ulong unchecked unsafe ushort using 
value virtual void volatile 
where while
yield
#@+node:ekr.20090615053403.4885: *4* @test colorizer css
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4886: *5* css
@language css
/* New in 4.2. */

/*html tags*/
address, applet, area, a, base, basefont,
big, blockquote, body, br, b, caption, center,
cite, code, dd, dfn, dir, div, dl, dt, em, font,
form, h1, h2, h3, h4, h5, h6, head, hr, html, img,
input, isindex, i, kbd, link, li, link, map, menu,
meta, ol, option, param, pre, p, samp,
select, small, span, strike, strong, style, sub, sup,
table, td, textarea, th, title, tr, tt, ul, u, var,
/*units*/
mm, cm, in, pt, pc, em, ex, px,
/*colors*/
aqua, black, blue, fuchsia, gray, green, lime, maroon, navy, olive, purple, red, silver, teal, yellow, white,
/*important directive*/
!important,
/*font rules*/
font, font-family, font-style, font-variant, font-weight, font-size,
/*font values*/
cursive, fantasy, monospace, normal, italic, oblique, small-caps,
bold, bolder, lighter, medium, larger, smaller,
serif, sans-serif,
/*background rules*/
background, background-color, background-image, background-repeat, background-attachment, background-position,
/*background values*/
contained, none, top, center, bottom, left, right, scroll, fixed,
repeat, repeat-x, repeat-y, no-repeat,
/*text rules*/
word-spacing, letter-spacing, text-decoration, vertical-align, text-transform, text-align, text-indent, text-transform, text-shadow, unicode-bidi, line-height,
/*text values*/
normal, none, underline, overline, blink, sub, super, middle, top, text-top, text-bottom,
capitalize, uppercase, lowercase, none, left, right, center, justify,
line-through,
/*box rules*/
margin, margin-top, margin-bottom, margin-left, margin-right,
margin, padding-top, padding-bottom, padding-left, padding-right,
border, border-width, border-style, border-top, border-top-width, border-top-style, border-bottom, border-bottom-width, border-bottom-style, border-left, border-left-width, border-left-style, border-right, border-right-width, border-right-style, border-color,
/*box values*/
width, height, float, clear,
auto, thin, medium, thick, left, right, none, both,
none, dotted, dashed, solid, double, groove, ridge, inset, outset,
/*display rules*/
display, white-space, 
min-width, max-width, min-height, max-height,
outline-color, outline-style, outline-width,
/*display values*/
run-in, inline-block, list-item, block, inline, none, normal, pre, nowrap, table-cell, table-row, table-row-group, table-header-group, inline-table, table-column, table-column-group, table-cell, table-caption
/*list rules*/
list-style, list-style-type, list-style-image, list-style-position,
/*list values*/
disc, circle, square, decimal, decimal-leading-zero, none,
lower-roman, upper-roman, lower-alpha, upper-alpha, lower-latin, upper-latin,
/*table rules*/
border-collapse, caption-side,
/*table-values*/
empty-cells, table-layout,
/*misc values/rules*/
counter-increment, counter-reset,
marker-offset, z-index,
cursor, direction, marks, quotes,
clip, content, orphans, overflow, visibility,
/*aural rules*/
pitch, range, pitch-during, cue-after, pause-after, cue-before, pause-before, speak-header, speak-numeral, speak-punctuation, speed-rate, play-during, voice-family,
/*aural values*/
stress, azimuth, elevation, pitch, richness, volume,
page-break, page-after, page-inside
#@+node:ekr.20090615053403.4887: *4* @test colorizer CWEB
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4888: *5* CWEB
@language cweb

% This is limbo in cweb mode... It should be in \LaTeX mode, not \c mode.
% The following should not be colorized: class,if,else.

@* this is a _cweb_ comment.  Code is written in \c.
"strings" should not be colorized.
It should be colored in \LaTeX mode.
The following are not keywords in latex mode: if, else, etc.
Noweb section references are _valid_ in cweb comments!
<< section ref >>
<< missing ref >>
@c

and this is C code. // It is colored in \LaTeX mode by default.
/* This is a C block comment.  It may also be colored in restricted \LaTeX mode. */

// Section refs are valid in code too, of course.
<< section ref >>
<< missing ref >>

\LaTeX and \c should not be colored.
if else, while, do // C keywords.
#@+node:ekr.20090615053403.4889: *6* << section ref >>
<< section def >>=

    my \c code goes here // This is \LaTeX text
    /* This is also \LaTeX text */
#@+node:ekr.20110521073115.3486: *4* @test colorizer cython
@language python

p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20110521073115.3490: *5* cython
@language cython

by cdef cimport cpdef ctypedef enum except?
extern gil include nogil property public
readonly struct union DEF IF ELIF ELSE
                    
NULL bint char dict double float int list
long object Py_ssize_t short size_t void

try:
    pass
except Exception:
    pass

#@+node:ekr.20090615053403.4890: *4* @test colorizer elisp
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4891: *5* elisp
@language elisp

; Maybe...
error princ 

; More typical of other lisps...
and apply
car cdr cons cond
defconst defun defvar 
eq equal eval
gt ge
if 
let le lt
mapcar 
ne nil 
or not 
prog progn 
set setq 
t type-of 
unless 
when while
#@+node:ekr.20090615053403.4892: *4* @test colorizer erlang
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4893: *5* erlang
@language erlang

halt()

-module()
#@+node:ekr.20090615053403.4894: *4* @test colorizer forth
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4895: *5* forth
@language forth

\ tiny demo of Leo forth syntax colouring

: some-forth-word ( x1 x2 -- x3 ) \ blue :, black/bold some-forth-word
   label: y  \ blue label:
   asm[ s" some string" type ]asm cr
   asm[ abc ]asm
   a
   s" abc "
   s" abc"
   a
   tty" abc "
   lcd2" abc "
   until

@ test
@c

{ abc }

a b @ c

asm[ abc ]asm

.( ab ) \ a string

: foo [ .s ] ;

   [ a b c
   x y z]
;
#@+node:ekr.20090615053403.4896: *4* @test colorizer HTML string bug
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4897: *5* html
@language html

b = "cd"
d
#@+node:ekr.20090615053403.4898: *4* @test colorizer HTML1
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4899: *5* html
@language html

<HTML>
<!-- Author: Edward K. Ream, edream@tds.net -->
<HEAD>
  <META NAME="GENERATOR" CONTENT="Microsoft FrontPage 4.0">
  <TITLE> Leo's Home Page </TITLE>
  <META NAME="description" CONTENT="This page describes Leo.
Leo adds powerful outlines to the noweb and CWEB literate programming languages.">
  <META NAME="keywords" CONTENT="LEO, LITERATE PROGRAMMING, OUTLINES, CWEB,
NOWEB, OUTLINES, EDWARD K. REAM, DONALD E. KNUTH, SILVIO LEVY, OPEN SOFTWARE">
</HEAD>
<!-- Last Modified: May 12, 2002 -->
<BODY BGCOLOR="#fffbdc">

<H1 ALIGN=CENTER><a NAME="top"></a><IMG SRC="Blank.gif" width=
"32" height="32" ALIGN="BOTTOM" NATURALSIZEFLAG="3"><IMG SRC="leo.gif" 
WIDTH="32" HEIGHT="32" ALIGN="BOTTOM" NATURALSIZEFLAG="3"><a href="leo_TOC.html#top"><IMG SRC=
"arrow_rt.gif" WIDTH="32" HEIGHT="32" ALIGN="BOTTOM" NATURALSIZEFLAG="3"></a> &nbsp;</H1>

<H1 ALIGN=CENTER> Leo's Home Page</H1>

<p align="center"><a href="http://www.python.org/"><img border="0" src="PythonPowered.gif" width="110" height="44"> </a> <A HREF="http://sourceforge.net/"><IMG SRC="http://sourceforge.net/sflogo.php?group_id=3458&type=1" NATURALSIZEFLAG="0" ALT="SourceForge Logo"></A>&nbsp;&nbsp;&nbsp;
<A HREF="http://sourceforge.net/project/?group_id=3458">Leo at SourceForge</A>&nbsp;&nbsp;
<a href="icons.html"><img border="0" src="LeoCodeGray.gif" width="77" height="42"></a>&nbsp;&nbsp;
<a href="icons.html"><img border="0" src="LeoProse.gif" width="81" height="42"></a>&nbsp;&nbsp;&nbsp;&nbsp;

<H3><A NAME="anchor127554"></A>Summary</H3>

<UL>
  <LI>Leo is a <i> programmer's editor</i>  and a flexible <i>browser</i> for
    projects, programs, classes or data. Leo clarifies design, coding, debugging, testing
  and maintenance.
  <LI>Leo is an <i>outlining editor</i>. Outlines clarify the big picture while
    providing unlimited space for details.
  <LI>Leo
    is a <a HREF="http://www.literateprogramming.com/"><i>literate
    programming</i></a> tool, compatible with <A HREF="http://www.eecs.harvard.edu/~nr/noweb/">noweb</A>
    and <a HREF="http://www-cs-faculty.stanford.edu/~knuth/cweb.html">CWEB</a>.
    Leo enhances any text-based
programming language, from assembly language and C to Java, Python and XML.
  <LI>Leo is also a <i>data organizer</i>. A single Leo outline can generate complex
    data spanning many different files.&nbsp; Leo has been used to manage web sites.
  <LI>Leo is a <i> project manager</i>. Leo provides multiple views
of a project within a single outline. Leo naturally represents tasks that remain
    up-to-date.
  <LI>Leo is fully <i> scriptable</i> using <A HREF="http://www.python.org/">Python</A>
  and saves its files in <A HREF="http://www.w3.org/XML/">XML</A> format.
  <LI>Leo is <i>portable</i>.&nbsp; Leo.py is 100% pure Python and will run on
    any platform supporting <A HREF="http://www.python.org/">Python</A>
    and <a href="http://tcl.activestate.com/">Tk/tcl</a>, including Windows,
    Linux and MacOS X.&nbsp; Leo.exe runs on any Windows platform.
  <LI>Leo is <a href="http://www.opensource.org/"> <i> Open Software</i></a>, distributed under
    the <a href="http://www.python.org/doc/Copyright.html"> Python License</a>.
</UL>

<H3>More Information and downloads</H3>

<ul>
  <LI>An excellent <a href="http://www.3dtree.com/ev/e/sbooks/leo/sbframetoc_ie.htm">online
    tutorial</a> and <A HREF="http://www.jserv.com/jk_orr/xml/leo.htm">Leo resource
  page</A>, both written by <a href="http://www.jserv.com/jk_orr">Joe Orr</a>.
  <LI>My brother's <a href="SpeedReam.html">slashdot
    article about Leo</a>, the best description about why Leo is special.
  <LI><A HREF="testimonials.html#anchor104391">What people are saying about Leo</A>
  <LI><A HREF="leo_TOC.html#anchor964914">Complete users guide</A>
    and
    <A HREF="intro.html#anchor887874">tutorial introduction</A>  with
  screen shots.
  <li><a href="FAQ.html">FAQ</a> and <a href="http://sourceforge.net/forum/?group_id=3458">help and discussion
    forums</a>, preferable to <A HREF="mailto:edream@tds.net">email</A> so others may join
    in.</li>
  <li><a href="icons.html">Icons</a> for bragging about Leo.</li>
</ul>

<a href="http://sourceforge.net/project/showfiles.php?group_id=3458">Download
    Leo</a> from <A HREF="http://sourceforge.net/project/?group_id=3458">Leo's SourceForge
site</A>.

<P ALIGN=left>Leo's author is <A HREF="http://personalpages.tds.net/~edream/index.html">Edward
  K. Ream</A> email: <A HREF="mailto:edream@tds.net">edream@tds.net</A> voice: (608) 231-0766

<HR ALIGN=LEFT>

<p align="center">

<IMG SRC="Blank.gif" ALIGN="left" NATURALSIZEFLAG=
"3" width="34" height="34"><IMG SRC="leo.gif" ALIGN="left" NATURALSIZEFLAG=
"3" width="32" height="32"><a HREF="leo_TOC.html"><IMG SRC="arrow_rt.gif" WIDTH="32"
HEIGHT="32" ALIGN="left" NATURALSIZEFLAG="3">

</BODY>
</HTML>
#@+node:ekr.20090615053403.4900: *4* @test colorizer HTML2
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4901: *5* html
@language html

<? xml version="1.0">
<!-- test -->
<project name="Converter" default="dist">
</project>"""
#@+node:ekr.20090615053403.4902: *4* @test colorizer Java
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4903: *5* html
@ doc part
@c

@language java /* Colored by match_leo_keyword: tag = leoKeyword. */

@whatever /* Colored by java match_following rule: tag = keyword4. */

/** A javadoc: tag = comment3 */

/** <!-- comment --> tag = comment1. */

/** @see tag = label */
#@+node:ekr.20090615053403.4904: *4* @test colorizer LaTex
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4905: *5* LaTex
@language latex

% This is a \LaTeX mode comment.

This is a test of \LaTeX mode.

@ blah blah blah
@c

\c and \LaTeX are latex keywords.

This is a keyword \% not the start of a comment.

More keywords: \@ and \( and \) and \{ and \}

The following should be colored:

\documentclass{report}

The following 2-letter words should be colored, regardless of what follows:

\(\)\{\}\@
\(abc\)abc\{abc\}abc\@abc
#@+node:ekr.20090615053403.4906: *4* @test colorizer lisp
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4907: *5* lisp
@language lisp

; Maybe...
error princ 

; More typical of other lisps...
and apply
car cdr cons cond
defconst defun defvar 
eq equal eval
gt ge
if 
let le lt
mapcar 
ne nil 
or not 
prog progn 
set setq 
t type-of 
unless 
when while
#@+node:ekr.20101020123501.6005: *4* @test colorizer objective-c
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20101020123501.6006: *5* objective-c
@language objective_c

@interface Application
    -(void) init;
    -(void) showMessage;
@end

@implementation Application 
    -(id) init {
        if (self = [super init]) {
            NSLog(@"Init ok");
            return self;
        }
        return nil;
    }
    -(void) showMessage {
        NSLog(@"Hello there");
    }
@end

@"Hello there"

,@interface
, @interface
the @interface

// By the way, I have noticed that such kind of words in doxygen block
// are highlighted properly, but they are labels here, not keywords1 as in my case.
/**
@var test
@todo
*/
#@+node:ekr.20090615053403.4908: *4* @test colorizer perl
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4909: *5* perl
@language perl

# From a perl tutorial.

print 'Hello world.';		# Print a message

$a = $b;	# Assign $b to $a

@food  = ("apples", "pears", "eels");

$grub = pop(@food);	# Now $grub = "eels"

$#food

@lines = <INFO>;

#!/usr/local/bin/perl
print "Password? ";		# Ask for input
$a = <STDIN>;			# Get input
chop $a;			# Remove the newline at end
while ($a ne "fred")		# While input is wrong...
{
    print "sorry. Again? ";	# Ask again
    $a = <STDIN>;		# Get input again
    chop $a;			# Chop off newline again
}

if ($sentence =~ /under/)
{
	print "We're talking about rugby\\n";
}

$sentence =~ s/london/London/

$_ = "Capes:Geoff::Shot putter:::Big Avenue";
@personal = split(/:/);

foreach $age (values %ages)
{
	print "Somebody is $age\\n";
}

&mysubroutine;		# Call the subroutine
&mysubroutine($_);	# Call it with a parameter
&mysubroutine(1+2, $_);	# Call it with two parameters

sub inside
{
	local($a, $b);			# Make local variables
	($a, $b) = ($_[0], $_[1]);	# Assign values
	$a =~ s/ //g;			# Strip spaces from
	$b =~ s/ //g;			#   local variables
	($a =~ /$b/ || $b =~ /$a/);	# Is $b inside $a
					#   or $a inside $b?
}
#@+node:ekr.20090615053403.4910: *4* @test colorizer PHP
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4911: *5* PHP
@language php
@ doc
This is a doc part.
@c

and or
array
array()
/* Multi-line comment
*/
this is a test.
__CLASS__
<?php and or array() ?>
<?PHP and or array() ?>
#@+node:ekr.20090615053403.4912: *4* @test colorizer plsql
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4913: *5* plsql
@language plsql

"a string"
-- reserved keywords
ABORT,
abort,
ACceSS,
access,
add,
all,
allocate,
alter,
analyze,
and,
any,
archive,
archivelog,
array,
arraylen,
as,
asc,
assert,
assign,
at,
audit,
authorization,
avg,
backup,
base_table,
become,
before,
begin,
between,
binary_integer,
block,
body,
boolean,
by,
cache,
cancel,
cascade,
case,
change,
char,
char_base,
character,
check,
checkpoint,
close,
cluster,
clusters,
cobol,
colauth,
column,
columns,
comment,
commit,
compile,
compress,
connect,
constant,
constraint,
constraints,
contents,
continue,
controlfile,
count,
crash,
create,
current,
currval,
cursor,
cycle,
data_base,
database,
datafile,
date,
dba,
debugoff,
debugon,
dec,
decimal,
declare,
default,
definition,
delay,
delete,
delta,
desc,
digits,
disable,
dismount,
dispose,
distinct,
distinct,
do,
double,
drop,
drop,
dump,
each,
else,
else,
elsif,
enable,
end,
end,
entry,
escape,
events,
except,
exception,
exception_init,
exceptions,
exclusive,
exec,
execute,
exists,
exists,
exit,
explain,
extent,
externally,
false,
fetch,
fetch,
file,
float,
float,
flush,
for,
for,
force,
foreign,
form,
fortran,
found,
freelist,
freelists,
from,
from,
function,
generic,
go,
goto,
grant,
group,
groups,
having,
identified,
if,
immediate,
in,
including,
increment,
index,
indexes,
indicator,
initial,
initrans,
insert,
instance,
int,
integer,
intersect,
into,
is,
key,
language,
layer,
level,
like,
limited,
link,
lists,
lock,
logfile,
long,
loop,
manage,
manual,
max,
maxdatafiles,
maxextents,
maxinstances,
maxlogfiles,
maxloghistory,
maxlogmembers,
maxtrans,
maxvalue,
min,
minextents,
minus,
minvalue,
mlslabel,
mod,
mode,
modify,
module,
mount,
natural,
new,
new,
next,
nextval,
noarchivelog,
noaudit,
nocache,
nocompress,
nocycle,
nomaxvalue,
nominvalue,
none,
noorder,
noresetlogs,
normal,
nosort,
not,
notfound,
nowait,
null,
number,
number_base,
numeric,
of,
off,
offline,
old,
on,
online,
only,
open,
open,
optimal,
option,
or,
order,
others,
out,
own,
package,
package,
parallel,
partition,
pctfree,
pctincrease,
pctused,
plan,
pli,
positive,
pragma,
precision,
primary,
prior,
private,
private,
privileges,
procedure,
procedure,
profile,
public,
quota,
raise,
range,
raw,
read,
real,
record,
recover,
references,
referencing,
release,
remr,
rename,
resetlogs,
resource,
restricted,
return,
reuse,
reverse,
revoke,
role,
roles,
rollback,
row,
rowid,
rowlabel,
rownum,
rows,
rowtype,
run,
savepoint,
schema,
scn,
section,
segment,
select,
select,
separate,
sequence,
session,
set,
set,
share,
shared,
size,
size,
smallint,
smallint,
snapshot,
some,
sort,
space,
sql,
sqlbuf,
sqlcode,
sqlerrm,
sqlerror,
sqlstate,
start,
start,
statement,
statement_id,
statistics,
stddev,
stop,
storage,
subtype,
successful,
sum,
sum,
switch,
synonym,
sysdate,
system,
tabauth,
table,
tables,
tables,
tablespace,
task,
temporary,
terminate,
then,
thread,
time,
to,
tracing,
transaction,
trigger,
triggers,
true,
truncate,
type,
uid,
under,
union,
unique,
unlimited,
until,
update,
use,
user,
using,
validate,
values,
varchar,
varchar2,
variance,
view,
views,
when,
whenever,
where,
while,
with,
work,
write,
xor
#@+node:ekr.20090615053403.4914: *4* @test colorizer python.xml (jEdit)
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4915: *5* python.xml
@language html

<?xml version="1.0"?>

<!DOCTYPE MODE SYSTEM "xmode.dtd">
<< remarks >>

<MODE>
    <PROPS>
        <PROPERTY NAME="indentPrevLine" VALUE="\s*.{3,}:\s*(#.*)?" />
        <PROPERTY NAME="lineComment" VALUE="#" />
    </PROPS>
    <RULES ESCAPE="\" IGNORE_CASE="FALSE" HIGHLIGHT_DIGITS="TRUE">
        << comments >>
        << literals >>
        << operators >>
        <MARK_PREVIOUS TYPE="FUNCTION" EXCLUDE_MATCH="TRUE">(</MARK_PREVIOUS>
        << keywords >>
    </RULES>
</MODE>
#@+node:ekr.20090615053403.4916: *6* << remarks >>
<!-- Python mode, by Slava Pestov. Based on PythonTokenMarker by -->
<!-- Jonathan Revusky -->

<!-- Modified 19-Jul-00 by Ivan Frohne to: -->
<!--  (a) implement 'indentOnEnter'; -->
<!--  (b) indent next line automatically after control structures followed -->
<!--	  by ':'; -->
<!--  (c) make """ or ''' multiline quotes TYPE LITERAL2; -->
<!--  (d) add TYPE FUNCTION identified by a following '(' -->
<!--  (e) eliminate the '?' SEQ TYPE ('?' has no meaning in Python); -->
<!--  (f) change the TYPE of 'and', 'or', and 'not' to KEYWORD1; and -->
<!--  (g) add all builtin functions, builtin exceptions, -->
<!--	  builtin type methods, File object methods, and special type -->
<!--	  attributes as TYPE KEYWORD3. -->
#@+node:ekr.20090615053403.4917: *6* << comments >>
<!-- Comment -->
<EOL_SPAN TYPE="COMMENT1">#</EOL_SPAN>

<!-- Triple-quotes -->
<SPAN TYPE="LITERAL2">
    <BEGIN>"""</BEGIN>
    <END>"""</END>
</SPAN>

<SPAN TYPE="LITERAL2">
    <BEGIN>'''</BEGIN>
    <END>'''</END>
</SPAN>
#@+node:ekr.20090615053403.4918: *6* << literals >>
<!-- Standard literals -->
<SPAN TYPE="LITERAL1">
    <BEGIN>"</BEGIN>
    <END>"</END>
</SPAN>

<SPAN TYPE="LITERAL1">
    <BEGIN>'</BEGIN>
    <END>'</END>
</SPAN>
#@+node:ekr.20090615053403.4919: *6* << operators >>
<SEQ TYPE="OPERATOR">=</SEQ>
<SEQ TYPE="OPERATOR">!</SEQ>
<SEQ TYPE="OPERATOR">&gt;=</SEQ>
<SEQ TYPE="OPERATOR">&lt;=</SEQ>
<SEQ TYPE="OPERATOR">+</SEQ>
<SEQ TYPE="OPERATOR">-</SEQ>
<SEQ TYPE="OPERATOR">/</SEQ>
<SEQ TYPE="OPERATOR">*</SEQ>
<SEQ TYPE="OPERATOR">&gt;</SEQ>
<SEQ TYPE="OPERATOR">&lt;</SEQ>
<SEQ TYPE="OPERATOR">%</SEQ>
<SEQ TYPE="OPERATOR">&amp;</SEQ>
<SEQ TYPE="OPERATOR">|</SEQ>
<SEQ TYPE="OPERATOR">^</SEQ>
<SEQ TYPE="OPERATOR">~</SEQ>
#@+node:ekr.20090615053403.4920: *6* << keywords >>
<KEYWORDS>
    << reserved words >>
    << builtins >>
    << exceptions >>
    << types >>
</KEYWORDS>
#@+node:ekr.20090615053403.4921: *7* << reserved words >>
<!--  Reserved Words  -->
<KEYWORD1>and</KEYWORD1>
<KEYWORD1>as</KEYWORD1>
<KEYWORD1>assert</KEYWORD1>
<KEYWORD1>break</KEYWORD1>
<KEYWORD1>class</KEYWORD1>
<KEYWORD1>continue</KEYWORD1>
<KEYWORD1>def</KEYWORD1>
<KEYWORD1>del</KEYWORD1>
<KEYWORD1>elif</KEYWORD1>
<KEYWORD1>else</KEYWORD1>
<KEYWORD1>except</KEYWORD1>
<KEYWORD1>exec</KEYWORD1>
<KEYWORD1>finally</KEYWORD1>
<KEYWORD1>for</KEYWORD1>
<KEYWORD1>from</KEYWORD1>
<KEYWORD1>global</KEYWORD1>
<KEYWORD1>if</KEYWORD1>
<KEYWORD1>import</KEYWORD1>
<KEYWORD1>in</KEYWORD1>
<KEYWORD1>is</KEYWORD1>
<KEYWORD1>lambda</KEYWORD1>
<KEYWORD1>not</KEYWORD1>
<KEYWORD1>or</KEYWORD1>
<KEYWORD1>pass</KEYWORD1>
<KEYWORD1>print</KEYWORD1>
<KEYWORD1>raise</KEYWORD1>
<KEYWORD1>return</KEYWORD1>
<KEYWORD1>try</KEYWORD1>
<KEYWORD1>while</KEYWORD1>
<KEYWORD1>yield</KEYWORD1>
#@+node:ekr.20090615053403.4922: *7* << builtins >>
<!-- builtins -->
<KEYWORD2>abs</KEYWORD2>
<KEYWORD2>apply</KEYWORD2>
<KEYWORD2>bool</KEYWORD2>
<KEYWORD2>buffer</KEYWORD2>
<KEYWORD2>callable</KEYWORD2>
<KEYWORD2>chr</KEYWORD2>
<KEYWORD2>classmethod</KEYWORD2>
<KEYWORD2>cmp</KEYWORD2>
<KEYWORD2>coerce</KEYWORD2>
<KEYWORD2>compile</KEYWORD2>
<KEYWORD2>complex</KEYWORD2>
<KEYWORD2>delattr</KEYWORD2>
<KEYWORD2>dict</KEYWORD2>
<KEYWORD2>dir</KEYWORD2>
<KEYWORD2>divmod</KEYWORD2>
<KEYWORD2>eval</KEYWORD2>
<KEYWORD2>execfile</KEYWORD2>
<KEYWORD2>file</KEYWORD2>
<KEYWORD2>filter</KEYWORD2>
<KEYWORD2>float</KEYWORD2>
<KEYWORD2>getattr</KEYWORD2>
<KEYWORD2>globals</KEYWORD2>
<KEYWORD2>hasattr</KEYWORD2>
<KEYWORD2>hash</KEYWORD2>
<KEYWORD2>hex</KEYWORD2>
<KEYWORD2>id</KEYWORD2>
<KEYWORD2>input</KEYWORD2>
<KEYWORD2>int</KEYWORD2>
<KEYWORD2>intern</KEYWORD2>
<KEYWORD2>isinstance</KEYWORD2>
<KEYWORD2>issubclass</KEYWORD2>
<KEYWORD2>iter</KEYWORD2>
<KEYWORD2>len</KEYWORD2>
<KEYWORD2>list</KEYWORD2>
<KEYWORD2>locals</KEYWORD2>
<KEYWORD2>long</KEYWORD2>
<KEYWORD2>map</KEYWORD2>
<KEYWORD2>max</KEYWORD2>
<KEYWORD2>min</KEYWORD2>
<KEYWORD2>object</KEYWORD2>
<KEYWORD2>oct</KEYWORD2>
<KEYWORD2>open</KEYWORD2>
<KEYWORD2>ord</KEYWORD2>
<KEYWORD2>pow</KEYWORD2>
<KEYWORD2>property</KEYWORD2>
<KEYWORD2>range</KEYWORD2>
<KEYWORD2>raw_input</KEYWORD2>
<KEYWORD2>reduce</KEYWORD2>
<KEYWORD2>reload</KEYWORD2>
<KEYWORD2>repr</KEYWORD2>
<KEYWORD2>round</KEYWORD2>
<KEYWORD2>setattr</KEYWORD2>
<KEYWORD2>slice</KEYWORD2>
<KEYWORD2>staticmethod</KEYWORD2>
<KEYWORD2>str</KEYWORD2>
<KEYWORD2>super</KEYWORD2>
<KEYWORD2>tuple</KEYWORD2>
<KEYWORD2>type</KEYWORD2>
<KEYWORD2>unichr</KEYWORD2>
<KEYWORD2>unicode</KEYWORD2>
<KEYWORD2>vars</KEYWORD2>
<KEYWORD2>xrange</KEYWORD2>
<KEYWORD2>zip</KEYWORD2>
#@+node:ekr.20090615053403.4923: *7* << exceptions >>
<!-- exceptions -->
<KEYWORD3>ArithmeticError</KEYWORD3>
<KEYWORD3>AssertionError</KEYWORD3>
<KEYWORD3>AttributeError</KEYWORD3>
<KEYWORD3>DeprecationWarning</KEYWORD3>
<KEYWORD3>EOFError</KEYWORD3>
<KEYWORD3>EnvironmentError</KEYWORD3>
<KEYWORD3>Exception</KEYWORD3>
<KEYWORD3>FloatingPointError</KEYWORD3>
<KEYWORD3>IOError</KEYWORD3>
<KEYWORD3>ImportError</KEYWORD3>
<KEYWORD3>IndentationError</KEYWORD3>
<KEYWORD3>IndexError</KEYWORD3>
<KEYWORD3>KeyError</KEYWORD3>
<KEYWORD3>KeyboardInterrupt</KEYWORD3>
<KEYWORD3>LookupError</KEYWORD3>
<KEYWORD3>MemoryError</KEYWORD3>
<KEYWORD3>NameError</KEYWORD3>
<KEYWORD3>NotImplemented</KEYWORD3>
<KEYWORD3>NotImplementedError</KEYWORD3>
<KEYWORD3>OSError</KEYWORD3>
<KEYWORD3>OverflowError</KEYWORD3>
<KEYWORD3>OverflowWarning</KEYWORD3>
<KEYWORD3>ReferenceError</KEYWORD3>
<KEYWORD3>RuntimeError</KEYWORD3>
<KEYWORD3>RuntimeWarning</KEYWORD3>
<KEYWORD3>StandardError</KEYWORD3>
<KEYWORD3>StopIteration</KEYWORD3>
<KEYWORD3>SyntaxError</KEYWORD3>
<KEYWORD3>SyntaxWarning</KEYWORD3>
<KEYWORD3>SystemError</KEYWORD3>
<KEYWORD3>SystemExit</KEYWORD3>
<KEYWORD3>TabError</KEYWORD3>
<KEYWORD3>TypeError</KEYWORD3>
<KEYWORD3>UnboundLocalError</KEYWORD3>
<KEYWORD3>UnicodeError</KEYWORD3>
<KEYWORD3>UserWarning</KEYWORD3>
<KEYWORD3>ValueError</KEYWORD3>
<KEYWORD3>Warning</KEYWORD3>
<KEYWORD3>WindowsError</KEYWORD3>
<KEYWORD3>ZeroDivisionError</KEYWORD3>
#@+node:ekr.20090615053403.4924: *7* << types >>
<!-- types (from types module) -->
<KEYWORD3>BufferType</KEYWORD3>
<KEYWORD3>BuiltinFunctionType</KEYWORD3>
<KEYWORD3>BuiltinMethodType</KEYWORD3>
<KEYWORD3>ClassType</KEYWORD3>
<KEYWORD3>CodeType</KEYWORD3>
<KEYWORD3>ComplexType</KEYWORD3>
<KEYWORD3>DictProxyType</KEYWORD3>
<KEYWORD3>DictType</KEYWORD3>
<KEYWORD3>DictionaryType</KEYWORD3>
<KEYWORD3>EllipsisType</KEYWORD3>
<KEYWORD3>FileType</KEYWORD3>
<KEYWORD3>FloatType</KEYWORD3>
<KEYWORD3>FrameType</KEYWORD3>
<KEYWORD3>FunctionType</KEYWORD3>
<KEYWORD3>GeneratorType</KEYWORD3>
<KEYWORD3>InstanceType</KEYWORD3>
<KEYWORD3>IntType</KEYWORD3>
<KEYWORD3>LambdaType</KEYWORD3>
<KEYWORD3>ListType</KEYWORD3>
<KEYWORD3>LongType</KEYWORD3>
<KEYWORD3>MethodType</KEYWORD3>
<KEYWORD3>ModuleType</KEYWORD3>
<KEYWORD3>NoneType</KEYWORD3>
<KEYWORD3>ObjectType</KEYWORD3>
<KEYWORD3>SliceType</KEYWORD3>
<KEYWORD3>StringType</KEYWORD3>
<KEYWORD3>StringTypes</KEYWORD3>
<KEYWORD3>TracebackType</KEYWORD3>
<KEYWORD3>TupleType</KEYWORD3>
<KEYWORD3>TypeType</KEYWORD3>
<KEYWORD3>UnboundMethodType</KEYWORD3>
<KEYWORD3>UnicodeType</KEYWORD3>
<KEYWORD3>XRangeType</KEYWORD3>

<KEYWORD3>False</KEYWORD3>
<KEYWORD3>None</KEYWORD3>
<KEYWORD3>True</KEYWORD3>

<KEYWORD3>__abs__</KEYWORD3>
<KEYWORD3>__add__</KEYWORD3>
<KEYWORD3>__all__</KEYWORD3>
<KEYWORD3>__author__</KEYWORD3>
<KEYWORD3>__bases__</KEYWORD3>
<KEYWORD3>__builtins__</KEYWORD3>
<KEYWORD3>__call__</KEYWORD3>
<KEYWORD3>__class__</KEYWORD3>
<KEYWORD3>__cmp__</KEYWORD3>
<KEYWORD3>__coerce__</KEYWORD3>
<KEYWORD3>__contains__</KEYWORD3>
<KEYWORD3>__debug__</KEYWORD3>
<KEYWORD3>__del__</KEYWORD3>
<KEYWORD3>__delattr__</KEYWORD3>
<KEYWORD3>__delitem__</KEYWORD3>
<KEYWORD3>__delslice__</KEYWORD3>
<KEYWORD3>__dict__</KEYWORD3>
<KEYWORD3>__div__</KEYWORD3>
<KEYWORD3>__divmod__</KEYWORD3>
<KEYWORD3>__doc__</KEYWORD3>
<KEYWORD3>__eq__</KEYWORD3>
<KEYWORD3>__file__</KEYWORD3>
<KEYWORD3>__float__</KEYWORD3>
<KEYWORD3>__floordiv__</KEYWORD3>
<KEYWORD3>__future__</KEYWORD3>
<KEYWORD3>__ge__</KEYWORD3>
<KEYWORD3>__getattr__</KEYWORD3>
<KEYWORD3>__getattribute__</KEYWORD3>
<KEYWORD3>__getitem__</KEYWORD3>
<KEYWORD3>__getslice__</KEYWORD3>
<KEYWORD3>__gt__</KEYWORD3>
<KEYWORD3>__hash__</KEYWORD3>
<KEYWORD3>__hex__</KEYWORD3>
<KEYWORD3>__iadd__</KEYWORD3>
<KEYWORD3>__import__</KEYWORD3>
<KEYWORD3>__imul__</KEYWORD3>
<KEYWORD3>__init__</KEYWORD3>
<KEYWORD3>__int__</KEYWORD3>
<KEYWORD3>__invert__</KEYWORD3>
<KEYWORD3>__iter__</KEYWORD3>
<KEYWORD3>__le__</KEYWORD3>
<KEYWORD3>__len__</KEYWORD3>
<KEYWORD3>__long__</KEYWORD3>
<KEYWORD3>__lshift__</KEYWORD3>
<KEYWORD3>__lt__</KEYWORD3>
<KEYWORD3>__members__</KEYWORD3>
<KEYWORD3>__metaclass__</KEYWORD3>
<KEYWORD3>__mod__</KEYWORD3>
<KEYWORD3>__mro__</KEYWORD3>
<KEYWORD3>__mul__</KEYWORD3>
<KEYWORD3>__name__</KEYWORD3>
<KEYWORD3>__ne__</KEYWORD3>
<KEYWORD3>__neg__</KEYWORD3>
<KEYWORD3>__new__</KEYWORD3>
<KEYWORD3>__nonzero__</KEYWORD3>
<KEYWORD3>__oct__</KEYWORD3>
<KEYWORD3>__or__</KEYWORD3>
<KEYWORD3>__path__</KEYWORD3>
<KEYWORD3>__pos__</KEYWORD3>
<KEYWORD3>__pow__</KEYWORD3>
<KEYWORD3>__radd__</KEYWORD3>
<KEYWORD3>__rdiv__</KEYWORD3>
<KEYWORD3>__rdivmod__</KEYWORD3>
<KEYWORD3>__reduce__</KEYWORD3>
<KEYWORD3>__repr__</KEYWORD3>
<KEYWORD3>__rfloordiv__</KEYWORD3>
<KEYWORD3>__rlshift__</KEYWORD3>
<KEYWORD3>__rmod__</KEYWORD3>
<KEYWORD3>__rmul__</KEYWORD3>
<KEYWORD3>__ror__</KEYWORD3>
<KEYWORD3>__rpow__</KEYWORD3>
<KEYWORD3>__rrshift__</KEYWORD3>
<KEYWORD3>__rsub__</KEYWORD3>
<KEYWORD3>__rtruediv__</KEYWORD3>
<KEYWORD3>__rxor__</KEYWORD3>
<KEYWORD3>__setattr__</KEYWORD3>
<KEYWORD3>__setitem__</KEYWORD3>
<KEYWORD3>__setslice__</KEYWORD3>
<KEYWORD3>__self__</KEYWORD3>
<KEYWORD3>__slots__</KEYWORD3>
<KEYWORD3>__str__</KEYWORD3>
<KEYWORD3>__sub__</KEYWORD3>
<KEYWORD3>__truediv__</KEYWORD3>
<KEYWORD3>__version__</KEYWORD3>
<KEYWORD3>__xor__</KEYWORD3>
#@+node:ekr.20090615053403.4925: *4* @test colorizer Python1
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4926: *5* python
@language python

int
float
dict
#@+node:ekr.20090615053403.4927: *4* @test colorizer Python2
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4928: *5* python
"""This creates a free-floating copy of v's tree for undo.
The copied trees must use different tnodes than the original."""

def copyTree(self,root):

    c = self
    # Create the root vnode.
    result = v = leoNodes.vnode(c)
    # Copy the headline and icon values v.copyNode(root,v)
    # Copy the rest of tree.
    v.copyTree(root,v)
    # Replace all tnodes in v by copies.
    assert(v.nodeAfterTree() == None)
    while v:
        v = leoNodes.vnode(c)
        v = v.threadNext()
    return result
#@+node:ekr.20090615053403.4929: *4* @test colorizer r
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4930: *5* r
@language r

x <- rnorm(10) 

vv <- function(z) return(z) 

def python_funct(uu): 
return uu
#@+node:ekr.20090615053403.4931: *4* @test colorizer rapidq
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4932: *5* rapidq
' New in 4.2.
@language rapidq
' a comment.

$APPTYPE,$DEFINE,$ELSE,$ENDIF,$ESCAPECHARS,$IFDEF,$IFNDEF,
$INCLUDE,$MACRO,$OPTIMIZE,$OPTION,$RESOURCE,$TYPECHECK,$UNDEF,
ABS,ACOS,ALIAS,AND,AS,ASC,ASIN,ATAN,ATN,BIN$,BIND,BYTE,
CALL,CALLBACK,CALLFUNC,CASE,CEIL,CHDIR,CHDRIVE,CHR$,CINT,
CLNG,CLS,CODEPTR,COMMAND$,COMMANDCOUNT,CONSOLE,CONST,CONSTRUCTOR,
CONVBASE$,COS,CREATE,CSRLIN,CURDIR$,DATA,DATE$,DEC,DECLARE,
DEFBYTE,DEFDBL,DEFDWORD,DEFINT,DEFLNG,DEFSHORT,DEFSNG,DEFSTR,
DEFWORD,DELETE$,DIM,DIR$,DIREXISTS,DO,DOEVENTS,DOUBLE,DWORD,
ELSE,ELSEIF,END,ENVIRON,ENVIRON$,EVENT,EXIT,EXP,EXTENDS,
EXTRACTRESOURCE,FIELD$,FILEEXISTS,FIX,FLOOR,FOR,FORMAT$,FRAC,
FUNCTION,FUNCTIONI,GET$,GOSUB,GOTO,HEX$,IF,INC,INITARRAY,
INKEY$,INP,INPUT,INPUT$,INPUTHANDLE,INSERT$,INSTR,INT,INTEGER,
INV,IS,ISCONSOLE,KILL,KILLMESSAGE,LBOUND,LCASE$,LEFT$,LEN,
LFLUSH,LIB,LIBRARYINST,LOCATE,LOG,LONG,LOOP,LPRINT,LTRIM$,
MEMCMP,MESSAGEBOX,MESSAGEDLG,MID$,MKDIR,MOD,MOUSEX,MOUSEY,
NEXT,NOT,OFF,ON,OR,OUT,OUTPUTHANDLE,PARAMSTR$,PARAMSTRCOUNT,
PARAMVAL,PARAMVALCOUNT,PCOPY,PEEK,PLAYWAV,POKE,POS,POSTMESSAGE,
PRINT,PROPERTY,QUICKSORT,RANDOMIZE,REDIM,RENAME,REPLACE$,
REPLACESUBSTR$,RESOURCE,RESOURCECOUNT,RESTORE,RESULT,RETURN,
REVERSE$,RGB,RIGHT$,RINSTR,RMDIR,RND,ROUND,RTRIM$,RUN,
SCREEN,SELECT,SENDER,SENDMESSAGE,SETCONSOLETITLE,SGN,SHELL,
SHL,SHORT,SHOWMESSAGE,SHR,SIN,SINGLE,SIZEOF,SLEEP,SOUND,
SPACE$,SQR,STACK,STATIC,STEP,STR$,STRF$,STRING,STRING$,
SUB,SUBI,SWAP,TALLY,TAN,THEN,TIME$,TIMER,TO,TYPE,UBOUND,
UCASE$,UNLOADLIBRARY,UNTIL,VAL,VARIANT,VARPTR,VARPTR$,VARTYPE,
WEND,WHILE,WITH,WORD,XOR
#@+node:ekr.20090615053403.4933: *4* @test colorizer Rebol
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4934: *5* Rebol
@language rebol

; a comment
about abs absolute add alert alias all alter and and~ any append arccosine arcsine arctangent array ask at  
back bind boot-prefs break browse build-port build-tag  
call caret-to-offset catch center-face change change-dir charset checksum choose clean-path clear clear-fields close comment complement compose compress confirm continue-post context copy cosine create-request crypt cvs-date cvs-version  
debase decode-cgi decode-url decompress deflag-face dehex delete demo desktop detab dh-compute-key dh-generate-key dh-make-key difference dirize disarm dispatch divide do do-boot do-events do-face do-face-alt does dsa-generate-key dsa-make-key dsa-make-signature dsa-verify-signature  
echo editor either else emailer enbase entab exclude exit exp extract 
fifth find find-key-face find-window flag-face first flash focus for forall foreach forever form forskip fourth free func function  
get get-modes get-net-info get-style  
halt has head help hide hide-popup  
if import-email in inform input insert insert-event-func intersect 
join 
last launch launch-thru layout license list-dir load load-image load-prefs load-thru log-10 log-2 log-e loop lowercase  
make make-dir make-face max maximum maximum-of min minimum minimum-of mold multiply  
negate net-error next not now  
offset-to-caret open open-events or or~ 
parse parse-email-addrs parse-header parse-header-date parse-xml path-thru pick poke power prin print probe protect protect-system  
q query quit  
random read read-io read-net read-thru reboot recycle reduce reform rejoin remainder remold remove remove-event-func rename repeat repend replace request request-color request-date request-download request-file request-list request-pass request-text resend return reverse rsa-encrypt rsa-generate-key rsa-make-key 
save save-prefs save-user scroll-para second secure select send send-and-check set set-modes set-font set-net set-para set-style set-user set-user-name show show-popup sine size-text skip sort source split-path square-root stylize subtract switch  
tail tangent textinfo third throw throw-on-error to to-binary to-bitset to-block to-char to-date to-decimal to-email to-event to-file to-get-word to-hash to-hex to-idate to-image to-integer to-issue to-list to-lit-path to-lit-word to-local-file to-logic to-money to-none to-pair to-paren to-path to-rebol-file to-refinement to-set-path to-set-word to-string to-tag to-time to-tuple to-url to-word trace trim try  
unfocus union unique uninstall unprotect unset until unview update upgrade uppercase usage use  
vbug view view-install view-prefs  
wait what what-dir while write write-io  
xor xor~  
action! any-block! any-function! any-string! any-type! any-word!  
binary! bitset! block!  
char!  
datatype! date! decimal! 
email! error! event!  
file! function!  
get-word!  
hash!  
image! integer! issue!  
library! list! lit-path! lit-word! logic!  
money!  
native! none! number!  
object! op!  
pair! paren! path! port!  
refinement! routine!  
series! set-path! set-word! string! struct! symbol!  
tag! time! tuple!  
unset! url!  
word!  
any-block? any-function? any-string? any-type? any-word?  
binary? bitset? block?  
char? connected? crypt-strength? 
datatype? date? decimal? dir?  
email? empty? equal? error? even? event? exists? exists-key?
file? flag-face? found? function?  
get-word? greater-or-equal? greater?  
hash? head?  
image? in-window? index? info? input? inside? integer? issue?  
length? lesser-or-equal? lesser? library? link-app? link? list? lit-path? lit-word? logic?  
modified? money?  
native? negative? none? not-equal? number?  
object? odd? offset? op? outside?  
pair? paren? path? port? positive?  
refinement? routine?  
same? screen-offset? script? series? set-path? set-word? size? span? strict-equal? strict-not-equal? string? struct?  
tag? tail? time? tuple? type?  
unset? url?  
value? view? 
within? word?  
zero?
#@+node:ekr.20090615053403.4935: *4* @test colorizer rest
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4936: *5* rest
@language rest

@ @rst-options
code_mode=False
generate_rst=True
http_server_support = False
show_organizer_nodes=True
show_headlines=True
show_leo_directives=True
stylesheet_path=..\doc
write_intermediate_file = False
verbose=True
@c

. Links used in this document...

.. _`Pmw`:                  http://pmw.sourceforge.net/
.. _run:                    `Running Leo`_

.. WARNING: image targets may not have upper case letters!

.. |back| image:: arrow_lt.gif
    :target: FAQ.html

.. |leo| image:: leo.gif
    :target: front.html

.. |next| image:: arrow_rt.gif
    :target: intro.html

|back| |leo| |next|

###########################
Chapter 1: Installing Leo
###########################

This chapter tells how to install and run Leo.

**Important**:

If you have *any* problems installing Leo,
please ask for help on Leo's help forum:

.. contents::

**Windows**
    If you have `associated .leo files with Leo`_ you may run Leo by double-clicking any .leo file.
    You can also use a batch file.
    Put the following .bat file in c:\\Windows::

        cd c:\prog\LeoCVS\leo
        c:\python22\python c:\prog\LeoCVS\leo\leo.py %1

-   Download the latest version of Leo from `Leo's download page`_.

-   In Windows 2K or XP, go to ``Start->Settings->Control panel``, open the ``Folder Options`` tab.

    **Warning**: When building Tcl on Linux, do **not** specify
    "--enable-threads".
    Only use Tcl with the default "threads not enabled" case.

-------------

|back| |leo| |next|
#@+node:ekr.20110529215703.3494: *4* @test colorizer scala
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20110529215703.3495: *5* scala
@language scala

/* A comment */

object HelloWorld {
    def main(args: Array[String]) {
      println("Hello, world!")
    }
  }
#@+node:ekr.20090615053403.4937: *4* @test colorizer shell
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4938: *5* shell
# New in 4.2.

@language shell

# comment
$# not a comment
break
case,continue,
do,done
elif,else,esac
fi,for
if,in
return,
then
until
while,

cd,chdir,eval,exec,
exit,kill,newgrp,pwd,read,readonly,
shift,test,trap,ulimit,
umask,wait
#@+node:ekr.20090615053403.4939: *4* @test colorizer shellscript
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4940: *5* shellscript
@language shellscript

# comment
$# not a comment
break
case,continue,
do,done
elif,else,esac
fi,for
if,in
return,
then
until
while,

cd,chdir,eval,exec,
exit,kill,newgrp,pwd,read,readonly,
shift,test,trap,ulimit,
umask,wait
#@+node:ekr.20090615053403.4941: *4* @test colorizer tex.xml (jEdit)
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4942: *5* tex.xml
@language html

<!-- ekr uses the MARK_FOLLOWING to mark _anything_ after \ -->

<?xml version="1.0"?>

<!DOCTYPE MODE SYSTEM "xmode.dtd">

<MODE>
    <PROPS>
        <PROPERTY NAME="lineComment" VALUE="%" />
    </PROPS>

    <RULES>
        << general rules >>
    </RULES>

    <RULES SET="MATH" DEFAULT="MARKUP">
        << math rules >>
    </RULES>
</MODE>
#@+node:ekr.20090615053403.4943: *6* << general rules >>
<!-- $$...$$ -->
<SPAN TYPE="MARKUP" DELEGATE="MATH">
    <BEGIN>$$</BEGIN>
    <END>$$</END>
</SPAN>

<!-- $...$ -->
<SPAN TYPE="MARKUP" DELEGATE="MATH">
    <BEGIN>$</BEGIN>
    <END>$</END>
</SPAN>

<!-- \[...\] (LaTeX math mode) -->
<SPAN TYPE="MARKUP" DELEGATE="MATH">
    <BEGIN>\[</BEGIN>
    <END>\]</END>
</SPAN>

<!-- some commands must be handled specially -->
<SEQ TYPE="KEYWORD1">\$</SEQ>
<SEQ TYPE="KEYWORD1">\\</SEQ>
<SEQ TYPE="KEYWORD1">\%</SEQ>

<!-- \... commands -->
<MARK_FOLLOWING TYPE="KEYWORD1">\</MARK_FOLLOWING>

<!-- comments -->
<EOL_SPAN TYPE="COMMENT1">%</EOL_SPAN>

<!-- word separators -->
<SEQ TYPE="OPERATOR">{</SEQ>
<SEQ TYPE="OPERATOR">}</SEQ>
<SEQ TYPE="OPERATOR">[</SEQ>
<SEQ TYPE="OPERATOR">]</SEQ>
#@+node:ekr.20090615053403.4944: *6* << math rules >>
<!-- some commands must be handled specially -->
<SEQ TYPE="KEYWORD3">\$</SEQ>
<SEQ TYPE="KEYWORD3">\\</SEQ>
<SEQ TYPE="KEYWORD3">\%</SEQ>

<!-- \... commands -->
<MARK_FOLLOWING TYPE="KEYWORD3">\</MARK_FOLLOWING>

<!-- word separators -->
<SEQ TYPE="KEYWORD2">)</SEQ>
<SEQ TYPE="KEYWORD2">(</SEQ>
<SEQ TYPE="KEYWORD2">{</SEQ>
<SEQ TYPE="KEYWORD2">}</SEQ>
<SEQ TYPE="KEYWORD2">[</SEQ>
<SEQ TYPE="KEYWORD2">]</SEQ>
<SEQ TYPE="KEYWORD2">=</SEQ>
<SEQ TYPE="KEYWORD2">!</SEQ>
<SEQ TYPE="KEYWORD2">+</SEQ>
<SEQ TYPE="KEYWORD2">-</SEQ>
<SEQ TYPE="KEYWORD2">/</SEQ>
<SEQ TYPE="KEYWORD2">*</SEQ>
<SEQ TYPE="KEYWORD2">&gt;</SEQ>
<SEQ TYPE="KEYWORD2">&lt;</SEQ>
<SEQ TYPE="KEYWORD2">&amp;</SEQ>
<SEQ TYPE="KEYWORD2">|</SEQ>
<SEQ TYPE="KEYWORD2">^</SEQ>
<SEQ TYPE="KEYWORD2">~</SEQ>
<SEQ TYPE="KEYWORD2">.</SEQ>
<SEQ TYPE="KEYWORD2">,</SEQ>
<SEQ TYPE="KEYWORD2">;</SEQ>
<SEQ TYPE="KEYWORD2">?</SEQ>
<SEQ TYPE="KEYWORD2">:</SEQ>
<SEQ TYPE="KEYWORD2">'</SEQ>
<SEQ TYPE="KEYWORD2">"</SEQ>
<SEQ TYPE="KEYWORD2">`</SEQ>

<!-- comments -->
<EOL_SPAN TYPE="COMMENT1">%</EOL_SPAN>
#@+node:ekr.20090615053403.4945: *4* @test colorizer wikiTest1
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4946: *5* wiki
# both color_markup & add_directives plugins must be enabled.

@markup wiki
@language python

""" {picture file=../Icons/Leoapp.GIF}this """ # Problems with correct indexing following a graphic.

""" {picture file=../Icons/Leoapp.GIF}this """ # two copies work.

abc

""" {picture file=../Icons/Leodoc.GIF} """ # xyz

""" continued
string"""

@ ''ab'' __xxx__ ''wx'' __xyz__
@c

# /* ''ab'' __xxx__ ''wx'' __xyz__ */

# Test

""" ''' """ ''' """'''  # Leo handles the common cases correctly.

''' ''ab'' __xxx__ ''wx'' __xyz__ ''' # No wiki markup in ''' strings.

""" ''ab'' __xxx__ ''wx'' __xyz__ """

# ''ab'' __xxx__ ''wx'' __xyz__

""" ''y'' """

""" text~~#ff00ff:some text~~more text"""

if 1 and 2:
    pass

print(g.app().loadDir)
#@+node:ekr.20090615053403.4947: *4* @test colorizer wikiTest2
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4948: *5* wiki
# both color_markup & add_directives plugins must be enabled.
@markup wiki

""" continued
string"""

@ ''ab'' __xxx__ ''wx'' __xyz__  __''bolditalic''__ and ''__italicbold__''
@c

# /* ''ab'' __xxx__ ''wx'' __xyz__ */

__abc__ 

# Test

""" ''' """ ''' """'''  # Leo handles the __b__ common cases correctly.

''' ''ab'' __xxx__ ''wx'' __xyz__ ''' # No wiki markup in ''' strings.

""" ''ab'' __xxx__ ''wx'' __xyz__ """

# ''ab'' __xxx__ ''wx'' __xyz__

""" ''y'' """

""" text~~#ee00ff:some text~~more text"""


if 1 and 2:
    pass

print(g.app().loadDir)
#@+node:ekr.20090615053403.4949: *4* @test colorizer wikiTest3
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4950: *5* wiki
# both color_markup & add_directives plugins must be enabled.

@markup wiki

""" text~~red:some text~~more text"""

""" text~~#ee0ff:some text~~more text"""

if 1 and 2:
    pass
#@+node:ekr.20090615053403.4951: *4* @test leoColor.doNowebSecRef
<< test defined >>
#@+node:ekr.20090615053403.4952: *5* << test defined >>
pass
#@+node:ekr.20090615053403.4953: *4* @test python keywords (new colorizer)
try:
    mode = c.frame.body.colorizer.modes.get('python')
    mode.keywords['as'] = 1 # append the keyword, colorize with 'keyword1' tag.
except AttributeError:
    pass # modes only exists for new colorizer.
#@+node:ekr.20090615053403.4954: *4* @test scanColorDirectives
# This will work regardless of where this method is.
@language python

language = g.findLanguageDirectives(c,p)
assert language == 'python','got:%s' % language
#@+node:ekr.20090615053403.4955: *4* @test vbscript
p = c.p.firstChild()

c.selectPosition(p) # Sets body text.
val = c.frame.body.colorizer.colorize(p,incremental=False)
assert val=="ok", "colorizer test failed: %s" % p.h
#@+node:ekr.20090615053403.4956: *5* vbscript
@language vbscript

if
IF
#@+node:ekr.20090615053403.4957: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

print('\nEnd of leoColor tests')
#@+node:ekr.20110608135658.3377: *3* leoChapters
#@+node:ekr.20110608162543.3363: *4* @test chapter-create/remove & undo
cc = c.chapterController
chaptersNode = cc.findChaptersNode()
assert chaptersNode

chapterNode = (
    cc.findChapterNode('aaa') or
    cc.createChapterByName('aaa',p=None))

cc.selectChapterByName('aaa',chaptersNode)
cc.removeChapterByName('aaa')
c.undoer.undo()
assert cc.findChapterNode('aaa')
cc.selectChapterByName('main',collapse=True)
#@+node:ekr.20110608162543.3365: *4* @test chapter-rename & undo
cc = c.chapterController
chaptersNode = cc.findChaptersNode()
assert chaptersNode

chapterNode = (
    cc.findChapterNode('aaa') or
    cc.createChapterByName('aaa',p=None))
    
try:
    cc.selectChapterByName('aaa',chaptersNode)
    cc.renameChapterByName('bbb')
    cc.selectChapterByName('bbb',chaptersNode)
    cc.renameChapterByName('aaa')
    assert cc.findChapterNode('aaa'),'after undo'
finally:
    cc.selectChapterByName('main',collapse=True)
#@+node:ekr.20110608181936.3368: *4* @test chapter-move/clone/copy-node-to
cc = c.chapterController
chaptersNode = cc.findChaptersNode()
assert chaptersNode,'fail 0'

chapterNode = (
    cc.findChapterNode('aaa') or
    cc.createChapterByName('aaa',p=None))
    
table = (
    ('node a',cc.moveNodeToChapterHelper),
    ('node b',cc.copyNodeToChapterHelper),
    ('node c',cc.cloneNodeToChapterHelper),
)
    
# Initialze 
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

for h,unused_f in table:
    p2 = p.insertAsLastChild()
    p2.h = h
    p2.b = '# %s' % h

try:
    cc.selectChapterByName('aaa',chaptersNode)
    for h,f in table:
        p2 = g.findNodeInTree(c,p,h)
        assert p2,'fail 1'
        c.selectPosition(p2) # All helpers work on c.p.
        f('aaa')
        assert g.findNodeInTree(c,chapterNode,h),'fail 2'
    assert not g.findNodeInTree(c,p,'node a')
    assert g.findNodeInTree(c,p,'node b')
    assert g.findNodeInTree(c,p,'node c')
finally:
    if 1: # Restore the tree so activeUnitTests.txt does not change.
        while p.hasChildren():
            p.firstChild().doDelete(newNode=None)
        for h,f in table:
            # if not g.findNodeInTree(c,p,h):
                # p2 = p.insertAsLastChild()
                # p2.h = h
                # p2.b = '# %s' % h
            p3 = g.findNodeInTree(c,chapterNode,h)
            if p3: p3.doDelete()
    cc.selectChapterByName('main',collapse=True)
    c.redraw()
#@+node:ekr.20080503132221.1: *4* @test chapter-create-from-node
cc = c.chapterController
root = p.copy()

# Init the children
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

child = p.insertAsNthChild(0)
# c.setHeadString(child,'child') # Force the headline to update.
child.h = 'child'
child.b = '# child'

# Kill the chapter so the test will not fail if run twice.
chapter = cc.chaptersDict.get('new-chapter')
if chapter:
    cc.removeChapterByName('new-chapter')

try:
    c.selectPosition(child)
    c.chapterController.createChapterByName(
        'new-chapter',child,'Create Chapter From Node')
    if 0:
        c.undoer.undo()
        c.undoer.redo()
        c.undoer.undo()
        c.undoer.redo()
        c.undoer.undo() # Don't pollute future unit tests.
    else:
        c.redraw_now() # Required.
        chapterNode = cc.findChapterNode('new-chapter')
        assert chapterNode,'fail 1: %s' % (undoType)
        chapterNode.doDelete()
        c.redraw_now()
finally:
    cc.selectChapterByName('main',collapse=True)
    if 1: # Do this so the activeUnitTests.txt does not change.
        while root.hasChildren():
            root.firstChild().doDelete(newNode=None)
    c.redraw_now()
#@+node:ekr.20071113193624: *3* leoCommands
# 7 failures with Alt-5
#@+node:ekr.20090104053806.1: *4* @@test c.checkFileTimeStamp & c.setFileTimeStamp
# Disabled because modifying errorTest.py creates annoying bzr conflicts.

import os

path = g.os_path_finalize_join(g.app.testDir,'unittest','errorTest.py')
assert g.os_path_exists(path),path
timeStamp = c.timeStampDict.get(path)
val = c.checkFileTimeStamp(path)
assert val == True

f = open(path)
s = f.read()
lines = g.splitLines(s)
result = [] ; found = False
tag = '# timestamp:'
for line in lines:
    if line.startswith(tag):
        timeStamp = os.path.getmtime(path)
        result.append('%s %s\n' % (tag,timeStamp))
        found = True
    else:
        result.append(line)
f.close()

assert found,' no line starts with "%s"' % tag

f = open(path,'w')
f.write(''.join(result))
f.close()

timeStamp2 = os.path.getmtime(path)
assert timeStamp != timeStamp2
val = c.checkFileTimeStamp(path)
assert not val,repr(val)
c.setFileTimeStamp(path)
val = c.checkFileTimeStamp(path)
assert val,repr(val)
#@+node:ekr.20110510054817.3475: *4* @test c.alert
c.alert('test of c.alert')
#@+node:ekr.20071113145804.10: *4* @test c.contractAllHeadlines
c.contractAllHeadlines()
p = c.rootPosition()
while p.hasNext():
    p.moveToNext()
c.selectPosition(p)
#@+node:ekr.20100209155559.5386: *4* @test c.createOpenWithTempFile
c.createOpenWithTempFile(p,'.py')
#@+node:ekr.20100203103015.5355: *4* @test c.getOpenWithExt
@language python

table = (
    # (None,'.py'),
    # ('','.py'),
    ('txt','.txt'),
    ('.txt','.txt'),
)

for ext,result in table:
    result2 = c.getOpenWithExt(p,ext)
    assert result==result2,'ext: %s, expected %s, got %s' % (
        repr(ext),repr(result),repr(result2))
#@+node:ekr.20100212072149.5341: *4* @test c.goToScriptLineNumber
child = g.findNodeInChildren(c,p,'syntax-error')
assert child,'no child'
script = child.b
try:
    c.goToScriptLineNumber(child,script,1)
finally:
    p.contract()
    c.selectPosition(p)
    c.redraw()
#@+node:ekr.20100212072149.5342: *5* syntax-error
@language python
def spam:
    pass
#@+node:ekr.20061106112522: *4* @test c.insertBodyTime
w = c.frame.body.bodyCtrl
s = w.getAllText()

try:
    w.setInsertPoint(len(s))
    c.insertBodyTime()
finally:
    w.setAllText(s)
    p.setBodyString(s)
    # c.recolor()

# end:
#@+node:ekr.20050512083807.1: *4* @test c.markAllAtFileNodesDirty
marks = [p.v for p in c.all_positions() if p.isMarked()]
try:
    ok = True
    try:
        c.markAllAtFileNodesDirty()
    except Exception:
        ok = False
finally:
    for p in c.all_positions():
        if p.v in marks:
            if not p.isMarked():
                c.setMarked(p)
        else:
            if p.isMarked():
                c.clearMarked(p)

if not ok: raise
#@+node:ekr.20100203103015.5356: *4* @test c.openTempFileInExternalEditor
arg = ''
arg0 = 'one'
fn = '<fn>'
filename = '' # g.os.path.basename(arg)
vtuple = [arg0,fn]

table = (
    ('os.system',       'os.system(%s)' % (arg+fn)),
    ('os.startfile',    'os.startfile(%s)' % (arg+fn)),
    ('exec',            'exec(%s)' % (arg+fn)),
    ('os.spawnl',       'os.spawnl(%s,%s,%s)' % (arg,filename,fn)),
    ('os.spawnv',       'os.spawnv(%s,%s)' % (arg0,vtuple)),
    ('subprocess.Popen','subprocess.Popen(%s)' % vtuple),
    ('huh?',            'bad command:'+'huh?'),
)

for openType,result in table:
    if openType in ('os.spawnv','subprocess.Popen'):
        arg2 = ['one']
    else:
        arg2 = None
    result2 = c.openTempFileInExternalEditor(
        arg2,fn,openType,testing=True)
    assert result==result2,'expected %s, got %s' % (
        repr(result),repr(result2))
#@+node:ekr.20100203103015.5354: *4* @test c.openWithTempFilePath
s = c.openWithTempFilePath(p,'.py')
assert s.find('LeoTemp') > -1
assert s.endswith('.py')
#@+node:ekr.20040802065214: *4* @test changing headline marks descendent @thin nodes dirty
# Make sure that changing this headline marks descendant @thin nodes dirty.
h = p.h

try:
    child = p.firstChild()
    child.initHeadString("@thin bogus")
    assert child.h == "@thin bogus", "setting headline failed"
    child.clearDirty()
    assert not child.isDirty(), "clearing dirty failed"
    c.setHeadString(p,"changed")
    assert child.isDirty(), "setting descendant @thin nodes dirty failed."
finally:
    try:
        c.setHeadString(p,h)
        c.setHeadString(child,"bogus")
        p.clearDirty()
        child.clearDirty()
    finally: pass

#### c.redraw()
#@+node:ekr.20040802065214.1: *5* bogus
test
#@+node:ekr.20050512084850: *4* @test check outline
errors = c.checkOutline(verbose=False,unittest=True,full=True) # Run full check.

assert errors == 0, "Check Outline reported %d errors" % errors
#@+node:ekr.20040713070526: *5* Scripts
@language python 

import leo.core.leoTest as leoTest

u = leoTest.testUtils(c)
dump = False 
all = False 

if all:
    c.prettyPrintAllPythonCode(dump=dump)
else:
    # Warning: at present the before and after text is unprotected:
    # Running Pretty Print on these nodes will negate the value of the test.
    temp = u.findNodeInTree(p,"tempNode")
    c.setBodyString(temp,"")
    before = u.findNodeInTree(p,"before")
    after = u.findNodeInTree(p,"after")
    temp.scriptSetBodyString(before.b)
    c.prettyPrintPythonCode(p=temp,dump=dump)
    assert temp.b == after.b,"Pretty Print Test failed"
#@+node:ekr.20040713123617: *6* tempNode
@ This is a test of stuff.in doc parts.

         I wonder what will happen.
@c

def spam (self):

    """ This is a ' triple'   quoted string:
        It should remain untouched."""

    if a == 3:
        g.pr("Ä á Û")

    ''' Another ' triple'   quoted string:
        It should remain untouched.'''

    "yet another\
    multi-line string"

class eggs:

    """ A typical doc string """

    @others
#@+node:ekr.20050726141158: *6* before
@ This is    a test of stuff.in doc parts.

         I wonder           what will happen.
@c

def        spam (self         )  :   

    """ This is a ' triple'   quoted string:
        It should remain untouched."""

    if a==3:
        g.pr("Ä á Û")

    ''' Another ' triple'   quoted string:
        It should remain untouched.'''

    "yet another\
    multi-line string"

class eggs:

    """ A typical doc string """

    @others
#@+node:ekr.20040713123828.1: *6* after
@ This is a test of stuff.in doc parts.

         I wonder what will happen.
@c

def spam (self):

    """ This is a ' triple'   quoted string:
        It should remain untouched."""

    if a == 3:
        g.pr("Ä á Û")

    ''' Another ' triple'   quoted string:
        It should remain untouched.'''

    "yet another\
    multi-line string"

class eggs:

    """ A typical doc string """

    @others
#@+node:ekr.20100131180007.5465: *4* @test class StubConfig
class StubConfig(g.nullObject):
    pass

x = StubConfig()
assert not x.getBool(c,'mySetting')
assert not x.enabledPluginsFileName
#@+node:ekr.20070611105423.1: *4* @test contract all
c.contractAllHeadlines()
#@+node:ville.20090602190735.4770: *4* @test g.command decorator
_foo = 0

@g.command('my-test-command')
def mytestcommand(event):
    global _foo

    _foo = 1

c.k.simulateCommand('my-test-command')
assert _foo == 1

# bonus test: c.app.commanders()
assert c in g.app.commanders()



#@+node:ekr.20100203103015.5357: *4* @test g.isCallable
def spam(): pass
lam = lambda a: None
class aCallable:
    def __call__ (self):
        pass
c = aCallable()

table = (
    ('abc',False),
    (spam,True),
    (lam,True),
    (c,True)
)

for obj,val in table:
    val2 = g.isCallable(obj)
    assert val == val2,'%s, expected %s, got %s' % (
        repr(obj),val,val2)
#@+node:ekr.20071113105654.1: *4* @test hoist with no children
c.hoist()
c.dehoist()
#@+node:ekr.20070611105728: *4* @test illegal clone demote
# Remove any previous children.
while p.hasChildren():
    p.firstChild().doDelete()
# Create two cloned children.
c.selectPosition(p)
c.insertHeadline()
p2 = c.p
p2.moveToFirstChildOf(p)
p2.setHeadString('aClone')
c.selectPosition(p2)
c.clone()
assert 2 == p.numberOfChildren()

# Select the first clone and demote (it should be illegal)
c.selectPosition(p2)
c.demote() # This should do nothing.
assert g.app.unitTestDict.get('checkMoveWithParentWithWarning'),'fail 1'
assert 0 == c.checkOutline(event=None,verbose=False,unittest=True,full=True), 'fail 2'
assert 2 == p.numberOfChildren(), 'fail 3'
# Delete the children, but only if there are no errors.
while p.hasChildren():
    p.firstChild().doDelete()
#@+node:ekr.20050512083822.1: *4* @test markSubheads
marks = [p.v for p in c.all_positions() if p.isMarked()]
try:
    ok = True
    try:
        c.markSubheads()
    except Exception:
        ok = False
finally:
    for p in c.all_positions():
        if p.v in marks:
            if not p.isMarked():
                c.setMarked(p)
        else:
            if p.isMarked():
                c.clearMarked(p)

if not ok: raise
#@+node:ekr.20050512084850.1: *5* child 1
pass
#@+node:ekr.20050512084850.2: *5* child 2
pass
#@+node:ekr.20100203103015.5353: *4* @test open-with conflict dialog
# A copy of the code from c.createOrRecreateTempFileAsNeeded.
# Not a perfect test, but stil significant.

assert c.conflict_message,'fail 1'

result = g.app.gui.runAskYesNoCancelDialog(c,
    "Conflict!", c.conflict_message,
    yesMessage = "Outline",
    noMessage = "File",
    defaultButton = "Cancel")

assert result in (None,'cancel'),'fail 2: %s' % result
#@+node:ekr.20041019124050: *4* @test prettyPrintPythonCode
test1 = p.firstChild()
test2 = p.firstChild().next()

c.prettyPrintPythonCode(p=test2,dump=False)

assert(test2.b==test1.b)
#@+node:ekr.20041019124050.1: *5* Original
"""
line 1
line 2
line 3
"""
#@+node:ekr.20041019124050.2: *5* Test
"""
line 1
line 2
line 3
"""
#@+node:ekr.20050512083822.2: *4* @test unmarkAll
marks = [p.v for p in c.all_positions() if p.isMarked()]
try:
    ok = True
    try:
        c.unmarkAll()
    except Exception:
        ok = False
finally:
    for p in c.all_positions():
        if p.v in marks:
            if not p.isMarked():
                c.setMarked(p)
        else:
            if p.isMarked():
                c.clearMarked(p)

if not ok: raise
#@+node:ekr.20071113201833: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

print('\nEnd of leoCommands tests')
#@+node:ekr.20101021205258.6009: *4* c.Directives & directories
#@+node:ekr.20080917151620.9: *5* @test c.scanAllDirectives
@language python
@comment a b c
    # @comment must follow @language
@tabwidth -4
@pagewidth 72
@encoding utf-8
@lineending crlf

d = c.scanAllDirectives(p)
# print(g.dictToString(d))

table = (
    ('delims', ('a','b','c'),),
    ('encoding','utf-8'),
    ('language','python'),
    ('lineending','\r\n'),
    ('pagewidth',72),
    ('tabwidth',-4),
)

for kind,expected in table:
    got = d.get(kind)
    assert got == expected, 'kind: %s, expected %s, got %s' % (
        kind,repr(expected),repr(got))
#@+node:ekr.20100131180007.5466: *5* @test c.scanAtPathDirectives
p2 = p.firstChild().firstChild().firstChild()

aList = g.get_directives_dict_list(p2)
path = c.scanAtPathDirectives(aList)
# print (path,p2.h)
endpath = g.os_path_normpath('one/two')
assert path and path.endswith(endpath),'expected ending %s got %s' % (
    endpath,path)
#@+node:ekr.20100131180007.5467: *6* @path one
#@+node:ekr.20100131180007.5468: *7* @path two
#@+node:ekr.20100131180007.5469: *8* xyz
#@+node:sps.20100531034136.20110: *5* @test c.scanAtPathDirectives same name subdirs
p2 = p.firstChild().firstChild().firstChild()

aList = g.get_directives_dict_list(p2)
path = c.scanAtPathDirectives(aList)
# print (path,p2.h)
endpath = g.os_path_normpath('again/again')
assert path and path.endswith(endpath),'expected ending %s got %s' % (
    endpath,path)
#@+node:sps.20100531034136.20111: *6* @path again
#@+node:sps.20100531034136.20112: *7* @path again
#@+node:sps.20100531034136.20113: *8* xyz
#@+node:ekr.20071113194216: *3* leoConfig
# 3 failurs with Alt-5
#@+node:ekr.20060325071703.2: *4* @@test ifgui
guiname = g.app.gui.guiName()

tkinter = c.config.getBool('test_tkinter_setting')
wx      = c.config.getBool('test_wxWindows_setting')

print(guiname)

if guiname == 'tkinter':
    assert(tkinter)
    assert(not wx)

if guiname == 'wxWindows':
    assert(not tkinter)
    assert(wx)
#@+node:ekr.20100211110729.5389: *4* @test g.app.config.writeRecentFilesFileHelper
@first # -*- coding: utf-8 -*-

# On Windows, this works with or without the following line in sitecustomize.py
# sys.setdefaultencoding('utf-8')

import os

if g.isPython3:
    fn ='ффф.leo'
else:
    fn = g.toUnicode('ффф.leo')

g.app.config.writeRecentFilesFileHelper(fn)
assert g.os_path_exists(fn),'fail 1'
os.remove(fn)
assert not g.os_path_exists(fn),'fail 1'
#@+node:ekr.20050203084930.1: *4* @test global settings
w = g.app.config.get(None,'global_setting_for_unit_tests','int')

assert w == 132
#@+node:ekr.20060325071703.1: *4* @test ifplatform
import sys

win32  = c.config.getBool('test_win32_setting')
darwin = c.config.getBool('test_darwin_setting')

if sys.platform == 'win32':
    assert(win32)
    assert(not darwin)

elif sys.platform== 'darwin':
    assert(not win32)
    assert(darwin)

#@+node:ekr.20050203001146: *4* @test local settings (c.page_width)
# g.es(c.page_width)

assert c.page_width == 80
#@+node:ekr.20071113201854: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

print('\nEnd of leoConfig tests')
#@+node:ekr.20100131171342.5592: *3* leoDialogs
#@+node:ekr.20100131171342.5593: *4* @test ctors for all dialogs
# For some reason these don't select the dialog properly when run as a script.
# However, the main reason for the tests is to make sure the ctors don't crash.
# Also, for unit testing the value of c doesn't matter.

oldGui = g.app.gui ; guis = [g.app.gui]

import leo.core.leoGui as leoGui
guis.append(leoGui.unitTestGui())

for gui in guis:
    gui.runAboutLeoDialog(c,'version','copyright','url','email')
    gui.runAskLeoIDDialog()
    gui.runAskOkDialog(c,'title','message')
    gui.runAskOkCancelNumberDialog(c,'title','message')
    gui.runAskOkCancelStringDialog(c,'title','message')
    gui.runAskYesNoDialog(c,'title','message')
    gui.runAskYesNoCancelDialog(c,'title','message')
    # gui.runCompareDialog(c) # Removed.

g.app.gui = oldGui
#@+node:ekr.20071113192611: *3* leoEditCommands
# 24 failures, 2 errors with Alt-5
#@+node:ekr.20070131175538: *4*  Commands A-B
#@+node:ekr.20061101121602.78: *5* @test add-space-to-lines
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.79: *6* work
first line
 line 1
     line a
 line b
last line
#@+node:ekr.20061101121602.80: *6* before sel=2.0,4.6
first line
line 1
    line a
line b
last line
#@+node:ekr.20061101121602.81: *6* after sel=2.0,4.7
first line
 line 1
     line a
 line b
last line
#@+node:ekr.20061101121602.82: *5* @test add-tab-to-lines
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.83: *6* work
first line
    line 1
        line a
            line b
    line c
last line
#@+node:ekr.20061101121602.84: *6* before sel=2.0,5.6
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.85: *6* after sel=2.0,5.10
first line
    line 1
        line a
            line b
    line c
last line
#@+node:ekr.20071113145804.16: *5* @test apropos_bindings
c.helpCommands.aproposBindings()
#@+node:ekr.20071113145804.17: *5* @test apropos_find_commands
c.helpCommands.aproposFindCommands()
#@+node:ekr.20061101121602.86: *5* @test back-char
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.87: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.88: *6* before sel=3.8,3.8
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.89: *6* after sel=3.7,3.7
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.90: *5* @test back-char-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.91: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.92: *6* before sel=4.12,4.12
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.93: *6* after sel=4.11,4.12
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.94: *5* @test back-paragraph
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.95: *6* work
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.96: *6* before sel=9.0,9.0
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.97: *6* after sel=6.7,6.7
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.98: *5* @test back-paragraph-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.99: *6* work
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.100: *6* before sel=9.0,9.5
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.101: *6* after sel=6.7,9.5
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.102: *5* @test back-sentence
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.103: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.104: *6* before sel=3.169,3.169
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.105: *6* after sel=3.143,3.143
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.106: *5* @test back-sentence-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.107: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.108: *6* before sel=3.208,3.208
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.109: *6* after sel=3.143,3.208
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.110: *5* @test back-to-indentation
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.111: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.112: *6* before sel=4.13,4.13
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.113: *6* after sel=4.8,4.8
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20090427104851.7: *5* @test back-to-home (at start of line)
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20090427104851.8: *6* work
if a:
    b = 'xyz'
#@+node:ekr.20090427104851.9: *6* before sel=2.0,2.0
if a:
    b = 'xyz'
#@+node:ekr.20090427104851.10: *6* after sel=2.4,2.4
if a:
    b = 'xyz'
#@+node:ekr.20090427104851.15: *5* @test back-to-home (at indentation
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20090427104851.16: *6* work
if a:
    b = 'xyz'
#@+node:ekr.20090427104851.17: *6* before sel=2.4,2.4
if a:
    b = 'xyz'
#@+node:ekr.20090427104851.18: *6* after sel=2.0,2.0
if a:
    b = 'xyz'
#@+node:ekr.20090427104851.11: *5* @test back-to-home (at end of line)
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20090427104851.12: *6* work
if a:
    b = 'xyz'
#@+node:ekr.20090427104851.13: *6* before sel=2.12,2.12
if a:
    b = 'xyz'
#@+node:ekr.20090427104851.14: *6* after sel=2.4,2.4
if a:
    b = 'xyz'
#@+node:ekr.20061101121602.114: *5* @test back-word
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.115: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.116: *6* before sel=1.183,1.183
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.117: *6* after sel=1.178,1.178
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.118: *5* @test back-word-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.119: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.120: *6* before sel=3.342,3.342
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.121: *6* after sel=3.332,3.342
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.122: *5* @test backward-delete-char
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.123: *6* work
first lie
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.124: *6* before sel=1.9,1.9
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.125: *6* after sel=1.8,1.8
first lie
line 1
    line a
        line b
line c
last line
#@+node:ekr.20071007121529: *5* @test backward-delete-char  (middle of line)
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20071007121529.1: *6* work
firstline
last line
#@+node:ekr.20071007121529.2: *6* before sel=1.6,1.6
first line
last line
#@+node:ekr.20071007121529.3: *6* after sel=1.5,1.5
firstline
last line
#@+node:ekr.20071007120947: *5* @test backward-delete-char (last char)
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20071007120947.6: *6* work
first line
last lin
#@+node:ekr.20071007120947.7: *6* before sel=2.9,2.9
first line
last line
#@+node:ekr.20071007120947.8: *6* after sel=2.8,2.8
first line
last lin
#@+node:ekr.20100817131738.5886: *5* @test backward-delete-word (no selection)
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20100817131738.5887: *6* work
aaaa cccc dddd
#@+node:ekr.20100817131738.5888: *6* before sel=1.10,1.10
aaaa bbbb cccc dddd
#@+node:ekr.20100817131738.5889: *6* after sel=1.5,1.5
aaaa cccc dddd
#@+node:ekr.20100817131738.5894: *5* @test backward-delete-word (selection)
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20100817131738.5895: *6* work
aaaa bbcc dddd
#@+node:ekr.20100817131738.5896: *6* before sel=1.7,1.12
aaaa bbbb cccc dddd
#@+node:ekr.20100817131738.5897: *6* after sel=1.7,1.7
aaaa bbcc dddd
#@+node:ekr.20061101121602.126: *5* @test backward-kill-paragraph
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.127: *6* work
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.128: *6* before sel=9.0,9.0
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.129: *6* after sel=7.0,7.0
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20070131173932: *5* @test backward-kill-sentence
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070131173932.1: *6* work
This is the first sentence.  This
is the second sentence.
#@+node:ekr.20070131173932.2: *6* before sel=3.2,3.2
This is the first sentence.  This
is the second sentence.  And
this is the last sentence.
#@+node:ekr.20070131173932.3: *6* after sel=2.23,2.23
This is the first sentence.  This
is the second sentence.
#@+node:ekr.20081215084144.2: *5* @test backward-kill-word
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20081215084144.3: *6* work
This is the first sentence.  This
is the second sentence.  And
this  the last sentence.
#@+node:ekr.20081215084144.4: *6* before sel=3.7,3.7
This is the first sentence.  This
is the second sentence.  And
this is the last sentence.
#@+node:ekr.20081215084144.5: *6* after sel=3.5,3.5
This is the first sentence.  This
is the second sentence.  And
this  the last sentence.
#@+node:ekr.20061101121602.130: *5* @test beginning-of-buffer
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.131: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.132: *6* before sel=5.56,5.56
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.133: *6* after sel=1.0,1.0
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.134: *5* @test beginning-of-buffer-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.135: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.136: *6* before sel=3.423,3.423
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.137: *6* after sel=1.0,3.423
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.138: *5* @test beginning-of-line
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.139: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.140: *6* before sel=3.10,3.10
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.141: *6* after sel=3.0,3.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.142: *5* @test beginning-of-line-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.143: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.144: *6* before sel=4.10,4.10
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.145: *6* after sel=4.0,4.10
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20081111084046.1: *5* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

#@+node:ekr.20081111084046.2: *4*  Commands C-E
#@+node:ekr.20061101121602.146: *5* @test capitalize-word
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.147: *6* work
first line
line 1
    Line a
        line b
line c
last line
#@+node:ekr.20061101121602.148: *6* before sel=3.6,3.6
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.149: *6* after sel=3.6,3.6
first line
line 1
    Line a
        line b
line c
last line
#@+node:ekr.20061101121602.150: *5* @test center-line
@pagewidth 70 # Required for unit test.

import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.151: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related,
leading to around 500 deaths per year and nearly $14 billion in damage.
StormReady, a program started in 1999 in Tulsa, OK,
helps arm America's communities with the communication and safety
skills needed to save lives and property– before and during the event.
StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.152: *6* before sel=3.0,9.0
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related,
leading to around 500 deaths per year and nearly $14 billion in damage.
StormReady, a program started in 1999 in Tulsa, OK,
helps arm America's communities with the communication and safety
skills needed to save lives and property– before and during the event.
StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.153: *6* after sel=3.0,9.0
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related,
leading to around 500 deaths per year and nearly $14 billion in damage.
StormReady, a program started in 1999 in Tulsa, OK,
helps arm America's communities with the communication and safety
skills needed to save lives and property– before and during the event.
StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.154: *5* @test center-region
@pagewidth 70 # Required for unit test.

import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.155: *6* work
Some 90% of all presidentially declared disasters are weather related,
leading to around 500 deaths per year and nearly $14 billion in damage.
         StormReady, a program started in 1999 in Tulsa, OK,
  helps arm America's communities with the communication and safety
skills needed to save lives and property– before and during the event.
StormReady helps community leaders and emergency managers strengthen local safety programs.
#@+node:ekr.20061101121602.156: *6* before sel=1.0,7.0
Some 90% of all presidentially declared disasters are weather related,
leading to around 500 deaths per year and nearly $14 billion in damage.
StormReady, a program started in 1999 in Tulsa, OK,
helps arm America's communities with the communication and safety
skills needed to save lives and property– before and during the event.
StormReady helps community leaders and emergency managers strengthen local safety programs.
#@+node:ekr.20061101121602.157: *6* after sel=1.0,7.0
Some 90% of all presidentially declared disasters are weather related,
leading to around 500 deaths per year and nearly $14 billion in damage.
         StormReady, a program started in 1999 in Tulsa, OK,
  helps arm America's communities with the communication and safety
skills needed to save lives and property– before and during the event.
StormReady helps community leaders and emergency managers strengthen local safety programs.
#@+node:ekr.20061101121602.158: *5* @test clear-selected-text
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.159: *6* work
first line
line    line b
line c
last line
#@+node:ekr.20061101121602.160: *6* before sel=2.4,4.4
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.161: *6* after sel=2.4,2.4
first line
line    line b
line c
last line
#@+node:ekr.20061101121602.162: *5* @test count-region
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.163: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.164: *6* before sel=2.4,4.8
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.165: *6* after sel=2.4,4.8
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.166: *5* @test delete-char
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.167: *6* work
firstline
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.168: *6* before sel=1.5,1.5
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.169: *6* after sel=1.5,1.5
firstline
line 1
    line a
        line b
line c
last line
#@+node:ekr.20071007120750.3: *5* @test delete-indentation
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20071007121115.1: *6* work
first line
line 1
last line
#@+node:ekr.20071007121115.2: *6* before sel=2.8,2.8
first line
    line 1
last line
#@+node:ekr.20071007121115.3: *6* after sel=2.4,2.4
first line
line 1
last line
#@+node:ekr.20070131162935: *5* @test delete-spaces
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070131162935.1: *6* work
first line
line 1
line a
        line b
line c
last line
#@+node:ekr.20070131162935.2: *6* before sel=3.2,3.2
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20070131162935.3: *6* after sel=3.0,3.0
first line
line 1
line a
        line b
line c
last line
#@+node:ekr.20100830113702.5969: *5* @test delete-word (no selection)
if g.app.gui.guiName() == 'qt':
    exec(g.findTestScript(c,'@common leoEditCommands test code'))
    runEditCommandTest(c,p,inHeadline=False)
    runEditCommandTest(c,p,inHeadline=True)
#@+node:ekr.20100830113702.5970: *6* work
aaaa bbbb dddd
#@+node:ekr.20100830113702.5971: *6* before sel=1.10,1.10
aaaa bbbb cccc dddd
#@+node:ekr.20100830113702.5972: *6* after sel=1.10,1.10
aaaa bbbb dddd
#@+node:ekr.20100830113702.5977: *5* @test delete-word (selection)
if g.app.gui.guiName() == 'qt':

    exec(g.findTestScript(c,'@common leoEditCommands test code'))
    runEditCommandTest(c,p,inHeadline=False)
    runEditCommandTest(c,p,inHeadline=True)
#@+node:ekr.20100830113702.5978: *6* work
aaaa bbcc dddd
#@+node:ekr.20100830113702.5979: *6* before sel=1.7,1.12
aaaa bbbb cccc dddd
#@+node:ekr.20100830113702.5980: *6* after sel=1.7,1.7
aaaa bbcc dddd
#@+node:ekr.20061101121602.170: *5* @test do-nothing
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.171: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.172: *6* before sel=1.0,1.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.173: *6* after sel=1.0,1.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.174: *5* @test downcase-region
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
assert g.app.unitTestDict.get('colorized')
#@+node:ekr.20061101121602.175: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. stormready, a program started in 1999 in tulsa, ok, helps arm america's communities with the communication and safety skills needed to save lives and property– before and during the event. stormready helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.176: *6* before sel=3.0,4.0
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.177: *6* after sel=3.0,4.0
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. stormready, a program started in 1999 in tulsa, ok, helps arm america's communities with the communication and safety skills needed to save lives and property– before and during the event. stormready helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.178: *5* @test downcase-word
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
assert g.app.unitTestDict.get('colorized')
#@+node:ekr.20061101121602.179: *6* work
xyzzy line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.180: *6* before sel=1.4,1.4
XYZZY line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.181: *6* after sel=1.4,1.4
xyzzy line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.182: *5* @test end-of-buffer
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.183: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.184: *6* before sel=1.3,1.3
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.185: *6* after sel=7.0,7.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.186: *5* @test end-of-buffer-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.187: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.188: *6* before sel=1.0,1.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.189: *6* after sel=1.0,7.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.190: *5* @test end-of-line
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.191: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.192: *6* before sel=1.0,1.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.193: *6* after sel=1.10,1.10
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061128082002: *5* @test end-of-line 2
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061128082002.1: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061128082002.2: *6* before sel=6.0,6.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061128082002.3: *6* after sel=6.9,6.9
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.194: *5* @test end-of-line-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.195: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.196: *6* before sel=3.0,3.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.197: *6* after sel=3.0,3.10
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.198: *5* @test exchange-point-mark
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.199: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.200: *6* before sel=1.0,1.10
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.201: *6* after sel=1.0,1.10
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.202: *5* @test extend-to-line
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.203: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.204: *6* before sel=3.3,3.3
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.205: *6* after sel=3.0,3.10
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.206: *5* @test extend-to-paragraph
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.207: *6* work
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.208: *6* before sel=9.0,9.0
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.209: *6* after sel=8.0,13.33
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.210: *5* @test extend-to-sentence
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.211: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.212: *6* before sel=3.5,3.5
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.213: *6* after sel=1.395,3.142
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.214: *5* @test extend-to-word
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.215: *6* work
first line
line 1
    line_24a a
        line b
line c
last line
#@+node:ekr.20061101121602.216: *6* before sel=3.10,3.10
first line
line 1
    line_24a a
        line b
line c
last line
#@+node:ekr.20061101121602.217: *6* after sel=3.4,3.12
first line
line 1
    line_24a a
        line b
line c
last line
#@+node:ekr.20081111082931.1: *5* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False
#@+node:ekr.20070131175538.1: *4*  Commands F-L
#@+node:ekr.20061128090441: *5* @@test kill-line end-2
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061128090441.1: *6* work
line 1
line 2
#@+node:ekr.20061128090441.3: *6* before sel=3.0,3.0
line 1
line 2
#@+node:ekr.20061128090441.2: *6* after sel=2.6,2.6
line 1
line 2
#@+node:ekr.20061101121602.218: *5* @test fill-paragraph
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.219: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.220: *6* before sel=3.0,3.7
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage.
StormReady, a program started in 1999 in Tulsa, OK,
helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event.
StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.221: *6* after sel=8.33,8.33
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20071007120750.4: *5* @test fill-region (one paragraph)
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20071007121312.1: *6* work
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related,
leading to around 500 deaths per year and nearly
$14 billion in damage.
StormReady, a program started in 1999 in Tulsa,
OK, helps arm America's communities with the communication
and safety skills needed to save lives and property– before and during the event.
StormReady helps community leaders
and emergency managers strengthen local safety programs.

StormReady communities are better prepared
to save lives from the onslaught of severe
weather through better planning, education, and awareness.
No community is storm proof,
but
StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20071007121312.2: *6* before sel=1.0,9.7
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms,
2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes.
Potentially deadly
weather impacts every American.
Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related,
leading to around 500 deaths per year and nearly
$14 billion in damage.
StormReady, a program started in 1999 in Tulsa,
OK, helps arm America's communities with the communication
and safety skills needed to save lives and property– before and during the event.
StormReady helps community leaders
and emergency managers strengthen local safety programs.

StormReady communities are better prepared
to save lives from the onslaught of severe
weather through better planning, education, and awareness.
No community is storm proof,
but
StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20071007121312.3: *6* after sel=6.7,6.7
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related,
leading to around 500 deaths per year and nearly
$14 billion in damage.
StormReady, a program started in 1999 in Tulsa,
OK, helps arm America's communities with the communication
and safety skills needed to save lives and property– before and during the event.
StormReady helps community leaders
and emergency managers strengthen local safety programs.

StormReady communities are better prepared
to save lives from the onslaught of severe
weather through better planning, education, and awareness.
No community is storm proof,
but
StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20071007124202: *5* @test fill-region (three paragraphs)
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20071007124202.1: *6* work
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20071007124202.2: *6* before sel=1.0,24.78
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms,
2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes.
Potentially deadly
weather impacts every American.
Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related,
leading to around 500 deaths per year and nearly
$14 billion in damage.
StormReady, a program started in 1999 in Tulsa,
OK, helps arm America's communities with the communication
and safety skills needed to save lives and property– before and during the event.
StormReady helps community leaders
and emergency managers strengthen local safety programs.

StormReady communities are better prepared
to save lives from the onslaught of severe
weather through better planning, education, and awareness.
No community is storm proof,
but
StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20071007124202.3: *6* after sel=18.18,18.18
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.222: *5* @test forward-char
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.223: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.224: *6* before sel=1.2,1.2
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.225: *6* after sel=1.3,1.3
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.226: *5* @test forward-char-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.227: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.228: *6* before sel=1.1,1.1
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.229: *6* after sel=1.1,1.2
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.230: *5* @test forward-end-word (end of line)
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.231: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.232: *6* before sel=1.395,1.395
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.233: *6* after sel=3.4,3.4
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.234: *5* @test forward-end-word (start of word)
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.235: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.236: *6* before sel=1.310,1.310
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.237: *6* after sel=1.317,1.317
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.238: *5* @test forward-end-word-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.239: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.240: *6* before sel=3.20,3.20
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.241: *6* after sel=3.20,3.30
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.242: *5* @test forward-paragraph
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.243: *6* work
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.244: *6* before sel=9.0,9.0
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.245: *6* after sel=15.0,15.0
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.246: *5* @test forward-paragraph-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.247: *6* work
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.248: *6* before sel=10.0,10.0
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.249: *6* after sel=10.0,15.0
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.250: *5* @test forward-sentence
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.251: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.252: *6* before sel=3.17,3.17
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.253: *6* after sel=3.142,3.142
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.254: *5* @test forward-sentence-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.255: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.256: *6* before sel=1.264,1.264
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.257: *6* after sel=1.264,1.395
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.258: *5* @test forward-word
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.259: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.260: *6* before sel=1.261,1.261
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.261: *6* after sel=1.273,1.273
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.262: *5* @test forward-word-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.263: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.264: *6* before sel=1.395,1.395
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.265: *6* after sel=1.395,3.0
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20070305095401: *5* @test goNext/PrevVisitedNode
p = c.p.copy()
c.selectPosition(p.threadBack())
p1 = c.p
# print(p1)
c.goPrevVisitedNode()
p2 = c.p
# print(p2)
c.goNextVisitedNode()
p3 = c.p
# print(p3)
# assert p == p3
#@+node:ekr.20100212104817.5351: *5* @test help-for-command
result = c.helpCommands.getBindingsForCommand('help-for-command')
assert result.strip().lower()=='f1'
#@+node:ekr.20061101121602.266: *5* @test indent-relative
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.267: *6* work
first line
line 1
    line a
        line b
        line c
last line
#@+node:ekr.20061101121602.268: *6* before sel=5.0,5.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.269: *6* after sel=5.8,5.8
first line
line 1
    line a
        line b
        line c
last line
#@+node:ekr.20061101121602.270: *5* @test indent-rigidly
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.271: *6* work
first line
	line 1
	    line a
	        line b
	line c
last line
#@+node:ekr.20061101121602.272: *6* before sel=2.0,5.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.273: *6* after sel=2.0,5.1
first line
	line 1
	    line a
	        line b
	line c
last line
#@+node:ekr.20071007120750.5: *5* @test indent-to-comment-column
import leo.core.leoTest as leoTest
c.editCommands.ccolumn = 4 # Set the comment column
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20071007121312.5: *6* work
first line
    line b
last line
#@+node:ekr.20071007121312.6: *6* before sel=2.0,2.0
first line
line b
last line
#@+node:ekr.20071007121312.7: *6* after sel=2.4,2.4
first line
    line b
last line
#@+node:ekr.20061101121602.274: *5* @test insert-newline
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.275: *6* work
first li
ne
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.276: *6* before sel=1.8,1.8
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.277: *6* after sel=2.0,2.0
first li
ne
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.278: *5* @test insert-parentheses
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.279: *6* work
first() line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.280: *6* before sel=1.5,1.5
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.281: *6* after sel=1.6,1.6
first() line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061128090338: *5* @test kill-line end-1
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061128090338.1: *6* work
line 1
line 2

#@+node:ekr.20061128090338.2: *6* before sel=3.5,3.5
line 1
line 2
line 3
#@+node:ekr.20061128090338.3: *6* after sel=3.0,3.0
line 1
line 2

#@+node:ekr.20061128090021: *5* @test kill-line middle-1
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061128090021.1: *6* work
line 1
line 2

line 4
#@+node:ekr.20061128090021.2: *6* before sel=3.0,3.0
line 1
line 2
line 3
line 4
#@+node:ekr.20061128090021.3: *6* after sel=3.0,3.0
line 1
line 2

line 4
#@+node:ekr.20061128090147: *5* @test kill-line middle-2
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061128090147.1: *6* work
line 1
line 2
line 4
#@+node:ekr.20061128090147.2: *6* before sel=3.0,3.0
line 1
line 2

line 4
#@+node:ekr.20061128090147.3: *6* after sel=3.0,3.0
line 1
line 2
line 4
#@+node:ekr.20061101121602.282: *5* @test kill-paragraph
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.283: *6* work
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.



StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.285: *6* before sel=9.0,9.0
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.

Some 90% of all presidentially declared disasters are weather related, leading
to around 500 deaths per year and nearly $14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK, helps arm America's communities with the
communication and safety skills needed to save lives and property– before and
during the event. StormReady helps community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20061101121602.284: *6* after sel=8.0,8.0
Americans live in the most severe weather-prone country on Earth. Each year,
Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000
tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly
weather impacts every American. Communities can now rely on the National Weather
Service’s StormReady program to help them guard against the ravages of Mother
Nature.



StormReady communities are better prepared to save lives from the onslaught of
severe weather through better planning, education, and awareness. No community
is storm proof, but StormReady can help communities save lives. Does StormReady
make a difference?
#@+node:ekr.20070131172706: *5* @test kill-sentence
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070131172706.1: *6* work
This is the first sentence.  And
this is the last sentence.
#@+node:ekr.20070131172706.2: *6* before sel=2.2,2.2
This is the first sentence.  This
is the second sentence.  And
this is the last sentence.
#@+node:ekr.20070131172706.3: *6* after sel=1.27,1.27
This is the first sentence.  And
this is the last sentence.
#@+node:ekr.20081215084144.7: *5* @test kill-word
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20081215084144.8: *6* work
This is the first sentence.  This
is the  sentence.  And
this is the last sentence.
#@+node:ekr.20081215084144.9: *6* before sel=2.6,2.6
This is the first sentence.  This
is the second sentence.  And
this is the last sentence.
#@+node:ekr.20081215084144.10: *6* after sel=2.7,2.7
This is the first sentence.  This
is the  sentence.  And
this is the last sentence.
#@+node:ekr.20081111084046.3: *5* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False
#@+node:ekr.20110610122533.3369: *5* goto-global-line tests
#@+node:ekr.20110610122533.3388: *6* Tests with @auto as the root
#@+node:ekr.20110610122533.3389: *7* @test goto-line-number @auto 1
root = p.parent().parent()
h = '@auto unittest/at-auto-line-number-test.py'
target = g.findNodeAnywhere(c,h)
assert target,'no @auto node'

p,n,found = c.goToLineNumber(c).countLines(target,2)
assert found,'not found'
assert n == 1,'n: %s' % (n)
assert p.h == 'at_auto_child',p.h
#@+node:ekr.20110610122533.3390: *7* @test goto-global-line @auto 2
h = '@auto unittest/at-auto-line-number-test.py'
root = g.findNodeAnywhere(c,h)
assert root,'no root'
p,n,found = c.goToLineNumber(c).countLines(root,20)
assert not found,'not found'
#@+node:ekr.20110610122533.3391: *7* @test goto-global-line @auto 3
h = '@auto unittest/at-auto-line-number-test.py'
root1 = g.findNodeAnywhere(c,h)
assert root1
assert root1.isAnyAtFileNode()

fileName,lines,n,root = c.goToLineNumber(c).setup_file(n=3,p=root1)
assert fileName == h[6:],'fileName: %s' % (fileName)
assert root == root1,'root: %s, root1: %s' % (root and root.h,root1 and root1.h)

if 0:
    print('root:%s, isRaw:%s, n:%s, len(lines): %s' % (
        root and root.h,isRaw,n,len(lines)))
#@+node:ekr.20110610122533.3392: *7* @test goto-global-line @auto 4
h = '@auto unittest/at-auto-line-number-test.py'
root1 = g.findNodeAnywhere(c,h)
assert root1
assert root1.isAnyAtFileNode()

scriptData = {'p':root1.copy(),'lines':['a','b','c']}
fileName,lines2,p2,root2 = c.goToLineNumber(c).setup_script(scriptData)

assert fileName == h[6:],'fileName'
assert lines2 == scriptData.get('lines'),'lines'
assert p2 == root1,'p'
assert root2 == root1,'root'

if 0:
    print('root:%s, n:%s, len(lines): %s' % (
        root and root.h,n,len(lines)))
#@+node:ekr.20110610122533.3406: *7* @test goto-global-line @auto 5
# The @auto node must be a child of this node
# for findNodeAnywhere to succeed with Alt-6.
fn = '../test/at-auto-unit-test.py'
root = g.findNodeAnywhere(c,'@auto %s' % (fn))
assert root,'no root'

child1 = root.firstChild()
assert child1,'no child1'
grand11 = child1.firstChild()
assert grand11,'no grand11'
grand12 = grand11.next()
assert grand12,'no grand12'

child2 = child1.next()
assert child2,'no child2'
grand21 = child2.firstChild()
assert grand21,'no grand21'
grand22 = grand21.next()
assert grand22,'no grand22'

def oops(found,p2,node,n,n2):
    result = [' ']
    result.append('goto-global-line test failed at line %s' % (n))
    if not found:
        result.append('line %s not found',n)
    else:
        result.append('got node "%s", expected "%s"' % (p2.h,node.h))
        result.append('got offset %s, expected %s' % (n2,n))
    return '\n'.join(result)

table = (
    # Use 1-based numbers externally.
    # countLines converts to zero-based numbers.
    (1, child1,  0),
    (2, grand11, 0),
    (3, grand11, 1),
    (4, grand12, 0),
    (5, grand12, 1),
    (6, child1,  2),
    (7, child2,  0),
    (8, grand21, 0),
    (9, grand21, 1),
    (10,grand22, 0),
    (11,grand22, 1),
    (12,root,    3),
)

# Test against actual lines of the file.
path = g.os_path_finalize_join(g.app.loadDir,'..','test',fn)
f = open(path,'r') ; s = f.read() ; f.close()
lines = g.splitLines(s) # The lines from the file.
for n,node,index in table:
    goto = c.goToLineNumber(c)
    p2,n2,found = goto.countLines(root,n)
        # n, the argument to countLines, is 1-based
        # n2, the returned index into p2.b, is zero-based
    n -= 1
        # Convert n to zero-based for the comparisons below.
    lines2 = g.splitLines(p2.b)
    if 0:
        print('%2d %s' % (n,repr(lines[n])))
    else:
        ok = lines2[n2].lstrip() == lines[n].lstrip() 
        if not ok:
            i = 0
            for z in lines:
                print('%2d %s' % (i,repr(z)))
                i += 1
        if not ok:
            print('at line %s, index %s, node %s\ngot line %s\nexpected %s' % (
                n,n2,p2.h,repr(lines2[n2].lstrip()),repr(lines[n].lstrip())))
        assert ok
#@+node:ekr.20110610122533.3407: *8* @auto ../test/at-auto-unit-test.py
@language python
@tabwidth -4
@others
# last line
#@+node:ekr.20110610122533.3408: *9* class child1
class child1:
    @others
    # After @others in child1.
#@+node:ekr.20110610122533.3409: *10* child1_method1
def child1_method1():
    pass
#@+node:ekr.20110610122533.3410: *10* child1_method2
def child1_method2():
    pass
#@+node:ekr.20110610122533.3411: *9* class child2
class child2:
    @others
#@+node:ekr.20110610122533.3412: *10* child2_method1
def child2_method1():
    pass
#@+node:ekr.20110610122533.3413: *10* child2_method2
def child2_method2():
    pass
#@+node:ekr.20110610122533.3393: *6* Tests with @file as the root
#@+node:ekr.20110610122533.3394: *7* @test goto-global-line @file 1
root = p.parent().parent()
h = '@file unittest/at-file-line-number-test.py'
target = g.findNodeAnywhere(c,h)
assert target,'no target'

gnx = g.app.nodeIndices.toString(target.v.fileIndex)
assert gnx,'no gnx'

delim = '#'
found = c.goToLineNumber(c).findGnx(delim,root,gnx,h)
assert found,'not found'
#@+node:ekr.20110610122533.3395: *7* @test goto-global-line @file 2
root = p.parent().parent()
h = '@file unittest/at-file-line-number-test.py'
target = g.findNodeAnywhere(c,h)
assert target,'no target'

n = 2
fileName,lines,n,root = c.goToLineNumber(c).setup_file(n,p=target)
assert fileName == h[6:]
# print('lines\n%s' % g.listToString(lines))
assert root == target

ignoreSentinels = True
vnodeName,gnx,offset,delim = c.goToLineNumber(c).findVnode(root,lines,n,ignoreSentinels)

assert lines,'no lines'
assert offset is not None,repr(offset)
assert vnodeName,repr(vnodeName)
#@+node:ekr.20110610122533.3396: *6* Tests with @shadow as the root
#@+node:ekr.20110610122533.3397: *7* @test goto-global-line @shadow
h = '@shadow unittest/at-shadow-line-number-test.py'
root1 = g.findNodeAnywhere(c,h)
assert root1
assert root1.isAnyAtFileNode()

fileName,lines,n,root2 = c.goToLineNumber(c).setup_file(n=6,p=root1)
assert fileName == h[8:],'fileName'
assert root2 == root1

if 0:
    print('root:%s, isRaw:%s, n:%s, len(lines): %s' % (
        root and root.h,isRaw,n,len(lines)))
#@+node:ekr.20110610122533.3398: *6* Tests with @nosent as the root
#@+node:ekr.20110610122533.3399: *7* @test goto-global-line @nosent
h = '@nosent unittest/at-nosent-line-number-test.py'
root1 = g.findNodeAnywhere(c,h)
assert root1
assert root1.isAnyAtFileNode()

fileName,lines,n,root2 = c.goToLineNumber(c).setup_file(n=6,p=root1)
assert fileName == h[8:],'fileName'
assert root2 == root1

if 0:
    print('root:%s, isRaw:%s, n:%s, len(lines): %s' % (
        root and root.h,isRaw,n,len(lines)))
#@+node:ekr.20110610122533.3401: *6* @test goToLineNumber.findRoot 1
root = p.parent().parent()
h = '@auto unittest/at-auto-line-number-test.py'
target = g.findNodeAnywhere(c,h)
assert target,'no target'
child = target.firstChild()
assert child.h == 'at_auto_child','child.h'

p,found = c.goToLineNumber(c).findRoot(child)

assert p == target,'p' #p and p.h
assert found,'not found'
#@+node:ekr.20110610122533.3404: *6* @test goto_showResults not found
c.goToLineNumber(c).showResults(
    found=False,p=p,n=3,n2=3,lines=['a','b'])



#@+node:ekr.20110610122533.3405: *6* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False
#@+node:ekr.20070131175646: *4*  Commands M-Z
#@+node:ekr.20070131171218.1: *5* @@test zap-to-chararacter
#@+node:ekr.20070131171218.2: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.286: *5* @test move-lines-down
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.287: *6* work
first line
line 1
line c
    line a
        line b
last line
#@+node:ekr.20061101121602.288: *6* before sel=3.3,4.3
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.289: *6* after sel=4.3,5.3
first line
line 1
line c
    line a
        line b
last line
#@+node:ekr.20061101121602.290: *5* @test move-lines-up
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.291: *6* work
line 1
first line
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.292: *6* before sel=2.2,2.2
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.293: *6* after sel=1.2,1.2
line 1
first line
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.294: *5* @test move-past-close
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.295: *6* work
first (line)
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.296: *6* before sel=1.10,1.10
first (line)
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.297: *6* after sel=1.12,1.12
first (line)
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.298: *5* @test move-past-close-extend-selection
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.299: *6* work
first line
line 1
    (line )a
        line b
line c
last line
#@+node:ekr.20061101121602.300: *6* before sel=3.7,3.7
first line
line 1
    (line )a
        line b
line c
last line
#@+node:ekr.20061101121602.301: *6* after sel=3.7,3.11
first line
line 1
    (line )a
        line b
line c
last line
#@+node:ekr.20061101121602.302: *5* @test newline-and-indent
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.303: *6* work
first line
line 1
    
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.304: *6* before sel=2.6,2.6
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.305: *6* after sel=3.4,3.4
first line
line 1
    
    line a
        line b
line c
last line
#@+node:ekr.20070315065720: *5* @test next-line
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070315065720.1: *6* work
a

b
#@+node:ekr.20070315065720.2: *6* before sel=1.1,1.1
a

b
#@+node:ekr.20070315065720.3: *6* after sel=2.0,2.0
a

b
#@+node:ekr.20070315065849: *5* @test previous-line
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070315065849.1: *6* work
a

b
#@+node:ekr.20070315065849.2: *6* before sel=3.0,3.0
a

b
#@+node:ekr.20070315065849.3: *6* after sel=2.0,2.0
a

b
#@+node:ekr.20070217071121.1: *5* @test rectangle-clear
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070217071121.2: *6* work
before
aaa   bbb
aaa   bbb
aaa   bbb
aaa   bbb
after
#@+node:ekr.20070217071121.3: *6* before sel=2.3,5.6
before
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
after
#@+node:ekr.20070217071121.4: *6* after sel=2.3,5.6
before
aaa   bbb
aaa   bbb
aaa   bbb
aaa   bbb
after
#@+node:ekr.20070217071121.5: *5* @test rectangle-close
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070217071121.6: *6* work
before
aaabbb
aaabbb
aaabbb
aaabbb
after
#@+node:ekr.20070217071121.7: *6* before sel=2.3,5.6
before
aaa   bbb
aaa   bbb
aaa   bbb
aaa   bbb
after
#@+node:ekr.20070217071121.8: *6* after sel=2.3,5.3
before
aaabbb
aaabbb
aaabbb
aaabbb
after
#@+node:ekr.20070217071121.9: *5* @test rectangle-delete
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070217071121.10: *6* work
before
aaabbb
aaabbb
aaabbb
aaabbb
after
#@+node:ekr.20070217071121.11: *6* before sel=2.3,5.6
before
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
after
#@+node:ekr.20070217071121.12: *6* after sel=2.3,5.3
before
aaabbb
aaabbb
aaabbb
aaabbb
after
#@+node:ekr.20070217071121.17: *5* @test rectangle-kill
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070217071121.18: *6* work
before
aaabbb
aaabbb
aaabbb
aaabbb
after
#@+node:ekr.20070217071121.19: *6* before sel=2.3,5.6
before
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
after
#@+node:ekr.20070217071121.20: *6* after sel=5.3,5.3
before
aaabbb
aaabbb
aaabbb
aaabbb
after
#@+node:ekr.20070217071121.13: *5* @test rectangle-open
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070217071121.14: *6* work
before
aaa   xxxbbb
aaa   xxxbbb
aaa   xxxbbb
aaa   xxxbbb
after
#@+node:ekr.20070217071121.15: *6* before sel=2.3,5.6
before
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
after
#@+node:ekr.20070217071121.16: *6* after sel=2.3,5.6
before
aaa   xxxbbb
aaa   xxxbbb
aaa   xxxbbb
aaa   xxxbbb
after
#@+node:ekr.20070217071121.21: *5* @test rectangle-string
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070217071121.22: *6* work
before
aaas...sbbb
aaas...sbbb
aaas...sbbb
aaas...sbbb
after
#@+node:ekr.20070217071121.23: *6* before sel=2.3,5.6
before
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
after
#@+node:ekr.20070217071121.24: *6* after sel=2.3,5.8
before
aaas...sbbb
aaas...sbbb
aaas...sbbb
aaas...sbbb
after
#@+node:ekr.20070217071121.25: *5* @test rectangle-yank
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20070217071121.26: *6* work
before
aaaY1Ybbb
aaaY2Ybbb
aaaY3Ybbb
aaaY4Ybbb
after
#@+node:ekr.20070217071121.28: *6* before sel=2.3,5.6
before
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
aaaxxxbbb
after
#@+node:ekr.20070217071121.27: *6* after sel=2.3,5.6
before
aaaY1Ybbb
aaaY2Ybbb
aaaY3Ybbb
aaaY4Ybbb
after
#@+node:ekr.20061101121602.306: *5* @test remove-blank-lines
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.307: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.308: *6* before sel=1.0,9.0
first line

line 1
    line a
        line b

line c
last line
#@+node:ekr.20061101121602.309: *6* after sel=1.0,6.9
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.310: *5* @test remove-space-from-lines
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.311: *6* work
first line

line 1
   line a
       line b

line c
last line
#@+node:ekr.20061101121602.312: *6* before sel=1.0,9.0
first line

line 1
    line a
        line b

line c
last line
#@+node:ekr.20061101121602.313: *6* after sel=1.0,9.0
first line

line 1
   line a
       line b

line c
last line
#@+node:ekr.20061101121602.314: *5* @test remove-tab-from-lines
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.315: *6* work
first line
line 1
line a
    line b
line c
last line
#@+node:ekr.20061101121602.316: *6* before sel=1.0,7.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.317: *6* after sel=1.0,7.0
first line
line 1
line a
    line b
line c
last line
#@+node:ekr.20061101121602.318: *5* @test reverse-region
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.319: *6* work

last line
line c
        line b
    line a
line 1
first line
#@+node:ekr.20061101121602.320: *6* before sel=1.0,7.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.321: *6* after sel=7.10,7.10

last line
line c
        line b
    line a
line 1
first line
#@+node:ekr.20071113081247: *5* @test reverse-sort-lines
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20071113081247.1: *6* work
z
x
e
d
a
#@+node:ekr.20071113081247.2: *6* before sel=1.0,5.1
a
d
e
z
x
#@+node:ekr.20071113081247.3: *6* after sel=1.0,5.1
z
x
e
d
a
#@+node:ekr.20071113082531: *5* @test reverse-sort-lines-ignoring-case
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20071113082531.1: *6* work
z
Y
X
c
b
A
#@+node:ekr.20071113082531.2: *6* before sel=1.0,6.1
c
A
z
X
Y
b
#@+node:ekr.20071113082531.3: *6* after sel=1.0,6.1
z
Y
X
c
b
A
#@+node:ekr.20071113145804.4: *5* @test selfInsertCommand-1
@first # -*- coding: utf-8 -*-
@language python

try:
    ec = c.editCommands ; w = c.frame.body.bodyCtrl
    s = w.getAllText()

    # This strings tests unicode, paren matching, and auto-indentation.
    u = g.u('(a\u00c9\u03a9B\u3045\u4e7cz):\n') # '(aÉΩBぅ乼cz):\n'
    u = g.u('(pdq):\n')
    w.setInsertPoint(len(s))
    for char in u:
        stroke = g.choose(char=='\n','Return',char)
        event = g.app.gui.create_key_event(c,char,stroke,w)
        ec.selfInsertCommand(event)
    result = w.getAllText()
    #g.trace('result',repr(result))
    assert result.endswith('    '),'result:\n%s' % result
    # Test of autocompleter.
finally:
    if 1:
        w.setAllText(s)
        p.setBodyString(s)
        # g.trace(repr(s))
        c.recolor()

# end:
#@+node:ekr.20071113145804.5: *5* @test selfInsertCommand-2 (replacing tabs)
@language python
@tabwidth -4

try:
    ec = c.editCommands ; w = c.frame.body.bodyCtrl
    s = w.getAllText()
    w.setSelectionRange(len(s)-9,len(s)-6)
    event = g.app.gui.create_key_event(c,'\t','Tab',w)
    ec.selfInsertCommand(event)
    result = w.getAllText()
    # print('result %s' % result)
    assert result.endswith('\n    ###abcdef\n'),'result\n%s' % (repr(result))
finally:
    w.setAllText(s)
    p.setBodyString(s)
    c.recolor_now()

###abcdef
#@+node:ekr.20071007120750.6: *5* @test set-fill-prefix
# xxxx.yyyy

s = p.b
w = c.frame.body.bodyCtrl
w.setSelectionRange(2,11)
c.editCommands.setFillPrefix(event=None)
assert c.editCommands.fillPrefix == 'xxxx.yyyy'
#@+node:ekr.20061101121602.322: *5* @test sort-columns
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.323: *6* work
        line b
    line a
first line
last line
line 1
line c
#@+node:ekr.20061101121602.324: *6* before sel=1.0,6.2
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.325: *6* after sel=1.0,7.0
        line b
    line a
first line
last line
line 1
line c
#@+node:ekr.20061101121602.326: *5* @test sort-lines
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.327: *6* work
first line
        line b
    line a
line 1
line c
last line
#@+node:ekr.20061101121602.328: *6* before sel=2.0,5.6
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.329: *6* after sel=2.0,5.6
first line
        line b
    line a
line 1
line c
last line
#@+node:ekr.20071113081247.8: *5* @test sort-lines-ignoring-case
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20071113081247.9: *6* work
A
B
c
x
z
#@+node:ekr.20071113081247.10: *6* before sel=1.0,5.1
x
z
A
c
B
#@+node:ekr.20071113081247.11: *6* after sel=1.0,5.1
A
B
c
x
z
#@+node:ekr.20100212104817.5346: *5* @test sort-recent-files (new)
c.sortRecentFiles()
#@+node:ekr.20100212104817.5347: *5* @test sort-siblings (new)
child = p.firstChild()
assert child.h == 'b','fail 1'
try:
    c.selectPosition(child)
    c.sortSiblings()
    c.redraw_now()
    child = p.firstChild()
    assert child.h == 'a'
    child = child.next()
    assert child.h == 'b'
    child = child.next()
    assert child.h == 'c'
    assert not child.next()
finally:
    c.undoer.undo()
    p.contract()
    c.redraw(p)
#@+node:ekr.20100212104817.5348: *6* b
#@+node:ekr.20100212104817.5349: *6* a
#@+node:ekr.20100212104817.5350: *6* c
#@+node:ekr.20061101121602.330: *5* @test split-line
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.331: *6* work
first
 line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.332: *6* before sel=1.5,1.5
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.333: *6* after sel=2.0,2.0
first
 line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.334: *5* @test tabify
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.335: *6* work
first line
line 1
	line a
		line b
line c
last line
#@+node:ekr.20061101121602.336: *6* before sel=1.0,7.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.337: *6* after sel=7.0,7.0
first line
line 1
	line a
		line b
line c
last line
#@+node:ekr.20061101121602.338: *5* @test transpose-chars
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.339: *6* work
frist line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.340: *6* before sel=1.2,1.2
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.341: *6* after sel=1.2,1.2
frist line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.342: *5* @test transpose-lines
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.343: *6* work
line 1
first line
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.344: *6* before sel=2.2,2.2
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.345: *6* after sel=2.10,2.10
line 1
first line
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.346: *5* @test untabify
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20061101121602.347: *6* work
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.348: *6* before sel=1.0,7.0
first line
line 1
	line a
		line b
line c
last line
#@+node:ekr.20061101121602.349: *6* after sel=7.0,7.0
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.350: *5* @test upcase-region
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
assert g.app.unitTestDict.get('colorized')
#@+node:ekr.20061101121602.351: *6* work
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

SOME 90% OF ALL PRESIDENTIALLY DECLARED DISASTERS ARE WEATHER RELATED, LEADING TO AROUND 500 DEATHS PER YEAR AND NEARLY $14 BILLION IN DAMAGE. STORMREADY, A PROGRAM STARTED IN 1999 IN TULSA, OK, HELPS ARM AMERICA'S COMMUNITIES WITH THE COMMUNICATION AND SAFETY SKILLS NEEDED TO SAVE LIVES AND PROPERTY– BEFORE AND DURING THE EVENT. STORMREADY HELPS COMMUNITY LEADERS AND EMERGENCY MANAGERS STRENGTHEN LOCAL SAFETY PROGRAMS.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.352: *6* before sel=3.0,4.0
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.353: *6* after sel=3.0,4.0
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

SOME 90% OF ALL PRESIDENTIALLY DECLARED DISASTERS ARE WEATHER RELATED, LEADING TO AROUND 500 DEATHS PER YEAR AND NEARLY $14 BILLION IN DAMAGE. STORMREADY, A PROGRAM STARTED IN 1999 IN TULSA, OK, HELPS ARM AMERICA'S COMMUNITIES WITH THE COMMUNICATION AND SAFETY SKILLS NEEDED TO SAVE LIVES AND PROPERTY– BEFORE AND DURING THE EVENT. STORMREADY HELPS COMMUNITY LEADERS AND EMERGENCY MANAGERS STRENGTHEN LOCAL SAFETY PROGRAMS.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?
#@+node:ekr.20061101121602.354: *5* @test upcase-word
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
assert g.app.unitTestDict.get('colorized')
#@+node:ekr.20061101121602.355: *6* work
first line
line 1
    LINE a
        line b
line c
last line
#@+node:ekr.20061101121602.356: *6* before sel=3.7,3.7
first line
line 1
    line a
        line b
line c
last line
#@+node:ekr.20061101121602.357: *6* after sel=3.7,3.7
first line
line 1
    LINE a
        line b
line c
last line
#@+node:ekr.20081111084046.4: *5* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

#@+node:ekr.20110118082508.3729: *5* reformat-paragraph tests
@language plain
@pagewidth 40
@tabwidth 8
#@+node:ekr.20110118082508.3730: *6* @test reformat-paragraph simple hanging indent
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20110118082508.3745: *7* work
Honor this line that has a hanging
  indentation, please.  Hanging
  indentation is valuable for lists of
  all kinds.  But it is tricky to get
  right. 

Next paragraph.
#@+node:ekr.20110118082508.3746: *7* before sel= 1.0,1.0
Honor this line that has a hanging indentation, please.  Hanging
  indentation is valuable for lists of all kinds.  But it is tricky to get right.

Next paragraph.
#@+node:ekr.20110118082508.3747: *7* after sel= 5.9,5.9
Honor this line that has a hanging
  indentation, please.  Hanging
  indentation is valuable for lists of
  all kinds.  But it is tricky to get
  right. 

Next paragraph.
#@+node:ekr.20110118082508.3748: *6* @test reformat-paragraph simple hanging indent 2
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20110118082508.3754: *7* work
Honor this line that has a hanging
  indentation, please.  Hanging
  indentation is valuable for lists of
  all kinds.  But it is tricky to get
  right. 

Next paragraph.
#@+node:ekr.20110118082508.3755: *7* before sel=2.0,2.0
Honor this line that has
  a hanging indentation, please.  Hanging
    indentation is valuable for lists of all kinds.  But it is tricky to get right.

Next paragraph.
#@+node:ekr.20110118082508.3756: *7* after sel=5.9,5.9
Honor this line that has a hanging
  indentation, please.  Hanging
  indentation is valuable for lists of
  all kinds.  But it is tricky to get
  right. 

Next paragraph.
#@+node:ekr.20110118082508.3757: *6* @test reformat-paragraph simple hanging indent 3
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20110118082508.3763: *7* work
Honor this line that has a hanging
  indentation, please.  Hanging
  indentation is valuable for lists of
  all kinds.  But it is tricky to get
  right. 

Next Paragraph.
#@+node:ekr.20110118082508.3764: *7* before sel=1.0,1.0
Honor this line that 
  has a hanging indentation, 
  please.  Hanging
   indentation is valuable
    for lists of all kinds.  But 
    it is tricky to get right.

Next Paragraph.
#@+node:ekr.20110118082508.3765: *7* after sel=5.9,5.9
Honor this line that has a hanging
  indentation, please.  Hanging
  indentation is valuable for lists of
  all kinds.  But it is tricky to get
  right. 

Next Paragraph.
#@+node:ekr.20110118082508.3766: *6* @test reformat-paragraph paragraph 1 of 3
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20110118082508.3772: *7* work
Americans live in the most severe
weather-prone country on Earth. Each
year, Americans cope with an average of
10,000 thunderstorms, 2,500 floods,
1,000 tornadoes, as well as an average
of 6 deadly hurricanes. Potentially
deadly weather impacts every American.
Communities can now rely on the National
Weather Service’s StormReady program to
help them guard against the ravages of
Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?

Last paragraph.
#@+node:ekr.20110118082508.3773: *7* before sel=1.0,1.0
Americans live in the most severe weather-prone country on Earth. Each year, Americans cope with an average of 10,000 thunderstorms, 2,500 floods, 1,000 tornadoes, as well as an average of 6 deadly hurricanes. Potentially deadly weather impacts every American. Communities can now rely on the National Weather Service’s StormReady program to help them guard against the ravages of Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?

Last paragraph.
#@+node:ekr.20110118082508.3792: *7* after sel=11.14,11.14
Americans live in the most severe
weather-prone country on Earth. Each
year, Americans cope with an average of
10,000 thunderstorms, 2,500 floods,
1,000 tornadoes, as well as an average
of 6 deadly hurricanes. Potentially
deadly weather impacts every American.
Communities can now rely on the National
Weather Service’s StormReady program to
help them guard against the ravages of
Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?

Last paragraph.
#@+node:ekr.20110118082508.3779: *6* @test reformat-paragraph paragraph 2 of 3
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20110118082508.3780: *7* work
Americans live in the most severe
weather-prone country on Earth. Each
year, Americans cope with an average of
10,000 thunderstorms, 2,500 floods,
1,000 tornadoes, as well as an average
of 6 deadly hurricanes. Potentially
deadly weather impacts every American.
Communities can now rely on the National
Weather Service’s StormReady program to
help them guard against the ravages of
Mother Nature.

Some 90% of all presidentially declared
disasters are weather related, leading
to around 500 deaths per year and nearly
$14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK,
helps arm America's communities with the
communication and safety skills needed
to save lives and property– before and
during the event. StormReady helps
community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?

Last paragraph.
#@+node:ekr.20110118082508.3781: *7* before sel=13.0,13.0
Americans live in the most severe
weather-prone country on Earth. Each
year, Americans cope with an average of
10,000 thunderstorms, 2,500 floods,
1,000 tornadoes, as well as an average
of 6 deadly hurricanes. Potentially
deadly weather impacts every American.
Communities can now rely on the National
Weather Service’s StormReady program to
help them guard against the ravages of
Mother Nature.

Some 90% of all presidentially declared disasters are weather related, leading to around 500 deaths per year and nearly $14 billion in damage. StormReady, a program started in 1999 in Tulsa, OK, helps arm America's communities with the communication and safety skills needed to save lives and property– before and during the event. StormReady helps community leaders and emergency managers strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?

Last paragraph.
#@+node:ekr.20110118082508.3782: *7* after sel=23.33,23.33
Americans live in the most severe
weather-prone country on Earth. Each
year, Americans cope with an average of
10,000 thunderstorms, 2,500 floods,
1,000 tornadoes, as well as an average
of 6 deadly hurricanes. Potentially
deadly weather impacts every American.
Communities can now rely on the National
Weather Service’s StormReady program to
help them guard against the ravages of
Mother Nature.

Some 90% of all presidentially declared
disasters are weather related, leading
to around 500 deaths per year and nearly
$14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK,
helps arm America's communities with the
communication and safety skills needed
to save lives and property– before and
during the event. StormReady helps
community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?

Last paragraph.
#@+node:ekr.20110118082508.3787: *6* @test reformat-paragraph paragraph 3 of 3
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20110118082508.3788: *7* work
Americans live in the most severe
weather-prone country on Earth. Each
year, Americans cope with an average of
10,000 thunderstorms, 2,500 floods,
1,000 tornadoes, as well as an average
of 6 deadly hurricanes. Potentially
deadly weather impacts every American.
Communities can now rely on the National
Weather Service’s StormReady program to
help them guard against the ravages of
Mother Nature.

Some 90% of all presidentially declared
disasters are weather related, leading
to around 500 deaths per year and nearly
$14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK,
helps arm America's communities with the
communication and safety skills needed
to save lives and property– before and
during the event. StormReady helps
community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better
prepared to save lives from the
onslaught of severe weather through
better planning, education, and
awareness. No community is storm proof,
but StormReady can help communities save
lives. Does StormReady make a
difference?

Last paragraph.
#@+node:ekr.20110118082508.3789: *7* before sel=25.10,25.10
Americans live in the most severe
weather-prone country on Earth. Each
year, Americans cope with an average of
10,000 thunderstorms, 2,500 floods,
1,000 tornadoes, as well as an average
of 6 deadly hurricanes. Potentially
deadly weather impacts every American.
Communities can now rely on the National
Weather Service’s StormReady program to
help them guard against the ravages of
Mother Nature.

Some 90% of all presidentially declared
disasters are weather related, leading
to around 500 deaths per year and nearly
$14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK,
helps arm America's communities with the
communication and safety skills needed
to save lives and property– before and
during the event. StormReady helps
community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better prepared to save lives from the onslaught of severe weather through better planning, education, and awareness. No community is storm proof, but StormReady can help communities save lives. Does StormReady make a difference?

Last paragraph.
#@+node:ekr.20110118082508.3790: *7* after sel=32.11,32.11
Americans live in the most severe
weather-prone country on Earth. Each
year, Americans cope with an average of
10,000 thunderstorms, 2,500 floods,
1,000 tornadoes, as well as an average
of 6 deadly hurricanes. Potentially
deadly weather impacts every American.
Communities can now rely on the National
Weather Service’s StormReady program to
help them guard against the ravages of
Mother Nature.

Some 90% of all presidentially declared
disasters are weather related, leading
to around 500 deaths per year and nearly
$14 billion in damage. StormReady, a
program started in 1999 in Tulsa, OK,
helps arm America's communities with the
communication and safety skills needed
to save lives and property– before and
during the event. StormReady helps
community leaders and emergency managers
strengthen local safety programs.

StormReady communities are better
prepared to save lives from the
onslaught of severe weather through
better planning, education, and
awareness. No community is storm proof,
but StormReady can help communities save
lives. Does StormReady make a
difference?

Last paragraph.
#@+node:ekr.20110118082508.3793: *6* @test reformat-paragraph list 1 of 5
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20110118082508.3799: *7* work
This paragraph leads of this test.  It
is the "lead" paragraph. 

  1. This is item 
     number 1.  It is the first item in the list.

  2. This is item 
     number 2.  It is the second item in the list.

  3. This is item 
     number 3.  It is the third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3800: *7* before sel=1.0,1.0
This paragraph leads of this test.  It is the "lead"
paragraph.

  1. This is item 
     number 1.  It is the first item in the list.

  2. This is item 
     number 2.  It is the second item in the list.

  3. This is item 
     number 3.  It is the third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3803: *7* after sel=2.25,2.25
This paragraph leads of this test.  It
is the "lead" paragraph. 

  1. This is item 
     number 1.  It is the first item in the list.

  2. This is item 
     number 2.  It is the second item in the list.

  3. This is item 
     number 3.  It is the third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3808: *6* @test reformat-paragraph list 2 of 5
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20110118082508.3809: *7* work
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item 
     number 2.  It is the second item in the list.

  3. This is item 
     number 3.  It is the third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3810: *7* before sel=4.0,4.0
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item 
     number 2.  It is the second item in the list.

  3. This is item 
     number 3.  It is the third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3811: *7* after sel=7.0,7.0
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item 
     number 2.  It is the second item in the list.

  3. This is item 
     number 3.  It is the third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3816: *6* @test reformat-paragraph list 3 of 5
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20110118082508.3817: *7* work
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item number 2. It is the
     second item in the list.

  3. This is item 
     number 3.  It is the third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3818: *7* before sel=7.0,7.0
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item 
     number 2.  It is the second item in the list.

  3. This is item 
     number 3.  It is the third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3819: *7* after sel=8.29,8.29
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item number 2. It is the
     second item in the list.

  3. This is item 
     number 3.  It is the third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3824: *6* @test reformat-paragraph list 4 of 5
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20110118082508.3825: *7* work
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item number 2. It is the
     second item in the list.

  3. This is item number 3. It is the
     third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3826: *7* before sel=10.0,10.0
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item number 2. It is the
     second item in the list.

  3. This is item 
     number 3.  It is the third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3827: *7* after sel=11.28,11.28
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item number 2. It is the
     second item in the list.

  3. This is item number 3. It is the
     third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3832: *6* @test reformat-paragraph list 5 of 5
import leo.core.leoTest as leoTest
leoTest.runEditCommandTest(c,p)
#@+node:ekr.20110118082508.3833: *7* work
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item number 2. It is the
     second item in the list.

  3. This is item number 3. It is the
     third item in the list.

This paragraph ends the test.  It is the
"final" paragraph. 
#@+node:ekr.20110118082508.3834: *7* before sel=13.0,13.0
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item number 2. It is the
     second item in the list.

  3. This is item number 3. It is the
     third item in the list.

This paragraph ends the test.  It is the "final"
paragraph.
#@+node:ekr.20110118082508.3835: *7* after sel=14.19,14.19
This paragraph leads of this test. It is
the "lead" paragraph.

  1. This is item number 1. It is the
     first item in the list.

  2. This is item number 2. It is the
     second item in the list.

  3. This is item number 3. It is the
     third item in the list.

This paragraph ends the test.  It is the
"final" paragraph. 
#@+node:ekr.20061104172236.1: *4*  Function tests
#@+node:ekr.20100902074747.5970: *5* @test addAbbrevHelper
f = c.abbrevCommands.addAbbrevHelper
d = c.abbrevCommands.abbrevs

table = (
    ('ut1','ut1=aa','aa'),
    ('ut2','ut2 =bb','bb'),
    ('ut3','ut3=cc=dd','cc=dd'),
    ('ut4','ut4= ee',' ee'),
    ('ut5','ut5= ff = gg',' ff = gg'),
    ('ut6','ut6= hh==ii',' hh==ii'),
    ('ut7','ut7=j=k','j=k'),
    ('ut8','ut8=l==m','l==m'),
    ('@ut1','@ut1=@a','@a'),
)

for name,s,expected in table:
    for s2,kind in ((s,'(no nl)'),(s+'\n','(nl)')):
        f(s2,tag='unit-test')
        result,tag = d.get(name,(None,None),)
        assert result==expected, '%s expected <%s>, got <%s>' % (
            kind,expected,result)
#@+node:ekr.20061104172236.3: *5* @test capitalizeHelper
# TARGETWORD

w = c.frame.body.bodyCtrl

for (which,result) in (('cap','Targetword'),('low','targetword'),('up','TARGETWORD')):
    w.setInsertPoint(5)
    c.editCommands.capitalizeHelper(event=None,which=which,undoType=None)
    s = w.getAllText()
    word = s[2:12]
    assert word == result, 'Expected %s, got: %s' % (result,repr(word))
    i = w.getInsertPoint()
    assert i == 5, 'Expected 5, got: %d' % i
#@+node:ekr.20061104172236.5: *5* @test extendHelper
ec = c.editCommands ; w = c.frame.body.bodyCtrl

for i,j,python in (
    # ('1.0','4.5',False),
    (5,50,True),
):
    extend = True
    ec.moveSpot = None # It's hard to init this properly.
    ec.extendHelper(w,extend,j)
    i2,j2 = w.getSelectionRange()
    # print(i2,j2)
    #assert 0==i2, 'Expected i=%s, got %s' % (repr(i),repr(i2))
    #assert j==j2, 'Expected j=%s, got %s' % (repr(j),repr(j2))
#@+node:ekr.20080408094623.1: *5* @test findWord
# start
# targetWord

e = c.editCommands
k = c.k ; w = c.frame.body.bodyCtrl
w.setInsertPoint(0)
k.arg = 't' # 'targetWord'
k.setState('find-word',1)
e.oneLineFlag = False
f = e.findWord(event=None)
i,j = w.getSelectionRange()
assert i == 10, 'expected 15, got %s' % (i)
#@+node:ekr.20061104172236.2: *5* @test findWordInLine
# targetWord

e = c.editCommands
k = c.k ; w = c.frame.body.bodyCtrl
w.setInsertPoint(0)
k.arg = 't' # 'targetWord'
k.setState('find-word',1)
for val in (True,False):
    e.oneLineFlag = val
    f = e.findWordInLine(event=None)
    i,j = w.getSelectionRange()
    assert i == 2, 'expected 2, got' % (i)
    # s = w.getAllText()
    # ch = s[i]
    # assert word == 'targetWord', 'got: %s' % word

#@+node:ekr.20071113145804.15: *5* @test helpForMinibuffer
c.helpCommands.helpForMinibuffer()
#@+node:ekr.20061104172236.6: *5* @test moveToHelper
ec = c.editCommands ; w = c.frame.body.bodyCtrl

for i,j,python in (
    #('1.0','4.5',False),
    (5,50,True),
):
    event = None ; extend = True ; ec.moveSpot = None
    w.setInsertPoint(i)
    ec.moveToHelper (event,j,extend)
    i2,j2 = w.getSelectionRange()
    assert i==i2, 'Expected %s, got %s' % (repr(i),repr(i2))
    assert j==j2, 'Expected %s, got %s' % (repr(j),repr(j2))
    w.setSelectionRange(0,0,insert=None)
#@+node:ekr.20061110094226: *5* @test moveUpOrDownHelper
ec = c.editCommands ; w = c.frame.body.bodyCtrl

for i,result,direction in (('5.8','4.8','up'),('5.8','6.8','down')):
    event = None ; extend = False; ec.moveSpot = None
    w.setInsertPoint(i)
    ec.moveUpOrDownHelper (event,direction,extend)
    i2,j2 = w.getSelectionRange()
    if 1:
        break
    else:
        assert i==i2, 'Expected %s, got %s' % (repr(i),repr(i2))
        assert j==j2, 'Expected %s, got %s' % (repr(j),repr(j2))
        w.setSelectionRange(0,0,insert=None)
#@+node:ekr.20061104172236.7: *5* @test scrollHelper
ec = c.editCommands
w = c.frame.body.bodyCtrl

for direction in ('up','down'):
    for distance in ('line','page','half-page'):
        event = g.app.gui.create_key_event(c,None,None,w)
        ec.scrollHelper(event,direction,distance)
#@+node:ekr.20061104172236.4: *5* @test setMoveCol
w = c.frame.body.bodyCtrl
ec = c.editCommands

for spot,result in (('1.0',0),(5,5)):
    ec.setMoveCol(w,spot)
    assert ec.moveSpot == result
    assert ec.moveCol == result
#@+node:ekr.20051107115231: *4*  Typing
# These are mysteriously fragile tests, so they go first
#@+node:ekr.20051122095426: *5* Doctests
#@+node:ekr.20051216171321: *5* General
#@+node:ekr.20051107115231.13: *5* Plugins
#@+node:ekr.20090128184952.3: *6* Test headline abc
#@+node:ekr.20060208072415: *6* @test Delete key sticks in body
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.selectPosition(p)
s = 'ABC'
c.setBodyString(p,s)
try:
    c.bodyWantsFocus()
    w = c.frame.body.bodyCtrl
    w.setInsertPoint(2)
    c.outerUpdate() # This fixed the problem.
    g.app.gui.event_generate(c,'Delete','Delete',w) # Calls c.outerUpdate()
    assert p.b == s[:-1],'oops1: expected "AB", got %s' % p.b
    c.selectPosition(p.threadBack())
    c.selectPosition(p)
    assert p.b == s[:-1],'oops2: expected "AB", got %s' % p.b
finally:
    if 1:
        c.setBodyString(p,'')
        c.redraw(p)
#@+node:ekr.20051125170139: *6* @test Delete key sticks in headline
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.redraw(p) # To make node visible
c.frame.tree.editLabel(p)
w = c.edit_widget(p)
try:
    assert w
    w.setSelectionRange('end','end')
finally:
    if 1:
        c.setHeadString(p,h) # Essential
        c.redraw(p)
#@+node:ekr.20051109091333: *6* @test deleting the last body character text redraws the screen (and icon)
# Not ready yet: generating a backspace seems impossible!

import leo.core.leoTest as leoTest
u = leoTest.testUtils(c)
h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.selectPosition(p)
c.setBodyString(p,'a')
c.redraw_now() # To make node visible and to set the icon.
try:
    c.bodyWantsFocus()
    n = c.frame.tree.redrawCount
    w = c.frame.body.bodyCtrl
    w.setInsertPoint('end')
    g.app.gui.event_generate(c,'\b','BackSpace',w)
    n2 = c.frame.tree.redrawCount
    assert n2 == n + 1,'too many or too few redraws: %d' % (n2-n)
finally:
    if 1:
        c.setBodyString(p,'')
        c.redraw_now()
#@+node:ekr.20051107115231.15: *6* @test editLabel selects entire headline
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)

k = c.keyHandler
frame = c.frame ; tree = frame.tree ; canvas = tree.canvas
h = '@test editLabel selects entire headline'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.redraw(p) # To make node visible
tree.editLabel(p)
w = c.edit_widget(p)
assert w
s = w.getAllText()
selectAll = c.config.getBool('select_all_text_when_editing_headlines')
# g.trace('editLabel selects entire headline',selectAll)
i,j = w.getSelectionRange()
if selectAll:
    assert i == 0 and j == len(s),'oops1: i: %d, j: %d' % (i,j)
else:
    assert i == len(s) and j == len(s),'oops2: i: %d, j: %d' % (i,j)
#@+node:ekr.20051120110335: *6* @test inserting a new node can be undone and redone
u = c.undoer
c.insertHeadline()
assert u.undoMenuLabel == 'Undo Insert Node',repr(c.undoMenuLabel)
c.undoer.undo()
assert u.redoMenuLabel == 'Redo Insert Node',repr(u.undoMenuLabel)
#@+node:ekr.20051125155134: *6* @test inserting a new node draws the screen exactly once
n = c.frame.tree.redrawCount
# print('before')
c.insertHeadline()
c.outerUpdate() # Not actually needed, but should not matter.
# print('after')

try:
    n2 = c.frame.tree.redrawCount
    assert n2 == n + 1,'redraws: %d' % (n2 - n)
finally:
    c.undoer.undo()
#@+node:ekr.20051107115231.18: *6* @test paste and undo in headline - at end
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
k = c.keyHandler
frame = c.frame ; tree = frame.tree ; canvas = tree.canvas
h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.redrawAndEdit(p) # To make node visible
w = c.edit_widget(p)
try:
    assert w,'oops1'
    w.setSelectionRange('end','end')
    paste = 'ABC'
    g.app.gui.replaceClipboardWith(paste)
    w.setSelectionRange('end','end')
    k.manufactureKeyPressForCommandName(w,'paste-text')
    g.app.gui.event_generate(c,'\n','Return',w)
    assert p.h == h + paste,'oops2 got: %s' % p.h
    k.manufactureKeyPressForCommandName(w,'undo')
    assert p.h == h,'oops3 got: %s' % p.h
finally:
    if 1:
        c.setHeadString(p,h) # Essential
        c.redraw(p)
#@+node:ekr.20051107115231.20: *6* @test paste and undo in headline - with selection
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
k = c.keyHandler
frame = c.frame ; tree = frame.tree ; canvas = tree.canvas
h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.redraw(p) # To make node visible
tree.editLabel(p)
w = c.edit_widget(p)
try:
    assert w, 'Null w'
    paste = 'ABC'
    g.app.gui.replaceClipboardWith(paste)
    w.setSelectionRange('1.1','1.2')
    k.manufactureKeyPressForCommandName(w,'paste-text')
    g.app.gui.event_generate(c,'\n','Return',w)
    assert p.h == h[0] + paste + h[2:]
    k.manufactureKeyPressForCommandName(w,'undo')
    assert p.h == h, 'head mismatch'
finally:
    if 1:
        c.setHeadString(p,h) # Essential
        c.redraw(p)
#@+node:ekr.20051107115231.16: *6* @test paste at end of headline
trace = False ; verbose = False
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
k = c.keyHandler
frame = c.frame ; tree = frame.tree ; canvas = tree.canvas
h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
if trace: print('='*20)
c.redrawAndEdit(p) # To make node visible
w = c.edit_widget(p)
g.app.gui.set_focus(c,w)
w2 = g.app.gui.get_focus(c)
if trace: print('focus 1',w2)
if trace: print('*** w ***',w)
if 0: # The tkGui.set_focus now does an update to force the focus.
    w2 = g.app.gui.get_focus(c)
    if w != w2:
        print('*** FAIL ***\nw: %s\nw2: %s' % (w,w2))
    assert w == w2 or hasattr(w,'widget') and w.widget == w2,'w: %s\nw2: %s' % (w,w2)
    if trace: print('focus',w2)
# For the qt gui w is a wrapper and w.widget is the actual widget.

try:
    assert w
    paste = 'ABC'
    g.app.gui.replaceClipboardWith(paste)
    g.app.gui.set_focus(c,w)
    w2 = g.app.gui.get_focus(c)
    if trace: print('focus 1',w2)
    w.setSelectionRange('end','end')
    k.manufactureKeyPressForCommandName(w,'paste-text')
    g.app.gui.event_generate(c,'\n','Return',w)
    w.update()
    if 1:
        assert p.h == h + paste,'Expected: %s, got %s' % (
            h + paste,p.h)
finally:
    if trace: print('-'*20)
    if 1:
        c.setHeadString(p,h) # Essential
        c.redraw(p)
#@+node:ekr.20060208072307: *6* @test paste from menu into body sticks
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)

if c.k.defaultUnboundKeyAction == 'insert':
    h = 'Test headline abc'
    p = u.findNodeAnywhere(h)
    assert p,'node not found: %s' % h
    c.redraw(p)
    c.bodyWantsFocus()
    paste = 'ABC'
    g.app.gui.replaceClipboardWith(paste)
    event = g.app.gui.create_key_event(c,None,None,c.frame.body.bodyCtrl)
    c.frame.pasteText(event)
    
    # Move around and and make sure it doesn't change.
    try:
        assert p.b == paste, 'paste1 failed'
        c.selectPosition(p.threadBack())
        assert p.b == paste, 'stick failed'
        c.selectPosition(p)
        assert p.b == paste, 'revisit failed'
    finally:
        if 1:
            c.setBodyString(p,'')
            c.redraw(p)
#@+node:ekr.20060208072331: *6* @test paste from menu into headline sticks
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.selectPosition(p)
c.frame.tree.editLabel(p)
w = c.edit_widget(p)
w.setSelectionRange('end','end',insert='end')
paste = 'ABC'
g.app.gui.replaceClipboardWith(paste)
event = g.app.gui.create_key_event(c,None,None,w)
c.frame.pasteText(event)
# Move around and and make sure it doesn't change.
try:
    # g.trace('before select',w,w.getAllText())
    c.selectPosition(p.threadBack())
    assert p.h == h + paste,'oops1: expected: %s, got %s' % (h + paste,p.h)
    c.selectPosition(p)
    assert p.h == h + paste,'oops2: expected: %s, got %s' % (h + paste,p.h)
finally:
    if 1:
        c.setHeadString(p,h) # Essential
        c.redraw(p)
#@+node:ekr.20051107115231.24: *6* @test paste from menu to body recolors the body
# Should be a comment# Should be a comment# Should be a comment# Should be a comment
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.selectPosition(p)
c.bodyWantsFocus()
paste = '# Should be a comment'
g.app.gui.replaceClipboardWith(paste)
c.outerUpdate()
n = c.frame.body.colorizer.count
event = g.app.gui.create_key_event(c,None,None,c.frame.body.bodyCtrl)
c.frame.pasteText(event)

# Move around and and make sure it doesn't change.
try:
    # There is no colorizer to test for wx.
    if g.app.gui.guiName() == 'tkinter':
        c.outerUpdate() # Force the coloring before doing the test.
        assert c.frame.body.colorizer.count > n, 'did not recolor text'
finally:
    if 1:
        c.setBodyString(p,'')
        c.redraw(p)
#@+node:ekr.20051107115231.14: *6* @test return ends editing of headline
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)

h = '@test return ends editing of headline'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.redraw(p) # To make node visible
c.frame.tree.editLabel(p)
w = c.edit_widget(p)
guiName = g.app.gui.guiName()
wName = g.app.gui.widget_name(w)
assert wName.startswith('head'),'w.name:%s' % wName
g.app.gui.event_generate(c,'\n','Return',w)
c.outerUpdate()
assert w != c.get_focus(),'oops2: focus in headline'
#@+node:ekr.20051107115231.28: *6* @test selecting new node retains paste in headline
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
k = c.keyHandler
frame = c.frame ; tree = frame.tree ; canvas = tree.canvas
h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.redraw(p) # To make node visible
tree.editLabel(p)
w = c.edit_widget(p)
try:
    assert w,'oops1'
    w.setSelectionRange('end','end')
    paste = 'ABC'
    g.app.gui.replaceClipboardWith(paste)
    w.setSelectionRange('end','end')
    k.manufactureKeyPressForCommandName(w,'paste-text')
    c.selectPosition(p.visBack(c))
    assert p.h == h + paste
    k.manufactureKeyPressForCommandName(w,'undo')
    assert p.h == h,'expected: %s, got: %s' % (
        h,p.h)
finally:
    if 1:
        c.setHeadString(p,h) # Essential
        c.redraw(p)
#@+node:ekr.20051107115231.21: *6* @test selecting new node retains typing in headline
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
k = c.k

if k.defaultUnboundKeyAction == 'insert':
    frame = c.frame ; tree = frame.tree ; canvas = tree.canvas
    h = 'Test headline abc'
    p = u.findNodeAnywhere(h)
    assert p,'node not found: %s' % h
    c.redraw(p) # To make node visible
    tree.editLabel(p)
    w = c.edit_widget(p)
    try:
        assert w
        w.setSelectionRange('end','end')
        g.app.gui.event_generate(c,'X','Shift+X',w)
        g.app.gui.event_generate(c,'Y','Shift+Y',w)
        g.app.gui.event_generate(c,'Z','Shift+Z',w)
        g.app.gui.event_generate(c,'\n','Return',w)
        assert p.h == h + 'XYZ'
        k.manufactureKeyPressForCommandName(w,'undo')
        assert p.h == h
    finally:
        if 1:
            c.setHeadString(p,h) # Essential
            c.redraw(p)
#@+node:ekr.20051107115231.17: *6* @test typing and undo in headline - at end
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
k = c.k

if k.defaultUnboundKeyAction == 'insert':
    frame = c.frame ; tree = frame.tree ; canvas = tree.canvas
    h = 'Test headline abc'
    p = u.findNodeAnywhere(h)
    assert p,'node not found: %s' % h
    c.redrawAndEdit(p) # To make the node visible.
    w = c.edit_widget(p)
    # print('guiName',g.app.gui.guiName())
    try:
        assert w, 'oops1'
        wName = g.app.gui.widget_name(w)
        assert wName.startswith('head'),'w.name:%s' % wName
        w.setSelectionRange('end','end')
        g.app.gui.event_generate(c,'X','Shift+X',w)
        g.app.gui.event_generate(c,'Y','Shift+Y',w)
        g.app.gui.event_generate(c,'Z','Shift+Z',w)
        g.app.gui.event_generate(c,'\n','Return',w)
        assert p.h == h + 'XYZ',(
            'oops2: expected: %s, got: %s' % (
                h + 'XYZ',p.h))
        if g.app.gui.guiName() != 'nullGui':
            assert c.undoer.undoMenuLabel == 'Undo Typing','oops3: %s' % (
                c.undoer.undoMenuLabel)
        k.manufactureKeyPressForCommandName(w,'undo')
        if g.app.gui.guiName() != 'nullGui':
            assert c.undoer.redoMenuLabel == 'Redo Typing','oops4'
        assert p.h == h,'oops5 got: %s, expected: %s' % (
            p.h,h)
    finally:
        if 1:
            c.setHeadString(p,h) # Essential
            c.redraw(p)
#@+node:ekr.20060208072358: *6* @test typing in empty body text redraws the screen (and icon)
# This test is too flaky for Tk.
if g.app.gui.guiName() != 'tkinter':

    import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)

    h = 'Test headline abc'
    p = u.findNodeAnywhere(h)
    assert p,'node not found: %s' % h
    c.selectPosition(p)
    c.bodyWantsFocus()
    c.redraw(p) # To make node visible
    n = c.frame.tree.redrawCount
    assert not p.b, 'oops1'
    try:
        # print('before insert a',c.p)
        assert p == c.p,'position has changed!'
        w = c.frame.body.bodyCtrl
        g.app.gui.event_generate(c,'a','a',w)
        assert p.b == 'a', 'expected "a", got: %s' % repr(p.b)
        if g.app.gui.guiName() != 'nullGui':
            n2 = c.frame.tree.redrawCount
            c.outerUpdate() # Force the coloring before doing the test.
            assert n2 == n + 1,'too many or too few redraws: expected 1: got: %d' % (n2-n)
    finally:
        if 1:
            c.setBodyString(p,'')
            c.redraw(p)
#@+node:ekr.20051107115231.25: *6* @test typing in headline recomputes width
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
k = c.keyHandler
h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.redraw(p) # To make node visible
c.frame.tree.editLabel(p)
w = c.edit_widget(p)
try:
    assert w
    g.app.gui.set_focus(c,w)
    w2 = g.app.gui.get_focus(c)
    # assert w == w2 or hasattr(w,'widget') and w.widget == w2,'w: %s\nw2: %s' % (w,w2)
    w.setSelectionRange('end','end')
    n = w.getWidth()
    g.app.gui.event_generate(c,'X','Shift+X',w)
    g.app.gui.event_generate(c,'Y','Shift+Y',w)
    g.app.gui.event_generate(c,'Z','Shift+Z',w)
    g.app.gui.event_generate(c,'\n','Return',w)
    w.update()
    assert w, 'fail 2'
    # n2 = w.getWidth()
    # if g.app.gui.guiName() == 'tkinter':
        # assert n2 > n, '%s %s' % (n2,n)
    # g.trace(n,n2)
finally:
    if 1:
        c.setHeadString(p,h) # Essential
        c.redraw(p)
#@+node:ekr.20051109091731: *6* @test typing in non-empty body text does not redraw the screen
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)

h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.setBodyString(p,'a')
c.redraw(p) # To make node visible
# print('after redraw_now')
c.bodyWantsFocus()
n = c.frame.tree.redrawCount
try:
    w = c.frame.body.bodyCtrl
    g.app.gui.event_generate(c,'a','a',w)
    n2 = c.frame.tree.redrawCount
    assert n2 == n,'too many redraws: %d' % (n2-n)
finally:
    if 1:
        c.setBodyString(p,'')
        c.redraw(p)
#@+node:ekr.20051120115046: *6* @test undoing insert node restores previous node's body text
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
h = 'Test headline abc'
p = u.findNodeAnywhere(h)
assert p,'node not found: %s' % h
c.selectPosition(p)
body = 'This is a test'
c.setBodyString(p,body)

try:
    assert p.b == body
    c.insertHeadline()
    c.undoer.undo()
    assert p.b == body
finally:
    c.setBodyString(p,'')
#@+node:ekr.20060131102450: *6* print end of typing and undo tests
print('\nEnd of typing and undo tests')
#@+node:ekr.20051109143831: *5* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractAllHeadlines()
g.app.unitTestDict['restoreSelectedNode']=False


#@+node:ekr.20100830114008.5967: *4* @common leoEditCommands test code
@others
#@+node:ekr.20100830114008.5968: *5* runEditCommandTest
import leo.core.leoTest as leoTest

@
This is an updated version of leo.core.leoTest.runEditCommandTest,
moved here to take advantage of EKR's new common-test-code-sharing
mechanism. It should be okay to delete the old code and replace
all uses with:

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

def runEditCommandTest (c,p,inHeadline=False):
    '''
    This is a helper for testing edit commands. It takes the name of the
    command from the title of the test and the before and after conditions
    from child nodes.

    :param inHeadline: if True, tests the command in the headline; if False,
    tests the command in the body.
    '''

    u = leoTest.testUtils(c) ; atTest = p.copy()

    h = atTest.h
    assert h.startswith('@test '),'expected head: %s, got: %s' % ('@test',h)
    commandName = h[6:].strip()
    # Ignore everything after the actual command name.
    i = g.skip_id(commandName, 0, chars='-')
    commandName = commandName[:i]
    assert commandName, 'empty command name'
    command = c.commandsDict.get(commandName)
    assert command, 'no command: %s' % (commandName)

    work,before,after = u.findChildrenOf(atTest)
    before_h = 'before sel='
    after_h = 'after sel='
    for node,h in ((work,'work'),(before,before_h),(after,after_h)):
        h2 = node.h
        assert h2.startswith(h),'expected head: %s, got: %s' % (h,h2)

    sels = []
    for node,h in ((before,before_h),(after,after_h)):
        sel = node.h[len(h):].strip()
        aList = [str(z) for z in sel.split(',')]
        sels.append(tuple(aList))
    sel1,sel2 = sels
    #g.trace(repr(sels))

    c.selectPosition(work)

    if inHeadline:
        c.setHeadString(work,before.b)
        # To make the node visible, and edit the label
        c.redrawAndEdit(work)
        w = c.edit_widget(work)
        g.app.gui.set_focus(c,w)
    else:
        w = c.frame.body.bodyCtrl
        c.setBodyString(work,before.b)

    try:
        #g.trace(repr(sel1[0]),repr(sel1[1]))
        w.setSelectionRange(sel1[0],sel1[1],insert=sel1[1])
        if inHeadline:
            # simulateCommand doesn't seem to work when editing a headline
            c.k.manufactureKeyPressForCommandName(w,commandName)
        else:
            c.k.simulateCommand(commandName)

        # Exit headline-editing mode
        if inHeadline:
            g.app.gui.event_generate(c,'\n','Return',w)

        location = 'headline' if inHeadline else 'body'
        s1 = work.h if inHeadline else work.b
        s2 = after.b

        assert s1 == s2, 'mismatch in %s\nexpected: %s\n     got: %s' % (location,repr(s2),repr(s1))
        sel3 = w.getSelectionRange()
        ins = w.toGuiIndex(w.getInsertPoint())
        #g.trace('ins',ins,'s1[j:...]',repr(s1[j:j+10]))
        # Convert both selection ranges to gui indices.
        sel2_orig = sel2
        # g.trace(w)
        assert len(sel2) == 2,'Bad headline index.  Expected index,index.  got: %s' % sel2
        i,j = sel2 ; sel2 = w.toGuiIndex(i),w.toGuiIndex(j)
        assert len(sel3) == 2,'Bad headline index.  Expected index,index.  got: %s' % sel3
        i,j = sel3 ; sel3 = w.toGuiIndex(i),w.toGuiIndex(j)
        assert sel2 == sel3, 'mismatch in sel\nexpected: %s = %s, got: %s' % (sel2_orig,sel2,sel3)
        c.selectPosition(atTest)
        atTest.contract()
        # Don't redraw.
    finally:
        # Make sure to restore the headline so it can be used for future tests
        if inHeadline:
            c.setHeadString(work,'work')
#@+node:ekr.20100131180007.5453: *4* @test dynamicExpandHelper
# A totally wimpy test.
c.abbrevCommands.dynamicExpandHelper(event=None,prefix='',rlist=None,w=None)
#@+node:ekr.20070306091949: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

print('\nEnd of leoEditCommands tests.')
#@+node:ekr.20100204165850.5371: *4* Toggle commands
# These tests will be important when revising config code.
#@+node:ekr.20100119102849.5108: *5* @test toggle-extend-mode
# backward-find-character and find-character
# can't be tested this way because they require k.getarg.
# They pass hand tests.

<< define table >>

w = c.frame.body.bodyCtrl
child = g.findNodeInChildren(c,p,'work')
assert child
c.selectPosition(child)

for commandName in table:
    # Put the cursor in the middle of the middle line
    # so all cursor moves will actually do something.
    w.setInsertPoint(15) # for move-past-close
    try:
        c.editCommands.extendMode = True
        c.keyHandler.simulateCommand(commandName)
        i,j = w.getSelectionRange()
        assert i != j,'i == j: %s %s' % (i,commandName)
    finally:
        c.editCommands.extendMode = False

#@+node:ekr.20100119102849.5109: *6* << define table >>
# Cursor movement commands affected by extend mode.
# The x-extend-selection commands are not so affected.
table = (
    'back-to-indentation',
    'back-to-home',
    'back-char',
    'back-page',
    'back-paragraph',
    'back-sentence',
    'back-word',
    'beginning-of-buffer',
    'beginning-of-line',
    'end-of-buffer',
    'end-of-line',
    'forward-char',
    'forward-page',
    'forward-paragraph',
    'forward-sentence',
    'forward-end-word',
    'forward-word',
    'move-past-close',
    'next-line',
    'previous-line',
)
#@+node:ekr.20100119102849.5110: *6* work
line 1.
line 2(xxx).
line 3.
#@+node:ekr.20100204165850.5373: *5* @test most toggle commands
k = c.k
colorizer = c.frame.body.getColorizer()
ed = c.editCommands

# These don't set ivars
    # 'toggle-active-pane'),
    # 'toggle-angle-brackets',
    # 'toggle-input-state'),
    # 'toggle-mini-buffer'),
    # 'toggle-split-direction'),

table = (
    (k,'abbrevOn','toggle-abbrev-mode'),
    (k,'enable_autocompleter','toggle-autocompleter'),
    (k,'enable_calltips','toggle-calltips'),
    (ed,'extendMode','toggle-extend-mode'),
    (c,'sparse_find','toggle-find-collapses-nodes'),
    (colorizer,'showInvisibles','toggle-invisibles'),
    (c,'sparse_move','toggle-sparse-move'),
)

for obj,ivar,command in table:
    val1 = getattr(obj,ivar)
    try:
        k.simulateCommand(command)
        val2 = getattr(obj,ivar)
        assert val2 == (not val1),'failed 1 %s' % command
        k.simulateCommand(command)
        val3 = getattr(obj,ivar)
        assert val3 == val1,'failed 2 %s' % command
        # print('pass',command)
    finally:
        setattr(obj,ivar,val1)
#@+node:ekr.20100204173354.5375: *5* @test toggle-find-x
table = (
    ('ignore_case','toggle-find-ignore-case-option'),
    ('search_body','toggle-find-in-body-option'),
    ('search_headline','toggle-find-in-headline-option'),
    ('mark_changes','toggle-find-mark-changes-option'),
    ('mark_finds','toggle-find-mark-finds-option'),
    ('pattern_match','toggle-find-regex-option'),
    # ('reverse','toggle-find-reverse-option'),
    ('whole_word','toggle-find-word-option'),
    ('wrap','toggle-find-wrap-around-option'),
)

finder = c.searchCommands.getHandler().finder
for ivar,command in table:
    val1 = finder.getOption(ivar)
    try:
        c.k.simulateCommand(command)
        val2 = finder.getOption(ivar)
        assert val2 == (not val1),'failed 1 %s' % command
        c.k.simulateCommand(command)
        val3 = finder.getOption(ivar)
        assert val3 == val1,'failed 2 %s' % command
    finally:
        finder.setOption(ivar,val1)
#@+node:ekr.20061001114637: *3* leoFileCommands
# 3 failures with Alt-5
#@+node:ekr.20100206165505.5386: *4* @@test fc.handleNodeConflicts
# More suitable as a hand test:
# it makes no effort to delete the 'Recovered Nodes' node.

c.nodeConflictList = []

for i in range(2):
    c.nodeConflictList.append(g.bunch(
        tag='(uncached)',
        gnx='gnx %s' % (i),
        fileName ='filename %s' % (i),
        b_old='old body %s' % (i),
        b_new='new body %s' % (i),
        h_old='head %s' % (i),
        h_new='head %s' % (i),
    ))

c.fileCommands.handleNodeConflicts()

c.nodeConflictList = []

c.redraw()
#@+node:ekr.20100131180007.5451: *4* @test fc.cleanSaxInputString
s = 'test%cthis' % 27

assert c.fileCommands.cleanSaxInputString(s) == 'test this'
#@+node:ekr.20071113145804.18: *4* @test fc.deleteFileWithMessage
fc=c.fileCommands
fc.deleteFileWithMessage('xyzzy','test')

if 0: # one-time test of es statements.
    fileName = 'fileName' ; kind = 'kind'
    g.es("read only",color="red")
    g.es("exception deleting %s file: %s" % (fileName,kind))
    g.es("exception deleting backup file:" + fileName)
#@+node:ekr.20100131180007.5450: *4* @test fc.getSaxUa
expectedIconDictList = [
{
    'on': 'tnode',
    'where': 'beforeHeadline',
    'yoffset': 0,
    # 'file': u'C:\\leo.repo\\trunk\\leo\\Icons\\Tango\\16x16\\actions\\add.png',
    'file': 'C:\\leo.repo\\trunk\\leo\\Icons\\Tango\\16x16\\actions\\add.png',
    'xpad': 1,
    'type': 'file',
    'xoffset': 2,
    # 'relPath': u'Tango\\16x16\\actions\\add.png',
    'relPath': 'Tango\\16x16\\actions\\add.png',
},
{
    'on': 'tnode',
    'where': 'beforeHeadline',
    'yoffset': 0,
    # 'file': u'C:\\leo.repo\\trunk\\leo\\Icons\\Tango\\16x16\\actions\\bottom.png',
    'file': 'C:\\leo.repo\\trunk\\leo\\Icons\\Tango\\16x16\\actions\\bottom.png',
    'xpad': 1,
    'type': 'file',
    'xoffset': 2,
    # 'relPath': u'Tango\\16x16\\actions\\bottom.png',
    'relPath': 'Tango\\16x16\\actions\\bottom.png',
}]
table = (
('tx','raw',None,"ekr.20090701133940.1767"),
('lineYOffset',None,3,"4b032e"),
# A real icon
('icons',None,expectedIconDictList,
"5d7100287d71012855026f6e71025505746e6f6465710355047479\
70657104550466696c6571055507796f666673657471064b006805583700000\
0433a5c6c656f2e7265706f5c7472756e6b5c6c656f5c49636f6e735c54616e\
676f5c31367831365c616374696f6e735c6164642e706e67710755047870616\
471084b01550577686572657109550e6265666f7265486561646c696e65710a\
5507786f6666736574710b4b02550772656c50617468710c581b00000054616\
e676f5c31367831365c616374696f6e735c6164642e706e67710d757d710e28\
55026f6e710f68035504747970657110550466696c6571115507796f6666736\
57471124b006811583a000000433a5c6c656f2e7265706f5c7472756e6b5c6c\
656f5c49636f6e735c54616e676f5c31367831365c616374696f6e735c626f7\
4746f6d2e706e67711355047870616471144b01550577686572657115550e62\
65666f7265486561646c696e6571165507786f666673657471174b025507726\
56c506174687118581e00000054616e676f5c31367831365c616374696f6e73\
5c626f74746f6d2e706e67711975652e"),
)
for attr,kind,expected,val in table:
    result = c.fileCommands.getSaxUa(attr,val,kind=kind)
    if expected is None: expected = val
    assert g.toEncodedString(expected)==result,'expected %s got %s' % (
        expected,result)
#@+node:ekr.20100131180007.5463: *4* @test fc.handleTnodeSaxAttributes
sax_node = g.bunch(
    tnodeAttributes={
# The 'tx' attribute is handled by contentHandler.tnodeAttributes.
# 'tx':"ekr.20090701133940.1767",
'lineYOffset':"4b032e",
# A real icon attribute, see the tests below for what we expect
'icons':"5d7100287d71012855026f6e71025505746e6f6465710355047479\
70657104550466696c6571055507796f666673657471064b006805583700000\
0433a5c6c656f2e7265706f5c7472756e6b5c6c656f5c49636f6e735c54616e\
676f5c31367831365c616374696f6e735c6164642e706e67710755047870616\
471084b01550577686572657109550e6265666f7265486561646c696e65710a\
5507786f6666736574710b4b02550772656c50617468710c581b00000054616\
e676f5c31367831365c616374696f6e735c6164642e706e67710d757d710e28\
55026f6e710f68035504747970657110550466696c6571115507796f6666736\
57471124b006811583a000000433a5c6c656f2e7265706f5c7472756e6b5c6c\
656f5c49636f6e735c54616e676f5c31367831365c616374696f6e735c626f7\
4746f6d2e706e67711355047870616471144b01550577686572657115550e62\
65666f7265486561646c696e6571165507786f666673657471174b025507726\
56c506174687118581e00000054616e676f5c31367831365c616374696f6e73\
5c626f74746f6d2e706e67711975652e"
})
try:
    p2 = p.insertAsLastChild()
    v = p2.v
    c.fileCommands.handleTnodeSaxAttributes(sax_node,v)
    # print v,v.u
    d = v.u
    for attr in ('lineYOffset','icons'):
        assert d.get(attr),attr
    for attr in ('tx','a'):
        assert d.get(attr) is None,attr # A known attribute.
finally:
    if 1:
        while p.hasChildren():
            # print('deleting',p.firstChild())
            p.firstChild().doDelete()
#@+node:ekr.20100131180007.5460: *4* @test fc.handleVnodeSaxAttributes
sax_node = g.bunch(
    attributes={
'a':'M',
'lineYOffset':"4b032e",
# A real icon attribute, see the tests below for what we expect
'icons':"5d7100287d71012855026f6e71025505746e6f6465710355047479\
70657104550466696c6571055507796f666673657471064b006805583700000\
0433a5c6c656f2e7265706f5c7472756e6b5c6c656f5c49636f6e735c54616e\
676f5c31367831365c616374696f6e735c6164642e706e67710755047870616\
471084b01550577686572657109550e6265666f7265486561646c696e65710a\
5507786f6666736574710b4b02550772656c50617468710c581b00000054616\
e676f5c31367831365c616374696f6e735c6164642e706e67710d757d710e28\
55026f6e710f68035504747970657110550466696c6571115507796f6666736\
57471124b006811583a000000433a5c6c656f2e7265706f5c7472756e6b5c6c\
656f5c49636f6e735c54616e676f5c31367831365c616374696f6e735c626f7\
4746f6d2e706e67711355047870616471144b01550577686572657115550e62\
65666f7265486561646c696e6571165507786f666673657471174b025507726\
56c506174687118581e00000054616e676f5c31367831365c616374696f6e73\
5c626f74746f6d2e706e67711975652e"
})
try:
    p2 = p.insertAsLastChild()
    v = p2.v
    c.fileCommands.handleVnodeSaxAttributes(sax_node,v)
    # print v,v.u
    d = v.u
    for attr in ('lineYOffset','icons'):
        assert d.get(attr) is not None,attr
    # The a:M attribute should mark the node.
    assert d.get('a') is None
    assert v.isMarked()
    aList = d.get('icons')
    assert aList
    assert len(aList) == 2
    for d2 in aList:
        for key in ('on','where','yoffset','file'):
            assert d2.get(key) is not None,key
finally:
    if 1:
        while p.hasChildren():
            # print('deleting',p.firstChild())
            p.firstChild().doDelete()
#@+node:ekr.20080806072412.1: *4* @test fc.resolveArchivedPosition
child1 = p.firstChild()
child2 = p.firstChild().next()
grandChild1 = child2.firstChild()
grandChild2 = grandChild1.next()
greatGrandChild11 = grandChild1.firstChild()
greatGrandChild12 = greatGrandChild11.next()
greatGrandChild21 = grandChild2.firstChild()
greatGrandChild22 = greatGrandChild21.next()
root_v = p.v

table = (
    # Errors.
    (None,'-1'),
    (None,'1'),
    (None,'0.2'),
    (None,'0.0.0'),
    (None,'0.1.2'),
    # Valid.
    (root_v,'0'),
    (child1.v,'0.0'),
    (child2.v,'0.1'),
    (grandChild1.v,'0.1.0'),
    (greatGrandChild11.v,'0.1.0.0'),
    (greatGrandChild12.v,'0.1.0.1'),
    (grandChild2.v,'0.1.1'),
    (greatGrandChild21.v,'0.1.1.0'),
    (greatGrandChild22.v,'0.1.1.1'),
)

for v,archivedPosition in table:
    v2 = c.fileCommands.resolveArchivedPosition(archivedPosition,root_v)
    assert v == v2,'got %s, expected %s' % (v2,v)
#@+node:ekr.20080806072412.2: *5* first child
#@+node:ekr.20080806072412.3: *5* second child
#@+node:ekr.20080806072412.4: *6* grandChild1
#@+node:ekr.20080806080425.1: *7* greatGrandChild11
#@+node:ekr.20080806080425.2: *7* greatGrandChild12
#@+node:ekr.20080806072412.5: *6* grandChild 2
#@+node:ekr.20080806080425.3: *7* greatGrandChild21
#@+node:ekr.20080806080425.4: *7* greatGrandChild22
#@+node:ekr.20080805105541.1: *4* @test p.archivedPosition
val = p.archivedPosition(root_p=p)
assert val == [0],'expected %s, got %s' % ([0],val)

i = 0
for z in p.parent().children_iter():
    val = z.archivedPosition(root_p=p.parent())
    assert val == [0,i],'expected %s, got %s'%([0,i],val)
    i += 1

i = 0
for z in p.children_iter():
    val = z.archivedPosition(root_p=p)
    assert val == [0,i],'expected %s, got %s'%([0,i],val)
    i += 1

i = 0
for z in p.firstChild().next().children_iter():
    val = z.archivedPosition(root_p=p)
    assert val == [0,1,i],'expected %s, got %s'%([0,1,i],val)
    i += 1
#@+node:ekr.20080805122315.1: *5* first child
#@+node:ekr.20080805122315.2: *5* second child
#@+node:ekr.20080805122315.3: *6* grandChild
#@+node:ekr.20080805122315.4: *6* grandChild 2
#@+node:ekr.20080805104144.1: *4* @test putDescendentVnodeUas
fc = c.fileCommands
child = p.firstChild()
grandChild = child.firstChild()
child.v.unknownAttributes = {'unit_test_child':'abcd'}
grandChild.v.unknownAttributes = {'unit_test_grandchild':'wxyz'}

try:

    s = fc.putDescendentVnodeUas (p)

    if g.isPython3:
        expected = ' descendentVnodeUnknownAttributes="\
7d7100285803000000302e3071017d7102580f000000756e6974\
5f746573745f6368696c64710358040000006162636471047358\
05000000302e302e3071057d71065814000000756e69745f7465\
73745f6772616e646368696c64710758040000007778797a710873752e"'

    else:
        expected = ' descendentVnodeUnknownAttributes="\
7d7100285503302e3071017d7102550f756e69745f746573745f\
6368696c6471035504616263647104735505302e302e3071057d\
71065514756e69745f746573745f6772616e646368696c647107\
55047778797a710873752e"'

    assert s == expected, 'expected: %s, got: %s' % (repr(expected),repr(s))
finally:
    del child.v.unknownAttributes
    del grandChild.v.unknownAttributes
#@+node:ekr.20080805104144.2: *5* child
#@+node:ekr.20080805104144.3: *6* grandChild
#@+node:ekr.20061001114236: *4* @test putUa
fc = c.fileCommands # self is a dummy
p.v.unknownAttributes = {g.u('unit_test'):g.u('abcd')}
s = fc.putUnknownAttributes (p.v)
expected = g.u(' unit_test="58040000006162636471002e"')
assert s == expected, '\nexpected: %s\ngot:      %s' % (repr(expected),repr(s))
#@+node:ekr.20051107115231.9: *4* @test Select a node when file is first loaded
c.redraw(p) # To make node visible

c2 = c.new()
p2 = c2.p

try:
    # This fails, but it is possible to edit the headline.
    # assert c2.edit_widget(p2),'c2.edit_widget(p2) failed: %s' % repr(p2)
    assert p2,'p2 failed: %s' % repr(p2)
    # assert c.edit_widget(p),'c.edit_widget(p) failed: %s' % repr(p)
finally:
    c2.setChanged(False)
    c2.close()
#@+node:ekr.20090507084947.5152: *4* @test t.fileIndex remains the same
assert p.v.fileIndex == ('ekr', '20090507084947', 5152)
#@+node:ekr.20071113202045: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

print('\nEnd of leoFileCommands tests.')
#@+node:ekr.20071113193527: *3* leoFind
# 4 failures with Alt-5
#@+node:ekr.20051107115231.29: *4* @@test Find keeps focus in body & shows selected text
import leo.core.leoEditCommands as leoEditCommands
s = 'foo' ; bodyCtrl = c.frame.body.bodyCtrl

c.searchCommands.openFindTab()
h = c.searchCommands.findTabHandler
w = h.find_ctrl
w.setAllText(s)
c.bodyWantsFocus()
bodyCtrl.setInsertPoint(0)
c.searchCommands.findTabFindNext()
w = c.get_focus()
wName = g.app.gui.widget_name(w)

# in wxPython w != bodyCtrl (it's a proxy)
assert 'body' in wName, 'focus: %s = %s, expected %s = %s' % (
    w,wName,bodyCtrl,g.app.gui.widget_name(bodyCtrl))
#@+node:ekr.20060130151716.3: *4* @test minbuffer find commands
table = (
    're-search-forward',
    're-search-backward',
    'search-forward',
    'search-backward',
    'word-search-forward',
    'word-search-backward',
)

for command in table:
    # This is not a full test.  We must use keyboardQuit here!
    c.k.simulateCommand(command)
    c.k.keyboardQuit(None)
#@+node:ekr.20060130151716.2: *4* @test set find mode commands
table = (
    'set-find-everywhere',
    'set-find-node-only',
    'set-find-suboutline-only',
)

# show-find-tab-options     = Ctrl-o
# show-find-options         = o

for command in table:
    c.k.simulateCommand(command)
#@+node:ekr.20060130151716.4: *4* @test show-find-options
c.k.simulateCommand('show-find-options')
#@+node:ekr.20060130151716.1: *4* @test toggle find options commands
table = (
    # 'toggle-find-clone-find-all-option',
    'toggle-find-ignore-case-option',
    'toggle-find-in-body-option',
    'toggle-find-in-headline-option',
    'toggle-find-mark-changes-option',
    'toggle-find-mark-finds-option',
    'toggle-find-regex-option',
    # 'toggle-find-reverse-option',
    'toggle-find-word-option',
    'toggle-find-wrap-around-option',
)

for command in table:
    c.k.simulateCommand(command)
    c.k.simulateCommand(command)

#@+node:ekr.20071113202153: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

# print('\nEnd of leoFind tests.')
#@+node:ekr.20071113194424: *3* leoFrame
# 3 failures with Alt-5
#@+node:ekr.20060912091510.1: *4* @@test add-editor & delete-editor
import time

c.frame.body.addEditor()

time.sleep(0.5)

c.frame.body.deleteEditor()

time.sleep(0.5)
#@+node:ekr.20090608174319.4791: *4* @@test delete-editor
# This causes trouble if executed quickly after the add-editor command.
# Presumably this is a timing condition that will never happen in practice.

if 0:
    c.frame.body.deleteEditor()
#@+node:ekr.20061104172236.22: *4* @test c.frame.pasteText
# target.

try:
    w = c.frame.body.bodyCtrl
    s = w.getAllText()
    w.setInsertPoint(len(s))
    c.k.previousSelection = 2,8
    event = g.app.gui.create_key_event(c,None,None,w)
    c.frame.pasteText(event=event,middleButton=True)
    s2 = w.getAllText()
    assert len(s2) == len(s) + len('target')
finally:
    w.setAllText(s)
    p.setBodyString(s)
    # g.trace(repr(s))
    c.recolor()

# end
#@+node:ekr.20071113145804.33: *4* @test c.frame.pasteText 2
# target

try:
    w = c.frame.body.bodyCtrl
    # print((w))
    s2 = p.b
    s = w.getAllText()
    assert s == s2, 'w.getAllText() != p.b: len(w)=%d, len(p)=%d' % (len(s),len(s2))
    w.setInsertPoint(len(s))
    c.k.previousSelection = 2,8
    event = g.app.gui.create_key_event(c,None,None,w)
    c.frame.pasteText(event=event,middleButton=True)
    s2 = w.getAllText()
    assert len(s2) == len(s) + len('target')
finally:
    w.setAllText(s)
    p.setBodyString(s)
    # g.trace(repr(s))
    c.recolor()

# end5targettargettargettargettargettargettargettargettargettargettargettargettargettargettargettarget
#@+node:ekr.20061106201509.6: *4* @test leoBody.getInsertLines
# line 1
# line 2
# line 3

w = c.frame.body.bodyCtrl
index = 11 # in the second line.
w.setInsertPoint(index)
before,ins,after = c.frame.body.getInsertLines()
assert before == '# line 1\n','Got %s' % repr(before)
assert ins    == '# line 2\n','Got %s' % repr(ins)
assert after.startswith('# line 3\n'),'line3'
assert after.endswith('# end.\n'),'end'

# end.
#@+node:ekr.20061106201509.7: *4* @test leoBody.getSelectionAreas
# line 1
# line 2
# line 3

w = c.frame.body.bodyCtrl
s = w.getAllText()
start,end = 11,15
w.setSelectionRange(start,end)
before,ins,after = c.frame.body.getSelectionAreas()
assert before == s[0:start],'Got %s' % repr(before)
assert ins    == s[start:end],'Got %s' % repr(ins)
assert after == s[end:]

# end.
#@+node:ekr.20071113145804.32: *4* @test leoBody.getSelectionAreas & test
# line 1
# line 2
# line 3

w = c.frame.body.bodyCtrl
s = w.getAllText()
start,end = 11,15
w.setSelectionRange(start,end)
before,ins,after = c.frame.body.getSelectionAreas()
assert before == s[0:start],'Got %s' % repr(before)
assert ins    == s[start:end],'Got %s' % repr(ins)
assert after == s[end:]

# end.
#@+node:ekr.20100131180007.5359: *4* @test OnIconDoubleClick
c.frame.tree.OnIconDoubleClick(p)
#@+node:ekr.20061104172236.23: *4* @test tkBody.onClick
w = c.frame.body.bodyCtrl
y = 10
for x in range(0,100,10):
    event = g.app.gui.create_key_event(c,None,None,w,x=x,y=y)
    c.frame.body.onClick(event)
#@+node:ekr.20071113202153.1: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

# print('\nEnd of leoFrame tests.')
#@+node:ekr.20071113194033.3: *3* leoGlobals
# No failures with Alt-5 but warnings about no tnode lists.
#@+node:ekr.20100131180007.5398: *4* @test g.adjustTripleString
if 1: # The following must be indented.

    s = '''\
    a
      b

c
    d'''

    s2 = 'a\n  b\n\nc\nd'

    result = g.adjustTripleString(s,c.tab_width)
    assert result == s2,repr(result)


#@+node:ekr.20110510054817.3476: *4* @test g.alert
g.alert(c,'test of g.alert')
#@+node:ekr.20040917062206: *4* @test g.cantImport returns None
assert(g.cantImport("xyzzy","during unit testing") is None)
#@+node:ekr.20060921115303: *4* @test g.checkVersion
# for condition in ('<','<=','>','>='):

for v1,condition,v2 in (
    ('8.4.12','>','8.4.3'),
    ('1','==','1.0'),
    ('2','>','1'),
    ('1.2','>','1'),
    ('2','>','1.2.3'),
    ('1.2.3','<','2'),
    ('1','<','1.1'),
):
    assert g.CheckVersion(v1,v2,condition=condition,trace=False)
#@+node:ekr.20071113143844.9: *4* @test g.CheckVersionToInt
assert g.CheckVersionToInt('12') == 12,'fail 1'
assert g.CheckVersionToInt('2a5') == 2, 'fail 2'
assert g.CheckVersionToInt('b2') == 0, 'fail 3'
#@+node:ekr.20100131180007.5428: *4* @test g.comment_delims_from_extension
# New in Leo 4.6, set_delims_from_language returns '' instead of None.
table = (
    ('.c',      ('//','/*','*/')),
    ('.html',   ('', '<!--', '-->')),
    ('.py',     ('#','','')),
    ('.xxx',    ('','','')),
)

for ext, expected in table:
    result = g.comment_delims_from_extension(ext)
    assert result==expected,'ext %s expected %s, got %s' % (
        ext,expected,result)
#@+node:ekr.20071113145804.26: *4* @test g.convertPythonIndexToRowCol
s1 = 'abc\n\np\nxy'
table1 = (
    (-1,(0,0)), # One too small.
    (0,(0,0)),
    (1,(0,1)),
    (2,(0,2)),
    (3,(0,3)), # The newline ends a row.
    (4,(1,0)),
    (5,(2,0)),
    (6,(2,1)),
    (7,(3,0)),
    (8,(3,1)),
    (9,(3,2)), # One too many.
    (10,(3,2)), # Two too many.
)
s2 = 'abc\n\np\nxy\n'
table2 = (
    (9,(3,2)),
    (10,(4,0)), # One too many.
    (11,(4,0)), # Two too many.
)
s3 = 'ab' # Test special case.  This was the cause of off-by-one problems.
table3 = (
    (-1,(0,0)), # One too small.
    (0,(0,0)),
    (1,(0,1)),
    (2,(0,2)), # One too many.
    (3,(0,3)), # Two too many.
)

for s,table in ((s1,table1),(s2,table2)):
    for i,result in table:
        row,col = g.convertPythonIndexToRowCol(s,i)
        assert row == result[0], 'i: %d, expected row %d, got %d' % (i,result[0],row)
        assert col == result[1], 'i: %d, expected col %d, got %d' % (i,result[1],col)
#@+node:ekr.20071113145804.27: *4* @test g.convertRowColToPythonIndex
s1 = 'abc\n\np\nxy'
s2 = 'abc\n\np\nxy\n'
table1 = (
    (0,(-1,0)), # One too small.
    (0,(0,0)),
    (1,(0,1)),
    (2,(0,2)),
    (3,(0,3)), # The newline ends a row.
    (4,(1,0)),
    (5,(2,0)),
    (6,(2,1)),
    (7,(3,0)),
    (8,(3,1)),
    (9,(3,2)), # One too large.
)
table2 = (
    (9,(3,2)),
    (10,(4,0)), # One two many.
)
for s,table in ((s1,table1),(s2,table2)):
    for i,data in table:
        row,col = data
        result = g.convertRowColToPythonIndex(s,row,col)
        assert i == result, 'row: %d, col: %d, expected: %d, got: %s' % (row,col,i,result)
#@+node:ekr.20071113145804.21: *4* @test g.create_temp_file
theFile,fn = g.create_temp_file()
assert theFile
assert g.isString(fn)
#@+node:ekr.20100131180007.5403: *4* @test g.ensureLeadingNewlines
s = ' \n \n\t\naa bc'
s2 = 'aa bc'

for i in range(3):
    result = g.ensureLeadingNewlines(s,i)
    val = ('\n' * i) + s2
    assert result == val, 'expected %s, got %s' % (
        repr(val),repr(result))
#@+node:ekr.20100131180007.5404: *4* @test g.ensureTrailingNewlines
s = 'aa bc \n \n\t\n'
s2 = 'aa bc'

for i in range(3):
    result = g.ensureTrailingNewlines(s,i)
    val = s2 + ('\n' * i)
    assert result == val, 'expected %s, got %s' % (
        repr(val),repr(result))
#@+node:ekr.20071113145804.22: *4* @test g.es_trace
@first # -*- coding: utf-8 -*-

if 0: # Not usually enabled.
    g.es_trace('\ntest of es_trace: Ă',color='red')
#@+node:ekr.20101021210253.6019: *4* g.Directives & directories
#@+node:ekr.20071113090055.5: *5* @test g.get_directives_dict
# This will work regardless of where this method is.
@language python
@tabwidth -4
# @path xyzzy # Creates folder called xyzzy: interferes with other unit tests.
@pagewidth 120

d = c.atFileCommands.scanAllDirectives(p)
# print(d)
assert d.get('language') == 'python'
assert d.get('tabwidth') == -4
# assert d.get('path').endswith('xyzzy')
assert d.get('pagewidth') == 120
#@+node:ekr.20100131180007.5434: *5* @test g.get_directives_dict 2
@language python
@comment a b c
    # @comment must follow @language.
@tabwidth -8
@pagewidth 72
@encoding utf-8
@path: anError # @path ends with ':'.

# @path xyzzy # Creates folder called xyzzy: interferes with other unit tests.

d = g.get_directives_dict(p)

# assert d.get('_p') == p # Never used, and a bad idea.
assert d.get('language') == 'python'
assert d.get('tabwidth') == '-8'
assert d.get('pagewidth') == '72'
assert d.get('encoding') == 'utf-8'
assert d.get('comment') == 'a b c'
assert not d.get('path'),d.get('path')
# assert d.get('path').endswith('xyzzy')
#@+node:ekr.20101021205258.6010: *5* @test g.makeAllNonExistentDirectories
#@+node:ekr.20061104172236.18: *4* @test g.getLine
s = 'a\ncd\n\ne'

for i,result in (
    (-1,(0,2)), # One too few.
    (0,(0,2)),(1,(0,2)),
    (2,(2,5)),(3,(2,5)),(4,(2,5)),
    (5,(5,6)),
    (6,(6,7)),
    (7,(6,7)), # One too many.
):
    j,k = g.getLine(s,i)
    assert (j,k) == result, 'i: %d, expected %d,%d, got %d,%d' % (i,result[0],result[1],j,k)
#@+node:ekr.20071113145804.28: *4* @test g.getScript strips crlf
script = g.getScript(c,p) # This will get the text of this node.
assert script.find('\r\n') == -1, repr(script)
#@+node:ekr.20061104172236.11: *4* @test g.getWord
s = 'abc xy_z5 pdq'
i,j = g.getWord(s,5)
assert s[i:j] == 'xy_z5','got %s' % s[i:j]
#@+node:ekr.20110612064437.3310: *4* @test g.guessExternalEditor
val = g.guessExternalEditor(c)
assert val,'no val' # This can be different on different platforms.
#@+node:ekr.20100131180007.5417: *4* @test g.openLeoOrZipFile
import zipfile

# Create a zip file for testing.
s = 'this is a test file'
testDir = g.os_path_join(g.app.loadDir,'..','test')
assert g.os_path_exists(testDir)
path = g.os_path_finalize_join(testDir,'testzip.zip')
theFile = zipfile.ZipFile(path,'w')
theFile.writestr('leo-zip-file',s)
theFile.close()

# Open the file, and use read (with no args) to get the contents.
theFile,ok = g.openLeoOrZipFile(path)
assert ok,'not ok'
s2 = theFile.read()
assert s == s2,'s:  %s\ns2: %s' % (repr(s),repr(s2))
#@+node:ekr.20071113145804.19: *4* @test g.pdb
import sys

# Not a good unit test; it probably will never fail.
def aFunction(): pass
assert type(g.pdb)==type(aFunction), 'wrong type for g.pdb: %s' % type(g.pdb)

class myStdout:
    def write(self,s):
        pass # g.es('From pdb:',s)

class myStdin:
    def readline (self):
        return 'c' # Return 'c' (continue) for all requests for input.

def restore():
    sys.stdout,sys.stdin = sys.__stdout__,sys.__stdin__

try:
    sys.stdin = myStdin() # Essential
    sys.stdout=myStdout() # Optional
    g.pdb()
    restore()
    # assert False,'test of reraising'
except Exception:
    restore()
    raise
#@+node:ekr.20100212112056.5361: *4* @test g.printGcAll
g.printGcAll()
#@+node:ekr.20100131180007.5396: *4* @test g.removeBlankLines
for s,expected in (
    ('a\nb', 'a\nb'),
    ('\n  \n\nb\n', 'b\n'),
    (' \t \n\n  \n c\n\t\n', ' c\n'),
):
    result = g.removeBlankLines(s)
    assert result == expected, '\ns: %s\nexpected: %s\nresult:   %s' % (
        repr(s),repr(expected),repr(result))
#@+node:ekr.20071113145804.29: *4* @test g.removeExtraLws
for s,expected in (
    (' a\n b\n c', 'a\nb\nc'),
    (' \n  A\n    B\n  C\n', '\nA\n  B\nC\n'),
):
    result = g.removeExtraLws(s,c.tab_width)
    assert result == expected, '\ns: %s\nexpected: %s\nresult:   %s' % (
        repr(s),repr(expected),repr(result))
#@+node:ekr.20100131180007.5395: *4* @test g.removeLeadingBlankLines
for s,expected in (
    ('a\nb', 'a\nb'),
    ('\n  \nb\n', 'b\n'),
    (' \t \n\n\n c', ' c'),
):
    result = g.removeLeadingBlankLines(s)
    assert result == expected, '\ns: %s\nexpected: %s\nresult:   %s' % (
        repr(s),repr(expected),repr(result))
#@+node:ekr.20100131180007.5402: *4* @test g.removeTrailing
s = 'aa bc \n \n\t\n'
table = (
    ('\t\n ','aa bc'),
    ('abc\t\n ',''),
    ('c\t\n ','aa b'),
)

for arg,val in table:
    result = g.removeTrailing(s,arg)
    assert result == val, 'expected %s, got %s' % (val,result)
#@+node:ekr.20080917151620.13: *4* @test g.scanAtHeaderDirectives header
@header

aList = g.get_directives_dict_list(p)
g.scanAtHeaderDirectives(aList)
#@+node:ekr.20100131180007.5435: *4* @test g.scanAtHeaderDirectives header
@header

c,p = g.getTestVars()
aList = g.get_directives_dict_list(p)
g.scanAtHeaderDirectives(aList)
#@+node:ekr.20080917151620.14: *4* @test g.scanAtHeaderDirectives noheader
@noheader

aList = g.get_directives_dict_list(p)
g.scanAtHeaderDirectives(aList)
#@+node:ekr.20080917151620.15: *4* @test g.scanAtLineendingDirectives cr
@lineending cr

aList = g.get_directives_dict_list(p)
s = g.scanAtLineendingDirectives(aList)

assert s == '\r'
#@+node:ekr.20080917151620.16: *4* @test g.scanAtLineendingDirectives crlf
@lineending crlf

aList = g.get_directives_dict_list(p)
s = g.scanAtLineendingDirectives(aList)
# print('@lineending: %s'%repr(s))

assert s == '\r\n'
#@+node:ekr.20080917151620.17: *4* @test g.scanAtLineendingDirectives lf
@lineending lf

aList = g.get_directives_dict_list(p)
s = g.scanAtLineendingDirectives(aList)

assert s == '\n'
#@+node:ekr.20080917151620.18: *4* @test g.scanAtLineendingDirectives nl
@lineending nl

aList = g.get_directives_dict_list(p)
s = g.scanAtLineendingDirectives(aList)

assert s == '\n'
#@+node:ekr.20080917151620.19: *4* @test g.scanAtLineendingDirectives platform
@lineending platform

import sys

aList = g.get_directives_dict_list(p)
s = g.scanAtLineendingDirectives(aList)

if sys.platform.startswith('win'):
    assert s == '\r\n'
else:
    assert s == '\n'
#@+node:ekr.20100131180007.5442: *4* @test g.scanAtPagewidthDirectives -40
@pagewidth -40

aList = g.get_directives_dict_list(p)
n = g.scanAtPagewidthDirectives(aList)

# The @pagewidth directive in the parent should control.
# Depending on how this test is run, the result could be 80 or None.
assert n in (None,80),repr(n)
#@+node:ekr.20080917151620.21: *4* @test g.scanAtPagewidthDirectives 40
@pagewidth 40

aList = g.get_directives_dict_list(p)
n = g.scanAtPagewidthDirectives(aList)

assert n == 40
#@+node:ekr.20080917151620.22: *4* @test g.scanAtPathDirectives ../test/unittest/at-path-test1.py
aList = g.get_directives_dict_list(p.firstChild())
s = c.scanAtPathDirectives(aList)
end = g.os_path_normpath(r'leo/test')

assert s.endswith(end),repr(s)
#@+node:ekr.20080917151620.23: *5* @thin ../test/unittest/at-path-test1.py
@language python
# unittest/at-path-test1.py 
#@+node:ekr.20080917151620.27: *4* @test g.scanAtPathDirectives @path ../test @path unittest @thin at-path-test3.py
greatGrandChild = p.firstChild().firstChild().firstChild()
aList = g.get_directives_dict_list(greatGrandChild)
s = c.scanAtPathDirectives(aList)
end = g.os_path_normpath(r'leo/test/unittest')

assert s.endswith(end),repr(s)
#@+node:ekr.20080917151620.28: *5* @path ../test
#@+node:ekr.20080917151620.29: *6* @path unittest
#@+node:ekr.20080917151620.30: *7* @thin at-path-test3.py
@language python
# unittest/at-path-test3.py 
#@+node:ekr.20080917151620.24: *4* @test g.scanAtPathDirectives @path ../test/unittest @thin at-path-test2.py
grandChild = p.firstChild().firstChild()
aList = g.get_directives_dict_list(grandChild)
s = c.scanAtPathDirectives(aList)
end = g.os_path_normpath(r'leo/test/unittest')

assert s.endswith(end),repr(s)
#@+node:ekr.20080917151620.25: *5* @path ../test/unittest
#@+node:ekr.20080917151620.26: *6* @thin at-path-test2.py
@language python
# unittest/at-path-test2.py
#@+node:ekr.20080917151620.31: *4* @test g.scanAtTabwidthDirectives +6
@tabwidth 6

aList = g.get_directives_dict_list(p)
n = g.scanAtTabwidthDirectives(aList)

assert n == 6,repr(n)
#@+node:ekr.20080917151620.32: *4* @test g.scanAtTabwidthDirectives -6
@tabwidth -6

aList = g.get_directives_dict_list(p)
n = g.scanAtTabwidthDirectives(aList)

assert n == -6
#@+node:ekr.20080917151620.33: *4* @test g.scanAtWrapDirectives nowrap
@nowrap

aList = g.get_directives_dict_list(p)
s = g.scanAtWrapDirectives(aList)

assert s is False,repr(s)
#@+node:ekr.20080917151620.34: *4* @test g.scanAtWrapDirectives wrap (with @wrap)
@wrap

aList = g.get_directives_dict_list(p)
s = g.scanAtWrapDirectives(aList)

assert s is True,repr(s)
#@+node:ekr.20080917151620.35: *4* @test g.scanAtWrapDirectives wrap (without @nowrap)
aList = g.get_directives_dict_list(p)
s = g.scanAtWrapDirectives(aList)

assert s is None,repr(s)
#@+node:ekr.20100131180007.5426: *4* @test g.set_delims_from_language
# New in Leo 4.6, set_delims_from_language returns '' instead of None.
table = (
    ('c',       ('//','/*','*/')),
    ('python',  ('#','','')),
    ('xxxyyy',  ('','','')),
)

for language, expected in table:
    result = g.set_delims_from_language(language)
    assert result==expected,'language %s expected %s, got %s' % (
        language,expected,result)
#@+node:ekr.20100131180007.5425: *4* @test g.set_delims_from_string
# New in Leo 4.6, set_delims_from_string returns '' instead of None.
table = (
    ('c','@comment // /* */',   ('//','/*','*/')),
    ('c','// /* */',            ('//','/*','*/')),
    ('python','@comment #',     ('#','','')),
    ('python','#',              ('#','','')),
    ('xxxyyy','@comment a b c', ('a','b','c')),
    ('xxxyyy','a b c',          ('a','b','c')),
)

for language,s,expected in table:
    result = g.set_delims_from_string(s)
    assert result==expected,'language %s expected %s, got %s' % (
        language,expected,result)
#@+node:ekr.20100131180007.5421: *4* @test g.setDefaultDirectory
c,p = g.getTestVars()

# result,error = g.setDefaultDirectory(c,p,importing=False)
# assert error == ''
# assert result == c.openDirectory,result

result = g.setDefaultDirectory(c,p,importing=False)
assert result == c.openDirectory,result
#@+node:sps.20100609234650.16094: *4* @test g.skip_blank_lines
end = g.skip_blank_lines("",0)
assert end == 0, "expected 0, got %d" % end
end = g.skip_blank_lines(" ",0)
assert end == 0, "expected 0, got %d" % end
end = g.skip_blank_lines("\n",0)
assert end == 1, "expected 1, got %d" % end
end = g.skip_blank_lines(" \n",0)
assert end == 2, "expected 1, got %d" % end
end = g.skip_blank_lines("\n\na\n",0)
assert end == 2, "expected 2, got %d" % end
end = g.skip_blank_lines("\n\n a\n",0)
assert end == 2, "expected 2, got %d" % end
#@+node:ekr.20061104172236.15: *4* @test g.skip_line
s = 'a\n\nc'

for i,result in (
    (-1,2), # One too few.
    (0,2),(1,2),
    (2,3),
    (3,4),
    (4,4), # One too many.
):
    j = g.skip_line(s,i)
    assert j == result, 'i: %d, expected %d, got %d' % (i,result,j)
#@+node:ekr.20061104172236.16: *4* @test g.skip_to_end_of_line
s = 'a\n\nc'

for i,result in (
    (-1,1), # One too few.
    (0,1),(1,1),
    (2,2),
    (3,4),
    (4,4), # One too many.
):
    j = g.skip_to_end_of_line(s,i)
    assert j == result, 'i: %d, expected %d, got %d' % (i,result,j)
#@+node:ekr.20061104172236.17: *4* @test g.skip_to_start_of_line
s1 = 'a\n\nc'
table1 = (
    (-1,0), # One too few.
    (0,0),(1,0),
    (2,2),
    (3,3),
    (4,4), # One too many.
)
s2 = 'a\n'
table2 = ((1,0),(2,2)) # A special case at end.

for s,table in ((s1,table1),(s2,table2)):
    for i,result in table:
        j = g.skip_to_start_of_line(s,i)
        assert j == result, 'i: %d, expected %d, got %d' % (i,result,j)
#@+node:ekr.20100131180007.5427: *4* @test g.stripPathCruft
table =  (
    (None,None), # Retain empty paths for warnings.
    ('',''),
    (g.app.loadDir,g.app.loadDir),
    ('<abc>','abc'),
    ('"abc"','abc'),
    ("'abc'",'abc'),
)

for path,expected in table:
    result = g.stripPathCruft(path)
    assert result == expected
#@+node:ekr.20050105084757.1: *4* @test g.utils_remove
import os

exists = g.os_path_exists

path = g.os_path_join(g.app.testDir,'xyzzy')
if exists(path):
    os.remove(path)

assert not exists(path)
assert not g.utils_remove(path,verbose=False)

f = open(path,'w')
f.write('test')
f.close()

assert exists(path)
assert g.utils_remove(path,verbose=True)
assert not exists(path)
#@+node:ekr.20050105091547: *4* @test g.utils_rename
import os

exists = g.os_path_exists
path = g.os_path_join(g.app.testDir,'xyzzy')
path2 = g.os_path_join(g.app.testDir,'xyzzy2')

# Create both paths.
for p in (path,path2):
    if exists(p):
        os.remove(p)
    assert not exists(p)
    f = open(p,'w')
    f.write('test %s' % p)
    f.close()
    assert exists(p)

assert g.utils_rename(c,path,path2) #,verbose=True)
assert exists(path2)
f = open(path2)
s = f.read()
f.close()
# print('Contents of %s: %s' % (path2,s))
assert s == 'test %s' % path
os.remove(path2)
assert not exists(path)
#@+node:ekr.20100131180007.5429: *4* @test g.warnOnReadOnlyFile
import os,stat

fc = c.fileCommands
path = g.os_path_finalize_join(g.app.loadDir,'..','test','test-read-only.txt')
if os.path.exists(path):
    os.chmod(path, stat.S_IREAD)
    fc.warnOnReadOnlyFiles(path)
    assert fc.read_only
else:
    fc.warnOnReadOnlyFiles(path)
#@+node:ekr.20050208135429: *4* @test pre-definition of g in scripts
# print(g.listToString(dir()))

for ivar in ('c','g','p'):
    assert ivar in dir()
#@+node:ekr.20071113202153.2: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

# print('\nEnd of leoGlobals tests.')
#@+node:ekr.20100131171342.5599: *3* leoGui
#@+node:ekr.20100131171342.5600: *4* @test w.toGui/PythonIndex
w = c.frame.body.bodyCtrl
s = w.getAllText()

for i in range(len(s)):
    i2 = w.toGuiIndex(i)
    i3 = w.toPythonIndex(i2)
    assert(i3==i)
#@+node:ekr.20100131171342.5601: *4* @test w.toGuiIndex (test2)
#ab
#

w = c.frame.body.bodyCtrl

# This test applies only to tkinter indices.
if g.app.gui.guiName() == 'tkinter':

    table = (
        (-1,'1.0'), # One too small.
        (0,'1.0'),
        (1,'1.1'),
        (2,'1.2'),
        (3,'1.3'), # The newline ends a row.
        (4,'2.0'),
        (5,'2.1'),
    )

    for i,expected in table:
        result = w.toGuiIndex(i)
        assert result == expected,'toGuiIndex(i): %s, expected: %s, got: %s' % (i,expected,result)
#@+node:ekr.20100131171342.5602: *4* @test leoTextWidget
if g.app.gui.guiName() == 'tkinter':

    pc = g.app.pluginsController
    tkGui = pc.loadOnePlugin('leo.plugins.tkGui',verbose=False)
    import Tkinter as Tk
    w = tkGui.leoTkTextWidget()
    w.setAllText('abcdef\n')
    s = w.getAllText()
    assert s == 'abcdef\n'
    s1 = w.get(0,len(s))
    assert s1 == 'abcdef\n'
    w.delete(0,len(s))
    assert len(w.getAllText()) == 0
    w.setAllText('')
    w.insert(0,'abcdef\n')
    s = w.getAllText()
    assert s == 'abcdef\n','got: %s' % repr(s)
    w.setInsertPoint(2)
    i = w.getInsertPoint()
    assert i == 2
    w.setSelectionRange(2,4)
    assert w.hasSelection()
    i,j = w.getSelectionRange()
    assert i==2 and j==4
    s3 = w.getSelectedText()
    assert s3 == 'cd'
    w.deleteTextSelection()
    s4 = w.getAllText()
    assert s4 == 'abef\n'
    w.selectAllText()
    i,j = w.getSelectionRange()
    assert i==0 and j==5,'getSelectionRange failed: i=%d,j=%d' % (i,j)
    w.replace(0,3,'wxyz')
    s5 = w.getAllText()
    assert s5 == 'wxyzf\n','getAllText failed'
    w.flashCharacter(3)
    i = w.xyToGuiIndex(0,0)
    assert i == '1.0','wxToGuiIndex failed'
    i = w.xyToPythonIndex(0,0)
    assert i == 0
    w.mark_set('insert','1.3'),'xyToPythonIndex failed'
    i = w.getInsertPoint()
    assert i == 3
    w.tag_add('test',4,6)
    aTuple = w.tag_ranges('test')
    assert aTuple == (4,6),'tag_add failed: %s' % aTuple
#@+node:ekr.20100131171342.5603: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

# print('\nEnd of leoGui tests.')
#@+node:ekr.20090529141856.4682: *3* leoImport
# These test are inconvenient to include in leoPy.leo
# because they would need a @mark-for-unit-tests node,
# and Alt-5 would execute all the tests.
#@+node:ekr.20090529141856.4684: *4*  Export tests
@language python
@tabwidth -4
#@+node:ekr.20090529141856.4685: *5* @suite Export tests
# Create unit tests in g.app.scriptDict["suite"]


import unittest
import leo.core.leoTest as leoTest

@others

suite = leoTest.makeImportExportSuite(c,"exportTests",doImport=False)

g.app.scriptDict['suite'] = suite
#@+node:ekr.20090529141856.4686: *5* exportTests
@language plain
#@+node:ekr.20090529141856.4687: *6* tempNode
#@+node:ekr.20090529141856.4688: *6* exportHeadlines
#@+node:ekr.20090529141856.4689: *7* dialog
saveFileDialog
test\\unittest\\output\\exportHeadlines.txt
#@+node:ekr.20090529141856.4690: *6* flattenOutline
#@+node:ekr.20090529141856.4691: *7* dialog
saveFileDialog
test\\unittest\\output\\flattenOutline.txt
#@+node:ekr.20090529141856.4692: *6* weave
#@+node:ekr.20090529141856.4693: *7* dialog
saveFileDialog
test\\unittest\\output\\weave.txt
#@+node:ekr.20090529141856.4694: *6* outlineToNoweb
#@+node:ekr.20090529141856.4695: *7* dialog
saveFileDialog
test\\unittest\\output\\outlineToNoweb.txt
#@+node:ekr.20090529141856.4696: *6* outlineToCWEB
#@+node:ekr.20090529141856.4697: *7* dialog
saveFileDialog
test\\unittest\\output\\outlineToCweb.txt
#@+node:ekr.20090529141856.4698: *4*  Import tests
#@+node:ekr.20090529141856.4699: *5* @suite Import tests
# Create unit tests in g.app.scriptDict["suite"]

import unittest
import leo.core.leoTest as leoTest

@others

suite = leoTest.makeImportExportSuite(c,"importTests",doImport=True)

g.app.scriptDict['suite'] = suite
#@+node:ekr.20090529141856.4700: *5* importTests
@language plain
#@+node:ekr.20090529141856.4701: *6* tempNode
#@+node:ekr.20090529141856.4702: *6* importAtRoot
#@+node:ekr.20090529141856.4703: *7* dialog
openFileDialog
test\\unittest\\perfectImport\\formatter.py
#@+node:ekr.20090529141856.4704: *6* importDerivedFile
#@+node:ekr.20090529141856.4705: *7* dialog
openFileDialog
core\\runLeo.py
#@+node:ekr.20090529141856.4706: *6* importNowebFiles
#@+node:ekr.20090529141856.4707: *7* dialog
openFileDialog
test\\unittest\\input\\noweave.nw.txt
#@+node:ekr.20090529141856.4708: *6* importFlattenedOutline
#@+node:ekr.20090529141856.4709: *7* dialog
openFileDialog
test\\unittest\\input\\flat.txt
#@+node:ekr.20090529141856.4710: *6* importCWEBFiles
#@+node:ekr.20090529141856.4711: *7* dialog
openFileDialog
test\\unittest\\input\\cweave.w
#@+node:ekr.20090529141856.4712: *6* removeSentinels
#@+node:ekr.20090529141856.4713: *7* dialog
openFileDialog
test\\unittest\\input\\testLeoAtFile.py
#@+node:ekr.20090529141856.4714: *6* importAtFile
#@+node:ekr.20090529141856.4715: *7* dialog
openFileDialog
test\\unittest\\perfectImport\\formatter.py
#@+node:ekr.20090529141856.4790: *4*  Test files
import leo.core.leoImport as leoImport
ic = c.importCommands
runner = leoImport.baseScannerClass(ic,atAuto=True,language='python')
i = 0
lines1 = ['abc',]
lines2 = ['xyz',]

g.app.unitTestDict ['expectedErrors'] = 1
g.app.unitTestDict ['expectedMismatchLine'] = 1

runner.compareHelper(lines1,lines2,i,strict=True)
#@+node:ekr.20090529141856.4716: *4*  Tests of @auto
@tabwidth -4
@language python
#@+node:ekr.20090529141856.4782: *5* @test checkTrialWrite
@first # -*- coding: utf-8 -*-

import leo.core.leoImport as leoImport
ic = c.importCommands
runner = leoImport.baseScannerClass(ic,atAuto=True,language='python')
runner.root = p.copy()

g.app.unitTestDict ['expectedMismatchLine'] = 1

s1 = g.toUnicode('line Ä, ڱ,  궯, 奠 end',encoding='utf-8')
s2 = g.toUnicode('line Ä, ڱ,  궯, 奠 x end',encoding='utf-8')

ok = runner.checkTrialWrite(s1=s1,s2=s2)

assert ok
#@+node:ekr.20090529141856.4783: *5* @test collapse-all
c.contractAllHeadlines()
#@+node:ekr.20090529141856.4717: *5* C tests
#@+node:ekr.20090529141856.4718: *6* @test c class 1
fileName = p.h

s = '''\
class cTestClass1 {

    int foo (int a) {
        a = 2 ;
    }

    char bar (float c) {
        ;
    }
}
'''

c.importCommands.cUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4719: *6* @test c class--underindented line
fileName = p.h

s = '''\
class cTestClass1 {

    int foo (int a) {
# an underindented line.
        a = 2 ;
    }

    # This should go with the next function.

    char bar (float c) {
        ;
    }
}
'''

g.app.unitTestDict ['expectedErrors'] = 1
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.cUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4720: *6* @test defaultImporter
fileName = p.h

s = '''\
class cTestClass1 {

    int foo (int a) {
        a = 2 ;
    }

    char bar (float c) {
        ;
    }
}
'''

c.importCommands.defaultImporterUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4721: *6* @test c test--comment follows arg list
fileName = p.h

s = '''\
void
aaa::bbb::doit
    (
    awk* b
    )
{
    assert(false);
}

bool
aaa::bbb::dothat
    (
    xyz *b
    ) //  <---------------------problem
{
    return true;
}
'''

c.importCommands.cUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4722: *6* @test c test--comment follows block delim
fileName = p.h

s = '''\
void
aaa::bbb::doit
    (
    awk* b
    )
{
    assert(false);
}

bool
aaa::bbb::dothat
    (
    xyz *b
    ) 
{
    return true;
} //  <---------------------problem
'''

c.importCommands.cUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4723: *6* @test c test--intermixed blanks and tabs
fileName = p.h

s = '''
void
aaa::bbb::doit
    (
    awk* b  // leading blank
    )
{
	assert(false); // leading tab
}

'''

g.app.unitTestDict ['expectedErrors'] = 0 # Intermixed blanks and tabs are ok for C.

c.importCommands.cUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4724: *6* @test c old-style decl 1
fileName = p.h

s = '''\
static void
ReleaseCharSet(cset)
    CharSet *cset;
{
    ckfree((char *)cset->chars);
    if (cset->ranges) {
    ckfree((char *)cset->ranges);
    }
}
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.cUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4725: *6* @test c old-style decl 2
fileName = p.h

s = '''\
Tcl_Obj *
Tcl_NewLongObj(longValue)
    register long longValue;	/* Long integer used to initialize the
         * new object. */
{
    return Tcl_DbNewLongObj(longValue, "unknown", 0);
}
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.cUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4726: *6* @test c extern
fileName = p.h

s = '''\
extern  "C"
{
#include "stuff.h"
void    init(void);
#include "that.h"
}
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.cUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4727: *5* c# tests
#@+node:ekr.20090529141856.4728: *6* @test c# namespace indent
s = '''\
namespace {
    class cTestClass1 {
        ;
    }
}
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.cSharpUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4729: *6* @test c# namespace no indent
s = '''\
namespace {
class cTestClass1 {
    ;
}
}
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.cSharpUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4730: *6* @@test c# ref card
import sys

if sys.platform.lower().startswith('win'):

    fileName = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..','test','big-c#-test.c#'))

    f = open(fileName)
    s = f.read()
    f.close()

    c.importCommands.cSharpUnitTest(p,s=s,fileName=fileName,showTree=False)
#@+node:ekr.20090529141856.4731: *5* elisp tests
#@+node:ekr.20090529141856.4732: *6* @test elisp functions
s = '''\
;;; a.el --- Test

;; some other verbose comment
;; some other verbose comment
;; some other verbose comment

(defun abc (a1 a2)
  "Return blah blah."
  (+ 1 2))

(defun fgh (a1 a2)
  "Return blah blah."
  (- 1 2))

;;; a.el ends here
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.elispUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4733: *6* @test elisp 2
s = '''\
;;; comment
;;; continue
;;;

(defun abc (a b)
   (+ 1 2 3))

; comm
(defun cde (a b)
   (+ 1 2 3))
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.elispUnitTest(p,s=s,showTree=False)
#@+node:ekr.20100803234640.5804: *5* ini tests
#@+node:ekr.20100803234640.5805: *6* @test ini-test-1
s = '''\
; last modified 1 April 2001 by John Doe
[owner]
name=John Doe
organization=Acme Widgets Inc.

[database]
server=192.0.2.62     ; use IP address in case network name resolution is not working
port=143
file = "payroll.dat"
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.iniUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4766: *5* Java tests
#@+node:ekr.20090529141856.4767: *6* @test java interface test1
s = '''\
interface Bicycle {
    void changeCadence(int newValue);
    void changeGear(int newValue);
}
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.javaUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4768: *6* @test java interface test2
s = '''\
interface Bicycle {
void changeCadence(int newValue);
void changeGear(int newValue);
}
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.javaUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4769: *6* @@test constants.java
import sys

if sys.platform.lower().startswith('win'):

    fileName = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..','test','constants.java'))

    f = open(fileName)
    s = f.read()
    f.close()

    c.importCommands.javaUnitTest(p,s=None,fileName=fileName,showTree=False)
#@+node:ekr.20090529141856.4770: *6* @test from AdminPermission.java
s = '''\
/**
 * Indicates the caller's authority to perform lifecycle operations on
 */

public final class AdminPermission extends BasicPermission
{
    /**
     * Creates a new <tt>AdminPermission</tt> object.
     */
    public AdminPermission()
    {
        super("AdminPermission");
    }
}
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.javaUnitTest(p,s=s,showTree=False)

#@+node:ekr.20090529141856.4771: *6* @@test AdminPermission.java
import sys

if sys.platform.lower().startswith('win'):


    fileName = g.os_path_abspath(g.os_path_join(g.app.loadDir,'..','test','AdminPermission.java'))

    f = open(fileName)
    s = f.read()
    f.close()

    c.importCommands.javaUnitTest(p,s=s,fileName=fileName,showTree=False)
#@+node:ekr.20090529141856.4772: *6* Test BundleException.java
@tabwidth 8
#@+node:ekr.20090529141856.4773: *7* @test from BundleException.java
@language python

s = '''\
/*
 * $Header: /cvs/leo/test/unitTest.leo,v 1.247 2008/02/14 14:59:04 edream Exp $
 * 
 * Copyright (c) OSGi Alliance (2000, 2005). All Rights Reserved.
 * 
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this 
 * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html.
 */

package org.osgi.framework;

/**
 * A Framework exception used to indicate that a bundle lifecycle problem
 * occurred.
 * 
 * <p>
 * <code>BundleException</code> object is created by the Framework to denote
 * an exception condition in the lifecycle of a bundle.
 * <code>BundleException</code>s should not be created by bundle developers.
 * 
 * <p>
 * This exception is updated to conform to the general purpose exception
 * chaining mechanism.
 * 
 * @version $Revision: 1.247 $
 */

public class BundleException extends Exception {
	static final long	serialVersionUID	= 3571095144220455665L;
	/**
	 * Nested exception.
	 */
	private Throwable	cause;

	/**
	 * Creates a <code>BundleException</code> that wraps another exception.
	 * 
	 * @param msg The associated message.
	 * @param cause The cause of this exception.
	 */
	public BundleException(String msg, Throwable cause) {
		super(msg);
		this.cause = cause;
	}
}

'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.javaUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4774: *5* Javascript tests
#@+node:ekr.20090529141856.4775: *6* Problems
@language javascript

// regexps that look like section references.

{
	name: "macro",
	match: "<<",
	lookaheadRegExp: /<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[1]) {
			w.nextMatch = this.lookaheadRegExp.lastIndex;
			invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler);
		}
	}
},

// Comments that look like section references.

// <<gradient [[tiddler name]] vert|horiz rgb rgb rgb rgb... >>

config.macros.gradient.handler = function(place,macroName,params,wikifier)
{
	var panel = wikifier ? createTiddlyElement(place,"div",null,"gradient") : place;
	panel.style.position = "relative";
	panel.style.overflow = "hidden";
	panel.style.zIndex = "0";
	if(wikifier) {
		var styles = config.formatterHelpers.inlineCssHelper(wikifier);
		config.formatterHelpers.applyCssHelper(panel,styles);
	}
	var colours = [];
	for(var t=1; t<params.length; t++) {
		var c = new RGB(params[t]);
		if(c)
			colours.push(c);
	}
	drawGradient(panel,params[0] != "vert",colours);
	if(wikifier)
		wikifier.subWikify(panel,">>");
	if(document.all) {
		panel.style.height = "100%";
		panel.style.width = "100%";
	}
};

// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
	createTiddlyElement(place,"br");
};
#@+node:ekr.20090529141856.4776: *6* @test Javascript-regex-1
s = '''\

String.prototype.toJSONString = function()
{
    if(/["\\\\\\x00-\\x1f]/.test(this))
		return '"' + this.replace(/([\\x00-\\x1f\\"])/g,replaceFn) + '"';

	return '"' + this + '"';
};

'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.javaScriptUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4777: *6* @test Javascript-2
    s = '''\

// Convert a string to it's JSON representation by encoding control characters, double quotes and backslash. See json.org
String.prototype.toJSONString = function()
{
	var m = {
		'\\b': '\\\\b',
		'\\f': '\\\\f',
		'\\n': '\\\\n',
		'\\r': '\\\\r',
		'\\t': '\\\\t',
		'"' : '\\\\"',
		'\\\\': '\\\\\\\\'
		};
	var replaceFn = function(a,b) {
		var c = m[b];
		if(c)
			return c;
		c = b.charCodeAt();
		return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
		};
    if(/["\\\\\\x00-\\x1f]/.test(this))
		return '"' + this.replace(/([\\x00-\\x1f\\"])/g,replaceFn) + '"';

	return '"' + this + '"';
};

'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.javaScriptUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4778: *6* @test Javascript-3
s = '''\

// Restarting
function restart()
{
	invokeParamifier(params,"onstart");
	if(story.isEmpty()) {
		var tiddlers = store.filterTiddlers(store.getTiddlerText("DefaultTiddlers"));
		for(var t=0; t<tiddlers.length; t++) {
			story.displayTiddler("bottom",tiddlers[t].title);
		}
	}
	window.scrollTo(0,0);
}

'''

# Double each backslash (they are in a docstring).
# chars = [z for z in s]
# s = []
# for z in char:
    # if z == '\\': s.append('\\\\')
    # else: s.append(z)
# s = s.join('')

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.javaScriptUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4779: *6* @@test javascript-test-js
f = open('test.js')
s = f.read()
f.close()

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.javaScriptUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4734: *5* Pascal tests
#@+node:ekr.20090529141856.4735: *6* @test pascal-to-delphi interface
s = '''
unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls,
Forms,
Dialogs;

type
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
var
x,y: double;
begin
x:= 4;
Y := x/2;
end;

end.
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pascalUnitTest(p,s=s,showTree=False)
#@+node:ekr.20100219080213.5365: *5* PHP tests
#@+node:ekr.20100219080213.5366: *6* @test php import class
s = '''\
<?php

$type = 'cc';
$obj = new $type; // outputs "hi!"

class cc {
    function __construct() {
        echo 'hi!';
    }
}

?>

'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.phpUnitTest(p,s=s,showTree=False)
#@+node:ekr.20100219080213.5367: *6* @test php import conditional class
s = '''\
<?php

if (expr) {
    class cc {
        // version 1
    }
} else {
    class cc {
        // version 2
    }
}

?>
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.phpUnitTest(p,s=s,showTree=False)
#@+node:ekr.20100219080213.5368: *6* @test php import classes & functions
s = '''\
<?php
class Enum {
    protected $self = array();
    public function __construct( /*...*/ ) {
        $args = func_get_args();
        for( $i=0, $n=count($args); $i<$n; $i++ )
            $this->add($args[$i]);
    }

    public function __get( /*string*/ $name = null ) {
        return $this->self[$name];
    }

    public function add( /*string*/ $name = null, /*int*/ $enum = null ) {
        if( isset($enum) )
            $this->self[$name] = $enum;
        else
            $this->self[$name] = end($this->self) + 1;
    }
}

class DefinedEnum extends Enum {
    public function __construct( /*array*/ $itms ) {
        foreach( $itms as $name => $enum )
            $this->add($name, $enum);
    }
}

class FlagsEnum extends Enum {
    public function __construct( /*...*/ ) {
        $args = func_get_args();
        for( $i=0, $n=count($args), $f=0x1; $i<$n; $i++, $f *= 0x2 )
            $this->add($args[$i], $f);
    }
}
?>

'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.phpUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4736: *5* Python tests
# Warning: setting atAuto=True can wipe out unit tests.
#@+node:ekr.20090529141856.4737: *6* @@test nested class
s = '''\
NS = { 'i': 'http://www.inkscape.org/namespaces/inkscape',
      's': 'http://www.w3.org/2000/svg',
      'xlink' : 'http://www.w3.org/1999/xlink'}

tabLevels = 4  # number of defined tablevels, FIXME, could derive from template?
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4738: *6* @test comment after dict assign
s = '''\
NS = { 'i': 'http://www.inkscape.org/namespaces/inkscape',
      's': 'http://www.w3.org/2000/svg',
      'xlink' : 'http://www.w3.org/1999/xlink'}

tabLevels = 4  # number of defined tablevels, FIXME, could derive from template?
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4739: *6* @test decorator test
s = '''\
class Index:
    """docstring"""
    @cherrypy.nocolor
    @cherrypy.expose
    def index(self):
        return "Hello world!"
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4740: *6* @test def inside def
s = '''\
class aClass:
    def outerDef(self):
        """docstring.
        line two."""

        def pr(*args,**keys):
            g.es_print(color='blue',*args,**keys)

        a = 3
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4741: *6* @test docstring only
s = '''\
"""A file consisting only of a docstring.
"""
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4742: *6* @test overindent def--no following def
s = '''\
class aClass:
    def def1(self):
        pass

    if False or g.unitTesting:

        def pr(*args,**keys): # reportMismatch test
            g.es_print(color='blue',*args,**keys)

        pr('input...')
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4743: *6* @test overindent def--one following def
s = '''\
class aClass:
    def def1(self):
        pass

    if False or g.unitTesting:

        def pr(*args,**keys): # reportMismatch test
            g.es_print(color='blue',*args,**keys)

        pr('input...')

    def def2(self):
        pass
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4744: *6* @test overindented def 3
@language python

# This caused PyParse.py not to be imported properly.

s = '''\

import re

if 0: # Causes the 'overindent'
   if 0:   # for throwaway debugging output
      def dump(*stuff):
        sys.__stdout__.write(" ".join(map(str, stuff)) + "\n")

for ch in "({[":
   _tran[ord(ch)] = '('

class testClass1:
    pass
# '''

c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4745: *6* @test python bad class test
s = '''\
class testClass1 # no colon
    pass

def spam():
    pass
'''

g.app.unitTestDict ['expectedErrors'] = 0 # Not really an error.

c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20101101034131.6042: *6* @test python bug 603720
# Leo bug 603720
# Within the docstring we must change '\' to '\\'
s = '''\
def foo():
    s = \\
"""#!/bin/bash
cd /tmp
ls"""
    file('/tmp/script', 'w').write(s)

class bar:
    pass

foo()
'''

showTree = False

tree = c.importCommands.pythonUnitTest(p,s=s,showTree=showTree)

if showTree:
    c.redraw_now()
    foo = g.findNodeInTree(c,p,'foo')
    assert foo
    s = "file('/tmp/script', 'w').write(s)"
    print('foo.b',repr(foo.b))
    assert foo.b.find(s) > -1,"foo.b: %s" % foo.b
#@+node:ekr.20090529141856.4746: *6* @test python class test 2
s = '''\
class testClass2:
    pass
'''

tree = c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4747: *6* @test python class tests 1
s = '''\
class testClass1:
    """A docstring"""
    def __init__ (self):
        pass
    def f1(self):
        pass
'''

c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4748: *6* @test python decls test 1
s = '''\
import leo.core.leoGlobals as g

a = 3
'''

c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4749: *6* @test python def test 1
s = '''\

class test:

    def importFilesCommand (self,files=None,treeType=None,
        perfectImport=True,testing=False,verbose=False):
            # Not a command.  It must *not* have an event arg.

        c = self.c
        if c == None: return
        p = c.currentPosition()

    # Used by paste logic.

    def convertMoreStringToOutlineAfter (self,s,firstVnode):
        s = string.replace(s,"\\r","")
        strings = string.split(s,"\\n")
        return self.convertMoreStringsToOutlineAfter(strings,firstVnode)
'''

c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4750: *6* @test python def test 2
s = '''\

class test:
    def spam(b):
        pass

    # Used by paste logic.

    def foo(a):
        pass
'''

c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4751: *6* @test python empty decls
s = '''\
import leo.core.leoGlobals as g

a = 3
'''

c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4752: *6* @test python extra leading ws test
s = '''\

class cls:
     def fun(): # one extra space.
        pass
'''

g.app.unitTestDict ['expectedErrors'] = None # No error unless we get an unexpected mismatch line.
g.app.unitTestDict ['expectedMismatchLine'] = 3 # The error happens before any lines are checked.
g.app.unitTestDict ['expectedErrorMessage'] = 'leading whitespace not consistent with @tabwidth -4'

c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4753: *6* @test python indent decls
s = '''\

class mammalProviderBase(object):
    """Root class for content providers used by DWEtree.py"""
    def __init__(self, params):
        """store reference to parameters"""
        self.params = params
    def provide(self, what):
        """default <BASE> value"""
        if what == 'doctitle':
            return ELE('base', href=self.params['/BASE/'])
        return None

    def imagePath(self, sppdat):
        """return path to images and list of images for *species*"""
        path = 'MNMammals/imglib/Mammalia'
        for i in 'Order', 'Family', 'Genus', 'Species':
            path = os.path.join(path, sppdat['%sName' % (i,)])
        imglib = os.path.join('/var/www',path)
        imglib = os.path.join(imglib, '*.[Jj][Pp][Gg]')
        path = os.path.join('/',path)
        lst = [os.path.split(i)[1] for i in glob.glob(imglib)]
        lst.sort()
        return path, lst

class mainPages(mammalProviderBase):
    """provide content for pages in 'main' folder"""
    __parent = mammalProviderBase
    def provide(self, what):
        """add one layer to <BASE>"""
        ans = self.__parent.provide(self, what)
        if what == 'doctitle':
            return ELE('base', href=self.params['/BASE/']+'main/')
        return ans
''' 

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4754: *6* @test python minimal class 1
s = '''\

class ItasException(Exception):

    pass

def gpRun(gp, cmd, args, log = None):

    """Wrapper for making calls to the geoprocessor and reporting errors"""

    if log:

        log('gp: %s: %s\\n' % (cmd, str(args)))
'''

c.importCommands.pythonUnitTest(p,s=s,showTree=False)


#@+node:ekr.20090529141856.4755: *6* @test python minimal class 2
s = '''\

class emptyClass: pass

def followingDef():
    pass
'''

c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4756: *6* @test python minimal class 3
s = '''\

class emptyClass: pass # comment

def followingDef(): # comment
    pass
'''

c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4757: *6* @test python underindent method
s = '''\

class emptyClass: 

    def spam():

        """docstring line 1
under-indented docstring line"""
        pass

def followingDef(): # comment
    pass
'''

c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4758: *6* @test scanPythonText: leoImportNosent.py
@encoding utf-8
# leoImport.py uses unicode characters, so *this* test must have the directive above.

fileName = g.os_path_abspath(g.os_path_join(g.app.loadDir,'leoImport.py'))

f = open(fileName)
s = f.read()
f.close()

g.app.unitTestDict['testingLeoImport.py'] = True

c.importCommands.pythonUnitTest(p,s=None,fileName=fileName,showTree=False)
#@+node:ekr.20090529141856.4759: *6* @test string test: extra indent
s = '''\
class baseScannerClass:

        """The base class for all import scanner classes."""

        def __init__ (self,importCommands,language):

            self.c = ic.c

        def createHeadline (self,parent,body,headline):
            # g.trace("parent,headline:",parent,headline)
            return p
'''

# We expect mismatches because the indentation does not match @tabwidth -4.
g.app.unitTestDict ['expectedErrors'] = None # No error unless we get an unexpected mismatch line.
g.app.unitTestDict ['expectedMismatchLine'] = 3
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4760: *6* @test string underindent lines
s = '''\
class baseScannerClass:
    def containsUnderindentedComment(self):
        a = 2
    # A true underindented comment.
        b = 3
    # This underindented comment should be placed with next function.
    def empty(self):
        pass
'''

g.app.unitTestDict ['expectedErrors'] = 0 # underindented comments are no longer an error.
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4761: *6* @test string underindent lines 2
s = '''\
class baseScannerClass:
    def containsUnderindentedComment(self):
        a = 2
    #
        b = 3
        # This comment is part of the present function.

    def empty(self):
        pass
'''

g.app.unitTestDict ['expectedErrors'] = 0 # underindented comments are no longer an error.
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4762: *6* @test trailing comment
s = '''\
class aClass: # trailing comment


    def def1(self):             # trailing comment
        pass
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4763: *6* @test trailing comment--outer levels
s = '''\

xyz = 6 # trailing comment
pass
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4764: *6* @test two functions (for comparison with unindent does not end function)
s = '''\

def foo():
    pass

def bar():
    pass
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4765: *6* @test unindent in triple string does not end function
s = '''\

def foo():

    error("""line1
line2.
""")

    a = 5

def bar():
    pass
'''

showTree = False
keepTree = False

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.pythonUnitTest(p,s=s,showTree=showTree)

if showTree:
    try:
        child = p.firstChild()
        n = child.numberOfChildren()
        assert n == 2, 'expected 2 children, got %s' % n
    finally:
        if keepTree:
            h = child.h
            print('h',h)
            child.setHeadString('@'+h)
        else:
            while p.hasChildren():
                p.firstChild().doDelete()
        c.redraw(p)
#@+node:ekr.20090529141856.4780: *5* xml tests
#@+node:ekr.20090529141856.4781: *6* @test xml 1
s = '''\
<html>
<head>
    <title>Bodystring</title>
</head>
<body class='bodystring'>
<div id='bodydisplay'></div>
</body>
</html>
'''

g.app.unitTestDict ['expectedErrors'] = 0

c.importCommands.xmlUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4784: *4*  Tests of @auto-rst
#@+node:ekr.20090529141856.4785: *5* @test rST import test
s = '''\
.. toc

====
top
====

The top section

section 1
---------

section 1, line 1
--
selction 1, line 2

section 2
---------

section 2, line 1

section 2.1
~~~~~~~~~~~

section 2.1, line 1

section 2.1.1
.............

section 2.2.1 line 1

section 3
---------

section 3, line 1

section 3.1.1
.............

section 3.1.1, line 1
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.rstUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4786: *5* @test rST import test (no double-underlines)
s = '''\
.. toc

top
====

The top section

section 1
---------

section 1, line 1
--
selction 1, line 2

section 2
---------

section 2, line 1

section 2.1
~~~~~~~~~~~

section 2.1, line 1

section 2.1.1
.............

section 2.2.1 line 1

section 3
---------

section 3, line 1

section 3.1.1
.............

section 3.1.1, line 1
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.rstUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4787: *5* @test rST import test: long underlines
s = '''\
.. toc

top
-------------

The top section
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.rstUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4788: *5* @test rST import test: long overlines
s = '''\
.. toc

======
top
======

The top section
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.rstUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4789: *5* @test rST import test: trailing whitespace
s = '''\
.. toc

.. The section name contains trailing whitespace.

======
top 
======

The top section.
'''

g.app.unitTestDict ['expectedErrors'] = None
g.app.unitTestDict ['expectedMismatchLine'] = None
c.importCommands.rstUnitTest(p,s=s,showTree=False)
#@+node:ekr.20090529141856.4793: *4* @@test test imports for modes
d = g.app.extra_extension_dict

for ext in g.app.extension_dict.keys():
    language =  c.importCommands.languageForExtension(ext)
    language2 = c.importCommands.languageForExtension('.'+ext)
    assert language == language2

    # Now a many-one relationship.
    if language:
        # Do not test extensions that have 'none' as the value of d.get(ext)
        # Otherwise, test only d.get(ext).
        language2 = d.get(ext)
        if language2 in ('None','none'):  continue
        if language2: language = language2
        # Made-up languages do not have mode files.
        if not language.endswith('_language') and language not in ('autohotkey','rest',):
            path = g.os_path_join(g.app.loadDir,'..','modes','%s.py' % (language))
            assert g.os_path_exists(path), 'for ext=%s does not exist: %s' % (ext,path)

    if 0:
        if language is None:
            print('no language for ext=%s' % (ext))
#@+node:ekr.20100131180007.5393: *4* @test reportMismatch
import leo.core.leoImport as leoImport

ic = c.importCommands
scanner = leoImport.rstScanner(importCommands=ic,atAuto=True)
scanner.root = p
s1 = ["abc",]
s2 = ["xyz",]

scanner.reportMismatch(s1,s2,1)

# Why is leoSettings.leo scanned twice in dynamicUnitTest.leo?
#@+node:ekr.20090529141856.4792: *4* Load tests for .leo files
s = '''\
    a
\tb
'''

import leo.core.leoImport as leoImport
ic = c.importCommands
runner = leoImport.pythonScanner(c.importCommands,atAuto=False)
runner.tab_width = -4
runner.regularizeWhitespace(s)
assert runner.errors == 1
#@+node:ekr.20090529141856.4791: *4* Other tests
import leo.core.leoImport as leoImport
ic = c.importCommands
runner = leoImport.baseScannerClass(ic,atAuto=True,language='java')
runner.tab_width = -4
i = 0
lines1 = ['abc',]
lines2 = [' abc',]

# g.unitTesting = False # force the warning.

g.app.unitTestDict ['expectedErrors'] = 0
g.app.unitTestDict ['expectedMismatchLine'] = 1

runner.compareHelper(lines1,lines2,i,strict=False)
#@+node:ekr.20100131171342.5604: *3* leoKeys
#@+node:ekr.20100131171342.5606: *4* @@test k.autoCompleterClass.calltip
# This test is difficult to get right on all platforms.
# It's not worth doing.

try:
    k = c.k
    w = c.frame.body.bodyCtrl
    ac = k.autoCompleter
    # Set the insertion point.
    s = w.getAllText()
    w.setInsertPoint(len(s)-1)
    # Just test that this doesn't crash.
    ac.w = w
    ac.calltip()
finally:
    w.setAllText(s)
    p.setBodyString(s)
    c.recolor()

# c.frame
#@+node:ekr.20110509104953.3474: *4* @test k.get_leo_completions
table = (
    ( 50,'c.'),
    (  3,'p.ins'),
    ( 12,'g.com'),
)

ac = c.k.autoCompleter
ac.w = c.frame.body.bodyCtrl

for expected,prefix in table:
    
    aList = ac.get_leo_completions(prefix)
    assert len(aList) >= expected,'len(aList): %s, prefix: %s' % (len(aList),prefix)
    
    if 0:
        print()
        for z in aList:
            print(z)
#@+node:ekr.20100131171342.5605: *4* @test k.isPlainKey
import string

k = c.k

for ch in (string.printable):
    if ch == '\n': continue # A special case.
    assert k.isPlainKey(ch), 'wrong: not plain: %s' % (ch)

special = (
    'Return', # A special case.
    'Begin','Break','Caps_Lock','Clear','Down','End','Escape',
    'F1','F2','F3','F4','F5','F6','F7','F8','F9','F10','F11','F12',
    'KP_Add', 'KP_Decimal', 'KP_Divide', 'KP_Enter', 'KP_Equal',
    'KP_Multiply, KP_Separator,KP_Space, KP_Subtract, KP_Tab',
    'KP_F1','KP_F2','KP_F3','KP_F4',
    'KP_0','KP_1','KP_2','KP_3','KP_4','KP_5','KP_6','KP_7','KP_8','KP_9',
    'Home','Left','Linefeed','Next','Num_Lock',
    'PageDn','PageUp','Pause','Prior','Right','Up',
    'Sys_Req',
)

for ch in special:
    assert not k.isPlainKey(ch), 'wrong: is plain: %s' % (ch)
#@+node:ekr.20100212110954.5359: *4* @test k.print-bindings
lines = c.k.printBindings()
# assert lines[0].strip().endswith('Alt+Ctrl+Shift')
#@+node:ekr.20100131171342.5607: *4* @test k.registerCommand
import leo.core.leoTest as leoTest ; u = leoTest.testUtils(c)
k = c.k ; p = c.p ; w = c.edit_widget(p)
commandName = 'test-registerCommand'

def callback (event=None,c=c): # Must have an event param to pass later unit test.
    g.app.unitTestDict[commandName] = True

# Test 1
g.app.unitTestDict[commandName] = False
k.registerCommand(commandName,'Alt-Ctrl-Shift-z',callback,pane='all',verbose=True)
k.simulateCommand(commandName)
assert g.app.unitTestDict.get(commandName)

if 0: # Test 2
    g.app.unitTestDict[commandName] = False
    k.manufactureKeyPressForCommandName(w,commandName)
    assert g.app.unitTestDict.get(commandName)
#@+node:ekr.20100131171342.5608: *4* @test k.strokeFromSetting
# print('settingsNameDict',c.k.settingsNameDict)

table = (
    ('a','a'),
    ('A','a'),
    ('Alt-a','Alt+a'),
    ('Alt-A','Alt+a'),
    ('Alt-Shift-a','Alt+A'),
    ('Alt-=','Alt+equal'),
    ('Alt-+','Alt+plus'),
    # We can no longer igtnore the shift.
    # ('Alt-Shift++','Alt+plus'), # Ignore the shift.
    ('Alt--','Alt+minus'),
    ('Shift-a','A'),
    ('Shift-A','A'),
    ('RtArrow','Right'),
    ('Shift-RtArrow','Shift+Right'),
    ('Ctrl-RtArrow','Ctrl+Right'),
    ('Control-Right','Ctrl+Right'),
    ('PageUp','Prior'), ('Prior','Prior'),('Shift-PageUp','Shift+Prior'),
    ('PageDn','Next'),('Next','Next'),('Shift-Next','Shift+Next'),
)
for setting, result in table:
    val = c.k.strokeFromSetting(setting)
    assert val==result,'Expected %s, Got %s' % (result,val)
#@+node:ekr.20100131171342.5609: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

# print('\nEnd of leoKeys tests.')
#@+node:ekr.20071113194424.1: *3* leoNodes
# 4 failures with Alt-5
#@+node:ekr.20040712101754.181: *4*  inner @test: Test consistency between parents iter and v.parents
# The actual test is in a child node.
#@+node:ekr.20040712101754.182: *5* parent
#@+node:ekr.20040712101754.183: *6* @test consistency between parents_iter and v.parents
try:
    for p in c.all_positions():
        if 0: # Check all ancestors.  This is tricky and doesn't work yet.
            parents1 = [parent.v for parent in p.parents_iter()]
            parents2 = []
            parent2 = p.v.directParents()
            while parent2:
                v = parent2[0]
                parents2.append(v)
                parent2 = v.directParents()
        else:
            parents1 = p.v.parents
            parents2 = p.v.directParents()

        assert len(parents1) == len(parents2), "length mismatch: %s" % (p)
        for parent in parents1:
            assert parent in parents2, "%s not in %s" % (parent,parent1)
        for parent in parents2:
            assert parent in parents1, "%s not in %s" % (parent,parent2)

except AssertionError:
    print("parents1")
    for parent in parents1: print(parent)
    print("parents2")
    for parent in parents2: print(parent)
    raise
#@+node:ekr.20040712101754.175: *4* @@test p.t == p.v
# p.__getattr__ must be enabled for this test to work.

for p in c.all_positions():
    assert(p.t == p.v)
#@+node:ekr.20040712101754.200: *4* @@test that clones share subtrees
for p in c.all_positions():
    if p.isCloned() and p.hasChildren():
        childv = p.firstChild().v
        firstChild = p.v.children[0]
        assert childv == firstChild
#@+node:ekr.20070611071101: *4* @@test visback
p1 = p.copy()
a = p.firstChild()
b = a.firstChild()
c2 = b.firstChild()
limit = a.next()
d = limit.firstChild()
e = limit.next()
assert e.h == 'e'
for p2,h in ((a,'a'),(b,'b'),(c2,'c2'),(d,'d'),(limit,'limit')):
    p2.expand()
    assert p2.h==h,'headString mismatch'

try: # Tests without hoist...
    p1.expand()
    assert not c.hoistStack
    c.selectPosition(limit)
    result = limit.copy().moveToVisBack(c)
    assert result==c2,'visBack != c2: %s' % result
    #
    result = limit.copy().moveToVisNext(c)
    assert result==d,'visNext != d: %s' % result
finally:
    p1.contract()

try: # Tests with hoist.
    p1.expand()
    c.selectPosition(limit)
    c.hoist()
    result = limit.copy().moveToVisBack(c)
    assert not result,'limited visBack: %s' % result
    #
    result = limit.copy().moveToVisNext(c)
    assert result==d,'limited visNext !=d: %s' % result
finally:
    c.dehoist()
    c.selectPosition(p1)
    p1.contract()
    c.redraw_now()

#@+node:ekr.20070611071101.1: *5* a
#@+node:ekr.20070611071101.2: *6* b
#@+node:ekr.20070611071101.3: *7* c2
#@+node:ekr.20070611071101.4: *5* limit
#@+node:ekr.20070611071101.5: *6* d
#@+node:ekr.20070611071954: *5* e
#@+node:ekr.20040712101754.99: *4* @test c iters
<< coverage tests >>
<< duplicate tests >>

if 0:
    print("vnodes",len([v for v in c.all_vnodes_iter()]),len([v for v in c.all_unique_vnodes_iter()]))
    print("tnodes",len([t for t in c.all_tnodes_iter()]),len([t for t in c.all_unique_tnodes_iter()]))

if 0: # all nodes
    for v in c.all_vnodes_iter(): print(v)
    for t in c.all_tnodes_iter(): print(t)

if 0: # unique nodes
    for v in c.all_unique_vnodes_iter(): print(v)
    for t in c.all_unique_tnodes_iter(): print(t)
#@+node:ekr.20040712101754.100: *5* << coverage tests >>
v1 = [p.v for p in c.all_positions()]
v2 = [v for v in c.all_nodes()]
for v in v2: assert(v in v1)
for v in v1: assert(v in v2)

# print("coverage tests pass")
#@+node:ekr.20040712101754.101: *5* << duplicate tests >>
nodes = []
for v in c.all_unique_nodes():
    assert v not in nodes
    nodes.append(v)

# print("duplicate tests pass")
#@+node:ekr.20090102061858.2: *4* @test c.positionExists
child = p.insertAsLastChild()
assert c.positionExists(child)
child.doDelete()
assert not c.positionExists(child)

# also check the same on root level
child = c.rootPosition().insertAfter()
assert c.positionExists(child)
child.doDelete()
assert not c.positionExists(child)
#@+node:ekr.20090102062037.2: *4* @test c.positionExists for all nodes
root = c.rootPosition()

for p in c.all_positions():
    assert c.positionExists(p,root)
#@+node:ekr.20040712101754.204: *4* @test consistency of back/next links
for p in c.all_positions():

    back = p.back()
    next = p.next()
    if back: assert(back.getNext() == p)
    if next: assert(next.getBack() == p)
#@+node:ekr.20040712101754.201: *4* @test consistency of c.all_positions() and p.ThreadNext()
p2 = c.rootPosition()
for p in c.all_positions():
    assert p==p2, "%s != %s" % (p,p2)
    p2.moveToThreadNext()

assert not p2, repr(p2)
#@+node:ekr.20040712101754.202: *4* @test consistency of firstChild & children_iter()
for p in c.all_positions():
    p2 = p.firstChild()
    for p3 in p.children_iter():
        assert p3==p2, "%s != %s" % (p3,p2)
        p2.moveToNext()

assert not p2, repr(p2)
#@+node:ekr.20040712101754.203: *4* @test consistency of level
for p in c.all_positions():

    if p.hasParent():
        assert(p.parent().level() == p.level() - 1)

    if p.hasChildren():
        assert(p.firstChild().level() == p.level() + 1)

    if p.hasNext():
        assert(p.next().level() == p.level())

    if p.hasBack():
        assert(p.back().level() == p.level())
#@+node:ekr.20040712101754.205: *4* @test consistency of parent & parents_iter()
for p in c.all_positions():
    p2 = p.parent()
    for p3 in p.parents_iter():
        assert p3==p2, "%s != %s" % (p3,p2)
        p2.moveToParent()

    assert not p2, repr(p2)
#@+node:ekr.20040712101754.206: *4* @test consistency of parent/child links
# Test consistency of p.parent, p.next, p.back and p.firstChild.
for p in c.all_positions():

    if p.hasParent():
        n = p.childIndex()
        assert(p == p.parent().moveToNthChild(n))

    for child in p.children_iter():
        assert(p == child.parent())

    if p.hasNext():
        assert(p.next().parent() == p.parent())

    if p.hasBack():
        assert(p.back().parent() == p.parent())
#@+node:ekr.20040712101754.207: *4* @test consistency of threadBack/Next links
for p in c.all_positions():

    threadBack = p.threadBack()
    threadNext = p.threadNext()

    if threadBack:
        assert(p == threadBack.getThreadNext())

    if threadNext:
        assert(p == threadNext.getThreadBack())
#@+node:ekr.20040712101754.177: *4* @test convertTreeToString and allies
p = p.firstChild()
assert(p.h=="File Conversion")
p.convertTreeToString()
#@+node:ekr.20040712101754.178: *5* File Conversion
@
- convertTreeToString and moreHead can't be vnode methods because they uses level().
- moreBody could be anywhere: it may as well be a postion method.
#@+node:ekr.20040712101754.179: *6* moreHead
def moreHead (self, firstLevel,useVerticalBar=False):

    """Return the headline string in MORE format."""

    p = self

    level = self.level() - firstLevel
    plusMinus = g.choose(p.hasChildren(), "+", "-")

    return "%s%s %s" % ('\t'*level,plusMinus,p.h)
#@+node:ekr.20040712101754.180: *6* moreBody
@ 
    + test line
    - test line
    \ test line
    test line +
    test line -
    test line \
    More lines...
@c

def moreBody (self):

    """Returns the body string in MORE format.  

    Inserts a backslash before any leading plus, minus or backslash."""

    p = self ; list = []

    # Only escape the first non-blank character of the line.
    s =  p.b ; result = []
    lines = string.split(s,'\n')
    for s in lines:
        i = g.skip_ws(s,0)
        if i < len(s):
            ch = s[i]
            if ch == '+' or ch == '-' or ch == '\\':
                s = s[:i] + '\\' + s[i:]
        result.append(s)
    return string.join(result,'\n')
#@+node:ville.20090312195309.2: *4* @test find_h / find_b / filter_h / filter_b
#if this starts failing due to much refacting in unitTest.leo,
# adjust accordingly

# These seem to fail if various nodes are cloned.
import random,fnmatch

all_h = [z.copy().h for z in c.find_h('.')]

assert len(all_h) > 1000,'fail 1'

sample = random.sample(all_h, 20)    

# Test that all nodes are found at least once.
for h in sample:
    pat = fnmatch.translate(h)
    pl = c.find_h(pat)
    assert len(pl) > 0 and len(pl) < len(all_h),'fail 2'

tests = c.find_h('@test(.*)')

bm = tests.filter_b('(.*)all_positions')
forloops = 0
for node in bm:   
    # many of these are for loops
    for m in node.matchiter:
        if 'for' in m.group(1):
            forloops += 1

assert forloops > 10,'fail for'

# all of these should also be found by find_b
all_bm = c.find_b('(.*)all_positions')
assert len(all_bm) >= len(bm),'fail len'

assert set(el.h for el in bm).issubset(set(el.h for el in all_bm)),'fail set'

itertest = c.find_h('@test p.iters and v.iters')
assert len(itertest) >= 1,'fail 3'
tn = itertest[0]
assert tn.h == '@test p.iters and v.iters','fail h'
assert len(itertest.filter_b('notfound, really')) == 0,'fail 4'
assert len(itertest.filter_b('leoNodes')) == 1,'fail 5'
chi = itertest.children().filter_h('child?')
assert chi[0].h == 'child1','fail 6'
assert chi[1].h == 'child2','fail 7'
# twice, in clones
chi_b = chi.children().filter_h('a').children().filter_h('b')

if 0:
    assert len(chi_b) == 2,'fail len 2: %s: %s' % (chi_b,len(chi_b))
    assert chi_b[0].h == chi_b[1].h == 'b'
    chi_e = chi.children().filter_h('d').children().filter_h('e')
    assert len(chi_e) == 1,'fail 8'
    assert chi_e[0].h == 'e','fail 9'

#@+node:ekr.20090130133404.2: *4* @test leoNodes properties
v = p.v
b = p.b
p.b = b
assert p.b == b
v.b = b
assert v.b == b

h = p.h
p.h = h
assert p.h == h
v.h = h
assert v.h == h

for p in c.all_positions():
    assert p.b == p.bodyString()
    assert p.v.b == p.v.bodyString()
    assert p.h == p.headString()
    assert p.v.h == p.v.headString()
#@+node:ekr.20080310073711.1: *4* @test nodeIndices.toString(None) allocates a new index
gnx = g.app.nodeIndices.toString(None)
assert(gnx not in (None,'None'))
assert(len(gnx) > 1)
#@+node:ekr.20041013062906: *4* @test onHyperLinkControlClick
# This hack is needed only for tkinter gui.
if g.app.gui.guiName() == 'tkinter':
    p.OnHyperLinkControlClick(event=None)
#@+node:ekr.20100131180007.5369: *4* @test p.adjustPositionBeforeUnlink
table = (
    '1',
    '1-1','1-1-1','1-1-2',
    '1-2','1-2-1','1-2-2',
    '2',
    '2-1','2-1-1','2-1-2',
    '2-2','2-2-1','2-2-2',
    '3',
    '3-1','3-1-1','3-1-2',
    '3-2','3-2-1','3-2-2',
)

for suffix in table:
    h = 'node %s' % suffix
    p2 = g.findNodeInTree(c,p,h)
    assert p2,h

table2 = (
    ('2-1-2','2-1-1','2-1-1'),
    ('3','2','2'),
)  

for h1,h2,h3 in table2:
    p1 = g.findNodeInTree(c,p,'node %s' % h1)
    p2 = g.findNodeInTree(c,p,'node %s' % h2)
    p3 = g.findNodeInTree(c,p,'node %s' % h3)
    p1._adjustPositionBeforeUnlink(p2)
    result = p1
    assert result.stack == p3.stack,'expected %s got %s' % (
        p3.h,result and result.h or '<none>')

# Data.
@others
#@+node:ekr.20100131180007.5370: *5* node 1
# Node 1
#@+node:ekr.20100131180007.5371: *6* node 1-1
# node 1-1
#@+node:ekr.20100131180007.5372: *7* node 1-1-1
# node 1-1-1
#@+node:ekr.20100131180007.5373: *7* node 1-1-2
# node 1-1-2
#@+node:ekr.20100131180007.5374: *6* node 1-2
# node 1-2
#@+node:ekr.20100131180007.5375: *7* node 1-2-1
# node 1-2-1
#@+node:ekr.20100131180007.5376: *7* node 1-2-2
# node 1-2-2
#@+node:ekr.20100131180007.5377: *5* node 2
# node 2
#@+node:ekr.20100131180007.5378: *6* node 2-1
# node 2-1
#@+node:ekr.20100131180007.5379: *7* node 2-1-1
# node 2-1-1
#@+node:ekr.20100131180007.5380: *7* node 2-1-2
# node 2-1-2
#@+node:ekr.20100131180007.5381: *6* node 2-2
# node 2-2
#@+node:ekr.20100131180007.5382: *7* node 2-2-1
# node 2-2-1
#@+node:ekr.20100131180007.5383: *7* node 2-2-2
# node 2-2-2
#@+node:ekr.20100131180007.5384: *5* node 3
# node 3
#@+node:ekr.20100131180007.5385: *6* node 3-1
# node 3-1
#@+node:ekr.20100131180007.5386: *7* node 3-1-1
# node 3-1-1
#@+node:ekr.20100131180007.5387: *7* node 3-1-2
# node 3-1-2
#@+node:ekr.20100131180007.5388: *6* node 3-2
# node 3-2
#@+node:ekr.20100131180007.5389: *7* node 3-2-1
# node 3-2-1
#@+node:ekr.20100131180007.5390: *7* node 3-2-2
# node 3-2-2
#@+node:ekr.20040712101754.199: *4* @test p.comparisons
copy = p.copy()
assert(p == copy)
assert(p != p.threadNext())

root = c.rootPosition()
# assert p.equal(p.copy()) is True
# assert p.equal(root) is False
assert p.__eq__(copy) is True
assert p.__ne__(copy) is False
assert p.__eq__(root) is False
assert p.__ne__(root) is True
#@+node:ekr.20040712101754.209: *4* @test p.hasNextBack
for p in c.all_positions():

    back = p.back()
    next = p.next()

    assert(
        (back and p.hasBack()) or
        (not back and not p.hasBack()))

    assert(
        (next and p.hasNext()) or
        (not next and not p.hasNext()))
#@+node:ekr.20040712101754.210: *4* @test p.hasParentChild
for p in c.all_positions():

    child = p.firstChild()
    parent = p.parent()

    assert(
        (child and p.hasFirstChild()) or
        (not child and not p.hasFirstChild()))

    assert(
        (parent and p.hasParent()) or
        (not parent and not p.hasParent()))
#@+node:ekr.20040712101754.211: *4* @test p.hasThreadNextBack
for p in c.all_positions():

    threadBack = p.getThreadBack()
    threadNext = p.getThreadNext()

    assert(
        (threadBack and p.hasThreadBack()) or
        (not threadBack and not p.hasThreadBack()))

    assert(
        (threadNext and p.hasThreadNext()) or
        (not threadNext and not p.hasThreadNext()))
#@+node:ekr.20040722055040: *4* @test p.isAncestorOf
for p in c.all_positions():

    child = p.firstChild()
    while child:
        for parent in p.self_and_parents_iter():
            assert parent.isAncestorOf(child)
        child.moveToNext()

    next = p.next()
    assert not p.isAncestorOf(next)
#@+node:ekr.20060106211922: *4* @test p.isCurrentPosition
n = g.app.positions
assert c.isCurrentPosition(None) is False
assert c.isCurrentPosition(p) is True
assert g.app.positions == n
#@+node:ekr.20060106211922.1: *4* @test p.isRootPosition
assert not c.isRootPosition(None),'fail 1'
assert not c.isRootPosition(p),'fail 2'
#@+node:ekr.20040712101754.188: *4* @test p.iters and v.iters
import leo.core.leoNodes as leoNodes

current = c.p
child = current.firstChild()

allList = [p.v for p in c.all_positions_iter()]
vList1 = [v for v in c.p.vnodes_iter()]
vList2 = [v for v in c.p.unique_vnodes_iter()]

if 0:
    for v in vList1: print(v)
    for v in vList2: print(v)

if 0:
    print(len(allList),len(vList1),len(vList2))

if 0: # v.iters no longer exist.
    << tests of consistency of p and v iters >>
<< tests that node iterators return no duplicate nodes >>
<< print nodes returned by iterators >>
#@+node:ekr.20040712101754.189: *5* child1
#@+node:ekr.20040712101754.190: *6* a
#@+node:ekr.20040712101754.191: *7* b
#@+node:ekr.20040712101754.192: *6* c
#@+node:ekr.20040712101754.193: *6* d
#@+node:ekr.20040712101754.194: *7* e
#@+node:ekr.20040712101754.195: *5* child2
#@+node:ekr.20040712101754.196: *5* << tests of consistency of p and v iters >>
try:
    tag = "test1"
    list1 = [v for v in current.vnodes_iter()]
    list2 = [v for v in current.v.self_and_subtree_iter()]
    assert(list1==list2)

    tag = "test2"
    list1 = [p.v for p in c.all_positions_iter()]
    list2 = [v   for v in c.all_vnodes_iter()]
    assert(list1==list2)

    # print("consistency tests pass")

except AssertionError:
    print(tag)
    print("list1")
    for v in list1: print(v)
    print("list2")
    for v in list2: print(v)
    raise
#@+node:ekr.20040712101754.197: *5* << tests that node iterators return no duplicate nodes >>
nodes = []
for v in current.unique_vnodes_iter():
    assert v not in nodes
    nodes.append(v)

nodes = []
for t in current.unique_tnodes_iter():
    assert t not in nodes
    nodes.append(t)

# print("duplicate tests pass")
#@+node:ekr.20040712101754.198: *5* << print nodes returned by iterators >>
if 0:
    for v in current.vnodes_iter(): print(v)
    for v in current.unique_vnodes_iter(): print(v)

if 0: # subtree of root node:
    root = c.rootPosition()
    for v in root.vnodes_iter(): print(v)
    for t in root.tnodes_iter(): print(t)

if 0: # child1's tree.  child2 should not be included.
    for v in child.vnodes_iter(): print(v)
    for t in child.tnodes_iter(): print(t)
#@+node:ekr.20040802071519: *4* @test p.setBodyStringOrPane
# Tests that c.setBodyString works immediately.
h = p.h

try:
    child = p.firstChild()
    before = child.b
    after = "after"
    c.setBodyString(child,"after")
    c.selectPosition(child)
    t = c.frame.body.bodyCtrl
    s = t.get("1.0","end")
    assert s.rstrip() == after.rstrip(), \
        "c.setBodyString failed: %s, %s" % (repr(s),repr(after))
finally:
    c.setBodyString(child,before)
    c.selectPosition(p)
#@+node:ekr.20040802071519.1: *5* Test
after
#@+node:ekr.20110502130500.3471: *4* @test p.unique_nodes
aList = [z for z in p.unique_nodes()]
assert len(aList) == 3,len(aList)
v1,v2,v3 = aList
assert v1.h == p.h,p.h
assert v2.h == 'node 1',v2.h
assert v3.h == 'node 2',v3.h
#@+node:ekr.20110502130500.3472: *5* node 1
# Node 1
#@+node:ekr.20110502130500.3473: *6* node 2
# node 3
#@+node:ekr.20100131180007.5391: *4* @test v.atAutoNodeName & v.atAutoRstNodeName
table = (
    ('@auto-rst rst-file','rst-file','rst-file'),
    ('@auto x','x',''),
    ('xyz','',''),
)

for s,expected1,expected2 in table:
    result1 = p.v.atAutoNodeName(h=s)
    result2 = p.v.atAutoRstNodeName(h=s)
    assert result1 == expected1,'fail1: given %s expected %s got %s' % (
        repr(s),repr(expected1),repr(result1))
    assert result2 == expected2,'fail2: given %s expected %s got %s' % (
        repr(s),repr(expected2),repr(result2))
#@+node:ekr.20060913084600: *4* @test v/t.__hash__
import leo.core.leoNodes as leoNodes

if leoNodes.use_zodb:
    p.v.__hash__()
#@+node:ekr.20071113202452: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

print('\nEnd of leoNodes tests.')
#@+node:ekr.20080501121449.1: *4* Fundamental node operations
#@+node:ekr.20080423110627.2: *5* @test at most one vnode has str_leo_pos attribute
n = 0
for v in c.all_unique_vnodes_iter():
    if hasattr(v,'unknownAttributes'):
        d = v.unknownAttributes
        if d.get('str_leo_pos'):
            n += 1

# print(n)
assert n < 2
#@+node:ekr.20080423110627.3: *5* @test clone and move the clone to the root
# Delete all children.
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

child = p.insertAsNthChild(0)
c.setHeadString(child,'child') # Force the headline to update.

try:
    assert child, 'no child'
    c.selectPosition(child)
    clone = c.clone()
    assert clone == c.p
    assert clone.h == 'child','fail headstring: %s' % clone.h
    assert child.isCloned(), 'fail 1'
    assert clone.isCloned(), 'fail 2'
    assert child.isCloned(), 'fail 3'
    assert clone.isCloned(), 'fail 4'
    c.undoer.undo()
    assert not child.isCloned(), 'fail 1-a'
    c.undoer.redo()
    assert child.isCloned(),    'fail 1-b'
    c.undoer.undo()
    assert not child.isCloned(), 'fail 1-c'
    c.undoer.redo()
    assert child.isCloned(),    'fail 1-d'
    oldRoot = c.rootPosition()
    clone.moveToRoot(oldRoot=oldRoot) # Does not change child position.
    assert child.isCloned(),    'fail 3-2'
    assert clone.isCloned(),    'fail 4-2'
    assert not clone.parent(),  'fail 5'
    assert not clone.back(),    'fail 6'
    clone.doDelete()
    assert not child.isCloned(), 'fail 7'
finally:
    # Delete all children.
    if 1:
        while p.hasChildren():
            p.firstChild().doDelete(newNode=None)
    c.redraw_now(p)
#@+node:ekr.20080503082625.3: *5* @test delete node
root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

try:
    p2 = p.insertAsNthChild(0)
    p2.setHeadString('A')
    p3 = p.insertAsNthChild(1)
    p3.setHeadString('B')
    p4 = p.insertAsNthChild(2)
    p4.setHeadString('C')
    p.expand()
    c.selectPosition(p3)
    c.deleteOutline()
    c.redraw_now()
    p = c.p
    assert p.h == 'A', 'fail 1: got %s' % p.h
    assert p.next().h == 'C', 'fail 2'
    c.undoer.undo()
    c.outerUpdate()
    p = c.p
    assert p.back() == p2, 'fail 4 %s' % p.back()
    assert p.next() == p4, 'fail 5'
    c.undoer.redo()
    c.outerUpdate()
    p = c.p
    assert p.h == 'A',          'fail 1-2'
    assert p.next().h == 'C',   'fail 2-2'
    c.undoer.undo()
    c.outerUpdate()
    p = c.p
    assert p.back() == p2,  'fail 4-2'
    assert p.next() == p4,  'fail 5-2'
    c.undoer.redo()
    c.outerUpdate()
    p = c.p
    assert p.h == 'A',          'fail 1-3'
    assert p.next().h == 'C',   'fail 2-3'

finally:
    if 1:
        while root.hasChildren():
            root.firstChild().doDelete(newNode=None)
    c.redraw_now(root)
#@+node:ekr.20080423110627.13: *5* @test deleting the root should select another node
import leo.core.leoNodes as leoNodes

while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

child = p.insertAsNthChild(0)
child.setHeadString('child')

try:
    oldRoot = c.rootPosition()
    child.moveToRoot(oldRoot=oldRoot) # Does not change child position.
    c.setRootPosition(child)
    assert c.positionExists(child)
    assert c.rootPosition().h == 'child', 'fail 1'
    next = c.rootPosition().next()
    assert next.h == 'Startup', 'fail 2: next: %s' % next
    c.rootPosition().doDelete(newNode=next)
    c.setRootPosition(next)
finally:
    while p.hasChildren():
        p.firstChild().doDelete(newNode=None)
    # c.selectPosition(p)
    c.redraw_now()
#@+node:ekr.20080503082625.5: *5* @test demote
root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

try:
    p2 = p.insertAsNthChild(0)
    p2.setHeadString('A')
    p3 = p.insertAsNthChild(1)
    p3.setHeadString('B')
    p4 = p.insertAsNthChild(2)
    p4.setHeadString('C')
    p5 = p.insertAsNthChild(3)
    p5.setHeadString('D')
    p.expand()
    c.setCurrentPosition(p3)
    c.demote()
    p = c.p
    assert p == p3,         'fail 1'
    assert p.h == 'B',      'fail 2'
    assert not p.next(),    'fail 3'
    assert p.firstChild().h == 'C',          'fail child 1'
    assert p.firstChild().next().h == 'D',   'fail child 2'
    c.undoer.undo()
    p = c.p
    assert p == p3
    assert p.back() == p2, 'fail 5'
    assert p.next() == p4, 'fail 6'
    c.undoer.redo()
    assert p == p3,         'fail 1-2'
    assert p.h == 'B',      'fail 2-2'
    assert not p.next(),    'fail 3-2'
    assert p.firstChild().h == 'C',         'fail child 1-2'
    assert p.firstChild().next().h == 'D',  'fail child 2-2'
    c.undoer.undo()
    p = c.p
    assert p.back() == p2, 'fail 4-2'
    assert p.next() == p4, 'fail 5-2'
    c.undoer.redo()
    assert p == p3,         'fail 1-3'
    assert p.h == 'B',      'fail 2-3'
    assert not p.next(),    'fail 3-3'
    assert p.firstChild().h == 'C',         'fail child 1-3'
    assert p.firstChild().next().h == 'D',  'fail child 2-3'

finally:
    if 1:
        while root.hasChildren():
            root.firstChild().doDelete(newNode=None)
    c.redraw_now(root)
#@+node:ekr.20080501121449.3: *5* @test insert node
root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

try:
    p2 = p.insertAsNthChild(0)
    p2.setHeadString('A')
    p3 = p.insertAsNthChild(1)
    p3.setHeadString('B')
    p.expand()
    c.setCurrentPosition(p2)
    c.insertHeadline()
    p = c.p
    p.setHeadString('inserted')
    assert p.back().h == 'A', 'fail 1'
    assert p.next().h == 'B', 'fail 2'
    c.undoer.undo()
    p = c.p
    assert p == p2,         'fail 3'
    assert p.next() == p3,  'fail 4'
    c.undoer.redo()
    p = c.p
    assert p.back().h == 'A', 'fail 1-2'
    assert p.next().h == 'B', 'fail 2-2'
    c.undoer.undo()
    p = c.p
    assert p == p2,         'fail 3-2'
    assert p.next() == p3,  'fail 3-2'
    c.undoer.redo()
    p = c.p
    assert p.back().h == 'A', 'fail 1-3'
    assert p.next().h == 'B', 'fail 2-3'

finally:
    if 1:
        while root.hasChildren():
            root.firstChild().doDelete(newNode=None)
    c.redraw_now(root)
#@+node:ekr.20080423110627.11: *5* @test move-outline-down & undo/redo
root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

try:
    p2 = p.insertAsNthChild(0)
    p2.setHeadString('A')
    p3 = p.insertAsNthChild(1)
    p3.setHeadString('B')
    p4 = p.insertAsNthChild(2)
    p4.setHeadString('C')
    p5 = p.insertAsNthChild(3)
    p5.setHeadString('D')
    p.expand()
    c.setCurrentPosition(p3)
    c.moveOutlineDown()
    moved = c.p
    assert moved.h == 'B',          'fail 1: %s' % moved.h
    assert moved.back().h == 'C',   'fail 2'
    assert moved.next().h == 'D',   'fail 3'
    # This assert fails because p4._childIndex != moved.back()._childIndex.
    # assert moved.back() == p4, 'fail 4: %s != %s' % (moved.back(),p4)
    assert moved.next() == p5,      'fail 5: %s != %s' % (moved.next(),p5)
    c.undoer.undo()
    moved = c.p
    assert moved.back() == p2,      'fail 4'
    assert moved.next() == p4,      'fail 5'
    c.undoer.redo()
    moved = c.p
    assert moved.h == 'B',          'fail 1-2: %s' % moved.h
    assert moved.back().h == 'C',   'fail 2-2'
    assert moved.next().h == 'D',   'fail 3-2'
    c.undoer.undo()
    moved = c.p
    assert moved.back() == p2,      'fail 4-2'
    assert moved.next() == p4,      'fail 5-2'
    c.undoer.redo()
    moved = c.p
    assert moved.h == 'B',          'fail 1-3'
    assert moved.back().h == 'C',   'fail 2-3'
    assert moved.next().h == 'D',   'fail 3-3'

finally:
    if 1:
        while root.hasChildren():
            root.firstChild().doDelete(newNode=None)
    c.redraw_now(root)
#@+node:ekr.20080503073030.1: *5* @test move-outline-left
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

try:
    p2 = p.insertAsNthChild(0)
    p2.setHeadString('A')
    p.expand()
    c.setCurrentPosition(p2)
    c.moveOutlineLeft()
    moved = c.p
    assert moved.h == 'A','fail 1'
    # This assert fails because p4._childIndex != moved.back()._childIndex.
    assert moved.back() == p, 'fail 2: %s != %s' % (moved.back(),p4)
    c.undoer.undo()
    c.undoer.redo()
    c.undoer.undo()
    c.undoer.redo()

    moved.doDelete(newNode=p)

finally:
    if 1:
        while p.hasChildren():
            p.firstChild().doDelete(newNode=None)
        c.redraw_now(p)
#@+node:ekr.20080503073030.2: *5* @test move-outline-right
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

try:
    p2 = p.insertAsNthChild(0)
    p2.setHeadString('A')
    p3 = p.insertAsNthChild(1)
    p3.setHeadString('B')
    p4 = p.insertAsNthChild(2)
    p4.setHeadString('C')
    p.expand()
    c.setCurrentPosition(p3)
    c.moveOutlineRight()
    moved = c.p
    assert moved.h == 'B', 'fail 1'
    assert moved.parent() == p2
    c.undoer.undo()
    c.undoer.redo()
    c.undoer.undo()
    c.undoer.redo()
finally:
    if 1:
        while p.hasChildren():
            p.firstChild().doDelete(newNode=None)
    if 1:
        c.redraw_now(p)
#@+node:ekr.20080423110627.12: *5* @test move-outline-up
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

try:
    p2 = p.insertAsNthChild(0)
    p2.setHeadString('A')
    p3 = p.insertAsNthChild(1)
    p3.setHeadString('B')
    p4 = p.insertAsNthChild(2)
    p4.setHeadString('C')
    p5 = p.insertAsNthChild(3)
    p5.setHeadString('D')
    p.expand()
    c.setCurrentPosition(p4)
    c.moveOutlineUp()
    moved = c.p
    assert moved.h == 'C',          'fail 1'
    assert moved.back().h == 'A',   'fail 2'
    assert moved.next().h == 'B',   'fail 3'
    assert moved.back() == p2,      'fail 4: %s != %s' % (moved.back(),p2)
    # This assert fails because p4._childIndex != moved.back()._childIndex.
    # assert moved.next() == p3,    'fail 5: %s != %s' % (moved.next(),p3)
    c.undoer.undo()
    c.undoer.redo()
    c.undoer.undo()
    c.undoer.redo()
finally:
    if 1:
        while p.hasChildren():
            p.firstChild().doDelete(newNode=None)
    if 1:
        c.redraw_now(p)
#@+node:ekr.20080423110627.5: *5* @test paste-node
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

child = p.insertAsNthChild(0)
child.setHeadString('child')
child2 = p.insertAsNthChild(1)
child2.setHeadString('child2')
grandChild = child.insertAsNthChild(0)
grandChild.setHeadString('grand child')
c.selectPosition(grandChild)
c.clone()
c.selectPosition(child)

try:
    p.expand()
    c.selectPosition(child)
    assert c.p.h == 'child','fail 1'
    c.copyOutline()
    oldVnodes = [p2.v for p2 in child.self_and_subtree()]
    c.selectPosition(child)
    c.p.contract() # Essential
    c.pasteOutline()
    assert c.p != child, 'fail 2'
    assert c.p.h == 'child','fail 3'
    newVnodes = [p2.v for p2 in c.p.self_and_subtree()]
    for v in newVnodes:
        assert v not in oldVnodes, 'fail 4'
    c.undoer.undo()
    c.undoer.redo()
    c.undoer.undo()
    c.undoer.redo()

finally:
    if 1:
        while p.hasChildren():
            p.firstChild().doDelete(newNode=None)
    if 1:
        c.redraw_now(p)
#@+node:ekr.20080423110627.8: *5* @test paste-retaining-clones
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

child = p.insertAsNthChild(0)
child.setHeadString('child')
assert child, 'no child'
grandChild = child.insertAsNthChild(0)
grandChild.setHeadString('grand child')

try:
    c.selectPosition(child)
    c.copyOutline()
    oldVnodes = [p2.v for p2 in child.self_and_subtree()]
    c.p.contract() # Essential
    c.pasteOutlineRetainingClones()
    assert c.p != child, 'fail 2'
    newVnodes = [p2.v for p2 in c.p.self_and_subtree()]
    for v in newVnodes:
        assert v in oldVnodes, 'fail 3'
finally:
    if 1:
        while p.hasChildren():
            p.firstChild().doDelete(newNode=None)
    if 1:
        c.redraw_now(p)
#@+node:ekr.20080503082625.4: *5* @test promote
root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode=None)

try:
    p2 = p.insertAsNthChild(0)
    p2.setHeadString('A')
    p3 = p.insertAsNthChild(1)
    p3.setHeadString('B')
    p4 = p3.insertAsNthChild(0)
    p4.setHeadString('child 1')
    p5 = p3.insertAsNthChild(1)
    p5.setHeadString('child 2')
    p.expand()
    p6 = p.insertAsNthChild(2)
    p6.setHeadString('C')
    c.setCurrentPosition(p3)
    c.promote()
    p = c.p
    assert p == p3,         'fail 1'
    assert p.h == 'B',      'fail 2'
    assert p.next().h=='child 1',            'fail 3'
    assert p.next().next().h == 'child 2',   'fail child 1'
    assert p.next().next().next().h == 'C',  'fail child 2'
    c.undoer.undo()
    p = c.p
    assert p == p3
    assert p.back() == p2,  'fail 5'
    assert p.next() == p6,  'fail 6'
    assert p.firstChild().h=='child 1',          'fail child 3'
    assert p.firstChild().next().h == 'child 2', 'fail child 4'
    c.undoer.redo()
    p = c.p
    assert p == p3,         'fail 1-2'
    assert p.h == 'B',      'fail 2-2'
    assert p.next().h=='child 1',            'fail 3-2'
    assert p.next().next().h == 'child 2',   'fail child 1-2'
    assert p.next().next().next().h == 'C',  'fail child 2-2'
    c.undoer.undo()
    p = c.p
    assert p == p3
    assert p.back() == p2,                      'fail 5-2'
    assert p.next() == p6,                      'fail 6-2'
    assert p.firstChild().h=='child 1',         'fail child 3-2'
    assert p.firstChild().next().h == 'child 2','fail child 4-2'
    c.undoer.redo()
    p = c.p
    assert p == p3,     'fail 1-3'
    assert p.h == 'B',  'fail 2-3'
    assert p.next().h=='child 1',            'fail 3-3'
    assert p.next().next().h == 'child 2',   'fail child 1-3'
    assert p.next().next().next().h == 'C',  'fail child 2-3'

finally:
    if 1:
        while root.hasChildren():
            root.firstChild().doDelete(newNode=None)
    c.redraw_now(root)
#@+node:ekr.20081001094920.2: *4* tests for p.textOffset()
#@+node:ekr.20081001094920.3: *5* @test node that doesn't belong to a derived file
root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode = None)

try:

    p1 = p.insertAsLastChild()
    assert p1.textOffset() == 0

finally:
    if 1:
        while root.hasChildren():
            root.firstChild().doDelete(newNode = None)
    c.redraw_now()
#@+node:ekr.20081001094920.4: *5* @test root of a derived file
root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode = None)

try:

    p1 = p.insertAsLastChild()
    p1.setHeadString('@file zzz')
    assert p1.textOffset() == 0

finally:
    if 1:
        while root.hasChildren():
            root.firstChild().doDelete(newNode = None)
    c.redraw_now()
#@+node:ekr.20081001094920.5: *5* @test organizer node
root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode = None)

try:

    p1 = p.insertAsLastChild()
    p1.setHeadString('@file zzz')
    p2 = p1.insertAsLastChild()
    assert p1.textOffset() == 0
    assert p2.textOffset() == 0

finally:
    if 1:
        while root.hasChildren():
            root.firstChild().doDelete(newNode = None)
    c.redraw_now()
#@+node:ekr.20081001094920.6: *5* @test section node
root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode = None)

try:

    p1 = p.insertAsLastChild()
    p1.setHeadString('@file zzz')
    body = '''   %s
    ''' % (g.angleBrackets(' section '))
    p1.setBodyString(body)
    p2 = p1.insertAsLastChild()
    head = g.angleBrackets(' section ')
    p2.setHeadString(head)
    assert p1.textOffset() == 0
    assert p2.textOffset() == 3

finally:
    if 1:
        while root.hasChildren():
            root.firstChild().doDelete(newNode = None)
    c.redraw_now()
#@+node:ekr.20081001094920.7: *5* @test "others" directive
root = p.copy()
while p.hasChildren():
    p.firstChild().doDelete(newNode = None)

try:

    p1 = p.insertAsLastChild()
    p1.setHeadString('@file zzz')
    body = '''     %s
    ''' % (chr(64) + 'others') # ugly hack
    p1.setBodyString(body)
    p2 = p1.insertAsLastChild()
    assert p1.textOffset() == 0
    assert p2.textOffset() == 5
    root.firstChild().doDelete(newNode = None)

finally:
    if 1:
        while root.hasChildren():
            root.firstChild().doDelete(newNode = None)
    c.redraw_now()
#@+node:ekr.20100131171342.5610: *3* leoPlugins
#@+node:ekr.20100131171342.5611: *4* @test getHandlersForTag
pc = g.app.pluginsController

aList1 = pc.getHandlersForTag('select1')
aList2 = pc.getHandlersForOneTag('select1')

assert type(aList1) == type([])
assert type(aList2) == type([])
assert aList1 == aList2
#@+node:ekr.20100909082308.5990: *4* @test regularizeName
pc = g.app.pluginsController

table = (
    ('x',               'x'),
    ('foo.bar',         'foo.bar'),
    ('x.py',            'leo.plugins.x'),
    ('leo.plugins.x',   'leo.plugins.x')    
)

for fn,expected in table:
    result = pc.regularizeName(fn)
    assert result==expected,'expected %s, got %s' % (
        expected,result)
    # Make sure that calling regularizeName twice is benign.
    result2 = pc.regularizeName(result)
    assert result2==result
#@+node:ekr.20091219122958.5066: *3* leoRst
# Warning: these depend on the .css files in leo\test\unittest.
#@+node:ekr.20100812172232.5800: *4* @common leoRst test code
@others
#@+node:ekr.20100812182942.5804: *5* class rst3Test
class rst3Test:

    def __init__ (self,c,p):
        self.c = c
        self.p = p.copy()
        self.run()

    @others
#@+node:ekr.20100827194549.5963: *6* report
def report (self,expected,got):

    verbose = True
    expected_lines = g.splitLines(expected.b)
    got_lines = g.splitLines(got.b)

    for i in range(min(len(expected_lines),len(got_lines))):
        match = expected_lines[i]==got_lines[i]
        if verbose or not match:
            tag = g.choose(match,'  ','**')
            print ('%3d%s %s' % (i,tag,repr(expected_lines[i])))
            print ('%3d%s %s' % (i,tag,repr(got_lines[i])))
        if not verbose and not match:
            break
#@+node:ekr.20100827183358.5957: *6* run
def run(self):
    import sys
    if not sys.platform.startswith('win') and \
        g.isPython3: return
    def clean(s):
        return s.replace('\r','')
    c,p = self.c,self.p
    rc = c.rstCommands
    expected,got,source = self.setup()
    rc.processTree(p=source.firstChild(),ext='.html',toString=True,justOneFile=True)
    rst = clean(rc.source)
    html = clean(rc.stringOutput)
    assert rst,'rst'
    assert html,'html'
    # Kludge: disregard version of docutils.
    html = html.replace('Docutils 0.6','Docutils 0.8')
    html = html.replace('Docutils 0.7','Docutils 0.8')
    if expected.hasChildren():
        child1 = expected.firstChild()
        child2 = expected.firstChild().next()
        child1_b = clean(child1.b)
        child2_b = clean(child2.b)
        ok = rst == child1_b and html == child2_b
        if not ok:
            got_html,got_rst = self.set_got(expected,got)
            got_html.b = html
            got_rst.b = rst
        if rst != child1_b:
            self.report(child1,got_rst)
        if html != child2_b:
            self.report(child2,got_html)
        assert rst == child1_b,'rst mismatch'
        assert html == child2_b,'html mismatch'
    else:
        child = expected.insertAsNthChild(0)
        child.h,child.b = 'rst',rst
        child = expected.insertAsNthChild(1)
        child.h,child.b = ' html',html
#@+node:ekr.20100827183358.5958: *6* setup
def setup (self):

    c,p = self.c, self.p

    expected = g.findNodeInTree(c,p,'expected')
    got = g.findNodeInTree(c,p,'got')
    source = g.findNodeInTree(c,p,'source')

    assert source,'source'
    assert expected,'expected'

    return expected,got,source
#@+node:ekr.20100827183358.5959: *6* set_got
def set_got (self,expected,got):

    c,p = self.c, self.p

    if got:
        got_rst = g.findNodeInTree(c,got,'rst')
        got_html = g.findNodeInTree(c,got,'html')
        assert got_rst
        assert got_html
    else:
        got = p.insertAsLastChild()
        got.h = 'got'
        got_rst = got.insertAsNthChild(0)
        got_rst.h = 'rst'
        got_html = got.insertAsNthChild(1)
        got_html.h = 'html'

    return got_html,got_rst
#@+node:ekr.20091219121039.5065: *4* @test rst3 handleMissingStyleSheetArgs
x = c.rstCommands

result = x.handleMissingStyleSheetArgs(s=None)
assert result == {},'expected {}, got %s' % result

expected = {
    'documentoptions':'[english,12pt,lettersize]',
    'language':'ca',
    'use-latex-toc':'1',
}

for s in (
    '--language=ca, --use-latex-toc,--documentoptions=[english,12pt,lettersize]',
    '--documentoptions=[english,12pt,lettersize],--language=ca, --use-latex-toc',
    '--use-latex-toc,--documentoptions=[english,12pt,lettersize],--language=ca, ',
):

    result = x.handleMissingStyleSheetArgs(s=s)
    assert result == expected,'expected %s\ngot %s' % (expected,result)
#@+node:ekr.20100812172232.5801: *4* @test rst3 defaults
exec(g.findTestScript(c,'@common leoRst test code'))
rst3Test(c,p)
#@+node:ekr.20100812182942.5805: *5* source
@language rest
#@+node:ekr.20100812182942.5807: *6* @rst test.html
@language rest

#####
Title
#####

This is test.html
#@+node:ekr.20100812182942.5808: *7* section
@ This is a doc part
it has two lines.
@c
This is the body of the section.
#@+node:ekr.20100812213445.5814: *5* expected
@language html
#@+node:ekr.20100813100841.5848: *6* rst
.. rst3: filename: test.html


#####
Title
#####

This is test.html

section
+++++++

@ This is a doc part
it has two lines.
This is the body of the section.

#@+node:ekr.20100813100841.5849: *6*  html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>Title</title>
<style type="text/css">

/*ORIGINAL GOODGER + changes; up to line 224 it's standard reST stylesheet
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2006/10/19 13:23:15 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

/* EKR 10/19/06 */
/* some browsers require imported rules to precede all rulesets */
@import url(leo_rst.css);
@import url(silver_city.css);

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;}
  /*background-color: #eeeeee }*/
  /*for some reason i can't overide in an import*/

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

/*for some reason, the following isn't being overridden by the imports
at the end of this style sheet so I've commented it out*/
/*tt {
  background-color: #eeeeee }*/

ul.auto-toc {
  list-style-type: none }

hr { /* EKR */
  width: 100%;
  height: 1pt;
  color: gray;
}



</style>
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>

<!-- rst3: filename: test.html -->
<p>This is test.html</p>
<div class="section" id="section">
<h1>section</h1>
<p>&#64; This is a doc part
it has two lines.
This is the body of the section.</p>
</div>
</div>
</body>
</html>
#@+node:ekr.20100827182529.6840: *5* got
#@+node:ekr.20100827182529.6841: *6* rst
.. rst3: filename: test.html


#####
Title
#####

This is test.html

section
+++++++

@ This is a doc part
it has two lines.
This is the body of the section.

#@+node:ekr.20100827182529.6842: *6* html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>Title</title>
<style type="text/css">

/*ORIGINAL GOODGER + changes; up to line 224 it's standard reST stylesheet
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2006/10/19 13:23:15 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

/* EKR 10/19/06 */
/* some browsers require imported rules to precede all rulesets */
@import url(leo_rst.css);
@import url(silver_city.css);

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;}
  /*background-color: #eeeeee }*/
  /*for some reason i can't overide in an import*/

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

/*for some reason, the following isn't being overridden by the imports
at the end of this style sheet so I've commented it out*/
/*tt {
  background-color: #eeeeee }*/

ul.auto-toc {
  list-style-type: none }

hr { /* EKR */
  width: 100%;
  height: 1pt;
  color: gray;
}



</style>
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>

<!-- rst3: filename: test.html -->
<p>This is test.html</p>
<div class="section" id="section">
<h1>section</h1>
<p>&#64; This is a doc part
it has two lines.
This is the body of the section.</p>
</div>
</div>
</body>
</html>
#@+node:ekr.20100813100841.5850: *4* @test rst3 @no-head
exec(g.findTestScript(c,'@common leoRst test code'))
rst3Test(c,p)
#@+node:ekr.20100813100841.5854: *5* source
@language rest
#@+node:ekr.20100813100841.5855: *6* @rst test.html
@language rest

#####
Title
#####

This is test.html
#@+node:ekr.20100813100841.5856: *7* @rst-no-head section
This is the body of the section.
#@+node:ekr.20100813100841.5857: *5* expected
#@+node:ekr.20100813100841.5858: *6* rst
.. rst3: filename: test.html


#####
Title
#####

This is test.html

This is the body of the section.

#@+node:ekr.20100813100841.5859: *6* html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>Title</title>
<style type="text/css">

/*ORIGINAL GOODGER + changes; up to line 224 it's standard reST stylesheet
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2006/10/19 13:23:15 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

/* EKR 10/19/06 */
/* some browsers require imported rules to precede all rulesets */
@import url(leo_rst.css);
@import url(silver_city.css);

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;}
  /*background-color: #eeeeee }*/
  /*for some reason i can't overide in an import*/

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

/*for some reason, the following isn't being overridden by the imports
at the end of this style sheet so I've commented it out*/
/*tt {
  background-color: #eeeeee }*/

ul.auto-toc {
  list-style-type: none }

hr { /* EKR */
  width: 100%;
  height: 1pt;
  color: gray;
}



</style>
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>

<!-- rst3: filename: test.html -->
<p>This is test.html</p>
<p>This is the body of the section.</p>
</div>
</body>
</html>
#@+node:ekr.20100827182529.6843: *5* got
#@+node:ekr.20100827182529.6844: *6* rst
.. rst3: filename: test.html


#####
Title
#####

This is test.html

This is the body of the section.

#@+node:ekr.20100827182529.6845: *6* html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>Title</title>
<style type="text/css">

/*ORIGINAL GOODGER + changes; up to line 224 it's standard reST stylesheet
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2006/10/19 13:23:15 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

/* EKR 10/19/06 */
/* some browsers require imported rules to precede all rulesets */
@import url(leo_rst.css);
@import url(silver_city.css);

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;}
  /*background-color: #eeeeee }*/
  /*for some reason i can't overide in an import*/

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

/*for some reason, the following isn't being overridden by the imports
at the end of this style sheet so I've commented it out*/
/*tt {
  background-color: #eeeeee }*/

ul.auto-toc {
  list-style-type: none }

hr { /* EKR */
  width: 100%;
  height: 1pt;
  color: gray;
}



</style>
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>

<!-- rst3: filename: test.html -->
<p>This is test.html</p>
<p>This is the body of the section.</p>
</div>
</body>
</html>
#@+node:ekr.20100813100841.5824: *4* @test doc_only_mode (set in headline)
exec(g.findTestScript(c,'@common leoRst test code'))
rst3Test(c,p)
#@+node:ekr.20100813100841.5839: *5* source
@language rest
#@+node:ekr.20100813100841.5840: *6* @rst test.html
#####
Title
#####

This is test.html
#@+node:ekr.20100813124317.5868: *7* @rst-option doc_only_mode=True
#@+node:ekr.20100813100841.5841: *8* section
@ This is a doc part
it has two lines.
@c
This is the body of the section.
#@+node:ekr.20100813100841.5842: *5* expected
#@+node:ekr.20100813124317.5869: *6* rst
.. rst3: filename: test.html

#####
Title
#####

This is test.html



section
*******

This is a doc part
it has two lines.

#@+node:ekr.20100813124317.5870: *6*  html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>Title</title>
<style type="text/css">

/*ORIGINAL GOODGER + changes; up to line 224 it's standard reST stylesheet
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2006/10/19 13:23:15 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

/* EKR 10/19/06 */
/* some browsers require imported rules to precede all rulesets */
@import url(leo_rst.css);
@import url(silver_city.css);

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;}
  /*background-color: #eeeeee }*/
  /*for some reason i can't overide in an import*/

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

/*for some reason, the following isn't being overridden by the imports
at the end of this style sheet so I've commented it out*/
/*tt {
  background-color: #eeeeee }*/

ul.auto-toc {
  list-style-type: none }

hr { /* EKR */
  width: 100%;
  height: 1pt;
  color: gray;
}



</style>
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>

<!-- rst3: filename: test.html -->
<p>This is test.html</p>
<div class="section" id="section">
<h1>section</h1>
<p>This is a doc part
it has two lines.</p>
</div>
</div>
</body>
</html>
#@+node:ekr.20100827182529.6846: *5* got
#@+node:ekr.20100827182529.6847: *6* rst
.. rst3: filename: test.html

#####
Title
#####

This is test.html



section
*******

This is a doc part
it has two lines.

#@+node:ekr.20100827182529.6848: *6* html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>Title</title>
<style type="text/css">

/*ORIGINAL GOODGER + changes; up to line 224 it's standard reST stylesheet
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2006/10/19 13:23:15 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

/* EKR 10/19/06 */
/* some browsers require imported rules to precede all rulesets */
@import url(leo_rst.css);
@import url(silver_city.css);

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;}
  /*background-color: #eeeeee }*/
  /*for some reason i can't overide in an import*/

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

/*for some reason, the following isn't being overridden by the imports
at the end of this style sheet so I've commented it out*/
/*tt {
  background-color: #eeeeee }*/

ul.auto-toc {
  list-style-type: none }

hr { /* EKR */
  width: 100%;
  height: 1pt;
  color: gray;
}



</style>
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>

<!-- rst3: filename: test.html -->
<p>This is test.html</p>
<div class="section" id="section">
<h1>section</h1>
<p>This is a doc part
it has two lines.</p>
</div>
</div>
</body>
</html>
#@+node:ekr.20100813124317.5879: *4* @test doc_only_mode (set in options doc part)
exec(g.findTestScript(c,'@common leoRst test code'))
rst3Test(c,p)
#@+node:ekr.20100813124317.5880: *5* source
@language rest
#@+node:ekr.20100813124317.5881: *6* @rst test.html
#####
Title
#####

This is test.html
#@+node:ekr.20100813124317.5883: *7* section
@ @rst-options
doc_only_mode=True
@c
@ This is a doc part
it has two lines.
@c
This is the body of the section.
#@+node:ekr.20100813124317.5884: *5* expected
#@+node:ekr.20100813124317.5889: *6* rst
.. rst3: filename: test.html

#####
Title
#####

This is test.html

section
+++++++

This is a doc part
it has two lines.

#@+node:ekr.20100813124317.5890: *6*  html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>Title</title>
<style type="text/css">

/*ORIGINAL GOODGER + changes; up to line 224 it's standard reST stylesheet
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2006/10/19 13:23:15 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

/* EKR 10/19/06 */
/* some browsers require imported rules to precede all rulesets */
@import url(leo_rst.css);
@import url(silver_city.css);

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;}
  /*background-color: #eeeeee }*/
  /*for some reason i can't overide in an import*/

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

/*for some reason, the following isn't being overridden by the imports
at the end of this style sheet so I've commented it out*/
/*tt {
  background-color: #eeeeee }*/

ul.auto-toc {
  list-style-type: none }

hr { /* EKR */
  width: 100%;
  height: 1pt;
  color: gray;
}



</style>
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>

<!-- rst3: filename: test.html -->
<p>This is test.html</p>
<div class="section" id="section">
<h1>section</h1>
<p>This is a doc part
it has two lines.</p>
</div>
</div>
</body>
</html>
#@+node:ekr.20100827182529.6849: *5* got
#@+node:ekr.20100827182529.6850: *6* rst
.. rst3: filename: test.html

#####
Title
#####

This is test.html

section
+++++++

This is a doc part
it has two lines.

#@+node:ekr.20100827182529.6851: *6* html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>Title</title>
<style type="text/css">

/*ORIGINAL GOODGER + changes; up to line 224 it's standard reST stylesheet
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2006/10/19 13:23:15 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

/* EKR 10/19/06 */
/* some browsers require imported rules to precede all rulesets */
@import url(leo_rst.css);
@import url(silver_city.css);

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;}
  /*background-color: #eeeeee }*/
  /*for some reason i can't overide in an import*/

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

/*for some reason, the following isn't being overridden by the imports
at the end of this style sheet so I've commented it out*/
/*tt {
  background-color: #eeeeee }*/

ul.auto-toc {
  list-style-type: none }

hr { /* EKR */
  width: 100%;
  height: 1pt;
  color: gray;
}



</style>
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>

<!-- rst3: filename: test.html -->
<p>This is test.html</p>
<div class="section" id="section">
<h1>section</h1>
<p>This is a doc part
it has two lines.</p>
</div>
</div>
</body>
</html>
#@+node:ekr.20100813100841.5825: *4* @test show_doc_parts_in_rst_mode
# Applies to options doc parts as well.
#@+node:ekr.20100827140832.5913: *4* @test show_leo_directives=False
exec(g.findTestScript(c,'@common leoRst test code'))
rst3Test(c,p)
#@+node:ekr.20100827140832.5917: *5* source
@language rest
#@+node:ekr.20100827140832.5918: *6* @rst test.html
@language rest

@ @rst-options
show_leo_directives=False
@c

#####
Title
#####

This is test.html
#@+node:ekr.20100827140832.5919: *7* section
@ This is a doc part
it has two lines.
@c
This is the body of the section.
#@+node:ekr.20100827140832.5926: *5* expected
#@+node:ekr.20100827140832.5929: *6* rst
.. rst3: filename: test.html



#####
Title
#####

This is test.html

section
+++++++

@ This is a doc part
it has two lines.
This is the body of the section.

#@+node:ekr.20100827140832.5930: *6* html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>Title</title>
<style type="text/css">

/*ORIGINAL GOODGER + changes; up to line 224 it's standard reST stylesheet
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2006/10/19 13:23:15 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

/* EKR 10/19/06 */
/* some browsers require imported rules to precede all rulesets */
@import url(leo_rst.css);
@import url(silver_city.css);

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;}
  /*background-color: #eeeeee }*/
  /*for some reason i can't overide in an import*/

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

/*for some reason, the following isn't being overridden by the imports
at the end of this style sheet so I've commented it out*/
/*tt {
  background-color: #eeeeee }*/

ul.auto-toc {
  list-style-type: none }

hr { /* EKR */
  width: 100%;
  height: 1pt;
  color: gray;
}



</style>
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>

<!-- rst3: filename: test.html -->
<p>This is test.html</p>
<div class="section" id="section">
<h1>section</h1>
<p>&#64; This is a doc part
it has two lines.
This is the body of the section.</p>
</div>
</div>
</body>
</html>
#@+node:ekr.20100827182529.6852: *5* got
#@+node:ekr.20100827182529.6853: *6* rst
.. rst3: filename: test.html



#####
Title
#####

This is test.html

section
+++++++

@ This is a doc part
it has two lines.
This is the body of the section.

#@+node:ekr.20100827182529.6854: *6* html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>Title</title>
<style type="text/css">

/*ORIGINAL GOODGER + changes; up to line 224 it's standard reST stylesheet
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2006/10/19 13:23:15 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

/* EKR 10/19/06 */
/* some browsers require imported rules to precede all rulesets */
@import url(leo_rst.css);
@import url(silver_city.css);

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;}
  /*background-color: #eeeeee }*/
  /*for some reason i can't overide in an import*/

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

/*for some reason, the following isn't being overridden by the imports
at the end of this style sheet so I've commented it out*/
/*tt {
  background-color: #eeeeee }*/

ul.auto-toc {
  list-style-type: none }

hr { /* EKR */
  width: 100%;
  height: 1pt;
  color: gray;
}



</style>
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>

<!-- rst3: filename: test.html -->
<p>This is test.html</p>
<div class="section" id="section">
<h1>section</h1>
<p>&#64; This is a doc part
it has two lines.
This is the body of the section.</p>
</div>
</div>
</body>
</html>
#@+node:ekr.20100813100841.5847: *4* @ignore
#@+node:ekr.20100812213445.5824: *5* @test code_mode: rst3 show_doc_parts_as_paragraphs
exec(g.findTestScript(c,'@common leoRst test code'))

rst3Test(c,p)
#@+node:ekr.20100812213445.5825: *6* source
@language rest
#@+node:ekr.20100812213445.5826: *7* @rst test.html
@ @rst-options
show_doc_parts_as_paragraphs=True
@c
#####
Title
#####

This is test.html
#@+node:ekr.20100812213445.5827: *8* section
@ This is a doc part
it has two lines.
@c
This is the body of the section.
#@+node:ekr.20100812213445.5828: *6* expected
@language html
#@+node:ekr.20100813100841.5843: *7* rst
.. rst3: filename: test.html


#####
Title
#####

This is test.html

section
+++++++

@ This is a doc part
it has two lines.
@c

This is the body of the section.

#@+node:ekr.20100813100841.5844: *7*  html
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.8: http://docutils.sourceforge.net/" />
<title>Title</title>
<style type="text/css">

/*ORIGINAL GOODGER + changes; up to line 224 it's standard reST stylesheet
:Author: David Goodger
:Contact: goodger@users.sourceforge.net
:date: $Date: 2006/10/19 13:23:15 $
:version: $Revision: 1.2 $
:copyright: This stylesheet has been placed in the public domain.

Default cascading style sheet for the HTML output of Docutils.
*/

/* EKR 10/19/06 */
/* some browsers require imported rules to precede all rulesets */
@import url(leo_rst.css);
@import url(silver_city.css);

.first {
  margin-top: 0 }

.last {
  margin-bottom: 0 }

a.toc-backref {
  text-decoration: none ;
  color: black }

dd {
  margin-bottom: 0.5em }

div.abstract {
  margin: 2em 5em }

div.abstract p.topic-title {
  font-weight: bold ;
  text-align: center }

div.attention, div.caution, div.danger, div.error, div.hint,
div.important, div.note, div.tip, div.warning, div.admonition {
  margin: 2em ;
  border: medium outset ;
  padding: 1em }

div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title {
  color: red ;
  font-weight: bold ;
  font-family: sans-serif }

div.hint p.admonition-title, div.important p.admonition-title,
div.note p.admonition-title, div.tip p.admonition-title,
div.admonition p.admonition-title {
  font-weight: bold ;
  font-family: sans-serif }

div.dedication {
  margin: 2em 5em ;
  text-align: center ;
  font-style: italic }

div.dedication p.topic-title {
  font-weight: bold ;
  font-style: normal }

div.figure {
  margin-left: 2em }

div.footer, div.header {
  font-size: smaller }

div.sidebar {
  margin-left: 1em ;
  border: medium outset ;
  padding: 0em 1em ;
  background-color: #ffffee ;
  width: 40% ;
  float: right ;
  clear: right }

div.sidebar p.rubric {
  font-family: sans-serif ;
  font-size: medium }

div.system-messages {
  margin: 5em }

div.system-messages h1 {
  color: red }

div.system-message {
  border: medium outset ;
  padding: 1em }

div.system-message p.system-message-title {
  color: red ;
  font-weight: bold }

div.topic {
  margin: 2em }

h1.title {
  text-align: center }

h2.subtitle {
  text-align: center }

ol.simple, ul.simple {
  margin-bottom: 1em }

ol.arabic {
  list-style: decimal }

ol.loweralpha {
  list-style: lower-alpha }

ol.upperalpha {
  list-style: upper-alpha }

ol.lowerroman {
  list-style: lower-roman }

ol.upperroman {
  list-style: upper-roman }

p.attribution {
  text-align: right ;
  margin-left: 50% }

p.caption {
  font-style: italic }

p.credits {
  font-style: italic ;
  font-size: smaller }

p.label {
  white-space: nowrap }

p.rubric {
  font-weight: bold ;
  font-size: larger ;
  color: maroon ;
  text-align: center }

p.sidebar-title {
  font-family: sans-serif ;
  font-weight: bold ;
  font-size: larger }

p.sidebar-subtitle {
  font-family: sans-serif ;
  font-weight: bold }

p.topic-title {
  font-weight: bold }

pre.address {
  margin-bottom: 0 ;
  margin-top: 0 ;
  font-family: serif ;
  font-size: 100% }

pre.line-block {
  font-family: serif ;
  font-size: 100% }

pre.literal-block, pre.doctest-block {
  margin-left: 2em ;
  margin-right: 2em ;}
  /*background-color: #eeeeee }*/
  /*for some reason i can't overide in an import*/

span.classifier {
  font-family: sans-serif ;
  font-style: oblique }

span.classifier-delimiter {
  font-family: sans-serif ;
  font-weight: bold }

span.interpreted {
  font-family: sans-serif }

span.option {
  white-space: nowrap }

span.option-argument {
  font-style: italic }

span.pre {
  white-space: pre }

span.problematic {
  color: red }

table {
  margin-top: 0.5em ;
  margin-bottom: 0.5em }

table.citation {
  border-left: solid thin gray ;
  padding-left: 0.5ex }

table.docinfo {
  margin: 2em 4em }

table.footnote {
  border-left: solid thin black ;
  padding-left: 0.5ex }

td, th {
  padding-left: 0.5em ;
  padding-right: 0.5em ;
  vertical-align: top }

th.docinfo-name, th.field-name {
  font-weight: bold ;
  text-align: left ;
  white-space: nowrap }

h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
  font-size: 100% }

/*for some reason, the following isn't being overridden by the imports
at the end of this style sheet so I've commented it out*/
/*tt {
  background-color: #eeeeee }*/

ul.auto-toc {
  list-style-type: none }

hr { /* EKR */
  width: 100%;
  height: 1pt;
  color: gray;
}



</style>
</head>
<body>
<div class="document" id="title">
<h1 class="title">Title</h1>

<!-- rst3: filename: test.html -->
<p>This is test.html</p>
<div class="section" id="section">
<h1>section</h1>
<p>&#64; This is a doc part
it has two lines.
&#64;c</p>
<p>This is the body of the section.</p>
</div>
</div>
</body>
</html>
#@+node:ekr.20100813100841.5827: *5* @test code_mode: show_leo_directives
#@+node:ekr.20100813100841.5828: *5* @test code_mode: show_markup_doc_parts
#@+node:ekr.20100813100841.5829: *5* @test code_mode: show_options_doc_parts
#@+node:ekr.20100131180007.5459: *4* @test rst.initAtAutoWrite
rst = c.rstCommands
rst.initAtAutoWrite(p,fileName='<test file>',outputFile=None)

# Ensure we are actually testing the default logic.
d = p.v.u.get('rst-import',{})
underlines = d.get('underline_characters')
assert underlines is None,'fail 1: %s' % repr(underlines)
assert d == {},'fail 2: %s' % repr(d)
# Now test the logic.
assert rst.underlines2 == '','fail 3: %s' % repr(rst.underlines2)
assert rst.underlines1 == '=+*^~"\'`-:><_', 'fail4 %s' % repr(rst.underlines1)
assert rst.atAutoWriteUnderlines == '=+*^~"\'`-:><_', 'fail 5: %s' % (
    repr(rst.atAutoWriteUnderlines))
#@+node:ekr.20090529115704.4396: *3* leoShadow
#@+node:ekr.20090529115704.4560: *4* @@test (minitest) x.show_error
x = c.shadowController

lines1 = ('a','b','c')
lines2 = ('a','x','c')

x.show_error(
    lines1,lines2,
    message = "Test of x.show_error",
    lines1_message = "lines1",
    lines2_message = "lines2")
#@+node:ekr.20090529115704.4569: *4* @@test delete unittest shadow directory
# This unit test should come last.

import glob
import os

x = c.shadowController

shadow_dir = x.shadowDirName('unittest/xyzzy')

if g.os_path_exists(shadow_dir):
    files = g.os_path_abspath(g.os_path_join(shadow_dir,"*.*"))
    files = glob.glob(files)
    for z in files:
        if z != shadow_dir:
            os.unlink(z)
    os.rmdir(shadow_dir)
    assert not os.path.exists(shadow_dir)
    # g.es_print('deleted directory',shadow_dir,color='red')
#@+node:ekr.20090529115704.4397: *4* @suite run @shadow-test nodes in the @shadow-tests tree
import unittest

if 1:
    x = c.shadowController
else:
    import leo.core.leoShadow as leoShadow
    x = leoShadow.shadowController(c,trace=False,trace_writers=False)

suite = unittest.makeSuite(unittest.TestCase)
root = g.findNodeAnywhere(c,'@shadow-tests')
assert root, 'Node not found: @shadow-tests'

trace = False ; vrbose = False
for p in root.children_iter():
    h = p.h.strip()
    if h.startswith('@shadow-test-lax'):
        test = x.atShadowTestCase(c,p,x,lax=True)
    elif h.startswith('@shadow-test'):
        test = x.atShadowTestCase(c,p,x,lax=False)
    else:
        test = None
    if test:
        if trace and verbose: print(h)
        suite.addTest(test)
if suite:
    g.app.scriptDict['suite'] = suite
#@+node:ekr.20090529115704.4398: *5* @shadow-tests
@

All the tags should be tested at least once (equal, replace, delete, insert).

The replace, delete, insert operations should happen at least once:
    1. At the beginning of a node.
    2. In the middle of a node.
    3. At the end of a node.

For the delete and replace operators we must also test the case that the
deletion or replacement spans more than one block.
#@+node:ekr.20101023195640.6033: *6* @shadow-test replace in node new > old
#@+node:ekr.20101023195640.6034: *7* old
@others
#@+node:ekr.20101023195640.6035: *8* node 1
node 1 line 1
node 1 old line 1
node 1 old line 2
node 1 line 2
#@+node:ekr.20101023195640.6037: *7* new
@others
#@+node:ekr.20101023195640.6038: *8* node 1
node 1 line 1
node 1 new line 1
node 1 new line 2
node 1 new line 3
node 1 line 2
#@+node:ekr.20101023204543.6042: *6* @shadow-test replace in node new < old
#@+node:ekr.20101023204543.6043: *7* old
@others
#@+node:ekr.20101023204543.6044: *8* node 1
node 1 line 1
node 1 old line 1
node 1 old line 2
node 1 old line 3
node 1 old line 4
node 1 line 2
#@+node:ekr.20101023204543.6045: *7* new
@others
#@+node:ekr.20101023204543.6046: *8* node 1
node 1 line 1
node 1 new line 1
node 1 new line 2
node 1 line 2
#@+node:ekr.20090529115704.4400: *6* @shadow-test change middle line
#@+node:ekr.20090529115704.4401: *7* old
line 1
line 2
line 3
#@+node:ekr.20090529115704.4402: *7* new
line 1
line 2 changed
line 3
#@+node:ekr.20090529115704.4403: *6* @shadow-test change first line
#@+node:ekr.20090529115704.4404: *7* old
line 1
line 2
line 3
#@+node:ekr.20090529115704.4405: *7* new
line 1 changed
line 2
line 3
#@+node:ekr.20090529115704.4406: *6* @shadow-test change last line
#@+node:ekr.20090529115704.4407: *7* old
line 1
line 2
line 3
#@+node:ekr.20090529115704.4408: *7* new
line 1
line 2
line 3 changed
#@+node:ekr.20090529115704.4409: *6* @shadow-test delete first line
#@+node:ekr.20090529115704.4410: *7* old
line 1
line 2
line 3
#@+node:ekr.20090529115704.4411: *7* new
line 2
line 3
#@+node:ekr.20090529115704.4412: *6* @shadow-test delete middle line
#@+node:ekr.20090529115704.4413: *7* old
line 1
line 2
line 3
#@+node:ekr.20090529115704.4414: *7* new
line 1
line 3
#@+node:ekr.20090529115704.4415: *6* @shadow-test delete last line
#@+node:ekr.20090529115704.4416: *7* old
line 1
line 2
line 3
#@+node:ekr.20090529115704.4417: *7* new
line 1
line 2
#@+node:ekr.20090529115704.4418: *6* @shadow-test insert before first line
#@+node:ekr.20090529115704.4419: *7* old
line 1
line 2
line 3
#@+node:ekr.20090529115704.4420: *7* new
inserted line
line 1
line 2
line 3
#@+node:ekr.20090529115704.4421: *6* @shadow-test insert after first line
#@+node:ekr.20090529115704.4422: *7* old
line 1
line 2
line 3
#@+node:ekr.20090529115704.4423: *7* new
line 1
inserted line
line 2
line 3
#@+node:ekr.20090529115704.4424: *6* @shadow-test insert before last line
#@+node:ekr.20090529115704.4425: *7* old
line 1
line 2
line 3
#@+node:ekr.20090529115704.4426: *7* new
line 1
line 2
inserted line
line 3
#@+node:ekr.20090529115704.4427: *6* @shadow-test insert after last line
#@+node:ekr.20090529115704.4428: *7* old
line 1
line 2
line 3
#@+node:ekr.20090529115704.4429: *7* new
line 1
line 2
line 3
inserted line
#@+node:ekr.20090529115704.4430: *6* @shadow-test-lax insert between nodes: at end of prev node
#@+node:ekr.20090529115704.4431: *7* old
@others
#@+node:ekr.20090529115704.4432: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4433: *8* node 2
node 2 line 1
#@+node:ekr.20090529115704.4434: *7* new
@others
#@+node:ekr.20090529115704.4435: *8* node 1
node 1 line 1
inserted node at end of node 1
#@+node:ekr.20090529115704.4436: *8* node 2
node 2 line 1
#@+node:ekr.20090529115704.4437: *6* @shadow-test insert between nodes: at start of next node
#@+node:ekr.20090529115704.4438: *7* old
@others
#@+node:ekr.20090529115704.4439: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4440: *8* node 2
node 2 line 1
#@+node:ekr.20090529115704.4441: *7* new
@others
#@+node:ekr.20090529115704.4442: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4443: *8* node 2
inserted node at start of node 2
node 2 line 1
#@+node:ekr.20090529115704.4444: *6* @shadow-test delete between nodes: at end of prev node
#@+node:ekr.20090529115704.4445: *7* old
@others
#@+node:ekr.20090529115704.4446: *8* node 1
node 1 line 1
node 1 line 2
#@+node:ekr.20090529115704.4447: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4448: *7* new
@others
#@+node:ekr.20090529115704.4449: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4450: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4451: *6* @shadow-test delete between nodes: at start of next node
#@+node:ekr.20090529115704.4452: *7* old
@others
#@+node:ekr.20090529115704.4453: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4454: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4455: *7* new
@others
#@+node:ekr.20090529115704.4456: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4457: *8* node 2
node 2 line 2
#@+node:ekr.20090529115704.4458: *6* @shadow-test change end of prev node
#@+node:ekr.20090529115704.4459: *7* old
@others
#@+node:ekr.20090529115704.4460: *8* node 1
node 1 line 1
node 1 line 2
#@+node:ekr.20090529115704.4461: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4462: *7* new
@others
#@+node:ekr.20090529115704.4463: *8* node 1
node 1 line 1
node 1 line 1 changed
#@+node:ekr.20090529115704.4464: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4465: *6* @shadow-test change start of next node
#@+node:ekr.20090529115704.4466: *7* old
@others
#@+node:ekr.20090529115704.4467: *8* node 1
node 1 line 1
node 1 line 2
#@+node:ekr.20090529115704.4468: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4469: *7* new
@others
#@+node:ekr.20090529115704.4470: *8* node 1
node 1 line 1
node 1 line 2
#@+node:ekr.20090529115704.4471: *8* node 2
node 2 line 1 changed
node 2 line 2
#@+node:ekr.20090529115704.4472: *6* @shadow-test-lax multiple-line insert between nodes: at end of prev node
#@+node:ekr.20090529115704.4473: *7* old
@others
#@+node:ekr.20090529115704.4474: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4475: *8* node 2
node 2 line 1
#@+node:ekr.20090529115704.4476: *7* new
@others
#@+node:ekr.20090529115704.4477: *8* node 1
node 1 line 1
inserted node 1 at end of node 1
inserted node 2 at end of node 1
#@+node:ekr.20090529115704.4478: *8* node 2
node 2 line 1
#@+node:ekr.20090529115704.4479: *6* @shadow-test multiple-line insert between nodes: at start of next node
#@+node:ekr.20090529115704.4480: *7* old
@others
#@+node:ekr.20090529115704.4481: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4482: *8* node 2
node 2 line 1
#@+node:ekr.20090529115704.4483: *7* new
@others
#@+node:ekr.20090529115704.4484: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4485: *8* node 2
inserted node 1 at start of node 2
inserted node 2 at start of node 2
node 2 line 1
#@+node:ekr.20090529115704.4486: *6* @shadow-test multiple-line change end of prev node
#@+node:ekr.20090529115704.4487: *7* old
@others
#@+node:ekr.20090529115704.4488: *8* node 1
node 1 line 1
node 1 line 2
node 1 line 3
#@+node:ekr.20090529115704.4489: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4490: *7* new
@others
#@+node:ekr.20090529115704.4491: *8* node 1
node 1 line 1
node 1 line 2 changed
node 1 line 3 changed
#@+node:ekr.20090529115704.4492: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4493: *6* @shadow-test multiple-line change start of next node
#@+node:ekr.20090529115704.4494: *7* old
@others
#@+node:ekr.20090529115704.4495: *8* node 1
node 1 line 1
node 1 line 2
#@+node:ekr.20090529115704.4496: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4497: *7* new
@others
#@+node:ekr.20090529115704.4498: *8* node 1
node 1 line 1
node 1 line 2
#@+node:ekr.20090529115704.4499: *8* node 2
node 2 line 1 changed
node 2 line 2 changed
#@+node:ekr.20100107110353.5105: *6* @shadow-test NEW multiple-NODE changes
#@+node:ekr.20100107110353.5106: *7* old
@others
#@+node:ekr.20100107110353.5107: *8* node 1
node 1 line 1
node 1 line 2
#@+node:ekr.20100107110353.5108: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20100107110353.5109: *7* new
@others
#@+node:ekr.20100107110353.5110: *8* node 1
node 1 line 1
node 1 line 2 changed
#@+node:ekr.20100107110353.5111: *8* node 2
node 2 line 1 changed
node 2 line 2 changed
#@+node:ekr.20090529115704.4500: *6* @shadow-test multiple-line delete between nodes: at end of prev node
#@+node:ekr.20090529115704.4501: *7* old
@others
#@+node:ekr.20090529115704.4502: *8* node 1
node 1 line 1
node 1 line 2
node 1 line 3
#@+node:ekr.20090529115704.4503: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4504: *7* new
@others
#@+node:ekr.20090529115704.4505: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4506: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4507: *6* @shadow-test multiple-line delete between nodes: at start of next node
#@+node:ekr.20090529115704.4508: *7* old
@others
#@+node:ekr.20090529115704.4509: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4510: *8* node 2
node 2 line 1
node 2 line 2
node 2 line 3
#@+node:ekr.20090529115704.4511: *7* new
@others
#@+node:ekr.20090529115704.4512: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4513: *8* node 2
node 2 line 3
#@+node:ekr.20090529115704.4514: *6* @shadow-test verbatim sentinels-delete verbatim line
#@+node:ekr.20090529115704.4515: *7* old
@others
#@+node:ekr.20090529115704.4516: *8* node 1
node 1 line 1
@verbatim
@verbatim
@verbatim
@verbatim
#@verbatim
#@ should be handled by verbatim
line 1 line 3
#@+node:ekr.20090529115704.4517: *8* node 2
node 2 line 1
node 2 line 2
node 2 line 3
#@+node:ekr.20090529115704.4518: *7* new
@others
#@+node:ekr.20090529115704.4519: *8* node 1
node 1 line 1
line 1 line 3
#@+node:ekr.20090529115704.4520: *8* node 2
node 2 line 1
node 2 line 2
node 2 line 3
#@+node:ekr.20090529115704.4521: *6* @shadow-test verbatim sentinels-delete verbatim line: at start of node
#@+node:ekr.20090529115704.4522: *7* old
@others
#@+node:ekr.20090529115704.4523: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4524: *8* node 2
@verbatim
@verbatim
@verbatim
@verbatim
#@verbatim
#@ should be handled by verbatim
node 2 line 2
#@+node:ekr.20090529115704.4525: *7* new
@others
#@+node:ekr.20090529115704.4526: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4527: *8* node 2
node 2 line 2
#@+node:ekr.20090529115704.4528: *6* @shadow-test verbatim sentinels-no change
#@+node:ekr.20090529115704.4529: *7* old
@others
#@+node:ekr.20090529115704.4530: *8* node 1
node 1 line 1
@verbatim
@verbatim
@verbatim
@verbatim
#@verbatim
#@ should be handled by verbatim
line 1 line 3
#@+node:ekr.20090529115704.4531: *8* node 2
node 2 line 1
node 2 line 2
node 2 line 3
#@+node:ekr.20090529115704.4532: *7* new
@others
#@+node:ekr.20090529115704.4533: *8* node 1
node 1 line 1
@verbatim
@verbatim
@verbatim
@verbatim
#@verbatim
#@ should be handled by verbatim
line 1 line 3
#@+node:ekr.20090529115704.4534: *8* node 2
node 2 line 1
node 2 line 2
node 2 line 3
#@+node:ekr.20090529115704.4535: *6* @shadow-test verbatim sentinels-delete verbatim line: at end of node
#@+node:ekr.20090529115704.4536: *7* old
@others
#@+node:ekr.20090529115704.4537: *8* node 1
node 1 line 1
@verbatim
@verbatim
@verbatim
@verbatim
#@verbatim
#@ should be handled by verbatim
#@+node:ekr.20090529115704.4538: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4539: *7* new
@others
#@+node:ekr.20090529115704.4540: *8* node 1
node 1 line 1
#@+node:ekr.20090529115704.4541: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4542: *6* @shadow-test verbatim sentinels-add verbatim line
# This fails because the @all read logic inserts a second verbatim, I think.
#@+node:ekr.20090529115704.4543: *7* old
@others
#@+node:ekr.20090529115704.4544: *8* node 1
node 1 line 1
node 1 line 2
#@+node:ekr.20090529115704.4545: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20090529115704.4546: *7* new
@others
#@+node:ekr.20090529115704.4547: *8* node 1
node 1 line 1
@verbatim
#@verbatim
#@ should be handled by verbatim
node 1 line 2
#@+node:ekr.20090529115704.4548: *8* node 2
node 2 line 1
node 2 line 2
#@+node:ekr.20100131180007.5363: *4* @test class markerClass.getDelims
x = c.shadowController
table = (
    ('python','#',''),
    ('c','//',''),
    ('html','<!--','-->'),
    ('xxxx','#--unknown-language--',''),
)
for language,delim1,delim2 in table:
    delims = g.set_delims_from_language(language)
    marker = x.markerClass(delims)
    result = marker.getDelims()
    expected = delim1,delim2
    assert result==expected,'language %s expected %s got %s' % (
        language,expected,result)
#@+node:ekr.20100131180007.5362: *4* @test class markerClass.isSentinel
x = c.shadowController
table = (
    ('python','abc',False),
    ('python','#abc',False),
    ('python','#@abc',True),
    ('python','@abc#',False),
    ('c','abc',False),
    ('c','//@',True),
    ('c','// @abc',False),
    ('c','/*@ abc */',True),
    ('c','/*@ abc',False),
    ('html','#@abc',False),
    ('html','<!--abc-->',False),
    ('html','<!--@ abc -->',True),
    ('html','<!--@ abc ->',False),
    ('xxxx','#--unknown-language--@',True)
)
for language,s,expected in table:
    delims = g.set_delims_from_language(language)
    marker = x.markerClass(delims)
    result = marker.isSentinel(s)
    assert result==expected,'language %s s: %s expected %s got %s' % (
        language,s,expected,result)
#@+node:ekr.20100131180007.5361: *4* @test class markerClass.isVerbatimSentinel
x = c.shadowController
table = (
    ('python','abc',False),
    ('python','#abc',False),
    ('python','#verbatim',False),
    ('python','#@verbatim',True),
    ('c','abc',False),
    ('c','//@',False),
    ('c','//@verbatim',True),
    ('html','#@abc',False),
    ('html','<!--abc-->',False),
    ('html','<!--@verbatim -->',True),
    ('xxxx','#--unknown-language--@verbatim',True)
)
for language,s,expected in table:
    delims = g.set_delims_from_language(language)
    marker = x.markerClass(delims)
    result = marker.isVerbatimSentinel(s)
    assert result==expected,'language %s s: %s expected %s got %s' % (
        language,s,expected,result)
#@+node:ekr.20090529115704.4550: *4* @test x.baseDirName
x = c.shadowController

path = x.baseDirName()
expected = g.os_path_dirname(g.os_path_abspath(g.os_path_join(c.fileName())))

# print(path)
# print(expected)

assert path == expected,'\nexpected: %s\ngot     : %s' % (expected,path)
#@+node:ekr.20090529115704.4552: *4* @test x.dirName
x = c.shadowController

filename = 'xyzzy'
path = x.dirName(filename)
expected = g.os_path_dirname(g.os_path_abspath(
    g.os_path_join(g.os_path_dirname(c.fileName()),filename)))

# print(path)
# print(expected)

assert path == expected,'\nexpected: %s\ngot     : %s' % (expected,path)
#@+node:ekr.20100131180007.5366: *4* @test x.findAtLeoLine
x = c.shadowController
table = (
    ('c',('//@+leo','a'),                   '//@+leo'),
    ('c',('//@first','//@+leo','b'),        '//@+leo'),
    ('c',('/*@+leo*/','a'),                 '/*@+leo*/'),
    ('c',('/*@first*/','/*@+leo*/','b'),    '/*@+leo*/'),
    ('python',('#@+leo','a'),               '#@+leo'),
    ('python',('#@first','#@+leo','b'),     '#@+leo'),
    ('error',('',),''),
    ('html',('<!--@+leo-->','a'),                '<!--@+leo-->'),
    ('html',('<!--@first-->','<!--@+leo-->','b'),'<!--@+leo-->'),
)
for language,lines,expected in table:
    result = x.findLeoLine(lines)
    assert expected==result, 'language %s expected %s got %s lines %s' % (
        language,expected,result,'\n'.join(lines))
#@+node:ekr.20090529115704.4557: *4* @test x.makeShadowDirectory
import glob
import os

x = c.shadowController

@others

shadow_fn  = x.shadowPathName('unittest/xyzzy')
shadow_dir = x.shadowDirName('unittest/xyzzy')

if g.os_path_exists(shadow_fn):
    g.utils_remove(shadow_fn,verbose=True)
    assert not os.path.exists(shadow_fn),'still exists: %s' % shadow_fn

deleteShadowDir(shadow_dir)

x.makeShadowDirectory(shadow_dir)
assert os.path.exists(shadow_dir)

deleteShadowDir(shadow_dir)
#@+node:ekr.20090529115704.4558: *5* deleteShadowDir
def deleteShadowDir(shadowDir):

    if g.os_path_exists(shadow_dir):
        files = g.os_path_abspath(g.os_path_join(shadow_dir,"*.*"))
        files = glob.glob(files)
        for z in files:
            if z != shadow_dir:
                os.unlink(z)
        os.rmdir(shadow_dir)
        assert not os.path.exists(shadow_dir),'still exists: %s' % shadow_dir
#@+node:ekr.20100131180007.5365: *4* @test x.markerFromFileLines
x = c.shadowController
# Add -ver=4 so at.parseLeoSentinel does not complain.
table = (
    ('c',('//@+leo-ver=4','a'),                   '//',''),
    ('c',('//@first','//@+leo-ver=4','b'),        '//',''),
    ('c',('/*@+leo-ver=4*/','a'),                 '/*','*/'),
    ('c',('/*@first*/','/*@+leo-ver=4*/','b'),    '/*','*/'),
    ('python',('#@+leo-ver=4','a'),               '#',''),
    ('python',('#@first','#@+leo-ver=4','b'),     '#',''),
    ('error',('',),             '#--unknown-language--',''),
    ('html',('<!--@+leo-ver=4-->','a'),                '<!--','-->'),
    ('html',('<!--@first-->','<!--@+leo-ver=4-->','b'),'<!--','-->'),
)

for language,lines,delim1,delim2 in table:
    s = x.findLeoLine(lines)
    marker = x.markerFromFileLines(lines,'test-file-name')
    result1,result2 = marker.getDelims()
    assert delim1==result1, 'language %s expected1 %s got %s lines %s' % (
        language,delim1,result1,'\n'.join(lines))
    assert delim2==result2, 'language %s expected2 %s got %s lines %s' % (
        language,delim1,result1,'\n'.join(lines))
#@+node:ekr.20100131180007.5364: *4* @test x.markerFromFileName
x = c.shadowController

table = (
    ('ini',';','',),
    ('c','//',''),
    ('h','//',''),
    ('py','#',''),
    ('xyzzy','#--unknown-language--',''),
)

for ext,delim1,delim2 in table:
    filename = 'x.%s' % ext
    marker = x.markerFromFileName(filename)
    result1,result2 = marker.getDelims()
    assert delim1==result1, 'ext=%s, got %s, expected %s' % (
        ext,delim1,result1)
    assert delim2==result2, 'ext=%s, got %s, expected %s' % (
        ext,delim2,result2)
#@+node:ekr.20090529115704.4551: *4* @test x.pathName
x = c.shadowController

filename = 'xyzzy'

path = x.pathName(filename)
expected = g.os_path_abspath(g.os_path_join(x.baseDirName(),filename))

# print(path)
# print(expected)

assert path == expected,'\nexpected: %s\ngot     : %s' % (expected,path)
#@+node:ekr.20090529115704.4555: *4* @@test x.rename
if 0: # x.rename no longer exists
    x = c.shadowController

    filename = x.pathName('xyzzy')
    assert not g.os_path_exists(filename)
    n = x.errors
    x.rename('xyzzy','xyzzy2',silent=True)
    assert x.errors == n+1
    assert x.last_error.startswith('can not rename')
    # print(x.last_error)
#@+node:ekr.20090529115704.4559: *4* @test x.replaceFileWithString
x = c.shadowController
s = 'abc'

fn = '../test/unittest/replaceFileWithStringTestFile.py'
path = g.os_path_abspath(g.os_path_join(g.app.loadDir,fn))

x.replaceFileWithString(path,s)
f = open(path)
s2 = f.read()
f.close()
assert s == s2
#@+node:ekr.20100131180007.5367: *4* @test x.replaceFileWithString 2
c,p = g.getTestVars()
x = c.shadowController

fn = 'does/not/exist'
assert not g.os_path_exists(fn)
assert not x.replaceFileWithString (fn,'abc')
#@+node:ekr.20090529115704.4554: *4* @test x.shadowDirName
x = c.shadowController

subdir = c.config.getString('shadow_subdir') or '.leo_shadow'
prefix = c.config.getString('shadow_prefix') or ''

# print('c.fileName',c.fileName())
# print('c.relativeFileName',c.relativeFileName())

filename = 'xyzzy'
path = x.shadowDirName(filename)
expected = g.os_path_abspath(
    g.os_path_join(g.os_path_dirname(c.fileName()),subdir))

# print(path)
# print(expected)

assert path == expected,'\nexpected: %s\ngot     : %s' % (expected,path)
#@+node:ekr.20090529115704.4553: *4* @test x.shadowPathName
x = c.shadowController

# print(c.config.getString('shadow_subdir'))

subdir = c.config.getString('shadow_subdir') or '.leo_shadow'
prefix = c.config.getString('shadow_prefix') or ''

# print('c.fileName',c.fileName())
# print('c.relativeFileName',c.relativeFileName())

filename = 'xyzzy'
path = x.shadowPathName(filename)
expected = g.os_path_abspath(g.os_path_join(
    g.os_path_dirname(c.fileName()),subdir,prefix+filename))

if 0:
    print('prefix',prefix)
    print(path)
    print(expected)

assert path == expected,'\nexpected: %s\ngot     : %s' % (expected,path)
#@+node:ekr.20090529115704.4556: *4* @test x.unlink
x = c.shadowController

filename = x.pathName('xyzzy')
# print(filename)
assert not g.os_path_exists(filename)
n = x.errors
x.unlink('xyzzy',silent=True)
assert x.errors == n+1
assert x.last_error.startswith('can not delete xyzzy')
# print(x.last_error)
#@+node:ekr.20100131171342.5612: *3* leoTest
#@+node:ekr.20100131171342.5613: *4* @test unit testing with embedded class
def sendEmail(self):
    pass # g.trace('self2',self)

class test:
    pass

X = test()
sendEmail(X)
#@+node:ekr.20071113193729: *3* leoUndo
@

9 failures with Alt-5.

Any unit test that changes the structure of the outline should do the
following:

- The setUp method should do
    self.undoMark = c.undoer.getMark()
before altering the outline.

- The tearDown method should do
    c.undoer.rollBackToMark(self.undoMark)
after restoring the outline.

u.rollBackToMark deletes all entries in the undo stack following the saved mark.
This eliminates references to nodes that no longer exist in the present outline.
#@+node:ekr.20040712101754.37: *4* @suite Edit body tests
# Create unit tests in g.app.scriptDict["suite"]

import leo.core.leoTest as leoTest

g.app.enableUnitTest = True

suite = leoTest.makeEditBodySuite(c,p)

g.app.scriptDict['suite'] = suite
#@+node:ekr.20040712101754.38: *5* editBodyTests
@language plain

The names of child nodes are the names of commander methods to be called to do the test.

Each child node will in turn have two or more children:

- a "before" node
- an "after" node
- an optional selection node containing two lines giving the selection range in Tk coordinates.
- An optional insert node containing one line giving the insert point in Tk coordinates.
#@+node:ekr.20060127120604: *6* tempNode
#@+node:ekr.20050417202713: *6* addComments
#@+node:ekr.20050417202713.1: *7* before
@language python

def addCommentTest():

    if 1:
        a = 2
        b = 3

    pass
#@+node:ekr.20050417202713.2: *7* after
@language python

def addCommentTest():

    # if 1:
        # a = 2
        # b = 3

    pass
#@+node:ekr.20050417202713.3: *7* selection
5.0
7.8
#@+node:ekr.20050417204940: *6* convertAllBlanks
#@+node:ekr.20050417204940.1: *7* before
@tabwidth -4

line 1
    line 2
      line 3
line4
#@+node:ekr.20050417204940.2: *7* after
@tabwidth -4

line 1
	line 2
	  line 3
line4
#@+node:ekr.20050417204940.3: *7* selection
1.0
6.5
#@+node:ekr.20050417205012: *6* convertAllTabs
#@+node:ekr.20050417205012.1: *7* before
@tabwidth -4

line 1
	line 2
	  line 3
line4
#@+node:ekr.20050417205012.2: *7* after
@tabwidth -4

line 1
    line 2
      line 3
line4
#@+node:ekr.20050417205012.3: *7* selection
1.0
6.5
#@+node:ekr.20050417203114: *6* convertBlanks
#@+node:ekr.20050417203310: *7* before
@tabwidth -4

line 1
    line 2
      line 3
line4
#@+node:ekr.20050417203310.1: *7* after
@tabwidth -4

line 1
	line 2
	  line 3
line4
#@+node:ekr.20050417203336: *7* selection
1.0
6.5
#@+node:ekr.20050417203114.1: *6* convertTabs
#@+node:ekr.20050417204834: *7* before
@tabwidth -4

line 1
	line 2
	  line 3
line4
#@+node:ekr.20050417204830: *7* after
@tabwidth -4

line 1
    line 2
      line 3
line4
#@+node:ekr.20050417204901: *7* selection
1.0
6.5
#@+node:ekr.20040712101754.49: *6* dedentBody
#@+node:ekr.20040712101754.50: *7* before
line 1
    line 2
    line 3
line 4
#@+node:ekr.20040712101754.51: *7* after
line 1
line 2
line 3
line 4
#@+node:ekr.20040712101754.52: *7* selection
2.0
3.5
#@+node:ekr.20050417202817: *6* deleteComments
#@+node:ekr.20050417202817.1: *7* before
@language python

def deleteCommentTest():

    # if 1:
        # a = 2
        # b = 3

    pass
#@+node:ekr.20050417202817.2: *7* after
@language python

def deleteCommentTest():

    if 1:
        a = 2
        b = 3

    pass
#@+node:ekr.20050417202817.3: *7* selection
5.0
7.8
#@+node:ekr.20050417201845: *6* extract test1
#@+node:ekr.20050417201845.1: *7* before
before
    << section >>
    sec line 1
        sec line 2 indented
sec line 3
after
#@+node:ekr.20050417201845.2: *7* after
before
<< section >>
after
#@+node:ekr.20050417201845.3: *8* << section >> @nonl
sec line 1
    sec line 2 indented
sec line 3
#@+node:ekr.20050417201845.4: *7* selection
2.0
5.10
#@+node:ekr.20050518070540: *6* extract test2
#@+node:ekr.20050518070540.1: *7* before
before
    << section >>
    sec line 1
        sec line 2 indented
sec line 3
after
#@+node:ekr.20050518070545: *7* after
before
    << section >>
    sec line 1
        sec line 2 indented
sec line 3
after
#@+node:ekr.20050518070540.4: *7* selection
2.0
2.16
#@+node:ekr.20050518070927: *6* extractSection test1
#@+node:ekr.20050518070927.1: *7* before
before
    << section >>
    sec line 1
        sec line 2 indented
sec line 3
after
#@+node:ekr.20050518070927.2: *7* after
before
<< section >>
after
#@+node:ekr.20050518070927.3: *8* << section >> @nonl
sec line 1
    sec line 2 indented
sec line 3
#@+node:ekr.20050518070927.4: *7* selection
2.0
5.10
#@+node:ekr.20050518071251: *6* extractSection test2
#@+node:ekr.20050518071251.1: *7* before
before
    << section >>
    sec line 1
        sec line 2 indented
sec line 3
after
#@+node:ekr.20050518071258: *7* after
before
    << section >>
    sec line 1
        sec line 2 indented
sec line 3
after
#@+node:ekr.20050518071251.4: *7* selection
2.0
2.16
#@+node:ekr.20071113202510: *4* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.contractParent()
g.app.unitTestDict['restoreSelectedNode']=False

print('\nEnd of leoUndo tests.')
#@+node:ekr.20050120095423: ** Plugins
# Do this last.
#@+node:ekr.20110610082755.3362: *3*  qtGui.py
#@+node:ekr.20100131171342.5503: *4* @test c.vnode2position
trace = False

if trace: print('=' * 20)

for p in c.all_positions():

    p2 = c.vnode2position(p.v)

    if trace: print(p2.level(), p2.headString())

    # We can *not* assert that p == p2, only that
    # p2.v == p.v and c.positionExists(p2)
    assert p2
    assert p2.v == p.v,'p2.v: %s, p.v: %s' % (p2.v,v)
    assert c.positionExists(p2),'does not exist: %s' % p2
#@+node:ekr.20100131171342.5504: *4* @test position2Item
tree = c.frame.tree


c.redraw()

p = c.rootPosition()
while p:
    item = tree.position2item(p)
    v = tree.item2vnode(item)
    assert v == p.v, 'item2: %s, p.v: %s' % (item,p.v)
    p.moveToVisNext(c)
#@+node:ekr.20100131171342.5505: *4* @test item2position
def test_sibs(parent_p,parent_item):

    trace = False
    tree = c.frame.tree
    sib_items = tree.childItems(parent_item)
    sibs = [z.copy() for z in parent_p.self_and_siblings_iter()]

    assert len(sib_items) == len(sibs),(
        'child_items: %s, children: %s' % (
            g.listToString(sib_items),g.listToString(sibs)))

    for item,p in zip(sib_items,sibs):
        p2 = tree.item2position(item)
        if trace: print (id(item),p2 and p2.headString() or not p2 and '**None**')
        assert p == p2, 'item: %s, p: %s, p2: %s' % (id(item),p,p2)

        # Recursively test.
        child = p.firstChild()
        if child.isVisible(c):
            test_sibs(child,parent_item=item)

if hasattr(c.frame.tree,'item2position'):
    c.redraw()
    test_sibs(c.rootPosition(),None)
#@+node:ekr.20050120095423.11: *3* @suite import or test syntax of all plugins
'''Imports all plugins or just tests their syntax,
epending on a switch in PluginTestCase.runTest.'''

import leo.core.leoTest as leoTest
import glob
import sys
import unittest

@others

suite = makePluginsTestSuite(c)

g.app.scriptDict['suite'] = suite
#@+node:ekr.20050120095423.12: *4* makePluginsTestSuite
def makePluginsTestSuite(c):

    '''Create a plugin test for .py file in the plugins directory'''

    # Create the suite.
    suite = unittest.makeSuite(unittest.TestCase)

    # Add a test case for every plugin.
    plugins = g.os_path_join(g.app.loadDir,'..','plugins','*.py')
    plugins = g.os_path_abspath(plugins)
    files = glob.glob(plugins)
    files = [g.os_path_abspath(f) for f in files]
    files.sort()
    
    for fn in files:
        test = pluginTestCase(c,fn)
        # g.trace(test.shortDescription())
        suite.addTest(test)

    if 0:
        # Open a new window after all tests are completed.  Tests many plugins.
        lastTest = lastTestCase(c,openFlag=True)
        suite.addTest(lastTest)

    return suite
#@+node:ekr.20050120095423.13: *4* class pluginTestCase
class pluginTestCase(unittest.TestCase):

    '''A test case to test a single Leo plugin.'''

    @others
#@+node:ekr.20050120095423.14: *5* __init__
def __init__ (self,c,path):

    # Init the base class.
    unittest.TestCase.__init__(self)

    self.c = c
    self.path = path
#@+node:ekr.20050120095423.15: *5* fail
def fail (self,msg=None):

    """Mark a unit test as having failed."""

    g.app.unitTestDict["fail"] = g.callerName(2)
#@+node:ekr.20050120095423.16: *5* runTest
def runTest(self):
    
    import leo.core.leoTest as leoTest
    
    trace = False
    c = self.c ; path = self.path
    path,base = g.os_path_split(path)
    fn = base[:-3]
    
    ignore = (
        # Unfinished/obsolute gui's.
        'gtkDialogs','gtkGui','ironPython','ironPythonGui',
        'swing_gui','tkGui','wxGui','temacs',
        # Tk-only.
        'ipython',
        # Imports path & win32clipboard.
        'at_view',
        # Experimental.
        'stickynotes_plus',
        # Generated by unit tests.
        'pluginsTest',
        # Imports non-standard modules.
        'interact',         # import pexpect
        'jinjarender',      # import jinga2
        'leofeeds',         # import feedparser
    )

    if fn in ignore:
        return
    
    if trace: g.trace(fn)
    
    if 1:
        # Just check the syntax.  Doesn't pollute other unit tests.
        f = open(self.path,'r')
        s = f.read()
        f.close
        assert leoTest.checkFileSyntax(fn,s,reraise=False,suppress=False)
    else: # Good for initial tests, but pollutes all other unit tests.
        exec('import leo.plugins.%s' % fn)
    
#@+node:ekr.20050120095423.17: *5* setUp
def setUp(self):

    g.app.unitTestDict = {}
#@+node:ekr.20050120095423.18: *5* shortDescription
def shortDescription (self):

    return "pluginTestCase: %s" % g.shortFileName(self.path)
#@+node:ekr.20050120095423.20: *4* class lastTestCase
class lastTestCase(unittest.TestCase):

    '''A test case to print a message at the end of plugin tests.'''

    def __init__ (self,c,openFlag):
        # Init the base class.
        unittest.TestCase.__init__(self)
        self.c = c
        self.openFlag = openFlag

    def runTest(self):
        c = self.c
        print('\n%s a new window to test more plugin logic\n' % g.choose(
            self.openFlag,'opening','open'))
        if self.openFlag:
            self.new_c = new_c = c.new() # Create the new window.
            new_c.frame.setTitle("unit test for 'new' hook")

    if 0: # Doesn't work
        def shutDown(self):
            c = self.new_c
            c.close()
#@+node:ekr.20050218015346: *3* @@suite run all plugin test routines
# This test, if run at all, should be run elsewhere:
# Actually importing plugins affects other unit tests.

import glob
import inspect
import unittest

changed = c.isChanged() ; p1 = c.p
<< class testRoutineTestCase >>
@others

plugins = getAllPlugins()

# g.printList(plugins)

print('@suite run all plugin test routines')

if 1:
    g.app.unitTestDict["fail"] = False
    suite = unittest.makeSuite(unittest.TestCase)
    for plugin in plugins:
        n = addTestRoutinesInPluginToSuite(c,g,plugin,suite)
        if n:
            plural = g.choose(n==1,'','s')
            s = 'found %2d test routine%s for %s' % (n,plural,plugin)
            g.es_print(s)
    if 1: # For @suite nodes.  Better for unit testing.
        g.app.scriptDict['suite'] = suite
    else: # For script button nodes.  Good for testing.
        # Verbosity: 1: print just dots.
        unittest.TextTestRunner(verbosity=1).run(suite)
        c.setChanged(changed) # Restore changed state.
        c.selectVnode(p1) # N.B. Restore the selected node.
#@+node:ekr.20050218015346.11: *4* << class testRoutineTestCase >>
class testRoutineTestCase(unittest.TestCase):

    """Create a unit test from a snippet of code."""

    @others
#@+node:ekr.20050218015346.12: *5* __init__
def __init__ (self,c,g,moduleName,theClass,f,code,verbose=False):

     # Init the base class.
    unittest.TestCase.__init__(self)

    self.c = c
    self.moduleName = moduleName
    self.theClass = theClass
    self.f = f
    self.g = g
    self.code = code
    self.p = c.p.copy()
    self.verbose = verbose
#@+node:ekr.20050218015346.13: *5*  fail
def fail (self,msg=None):

    """Mark a unit test as having failed."""

    g.app.unitTestDict["fail"] = g.callerName(2)
#@+node:ekr.20050218015346.16: *5* runTest
def runTest (self):

    f = self.f ; name = f.__name__ ; theClass = self.theClass

    d = {'c':self.c,'g':self.g,'p':self.p}

    if 1: # Use dead text to ensure a clean environment.
        # The present code assumes all leading whitespace is consistent.
        code = removeLeadingWs(self.code)
        # The code is a def statement.  We concoct a call to the function or method.
        if theClass:
            s = '%s\n%s(self=None)\n' % (code,name)
        else:
            s = '%s\n%s()\n' % (code,name)

        if self.verbose:
            g.trace('executing...\n\n%s' % s)

        exec(s,d) # Execute s in a environment containing c, g and p.

    else: # Use live objects.
        if theClass:
            # Create a subclass of f's original class.
            class __dummyClass(theClass):
                # Create a ctor with a known signature.
                def __init__(self): pass
            # Make f a method of the dummyClass with name 'f'.
            # N.B. f is still a method of theClass, and must be called as such!
            if 0: # Override the method with f's actual name.
                g.funcToMethod(f,__dummyClass,name)
                obj = __dummyClass()
                f = getattr(obj,name)
                f(obj)
            else:
                # Use the name 'f' for f's name.
                g.funcToMethod(f,__dummyClass,'f')
                # Create an instance of __dummyClass and call it's f method.
                obj = __dummyClass()
                obj.f()
        else: # Execute a plain function.
            f(**keys)
#@+node:ekr.20050218015346.17: *5* shortDescription
def shortDescription (self):

    return 'test function',repr(self.f)
#@+node:ekr.20050218015346.18: *4* addTestRoutinesInPluginToSuite
def addTestRoutinesInPluginToSuite (c,g,pluginName,suite):

    path = g.os_path_abspath(g.os_path_join(g.app.loadDir,"..","plugins"))

    plugin = g.importFromPath(pluginName,path,verbose=True)
    if not plugin:
        return len([])

    tests = findTestsInModule(plugin,pluginName)

    for test in tests:
        theClass,f = test
        code = inspect.getsource(f)
        testCase = testRoutineTestCase(c,g,pluginName,theClass,f,code,verbose=False)
        suite.addTest(testCase)

    return len(tests)
#@+node:ekr.20050218015346.19: *4* findTestsInModule
def findTestsInModule (module,moduleName):

    # g.trace(moduleName)

    toString = g.listToString
    try:
        functions = inspect.getmembers(module,inspect.isfunction)
    except Exception:
        g.trace('Exception in inspect.getmembers(module,inspect.isfunction) for %s' % moduleName)
        functions = []
    try:
        classes = inspect.getmembers(module,inspect.isclass)
    except Exception:
        g.trace('Exception in inspect.getmembers(module,inspect.isclass) for %s' % moduleName)
        classes = []

    # Ignore subclasses of TestCase.
    classes = [theClass for className,theClass in classes
        if not issubclass(theClass,unittest.TestCase)]

    allMethods = []
    for theClass in classes:
        try:
            methods = inspect.getmembers(theClass,inspect.ismethod)
        except Exception:
            # This looks like a bug in inspect: The zodb classes have no methods.
            # g.trace('Exception in inspect.getmembers(theClass,inspect.ismethod) for %s' % moduleName)
            methods = []
        # print('\nmethods of class %s...\n\n%s' % (theClass,toString(methods)))
        methods = [(theClass,f) for name,f in methods if name.startswith('test_')]
        allMethods.extend(methods)

    # Hack: remove duplicate tests from leoGlobals.py.
    functions = [(None,f) for name,f in functions
        if name.startswith('test_') and not name.startswith('test_g_')]

    if 0:
        << print classes, methods & functions >>

    result = functions
    result.extend(allMethods)
    return result
#@+node:ekr.20050218015346.20: *5* << print classes, methods & functions >>
print('=' * 40)

if classes:
    print('classes in %s...\n%s' % (moduleName,toString(classes)))
else:
    print('no classes in %s' % (moduleName))
if allMethods:
    print('test methods in %s...\n%s'   % (moduleName,toString(allMethods)))
else:
    print('no test methods in %s' % (moduleName))
if functions:
    print('test functions in %s...\n%s' % (moduleName,toString(functions)))
else:
    print('no test functions in %s' % (moduleName))
#@+node:ekr.20050218015346.22: *4* removeLeadingWs
def removeLeadingWs (code):

    if not code.strip():
        return ''

    lines = g.splitLines(code)
    line = lines[0]
    i = g.skip_ws(line,0)
    ws = line[0:i]
    if not ws:
        return code
    result = [] ; n = len(ws)
    for line in lines:
        if line.startswith(ws):
            result.append(line[n:])
        elif not line.strip() and line.endswith('\n'):
            result.append('\n')
        else:
            print('unitTest.leo:underindented line:%s' % repr(line))
            result.append(line)

    # g.trace(g.listToString(result))

    result = ''.join(result)
    return result
#@+node:ekr.20100131171342.5497: *3* @test dectect_urls.py
import leo.plugins.detect_urls as detect_urls

w = c.frame.body.bodyCtrl
s = w.getAllText()
if s.endswith('\n'): s = s[:-1]
w.setInsertPoint(len(s))
url = detect_urls.openURL(tag='test',keywords={'c':c})
assert url == 'http://webpages.charter.net/edreamleo/front.html','Got:%s' % repr(url)

@ The last line is the url
http://webpages.charter.net/edreamleo/front.html
#@+node:ekr.20100131171342.5500: *3* @test macros.parameterize
import leo.plugins.macros as macros

controller = macros.paramClass(c)
controller.parameterize()
    # Not much will happen because there are no children.
    # However, this does test recent changes.
#@+node:ekr.20100131171342.5501: *3* @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.
import leo.core.leoTest as leoTest
u = leoTest.testUtils(c) # This *is* used

c.contractAllHeadlines()
h = 'All unit tests'
p = u.findNodeAnywhere(h)
if p:
    p.expand()
    g.app.unitTestDict['restoreSelectedNode']=False
    c.selectPosition(p)
    c.redraw()

print('\nEnd of plugins unit tests')
#@+node:ekr.20090306091634.1: ** @test print redraw count
tree = c.frame.tree
if hasattr(tree,'redrawCount'):
    print('tree.redrawCount:',tree.redrawCount)
#@+node:ekr.20081111150402.11: ** @test zz restore the screen
# This is **not** a real unit test.
# It simply restores the screen to a more convenient state.

c.selectPosition(p)
c.contractParent()
c.selectPosition(p.parent())
### c.save() # Only good way to save the present expansion/selection state.
g.app.unitTestDict['restoreSelectedNode']=False
c.bodyWantsFocus()

# Print does not work: it is redirected.
g.es('all unit tests done',color='blue')
#@-all
#@-leo
