summaryrefslogtreecommitdiffstats
path: root/runtime/indent/testdir
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/indent/testdir')
-rw-r--r--runtime/indent/testdir/README.txt97
-rw-r--r--runtime/indent/testdir/bitbake.in19
-rw-r--r--runtime/indent/testdir/bitbake.ok19
-rw-r--r--runtime/indent/testdir/html.in77
-rw-r--r--runtime/indent/testdir/html.ok77
-rw-r--r--runtime/indent/testdir/krl.in148
-rw-r--r--runtime/indent/testdir/krl.ok148
-rw-r--r--runtime/indent/testdir/matlab.in89
-rw-r--r--runtime/indent/testdir/matlab.ok89
-rw-r--r--runtime/indent/testdir/python.in94
-rw-r--r--runtime/indent/testdir/python.ok94
-rw-r--r--runtime/indent/testdir/runtest.vim145
-rw-r--r--runtime/indent/testdir/sshconfig.in53
-rw-r--r--runtime/indent/testdir/sshconfig.ok53
-rw-r--r--runtime/indent/testdir/tcl.in19
-rw-r--r--runtime/indent/testdir/tcl.ok19
-rw-r--r--runtime/indent/testdir/vb.in134
-rw-r--r--runtime/indent/testdir/vb.ok134
-rw-r--r--runtime/indent/testdir/vim.in941
-rw-r--r--runtime/indent/testdir/vim.ok941
-rw-r--r--runtime/indent/testdir/xml.in32
-rw-r--r--runtime/indent/testdir/xml.ok32
-rw-r--r--runtime/indent/testdir/yaml.in20
-rw-r--r--runtime/indent/testdir/yaml.ok20
24 files changed, 3494 insertions, 0 deletions
diff --git a/runtime/indent/testdir/README.txt b/runtime/indent/testdir/README.txt
new file mode 100644
index 0000000..6597560
--- /dev/null
+++ b/runtime/indent/testdir/README.txt
@@ -0,0 +1,97 @@
+TESTING INDENT SCRIPTS
+
+We'll use FILETYPE for the filetype name here.
+
+
+FORMAT OF THE FILETYPE.IN FILE
+
+First of all, create a FILETYPE.in file. It should contain:
+
+- A modeline setting the 'filetype' and any other option values.
+ This must work like a comment for FILETYPE. E.g. for vim:
+ " vim: set ft=vim sw=4 :
+
+- At least one block of lines to indent, prefixed with START_INDENT and
+ followed by END_INDENT. These lines must also look like a comment for your
+ FILETYPE. You would normally leave out all indent, so that the effect of
+ the indent command results in adding indent. Example:
+
+ " START_INDENT
+ func Some()
+ let x = 1
+ endfunc
+ " END_INDENT
+
+ If you just want to test normal indenting with default options, you can make
+ this a large number of lines. Just add all kinds of language constructs,
+ nested statements, etc. with valid syntax.
+
+- Optionally, add lines with INDENT_EXE after START_INDENT, followed by a Vim
+ command. This will be executed before indenting the lines. Example:
+
+ " START_INDENT
+ " INDENT_EXE let g:vim_indent_cont = 6
+ let cmd =
+ \ 'some '
+ \ 'string'
+ " END_INDENT
+
+ Note that the command is not undone, you may need to reverse the effect for
+ the next block of lines.
+
+- Alternatively to indenting all the lines between START_INDENT and
+ END_INDENT, use an INDENT_AT line, which specifies a pattern to find the
+ line to indent. Example:
+
+ " START_INDENT
+ " INDENT_AT this-line
+ func Some()
+ let f = x " this-line
+ endfunc
+ " END_INDENT
+
+ Alternatively you can use INDENT_NEXT to indent the line below the matching
+ pattern. Keep in mind that quite often it will indent relative to the
+ matching line:
+
+ " START_INDENT
+ " INDENT_NEXT next-line
+ func Some()
+ " next-line
+ let f = x
+ endfunc
+ " END_INDENT
+
+ Or use INDENT_PREV to indent the line above the matching pattern:
+
+ " START_INDENT
+ " INDENT_PREV prev-line
+ func Some()
+ let f = x
+ " prev-line
+ endfunc
+ " END_INDENT
+
+It's best to keep the whole file valid for FILETYPE, so that syntax
+highlighting works normally, and any indenting that depends on the syntax
+highlighting also works.
+
+
+RUNNING THE TEST
+
+Before running the test, create a FILETYPE.ok file. You can leave it empty at
+first.
+
+Now run "make test" from the parent directory. After Vim has done the
+indenting you will see a FILETYPE.fail file. This contains the actual result
+of indenting, and it's different from the FILETYPE.ok file.
+
+Check the contents of the FILETYPE.fail file. If it is perfectly OK, then
+rename it to overwrite the FILETYPE.ok file. If you now run "make test" again,
+the test will pass and create a FILETYPE.out file, which is identical to the
+FILETYPE.ok file. The FILETYPE.fail file will be deleted.
+
+If you try to run "make test" again you will notice that nothing happens,
+because the FILETYPE.out file already exists. Delete it, or do "make clean",
+so that the text runs again. If you edit the FILETYPE.in file, so that it's
+newer than the FILETYPE.out file, the test will also run.
diff --git a/runtime/indent/testdir/bitbake.in b/runtime/indent/testdir/bitbake.in
new file mode 100644
index 0000000..afd19be
--- /dev/null
+++ b/runtime/indent/testdir/bitbake.in
@@ -0,0 +1,19 @@
+# vim: set filetype=bitbake :
+
+# START_INDENT
+FOO = " \
+ bar \
+ baz \
+ qux \
+ "
+
+do_configure() {
+oe_conf
+}
+
+python do_task() {
+def foo(x):
+if y:
+print(x)
+}
+# END_INDENT
diff --git a/runtime/indent/testdir/bitbake.ok b/runtime/indent/testdir/bitbake.ok
new file mode 100644
index 0000000..1bc5a18
--- /dev/null
+++ b/runtime/indent/testdir/bitbake.ok
@@ -0,0 +1,19 @@
+# vim: set filetype=bitbake :
+
+# START_INDENT
+FOO = " \
+ bar \
+ baz \
+ qux \
+"
+
+do_configure() {
+ oe_conf
+}
+
+python do_task() {
+ def foo(x):
+ if y:
+ print(x)
+}
+# END_INDENT
diff --git a/runtime/indent/testdir/html.in b/runtime/indent/testdir/html.in
new file mode 100644
index 0000000..4783a09
--- /dev/null
+++ b/runtime/indent/testdir/html.in
@@ -0,0 +1,77 @@
+% vim: set ft=html sw=4 ts=8 :
+
+
+% START_INDENT
+<html>
+ <body>
+<style>
+div#d1 { color: red; }
+div#d2 { color: green; }
+</style>
+ <script>
+ var v1 = "v1";
+var v2 = "v2";
+ </script>
+<div>
+<div>
+text
+</div>
+</div>
+
+<div
+class="foo bar">
+text
+</div>
+
+<div class="foo bar"
+data="something">
+text
+</div>
+
+<div class="foo
+bar">
+text
+</div>
+
+<dl>
+<dd>
+dd text
+</dd>
+<dt>
+dt text
+</dt>
+</dl>
+<div
+class="test"
+style="color: yellow">
+text
+</div>
+
+ </body>
+</html>
+
+% END_INDENT
+
+% START_INDENT
+% INDENT_EXE let g:html_indent_style1 = "inc"
+% INDENT_EXE let g:html_indent_script1 = "zero"
+% INDENT_EXE let g:html_indent_attribute = 1
+% INDENT_EXE call HtmlIndent_CheckUserSettings()
+<html>
+ <body>
+<style>
+div#d1 { color: red; }
+div#d2 { color: green; }
+</style>
+ <script>
+ var v1 = "v1";
+var v2 = "v2";
+ </script>
+<div
+class="test"
+style="color: yellow">
+text
+</div>
+</body>
+</html>
+% END_INDENT
diff --git a/runtime/indent/testdir/html.ok b/runtime/indent/testdir/html.ok
new file mode 100644
index 0000000..4963634
--- /dev/null
+++ b/runtime/indent/testdir/html.ok
@@ -0,0 +1,77 @@
+% vim: set ft=html sw=4 ts=8 :
+
+
+% START_INDENT
+<html>
+ <body>
+ <style>
+div#d1 { color: red; }
+div#d2 { color: green; }
+ </style>
+ <script>
+ var v1 = "v1";
+ var v2 = "v2";
+ </script>
+ <div>
+ <div>
+ text
+ </div>
+ </div>
+
+ <div
+ class="foo bar">
+ text
+ </div>
+
+ <div class="foo bar"
+ data="something">
+ text
+ </div>
+
+ <div class="foo
+ bar">
+ text
+ </div>
+
+ <dl>
+ <dd>
+ dd text
+ </dd>
+ <dt>
+ dt text
+ </dt>
+ </dl>
+ <div
+ class="test"
+ style="color: yellow">
+ text
+ </div>
+
+ </body>
+</html>
+
+% END_INDENT
+
+% START_INDENT
+% INDENT_EXE let g:html_indent_style1 = "inc"
+% INDENT_EXE let g:html_indent_script1 = "zero"
+% INDENT_EXE let g:html_indent_attribute = 1
+% INDENT_EXE call HtmlIndent_CheckUserSettings()
+<html>
+ <body>
+ <style>
+ div#d1 { color: red; }
+ div#d2 { color: green; }
+ </style>
+ <script>
+var v1 = "v1";
+var v2 = "v2";
+ </script>
+ <div
+ class="test"
+ style="color: yellow">
+ text
+ </div>
+ </body>
+</html>
+% END_INDENT
diff --git a/runtime/indent/testdir/krl.in b/runtime/indent/testdir/krl.in
new file mode 100644
index 0000000..ec90feb
--- /dev/null
+++ b/runtime/indent/testdir/krl.in
@@ -0,0 +1,148 @@
+; vim: set ft=krl :
+
+; START_INDENT
+
+def One()
+int i
+If i==1 then
+While i>=1
+For i=1 to 5 step 2
+Loop
+i = i+1
+EndLoop
+EndFor
+EndWhile
+Else
+Repeat
+Switch i
+Case 1
+Skip 123
+i = i+1
+EndSkip 123
+Spline with $acc=100, $vel.cp=3
+slin {x 100}
+scirc {x 110, y 110}, {x 120, y 90}
+slin {x 200} c_dis
+Time_Block Start
+slin {x 300} c_dis
+Time_Block Part = 22.2
+slin {y 400} c_dis
+Time_Block Part = 33.3
+Time_Block End = 10
+slin {y 200} c_dis
+Const_Vel Start +100 OnStart
+slin {y 300} c_dis
+slin {x 100}
+Const_Vel End -5.5
+slin {y 200} c_dis
+EndSpline
+Case 2,3
+PTP_Spline with $acc=100, $vel.ptp=100
+sptp {a1 0} c_ptp
+sptp {a1 90}
+EndSpline c_spl
+Default
+i = i+1
+EndSwitch
+Continue
+Until False
+EndIf
+end
+
+DEF Two()
+int i
+END
+
+global def Three()
+int i
+end
+
+GLOBAL DEF Four()
+int i
+END
+
+Global Def Five()
+int i
+End
+
+deffct bool fOne()
+int i
+endfct
+
+DEFFCT bool fTwo()
+int i
+ENDFCT
+
+global deffct bool fThree()
+int i
+endfct
+
+GLOBAL DEFFCT bool fFour()
+int i
+ENDFCT
+
+Global DefFct bool fFive()
+int i
+EndFct
+
+DefDat datfile()
+global int i=1
+; don't indent column 1 comments unless g:krlCommentIndent is set
+; global int o=2
+EndDat
+
+; END_INDENT
+
+; START_INDENT
+; INDENT_EXE let g:krlSpaceIndent = 0
+; INDENT_EXE set shiftwidth=4
+
+def bla()
+int i
+end
+
+; END_INDENT
+
+; START_INDENT
+; INDENT_EXE let g:krlCommentIndent = 1
+def bla()
+; indent this first column comment because of g:krlCommentIndent=1
+end
+; END_INDENT
+
+; START_INDENT
+; INDENT_EXE let g:krlIndentBetweenDef = 0
+def bla()
+int i ; don't indent this line because of g:krlIndentBetweenDef=0
+end
+; END_INDENT
+
+; START_INDENT
+; INDENT_AT this-line
+def Some()
+int f
+if true then
+f = 1 ; this-line
+endif
+end
+; END_INDENT
+
+; START_INDENT
+; INDENT_NEXT next-line
+def Some()
+ int i
+ ; next-line
+i = 1 ; should get indent of line 'int i' above
+end
+; END_INDENT
+
+; START_INDENT
+; INDENT_PREV prev-line
+def Some()
+int f
+if true then
+f = 1
+; prev-line
+endif
+end
+; END_INDENT
diff --git a/runtime/indent/testdir/krl.ok b/runtime/indent/testdir/krl.ok
new file mode 100644
index 0000000..34dc0f5
--- /dev/null
+++ b/runtime/indent/testdir/krl.ok
@@ -0,0 +1,148 @@
+; vim: set ft=krl :
+
+; START_INDENT
+
+def One()
+ int i
+ If i==1 then
+ While i>=1
+ For i=1 to 5 step 2
+ Loop
+ i = i+1
+ EndLoop
+ EndFor
+ EndWhile
+ Else
+ Repeat
+ Switch i
+ Case 1
+ Skip 123
+ i = i+1
+ EndSkip 123
+ Spline with $acc=100, $vel.cp=3
+ slin {x 100}
+ scirc {x 110, y 110}, {x 120, y 90}
+ slin {x 200} c_dis
+ Time_Block Start
+ slin {x 300} c_dis
+ Time_Block Part = 22.2
+ slin {y 400} c_dis
+ Time_Block Part = 33.3
+ Time_Block End = 10
+ slin {y 200} c_dis
+ Const_Vel Start +100 OnStart
+ slin {y 300} c_dis
+ slin {x 100}
+ Const_Vel End -5.5
+ slin {y 200} c_dis
+ EndSpline
+ Case 2,3
+ PTP_Spline with $acc=100, $vel.ptp=100
+ sptp {a1 0} c_ptp
+ sptp {a1 90}
+ EndSpline c_spl
+ Default
+ i = i+1
+ EndSwitch
+ Continue
+ Until False
+ EndIf
+end
+
+DEF Two()
+ int i
+END
+
+global def Three()
+ int i
+end
+
+GLOBAL DEF Four()
+ int i
+END
+
+Global Def Five()
+ int i
+End
+
+deffct bool fOne()
+ int i
+endfct
+
+DEFFCT bool fTwo()
+ int i
+ENDFCT
+
+global deffct bool fThree()
+ int i
+endfct
+
+GLOBAL DEFFCT bool fFour()
+ int i
+ENDFCT
+
+Global DefFct bool fFive()
+ int i
+EndFct
+
+DefDat datfile()
+ global int i=1
+; don't indent column 1 comments unless g:krlCommentIndent is set
+; global int o=2
+EndDat
+
+; END_INDENT
+
+; START_INDENT
+; INDENT_EXE let g:krlSpaceIndent = 0
+; INDENT_EXE set shiftwidth=4
+
+def bla()
+ int i
+end
+
+; END_INDENT
+
+; START_INDENT
+; INDENT_EXE let g:krlCommentIndent = 1
+def bla()
+ ; indent this first column comment because of g:krlCommentIndent=1
+end
+; END_INDENT
+
+; START_INDENT
+; INDENT_EXE let g:krlIndentBetweenDef = 0
+def bla()
+int i ; don't indent this line because of g:krlIndentBetweenDef=0
+end
+; END_INDENT
+
+; START_INDENT
+; INDENT_AT this-line
+def Some()
+int f
+if true then
+ f = 1 ; this-line
+endif
+end
+; END_INDENT
+
+; START_INDENT
+; INDENT_NEXT next-line
+def Some()
+ int i
+ ; next-line
+ i = 1 ; should get indent of line 'int i' above
+end
+; END_INDENT
+
+; START_INDENT
+; INDENT_PREV prev-line
+def Some()
+int f
+if true then
+ f = 1
+; prev-line
+endif
+end
+; END_INDENT
diff --git a/runtime/indent/testdir/matlab.in b/runtime/indent/testdir/matlab.in
new file mode 100644
index 0000000..b997ec8
--- /dev/null
+++ b/runtime/indent/testdir/matlab.in
@@ -0,0 +1,89 @@
+% vim: set ft=matlab sw=4 :
+
+% START_INDENT
+if true
+disp foo
+elseif false
+disp bar
+end
+% END_INDENT
+
+% START_INDENT
+try
+statements
+catch exception
+statements
+end
+% END_INDENT
+
+% START_INDENT
+if true, ...
+if true
+disp hello
+end
+end
+% END_INDENT
+
+% START_INDENT
+switch a
+case expr
+if true, foo; end
+disp hello
+otherwise
+disp bar
+end
+% END_INDENT
+
+% START_INDENT
+if true
+A(1:end - 1)
+C{1:end - 1}
+disp foo
+end
+% END_INDENT
+
+% START_INDENT
+A = [{
+}
+] ...
+disp foo
+disp bar
+% END_INDENT
+
+% START_INDENT
+if true
+% end
+%% end
+disp foo
+end
+% END_INDENT
+
+% START_INDENT
+% INDENT_EXE let b:MATLAB_function_indent = 0
+function foo
+disp foo
+function nested
+disp bar
+end
+end
+% END_INDENT
+
+% START_INDENT
+% INDENT_EXE let b:MATLAB_function_indent = 1
+function foo
+disp foo
+function nested
+disp bar
+end
+end
+% END_INDENT
+
+% START_INDENT
+% INDENT_EXE let b:MATLAB_function_indent = 2
+function foo
+disp foo
+function nested
+disp bar
+end
+end
+% END_INDENT
diff --git a/runtime/indent/testdir/matlab.ok b/runtime/indent/testdir/matlab.ok
new file mode 100644
index 0000000..df4e7b2
--- /dev/null
+++ b/runtime/indent/testdir/matlab.ok
@@ -0,0 +1,89 @@
+% vim: set ft=matlab sw=4 :
+
+% START_INDENT
+if true
+ disp foo
+elseif false
+ disp bar
+end
+% END_INDENT
+
+% START_INDENT
+try
+ statements
+catch exception
+ statements
+end
+% END_INDENT
+
+% START_INDENT
+if true, ...
+ if true
+ disp hello
+ end
+end
+% END_INDENT
+
+% START_INDENT
+switch a
+ case expr
+ if true, foo; end
+ disp hello
+ otherwise
+ disp bar
+end
+% END_INDENT
+
+% START_INDENT
+if true
+ A(1:end - 1)
+ C{1:end - 1}
+ disp foo
+end
+% END_INDENT
+
+% START_INDENT
+A = [{
+ }
+ ] ...
+ disp foo
+disp bar
+% END_INDENT
+
+% START_INDENT
+if true
+ % end
+ %% end
+ disp foo
+end
+% END_INDENT
+
+% START_INDENT
+% INDENT_EXE let b:MATLAB_function_indent = 0
+function foo
+disp foo
+ function nested
+ disp bar
+ end
+end
+% END_INDENT
+
+% START_INDENT
+% INDENT_EXE let b:MATLAB_function_indent = 1
+function foo
+disp foo
+ function nested
+ disp bar
+ end
+end
+% END_INDENT
+
+% START_INDENT
+% INDENT_EXE let b:MATLAB_function_indent = 2
+function foo
+ disp foo
+ function nested
+ disp bar
+ end
+end
+% END_INDENT
diff --git a/runtime/indent/testdir/python.in b/runtime/indent/testdir/python.in
new file mode 100644
index 0000000..57719ee
--- /dev/null
+++ b/runtime/indent/testdir/python.in
@@ -0,0 +1,94 @@
+# vim: set ft=python sw=4 et:
+
+# START_INDENT
+dict = {
+'a': 1,
+'b': 2,
+'c': 3,
+}
+# END_INDENT
+
+# START_INDENT
+# INDENT_EXE let [g:python_indent.open_paren, g:python_indent.closed_paren_align_last_line] = ['shiftwidth()', v:false]
+dict = {
+'a': 1,
+'b': 2,
+'c': 3,
+}
+# END_INDENT
+
+# START_INDENT
+# INDENT_EXE let g:python_indent.open_paren = 'shiftwidth() * 2'
+# INDENT_EXE syntax match pythonFoldMarkers /{{{\d*/ contained containedin=pythonComment
+# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx {{{1
+
+if True:
+pass
+# END_INDENT
+
+# START_INDENT
+open_paren_not_at_EOL(100,
+(200,
+300),
+400)
+
+open_paren_at_EOL(
+100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+(200,
+300),
+400)
+
+open_paren_at_EOL(
+100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+(200,
+300),
+400)
+
+open_paren_at_EOL(
+100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+(200,
+300),
+400)
+
+open_paren_at_EOL(
+100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+(200,
+300),
+400)
+
+open_paren_at_EOL(
+100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+(200,
+300),
+400)
+
+open_paren_at_EOL(
+100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+(200,
+300),
+400)
+
+open_paren_at_EOL(
+100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+(200,
+300),
+400)
+
+open_paren_at_EOL(
+100, 200, 300, 400)
+
+# END_INDENT
diff --git a/runtime/indent/testdir/python.ok b/runtime/indent/testdir/python.ok
new file mode 100644
index 0000000..f5ebbc2
--- /dev/null
+++ b/runtime/indent/testdir/python.ok
@@ -0,0 +1,94 @@
+# vim: set ft=python sw=4 et:
+
+# START_INDENT
+dict = {
+ 'a': 1,
+ 'b': 2,
+ 'c': 3,
+ }
+# END_INDENT
+
+# START_INDENT
+# INDENT_EXE let [g:python_indent.open_paren, g:python_indent.closed_paren_align_last_line] = ['shiftwidth()', v:false]
+dict = {
+ 'a': 1,
+ 'b': 2,
+ 'c': 3,
+}
+# END_INDENT
+
+# START_INDENT
+# INDENT_EXE let g:python_indent.open_paren = 'shiftwidth() * 2'
+# INDENT_EXE syntax match pythonFoldMarkers /{{{\d*/ contained containedin=pythonComment
+# xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx {{{1
+
+if True:
+ pass
+# END_INDENT
+
+# START_INDENT
+open_paren_not_at_EOL(100,
+ (200,
+ 300),
+ 400)
+
+open_paren_at_EOL(
+ 100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+ (200,
+ 300),
+ 400)
+
+open_paren_at_EOL(
+ 100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+ (200,
+ 300),
+ 400)
+
+open_paren_at_EOL(
+ 100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+ (200,
+ 300),
+ 400)
+
+open_paren_at_EOL(
+ 100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+ (200,
+ 300),
+ 400)
+
+open_paren_at_EOL(
+ 100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+ (200,
+ 300),
+ 400)
+
+open_paren_at_EOL(
+ 100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+ (200,
+ 300),
+ 400)
+
+open_paren_at_EOL(
+ 100, 200, 300, 400)
+
+open_paren_not_at_EOL(100,
+ (200,
+ 300),
+ 400)
+
+open_paren_at_EOL(
+ 100, 200, 300, 400)
+
+# END_INDENT
diff --git a/runtime/indent/testdir/runtest.vim b/runtime/indent/testdir/runtest.vim
new file mode 100644
index 0000000..fa4e16e
--- /dev/null
+++ b/runtime/indent/testdir/runtest.vim
@@ -0,0 +1,145 @@
+" Runs all the indent tests for which there is no .out file.
+"
+" Current directory must be runtime/indent.
+
+" Only do this with the +eval feature
+if 1
+
+set nocp
+filetype indent on
+syn on
+set nowrapscan
+set report=9999
+set modeline
+set debug=throw
+
+au! SwapExists * call HandleSwapExists()
+func HandleSwapExists()
+ " Ignore finding a swap file for the test input and output, the user might be
+ " editing them and that's OK.
+ if expand('<afile>') =~ '.*\.\(in\|out\|fail\|ok\)'
+ let v:swapchoice = 'e'
+ endif
+endfunc
+
+let failed_count = 0
+for fname in glob('testdir/*.in', 1, 1)
+ let root = substitute(fname, '\.in', '', '')
+
+ " Execute the test if the .out file does not exist of when the .in file is
+ " newer.
+ let in_time = getftime(fname)
+ let out_time = getftime(root . '.out')
+ if out_time < 0 || in_time > out_time
+ call delete(root . '.fail')
+ call delete(root . '.out')
+
+ set sw& ts& filetype=
+ exe 'split ' . fname
+
+ let did_some = 0
+ let failed = 0
+ let end = 1
+ while 1
+ " Indent all the lines between "START_INDENT" and "END_INDENT"
+ exe end
+ let start = search('\<START_INDENT\>')
+ let end = search('\<END_INDENT\>')
+ if start <= 0 || end <= 0 || end <= start
+ if did_some == 0
+ call append(0, 'ERROR: START_INDENT and/or END_INDENT not found')
+ let failed = 1
+ endif
+ break
+ else
+ let did_some = 1
+
+ " Execute all commands marked with INDENT_EXE and find any pattern.
+ let lnum = start
+ let pattern = ''
+ let at = ''
+ while 1
+ exe lnum + 1
+ let lnum_exe = search('\<INDENT_EXE\>')
+ exe lnum + 1
+ let indent_at = search('\<INDENT_\(AT\|NEXT\|PREV\)\>')
+ if lnum_exe > 0 && lnum_exe < end && (indent_at <= 0 || lnum_exe < indent_at)
+ exe substitute(getline(lnum_exe), '.*INDENT_EXE', '', '')
+ let lnum = lnum_exe
+ let start = lnum
+ elseif indent_at > 0 && indent_at < end
+ if pattern != ''
+ call append(indent_at, 'ERROR: duplicate pattern')
+ let failed = 1
+ break
+ endif
+ let text = getline(indent_at)
+ let pattern = substitute(text, '.*INDENT_\S*\s*', '', '')
+ let at = substitute(text, '.*INDENT_\(\S*\).*', '\1', '')
+ let lnum = indent_at
+ let start = lnum
+ else
+ break
+ endif
+ endwhile
+
+ exe start + 1
+ if pattern == ''
+ try
+ exe 'normal =' . (end - 1) . 'G'
+ catch
+ call append(indent_at, 'ERROR: ' . v:exception)
+ let failed = 1
+ endtry
+ else
+ let lnum = search(pattern)
+ if lnum <= 0
+ call append(indent_at, 'ERROR: pattern not found: ' . pattern)
+ let failed = 1
+ break
+ endif
+ if at == 'AT'
+ exe lnum
+ elseif at == 'NEXT'
+ exe lnum + 1
+ else
+ exe lnum - 1
+ endif
+ try
+ normal ==
+ catch
+ call append(indent_at, 'ERROR: ' . v:exception)
+ let failed = 1
+ endtry
+ endif
+ endif
+ endwhile
+
+ if !failed
+ " Check the resulting text equals the .ok file.
+ if getline(1, '$') != readfile(root . '.ok')
+ let failed = 1
+ endif
+ endif
+
+ if failed
+ let failed_count += 1
+ exe 'write ' . root . '.fail'
+ echoerr 'Test ' . fname . ' FAILED!'
+ else
+ exe 'write ' . root . '.out'
+ echo "Test " . fname . " OK\n"
+ endif
+
+ quit! " close the indented file
+ endif
+endfor
+
+" Matching "if 1" at the start.
+endif
+
+if failed_count > 0
+ " have make report an error
+ cquit
+endif
+qall!
diff --git a/runtime/indent/testdir/sshconfig.in b/runtime/indent/testdir/sshconfig.in
new file mode 100644
index 0000000..87b998e
--- /dev/null
+++ b/runtime/indent/testdir/sshconfig.in
@@ -0,0 +1,53 @@
+# vim: set filetype=sshconfig shiftwidth=4 expandtab :
+
+# START_INDENT
+Host myhost
+User myuser
+PasswordAuthentication no
+# END_INDENT
+
+# START_INDENT
+Host aaa
+User bbb
+Host ccc
+Host ddd
+# END_INDENT
+
+# START_INDENT
+host aaa
+HOST bbb
+hoSt ccc
+match ddd
+MATCH eee
+MatCH fff
+# END_INDENT
+
+# START_INDENT
+Host aaa
+User host
+PasswordAuthentication no
+Host *
+User user
+PasswordAuthentication no
+Host match
+User bbb
+# END_INDENT
+
+# START_INDENT
+Host tab
+User myuser
+# END_INDENT
+
+# START_INDENT
+Host mix
+User myuser
+# END_INDENT
+
+# START_INDENT
+Host aaa
+User bbb
+Match ccc
+User ddd
+HostKeyAlgorithms ssh-ed25519
+Match eee
+# END_INDENT
diff --git a/runtime/indent/testdir/sshconfig.ok b/runtime/indent/testdir/sshconfig.ok
new file mode 100644
index 0000000..b24b7cf
--- /dev/null
+++ b/runtime/indent/testdir/sshconfig.ok
@@ -0,0 +1,53 @@
+# vim: set filetype=sshconfig shiftwidth=4 expandtab :
+
+# START_INDENT
+Host myhost
+ User myuser
+ PasswordAuthentication no
+# END_INDENT
+
+# START_INDENT
+Host aaa
+ User bbb
+Host ccc
+Host ddd
+# END_INDENT
+
+# START_INDENT
+host aaa
+HOST bbb
+hoSt ccc
+match ddd
+MATCH eee
+MatCH fff
+# END_INDENT
+
+# START_INDENT
+Host aaa
+ User host
+ PasswordAuthentication no
+Host *
+ User user
+ PasswordAuthentication no
+Host match
+ User bbb
+# END_INDENT
+
+# START_INDENT
+Host tab
+ User myuser
+# END_INDENT
+
+# START_INDENT
+Host mix
+ User myuser
+# END_INDENT
+
+# START_INDENT
+Host aaa
+ User bbb
+Match ccc
+ User ddd
+ HostKeyAlgorithms ssh-ed25519
+Match eee
+# END_INDENT
diff --git a/runtime/indent/testdir/tcl.in b/runtime/indent/testdir/tcl.in
new file mode 100644
index 0000000..c769d5b
--- /dev/null
+++ b/runtime/indent/testdir/tcl.in
@@ -0,0 +1,19 @@
+# vim: set filetype=tcl shiftwidth=4 tabstop=8 expandtab :
+
+# START_INDENT
+proc abc {} {
+set a 5
+if {[some_cmd]==1} {
+foreach i [list {1 2 3}] {
+# Does this comment affect anything?
+puts $i
+}
+}
+}
+
+command_with_a_long_time -arg1 "First" \
+-arg2 "Second" \
+-arg3 "Third"
+
+puts "Move indent back after line continuation is complete"
+# END_INDENT \ No newline at end of file
diff --git a/runtime/indent/testdir/tcl.ok b/runtime/indent/testdir/tcl.ok
new file mode 100644
index 0000000..77f24e9
--- /dev/null
+++ b/runtime/indent/testdir/tcl.ok
@@ -0,0 +1,19 @@
+# vim: set filetype=tcl shiftwidth=4 tabstop=8 expandtab :
+
+# START_INDENT
+proc abc {} {
+ set a 5
+ if {[some_cmd]==1} {
+ foreach i [list {1 2 3}] {
+ # Does this comment affect anything?
+ puts $i
+ }
+ }
+}
+
+command_with_a_long_time -arg1 "First" \
+ -arg2 "Second" \
+ -arg3 "Third"
+
+puts "Move indent back after line continuation is complete"
+# END_INDENT
diff --git a/runtime/indent/testdir/vb.in b/runtime/indent/testdir/vb.in
new file mode 100644
index 0000000..1653ae6
--- /dev/null
+++ b/runtime/indent/testdir/vb.in
@@ -0,0 +1,134 @@
+' vim: filetype=vb shiftwidth=4 expandtab
+'
+' START_INDENT
+Public Type GEmployeeRecord ' Create user-defined type.
+ID As Integer ' Define elements of data type.
+Name As String * 20
+Address As String * 30
+Phone As Long
+HireDate As Date
+End Type
+
+Public Enum InterfaceColors
+icMistyRose = &HE1E4FF&
+icSlateGray = &H908070&
+icDodgerBlue = &HFF901E&
+icDeepSkyBlue = &HFFBF00&
+icSpringGreen = &H7FFF00&
+icForestGreen = &H228B22&
+icGoldenrod = &H20A5DA&
+icFirebrick = &H2222B2&
+End Enum
+
+Enum SecurityLevel
+IllegalEntry = -1
+SecurityLevel1 = 0
+SecurityLevel2 = 1
+End Enum
+
+Public Function TestConditional (number As Integer, ext As String) As Boolean
+Dim inRange As Boolean
+
+Select Case number
+Case <= 0
+inRange = False
+Case > 10
+inRange = False
+Case Else
+inRange = True
+End Select
+
+' This is a special case identified in the indent script.
+Select Case number
+End Select
+
+If ext = ".xlm" Then
+If inRange Then
+TestConditional = True
+Else
+TestConditional = False
+End If
+ElseIf ext = ".xlsx" Then
+If inRange Then
+TestConditional = False
+Else
+TestConditional = True
+End If
+Else
+TestConditional = False
+End If
+End Function
+
+Private Sub TestIterators (lLimit As Integer, uLimit As Integer)
+Dim a() As Variant
+Dim elmt As Variant
+Dim found As Boolean
+Dim indx As Integer
+Const specialValue As Integer = 5
+
+If uLimit < lLimit Then
+Exit Sub
+End If
+
+ReDim a(lLimit To uLimit)
+For indx=lLimit To Ulimit
+a(indx) = 2 * indx
+Next indx
+
+found = False
+For Each elmt in a
+If elmt = specialValue Then
+found = True
+End If
+Next elmt
+
+If found then
+indx = uLimit
+Do While indx >= lLimit
+indx = indx - 1
+Loop
+End If
+
+End Sub
+
+Public Sub TestMultiline (cellAddr As String, rowNbr As Long)
+Dim rng As Range
+
+Set rng = Range(cellAddr)
+With rng
+.Cells(1,1).Value = _
+"Line 1 of multiline string; " & _
+"Line 2 of multiline string; " & _
+"Line 3 of multiline string"
+End With
+
+' The following lines have whitespace after the underscore character
+' and therefore do not form a valid multiline statement. The indent
+' script correctly treats them as four single line statements contrary
+' to the author's obvious indent.
+rng..Cells(1,1).Value = _
+"Line 1 of multiline string; " & _
+"Line 2 of multiline string; " & _
+"Line 3 of multiline string"
+
+End Sub
+
+Private Sub TestStmtLabel()
+GoTo stmtLabel
+
+' Statement labels are never indented
+stmtLabel:
+
+End Sub
+
+Sub TestTypeKeyword()
+Type EmployeeRecord ' Create user-defined type.
+ID As Integer ' Define elements of data type.
+Name As String * 20
+Address As String * 30
+Phone As Long
+HireDate As Date
+End Type
+Dim varType As EmployeeRecord
+End Sub
+' END_INDENT
diff --git a/runtime/indent/testdir/vb.ok b/runtime/indent/testdir/vb.ok
new file mode 100644
index 0000000..143c688
--- /dev/null
+++ b/runtime/indent/testdir/vb.ok
@@ -0,0 +1,134 @@
+' vim: filetype=vb shiftwidth=4 expandtab
+'
+' START_INDENT
+Public Type GEmployeeRecord ' Create user-defined type.
+ ID As Integer ' Define elements of data type.
+ Name As String * 20
+ Address As String * 30
+ Phone As Long
+ HireDate As Date
+End Type
+
+Public Enum InterfaceColors
+ icMistyRose = &HE1E4FF&
+ icSlateGray = &H908070&
+ icDodgerBlue = &HFF901E&
+ icDeepSkyBlue = &HFFBF00&
+ icSpringGreen = &H7FFF00&
+ icForestGreen = &H228B22&
+ icGoldenrod = &H20A5DA&
+ icFirebrick = &H2222B2&
+End Enum
+
+Enum SecurityLevel
+ IllegalEntry = -1
+ SecurityLevel1 = 0
+ SecurityLevel2 = 1
+End Enum
+
+Public Function TestConditional (number As Integer, ext As String) As Boolean
+ Dim inRange As Boolean
+
+ Select Case number
+ Case <= 0
+ inRange = False
+ Case > 10
+ inRange = False
+ Case Else
+ inRange = True
+ End Select
+
+ ' This is a special case identified in the indent script.
+ Select Case number
+ End Select
+
+ If ext = ".xlm" Then
+ If inRange Then
+ TestConditional = True
+ Else
+ TestConditional = False
+ End If
+ ElseIf ext = ".xlsx" Then
+ If inRange Then
+ TestConditional = False
+ Else
+ TestConditional = True
+ End If
+ Else
+ TestConditional = False
+ End If
+End Function
+
+Private Sub TestIterators (lLimit As Integer, uLimit As Integer)
+ Dim a() As Variant
+ Dim elmt As Variant
+ Dim found As Boolean
+ Dim indx As Integer
+ Const specialValue As Integer = 5
+
+ If uLimit < lLimit Then
+ Exit Sub
+ End If
+
+ ReDim a(lLimit To uLimit)
+ For indx=lLimit To Ulimit
+ a(indx) = 2 * indx
+ Next indx
+
+ found = False
+ For Each elmt in a
+ If elmt = specialValue Then
+ found = True
+ End If
+ Next elmt
+
+ If found then
+ indx = uLimit
+ Do While indx >= lLimit
+ indx = indx - 1
+ Loop
+ End If
+
+End Sub
+
+Public Sub TestMultiline (cellAddr As String, rowNbr As Long)
+ Dim rng As Range
+
+ Set rng = Range(cellAddr)
+ With rng
+ .Cells(1,1).Value = _
+ "Line 1 of multiline string; " & _
+ "Line 2 of multiline string; " & _
+ "Line 3 of multiline string"
+ End With
+
+ ' The following lines have whitespace after the underscore character
+ ' and therefore do not form a valid multiline statement. The indent
+ ' script correctly treats them as four single line statements contrary
+ ' to the author's obvious indent.
+ rng..Cells(1,1).Value = _
+ "Line 1 of multiline string; " & _
+ "Line 2 of multiline string; " & _
+ "Line 3 of multiline string"
+
+End Sub
+
+Private Sub TestStmtLabel()
+ GoTo stmtLabel
+
+ ' Statement labels are never indented
+stmtLabel:
+
+End Sub
+
+Sub TestTypeKeyword()
+ Type EmployeeRecord ' Create user-defined type.
+ ID As Integer ' Define elements of data type.
+ Name As String * 20
+ Address As String * 30
+ Phone As Long
+ HireDate As Date
+ End Type
+ Dim varType As EmployeeRecord
+End Sub
+' END_INDENT
diff --git a/runtime/indent/testdir/vim.in b/runtime/indent/testdir/vim.in
new file mode 100644
index 0000000..c60d2d1
--- /dev/null
+++ b/runtime/indent/testdir/vim.in
@@ -0,0 +1,941 @@
+" vim: set ft=vim sw=4 :
+
+" START_INDENT
+func Some()
+let x = 1
+endfunc
+
+let cmd =
+\ 'some '
+\ 'string'
+
+if 1
+let x = [
+\ ]
+endif
+
+for x in [
+{key: 'value'},
+]
+eval 0
+endfor
+
+let t = [
+\ {
+\ 'k': 'val',
+\ },
+\ ]
+
+def Func()
+var d = dd
+->extend({
+})
+eval 0
+enddef
+" END_INDENT
+
+" START_INDENT
+" INDENT_EXE let g:vim_indent_cont = 6
+
+let cmd =
+\ 'some '
+\ 'string'
+
+" END_INDENT
+
+" START_INDENT
+" INDENT_EXE let g:vim_indent_cont = 5
+
+let list = [
+\ 'one',
+\ 'two']
+
+" END_INDENT
+
+" START_INDENT
+" INDENT_EXE unlet g:vim_indent_cont
+
+let list = [
+'one',
+'two',
+]
+echo
+
+" END_INDENT
+
+" START_INDENT
+" INDENT_AT this-line
+func Some()
+let f = x " this-line
+endfunc
+" END_INDENT
+
+" START_INDENT
+" INDENT_NEXT next-line
+func Some()
+ " next-line
+let f = x
+endfunc
+" END_INDENT
+
+" START_INDENT
+" INDENT_PREV prev-line
+func Some()
+let f = x
+" prev-line
+endfunc
+" END_INDENT
+
+" START_INDENT
+let a =<< END
+nothing
+END
+" END_INDENT
+
+" START_INDENT
+let a =<< trim END
+nothing
+END
+" END_INDENT
+
+" START_INDENT
+" INDENT_AT this-line
+let a=<< trim END
+ blah
+ blah
+ blah this-line
+END
+" END_INDENT
+
+" START_INDENT
+if v:true
+echo 0
+end
+" END_INDENT
+
+" START_INDENT
+var result = Func(
+arg1,
+arg2
+)
+" END_INDENT
+
+" START_INDENT
+var result = Func(arg1,
+arg2)
+" END_INDENT
+
+" START_INDENT
+filter(list, (k, v) =>
+v > 0)
+" END_INDENT
+
+" START_INDENT
+filter(list, (k, v) => {
+const x = get(list, k, 0)
+return x > 0
+})
+" END_INDENT
+
+" START_INDENT
+if x > 0
+filter(list, (k, v) => {
+const x = get(list, k, 1)
+return x > 0
+})
+endif
+" END_INDENT
+
+" START_INDENT
+{
+var temp = 'temp'
+}
+" END_INDENT
+
+" START_INDENT
+var text = lead
+.. middle
+.. end
+" END_INDENT
+
+" START_INDENT
+var text = lead ..
+middle ..
+end
+" END_INDENT
+
+" START_INDENT
+var total = start +
+end -
+correction
+" END_INDENT
+
+" START_INDENT
+var result = start
+:+ print
+" END_INDENT
+
+" START_INDENT
+var result = positive
+? PosFunc(arg)
+: NegFunc(arg)
+" END_INDENT
+
+" START_INDENT
+var result = GetBuilder()
+->BuilderSetWidth(333)
+->BuilderSetHeight(777)
+->BuilderBuild()
+" END_INDENT
+
+" START_INDENT
+var result = MyDict
+.member
+" END_INDENT
+
+" START_INDENT
+autocmd BufNewFile *.match if condition
+| echo 'match'
+| endif
+" END_INDENT
+
+" START_INDENT
+set cpo+=C
+var lines =<< trim END
+| this works
+END
+set cpo-=C
+" END_INDENT
+
+" START_INDENT
+syn region Text
+\ start='foo'
+#\ comment
+\ end='bar'
+" END_INDENT
+
+" START_INDENT
+au CursorHold * echom 'BEFORE bar'
+#\ some comment
+| echom 'AFTER bar'
+" END_INDENT
+
+" START_INDENT
+def MyFunc(text: string,
+separator = '-'
+): string
+enddef
+" END_INDENT
+
+" START_INDENT
+def MyFunc(
+text: string,
+separator = '-'
+): string
+enddef
+" END_INDENT
+
+" START_INDENT
+[var1, var2] =
+Func()
+" END_INDENT
+
+" START_INDENT
+const list = ['one',
+'two']
+" END_INDENT
+
+" START_INDENT
+const list = [
+'one',
+'two',
+]
+" END_INDENT
+
+" START_INDENT
+const dict = {one: 1,
+two: 2
+}
+" END_INDENT
+
+" START_INDENT
+const dict = {
+one: 1,
+two: 2
+}
+" END_INDENT
+
+" START_INDENT
+if true
+const dict =
+{
+one: 1,
+two: 2
+}
+endif
+" END_INDENT
+
+" START_INDENT
+def Func()
+return {
+one: 1
+}
+enddef
+" END_INDENT
+
+" START_INDENT
+echo {
+a: 0,
+# b
+# c
+}
+" END_INDENT
+
+" START_INDENT
+echo search(
+# comment
+'1'
+.. '2'
+)
+" END_INDENT
+
+" START_INDENT
+if true
+var v = ( # trailing "(" starts line continuation
+3 + 4 # nothing special
+) # end of expression indicates continued line
+var x: number # needs to align with previous "var"
+endif
+" END_INDENT
+
+" START_INDENT
+def Func() # {{{
+# comment
+if true
+return
+endif
+enddef
+" END_INDENT
+
+" START_INDENT
+echo {
+key:
+'value',
+}
+" END_INDENT
+
+" START_INDENT
+var id = time
+->timer_start((_) => {
+n = 0
+})
+" END_INDENT
+
+" START_INDENT
+augroup Name
+autocmd!
+augroup END
+" END_INDENT
+
+" START_INDENT
+var n =
+# comment
+1
++ 2
+
+var s = ''
+" END_INDENT
+
+" START_INDENT
+var keys = {
+J: 'j',
+"\<Home>": '1G',
+"\<End>": 'G',
+z: 'zz'
+}
+" END_INDENT
+
+" START_INDENT
+export def Func(
+n: number,
+s: string,
+...l: list<bool>
+)
+enddef
+" END_INDENT
+
+" START_INDENT
+var heredoc =<< trim ENDD
+var nested_heredoc =<< trim END
+END
+ENDD
+" END_INDENT
+
+" START_INDENT
+if true
+else " comment
+endif
+" END_INDENT
+
+" START_INDENT
+if true | echo 'one' | endif
+if true | echo 'two' | endif
+if true | echo 'three' | endif
+" END_INDENT
+
+" START_INDENT
+if true
+:'<-1 mark <
+else
+echo ''
+endif
+" END_INDENT
+
+" START_INDENT
+substitute/pat /rep /
+echo
+" END_INDENT
+
+" START_INDENT
+try
+echo 1
+catch /pat / # comment
+echo 2
+endtry
+" END_INDENT
+
+" START_INDENT
+def Func()
+Cmd %
+enddef
+" END_INDENT
+
+" START_INDENT
+if end == 'xxx' || end == 'yyy'
+echo
+endif
+" END_INDENT
+
+" START_INDENT
+if true
+popup_move(id, {col: 1,
+line: 2})
+endif
+setwinvar(id, 'name', 3)
+" END_INDENT
+
+" START_INDENT
+var d = [
+{a: 'x',
+b: 'y'},
+FuncA(),
+FuncB(),
+]
+" END_INDENT
+
+" START_INDENT
+var ll = [[
+1,
+2,
+3], [
+4,
+5,
+6], [
+7,
+8,
+9]]
+" END_INDENT
+
+" START_INDENT
+var ld = [{
+a: 'xxx',
+b: 'yyy'}, {
+c: 'xxx',
+d: 'yyy'}, {
+e: 'xxx',
+f: 'yyy'}, {
+}]
+" END_INDENT
+
+" START_INDENT
+var d = {
+a: {
+b: {
+c: [{
+d: 'e',
+f: 'g',
+h: 'i'
+}],
+j: 'k',
+},
+},
+}
+" END_INDENT
+
+" START_INDENT
+if true
+var end: any
+if true
+end = 0
+elseif true
+echo
+endif
+endif
+" END_INDENT
+
+" START_INDENT
+nunmap <buffer> (
+nunmap <buffer> )
+inoremap [ {
+inoremap ] }
+silent! xunmap i{
+silent! xunmap a{
+" END_INDENT
+
+" START_INDENT
+def Func(
+s: string,
+n = 1,
+m = 2
+)
+enddef
+" END_INDENT
+
+" START_INDENT
+var h =<< END
+text
+END
+
+def Func()
+echo
+enddef
+" END_INDENT
+
+" START_INDENT
+def Func()
+var h =<< END
+text
+END
+echo 'test'
+enddef
+" END_INDENT
+
+" START_INDENT
+def Foo()
+lcd -
+enddef
+def Bar()
+echo
+enddef
+" END_INDENT
+
+" START_INDENT
+if true
+n = Func(1, 2,
+3)
+endif
+" END_INDENT
+
+" START_INDENT
+def Func(s: string,
+n: number): bool
+if true
+return false
+endif
+enddef
+" END_INDENT
+
+" START_INDENT
+def Func(
+n: number)
+#
+echo
+enddef
+" END_INDENT
+
+" START_INDENT
+" INDENT_AT this-line
+def Func(
+ n: number)
+ #
+echo # this-line
+enddef
+" END_INDENT
+
+" START_INDENT
+if true
+if true
+normal! ==
+endif
+endif
+" END_INDENT
+
+" START_INDENT
+var d = {
+a: () => true,
+b: () => true
+&& true
+&& Foo(),
+c: () => Bar(),
+e: () => Baz(),
+}
+" END_INDENT
+
+" START_INDENT
+def Select(Cont: func(func(any)), Pred: func(any): bool): func(func(any))
+return (Emit: func(any)) => {
+Cont((t: any) => {
+if Pred(t)
+Emit(t)
+endif
+})
+}
+enddef
+" END_INDENT
+
+" START_INDENT
+" INDENT_EXE let g:vim_indent = {'more_in_bracket_block': v:true}
+def Select(Cont: func(func(any)), Pred: func(any): bool): func(func(any))
+return (Emit: func(any)) => {
+Cont((t: any) => {
+if Pred(t)
+Emit(t)
+endif
+})
+}
+enddef
+" END_INDENT
+
+" START_INDENT
+" INDENT_EXE unlet! g:vim_indent
+" END_INDENT
+
+" START_INDENT
+g:lightline = {
+'active': {
+'left': [ [ 'mode', 'paste' ], [ 'readonly', 'relativepath', 'modified' ] ],
+},
+'inactive': {
+'left': [ [ 'readonly', 'relativepath', 'modified' ] ],
+}
+}
+" END_INDENT
+
+" START_INDENT
+if getline(1, 10)
+->map((_, v: string): number => strcharlen(v))
+->max() > 1'000
+&l:breakindent = false
+&l:linebreak = false
+else
+&l:breakindent = true
+&l:linebreak = true
+endif
+" END_INDENT
+
+" START_INDENT
+var ext2cmd: dict<string> = {
+doc: $'antiword {fname}',
+docx: $'pandoc --from=docx --to=markdown {fname}',
+epub: $'pandoc --from=epub --to=markdown {fname}',
+odp: $'odt2txt {fname}',
+odt: $'odt2txt {fname}',
+pdf: $'pdftotext -nopgbrk -layout -q -eol unix {fname} -',
+rtf: 'unrtf --text',
+}
+" END_INDENT
+
+" START_INDENT
+const ptybuf: number = term_start(&shell, {
+hidden: true,
+exit_cb: (_, _) => {
+if true
+close
+else
+help
+endif
+}
+})
+" END_INDENT
+
+" START_INDENT
+var d = {
+a: 0,
+# a ' quote {{{
+#}}}
+b: 0,
+}
+" END_INDENT
+
+" START_INDENT
+echo printf('%s () %s',
+1,
+2
+)
+" END_INDENT
+
+" START_INDENT
+prop_add(1, col('.'), {
+length: 2,
+type: 'test'
+})
+" END_INDENT
+
+" START_INDENT
+echo (() => " string starting with space")()
+echo
+" END_INDENT
+
+" START_INDENT
+var variables = deepcopy(g:)
+->filter((k: string, _): bool =>
+k =~ '\c\V' .. keyword->escape('\')
+&& k !~ '\%(loaded\|did_plugin_\)')
+->items()
+->map((_, v): string => v[0] .. ' = ' .. string(v[1]))
+new
+" END_INDENT
+
+" START_INDENT
+var d = freq
+->map((_, v) =>
+v * (
+1
++ 2
+))
+for item in d
+->items()
+->sort((a, b) => b[1] - a[1])
+echo
+endfor
+" END_INDENT
+
+" START_INDENT
+make_job = job_start([&shell, &shellcmdflag, make_cmd], {
+callback: function(MakeProcessOutput, [qfid]),
+close_cb: function(MakeCloseCb, [qfid]),
+exit_cb: MakeCompleted,
+in_io: 'null'
+})
+" END_INDENT
+
+" START_INDENT
+var matching_abbrev: list<dict<string>> = copy(ABBREV)
+->filter((_, v: dict<string>): bool =>
+stridx(v.lhs, word_to_complete) == 0)
+->map((_, v: dict<string>) => ({
+word: v.lhs,
+menu: AbbrevRhs(v.rhs)->stridx('expand_') >= 0
+? AbbrevRhs(v.rhs)->matchstr('.*,\s*''\zs.*\ze'')')
+: AbbrevRhs(v.rhs)
+}))
+" END_INDENT
+
+" START_INDENT
+def Func()
+if true
+vimgrep /^\C\s*\%(fu\%[nction]\|def\)\s\+/ file
+endif
+enddef
+" END_INDENT
+
+" START_INDENT
+setlocal iskeyword+=[
+cword = expand('<cword>')
+" END_INDENT
+
+" START_INDENT
+silent if true
+echo
+endif
+" END_INDENT
+
+" START_INDENT
+def Func()
+sort :^.*[\/]:
+enddef
+" END_INDENT
+
+" START_INDENT
+def Func()
+d = {
+}
+hd =<< trim END
+['
+]'
+END
+enddef
+" END_INDENT
+
+" START_INDENT
+def Func()
+if true
+var hd =<< trim END
+if get(b:, 'current_syntax', '')
+endif
+END
+elseif true
+echo
+endif
+enddef
+" END_INDENT
+
+" START_INDENT
+# test for control-flow keyword followed by commented fold marker {{{
+if true
+echo
+endif #}}}
+" END_INDENT
+
+" START_INDENT
+if winsz == 0|let winsz= ""|endif
+exe "noswapfile ".winsz."wincmd s"
+" END_INDENT
+
+" START_INDENT
+if true
+if true
+windo if true | echo | endif
+augroup Name
+autocmd WinLeave * if true | eval 1 + 2 | endif
+augroup END
+endif
+endif
+" END_INDENT
+
+" START_INDENT
+if true
+echo ' =<< trim END'
+->len()
+endif
+" END_INDENT
+
+" START_INDENT
+function Func()
+if true
+if true
+if true | echo com | endif
+if true | echo com | endif
+endif
+else
+endif
+endfunction
+" END_INDENT
+
+" START_INDENT
+function Func()
+if v:true
++
+echo
+-
+endif
+endfunction
+" END_INDENT
+
+" START_INDENT
+var matchpairs: string = &matchpairs
+var pairs: dict<list<string>>
+for [opening: string, closing: string]
+in matchpairs
+->split(',')
+->map((_, v: string): list<string> => split(v, ':'))
+pairs[opening] = [escape(opening, '[]'), escape(closing, '[]'), 'nW', 'w$']
+pairs[closing] = [escape(opening, '[]'), escape(closing, '[]'), 'bnW', 'w0']
+endfor
+" END_INDENT
+
+" START_INDENT
+{
+echo []
++ []
++ [{a: 1,
+b: 2}]
+}
+" END_INDENT
+
+" START_INDENT
+silent! argdel *
+edit file
+" END_INDENT
+
+" START_INDENT
+def Foo()
+Bar(1,
+[]->filter((_, v) => {
+return true
+}),
+() => {
+echo
+})
+enddef
+" END_INDENT
+
+" START_INDENT
+echo {
+k: () => {
+if true
+echo
+popup_setoptions(id,
+{title: 'title'})
+endif
+}
+}
+" END_INDENT
+
+" START_INDENT
+if true
+elseif
+endif
+" END_INDENT
+
+" START_INDENT
+if (
+true)
+&& true
+echo
+endif
+" END_INDENT
+
+" START_INDENT
+abstract class Shape
+this.color = Color.Black
+this.thickness = 10
+endclass
+" END_INDENT
+
+" START_INDENT
+class OtherThing
+this.size: number
+static totalSize: number
+
+static def ClearTotalSize(): number
+var prev = totalSize
+totalSize = 0
+return prev
+enddef
+endclass
+" END_INDENT
+
+" START_INDENT
+interface HasSurface
+this.size: number
+def Surface(): number
+endinterface
+" END_INDENT
+
+" START_INDENT
+interface EnterExit
+def Enter(): void
+def Exit(): void
+endinterface
+" END_INDENT
+
+" START_INDENT
+enum Color
+White
+Red
+Green
+Blue
+Black
+endenum
+" END_INDENT
diff --git a/runtime/indent/testdir/vim.ok b/runtime/indent/testdir/vim.ok
new file mode 100644
index 0000000..57f0dbf
--- /dev/null
+++ b/runtime/indent/testdir/vim.ok
@@ -0,0 +1,941 @@
+" vim: set ft=vim sw=4 :
+
+" START_INDENT
+func Some()
+ let x = 1
+endfunc
+
+let cmd =
+ \ 'some '
+ \ 'string'
+
+if 1
+ let x = [
+ \ ]
+endif
+
+for x in [
+ {key: 'value'},
+ ]
+ eval 0
+endfor
+
+let t = [
+ \ {
+ \ 'k': 'val',
+ \ },
+ \ ]
+
+def Func()
+ var d = dd
+ ->extend({
+ })
+ eval 0
+enddef
+" END_INDENT
+
+" START_INDENT
+" INDENT_EXE let g:vim_indent_cont = 6
+
+let cmd =
+ \ 'some '
+ \ 'string'
+
+" END_INDENT
+
+" START_INDENT
+" INDENT_EXE let g:vim_indent_cont = 5
+
+let list = [
+ \ 'one',
+ \ 'two']
+
+" END_INDENT
+
+" START_INDENT
+" INDENT_EXE unlet g:vim_indent_cont
+
+let list = [
+ 'one',
+ 'two',
+]
+echo
+
+" END_INDENT
+
+" START_INDENT
+" INDENT_AT this-line
+func Some()
+ let f = x " this-line
+endfunc
+" END_INDENT
+
+" START_INDENT
+" INDENT_NEXT next-line
+func Some()
+ " next-line
+ let f = x
+endfunc
+" END_INDENT
+
+" START_INDENT
+" INDENT_PREV prev-line
+func Some()
+ let f = x
+" prev-line
+endfunc
+" END_INDENT
+
+" START_INDENT
+let a =<< END
+nothing
+END
+" END_INDENT
+
+" START_INDENT
+let a =<< trim END
+ nothing
+END
+" END_INDENT
+
+" START_INDENT
+" INDENT_AT this-line
+let a=<< trim END
+ blah
+ blah
+ blah this-line
+END
+" END_INDENT
+
+" START_INDENT
+if v:true
+ echo 0
+end
+" END_INDENT
+
+" START_INDENT
+var result = Func(
+ arg1,
+ arg2
+)
+" END_INDENT
+
+" START_INDENT
+var result = Func(arg1,
+ arg2)
+" END_INDENT
+
+" START_INDENT
+filter(list, (k, v) =>
+ v > 0)
+" END_INDENT
+
+" START_INDENT
+filter(list, (k, v) => {
+ const x = get(list, k, 0)
+ return x > 0
+})
+" END_INDENT
+
+" START_INDENT
+if x > 0
+ filter(list, (k, v) => {
+ const x = get(list, k, 1)
+ return x > 0
+ })
+endif
+" END_INDENT
+
+" START_INDENT
+{
+ var temp = 'temp'
+}
+" END_INDENT
+
+" START_INDENT
+var text = lead
+ .. middle
+ .. end
+" END_INDENT
+
+" START_INDENT
+var text = lead ..
+ middle ..
+ end
+" END_INDENT
+
+" START_INDENT
+var total = start +
+ end -
+ correction
+" END_INDENT
+
+" START_INDENT
+var result = start
+:+ print
+" END_INDENT
+
+" START_INDENT
+var result = positive
+ ? PosFunc(arg)
+ : NegFunc(arg)
+" END_INDENT
+
+" START_INDENT
+var result = GetBuilder()
+ ->BuilderSetWidth(333)
+ ->BuilderSetHeight(777)
+ ->BuilderBuild()
+" END_INDENT
+
+" START_INDENT
+var result = MyDict
+ .member
+" END_INDENT
+
+" START_INDENT
+autocmd BufNewFile *.match if condition
+ | echo 'match'
+ | endif
+" END_INDENT
+
+" START_INDENT
+set cpo+=C
+var lines =<< trim END
+ | this works
+END
+set cpo-=C
+" END_INDENT
+
+" START_INDENT
+syn region Text
+ \ start='foo'
+ #\ comment
+ \ end='bar'
+" END_INDENT
+
+" START_INDENT
+au CursorHold * echom 'BEFORE bar'
+ #\ some comment
+ | echom 'AFTER bar'
+" END_INDENT
+
+" START_INDENT
+def MyFunc(text: string,
+ separator = '-'
+ ): string
+enddef
+" END_INDENT
+
+" START_INDENT
+def MyFunc(
+ text: string,
+ separator = '-'
+ ): string
+enddef
+" END_INDENT
+
+" START_INDENT
+[var1, var2] =
+ Func()
+" END_INDENT
+
+" START_INDENT
+const list = ['one',
+ 'two']
+" END_INDENT
+
+" START_INDENT
+const list = [
+ 'one',
+ 'two',
+]
+" END_INDENT
+
+" START_INDENT
+const dict = {one: 1,
+ two: 2
+}
+" END_INDENT
+
+" START_INDENT
+const dict = {
+ one: 1,
+ two: 2
+}
+" END_INDENT
+
+" START_INDENT
+if true
+ const dict =
+ {
+ one: 1,
+ two: 2
+ }
+endif
+" END_INDENT
+
+" START_INDENT
+def Func()
+ return {
+ one: 1
+ }
+enddef
+" END_INDENT
+
+" START_INDENT
+echo {
+ a: 0,
+ # b
+ # c
+}
+" END_INDENT
+
+" START_INDENT
+echo search(
+ # comment
+ '1'
+ .. '2'
+)
+" END_INDENT
+
+" START_INDENT
+if true
+ var v = ( # trailing "(" starts line continuation
+ 3 + 4 # nothing special
+ ) # end of expression indicates continued line
+ var x: number # needs to align with previous "var"
+endif
+" END_INDENT
+
+" START_INDENT
+def Func() # {{{
+ # comment
+ if true
+ return
+ endif
+enddef
+" END_INDENT
+
+" START_INDENT
+echo {
+ key:
+ 'value',
+}
+" END_INDENT
+
+" START_INDENT
+var id = time
+ ->timer_start((_) => {
+ n = 0
+ })
+" END_INDENT
+
+" START_INDENT
+augroup Name
+ autocmd!
+augroup END
+" END_INDENT
+
+" START_INDENT
+var n =
+ # comment
+ 1
+ + 2
+
+var s = ''
+" END_INDENT
+
+" START_INDENT
+var keys = {
+ J: 'j',
+ "\<Home>": '1G',
+ "\<End>": 'G',
+ z: 'zz'
+}
+" END_INDENT
+
+" START_INDENT
+export def Func(
+ n: number,
+ s: string,
+ ...l: list<bool>
+ )
+enddef
+" END_INDENT
+
+" START_INDENT
+var heredoc =<< trim ENDD
+ var nested_heredoc =<< trim END
+ END
+ENDD
+" END_INDENT
+
+" START_INDENT
+if true
+else " comment
+endif
+" END_INDENT
+
+" START_INDENT
+if true | echo 'one' | endif
+if true | echo 'two' | endif
+if true | echo 'three' | endif
+" END_INDENT
+
+" START_INDENT
+if true
+ :'<-1 mark <
+else
+ echo ''
+endif
+" END_INDENT
+
+" START_INDENT
+substitute/pat /rep /
+echo
+" END_INDENT
+
+" START_INDENT
+try
+ echo 1
+catch /pat / # comment
+ echo 2
+endtry
+" END_INDENT
+
+" START_INDENT
+def Func()
+ Cmd %
+enddef
+" END_INDENT
+
+" START_INDENT
+if end == 'xxx' || end == 'yyy'
+ echo
+endif
+" END_INDENT
+
+" START_INDENT
+if true
+ popup_move(id, {col: 1,
+ line: 2})
+endif
+setwinvar(id, 'name', 3)
+" END_INDENT
+
+" START_INDENT
+var d = [
+ {a: 'x',
+ b: 'y'},
+ FuncA(),
+ FuncB(),
+]
+" END_INDENT
+
+" START_INDENT
+var ll = [[
+ 1,
+ 2,
+ 3], [
+ 4,
+ 5,
+ 6], [
+ 7,
+ 8,
+ 9]]
+" END_INDENT
+
+" START_INDENT
+var ld = [{
+ a: 'xxx',
+ b: 'yyy'}, {
+ c: 'xxx',
+ d: 'yyy'}, {
+ e: 'xxx',
+ f: 'yyy'}, {
+ }]
+" END_INDENT
+
+" START_INDENT
+var d = {
+ a: {
+ b: {
+ c: [{
+ d: 'e',
+ f: 'g',
+ h: 'i'
+ }],
+ j: 'k',
+ },
+ },
+}
+" END_INDENT
+
+" START_INDENT
+if true
+ var end: any
+ if true
+ end = 0
+ elseif true
+ echo
+ endif
+endif
+" END_INDENT
+
+" START_INDENT
+nunmap <buffer> (
+nunmap <buffer> )
+inoremap [ {
+inoremap ] }
+silent! xunmap i{
+silent! xunmap a{
+" END_INDENT
+
+" START_INDENT
+def Func(
+ s: string,
+ n = 1,
+ m = 2
+ )
+enddef
+" END_INDENT
+
+" START_INDENT
+var h =<< END
+text
+END
+
+def Func()
+ echo
+enddef
+" END_INDENT
+
+" START_INDENT
+def Func()
+ var h =<< END
+text
+END
+ echo 'test'
+enddef
+" END_INDENT
+
+" START_INDENT
+def Foo()
+ lcd -
+enddef
+def Bar()
+ echo
+enddef
+" END_INDENT
+
+" START_INDENT
+if true
+ n = Func(1, 2,
+ 3)
+endif
+" END_INDENT
+
+" START_INDENT
+def Func(s: string,
+ n: number): bool
+ if true
+ return false
+ endif
+enddef
+" END_INDENT
+
+" START_INDENT
+def Func(
+ n: number)
+ #
+ echo
+enddef
+" END_INDENT
+
+" START_INDENT
+" INDENT_AT this-line
+def Func(
+ n: number)
+ #
+ echo # this-line
+enddef
+" END_INDENT
+
+" START_INDENT
+if true
+ if true
+ normal! ==
+ endif
+endif
+" END_INDENT
+
+" START_INDENT
+var d = {
+ a: () => true,
+ b: () => true
+ && true
+ && Foo(),
+ c: () => Bar(),
+ e: () => Baz(),
+}
+" END_INDENT
+
+" START_INDENT
+def Select(Cont: func(func(any)), Pred: func(any): bool): func(func(any))
+ return (Emit: func(any)) => {
+ Cont((t: any) => {
+ if Pred(t)
+ Emit(t)
+ endif
+ })
+ }
+enddef
+" END_INDENT
+
+" START_INDENT
+" INDENT_EXE let g:vim_indent = {'more_in_bracket_block': v:true}
+def Select(Cont: func(func(any)), Pred: func(any): bool): func(func(any))
+ return (Emit: func(any)) => {
+ Cont((t: any) => {
+ if Pred(t)
+ Emit(t)
+ endif
+ })
+ }
+enddef
+" END_INDENT
+
+" START_INDENT
+" INDENT_EXE unlet! g:vim_indent
+" END_INDENT
+
+" START_INDENT
+g:lightline = {
+ 'active': {
+ 'left': [ [ 'mode', 'paste' ], [ 'readonly', 'relativepath', 'modified' ] ],
+ },
+ 'inactive': {
+ 'left': [ [ 'readonly', 'relativepath', 'modified' ] ],
+ }
+}
+" END_INDENT
+
+" START_INDENT
+if getline(1, 10)
+ ->map((_, v: string): number => strcharlen(v))
+ ->max() > 1'000
+ &l:breakindent = false
+ &l:linebreak = false
+else
+ &l:breakindent = true
+ &l:linebreak = true
+endif
+" END_INDENT
+
+" START_INDENT
+var ext2cmd: dict<string> = {
+ doc: $'antiword {fname}',
+ docx: $'pandoc --from=docx --to=markdown {fname}',
+ epub: $'pandoc --from=epub --to=markdown {fname}',
+ odp: $'odt2txt {fname}',
+ odt: $'odt2txt {fname}',
+ pdf: $'pdftotext -nopgbrk -layout -q -eol unix {fname} -',
+ rtf: 'unrtf --text',
+}
+" END_INDENT
+
+" START_INDENT
+const ptybuf: number = term_start(&shell, {
+ hidden: true,
+ exit_cb: (_, _) => {
+ if true
+ close
+ else
+ help
+ endif
+ }
+})
+" END_INDENT
+
+" START_INDENT
+var d = {
+ a: 0,
+ # a ' quote {{{
+ #}}}
+ b: 0,
+}
+" END_INDENT
+
+" START_INDENT
+echo printf('%s () %s',
+ 1,
+ 2
+)
+" END_INDENT
+
+" START_INDENT
+prop_add(1, col('.'), {
+ length: 2,
+ type: 'test'
+})
+" END_INDENT
+
+" START_INDENT
+echo (() => " string starting with space")()
+echo
+" END_INDENT
+
+" START_INDENT
+var variables = deepcopy(g:)
+ ->filter((k: string, _): bool =>
+ k =~ '\c\V' .. keyword->escape('\')
+ && k !~ '\%(loaded\|did_plugin_\)')
+ ->items()
+ ->map((_, v): string => v[0] .. ' = ' .. string(v[1]))
+new
+" END_INDENT
+
+" START_INDENT
+var d = freq
+ ->map((_, v) =>
+ v * (
+ 1
+ + 2
+ ))
+for item in d
+ ->items()
+ ->sort((a, b) => b[1] - a[1])
+ echo
+endfor
+" END_INDENT
+
+" START_INDENT
+make_job = job_start([&shell, &shellcmdflag, make_cmd], {
+ callback: function(MakeProcessOutput, [qfid]),
+ close_cb: function(MakeCloseCb, [qfid]),
+ exit_cb: MakeCompleted,
+ in_io: 'null'
+})
+" END_INDENT
+
+" START_INDENT
+var matching_abbrev: list<dict<string>> = copy(ABBREV)
+ ->filter((_, v: dict<string>): bool =>
+ stridx(v.lhs, word_to_complete) == 0)
+ ->map((_, v: dict<string>) => ({
+ word: v.lhs,
+ menu: AbbrevRhs(v.rhs)->stridx('expand_') >= 0
+ ? AbbrevRhs(v.rhs)->matchstr('.*,\s*''\zs.*\ze'')')
+ : AbbrevRhs(v.rhs)
+ }))
+" END_INDENT
+
+" START_INDENT
+def Func()
+ if true
+ vimgrep /^\C\s*\%(fu\%[nction]\|def\)\s\+/ file
+ endif
+enddef
+" END_INDENT
+
+" START_INDENT
+setlocal iskeyword+=[
+cword = expand('<cword>')
+" END_INDENT
+
+" START_INDENT
+silent if true
+ echo
+endif
+" END_INDENT
+
+" START_INDENT
+def Func()
+ sort :^.*[\/]:
+enddef
+" END_INDENT
+
+" START_INDENT
+def Func()
+ d = {
+ }
+ hd =<< trim END
+ ['
+ ]'
+ END
+enddef
+" END_INDENT
+
+" START_INDENT
+def Func()
+ if true
+ var hd =<< trim END
+ if get(b:, 'current_syntax', '')
+ endif
+ END
+ elseif true
+ echo
+ endif
+enddef
+" END_INDENT
+
+" START_INDENT
+# test for control-flow keyword followed by commented fold marker {{{
+if true
+ echo
+endif #}}}
+" END_INDENT
+
+" START_INDENT
+if winsz == 0|let winsz= ""|endif
+exe "noswapfile ".winsz."wincmd s"
+" END_INDENT
+
+" START_INDENT
+if true
+ if true
+ windo if true | echo | endif
+ augroup Name
+ autocmd WinLeave * if true | eval 1 + 2 | endif
+ augroup END
+ endif
+endif
+" END_INDENT
+
+" START_INDENT
+if true
+ echo ' =<< trim END'
+ ->len()
+endif
+" END_INDENT
+
+" START_INDENT
+function Func()
+ if true
+ if true
+ if true | echo com | endif
+ if true | echo com | endif
+ endif
+ else
+ endif
+endfunction
+" END_INDENT
+
+" START_INDENT
+function Func()
+ if v:true
+ +
+ echo
+ -
+ endif
+endfunction
+" END_INDENT
+
+" START_INDENT
+var matchpairs: string = &matchpairs
+var pairs: dict<list<string>>
+for [opening: string, closing: string]
+ in matchpairs
+ ->split(',')
+ ->map((_, v: string): list<string> => split(v, ':'))
+ pairs[opening] = [escape(opening, '[]'), escape(closing, '[]'), 'nW', 'w$']
+ pairs[closing] = [escape(opening, '[]'), escape(closing, '[]'), 'bnW', 'w0']
+endfor
+" END_INDENT
+
+" START_INDENT
+{
+ echo []
+ + []
+ + [{a: 1,
+ b: 2}]
+}
+" END_INDENT
+
+" START_INDENT
+silent! argdel *
+edit file
+" END_INDENT
+
+" START_INDENT
+def Foo()
+ Bar(1,
+ []->filter((_, v) => {
+ return true
+ }),
+ () => {
+ echo
+ })
+enddef
+" END_INDENT
+
+" START_INDENT
+echo {
+ k: () => {
+ if true
+ echo
+ popup_setoptions(id,
+ {title: 'title'})
+ endif
+ }
+}
+" END_INDENT
+
+" START_INDENT
+if true
+elseif
+endif
+" END_INDENT
+
+" START_INDENT
+if (
+ true)
+ && true
+ echo
+endif
+" END_INDENT
+
+" START_INDENT
+abstract class Shape
+ this.color = Color.Black
+ this.thickness = 10
+endclass
+" END_INDENT
+
+" START_INDENT
+class OtherThing
+ this.size: number
+ static totalSize: number
+
+ static def ClearTotalSize(): number
+ var prev = totalSize
+ totalSize = 0
+ return prev
+ enddef
+endclass
+" END_INDENT
+
+" START_INDENT
+interface HasSurface
+ this.size: number
+ def Surface(): number
+endinterface
+" END_INDENT
+
+" START_INDENT
+interface EnterExit
+ def Enter(): void
+ def Exit(): void
+endinterface
+" END_INDENT
+
+" START_INDENT
+enum Color
+ White
+ Red
+ Green
+ Blue
+ Black
+endenum
+" END_INDENT
diff --git a/runtime/indent/testdir/xml.in b/runtime/indent/testdir/xml.in
new file mode 100644
index 0000000..88ad51e
--- /dev/null
+++ b/runtime/indent/testdir/xml.in
@@ -0,0 +1,32 @@
+<!-- vim: set ft=xml ts=8 sw=0 sts=-1 et : -->
+<!-- START_INDENT -->
+<?xml version="1.0" encoding="utf-8"?>
+<tag0>
+ <tag1>
+<!-- comment -->
+<tag2>
+ <tag3/>
+</tag2>
+<!-- text comment -->
+
+<!--
+text comment
+-->
+</tag1>
+<!--
+text comment
+end comment -->
+</tag0>
+<!-- END_INDENT -->
+
+<!-- START_INDENT -->
+<?xml version="1.0" encoding="utf-8"?>
+<tag0>
+ <tag1>
+<!-- comment -->
+<tag2>
+ <tag3/>
+</tag2>
+</tag1>
+</tag0>
+<!-- END_INDENT -->
diff --git a/runtime/indent/testdir/xml.ok b/runtime/indent/testdir/xml.ok
new file mode 100644
index 0000000..d5e2289
--- /dev/null
+++ b/runtime/indent/testdir/xml.ok
@@ -0,0 +1,32 @@
+<!-- vim: set ft=xml ts=8 sw=0 sts=-1 et : -->
+<!-- START_INDENT -->
+<?xml version="1.0" encoding="utf-8"?>
+<tag0>
+ <tag1>
+ <!-- comment -->
+ <tag2>
+ <tag3/>
+ </tag2>
+ <!-- text comment -->
+
+ <!--
+ text comment
+ -->
+ </tag1>
+ <!--
+ text comment
+ end comment -->
+</tag0>
+<!-- END_INDENT -->
+
+<!-- START_INDENT -->
+<?xml version="1.0" encoding="utf-8"?>
+<tag0>
+ <tag1>
+ <!-- comment -->
+ <tag2>
+ <tag3/>
+ </tag2>
+ </tag1>
+</tag0>
+<!-- END_INDENT -->
diff --git a/runtime/indent/testdir/yaml.in b/runtime/indent/testdir/yaml.in
new file mode 100644
index 0000000..bf99668
--- /dev/null
+++ b/runtime/indent/testdir/yaml.in
@@ -0,0 +1,20 @@
+# vim: set ft=yaml sw=2 et :
+
+# START_INDENT
+map1:
+sub1:
+- list item
+map2:
+- another list
+# END_INDENT
+
+# START_INDENT
+map: &anchor
+map: val
+# END_INDENT
+
+# START_INDENT
+map: |
+line1
+line2
+# END_INDENT
diff --git a/runtime/indent/testdir/yaml.ok b/runtime/indent/testdir/yaml.ok
new file mode 100644
index 0000000..8b38633
--- /dev/null
+++ b/runtime/indent/testdir/yaml.ok
@@ -0,0 +1,20 @@
+# vim: set ft=yaml sw=2 et :
+
+# START_INDENT
+map1:
+ sub1:
+ - list item
+map2:
+ - another list
+# END_INDENT
+
+# START_INDENT
+map: &anchor
+map: val
+# END_INDENT
+
+# START_INDENT
+map: |
+ line1
+ line2
+# END_INDENT