summaryrefslogtreecommitdiff
path: root/mnv/runtime/syntax/testdir/input
diff options
context:
space:
mode:
authorMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-04 12:41:27 +0300
committerMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-04 12:41:27 +0300
commit4f2d36194b4f299aa7509d815c07121039ea833b (patch)
treef3ded014bad3a4c76ff6a22b8726ebaab68c3d13 /mnv/runtime/syntax/testdir/input
parent5b578e70c314723a3cde5c9bfc2be0bf1dadc93b (diff)
downloadProject-Tick-4f2d36194b4f299aa7509d815c07121039ea833b.tar.gz
Project-Tick-4f2d36194b4f299aa7509d815c07121039ea833b.zip
NOISSUE change uvim folder name to mnv
Signed-off-by: Mehmet Samet Duman <yongdohyun@projecttick.org>
Diffstat (limited to 'mnv/runtime/syntax/testdir/input')
-rw-r--r--mnv/runtime/syntax/testdir/input/awk.awk9
-rw-r--r--mnv/runtime/syntax/testdir/input/c.c123
-rw-r--r--mnv/runtime/syntax/testdir/input/c_bool_constant.c11
-rw-r--r--mnv/runtime/syntax/testdir/input/c_character_constant.c41
-rw-r--r--mnv/runtime/syntax/testdir/input/c_integer_constant.c44
-rw-r--r--mnv/runtime/syntax/testdir/input/c_keywords.c64
-rw-r--r--mnv/runtime/syntax/testdir/input/c_noreturn.c23
-rw-r--r--mnv/runtime/syntax/testdir/input/c_preprocessor_conditional.c40
-rw-r--r--mnv/runtime/syntax/testdir/input/c_preprocessor_embed.c31
-rw-r--r--mnv/runtime/syntax/testdir/input/c_preprocessor_error.c19
-rw-r--r--mnv/runtime/syntax/testdir/input/c_string_literal.c59
-rw-r--r--mnv/runtime/syntax/testdir/input/codeowners.txt12
-rw-r--r--mnv/runtime/syntax/testdir/input/cpp_noreturn.cpp20
-rw-r--r--mnv/runtime/syntax/testdir/input/cpp_numbers.cpp20
-rw-r--r--mnv/runtime/syntax/testdir/input/csh.csh6
-rw-r--r--mnv/runtime/syntax/testdir/input/css_1.css5
-rw-r--r--mnv/runtime/syntax/testdir/input/dts_zephyr.overlay16
-rw-r--r--mnv/runtime/syntax/testdir/input/dts_zmk.keymap23
-rw-r--r--mnv/runtime/syntax/testdir/input/gdb.gdb1655
-rw-r--r--mnv/runtime/syntax/testdir/input/gdb_multiline_commands.gdb41
-rw-r--r--mnv/runtime/syntax/testdir/input/haskell.hs4
-rw-r--r--mnv/runtime/syntax/testdir/input/help.txt61
-rw-r--r--mnv/runtime/syntax/testdir/input/help_ex_version.txt238
-rw-r--r--mnv/runtime/syntax/testdir/input/html.html153
-rw-r--r--mnv/runtime/syntax/testdir/input/html_fold_expr.html105
-rw-r--r--mnv/runtime/syntax/testdir/input/html_fold_syntax.html105
-rw-r--r--mnv/runtime/syntax/testdir/input/java_annotations.java78
-rw-r--r--mnv/runtime/syntax/testdir/input/java_annotations_signature.java78
-rw-r--r--mnv/runtime/syntax/testdir/input/java_comments_html.java131
-rw-r--r--mnv/runtime/syntax/testdir/input/java_comments_markdown.java147
-rw-r--r--mnv/runtime/syntax/testdir/input/java_contextual_keywords.java52
-rw-r--r--mnv/runtime/syntax/testdir/input/java_enfoldment.java145
-rw-r--r--mnv/runtime/syntax/testdir/input/java_escapes.java123
-rw-r--r--mnv/runtime/syntax/testdir/input/java_generics.java162
-rw-r--r--mnv/runtime/syntax/testdir/input/java_generics_signature.java162
-rw-r--r--mnv/runtime/syntax/testdir/input/java_lambda_expressions.java154
-rw-r--r--mnv/runtime/syntax/testdir/input/java_lambda_expressions_signature.java154
-rw-r--r--mnv/runtime/syntax/testdir/input/java_method_references.java192
-rw-r--r--mnv/runtime/syntax/testdir/input/java_method_references_signature.java192
-rw-r--r--mnv/runtime/syntax/testdir/input/java_methods_indent2.java139
-rw-r--r--mnv/runtime/syntax/testdir/input/java_methods_indent2_signature.java131
-rw-r--r--mnv/runtime/syntax/testdir/input/java_methods_indent4.java139
-rw-r--r--mnv/runtime/syntax/testdir/input/java_methods_indent4_signature.java131
-rw-r--r--mnv/runtime/syntax/testdir/input/java_methods_indent8.java139
-rw-r--r--mnv/runtime/syntax/testdir/input/java_methods_indent8_signature.java131
-rw-r--r--mnv/runtime/syntax/testdir/input/java_methods_style.java117
-rw-r--r--mnv/runtime/syntax/testdir/input/java_methods_style_signature.java109
-rw-r--r--mnv/runtime/syntax/testdir/input/java_module_info.java35
-rw-r--r--mnv/runtime/syntax/testdir/input/java_numbers.java88
-rw-r--r--mnv/runtime/syntax/testdir/input/java_previews_430.java68
-rw-r--r--mnv/runtime/syntax/testdir/input/java_previews_455.java64
-rw-r--r--mnv/runtime/syntax/testdir/input/java_string.java44
-rw-r--r--mnv/runtime/syntax/testdir/input/java_switch.java122
-rw-r--r--mnv/runtime/syntax/testdir/input/java_unfoldment.java145
-rw-r--r--mnv/runtime/syntax/testdir/input/leex.xrl28
-rw-r--r--mnv/runtime/syntax/testdir/input/make_01.mak16
-rw-r--r--mnv/runtime/syntax/testdir/input/markdown_circularity.markdown54
-rw-r--r--mnv/runtime/syntax/testdir/input/markdown_conceal.markdown15
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_blocks.mnv49
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_builtin_object_methods.mnv114
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_builtin_object_methods2.mnv58
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_comment_strings.mnv27
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_comments.mnv99
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_constructors.mnv18
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_def_variables.mnv226
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_class_fold.mnv71
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_commands.mnv1211
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_echo.mnv36
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_enum.mnv111
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_enum2.mnv31
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_enum_fold.mnv50
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_for.mnv88
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_function_def_tail_comment_errors.mnv45
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_function_def_tail_comments.mnv45
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_import.mnv120
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_interface_fold.mnv38
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_let_heredoc.mnv299
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_loadkeymap.mnv28
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_ex_type.mnv12
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_expressions.mnv215
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_function_calls.mnv317
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_enum.mnv36
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_list.mnv215
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_set.mnv177
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_generic_functions.mnv97
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_lambdas.mnv161
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_legacy_header.mnv20
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_legacy_header_fold.mnv22
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_no_comment_strings.mnv27
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_shebang.mnv8
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords.mnv87
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords2.mnv63
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords3.mnv27
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_tuples.mnv25
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_types.mnv17
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_types_example_object.mnv29
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_types_object.mnv27
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv9_variables.mnv269
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_comment_strings.mnv22
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_comments.mnv83
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_abbreviate.mnv54
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_at.mnv66
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_augroup.mnv71
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_autocmd.mnv257
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_behave.mnv9
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_breakpoint_commands.mnv95
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_call.mnv52
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_catch.mnv19
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_cd.mnv110
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_command.mnv196
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_command_modifiers.mnv135
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_commands.mnv1210
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_debug.mnv13
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_debuggreedy.mnv34
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_def.mnv126
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_def_fold.mnv185
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_def_nested.mnv23
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_def_nested_fold.mnv25
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_def_return_type.mnv60
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_defer.mnv17
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_delfunction.mnv34
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_do_commands.mnv58
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_echo.mnv58
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_eval.mnv20
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_execute.mnv64
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_filetype.mnv30
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_filter.mnv16
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_for.mnv60
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_function.mnv266
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_function_def_tail_comment_errors.mnv45
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_function_def_tail_comments.mnv45
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_function_fold.mnv349
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_function_nested.mnv40
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_function_nested_fold.mnv42
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_grep.mnv47
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_help.mnvbin0 -> 986 bytes
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_helpgrep.mnv18
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_highlight.mnv108
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_history.mnv89
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_import.mnv119
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_language.mnv172
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_let_heredoc.mnv250
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap.mnv27
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap_after_bar.mnv11
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap_after_colon.mnv11
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_lua.mnv157
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_make.mnv38
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_map.mnv124
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_mark.mnv215
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_match.mnv64
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_menu.mnv88
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_menutranslate.mnv52
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_mnvgrep.mnv69
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_mzscheme.mnv157
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_normal.mnv30
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_perl.mnv157
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_profile.mnv48
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_prompt_commands.mnv46
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_python.mnv159
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_range.mnv90
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_redir.mnv71
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_ruby.mnv157
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_set.mnv131
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_set_backslash.mnv79
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_sleep.mnv13
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_sort.mnv64
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_substitute.mnv208
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_syntax.mnv377
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_syntime.mnv38
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_tcl.mnv157
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_terminal.mnv69
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_throw.mnv7
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_uniq.mnv31
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_ex_wincmd.mnv67
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_expressions.mnv426
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_function_calls.mnv277
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_function_variables.mnv414
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_key_notation.mnv166
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_lambdas.mnv135
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_line_continuation.mnv51
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_new.mnv21
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_nmnv_features.mnv229
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_no_comment_strings.mnv22
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_predefined_user_commands.mnv21
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_shebang.mnv5
-rw-r--r--mnv/runtime/syntax/testdir/input/mnv_variables.mnv411
-rw-r--r--mnv/runtime/syntax/testdir/input/modula2_iso.def114
-rw-r--r--mnv/runtime/syntax/testdir/input/modula2_pim.def111
-rw-r--r--mnv/runtime/syntax/testdir/input/modula2_r10.def146
-rw-r--r--mnv/runtime/syntax/testdir/input/po.po51
-rw-r--r--mnv/runtime/syntax/testdir/input/progress_comments.p45
-rw-r--r--mnv/runtime/syntax/testdir/input/python2_strings.py82
-rw-r--r--mnv/runtime/syntax/testdir/input/python_constants_builtin_default.py11
-rw-r--r--mnv/runtime/syntax/testdir/input/python_constants_builtin_highlight.py11
-rw-r--r--mnv/runtime/syntax/testdir/input/python_constants_keyword_default.py11
-rw-r--r--mnv/runtime/syntax/testdir/input/python_constants_keyword_highlight.py11
-rw-r--r--mnv/runtime/syntax/testdir/input/python_ellipsis.py46
-rw-r--r--mnv/runtime/syntax/testdir/input/python_strings_bytes.py249
-rw-r--r--mnv/runtime/syntax/testdir/input/python_type.py8
-rw-r--r--mnv/runtime/syntax/testdir/input/sed.sed65
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/README.txt10
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_0160
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_0230
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_0320
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_0415
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_0512
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_0610
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_079
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_088
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_097
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_106
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_116
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_125
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_135
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_145
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_154
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_164
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_174
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_184
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_194
-rw-r--r--mnv/runtime/syntax/testdir/input/selftestdir/dots_202
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/help.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/help_ex_version.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/html_fold_expr.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/java_module_info.mnv30
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/markdown_circularity.mnv4
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/markdown_conceal.mnv8
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_blocks.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_builtin_object_methods2.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_comments.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_def_variables.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_ex_class_fold.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_ex_commands.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_ex_enum.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_ex_enum2.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_ex_for.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_ex_function_def_tail_comment_errors.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_ex_function_def_tail_comments.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_ex_import.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_ex_interface_fold.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_ex_let_heredoc.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_ex_loadkeymap.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_expressions.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_lambdas.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_legacy_header.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords2.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords3.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv9_variables.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_comments.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_call.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_command.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_commands.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_def.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_fold.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_nested.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_nested_fold.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_echo.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_execute.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_for.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_function.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_def_tail_comment_errors.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_def_tail_comments.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_fold.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_import.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_let_heredoc.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap_after_bar.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap_after_colon.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_map.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_match.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_menu.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_redir.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_substitute.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_ex_syntax.mnv2
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_expressions.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_function_variables.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_lambdas.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_line_continuation.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/setup/mnv_variables.mnv1
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_01.sh4
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_02.sh30
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_03.sh33
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_04.sh22
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_05.sh373
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_06.sh71
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_07.sh93
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_08.sh82
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_09.sh20
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_10.sh12
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_11.sh20
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_12.sh206
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_13.sh9
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_14.sh8
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_15.sh13
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_bash.bash33
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_bash_alias.sh3
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_functions_bash.sh55
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_functions_dash.sh40
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_functions_ksh2020.sh51
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_functions_ksh88.sh45
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_functions_mksh.sh45
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_generic.ksh206
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_ksh2020.ksh206
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_ksh88.ksh206
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_ksh93_generic.ksh206
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_ksh93u.ksh206
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_ksh93v.ksh206
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_ksh_array.sh21
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_mksh.ksh206
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_mksh_gibberish.ksh126
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_quoting.sh4
-rw-r--r--mnv/runtime/syntax/testdir/input/sh_sundrous.bash58
-rw-r--r--mnv/runtime/syntax/testdir/input/skhdrc.skhdrc104
-rw-r--r--mnv/runtime/syntax/testdir/input/sml.sml71
-rw-r--r--mnv/runtime/syntax/testdir/input/sudoers_Defaults.sudoers43
-rw-r--r--mnv/runtime/syntax/testdir/input/sudoers_user-spec.sudoers43
-rw-r--r--mnv/runtime/syntax/testdir/input/tcsh.tcsh6
-rw-r--r--mnv/runtime/syntax/testdir/input/tera.tera165
-rw-r--r--mnv/runtime/syntax/testdir/input/tex_01.tex14
-rw-r--r--mnv/runtime/syntax/testdir/input/tex_02.tex11
-rw-r--r--mnv/runtime/syntax/testdir/input/tex_03.tex11
-rw-r--r--mnv/runtime/syntax/testdir/input/yaml.yaml128
323 files changed, 25826 insertions, 0 deletions
diff --git a/mnv/runtime/syntax/testdir/input/awk.awk b/mnv/runtime/syntax/testdir/input/awk.awk
new file mode 100644
index 0000000000..337a1ceeea
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/awk.awk
@@ -0,0 +1,9 @@
+{ # Comment 1
+ for (i = 0; # Comment 2
+ i < 1; # Comment 3
+ i++) # Comment 4
+ { # Comment 5
+ print # Comment 6
+ } # Comment 7
+} # Comment 8
+
diff --git a/mnv/runtime/syntax/testdir/input/c.c b/mnv/runtime/syntax/testdir/input/c.c
new file mode 100644
index 0000000000..52336cd034
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/c.c
@@ -0,0 +1,123 @@
+/* vi:set ts=8 sts=4 sw=4 noet:
+ * MNV_TEST_SETUP let g:c_comment_strings = 1
+ *
+ * MNV - MNV is not Vim by Bram Moolenaar
+ *
+ * Do ":help uganda" in MNV to read copying and usage conditions.
+ * Do ":help credits" in MNV to see a list of people who contributed.
+ * See README.txt for an overview of the MNV source code.
+ */
+
+#define EXTERN
+#include "mnv.h"
+
+#ifdef __CYGWIN__
+# include <cygwin/version.h>
+# include <sys/cygwin.h> // for cygwin_conv_to_posix_path() and/or
+ // cygwin_conv_path()
+# include <limits.h>
+#endif
+
+#if defined(MSWIN) && (!defined(FEAT_GUI_MSWIN) || defined(MNVDLL))
+# include "iscygpty.h"
+#endif
+
+// Values for edit_type.
+#define EDIT_NONE 0 // no edit type yet
+#define EDIT_FILE 1 // file name argument[s] given, use argument list
+#define EDIT_STDIN 2 // read file from stdin
+#define EDIT_TAG 3 // tag name argument given, use tagname
+#define EDIT_QF 4 // start in quickfix mode
+
+#if (defined(UNIX) || defined(VMS)) && !defined(NO_MNV_MAIN)
+static int file_owned(char *fname);
+#endif
+static void mainerr(int, char_u *);
+static void early_arg_scan(mparm_T *parmp);
+#ifndef NO_MNV_MAIN
+static void usage(void);
+static void parse_command_name(mparm_T *parmp);
+static void command_line_scan(mparm_T *parmp);
+static void check_tty(mparm_T *parmp);
+static void read_stdin(void);
+static void create_windows(mparm_T *parmp);
+static void edit_buffers(mparm_T *parmp, char_u *cwd);
+static void exe_pre_commands(mparm_T *parmp);
+static void exe_commands(mparm_T *parmp);
+static void source_startup_scripts(mparm_T *parmp);
+static void main_start_gui(void);
+static void check_swap_exists_action(void);
+# ifdef FEAT_EVAL
+static void set_progpath(char_u *argv0);
+# endif
+#endif
+
+
+/*
+ * Different types of error messages.
+ */
+static char *(main_errors[]) =
+{
+ N_("Unknown option argument"),
+#define ME_UNKNOWN_OPTION 0
+ N_("Too many edit arguments"),
+#define ME_TOO_MANY_ARGS 1
+ N_("Argument missing after"),
+#define ME_ARG_MISSING 2
+ N_("Garbage after option argument"),
+#define ME_GARBAGE 3
+ N_("Too many \"+command\", \"-c command\" or \"--cmd command\" arguments"),
+#define ME_EXTRA_CMD 4
+ N_("Invalid argument for"),
+#define ME_INVALID_ARG 5
+};
+
+#ifndef PROTO // don't want a prototype for main()
+
+// Various parameters passed between main() and other functions.
+static mparm_T params;
+
+#ifdef _IOLBF
+static void *s_vbuf = NULL; // buffer for setvbuf()
+#endif
+
+#ifndef NO_MNV_MAIN // skip this for unittests
+
+static char_u *start_dir = NULL; // current working dir on startup
+
+static int has_dash_c_arg = FALSE;
+
+# ifdef MNVDLL
+__declspec(dllexport)
+# endif
+ int
+# ifdef MSWIN
+MNVMain
+# else
+main
+# endif
+(int argc, char **argv)
+{
+#if defined(STARTUPTIME) || defined(CLEAN_RUNTIMEPATH)
+ int i;
+#endif
+
+ /*
+ * Do any system-specific initialisations. These can NOT use IObuff or
+ * NameBuff. Thus emsg2() cannot be called!
+ */
+ mch_early_init();
+
+ // Source startup scripts.
+ source_startup_scripts(&params);
+
+#if 0
+ /*
+ * Newer version of MzScheme (Racket) require earlier (trampolined)
+ * initialisation via scheme_main_setup.
+ */
+ return mzscheme_main();
+#else
+ return mnv_main2();
+#endif
+}
diff --git a/mnv/runtime/syntax/testdir/input/c_bool_constant.c b/mnv/runtime/syntax/testdir/input/c_bool_constant.c
new file mode 100644
index 0000000000..8c80728865
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/c_bool_constant.c
@@ -0,0 +1,11 @@
+// C boolean constants
+
+// Source: https://en.cppreference.com/w/c/language/bool_constant
+
+#include <assert.h>
+
+int main()
+{
+ assert(true == 1 && 0 == false);
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/c_character_constant.c b/mnv/runtime/syntax/testdir/input/c_character_constant.c
new file mode 100644
index 0000000000..56d028b1ae
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/c_character_constant.c
@@ -0,0 +1,41 @@
+// C character constants
+
+// Source: https://en.cppreference.com/w/c/language/character_constant
+
+#include <stddef.h>
+#include <stdio.h>
+#include <uchar.h>
+
+int main (void)
+{
+ printf("constant value \n");
+ printf("-------- ----------\n");
+
+ // integer character constants,
+ int c1='a'; printf("'a':\t %#010x\n", c1);
+ // implementation-defined
+ int c2='🍌'; printf("'🍌':\t %#010x\n\n", c2);
+
+ // multicharacter constant
+ int c3='ab'; printf("'ab':\t %#010x\n\n", c3); // implementation-defined
+
+ // 16-bit wide character constants
+ char16_t uc1 = u'a'; printf("'a':\t %#010x\n", (int)uc1);
+ char16_t uc2 = u'¢'; printf("'¢':\t %#010x\n", (int)uc2);
+ char16_t uc3 = u'猫'; printf("'猫':\t %#010x\n", (int)uc3);
+ // implementation-defined (🍌 maps to two 16-bit characters)
+ char16_t uc4 = u'🍌'; printf("'🍌':\t %#010x\n\n", (int)uc4);
+
+ // 32-bit wide character constants
+ char32_t Uc1 = U'a'; printf("'a':\t %#010x\n", (int)Uc1);
+ char32_t Uc2 = U'¢'; printf("'¢':\t %#010x\n", (int)Uc2);
+ char32_t Uc3 = U'猫'; printf("'猫':\t %#010x\n", (int)Uc3);
+ char32_t Uc4 = U'🍌'; printf("'🍌':\t %#010x\n\n", (int)Uc4);
+
+ // wide character constants
+ wchar_t wc1 = L'a'; printf("'a':\t %#010x\n", (int)wc1);
+ wchar_t wc2 = L'¢'; printf("'¢':\t %#010x\n", (int)wc2);
+ wchar_t wc3 = L'猫'; printf("'猫':\t %#010x\n", (int)wc3);
+ wchar_t wc4 = L'🍌'; printf("'🍌':\t %#010x\n\n", (int)wc4);
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/c_integer_constant.c b/mnv/runtime/syntax/testdir/input/c_integer_constant.c
new file mode 100644
index 0000000000..155fd8f74f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/c_integer_constant.c
@@ -0,0 +1,44 @@
+// C integer constants
+
+// Source: https://en.cppreference.com/w/c/language/integer_constant
+
+#include <inttypes.h>
+#include <stdio.h>
+
+int main(void)
+{
+ printf("123 = %d\n", 123);
+ printf("0123 = %d\n", 0123);
+ printf("0x123 = %d\n", 0x123);
+ printf("12345678901234567890ull = %llu\n", 12345678901234567890ull);
+ // the type is a 64-bit type (unsigned long long or possibly unsigned long)
+ // even without a long suffix
+ printf("12345678901234567890u = %"PRIu64"\n", 12345678901234567890u );
+
+ // printf("%lld\n", -9223372036854775808); // Error:
+ // the value 9223372036854775808 cannot fit in signed long long, which
+ // is the biggest type allowed for unsuffixed decimal integer constant
+
+ printf("%llu\n", -9223372036854775808ull );
+ // unary minus applied to unsigned value subtracts it from 2^64,
+ // this gives unsigned 9223372036854775808
+
+ printf("%lld\n", -9223372036854775807ll - 1);
+ // correct way to form signed value -9223372036854775808
+}
+
+// The following variables are initialized to the same value:
+
+int d = 42;
+int o = 052;
+int x = 0x2a;
+int X = 0X2A;
+int b = 0b101010; // C23
+
+// The following variables are also initialized to the same value:
+
+unsigned long long l1 = 18446744073709550592ull; // C99
+unsigned long long l2 = 18'446'744'073'709'550'592llu; // C23
+unsigned long long l3 = 1844'6744'0737'0955'0592uLL; // C23
+unsigned long long l4 = 184467'440737'0'95505'92LLU; // C23
+
diff --git a/mnv/runtime/syntax/testdir/input/c_keywords.c b/mnv/runtime/syntax/testdir/input/c_keywords.c
new file mode 100644
index 0000000000..fc994c299b
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/c_keywords.c
@@ -0,0 +1,64 @@
+// C keywords
+
+// Source: https://en.cppreference.com/w/c/keyword
+
+alignas // (C23)
+alignof // (C23)
+auto
+bool // (C23)
+break
+case
+char
+const
+constexpr // (C23)
+continue
+default
+do
+double
+else
+enum
+extern
+false // (C23)
+float
+for
+goto
+if
+inline // (C99)
+int
+long
+nullptr // (C23)
+register
+restrict // (C99)
+return
+short
+signed
+sizeof
+static
+static_assert // (C23)
+struct
+switch
+thread_local // (C23)
+true // (C23)
+typedef
+typeof // (C23)
+typeof_unqual // (C23)
+union
+unsigned
+void
+volatile
+while
+
+_Alignas // (C11)(deprecated in C23)
+_Alignof // (C11)(deprecated in C23)
+_Atomic // (C11)
+_BitInt // (C23)
+_Bool // (C99)(deprecated in C23)
+_Complex // (C99)
+_Decimal128 // (C23)
+_Decimal32 // (C23)
+_Decimal64 // (C23)
+_Generic // (C11)
+_Imaginary // (C99)
+_Noreturn // (C11)(deprecated in C23)
+_Static_assert // (C11)(deprecated in C23)
+_Thread_local // (C11)(deprecated in C23)
diff --git a/mnv/runtime/syntax/testdir/input/c_noreturn.c b/mnv/runtime/syntax/testdir/input/c_noreturn.c
new file mode 100644
index 0000000000..8b2202bf8e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/c_noreturn.c
@@ -0,0 +1,23 @@
+// C functions - _Noreturn function specifier (since C11)(deprecated in C23)
+
+// Source: https://en.cppreference.com/w/c/language/noreturn.html
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdnoreturn.h>
+
+// causes undefined behavior if i <= 0
+// exits if i > 0
+noreturn void exit_now(int i) // or _Noreturn void exit_now(int i)
+{
+ if (i > 0)
+ exit(i);
+}
+
+int main(void)
+{
+ puts("Preparing to exit...");
+ exit_now(2);
+ puts("This code is never executed.");
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/c_preprocessor_conditional.c b/mnv/runtime/syntax/testdir/input/c_preprocessor_conditional.c
new file mode 100644
index 0000000000..8faabcf10d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/c_preprocessor_conditional.c
@@ -0,0 +1,40 @@
+// C preprocessor - conditional inclusion
+
+// Source: https://en.cppreference.com/w/c/preprocessor/conditional
+
+#define ABCD 2
+#include <stdio.h>
+
+int main(void)
+{
+
+#ifdef ABCD
+ printf("1: yes\n");
+#else
+ printf("1: no\n");
+#endif
+
+#ifndef ABCD
+ printf("2: no1\n");
+#elif ABCD == 2
+ printf("2: yes\n");
+#else
+ printf("2: no2\n");
+#endif
+
+#if !defined(DCBA) && (ABCD < 2 * 4 - 3)
+ printf("3: yes\n");
+#endif
+
+// C23 directives #elifdef/#elifndef
+#ifdef CPU
+ printf("4: no1\n");
+#elifdef GPU
+ printf("4: no2\n");
+#elifndef RAM
+ printf("4: yes\n"); // selected in C23 mode, may be selected in pre-C23 mode
+#else
+ printf("4: no3\n"); // may be selected in pre-C23 mode
+#endif
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/c_preprocessor_embed.c b/mnv/runtime/syntax/testdir/input/c_preprocessor_embed.c
new file mode 100644
index 0000000000..3800cecef4
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/c_preprocessor_embed.c
@@ -0,0 +1,31 @@
+// C preprocessor - binary resource inclusion
+
+// Source: https://en.cppreference.com/w/c/preprocessor/embed
+
+#include <stdint.h>
+#include <stdio.h>
+
+const uint8_t image_data[] = {
+#embed "image.png"
+};
+
+const char message[] = {
+#embed "message.txt" if_empty('M', 'i', 's', 's', 'i', 'n', 'g', '\n')
+,'\0' // null terminator
+};
+
+void dump(const uint8_t arr[], size_t size)
+{
+ for (size_t i = 0; i != size; ++i)
+ printf("%02X%c", arr[i], (i + 1) % 16 ? ' ' : '\n');
+ puts("");
+}
+
+int main()
+{
+ puts("image_data[]:");
+ dump(image_data, sizeof image_data);
+ puts("message[]:");
+ dump((const uint8_t*)message, sizeof message);
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/c_preprocessor_error.c b/mnv/runtime/syntax/testdir/input/c_preprocessor_error.c
new file mode 100644
index 0000000000..ea89a31e7b
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/c_preprocessor_error.c
@@ -0,0 +1,19 @@
+// C preprocessor - diagnostic directives
+
+// Source: https://en.cppreference.com/w/c/preprocessor/error
+
+#if __STDC__ != 1
+# error "Not a standard compliant compiler"
+#endif
+
+#if __STDC_VERSION__ >= 202311L
+# warning "Using #warning as a standard feature"
+#endif
+
+#include <stdio.h>
+
+int main (void)
+{
+ printf("The compiler used conforms to the ISO C Standard !!");
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/c_string_literal.c b/mnv/runtime/syntax/testdir/input/c_string_literal.c
new file mode 100644
index 0000000000..cb67a40a2f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/c_string_literal.c
@@ -0,0 +1,59 @@
+// C string literals
+
+// Source: https://en.cppreference.com/w/c/language/string_literal
+
+#include <inttypes.h>
+#include <locale.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <uchar.h>
+
+int main(void)
+{
+ char s1[] = "a猫🍌"; // or "a\u732B\U0001F34C"
+#if __STDC_VERSION__ >= 202311L
+ char8_t
+#else
+ char
+#endif
+ s2[] = u8"a猫🍌";
+ char16_t s3[] = u"a猫🍌";
+ char32_t s4[] = U"a猫🍌";
+ wchar_t s5[] = L"a猫🍌";
+
+ setlocale(LC_ALL, "en_US.utf8");
+ printf(" \"%s\" is a char[%zu] holding { ", s1, sizeof s1 / sizeof *s1);
+ for(size_t n = 0; n < sizeof s1 / sizeof *s1; ++n)
+ printf("0x%02X ", +(unsigned char)s1[n]);
+ puts("}");
+ printf(
+#if __STDC_VERSION__ >= 202311L
+ "u8\"%s\" is a char8_t[%zu] holding { "
+#else
+ "u8\"%s\" is a char[%zu] holding { "
+#endif
+, s2, sizeof s2 / sizeof *s2);
+ for(size_t n = 0; n < sizeof s2 / sizeof *s2; ++n)
+#if __STDC_VERSION__ >= 202311L
+ printf("0x%02X ", s2[n]);
+#else
+ printf("0x%02X ", +(unsigned char)s2[n]);
+#endif
+ puts("}");
+ printf(" u\"a猫🍌\" is a char16_t[%zu] holding { ",
+ sizeof s3 / sizeof *s3);
+ for(size_t n = 0; n < sizeof s3 / sizeof *s3; ++n)
+ printf("0x%04" PRIXLEAST16" ", s3[n]);
+ puts("}");
+ printf(" U\"a猫🍌\" is a char32_t[%zu] holding { ",
+ sizeof s4 / sizeof *s4);
+ for(size_t n = 0; n < sizeof s4 / sizeof *s4; ++n)
+ printf("0x%08" PRIXLEAST32" ", s4[n]);
+ puts("}");
+ printf(" L\"%ls\" is a wchar_t[%zu] holding { ", s5, sizeof s5 / sizeof *s5);
+ for(size_t n = 0; n < sizeof s5 / sizeof *s5; ++n)
+ printf("0x%08X ", (unsigned)s5[n]);
+ puts("}");
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/codeowners.txt b/mnv/runtime/syntax/testdir/input/codeowners.txt
new file mode 100644
index 0000000000..c2fb96cb2d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/codeowners.txt
@@ -0,0 +1,12 @@
+# This is a comment.
+# Each line is a file pattern followed by one or more owners.
+
+* @global-owner1 @global-owner2
+*.js @js-owner #This is an inline comment.
+*.go docs@example.com
+*.txt @octo-org/octocats
+/a/b/ @doctocat
+docs/* docs@example.com @other
+**/logs @octocat
+
+# mnv: set ft=codeowners:
diff --git a/mnv/runtime/syntax/testdir/input/cpp_noreturn.cpp b/mnv/runtime/syntax/testdir/input/cpp_noreturn.cpp
new file mode 100644
index 0000000000..b4457e055e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/cpp_noreturn.cpp
@@ -0,0 +1,20 @@
+// C++ attributes - noreturn (since C++11)
+
+// Source: https://en.cppreference.com/w/c/language/noreturn.html [modified by MNV Project]
+
+#include <stdio.h>
+#include <stdlib.h>
+
+[[noreturn]] void error_exit(const char* reason)
+{
+ printf("Error: %s\n", reason);
+ exit(1);
+}
+
+int main(void)
+{
+ puts("Preparing to exit...");
+ error_exit("Assume something is wrong");
+ puts("This code is never executed.");
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/cpp_numbers.cpp b/mnv/runtime/syntax/testdir/input/cpp_numbers.cpp
new file mode 100644
index 0000000000..d6ef21b0ae
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/cpp_numbers.cpp
@@ -0,0 +1,20 @@
+void foo()
+{
+ {
+ // See https://en.cppreference.com/w/cpp/language/floating_literal
+ double a = 1.0E2;
+ double b = 1.0e2;
+ double c = 1E2;
+ double d = 1e2;
+
+ double e = 0X1ffp10;
+ double f = 0x1ffp10;
+ }
+
+ // See: https://en.cppreference.com/w/cpp/language/integer_literal
+ int a = 0X123;
+ int b = 0x123;
+
+ int c = 0B101;
+ int d = 0b101;
+}
diff --git a/mnv/runtime/syntax/testdir/input/csh.csh b/mnv/runtime/syntax/testdir/input/csh.csh
new file mode 100644
index 0000000000..1dfc1fd296
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/csh.csh
@@ -0,0 +1,6 @@
+# https://github.com/Project-Tick/Project-Tick/pull/19172#issuecomment-3751574224
+
+set script_dir="" #comment
+set script_dir=""
+set script_dir="" #
+
diff --git a/mnv/runtime/syntax/testdir/input/css_1.css b/mnv/runtime/syntax/testdir/input/css_1.css
new file mode 100644
index 0000000000..70a14127ce
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/css_1.css
@@ -0,0 +1,5 @@
+div {
+ margin-block: 1px;
+ margin-block-start: 1px;
+ margin-block-end: 1px;
+}
diff --git a/mnv/runtime/syntax/testdir/input/dts_zephyr.overlay b/mnv/runtime/syntax/testdir/input/dts_zephyr.overlay
new file mode 100644
index 0000000000..40d9aa6908
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/dts_zephyr.overlay
@@ -0,0 +1,16 @@
+/ {
+ chosen {
+ zephyr,uart-mcumgr = &cdc_acm_uart0;
+ zephyr,shell-uart = &cdc_acm_uart1;
+ };
+};
+
+&zephyr_udc0 {
+ cdc_acm_uart0: cdc_acm_uart0 {
+ compatible = "zephyr,cdc-acm-uart";
+ };
+
+ cdc_acm_uart1: cdc_acm_uart1 {
+ compatible = "zephyr,cdc-acm-uart";
+ };
+};
diff --git a/mnv/runtime/syntax/testdir/input/dts_zmk.keymap b/mnv/runtime/syntax/testdir/input/dts_zmk.keymap
new file mode 100644
index 0000000000..14fb210d09
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/dts_zmk.keymap
@@ -0,0 +1,23 @@
+#include <behaviors.dtsi>
+#include <dt-bindings/zmk/keys.h>
+
+// Define macro for layers.
+#define LAYER_MAIN 0
+
+/ {
+ keymap {
+ compatible = "zmk,keymap";
+
+ layer_0 {
+ bindings = <
+ &kp Z
+ &kp M
+ &kp K
+ &zmk_string
+ &to LAYER_MAIN
+ >;
+ };
+ };
+
+ ZMK_MACRO(zmk_string, wait-ms = <10>; tap-ms = <10>; bindings = <&macro_tap &kp Z &kp M &kp K>;)
+};
diff --git a/mnv/runtime/syntax/testdir/input/gdb.gdb b/mnv/runtime/syntax/testdir/input/gdb.gdb
new file mode 100644
index 0000000000..593da80954
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/gdb.gdb
@@ -0,0 +1,1655 @@
+# gdb --batch --ex 'help all' | sed 's/^\(Command class:\|Unclassified commands\)/\# \1/; s/ -- .*//; s/, /\n/g'
+
+
+# Command class: aliases
+
+
+# Command class: breakpoints
+
+awatch
+break
+brea
+bre
+br
+b
+break-range
+catch
+catch assert
+catch catch
+catch exception
+catch exec
+catch fork
+catch handlers
+catch load
+catch rethrow
+catch signal
+catch syscall
+catch throw
+catch unload
+catch vfork
+clear
+cl
+commands
+end
+condition
+delete
+del
+d
+delete bookmark
+delete breakpoints
+delete checkpoint
+delete display
+delete mem
+delete tracepoints
+delete tr
+delete tvariable
+disable
+disa
+dis
+disable breakpoints
+disable display
+disable frame-filter
+disable mem
+disable pretty-printer
+disable probes
+disable type-printer
+disable unwinder
+disable xmethod
+dprintf
+enable
+en
+enable breakpoints
+enable breakpoints count
+enable breakpoints delete
+enable breakpoints once
+enable count
+enable delete
+enable display
+enable frame-filter
+enable mem
+enable once
+enable pretty-printer
+enable probes
+enable type-printer
+enable unwinder
+enable xmethod
+ftrace
+hbreak
+ignore
+rbreak
+rwatch
+save
+save breakpoints
+save gdb-index
+save tracepoints
+skip
+skip delete
+skip disable
+skip enable
+skip file
+skip function
+strace
+tbreak
+tcatch
+tcatch assert
+tcatch catch
+tcatch exception
+tcatch exec
+tcatch fork
+tcatch handlers
+tcatch load
+tcatch rethrow
+tcatch signal
+tcatch syscall
+tcatch throw
+tcatch unload
+tcatch vfork
+thbreak
+trace
+trac
+tra
+tr
+tp
+watch
+
+# Command class: data
+
+agent-printf
+append
+append binary
+append binary memory
+append binary value
+append memory
+append value
+call
+disassemble
+display
+dump
+dump binary
+dump binary memory
+dump binary value
+dump ihex
+dump ihex memory
+dump ihex value
+dump memory
+dump srec
+dump srec memory
+dump srec value
+dump tekhex
+dump tekhex memory
+dump tekhex value
+dump value
+dump verilog
+dump verilog memory
+dump verilog value
+explore
+explore type
+explore value
+find
+init-if-undefined
+mem
+memory-tag
+memory-tag check
+memory-tag print-allocation-tag
+memory-tag print-logical-tag
+memory-tag set-allocation-tag
+memory-tag with-logical-tag
+output
+print
+inspect
+p
+print-object
+po
+printf
+ptype
+restore
+set
+set ada
+set ada print-signatures
+set ada source-charset
+set ada trust-PAD-over-XVS
+set agent
+set annotate
+set architecture
+set processor
+set args
+set auto-connect-native-target
+set auto-load
+set auto-load gdb-scripts
+set auto-load libthread-db
+set auto-load local-gdbinit
+set auto-load python-scripts
+set auto-load safe-path
+set auto-load scripts-directory
+set auto-solib-add
+set backtrace
+set backtrace limit
+set backtrace past-entry
+set backtrace past-main
+set basenames-may-differ
+set breakpoint
+set breakpoint always-inserted
+set breakpoint auto-hw
+set breakpoint condition-evaluation
+set breakpoint pending
+set can-use-hw-watchpoints
+set case-sensitive
+set charset
+set check
+set ch
+set c
+set check range
+set check type
+set circular-trace-buffer
+set code-cache
+set coerce-float-to-double
+set compile-args
+set compile-gcc
+set complaints
+set confirm
+set cp-abi
+set cwd
+set data-directory
+set dcache
+set dcache line-size
+set dcache size
+set debug
+set debug arch
+set debug auto-load
+set debug bfd-cache
+set debug check-physname
+set debug coff-pe-read
+set debug compile
+set debug compile-cplus-scopes
+set debug compile-cplus-types
+set debug displaced
+set debug dwarf-die
+set debug dwarf-line
+set debug dwarf-read
+set debug entry-values
+set debug event-loop
+set debug expression
+set debug fortran-array-slicing
+set debug frame
+set debug index-cache
+set debug infrun
+set debug jit
+set debug libthread-db
+set debug linux-namespaces
+set debug linux-nat
+set debug notification
+set debug observer
+set debug overload
+set debug parser
+set debug py-breakpoint
+set debug py-micmd
+set debug py-unwind
+set debug record
+set debug remote
+set debug remote-packet-max-chars
+set debug separate-debug-file
+set debug serial
+set debug skip
+set debug stap-expression
+set debug symbol-lookup
+set debug symfile
+set debug symtab-create
+set debug target
+set debug threads
+set debug timestamp
+set debug varobj
+set debug xml
+set debug-file-directory
+set debuginfod
+set debuginfod enabled
+set debuginfod urls
+set debuginfod verbose
+set default-collect
+set demangle-style
+set detach-on-fork
+set directories
+set disable-randomization
+set disassemble-next-line
+set disassembler-options
+set disassembly-flavor
+set disconnected-dprintf
+set disconnected-tracing
+set displaced-stepping
+set dprintf-channel
+set dprintf-function
+set dprintf-style
+set dump-excluded-mappings
+set editing
+set endian
+set environment
+set exec-direction
+set exec-done-display
+set exec-file-mismatch
+set exec-wrapper
+set extended-prompt
+set extension-language
+set filename-display
+set follow-exec-mode
+set follow-fork-mode
+set fortran
+set fortran repack-array-slices
+set frame-filter
+set frame-filter priority
+set gnutarget
+set g
+set guile
+set gu
+set guile print-stack
+set height
+set history
+set history expansion
+set history filename
+set history remove-duplicates
+set history save
+set history size
+set host-charset
+set index-cache
+set index-cache directory
+set index-cache enabled
+set inferior-tty
+set tty
+set input-radix
+set interactive-mode
+set language
+set libthread-db-search-path
+set listsize
+set logging
+set logging debugredirect
+set logging enabled
+set logging file
+set logging overwrite
+set logging redirect
+set max-completions
+set max-user-call-depth
+set max-value-size
+set may-call-functions
+set may-insert-breakpoints
+set may-insert-fast-tracepoints
+set may-insert-tracepoints
+set may-interrupt
+set may-write-memory
+set may-write-registers
+set mem
+set mem inaccessible-by-default
+set mi-async
+set mpx
+set mpx bound
+set multiple-symbols
+set non-stop
+set observer
+set opaque-type-resolution
+set osabi
+set output-radix
+set overload-resolution
+set pagination
+set print
+set pr
+set p
+set print address
+set print array
+set print array-indexes
+set print asm-demangle
+set print demangle
+set print elements
+set print entry-values
+set print finish
+set print frame-arguments
+set print frame-info
+set print inferior-events
+set print max-depth
+set print max-symbolic-offset
+set print memory-tag-violations
+set print null-stop
+set print object
+set print pascal_static-members
+set print pretty
+set print raw-frame-arguments
+set print raw-values
+set print repeats
+set print sevenbit-strings
+set print static-members
+set print symbol
+set print symbol-filename
+set print symbol-loading
+set print thread-events
+set print type
+set print type hex
+set print type methods
+set print type nested-type-limit
+set print type typedefs
+set print union
+set print vtbl
+set prompt
+set python
+set python dont-write-bytecode
+set python ignore-environment
+set python print-stack
+set radix
+set range-stepping
+set ravenscar
+set ravenscar task-switching
+set record
+set rec
+set record btrace
+set record btrace bts
+set record btrace bts buffer-size
+set record btrace cpu
+set record btrace cpu auto
+set record btrace cpu none
+set record btrace pt
+set record btrace pt buffer-size
+set record btrace replay-memory-access
+set record full
+set record full insn-number-max
+set record full memory-query
+set record full stop-at-limit
+set record function-call-history-size
+set record instruction-history-size
+set remote
+set remote TracepointSource-packet
+set remote Z-packet
+set remote access-watchpoint-packet
+set remote agent-packet
+set remote allow-packet
+set remote attach-packet
+set remote binary-download-packet
+set remote X-packet
+set remote breakpoint-commands-packet
+set remote btrace-conf-bts-size-packet
+set remote btrace-conf-pt-size-packet
+set remote catch-syscalls-packet
+set remote conditional-breakpoints-packet
+set remote conditional-tracepoints-packet
+set remote ctrl-c-packet
+set remote disable-btrace-packet
+set remote disable-randomization-packet
+set remote enable-btrace-bts-packet
+set remote enable-btrace-pt-packet
+set remote environment-hex-encoded-packet
+set remote environment-reset-packet
+set remote environment-unset-packet
+set remote exec-event-feature-packet
+set remote exec-file
+set remote fast-tracepoints-packet
+set remote fetch-register-packet
+set remote p-packet
+set remote fork-event-feature-packet
+set remote get-thread-information-block-address-packet
+set remote get-thread-local-storage-address-packet
+set remote hardware-breakpoint-limit
+set remote hardware-breakpoint-packet
+set remote hardware-watchpoint-length-limit
+set remote hardware-watchpoint-limit
+set remote hostio-close-packet
+set remote hostio-fstat-packet
+set remote hostio-open-packet
+set remote hostio-pread-packet
+set remote hostio-pwrite-packet
+set remote hostio-readlink-packet
+set remote hostio-setfs-packet
+set remote hostio-unlink-packet
+set remote hwbreak-feature-packet
+set remote install-in-trace-packet
+set remote interrupt-on-connect
+set remote interrupt-sequence
+set remote kill-packet
+set remote library-info-packet
+set remote library-info-svr4-packet
+set remote memory-map-packet
+set remote memory-read-packet-size
+set remote memory-tagging-feature-packet
+set remote memory-write-packet-size
+set remote multiprocess-feature-packet
+set remote no-resumed-stop-reply-packet
+set remote noack-packet
+set remote osdata-packet
+set remote pass-signals-packet
+set remote pid-to-exec-file-packet
+set remote program-signals-packet
+set remote query-attached-packet
+set remote read-aux-vector-packet
+set remote read-btrace-conf-packet
+set remote read-btrace-packet
+set remote read-fdpic-loadmap-packet
+set remote read-sdata-object-packet
+set remote read-siginfo-object-packet
+set remote read-watchpoint-packet
+set remote reverse-continue-packet
+set remote reverse-step-packet
+set remote run-packet
+set remote search-memory-packet
+set remote set-register-packet
+set remote P-packet
+set remote set-working-dir-packet
+set remote software-breakpoint-packet
+set remote startup-with-shell-packet
+set remote static-tracepoints-packet
+set remote supported-packets-packet
+set remote swbreak-feature-packet
+set remote symbol-lookup-packet
+set remote system-call-allowed
+set remote target-features-packet
+set remote thread-events-packet
+set remote threads-packet
+set remote trace-buffer-size-packet
+set remote trace-status-packet
+set remote traceframe-info-packet
+set remote unwind-info-block-packet
+set remote verbose-resume-packet
+set remote verbose-resume-supported-packet
+set remote vfork-event-feature-packet
+set remote write-siginfo-object-packet
+set remote write-watchpoint-packet
+set remoteaddresssize
+set remotecache
+set remoteflow
+set remotelogbase
+set remotelogfile
+set remotetimeout
+set remotewritesize
+set schedule-multiple
+set scheduler-locking
+set script-extension
+set serial
+set serial baud
+set serial parity
+set solib-search-path
+set source
+set source open
+set stack-cache
+set startup-quietly
+set startup-with-shell
+set step-mode
+set stop-on-solib-events
+set struct-convention
+set style
+set style address
+set style address background
+set style address foreground
+set style address intensity
+set style disassembler
+set style disassembler enabled
+set style enabled
+set style filename
+set style filename background
+set style filename foreground
+set style filename intensity
+set style function
+set style function background
+set style function foreground
+set style function intensity
+set style highlight
+set style highlight background
+set style highlight foreground
+set style highlight intensity
+set style metadata
+set style metadata background
+set style metadata foreground
+set style metadata intensity
+set style sources
+set style title
+set style title background
+set style title foreground
+set style title intensity
+set style tui-active-border
+set style tui-active-border background
+set style tui-active-border foreground
+set style tui-border
+set style tui-border background
+set style tui-border foreground
+set style variable
+set style variable background
+set style variable foreground
+set style variable intensity
+set style version
+set style version background
+set style version foreground
+set style version intensity
+set substitute-path
+set suppress-cli-notifications
+set sysroot
+set solib-absolute-prefix
+set target-charset
+set target-file-system-kind
+set target-wide-charset
+set tcp
+set tcp auto-retry
+set tcp connect-timeout
+set tdesc
+set tdesc filename
+set trace-buffer-size
+set trace-commands
+set trace-notes
+set trace-stop-notes
+set trace-user
+set trust-readonly-sections
+set tui
+set tui active-border-mode
+set tui border-kind
+set tui border-mode
+set tui compact-source
+set tui tab-width
+set unwind-on-terminating-exception
+set unwindonsignal
+set use-coredump-filter
+set use-deprecated-index-sections
+set variable
+set var
+set verbose
+set watchdog
+set width
+set write
+undisplay
+whatis
+with
+w
+x
+
+# Command class: files
+
+add-symbol-file
+add-symbol-file-from-memory
+cd
+core-file
+directory
+edit
+exec-file
+file
+forward-search
+fo
+search
+generate-core-file
+gcore
+list
+l
+load
+nosharedlibrary
+path
+pwd
+remote
+remote delete
+remote get
+remote put
+remove-symbol-file
+reverse-search
+rev
+section
+sharedlibrary
+symbol-file
+
+# Command class: internals
+
+maintenance
+mt
+maintenance agent
+maintenance agent-eval
+maintenance agent-printf
+maintenance btrace
+maintenance btrace clear
+maintenance btrace clear-packet-history
+maintenance btrace packet-history
+maintenance check
+maintenance check libthread-db
+maintenance check xml-descriptions
+maintenance check-psymtabs
+maintenance check-symtabs
+maintenance cplus
+maintenance cp
+maintenance cplus first_component
+maintenance demangler-warning
+maintenance deprecate
+maintenance dump-me
+maintenance expand-symtabs
+maintenance flush
+maintenance flush dcache
+maintenance flush register-cache
+maintenance flush source-cache
+maintenance flush symbol-cache
+maintenance info
+maintenance i
+maintenance info bfds
+maintenance info breakpoints
+maintenance info btrace
+maintenance info jit
+maintenance info line-table
+maintenance info program-spaces
+maintenance info psymtabs
+maintenance info sections
+maintenance info selftests
+maintenance info symtabs
+maintenance info target-sections
+maintenance internal-error
+maintenance internal-warning
+maintenance packet
+maintenance print
+maintenance print architecture
+maintenance print c-tdesc
+maintenance print cooked-registers
+maintenance print core-file-backed-mappings
+maintenance print dummy-frames
+maintenance print msymbols
+maintenance print objfiles
+maintenance print psymbols
+maintenance print raw-registers
+maintenance print reggroups
+maintenance print register-groups
+maintenance print registers
+maintenance print remote-registers
+maintenance print statistics
+maintenance print symbol-cache
+maintenance print symbol-cache-statistics
+maintenance print symbols
+maintenance print target-stack
+maintenance print type
+maintenance print user-registers
+maintenance print xml-tdesc
+maintenance selftest
+maintenance set
+maintenance set ada
+maintenance set ada ignore-descriptive-types
+maintenance set backtrace-on-fatal-signal
+maintenance set bfd-sharing
+maintenance set btrace
+maintenance set btrace pt
+maintenance set btrace pt skip-pad
+maintenance set catch-demangler-crashes
+maintenance set check-libthread-db
+maintenance set demangler-warning
+maintenance set demangler-warning quit
+maintenance set dwarf
+maintenance set dwarf always-disassemble
+maintenance set dwarf max-cache-age
+maintenance set dwarf unwinders
+maintenance set gnu-source-highlight
+maintenance set gnu-source-highlight enabled
+maintenance set internal-error
+maintenance set internal-error backtrace
+maintenance set internal-error corefile
+maintenance set internal-error quit
+maintenance set internal-warning
+maintenance set internal-warning backtrace
+maintenance set internal-warning corefile
+maintenance set internal-warning quit
+maintenance set per-command
+maintenance set per-command space
+maintenance set per-command symtab
+maintenance set per-command time
+maintenance set profile
+maintenance set selftest
+maintenance set selftest verbose
+maintenance set show-debug-regs
+maintenance set symbol-cache-size
+maintenance set target-async
+maintenance set target-non-stop
+maintenance set test-settings
+maintenance set test-settings auto-boolean
+maintenance set test-settings boolean
+maintenance set test-settings enum
+maintenance set test-settings filename
+maintenance set test-settings integer
+maintenance set test-settings optional-filename
+maintenance set test-settings string
+maintenance set test-settings string-noescape
+maintenance set test-settings uinteger
+maintenance set test-settings zinteger
+maintenance set test-settings zuinteger
+maintenance set test-settings zuinteger-unlimited
+maintenance set tui-resize-message
+maintenance set worker-threads
+maintenance show
+maintenance show ada
+maintenance show ada ignore-descriptive-types
+maintenance show backtrace-on-fatal-signal
+maintenance show bfd-sharing
+maintenance show btrace
+maintenance show btrace pt
+maintenance show btrace pt skip-pad
+maintenance show catch-demangler-crashes
+maintenance show check-libthread-db
+maintenance show demangler-warning
+maintenance show demangler-warning quit
+maintenance show dwarf
+maintenance show dwarf always-disassemble
+maintenance show dwarf max-cache-age
+maintenance show dwarf unwinders
+maintenance show gnu-source-highlight
+maintenance show gnu-source-highlight enabled
+maintenance show internal-error
+maintenance show internal-error backtrace
+maintenance show internal-error corefile
+maintenance show internal-error quit
+maintenance show internal-warning
+maintenance show internal-warning backtrace
+maintenance show internal-warning corefile
+maintenance show internal-warning quit
+maintenance show per-command
+maintenance show per-command space
+maintenance show per-command symtab
+maintenance show per-command time
+maintenance show profile
+maintenance show selftest
+maintenance show selftest verbose
+maintenance show show-debug-regs
+maintenance show symbol-cache-size
+maintenance show target-async
+maintenance show target-non-stop
+maintenance show test-options-completion-result
+maintenance show test-settings
+maintenance show test-settings auto-boolean
+maintenance show test-settings boolean
+maintenance show test-settings enum
+maintenance show test-settings filename
+maintenance show test-settings integer
+maintenance show test-settings optional-filename
+maintenance show test-settings string
+maintenance show test-settings string-noescape
+maintenance show test-settings uinteger
+maintenance show test-settings zinteger
+maintenance show test-settings zuinteger
+maintenance show test-settings zuinteger-unlimited
+maintenance show tui-resize-message
+maintenance show worker-threads
+maintenance space
+maintenance test-options
+maintenance test-options require-delimiter
+maintenance test-options unknown-is-error
+maintenance test-options unknown-is-operand
+maintenance time
+maintenance translate-address
+maintenance undeprecate
+maintenance with
+
+# Command class: obscure
+
+checkpoint
+compare-sections
+compile
+expression
+compile code
+end
+compile file
+end
+compile print
+end
+complete
+guile
+end
+gu
+end
+guile-repl
+gr
+monitor
+python
+end
+py
+end
+python-interactive
+pi
+record
+rec
+record btrace
+record b
+record btrace bts
+record bts
+record btrace pt
+record pt
+record delete
+record del
+record d
+record full
+record full restore
+record function-call-history
+record goto
+record goto begin
+record goto start
+record goto end
+record instruction-history
+record save
+record stop
+record s
+restart
+stop
+
+# Command class: running
+
+advance
+attach
+continue
+fg
+c
+detach
+detach checkpoint
+detach inferiors
+disconnect
+finish
+fin
+handle
+inferior
+interrupt
+jump
+j
+kill
+kill inferiors
+next
+n
+nexti
+ni
+queue-signal
+reverse-continue
+rc
+reverse-finish
+reverse-next
+rn
+reverse-nexti
+rni
+reverse-step
+rs
+reverse-stepi
+rsi
+run
+r
+signal
+start
+starti
+step
+s
+stepi
+si
+taas
+target
+target core
+target ctf
+target exec
+target extended-remote
+target native
+target record-btrace
+target record-core
+target record-full
+target remote
+target tfile
+task
+task apply
+task apply all
+tfaas
+thread
+t
+thread apply
+thread apply all
+thread find
+thread name
+until
+u
+
+# Command class: stack
+
+backtrace
+where
+bt
+down
+dow
+do
+faas
+frame
+f
+frame address
+frame apply
+frame apply all
+frame apply level
+frame function
+frame level
+frame view
+return
+select-frame
+select-frame address
+select-frame function
+select-frame level
+select-frame view
+up
+
+# Command class: status
+
+info
+inf
+i
+info address
+info all-registers
+info args
+info auto-load
+info auto-load gdb-scripts
+info auto-load libthread-db
+info auto-load local-gdbinit
+info auto-load python-scripts
+info auxv
+info bookmarks
+info breakpoints
+info b
+info checkpoints
+info classes
+info common
+info connections
+info copying
+info dcache
+info display
+info exceptions
+info extensions
+info files
+info float
+info frame
+info f
+info frame address
+info frame function
+info frame level
+info frame view
+info frame-filter
+info functions
+info guile
+info gu
+info inferiors
+info line
+info locals
+info macro
+info macros
+info mem
+info module
+info module functions
+info module variables
+info modules
+info os
+info pretty-printer
+info probes
+info probes all
+info probes dtrace
+info probes stap
+info proc
+info proc all
+info proc cmdline
+info proc cwd
+info proc exe
+info proc files
+info proc mappings
+info proc stat
+info proc status
+info program
+info record
+info rec
+info registers
+info r
+info scope
+info selectors
+info sharedlibrary
+info dll
+info signals
+info handle
+info skip
+info source
+info sources
+info stack
+info s
+info static-tracepoint-markers
+info symbol
+info target
+info tasks
+info terminal
+info threads
+info tracepoints
+info tp
+info tvariables
+info type-printers
+info types
+info unwinder
+info variables
+info vector
+info vtbl
+info warranty
+info watchpoints
+info win
+info xmethod
+macro
+macro define
+macro expand
+macro exp
+macro expand-once
+macro exp1
+macro list
+macro undef
+show
+info set
+show ada
+show ada print-signatures
+show ada source-charset
+show ada trust-PAD-over-XVS
+show agent
+show annotate
+show architecture
+show args
+show auto-connect-native-target
+show auto-load
+show auto-load gdb-scripts
+show auto-load libthread-db
+show auto-load local-gdbinit
+show auto-load python-scripts
+show auto-load safe-path
+show auto-load scripts-directory
+show auto-solib-add
+show backtrace
+show backtrace limit
+show backtrace past-entry
+show backtrace past-main
+show basenames-may-differ
+show breakpoint
+show breakpoint always-inserted
+show breakpoint auto-hw
+show breakpoint condition-evaluation
+show breakpoint pending
+show can-use-hw-watchpoints
+show case-sensitive
+show charset
+show check
+show ch
+show c
+show check range
+show check type
+show circular-trace-buffer
+show code-cache
+show coerce-float-to-double
+show commands
+show compile-args
+show compile-gcc
+show complaints
+show configuration
+show confirm
+show convenience
+show conv
+show copying
+show cp-abi
+show cwd
+show data-directory
+show dcache
+show dcache line-size
+show dcache size
+show debug
+show debug arch
+show debug auto-load
+show debug bfd-cache
+show debug check-physname
+show debug coff-pe-read
+show debug compile
+show debug compile-cplus-scopes
+show debug compile-cplus-types
+show debug displaced
+show debug dwarf-die
+show debug dwarf-line
+show debug dwarf-read
+show debug entry-values
+show debug event-loop
+show debug expression
+show debug fortran-array-slicing
+show debug frame
+show debug index-cache
+show debug infrun
+show debug jit
+show debug libthread-db
+show debug linux-namespaces
+show debug linux-nat
+show debug notification
+show debug observer
+show debug overload
+show debug parser
+show debug py-breakpoint
+show debug py-micmd
+show debug py-unwind
+show debug record
+show debug remote
+show debug remote-packet-max-chars
+show debug separate-debug-file
+show debug serial
+show debug skip
+show debug stap-expression
+show debug symbol-lookup
+show debug symfile
+show debug symtab-create
+show debug target
+show debug threads
+show debug timestamp
+show debug varobj
+show debug xml
+show debug-file-directory
+show debuginfod
+show debuginfod enabled
+show debuginfod urls
+show debuginfod verbose
+show default-collect
+show demangle-style
+show detach-on-fork
+show directories
+show disable-randomization
+show disassemble-next-line
+show disassembler-options
+show disassembly-flavor
+show disconnected-dprintf
+show disconnected-tracing
+show displaced-stepping
+show dprintf-channel
+show dprintf-function
+show dprintf-style
+show dump-excluded-mappings
+show editing
+show endian
+show environment
+show exec-direction
+show exec-done-display
+show exec-file-mismatch
+show exec-wrapper
+show extended-prompt
+show extension-language
+show filename-display
+show follow-exec-mode
+show follow-fork-mode
+show fortran
+show fortran repack-array-slices
+show frame-filter
+show frame-filter priority
+show gnutarget
+show guile
+show gu
+show guile print-stack
+show height
+show history
+show history expansion
+show history filename
+show history remove-duplicates
+show history save
+show history size
+show host-charset
+show index-cache
+show index-cache directory
+show index-cache enabled
+show index-cache stats
+show inferior-tty
+show input-radix
+show interactive-mode
+show language
+show libthread-db-search-path
+show listsize
+show logging
+show logging debugredirect
+show logging enabled
+show logging file
+show logging overwrite
+show logging redirect
+show max-completions
+show max-user-call-depth
+show max-value-size
+show may-call-functions
+show may-insert-breakpoints
+show may-insert-fast-tracepoints
+show may-insert-tracepoints
+show may-interrupt
+show may-write-memory
+show may-write-registers
+show mem
+show mem inaccessible-by-default
+show mi-async
+show mpx
+show mpx bound
+show multiple-symbols
+show non-stop
+show observer
+show opaque-type-resolution
+show osabi
+show output-radix
+show overload-resolution
+show pagination
+show paths
+show print
+show pr
+show p
+show print address
+show print array
+show print array-indexes
+show print asm-demangle
+show print demangle
+show print elements
+show print entry-values
+show print finish
+show print frame-arguments
+show print frame-info
+show print inferior-events
+show print max-depth
+show print max-symbolic-offset
+show print memory-tag-violations
+show print null-stop
+show print object
+show print pascal_static-members
+show print pretty
+show print raw-frame-arguments
+show print raw-values
+show print repeats
+show print sevenbit-strings
+show print static-members
+show print symbol
+show print symbol-filename
+show print symbol-loading
+show print thread-events
+show print type
+show print type hex
+show print type methods
+show print type nested-type-limit
+show print type typedefs
+show print union
+show print vtbl
+show prompt
+show python
+show python dont-write-bytecode
+show python ignore-environment
+show python print-stack
+show radix
+show range-stepping
+show ravenscar
+show ravenscar task-switching
+show record
+show rec
+show record btrace
+show record btrace bts
+show record btrace bts buffer-size
+show record btrace cpu
+show record btrace pt
+show record btrace pt buffer-size
+show record btrace replay-memory-access
+show record full
+show record full insn-number-max
+show record full memory-query
+show record full stop-at-limit
+show record function-call-history-size
+show record instruction-history-size
+show remote
+show remote TracepointSource-packet
+show remote Z-packet
+show remote access-watchpoint-packet
+show remote agent-packet
+show remote allow-packet
+show remote attach-packet
+show remote binary-download-packet
+show remote X-packet
+show remote breakpoint-commands-packet
+show remote btrace-conf-bts-size-packet
+show remote btrace-conf-pt-size-packet
+show remote catch-syscalls-packet
+show remote conditional-breakpoints-packet
+show remote conditional-tracepoints-packet
+show remote ctrl-c-packet
+show remote disable-btrace-packet
+show remote disable-randomization-packet
+show remote enable-btrace-bts-packet
+show remote enable-btrace-pt-packet
+show remote environment-hex-encoded-packet
+show remote environment-reset-packet
+show remote environment-unset-packet
+show remote exec-event-feature-packet
+show remote exec-file
+show remote fast-tracepoints-packet
+show remote fetch-register-packet
+show remote p-packet
+show remote fork-event-feature-packet
+show remote get-thread-information-block-address-packet
+show remote get-thread-local-storage-address-packet
+show remote hardware-breakpoint-limit
+show remote hardware-breakpoint-packet
+show remote hardware-watchpoint-length-limit
+show remote hardware-watchpoint-limit
+show remote hostio-close-packet
+show remote hostio-fstat-packet
+show remote hostio-open-packet
+show remote hostio-pread-packet
+show remote hostio-pwrite-packet
+show remote hostio-readlink-packet
+show remote hostio-setfs-packet
+show remote hostio-unlink-packet
+show remote hwbreak-feature-packet
+show remote install-in-trace-packet
+show remote interrupt-on-connect
+show remote interrupt-sequence
+show remote kill-packet
+show remote library-info-packet
+show remote library-info-svr4-packet
+show remote memory-map-packet
+show remote memory-read-packet-size
+show remote memory-tagging-feature-packet
+show remote memory-write-packet-size
+show remote multiprocess-feature-packet
+show remote no-resumed-stop-reply-packet
+show remote noack-packet
+show remote osdata-packet
+show remote pass-signals-packet
+show remote pid-to-exec-file-packet
+show remote program-signals-packet
+show remote query-attached-packet
+show remote read-aux-vector-packet
+show remote read-btrace-conf-packet
+show remote read-btrace-packet
+show remote read-fdpic-loadmap-packet
+show remote read-sdata-object-packet
+show remote read-siginfo-object-packet
+show remote read-watchpoint-packet
+show remote reverse-continue-packet
+show remote reverse-step-packet
+show remote run-packet
+show remote search-memory-packet
+show remote set-register-packet
+show remote P-packet
+show remote set-working-dir-packet
+show remote software-breakpoint-packet
+show remote startup-with-shell-packet
+show remote static-tracepoints-packet
+show remote supported-packets-packet
+show remote swbreak-feature-packet
+show remote symbol-lookup-packet
+show remote system-call-allowed
+show remote target-features-packet
+show remote thread-events-packet
+show remote threads-packet
+show remote trace-buffer-size-packet
+show remote trace-status-packet
+show remote traceframe-info-packet
+show remote unwind-info-block-packet
+show remote verbose-resume-packet
+show remote verbose-resume-supported-packet
+show remote vfork-event-feature-packet
+show remote write-siginfo-object-packet
+show remote write-watchpoint-packet
+show remoteaddresssize
+show remotecache
+show remoteflow
+show remotelogbase
+show remotelogfile
+show remotetimeout
+show remotewritesize
+show schedule-multiple
+show scheduler-locking
+show script-extension
+show serial
+show serial baud
+show serial parity
+show solib-search-path
+show source
+show source open
+show stack-cache
+show startup-quietly
+show startup-with-shell
+show step-mode
+show stop-on-solib-events
+show struct-convention
+show style
+show style address
+show style address background
+show style address foreground
+show style address intensity
+show style disassembler
+show style disassembler enabled
+show style enabled
+show style filename
+show style filename background
+show style filename foreground
+show style filename intensity
+show style function
+show style function background
+show style function foreground
+show style function intensity
+show style highlight
+show style highlight background
+show style highlight foreground
+show style highlight intensity
+show style metadata
+show style metadata background
+show style metadata foreground
+show style metadata intensity
+show style sources
+show style title
+show style title background
+show style title foreground
+show style title intensity
+show style tui-active-border
+show style tui-active-border background
+show style tui-active-border foreground
+show style tui-border
+show style tui-border background
+show style tui-border foreground
+show style variable
+show style variable background
+show style variable foreground
+show style variable intensity
+show style version
+show style version background
+show style version foreground
+show style version intensity
+show substitute-path
+show suppress-cli-notifications
+show sysroot
+show solib-absolute-prefix
+show target-charset
+show target-file-system-kind
+show target-wide-charset
+show tcp
+show tcp auto-retry
+show tcp connect-timeout
+show tdesc
+show tdesc filename
+show trace-buffer-size
+show trace-commands
+show trace-notes
+show trace-stop-notes
+show trace-user
+show trust-readonly-sections
+show tui
+show tui active-border-mode
+show tui border-kind
+show tui border-mode
+show tui compact-source
+show tui tab-width
+show unwind-on-terminating-exception
+show unwindonsignal
+show use-coredump-filter
+show use-deprecated-index-sections
+show user
+show values
+show varsize-limit
+show verbose
+show version
+show warranty
+show watchdog
+show width
+show write
+
+# Command class: support
+
+add-auto-load-safe-path
+add-auto-load-scripts-directory
+alias
+apropos
+define
+end
+define-prefix
+demangle
+document
+end
+dont-repeat
+down-silently
+echo
+help
+h
+if
+interpreter-exec
+make
+new-ui
+overlay
+ov
+ovly
+overlay auto
+overlay list-overlays
+overlay load-target
+overlay manual
+overlay map-overlay
+overlay off
+overlay unmap-overlay
+pipe
+|
+quit
+exit
+q
+shell
+!
+source
+up-silently
+while
+
+# Command class: text-user-interface
+
++
+-
+<
+>
+focus
+fs
+layout
+layout asm
+layout next
+layout prev
+layout regs
+layout split
+layout src
+refresh
+tui
+tui disable
+tui enable
+tui new-layout
+tui reg
+update
+winheight
+wh
+
+# Command class: tracepoints
+
+actions
+collect
+end
+passcount
+tdump
+teval
+tfind
+tfind end
+tfind none
+tfind line
+tfind outside
+tfind pc
+tfind range
+tfind start
+tfind tracepoint
+tsave
+tstart
+tstatus
+tstop
+tvariable
+while-stepping
+stepping
+ws
+
+# Command class: user-defined
+
+
+# Unclassified commands
+
+add-inferior
+clone-inferior
+eval
+flash-erase
+function
+function _any_caller_is
+function _any_caller_matches
+function _as_string
+function _caller_is
+function _caller_matches
+function _cimag
+function _creal
+function _gdb_maint_setting
+function _gdb_maint_setting_str
+function _gdb_setting
+function _gdb_setting_str
+function _isvoid
+function _memeq
+function _regex
+function _streq
+function _strlen
+jit-reader-load
+jit-reader-unload
+remove-inferiors
+unset
+unset environment
+unset exec-wrapper
+unset substitute-path
+unset tdesc
+unset tdesc filename
diff --git a/mnv/runtime/syntax/testdir/input/gdb_multiline_commands.gdb b/mnv/runtime/syntax/testdir/input/gdb_multiline_commands.gdb
new file mode 100644
index 0000000000..6738921d9a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/gdb_multiline_commands.gdb
@@ -0,0 +1,41 @@
+# GDB multiline commands
+# MNV_TEST_SETUP setl fdc=2 fdl=999 fdm=syntax
+
+define hello
+ echo Hello, world!\n
+end
+
+document Foo
+ Print a greeting.
+end
+
+commands
+ echo Hello, world!\n
+end
+
+compile code
+ printf("Hello, world!\n");
+end
+
+expression code
+ printf("Hello, world!\n");
+end
+
+python
+ print("Hello, world!\n")
+end
+
+guile
+ (display "Hello, world!\n")
+end
+
+while 0
+ echo Not this time\n
+end
+
+if 1
+ echo Yes\n
+else
+ echo No\n
+end
+
diff --git a/mnv/runtime/syntax/testdir/input/haskell.hs b/mnv/runtime/syntax/testdir/input/haskell.hs
new file mode 100644
index 0000000000..c8607920e1
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/haskell.hs
@@ -0,0 +1,4 @@
+-- Issue #18776 (allow spaces in backticked operators)
+
+main = print (9 ` div ` 4)
+
diff --git a/mnv/runtime/syntax/testdir/input/help.txt b/mnv/runtime/syntax/testdir/input/help.txt
new file mode 100644
index 0000000000..d7eb03271f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/help.txt
@@ -0,0 +1,61 @@
+
+
+ MNV REFERENCE MANUAL by Bram Moolenaar
+ and Somebody Else
+ and Another Person
+
+
+ MNV USER MANUAL by Bram Moolenaar
+ and Somebody Else
+ and Another Person
+
+
+MNV HELP FILE FORMAT
+
+
+Issue #17721 (Strange >mnv highlighting in help documentation?)~
+
+ *restore-cursor* *last-position-jump* >mnv
+ augroup RestoreCursor
+ autocmd!
+ autocmd BufReadPost *
+ \ let line = line("'\"")
+ \ | if line >= 1 && line <= line("$") && &filetype !~# 'commit'
+ \ && index(['xxd', 'gitrebase'], &filetype) == -1
+ \ && !&diff
+ \ | execute "normal! g`\""
+ \ | endif
+ augroup END
+
+
+URLs~
+
+ *g:zig_recommended_style*
+By default the following indentation options are set, in accordance with Zig's
+recommended style (https://ziglang.org/documentation/master/): >
+
+
+NOTE, WARNING and DEPRECATED~
+
+When you 'send a file to MNV', MNV changes to that file's directory. Note,
+however, that any long directory names will appear in their short (MS-DOS)
+form on some Windows versions. This is a limitation of the Windows "Send To"
+mechanism.
+
+
+EXAMPLE LANGUAGES~
+ *mnv9-mix*
+There is one way to use both legacy and MNV9 syntax in one script file: >mnv9
+
+ " legacy MNV script comments may go here
+ if !has('mnv9script')
+ " legacy MNV script commands go here
+ finish
+ endif
+ mnv9script
+ # MNV9 script commands go here
+
+This allows for writing a script that takes advantage of the MNV9 script
+syntax if possible, but will also work on a MNV version without it.
+
+ mnv:tw=78:ts=8:noet:ft=help:norl:
diff --git a/mnv/runtime/syntax/testdir/input/help_ex_version.txt b/mnv/runtime/syntax/testdir/input/help_ex_version.txt
new file mode 100644
index 0000000000..474e1800f8
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/help_ex_version.txt
@@ -0,0 +1,238 @@
+
+
+ *:ve* *:ver* *:version*
+:ve[rsion] Print the version number of the editor. If the
+ compiler used understands "__DATE__" the compilation
+ date is mentioned. Otherwise a fixed release-date is
+ shown.
+ The following lines contain information about which
+ features were enabled when MNV was compiled. When
+ there is a preceding '+', the feature is included,
+ when there is a '-' it is excluded. To change this,
+ you have to edit feature.h and recompile MNV.
+ To check for this in an expression, see |has()|.
+ Here is an overview of the features.
+ The first column shows the smallest version in which
+ they are included:
+ T tiny (always)
+ N normal
+ H huge
+ m manually enabled or depends on other features
+ - never, feature was removed
+ (none) system dependent
+ Thus if a feature is marked with "N", it is included
+ in the normal and huge versions of MNV.
+
+ *+feature-list*
+ *+acl* |ACL| support included
+ *+ARP* Amiga only: ARP support included
+H *+arabic* |Arabic| language support
+N *+autochdir* support 'autochdir' option
+T *+autocmd* |:autocmd|, automatic commands. Always enabled since
+ 8.0.1564
+H *+autoservername* Automatically enable |clientserver|
+m *+balloon_eval* |balloon-eval| support in the GUI. Included when
+ compiling with supported GUI (Motif, GTK, GUI) and
+ either Netbeans/Sun Workshop integration or |+eval|
+ feature.
+H *+balloon_eval_term* |balloon-eval| support in the terminal,
+ 'balloonevalterm'
+N *+browse* |:browse| command
+T *++builtin_terms* maximal terminals builtin |builtin-terms| Always
+ enabled since 9.0.0280
+N *+byte_offset* support for 'o' flag in 'statusline' option, "go"
+ and ":goto" commands.
+m *+channel* inter process communication |channel|
+T *+cindent* 'cindent', C indenting; Always enabled
+N *+clientserver* Unix and Win32: Remote invocation |clientserver|
+ *+clipboard* |clipboard| support compiled-in
+N *+clipboard_provider* |clipboard-providers| support compiled-in
+ *+clipboard_working* |clipboard| support compiled-in and working
+ *+clipboard_star_avail*
+ |clipboard| support compiled-in and star "*" register
+ available
+ *+clipboard_plus_avail*
+ |clipboard| support compiled-in and separate plus "+"
+ register available
+T *+cmdline_compl* command line completion |cmdline-completion|
+T *+cmdline_hist* command line history |cmdline-history|
+T *+cmdline_info* 'showcmd' and 'ruler'; Always enabled since
+ 9.0.0747
+T *+cmdwin* |cmdline-window| support; Always enabled since 9.0.0657
+T *+comments* 'comments' support
+N *+conceal* "conceal" support, see |conceal| |:syn-conceal| etc.
+N *+cryptv* encryption support |encryption|
+H *+cscope* |cscope| support
+T *+cursorbind* 'cursorbind' support
+m *+cursorshape* |termcap-cursor-shape| support
+m *+debug* Compiled for debugging.
+N *+dialog_gui* Support for |:confirm| with GUI dialog.
+N *+dialog_con* Support for |:confirm| with console dialog.
+N *+dialog_con_gui* Support for |:confirm| with GUI and console dialog.
+N *+diff* |mnvdiff| and 'diff'
+N *+digraphs* |digraphs| *E196*
+ *+directx* Win32 GUI only: DirectX and 'renderoptions'
+ *+dnd* Support for DnD into the "~ register |quote_~|.
+H *+emacs_tags* |emacs-tags| files
+N *+eval* expression evaluation |eval.txt|
+T *+ex_extra* always on now, used to be for MNV's extra Ex commands
+N *+extra_search* 'hlsearch' and 'incsearch' options.
+- *+farsi* Removed: |farsi| language
+T *+file_in_path* |gf|, |CTRL-W_f| and |<cfile>| Always enabled since
+ 9.0.265
+N *+find_in_path* include file searches: |[I|, |:isearch|,
+ |CTRL-W_CTRL-I|, |:checkpath|, etc.
+N *+folding* |folding|
+ *+footer* |gui-footer|
+ *+fork* Unix only: |fork| shell commands
+T *+float* Floating point support Always enabled since 9.0.0491
+N *+gettext* message translations |multi-lang|
+- *+GUI_Athena* Unix only: Athena |GUI|
+ *+GUI_neXtaw* Unix only: neXtaw |GUI|
+ *+GUI_GTK* Unix only: GTK+ |GUI|
+ *+GUI_Motif* Unix only: Motif |GUI|
+ *+GUI_Photon* QNX only: Photon |GUI|
+m *+hangul_input* Hangul input support |hangul|
+ *+iconv* Compiled with the |iconv()| function
+ *+iconv/dyn* Likewise |iconv-dynamic| |/dyn|
+T *+insert_expand* |insert_expand| Insert mode completion
+m *+ipv6* Support for IPv6 networking |channel|
+m *+job* starting and stopping jobs |job|
+T *+jumplist* |jumplist|; Always enabled since 8.2.3795
+H *+keymap* 'keymap'
+N *+lambda* |lambda| and |closure|
+H *+langmap* 'langmap'
+N *+libcall* |libcall()|
+N *+linebreak* 'linebreak', 'breakat' and 'showbreak'
+T *+lispindent* 'lisp'
+T *+listcmds* MNV commands for the list of buffers |buffer-hidden|
+ and argument list |:argdelete|
+T *+localmap* Support for mappings local to a buffer |:map-local|
+m *+lua* |Lua| interface
+m *+lua/dyn* |Lua| interface |/dyn|
+N *+menu* |:menu|
+N *+mksession* |:mksession|
+T *+modify_fname* |filename-modifiers|
+T *+mouse* Mouse handling |mouse-using|
+N *+mouseshape* 'mouseshape'
+N *+mouse_dec* Unix only: Dec terminal mouse handling |dec-mouse|
+N *+mouse_gpm* Unix only: Linux console mouse handling |gpm-mouse|
+m *+mouse_gpm/dyn* Same as |+mouse_gpm| with optional library dependency
+ |/dyn|
+N *+mouse_jsbterm* JSB mouse handling |jsbterm-mouse|
+N *+mouse_netterm* Unix only: netterm mouse handling |netterm-mouse|
+N *+mouse_pterm* QNX only: pterm mouse handling |qnx-terminal|
+N *+mouse_sysmouse* Unix only: *BSD console mouse handling |sysmouse|
+N *+mouse_sgr* Unix only: sgr mouse handling |sgr-mouse|
+N *+mouse_urxvt* Unix only: urxvt mouse handling |urxvt-mouse|
+N *+mouse_xterm* Unix only: xterm mouse handling |xterm-mouse|
+T *+multi_byte* Unicode support, 16 and 32 bit characters |multibyte|
+ *+multi_byte_ime* Win32 input method for multibyte chars |multibyte-ime|
+N *+multi_lang* non-English language support |multi-lang|
+m *+mzscheme* Mzscheme interface |mzscheme|
+m *+mzscheme/dyn* Mzscheme interface |mzscheme-dynamic| |/dyn|
+m *+netbeans_intg* |netbeans|
+T *+num64* 64-bit Number support |Number|
+ Always enabled since 8.2.0271, use v:numbersize to
+ check the actual size of a Number.
+m *+ole* Win32 GUI only: |ole-interface|
+N *+packages* Loading |packages|
+T *+path_extra* Up/downwards search in 'path' and 'tags' Always
+ enabled since 9.0.0270
+m *+perl* Perl interface |perl|
+m *+perl/dyn* Perl interface |perl-dynamic| |/dyn|
+N *+persistent_undo* Persistent undo |undo-persistence|
+N *+popupwin* Popup windows |popup-window|
+ *+postscript* |:hardcopy| writes a PostScript file
+N *+printer* |:hardcopy| command
+H *+profile* |:profile| command
+m *+python* Python 2 interface |python|
+m *+python/dyn* Python 2 interface |python-dynamic| |/dyn|
+m *+python3* Python 3 interface |python|
+m *+python3/dyn* Python 3 interface |python-dynamic| |/dyn|
+m *+python3/dyn-stable*
+ Python 3 interface |python-dynamic| |python-stable|
+ |/dyn|
+N *+quickfix* |:make| and |quickfix| commands
+N *+reltime* |reltime()| function, 'hlsearch'/'incsearch' timeout,
+ 'redrawtime' option
+H *+rightleft* Right to left typing 'rightleft'
+m *+ruby* Ruby interface |ruby|
+m *+ruby/dyn* Ruby interface |ruby-dynamic| |/dyn|
+T *+scrollbind* 'scrollbind'
+N *+signs* |:sign|
+T *+smartindent* 'smartindent'
+N *+socketserver* Unix only: socket server backend for clientserver
+ functionality
+H *+sodium* compiled with libsodium for better encryption support
+H *+sound* |sound_playevent()|, |sound_playfile()| functions, etc.
+N *+spell* spell checking support, see |spell|
+N *+startuptime* |--startuptime| argument
+N *+statusline* Options 'statusline', 'rulerformat' and special
+ formats of 'titlestring' and 'iconstring'
+- *+sun_workshop* Removed: |workshop|
+N *+syntax* Syntax highlighting |syntax|
+ *+system()* Unix only: opposite of |+fork|
+H *+tabpanel* Support for |tabpanel|
+T *+tag_binary* binary searching in tags file |tag-binary-search|
+- *+tag_old_static* Removed; method for static tags |tag-old-static|
+- *+tag_any_white* Removed; was to allow any white space in tags files
+m *+tcl* Tcl interface |tcl|
+m *+tcl/dyn* Tcl interface |tcl-dynamic| |/dyn|
+m *+terminal* Support for terminal window |terminal|
+ *+terminfo* uses |terminfo| instead of termcap
+N *+termresponse* support for |t_RV| and |v:termresponse|
+N *+termguicolors* 24-bit color in xterm-compatible terminals support
+T *+textobjects* |text-objects| selection. Always enabled since 9.0.0222.
+N *+textprop* |text-properties|
+ *+tgetent* non-Unix only: able to use external termcap
+N *+timers* the |timer_start()| function
+T *+title* Setting the window 'title' and 'icon'; Always enabled
+N *+toolbar* |gui-toolbar|
+T *+user_commands* User-defined commands. |user-commands|
+ Always enabled since 8.1.1210.
+H *+vartabs* Variable-width tab stops. 'vartabstop'
+T *+vertsplit* Vertically split windows |:vsplit|; Always enabled
+ since 8.0.1118.
+T *+mnv9script* |MNV9| script
+N *+mnvinfo* 'mnvinfo'
+T *+virtualedit* 'virtualedit' Always enabled since 8.1.826.
+T *+visual* Visual mode |Visual-mode| Always enabled since 7.4.200.
+T *+visualextra* extra Visual mode commands |blockwise-operators|
+T *+vreplace* |gR| and |gr|
+ *+vtp* on MS-Windows console: support for 'termguicolors'
+N *+wayland* Unix only: support for the Wayland protocol.
+N *+wayland_clipboard* Unix only: support for Wayland selections/clipboard.
+N *+wayland_focus_steal*
+ Unix only: support for Wayland clipboard on
+ compositors without a data control protocol
+T *+wildignore* 'wildignore' Always enabled since 9.0.0278
+T *+wildmenu* 'wildmenu' Always enabled since 9.0.0279
+T *+windows* more than one window; Always enabled since 8.0.1118.
+m *+writebackup* 'writebackup' is default on
+m *+xim* X input method |xim|
+ *+xfontset* X fontset support |xfontset|
+N *+xattr* compiled with extended attribute support (Linux only)
+ *+xpm* pixmap support
+m *+xpm_w32* Win32 GUI only: pixmap support |w32-xpm-support|
+ *+xsmp* XSMP (X session management) support
+ *+xsmp_interact* interactive XSMP (X session management) support
+N *+xterm_clipboard* Unix only: xterm clipboard handling
+m *+xterm_save* save and restore xterm screen |xterm-screens|
+N *+X11* Unix only: can restore window title |X11|
+
+ */dyn* *E370* *E448*
+ To some of the features "/dyn" is added when the
+ feature is only available when the related library can
+ be dynamically loaded.
+
+:ve[rsion] {nr} Is now ignored. This was previously used to check the
+ version number of a .mnvrc file. It was removed,
+ because you can now use the ":if" command for
+ version-dependent behavior.
+
+ *:redi* *:redir*
+:redi[r][!] > {file} Redirect messages to file {file}. The messages which
+
+
+ mnv:tw=78:ts=8:noet:ft=help:norl:
diff --git a/mnv/runtime/syntax/testdir/input/html.html b/mnv/runtime/syntax/testdir/input/html.html
new file mode 100644
index 0000000000..4a9b7a471d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/html.html
@@ -0,0 +1,153 @@
+<!--
+ HTML Syntax Test File
+ Maintainer: Doug Kearns <dougkearns@gmail.com>
+ Last Change: 2024 Jun 13
+ MNV_TEST_SETUP let g:html_no_rendering = 1
+
+ TODO: Investigate macOS test failures when comparing italicized text with,
+ for example, <em> and <i> elements. FreeBSD fails with an empty <strike>
+ element. See #13591 and #14215.
+-->
+
+<!-- HTML Elements -->
+<a></a>
+<abbr></abbr>
+<address></address>
+<area>
+<article></article>
+<aside></aside>
+<audio></audio>
+<b>bring attention to</b>
+<base>
+<bdi></bdi>
+<bdo></bdo>
+<blockquote></blockquote>
+<body></body>
+<br>
+<button></button>
+<canvas></canvas>
+<caption></caption>
+<cite></cite>
+<code></code>
+<col>
+<colgroup></colgroup>
+<data></data>
+<datalist></datalist>
+<dd></dd>
+<del>deleted text</del>
+<details></details>
+<dfn></dfn>
+<dialog></dialog>
+<div></div>
+<dl></dl>
+<dt></dt>
+<em>emphasis</em>
+<embed>
+<fieldset></fieldset>
+<figcaption></figcaption>
+<figure></figure>
+<footer></footer>
+<form></form>
+<h1>Heading Level 1</h1>
+<h2>Heading Level 3</h2>
+<h3>Heading Level 4</h3>
+<h4>Heading Level 4</h4>
+<h5>Heading Level 5</h5>
+<h6>Heading Level 6</h6>
+<head></head>
+<header></header>
+<hgroup></hgroup>
+<hr>
+<html></html>
+<i>idiomatic text</i>
+<iframe></iframe>
+<img>
+<input>
+<ins></ins>
+<kbd></kbd>
+<label></label>
+<legend></legend>
+<li></li>
+<link>
+<main></main>
+<map></map>
+<mark></mark>
+<menu></menu>
+<meta>
+<meter></meter>
+<nav></nav>
+<noscript></noscript>
+<object></object>
+<ol></ol>
+<optgroup></optgroup>
+<option></option>
+<output></output>
+<p></p>
+<picture></picture>
+<pre>preformatted text</pre>
+<progress></progress>
+<q></q>
+<rp></rp>
+<rt></rt>
+<ruby></ruby>
+<!-- FreeBSD failure
+<s>strikethrough</s>
+-->
+<samp></samp>
+<script></script>
+<search></search>
+<section></section>
+<select></select>
+<slot></slot>
+<small></small>
+<source>
+<span></span>
+<strong>strong importance</strong>
+<style></style>
+<sub></sub>
+<summary></summary>
+<sup></sup>
+<table></table>
+<tbody></tbody>
+<td></td>
+<template></template>
+<textarea></textarea>
+<tfoot></tfoot>
+<th></th>
+<thead></thead>
+<time></time>
+<title></title>
+<tr></tr>
+<track>
+<u>unarticulated annotation</u>
+<ul></ul>
+<var></var>
+<video></video>
+<wbr>
+<xmp></xmp>
+
+<!-- Deprecated Elements -->
+<acronym></acronym>
+<big></big>
+<center></center>
+<dir></dir>
+<font></font>
+<frame></frame>
+<frameset></frameset>
+<marquee></marquee>
+<menuitem></menuitem>
+<nobr></nobr>
+<noframes></noframes>
+<param>
+<rb></rb>
+<rtc></rtc>
+<strike>strikethrough</strike>
+<tt></tt>
+
+<!-- Experimental - not highlighted -->
+<portal></portal>
+
+<!-- Note: these deprecated elements have never been matched -->
+<image>
+<noembed>
+<plaintext>
diff --git a/mnv/runtime/syntax/testdir/input/html_fold_expr.html b/mnv/runtime/syntax/testdir/input/html_fold_expr.html
new file mode 100644
index 0000000000..81be6463a7
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/html_fold_expr.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<!--
+MNV_TEST_SETUP setlocal foldcolumn=8 foldlevel=8 foldmethod=expr
+
+
+
+-->
+<html lang="en"> <!-- 1 -->
+<HEAD> <!-- 2 -->
+<meta charset="UTF-8">
+<title>A folding syntax test</title><style> /* 3 FIXME */
+p { font-size: 24px; } /* </style>
+<style>*/</style></head></head></head></head>
+
+<bOdY STYLE="background: #bebebe"> <!-- 2 -->
+<br><br><br><br><script><![CDATA[ // 3
+// \x3C!--
+// \x3Cscript>
+// \x3C/script>
+// -->
+]]></script>
+<h2 id="></h2>"><i>An H2 header</i></h2>
+<br><br><br><br>
+<hr>
+
+<p>Paragraph #1. <!-- 3 -->
+</p>
+
+<p>Paragraph #2.
+
+<details> <!-- 3 </details> -->
+<summary> <!-- 4 </summary> -->
+</summary>
+<p>Paragraph #1.
+<ul> <!-- 4 -->
+<li>Item a.</li><li>Item b.</li>
+<li>Item c.
+</ul>
+<p>Paragraph #2. <!-- 4 -->
+</p>
+</details>
+
+<dl> <!-- 3 -->
+<dt>A quick brown fox jumps over the lazy dog
+<dd>Woof!
+<dl> <!-- 4 -->
+<dt>A quick brown fox jumps over the lazy dog
+<dd>Woof!
+</dl>
+</dl>
+
+<article>Thread #1 <!-- 3 -->
+<article>Thread #2 <!-- 4 -->
+</article>
+</article>
+
+<p> <!-- 3 -->
+<label for="selection">Select Option</label>
+<select
+id="selection"
+name="selection"> <!-- 4 -->
+<optgroup label="Primary Group"> <!-- 5 -->
+<option value="1">Alternative
+<option value="2" selected>Default
+<option value="3">Basic
+<option value="4">Extended
+</optgroup>
+</select>
+</p>
+
+<table> <!-- 3 -->
+<caption>Some Caption</caption>
+<colgroup><col><col><col>
+<thead>
+<tr><th>Header #1<th>Header #2<th>Header #3
+<tbody>
+<tr><td>Column #1<td>Column #2<td>Column #3
+<tr><td>Column #1<td>Column #2<td>Column #3
+<tr><td>Column #1<td>Column #2<td>Column #3
+<tr><td>Column #1<td>Column #2<td>Column #3
+</table>
+
+<div class="block"> <!-- 3 -->
+<blockquote><pre><code> <!-- 4 -->
+&lt;div class="block"&gt;
+&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;
+&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/div&gt;
+</code></pre></blockquote></div>
+
+<p>Paragraph #3.</p><p>Paragraph #4.</p><p>Paragraph #5.
+
+<p>Paragraph #6.</p><p>Paragraph #7.</p><p>Paragraph #8.</p><p>Paragraph #9.</p>
+
+<p id="></p>">Paragraph #10. <!-- 3 -->
+</p>
+
+<p >Paragraph #11.</p><p id="p"
+class="p">Paragraph #12.</p><p
+class="p">Paragraph #13.</p><p
+>Paragraph #14.</p>
+
+<p>Paragraph #15.
+<p>Paragraph #16.
+</BoDy>
+</HTML>
diff --git a/mnv/runtime/syntax/testdir/input/html_fold_syntax.html b/mnv/runtime/syntax/testdir/input/html_fold_syntax.html
new file mode 100644
index 0000000000..6be4ccb9a6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/html_fold_syntax.html
@@ -0,0 +1,105 @@
+<!DOCTYPE html>
+<!--
+MNV_TEST_SETUP let g:html_syntax_folding = 1
+MNV_TEST_SETUP setlocal foldcolumn=8 foldlevel=8 foldmethod=syntax
+
+
+-->
+<html lang="en"> <!-- 1 -->
+<HEAD> <!-- 2 -->
+<meta charset="UTF-8">
+<title>A folding syntax test</title><style> /* 3 */
+p { font-size: 24px; } /* </style>
+<style>*/</style></head></head></head></head>
+
+<bOdY STYLE="background: #bebebe"> <!-- 2 -->
+<br><br><br><br><script><![CDATA[ // 3
+// \x3C!--
+// \x3Cscript>
+// \x3C/script>
+// -->
+]]></script>
+<h2 id="></h2>"><i>An H2 header</i></h2>
+<br><br><br><br>
+<hr>
+
+<p>Paragraph #1. <!-- 3 -->
+</p>
+
+<p>Paragraph #2.</p>
+
+<details> <!-- 3 </details> -->
+<summary> <!-- 4 </summary> -->
+</summary>
+<p>Paragraph #1.</p>
+<ul> <!-- 4 FIXME -->
+<li>Item a.</li><li>Item b.</li>
+<li>Item c.</li>
+</ul>
+<p>Paragraph #2. <!-- 4 FIXME -->
+</p>
+</details>
+
+<dl> <!-- 3 -->
+<dt>A quick brown fox jumps over the lazy dog</dt>
+<dd>Woof! <!-- 4 -->
+<dl> <!-- 5 -->
+<dt>A quick brown fox jumps over the lazy dog</dt>
+<dd>Woof!</dd>
+</dl></dd>
+</dl>
+
+<article>Thread #1 <!-- 3 -->
+<article>Thread #2 <!-- 4 -->
+</article>
+</article>
+
+<p> <!-- 3 -->
+<label for="selection">Select Option</label>
+<select
+id="selection"
+name="selection"> <!-- 5 -->
+<optgroup label="Primary Group"> <!-- 5 -->
+<option value="1">Alternative</option>
+<option value="2" selected>Default</option>
+<option value="3">Basic</option>
+<option value="4">Extended</option>
+</optgroup>
+</select>
+</p>
+
+<table> <!-- 3 -->
+<caption>Some Caption</caption>
+<colgroup><col><col><col></colgroup>
+<thead> <!-- 4 -->
+<tr><th>Header #1</th><th>Header #2</th><th>Header #3</th></tr>
+</thead><tbody>
+<tr><td>Column #1</td><td>Column #2</td><td>Column #3</td></tr>
+<tr><td>Column #1</td><td>Column #2</td><td>Column #3</td></tr>
+<tr><td>Column #1</td><td>Column #2</td><td>Column #3</td></tr>
+<tr><td>Column #1</td><td>Column #2</td><td>Column #3</td></tr>
+</tbody></table>
+
+<div class="block"> <!-- 3 -->
+<blockquote><pre><code> <!-- 6 -->
+&lt;div class="block"&gt;
+&lt;blockquote&gt;&lt;pre&gt;&lt;code&gt;
+&lt;/code&gt;&lt;/pre&gt;&lt;/blockquote&gt;&lt;/div&gt;
+</code></pre></blockquote></div>
+
+<p>Paragraph #3.</p><p>Paragraph #4.</p><p>Paragraph #5.</p>
+
+<p>Paragraph #6.</p><p>Paragraph #7.</p><p>Paragraph #8.</p><p>Paragraph #9.</p>
+
+<p id="></p>">Paragraph #10. <!-- 3 FIXME -->
+</p>
+
+<p >Paragraph #11.</p><p id="p"
+class="p">Paragraph #12.</p><p
+class="p">Paragraph #13.</p><p
+>Paragraph #14.</p>
+
+<p>Paragraph #15. <!-- UNBALANCED! -->
+<p>Paragraph #16. <!-- UNBALANCED! -->
+</BoDy>
+</HTML>
diff --git a/mnv/runtime/syntax/testdir/input/java_annotations.java b/mnv/runtime/syntax/testdir/input/java_annotations.java
new file mode 100644
index 0000000000..969f3b3be5
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_annotations.java
@@ -0,0 +1,78 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'style'
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+class AnnotationsTests
+{
+ @Target(ElementType.TYPE_USE)
+ @interface Tag
+ {
+ String value() default "";
+ String kind() default "";
+ }
+
+ @Target(ElementType.TYPE_USE)
+ @interface Text
+ {
+ String[] value() default {""};
+ }
+
+ @Target({
+ ElementType.METHOD,
+ ElementType.PARAMETER,
+ ElementType.TYPE,
+ })
+ @interface Labels
+ {
+ Label[] value();
+ }
+
+ @java.lang.annotation.Target({
+ java.lang.annotation.ElementType.METHOD,
+ java.lang.annotation.ElementType.PARAMETER,
+ java.lang.annotation.ElementType.TYPE,
+ })
+ @java.lang.annotation.Repeatable(Labels.class)
+ @interface Label
+ {
+ String value() default "";
+ Class<?> type() default Label.class;
+ boolean redundant() default true;
+ Text text() default @Text;
+ Tag head() default @Tag();
+ Tag tail() default @Tag(value = "", kind = "");
+ }
+
+ /* Use identity cast expressions to nest TYPE_USE annotations. */
+ @Label(
+ (@Text({
+ (@Text({ "a", "aa", "aaa", "aaaa", }) String) "as",
+ (@Text({ "b", "bb", "bbb", "bbbb", }) String) "bs",
+ (@Text({ "c", "cc", "ccc", "cccc", }) String) "cs",
+ (@Text({ "d", "dd", "ddd", "dddd", }) String) "ds",
+ }) String) "abcd")
+ interface Primer { }
+
+ @Label @Label() @Label("""
+ n\
+ o\
+ O\
+ p""")
+ @Label(head = @Tag(value = "@Label"/*, kind = "name"*/))
+ @Label(// value = "Method",
+ type = AnnotationsTests.class,
+ redundant = !!!(1 != 1),
+ head = @Tag(value = "@Label"),
+ text = @Text({ "})", "({" }))
+ static void noOp(@Label @Label() @Label("dummy")
+ @Label(head = @Tag(/*value = "@Label",*/ kind = "name"))
+ @Label(// value = "Parameter",
+ type = AnnotationsTests.class,
+ head = @Tag(value = "@Label"),
+ text = @Text({ "){", "}(" }))
+ Object dummy)
+ {
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_annotations_signature.java b/mnv/runtime/syntax/testdir/input/java_annotations_signature.java
new file mode 100644
index 0000000000..c85732a704
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_annotations_signature.java
@@ -0,0 +1,78 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'style'
+// MNV_TEST_SETUP let g:java_highlight_signature = 1
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+class Annotations$Tests
+{
+ @Target(ElementType.TYPE_USE)
+ @interface Tag
+ {
+ String value() default "";
+ String kind() default "";
+ }
+
+ @Target(ElementType.TYPE_USE)
+ @interface Text
+ {
+ String[] value() default {""};
+ }
+
+ @Target({
+ ElementType.METHOD,
+ ElementType.PARAMETER,
+ ElementType.TYPE,
+ })
+ @interface Labels
+ {
+ Label[] value();
+ }
+
+ @java.lang.annotation.Target({
+ java.lang.annotation.ElementType.METHOD,
+ java.lang.annotation.ElementType.PARAMETER,
+ java.lang.annotation.ElementType.TYPE,
+ })
+ @java.lang.annotation.Repeatable(Labels.class)
+ @interface Label
+ {
+ String value() default "";
+ Class<?> type() default Label.class;
+ boolean redundant() default true;
+ Text text() default @Text;
+ Tag head() default @Tag();
+ Tag tail() default @Tag(value = "", kind = "");
+ }
+
+ /* Use identity cast expressions to nest TYPE_USE annotations. */
+ @Label(
+ (@Text({
+ (@Text({ "a", "aa", "aaa", "aaaa", }) String) "as",
+ (@Text({ "b", "bb", "bbb", "bbbb", }) String) "bs",
+ (@Text({ "c", "cc", "ccc", "cccc", }) String) "cs",
+ (@Text({ "d", "dd", "ddd", "dddd", }) String) "ds",
+ }) String) "abcd")
+ interface Primer { }
+
+ @Label @Label() @Label("""
+ n\
+ o\
+ O\
+ p""")
+ @Label(head = @Tag(value = "@Label"/*, kind = "name"*/))
+ @Label(// value = "Method",
+ type = Annotations$Tests.class,
+ redundant = !!!(1 != 1),
+ head = @Tag(value = "@Label"),
+ text = @Text({ "})", "({" }))
+ static void noOp(@Label @Label() @Label("dummy")
+ @Label(head = @Tag(/*value = "@Label",*/ kind = "name"))
+ @Label(// value = "Parameter",
+ type = Annotations$Tests.class,
+ head = @Tag(value = "@Label"),
+ text = @Text({ "){", "}(" }))
+ Object dummy)
+ {
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_comments_html.java b/mnv/runtime/syntax/testdir/input/java_comments_html.java
new file mode 100644
index 0000000000..6951344443
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_comments_html.java
@@ -0,0 +1,131 @@
+// MNV_TEST_SETUP unlet! g:java_no_tab_space_error g:java_ignore_javadoc
+// MNV_TEST_SETUP unlet! g:java_no_trail_space_error
+// MNV_TEST_SETUP unlet! g:java_consent_to_html_syntax_folding
+// MNV_TEST_SETUP let[g:java_space_errors,g:java_comment_strings]=[1,1]
+// MNV_TEST_SETUP let[g:java_ignore_markdown,g:html_syntax_folding]=[1,1]
+// MNV_TEST_SETUP let g:markdown_fenced_languages = ["java"]
+
+
+
+
+// MNV_TEST_SETUP setlocal spell fdc=2 fdl=64 fdm=syntax fen
+// MNV_TEST_SETUP highlight link javaCommentStart Todo
+// MNV_TEST_SETUP highlight link javaCommentTitle Underlined
+
+
+
+
+
+
+
+/**/ /*/ */ /* /*/ /*/*/ /*//*/ /** HTML comment tests.
+ * <p>There is no entry point method {@code main}:
+ * {@snippet file = HTMLSnippets.java region = main id = _01}
+ * <p>There is no textual representation:
+ * {@snippet class = HTMLSnippets region = toString id = _02} */
+class HTMLCommentsTests implements Comparable<HTMLCommentsTests>
+{ // JDK 21+.
+ private HTMLCommentsTests() { }
+
+ /** No-op, i. e. no operation.
+ * ({@literal@literal} may be used with {@code .} for contraction.)
+ * @return {@code null} */
+ Void noOp1() { return null; }
+
+ /** No-op, i.e. no operation.
+ * ({@literal<!-- -->} may be used after {@code .} for contraction.)
+ * @return {@code null} */
+ Void noOp2() { return null; }
+
+ /** No-op, i.e\u002e no operation.
+ * ({@literal\u005cu002e} is processed early, use alternatives.)
+ * @return {@code null} */
+ Void noOp3() { return null; }
+
+ /** No-op, i.e{@literal .} no operation.
+ * @return {@code null} */
+ Void noOp4() { return null; }
+
+ /** No-op, i.e.<!-- --> no operation.
+ * @return {@code null} */
+ Void noOp5() { return null; }
+
+ /** No-op, i.e.&nbsp;no operation.
+ * @return {@code null} */
+ Void noOp6() { return null; }
+
+ /** {@return {@code null}, with no-op, i.e. no operation} */
+ Void noOp7() { return null; }
+
+ /** {@return {@code null}, with no-op, i.e. no operation}.. */
+ Void noOp8() { return null; }
+
+ /** {@return {@code null}, with no-op, i.e. no operation} . . */
+ Void noOp9() { return null; }
+
+ /** {@return the major Java version}
+ * @hidden */
+ protected int majorVersion() { return 21; }
+
+ /** {@summary Compares this instance with the passed {@code that}
+ * instance for order by invoking {@link Integer#compare(int, int)
+ * compare} and passing it {@code this.majorVersion()} and
+ * {@code that.majorVersion()} as respective @arguments.}
+ * {@inheritDoc} */
+ @Override public int compareTo(HTMLCommentsTests that)
+ {
+ java.util.Objects.requireNonNull(that, "that");
+ return Integer.compare(this.majorVersion(),
+ that.majorVersion());
+ }
+
+ /// Returns an empty string for an @Override annotated method
+ /// (see Chapter 9.6.4.4 {@literal @Override} in a Java Language
+ /// Specification) overridden from `java.lang.Object`
+ ///
+ /// @return an empty string /// No period for the above summary!
+ private String asString() { return ""; }
+
+ /** Returns an empty string for an @Override annotated method
+ * (see Chapter 9.6.4.4 {@literal @Override} in a Java Language
+ * Specification) overridden from <code>java.lang.Object</code>
+ *
+ * @return an empty string */// No period for the above summary!
+ @Override public String toString() { return asString(); }
+}
+
+// javadoc --snippet-path . --source-path . -d /tmp/html_docs/ -package \
+// -tag 'jls:a:See Java Language Specification:' HTMLSnippets.java
+/** Snippets for HTML comment tests. */
+class HTMLSnippets
+{ /* TRAILING BLANKS AND MESSPILLINGS ARE SIGNIFICANT! */
+ private HTMLSnippets() { }
+
+ /** The method {@code main} must be declared {@code public}, {@code
+ * static}, and {@code void}. It must specify a formal parameter
+ * whose declared type is array of {@link String}. Therefore,
+ * <em>either</em> of the following declarations is acceptable:
+ * {@snippet lang="java":
+ * // @highlight substring="main" type="italic":
+ * public static void main(String[] args) { }
+ * }<br /><pre class="snippet">
+ *{@code public static void main(String... args) { }}</pre>
+ *
+ * @param args optional commande-line arguments
+ * @jls 12.1.4 Invoke {@code Test.main} */
+ // @start region = main
+ // @link substring = 'String' target = 'java.lang.String' :
+ public static void main(String[] args) { }
+ // @end
+
+ /** {@return an empty string}
+ * @see <a href="https://docs.oracle.com/javase/specs/jls/se21/html/jls-3.html#jls-3.10.5">3.10.5 String Literals</a>
+ * @see
+ * <a href="https://docs.oracle.com/javase/specs/jls/se21/html/jls-4.html#jls-4.3.2">4.3.2 The Class Object</a>
+ * @see java.base/java.lang.Object#toString() */
+ // @start region = toString
+ // @replace substring = '""' replacement = "\u0022\u0022"
+ // @link regex = '\bString' target = java.lang.String type = linkplain :
+ @Override public String toString() { return ""; }
+ // @end
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_comments_markdown.java b/mnv/runtime/syntax/testdir/input/java_comments_markdown.java
new file mode 100644
index 0000000000..1e4d56e529
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_comments_markdown.java
@@ -0,0 +1,147 @@
+// MNV_TEST_SETUP unlet! g:java_no_tab_space_error g:java_ignore_javadoc
+// MNV_TEST_SETUP unlet! g:java_no_trail_space_error
+// MNV_TEST_SETUP let[g:java_space_errors,g:java_comment_strings]=[1,1]
+// MNV_TEST_SETUP let[g:java_ignore_html,g:markdown_syntax_conceal]=[1,1]
+// MNV_TEST_SETUP let g:html_syntax_folding = 1
+// MNV_TEST_SETUP let g:java_consent_to_html_syntax_folding = 1
+// MNV_TEST_SETUP let g:markdown_fenced_languages = ["java"]
+
+
+// MNV_TEST_SETUP defer execute('match Visual /\%>21l\s\+$/')
+// MNV_TEST_SETUP setl spell fdc=2 fdl=64 fdm=syntax fen cole=3 cocu=n
+// MNV_TEST_SETUP highlight link javaCommentStart Todo
+// MNV_TEST_SETUP highlight link javaMarkdownCommentTitle Underlined
+// MNV_TEST_SETUP highlight link markdownH2 NonText
+// MNV_TEST_SETUP highlight link markdownHeadingRule NonText
+
+
+
+
+
+/**/ /*/ */ /* /*/ /*/*/ /*//*/ /// Markdown comment tests.
+///
+/// There is no entry point method `main`:
+/// {@snippet file = MarkdownSnippets.java region = main id = _01}
+///
+/// There is no textual representation:
+/// {@snippet class = MarkdownSnippets region = toString id = _02}
+class MarkdownCommentsTests implements Comparable<MarkdownCommentsTests>
+{ // JDK 23+.
+ private MarkdownCommentsTests() { }
+
+ /// No-op, i. e. no operation.
+ /// ({@literal@literal} may be used with `.` for contraction.)
+ /// @return `null`
+ Void noOp1() { return null; }
+
+ /// No-op, i.e. no operation.
+ /// ({@literal<!-- -->} may be used after `.` for contraction.)
+ /// @return `null`
+ Void noOp2() { return null; }
+
+ /// No-op, i.e\u002e no operation.
+ /// ({@literal\u005cu002e} is processed early, use alternatives.)
+ /// @return `null`
+ Void noOp3() { return null; }
+
+ /// No-op, i.e{@literal .} no operation.
+ /// @return `null`
+ Void noOp4() { return null; }
+
+ /// No-op, i.e.<!-- --> no operation.
+ /// @return `null`
+ Void noOp5() { return null; }
+
+ /// No-op, i.e.&nbsp;no operation.
+ /// @return `null`
+ Void noOp6() { return null; }
+
+ /// {@return `null`, with no-op, i.e. no operation}
+ Void noOp7() { return null; }
+
+ /// {@return `null`, with no-op, i.e. no operation}..
+ Void noOp8() { return null; }
+
+ /// {@return `null`, with no-op, i.e. no operation} . .
+ Void noOp9() { return null; }
+
+ /// {@return the major Java version}
+ /// @hidden
+ protected int majorVersion() { return 23; }
+
+ /// {@summary Compares this instance with the passed `that`
+ /// instance for order by invoking [Integer.compare(int, int)]
+ /// and passing it `this.majorVersion()` and
+ /// `that.majorVersion()` as respective @arguments.}
+ /// {@inheritDoc}
+ @Override public int compareTo(MarkdownCommentsTests that)
+ {
+ java.util.Objects.requireNonNull(that, "that");
+ return Integer.compare(this.majorVersion(),
+ that.majorVersion());
+ }
+
+ /** Returns an empty string for an @Override annotated method
+ * (see Chapter 9.6.4.4 {@literal @Override} in a Java Language
+ * Specification) overridden from <code>java.lang.Object</code>
+ *
+ * @return an empty string */// No period for the above summary!
+ private String asString() { return ""; }
+
+ /// Returns an empty string for an @Override annotated method
+ /// (see Chapter 9.6.4.4 {@literal @Override} in a Java Language
+ /// Specification) overridden from `java.lang.Object`
+ ///
+ /// @return an empty string /// No period for the above summary!
+ @Override public String toString() { return asString(); }
+
+ /// A summary comment.
+ static final String MARKDOWN_COMMENT_A = "///";
+ /// No summary comment (try fiddling with the above string value).
+ static final String MARKDOWN_COMMENT_B = "///";
+}
+
+// javadoc --snippet-path . --source-path . -d /tmp/md_docs/ -package \
+// -tag 'jls:a:See Java Language Specification:' MarkdownSnippets.java
+/// Snippets for Markdown comment tests.
+class MarkdownSnippets
+{ /* TRAILING BLANKS AND MESSPILLINGS ARE SIGNIFICANT! */
+ private MarkdownSnippets() { }
+
+ /// The method [`main`] must be declared `public`,
+ /// `static`, and `void`. It must specify a formal parameter
+ /// whose declared type is array of [String]. Therefore,
+ /// _either_ of the following declarations is acceptable. [^\*]
+ ///
+ /// ---------------------------------------------------------------
+ /// DECLARATIONS ([main(String\[\])][#main(String\[\])]):
+ /// -----------------------------------------------------
+ /// * E.g. {@snippet lang="java":
+ /// // @highlight substring="main" type="italic":
+ /// public static void main(String[] args) { }
+ /// }
+ /// + E.g.
+ /// <pre class="snippet">
+ /// public static void main(String... args) { }
+ /// </pre>
+ ///
+ /// @param args optional commande-line arguments
+ /// @jls 12.1.4 Invoke `Test.main`
+ ///
+ /// [^\*]: @jls 12.1.4 Invoke `Test.main`
+ // @start region = main
+ // @link substring = 'String' target = 'java.lang.String' :
+ public static void main(String[] args) { }
+ // @end
+
+ /// {@return an empty string}
+ /// @see String [3.10.5 String Literals](https://docs.oracle.com/javase/specs/jls/se21/html/jls-3.html#jls-3.10.5)
+ /// @see Object
+ /// [4.3.2 The Class Object](https://docs.oracle.com/javase/specs/jls/se21/html/jls-4.html#jls-4.3.2)
+ /// @see java.base/java.lang.Object#toString()
+ // @start region = toString
+ // @replace substring = '""' replacement = "\u0022\u0022"
+ // @link regex = '\bString' target = java.lang.String type = linkplain :
+ @Override public String toString() { return ""; }
+ // @end
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_contextual_keywords.java b/mnv/runtime/syntax/testdir/input/java_contextual_keywords.java
new file mode 100644
index 0000000000..af1377cf2f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_contextual_keywords.java
@@ -0,0 +1,52 @@
+// MNV_TEST_SETUP highlight link javaConceptKind NonText
+
+
+
+class ContextualKeywordsTests // See JLS, §3.9 Keywords.
+{
+ private ContextualKeywordsTests() { throw new Error(); }
+
+ // ModuleDeclaration: module open.
+ void module() { Object module = null; when(); }
+ void open() { Object open = null; module(); }
+ // ModuleDirective: exports opens provides requires to uses with.
+ void exports() { Object exports = null; open(); }
+ void opens() { Object opens = null; exports(); }
+ void provides() { Object provides = null; opens(); }
+ void requires() { Object requires = null; provides(); }
+ void to() { Object to = null; requires(); }
+ void uses() { Object uses = null; to(); }
+ void with() { Object with = null; uses(); }
+ // RequiresModifier: transitive.
+ void transitive() { Object transitive = null; with(); }
+ // LocalVariableType | LambdaParameterType: var.
+ void var() { var var = new Object(); transitive(); }
+ // YieldStatement: yield (see java_switch.java).
+ void yield() { Object yield = null; var(); }
+ // RecordDeclaration: record.
+ void record() { Object record = null; this.yield(); }
+ // Normal{Class,Interface}Declaration: non-sealed permits sealed.
+ void permits() { Object permits = null; record(); }
+ void sealed() { Object sealed = null; permits(); }
+ // Guard: when (see java_switch.java).
+ void when() { Object when = null; sealed(); }
+
+ sealed interface I1 permits C1, I3 { }
+ sealed interface I2 permits C1, I3 { }
+ non-sealed interface I3 extends I1, I2 { }
+ interface I4 extends I3 { }
+
+ abstract sealed class C1 implements I1, I2 permits C2, C3 { }
+ abstract non-sealed class C2 extends C1 { }
+ final class C3 extends C1 implements I3 { }
+ class C4 extends C2 { }
+
+ record R() implements I3 { }
+ enum E implements I3 { INSTANCE }
+
+ static <T> I<T> i1() { return (var var) -> var; }
+ static <T> I<T> i2() { return (T var) -> var; }
+ static <T> I<T> i3() { return (var) -> var; }
+ static <T> I<T> i4() { return var -> var; }
+ interface I<T> { T i(T i); default I<T> self() { return this; } }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_enfoldment.java b/mnv/runtime/syntax/testdir/input/java_enfoldment.java
new file mode 100644
index 0000000000..3afeaaec69
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_enfoldment.java
@@ -0,0 +1,145 @@
+// MNV_TEST_SETUP setlocal fen fdc=2 fdl=8 fdm=syntax
+// MNV_TEST_SETUP let g:java_foldtext_show_first_or_second_line = 1
+// MNV_TEST_SETUP let g:java_highlight_java_lang = 1
+// MNV_TEST_SETUP let g:java_ignore_folding = "x"
+// MNV_TEST_SETUP let g:java_lookbehind_byte_counts = {'javaBlock': -1}
+
+
+
+
+
+// MNV_TEST_SETUP highlight link javaBlockOtherStart Structure
+// MNV_TEST_SETUP highlight link javaBlockStart Todo
+
+
+
+/***/ import java.lang.Comparable; /*
+import java.lang.Object;
+import java.lang.String;
+*/
+import java.lang.String;
+
+import java.lang.Comparable; /***/
+import java.lang.Object; // //
+import java.lang.String; /***/
+
+import java.util.function.Function;
+ @SuppressWarnings({
+ """
+ bespoke
+ /*
+ *
+ */
+ /**
+ *
+ */
+ ///
+ ///
+ ///
+ //
+ //
+ //
+ {
+ }
+"""
+})
+class FoldingTests {
+ interface Foldable
+ {
+ }
+
+ static {
+ String import⁠$ = """
+import java.lang.String;
+""";
+ new Object() {
+ {
+ {
+ new Object() {{{
+ new Object() {{{}}};
+ }}};
+ }
+ }
+ };
+
+ switch (0) {
+ case 0:
+ case 1: {
+ break;
+ }
+ default: ;
+ }
+ }
+
+ { Object bb = ((Object) new byte[]{}); }
+ {
+out: {
+ do {
+ if (true)
+ break out;
+ } while (false);
+}
+ }
+/*\\\*/ {
+ (new Function<Object, Object>() {
+ /**
+ * {@inheritDoc} */
+ public Object apply(Object o) { return o; };
+ }).apply(
+ (new Function<Object, Object>() {
+ /** {@inheritDoc}
+ */
+ public Object apply(Object o) { return o; };
+ }));
+ }
+
+ /**
+ * No operation.
+ */
+ void noOp1() { }
+ /** No operation. */
+ void noOp2()
+ {
+ }
+ /** No operation. */
+ void noOp3() {
+ }
+ /** No operation. */
+ void noOp4() {
+ /*/\/\/\*/ ; }
+
+ /// No operation.
+ ///
+ ///
+ void noOp5() { }
+ /// No operation.
+ void noOp6()
+ {
+ }
+ /// No operation.
+ void noOp7() {
+ }
+ /// No operation.
+ void noOp8() {
+ /*/\/\/\*/ ; }
+}
+
+/*
+ * Some note.
+ * {
+ * }
+ */
+/**
+ * A summary.
+ * {
+ * }
+ */
+/// A summary.
+/// {
+/// }
+//
+// {
+// }
+
+/* 120|..........................................................................................*/ interface Foldable {
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_escapes.java b/mnv/runtime/syntax/testdir/input/java_escapes.java
new file mode 100644
index 0000000000..eadaa420b4
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_escapes.java
@@ -0,0 +1,123 @@
+class EscapesTests
+{ // javap -constants EscapesTests.class
+ // static final String hello = "hello";
+ \u0073\u0074\u0061\u0074\u0069\u0063
+ \u0066\u0069\u006e\u0061\u006c
+ \u0053\u0074\u0072\u0069\u006e\u0067
+ \u0068\u0065\u006c\u006c\u006f
+ \u003d
+ \u0022\u0068\u0065\u006c\u006c\u006f\u0022
+ \u003b
+
+ static {
+ char ee[] = {
+ '\b', '\s', '\t',
+ '\n', '\f', '\r',
+ '\"', '\'', '\\',
+ };
+
+ System.out.println(new String[] {
+ "\b", "\s", "\t",
+ "\n", "\f", "\r",
+ "\"", "\'", "\\",
+ });
+
+ char oo[] = {
+ '\0', '\1', '\2', '\3', '\4', '\5', '\6', '\7',
+
+ '\00', '\01', '\02', '\03', '\04', '\05', '\06', '\07',
+
+ '\000', '\001', '\002', '\003', '\004', '\005', '\006', '\007',
+
+ '\10', '\11', '\12', '\13', '\14', '\15', '\16', '\17',
+ '\20', '\21', '\22', '\23', '\24', '\25', '\26', '\27',
+ '\30', '\31', '\32', '\33', '\34', '\35', '\36', '\37',
+ '\40', '\41', '\42', '\43', '\44', '\45', '\46', '\47',
+ '\50', '\51', '\52', '\53', '\54', '\55', '\56', '\57',
+ '\60', '\61', '\62', '\63', '\64', '\65', '\66', '\67',
+ '\70', '\71', '\72', '\73', '\74', '\75', '\76', '\77',
+
+ '\010', '\011', '\012', '\013', '\014', '\015', '\016', '\017',
+ '\020', '\021', '\022', '\023', '\024', '\025', '\026', '\027',
+ '\030', '\031', '\032', '\033', '\034', '\035', '\036', '\037',
+ '\040', '\041', '\042', '\043', '\044', '\045', '\046', '\047',
+ '\050', '\051', '\052', '\053', '\054', '\055', '\056', '\057',
+ '\060', '\061', '\062', '\063', '\064', '\065', '\066', '\067',
+ '\070', '\071', '\072', '\073', '\074', '\075', '\076', '\077',
+
+ '\100', '\101', '\102', '\103', '\104', '\105', '\106', '\107',
+ '\110', '\111', '\112', '\113', '\114', '\115', '\116', '\117',
+ '\120', '\121', '\122', '\123', '\124', '\125', '\126', '\127',
+ '\130', '\131', '\132', '\133', '\134', '\135', '\136', '\137',
+ '\140', '\141', '\142', '\143', '\144', '\145', '\146', '\147',
+ '\150', '\151', '\152', '\153', '\154', '\155', '\156', '\157',
+ '\160', '\161', '\162', '\163', '\164', '\165', '\166', '\167',
+ '\170', '\171', '\172', '\173', '\174', '\175', '\176', '\177',
+ '\200', '\201', '\202', '\203', '\204', '\205', '\206', '\207',
+ '\210', '\211', '\212', '\213', '\214', '\215', '\216', '\217',
+ '\220', '\221', '\222', '\223', '\224', '\225', '\226', '\227',
+ '\230', '\231', '\232', '\233', '\234', '\235', '\236', '\237',
+ '\240', '\241', '\242', '\243', '\244', '\245', '\246', '\247',
+ '\250', '\251', '\252', '\253', '\254', '\255', '\256', '\257',
+ '\260', '\261', '\262', '\263', '\264', '\265', '\266', '\267',
+ '\270', '\271', '\272', '\273', '\274', '\275', '\276', '\277',
+ '\300', '\301', '\302', '\303', '\304', '\305', '\306', '\307',
+ '\310', '\311', '\312', '\313', '\314', '\315', '\316', '\317',
+ '\320', '\321', '\322', '\323', '\324', '\325', '\326', '\327',
+ '\330', '\331', '\332', '\333', '\334', '\335', '\336', '\337',
+ '\340', '\341', '\342', '\343', '\344', '\345', '\346', '\347',
+ '\350', '\351', '\352', '\353', '\354', '\355', '\356', '\357',
+ '\360', '\361', '\362', '\363', '\364', '\365', '\366', '\367',
+ '\370', '\371', '\372', '\373', '\374', '\375', '\376', '\377',
+ };
+
+ System.out.println(new String[] {
+ "\0", "\1", "\2", "\3", "\4", "\5", "\6", "\7",
+
+ "\00", "\01", "\02", "\03", "\04", "\05", "\06", "\07",
+
+ "\000", "\001", "\002", "\003", "\004", "\005", "\006", "\007",
+
+ "\10", "\11", "\12", "\13", "\14", "\15", "\16", "\17",
+ "\20", "\21", "\22", "\23", "\24", "\25", "\26", "\27",
+ "\30", "\31", "\32", "\33", "\34", "\35", "\36", "\37",
+ "\40", "\41", "\42", "\43", "\44", "\45", "\46", "\47",
+ "\50", "\51", "\52", "\53", "\54", "\55", "\56", "\57",
+ "\60", "\61", "\62", "\63", "\64", "\65", "\66", "\67",
+ "\70", "\71", "\72", "\73", "\74", "\75", "\76", "\77",
+
+ "\010", "\011", "\012", "\013", "\014", "\015", "\016", "\017",
+ "\020", "\021", "\022", "\023", "\024", "\025", "\026", "\027",
+ "\030", "\031", "\032", "\033", "\034", "\035", "\036", "\037",
+ "\040", "\041", "\042", "\043", "\044", "\045", "\046", "\047",
+ "\050", "\051", "\052", "\053", "\054", "\055", "\056", "\057",
+ "\060", "\061", "\062", "\063", "\064", "\065", "\066", "\067",
+ "\070", "\071", "\072", "\073", "\074", "\075", "\076", "\077",
+
+ "\100", "\101", "\102", "\103", "\104", "\105", "\106", "\107",
+ "\110", "\111", "\112", "\113", "\114", "\115", "\116", "\117",
+ "\120", "\121", "\122", "\123", "\124", "\125", "\126", "\127",
+ "\130", "\131", "\132", "\133", "\134", "\135", "\136", "\137",
+ "\140", "\141", "\142", "\143", "\144", "\145", "\146", "\147",
+ "\150", "\151", "\152", "\153", "\154", "\155", "\156", "\157",
+ "\160", "\161", "\162", "\163", "\164", "\165", "\166", "\167",
+ "\170", "\171", "\172", "\173", "\174", "\175", "\176", "\177",
+ "\200", "\201", "\202", "\203", "\204", "\205", "\206", "\207",
+ "\210", "\211", "\212", "\213", "\214", "\215", "\216", "\217",
+ "\220", "\221", "\222", "\223", "\224", "\225", "\226", "\227",
+ "\230", "\231", "\232", "\233", "\234", "\235", "\236", "\237",
+ "\240", "\241", "\242", "\243", "\244", "\245", "\246", "\247",
+ "\250", "\251", "\252", "\253", "\254", "\255", "\256", "\257",
+ "\260", "\261", "\262", "\263", "\264", "\265", "\266", "\267",
+ "\270", "\271", "\272", "\273", "\274", "\275", "\276", "\277",
+ "\300", "\301", "\302", "\303", "\304", "\305", "\306", "\307",
+ "\310", "\311", "\312", "\313", "\314", "\315", "\316", "\317",
+ "\320", "\321", "\322", "\323", "\324", "\325", "\326", "\327",
+ "\330", "\331", "\332", "\333", "\334", "\335", "\336", "\337",
+ "\340", "\341", "\342", "\343", "\344", "\345", "\346", "\347",
+ "\350", "\351", "\352", "\353", "\354", "\355", "\356", "\357",
+ "\360", "\361", "\362", "\363", "\364", "\365", "\366", "\367",
+ "\370", "\371", "\372", "\373", "\374", "\375", "\376", "\377",
+ });
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_generics.java b/mnv/runtime/syntax/testdir/input/java_generics.java
new file mode 100644
index 0000000000..4dc760c6ec
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_generics.java
@@ -0,0 +1,162 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'style'
+// MNV_TEST_SETUP let g:java_highlight_generics = 1
+// MNV_TEST_SETUP let g:java_highlight_java_lang = 1
+
+
+// MNV_TEST_SETUP hi link javaGenericsC1 Todo
+// MNV_TEST_SETUP hi link javaGenericsC2 Error
+// MNV_TEST_SETUP hi link javaWildcardBound Error
+
+
+import java.math.BigInteger;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.LongFunction;
+import java.util.function.Predicate;
+
+class GenericsTests<T extends Number & Comparable<? super T>, U>
+{ // JDK 21+.
+ static final Function<Function<Object, Object>, Object> PARTIAL =
+ GenericsTests.y0();
+ static final Function<BigInteger, BigInteger> FACTORIAL_2000 =
+ GenericsTests.<BigInteger, BigInteger>y1()
+ .apply(f -> x -> (x.compareTo(BigInteger.ONE) < 1)
+ ? BigInteger.ONE
+ : x.multiply(f.apply(x.subtract(BigInteger.ONE))));
+
+ static <T1> Y0<T1> y0()
+ {
+ return (Function<T1, T1> f) -> f.apply(
+ GenericsTests.<T1>y0()
+ .apply(f));
+ }
+
+ static <T1, T2> Y1<T1, T2> y1()
+ {
+ return (Function<Function<T1, T2>, Function<T1, T2>> f) ->
+ (T1 x) -> f.apply(GenericsTests.<T1, T2>y1()
+ .apply(f))
+ .apply(x);
+ }
+
+ static<T> void noOp(T dummy) { }
+
+ interface alpha<T> { }
+
+ interface Y0<T1> extends Function<Function<T1, T1>, T1> { }
+
+ interface Y1<T1, T2> extends Function<Function<Function<T1, T2>,
+ Function<T1, T2>>,
+ Function<T1, T2>> { }
+
+ interface Stackable<E> extends Iterable<E>
+ {
+ boolean isEmpty();
+ E peek();
+ E pop();
+ Stackable<E> popAll(Stackable<? super E> elements);
+ Stackable<E> popSome(Stackable<? super E> elements,
+ Predicate<? super E> filter);
+ Stackable<E> push(E element);
+ Stackable<E> pushAll(Iterable<? extends E> elements);
+ Stackable<E> pushSome(Iterable<? extends E> elements,
+ Predicate<? super E> filter);
+ Stackable<E> wind(Consumer<? super Stackable<E>> action);
+ }
+
+ sealed interface Num<N extends Number>
+ {
+ int radix();
+ N value();
+ }
+
+ record Bin<N extends Number>(N value) implements Num<N>
+ {
+ public int radix() { return 2; }
+ }
+
+ record Dec<N extends Number>(N value) implements Num<N>
+ {
+ public int radix() { return 10; }
+ }
+
+ record Hex<N extends Number>(N value) implements Num<N>
+ {
+ public int radix() { return 16; }
+ }
+
+ record Oct<N extends Number>(N value) implements Num<N>
+ {
+ public int radix() { return 8; }
+ }
+
+ static Num<Long> fromDecimal(long x, int radix)
+ {
+ record Pair(LongFunction<Num<Long>> a,
+ LongFunction<String> b) { }
+ final Pair p = switch (radix) {
+ case 2 -> new Pair(Bin::new, Long::toBinaryString);
+ case 8 -> new Pair(Oct::new, Long::toOctalString);
+ case 16 -> new Pair(Hex::new, Long::toHexString);
+ default -> new Pair(Dec::new,
+ y -> Long.toString(y));
+ };
+ return p.a().apply(Long.parseLong(p.b().apply(x), radix));
+ }
+
+ static long toDecimal(Num<Long> x)
+ {
+ return Long.parseLong(switch (x) {
+ case Bin<?>(Long b) -> Long.toBinaryString(b);
+ case Oct<?>(Long o) -> Long.toOctalString(o);
+ case Hex<?>(Long h) -> Long.toHexString(h);
+ default -> Long.toString(x.value());
+ }, x.radix());
+ }
+
+ static Class<?> eitherComparableOrIterable(Object o)
+ {
+ final boolean comparable;
+ return ((comparable = o instanceof Comparable) ^
+ o instanceof Iterable)
+ ? (comparable)
+ ? Comparable.class
+ : Iterable.class
+ : java.lang.Class.class;
+ }
+
+ <A, T extends java.util.function.Supplier<A>,
+ B, U extends java.util.function.Supplier<B>> U convert(T o)
+ {
+ throw new UnsupportedOperationException("TODO");
+ }
+
+ @java.lang.annotation.Target(
+ java.lang.annotation.ElementType.TYPE_USE)
+ @interface Taggable
+ {
+ String value() default "";
+ }
+
+ {
+ int N = 0, X = 1, Y = 2;
+ Predicate<T> f = y->N<y.intValue();
+ Predicate<T> g = y->X<N&&(Integer)y>N;
+ boolean[] bb = {
+ X<N||N>Y, X < Y, X <Y, X <(Y), X<(Y), (X)<Y,
+ Double.isFinite(X<<Y),
+ X<=Y, X<(int)(byte)Y, X<~Y, X<-Y, X<+Y,
+ };
+ Class<?> klass = GenericsTests.class;
+ Class< java.lang.Class<@Taggable("<>")int[][]> [] [] >
+ [ ] [ ] $ [ ] [ ];
+ if (false) { new GenericsTests<>(); }
+ alpha<?> ao;
+ alpha<U> au;
+ alpha<alpha<U>> aau;
+ alpha<Y0<?>> ay0o;
+ alpha<Y0<U>> ay0u;
+ Y0<alpha<?>> y0ao;
+ Y0<alpha<U>> y0au;
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_generics_signature.java b/mnv/runtime/syntax/testdir/input/java_generics_signature.java
new file mode 100644
index 0000000000..9c0d4d5ac6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_generics_signature.java
@@ -0,0 +1,162 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'style'
+// MNV_TEST_SETUP let g:java_highlight_signature = 1
+// MNV_TEST_SETUP let g:java_highlight_generics = 1
+// MNV_TEST_SETUP let g:java_highlight_java_lang = 1
+
+// MNV_TEST_SETUP hi link javaGenericsC1 Todo
+// MNV_TEST_SETUP hi link javaGenericsC2 Error
+// MNV_TEST_SETUP hi link javaWildcardBound Error
+
+
+import java.math.BigInteger;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.LongFunction;
+import java.util.function.Predicate;
+
+class Generics$Tests<T extends Number & Comparable<? super T>, U>
+{ // JDK 21+.
+ static final Function<Function<Object, Object>, Object> PARTIAL =
+ Generics$Tests.y0();
+ static final Function<BigInteger, BigInteger> FACTORIAL_2000 =
+ Generics$Tests.<BigInteger, BigInteger>y1()
+ .apply(f -> x -> (x.compareTo(BigInteger.ONE) < 1)
+ ? BigInteger.ONE
+ : x.multiply(f.apply(x.subtract(BigInteger.ONE))));
+
+ static <T1> Y0<T1> y0()
+ {
+ return (Function<T1, T1> f) -> f.apply(
+ Generics$Tests.<T1>y0()
+ .apply(f));
+ }
+
+ static <T1, T2> Y1<T1, T2> y1()
+ {
+ return (Function<Function<T1, T2>, Function<T1, T2>> f) ->
+ (T1 x) -> f.apply(Generics$Tests.<T1, T2>y1()
+ .apply(f))
+ .apply(x);
+ }
+
+ static<T> void noOp(T dummy) { }
+
+ interface alpha<T> { }
+
+ interface Y0<T1> extends Function<Function<T1, T1>, T1> { }
+
+ interface Y1<T1, T2> extends Function<Function<Function<T1, T2>,
+ Function<T1, T2>>,
+ Function<T1, T2>> { }
+
+ interface Stackable<E> extends Iterable<E>
+ {
+ boolean isEmpty();
+ E peek();
+ E pop();
+ Stackable<E> popAll(Stackable<? super E> elements);
+ Stackable<E> popSome(Stackable<? super E> elements,
+ Predicate<? super E> filter);
+ Stackable<E> push(E element);
+ Stackable<E> pushAll(Iterable<? extends E> elements);
+ Stackable<E> pushSome(Iterable<? extends E> elements,
+ Predicate<? super E> filter);
+ Stackable<E> wind(Consumer<? super Stackable<E>> action);
+ }
+
+ sealed interface Num<N extends Number>
+ {
+ int radix();
+ N value();
+ }
+
+ record Bin<N extends Number>(N value) implements Num<N>
+ {
+ public int radix() { return 2; }
+ }
+
+ record Dec<N extends Number>(N value) implements Num<N>
+ {
+ public int radix() { return 10; }
+ }
+
+ record Hex<N extends Number>(N value) implements Num<N>
+ {
+ public int radix() { return 16; }
+ }
+
+ record Oct<N extends Number>(N value) implements Num<N>
+ {
+ public int radix() { return 8; }
+ }
+
+ static Num<Long> fromDecimal(long x, int radix)
+ {
+ record Pair(LongFunction<Num<Long>> a,
+ LongFunction<String> b) { }
+ final Pair p = switch (radix) {
+ case 2 -> new Pair(Bin::new, Long::toBinaryString);
+ case 8 -> new Pair(Oct::new, Long::toOctalString);
+ case 16 -> new Pair(Hex::new, Long::toHexString);
+ default -> new Pair(Dec::new,
+ y -> Long.toString(y));
+ };
+ return p.a().apply(Long.parseLong(p.b().apply(x), radix));
+ }
+
+ static long toDecimal(Num<Long> x)
+ {
+ return Long.parseLong(switch (x) {
+ case Bin<?>(Long b) -> Long.toBinaryString(b);
+ case Oct<?>(Long o) -> Long.toOctalString(o);
+ case Hex<?>(Long h) -> Long.toHexString(h);
+ default -> Long.toString(x.value());
+ }, x.radix());
+ }
+
+ static Class<?> eitherComparableOrIterable(Object o)
+ {
+ final boolean comparable;
+ return ((comparable = o instanceof Comparable) ^
+ o instanceof Iterable)
+ ? (comparable)
+ ? Comparable.class
+ : Iterable.class
+ : java.lang.Class.class;
+ }
+
+ <A, T extends java.util.function.Supplier<A>,
+ B, U extends java.util.function.Supplier<B>> U convert(T o)
+ {
+ throw new UnsupportedOperationException("TODO");
+ }
+
+ @java.lang.annotation.Target(
+ java.lang.annotation.ElementType.TYPE_USE)
+ @interface Taggable
+ {
+ String value() default "";
+ }
+
+ {
+ int N = 0, X = 1, Y = 2;
+ Predicate<T> f = y->N<y.intValue();
+ Predicate<T> g = y->X<N&&(Integer)y>N;
+ boolean[] bb = {
+ X<N||N>Y, X < Y, X <Y, X <(Y), X<(Y), (X)<Y,
+ Double.isFinite(X<<Y),
+ X<=Y, X<(int)(byte)Y, X<~Y, X<-Y, X<+Y,
+ };
+ Class<?> klass = Generics$Tests.class;
+ Class< java.lang.Class<@Taggable("<>")int[][]> [] [] >
+ [ ] [ ] $ [ ] [ ];
+ if (false) { new Generics$Tests<>(); }
+ alpha<?> ao;
+ alpha<U> au;
+ alpha<alpha<U>> aau;
+ alpha<Y0<?>> ay0o;
+ alpha<Y0<U>> ay0u;
+ Y0<alpha<?>> y0ao;
+ Y0<alpha<U>> y0au;
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_lambda_expressions.java b/mnv/runtime/syntax/testdir/input/java_lambda_expressions.java
new file mode 100644
index 0000000000..31974a9a0e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_lambda_expressions.java
@@ -0,0 +1,154 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'style'
+
+
+import java.lang.annotation.ElementType;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+class LambdaExpressionsTests // JDK 21+.
+{
+ <I1, C1, C2, T1, T2, T3, Z1, Z2, Z3, S1, S2, S3> void test()
+ { // Schönfinkel's functions.
+ I<I1> i = x -> x;
+ C<C1, C2> c = x -> y -> x;
+ T<T1, T2, T3> t = f -> y -> x -> f.apply(x).apply(y);
+ Z<Z1, Z2, Z3> z = f -> g -> x -> f.apply(g.apply(x));
+ S<S1, S2, S3> s = f -> g -> x -> f.apply(x)
+ .apply(g.apply(x));
+
+ I<I1> i01 = (var x) -> x;
+ I<I1> i02 = (@Taggable var x) -> x;
+ I<I1> i03 = (@Taggable @Taggable var x) -> x;
+ I<I1> i04 = (final var x) -> x;
+ I<I1> i05 = (@Taggable final var x) -> x;
+ I<I1> i06 = (@Taggable @Taggable final var x) -> x;
+ I<I1> i07 = (I1 x) -> x;
+ I<I1> i08 = (@Taggable I1 x) -> x;
+ I<I1> i09 = (@Taggable @Taggable I1 x) -> x;
+ I<I1> i10 = (final I1 x) -> x;
+ I<I1> i11 = (@Taggable final I1 x) -> x;
+ I<I1> i12 = (@Taggable @Taggable final I1 x) -> x;
+
+ I<I1[]> ii01 = (I1... x) -> x;
+ I<I1[]> ii02 = (@Taggable I1... x) -> x;
+ I<I1[]> ii03 = (@Taggable @Taggable I1... x) -> x;
+ I<I1[]> ii04 = (final I1... x) -> x;
+ I<I1[]> ii05 = (@Taggable final I1... x) -> x;
+ I<I1[]> ii06 = (@Taggable @Taggable final I1... x) -> x;
+
+ BinaryOperator<I1> leftConst01 = (var x, var y) -> x;
+ BinaryOperator<I1> leftConst02 = (@Taggable var x,
+ @Taggable var y) -> x;
+ BinaryOperator<I1> leftConst03 = (@Taggable @Taggable var
+ x, @Taggable @Taggable var y) -> x;
+ BinaryOperator<I1> leftConst04 = (final var x,
+ final var y) -> x;
+ BinaryOperator<I1> leftConst05 = (@Taggable final
+ var x, @Taggable final var y) -> x;
+ BinaryOperator<I1> leftConst06 = (@Taggable
+ @Taggable final var x,
+ @Taggable
+ @Taggable final var y) -> x;
+ BinaryOperator<I1> leftConst07 = (I1 x, I1 y) -> x;
+ BinaryOperator<I1> leftConst08 = (@Taggable I1 x,
+ @Taggable I1 y) -> x;
+ BinaryOperator<I1> leftConst09 = (@Taggable @Taggable I1
+ x, @Taggable @Taggable I1 y) -> x;
+ BinaryOperator<I1> leftConst10 = (final I1 x,
+ final I1 y) -> x;
+ BinaryOperator<I1> leftConst11 = (@Taggable final
+ I1 x, @Taggable final I1 y) -> x;
+ BinaryOperator<I1> leftConst12 = (@Taggable
+ @Taggable final I1 x,
+ @Taggable
+ @Taggable final I1 y) -> x;
+
+ Runnable noOp = () -> {};
+ BinaryOperator<I1> leftConst = (x, y) -> x;
+ I<I1> id1 = (x) -> (x);
+ @SuppressWarnings("unchecked") I<I1> id2 =
+ ((I<I<I1>>) (I<?>) (Function<I1,
+ I1> x) -> x).apply(switch (0) {
+ case ((int) (byte) 1) -> (I1 x) -> x;
+ default -> (@Taggable I1 x) -> x; });
+ C<C1, C2> const1 = (x) -> (y) -> (x);
+ C<C1, C2> const2 = switch(switch ("") {
+ case "->"->"(s)->(s)";
+ default->"default"; }) {
+ case ("->")->(var x)->(var y)->(x);
+ default->(@Taggable var x)->(@Taggable var y)
+ ->(x);
+ };
+ }
+
+ @java.lang.annotation.Target(ElementType.PARAMETER)
+ @java.lang.annotation.Repeatable(Taggables.class)
+ @interface Taggable { String[] value() default ""; }
+
+ @java.lang.annotation.Target(ElementType.PARAMETER)
+ @interface Taggables { Taggable[] value(); }
+
+ interface I<A1> extends Function<A1, A1> { }
+ interface C<A1, A2> extends Function<A1, Function<A2, A1>> { }
+ interface T<A1, A2, A3> extends
+ Function<Function<A1, Function<A2, A3>>,
+ Function<A2,
+ Function<A1, A3>>> { }
+ interface Z<A1, A2, A3> extends Function<Function<A2, A3>,
+ Function<Function<A1, A2>,
+ Function<A1, A3>>> { }
+ interface S<A1, A2, A3> extends
+ Function<Function<A1, Function<A2, A3>>,
+ Function<Function<A1, A2>,
+ Function<A1, A3>>> { }
+
+ static void echo(Object o) { System.out.println(o); }
+
+ static {
+ enum Letters { OTHER, ALPHA, BETA }
+
+ Letters other = Letters.OTHER;
+
+ switch (other) {
+ case Letters alpha when Letters.ALPHA == alpha:
+ { echo(alpha); break; }
+ case Letters beta when Letters.BETA == beta:
+ { echo(beta); break; }
+ default: { echo(other); }
+ }
+
+ echo(switch (other) {
+ case Letters alpha when Letters.ALPHA == alpha
+ -> alpha;
+ case Letters beta when Letters.BETA == beta
+ -> beta;
+ default -> other;
+ });
+
+ switch (null) {
+ case String str when !"<empty>".equals(switch (str) {
+ case String str_ when
+ Predicate.<String>not(text ->
+ !text.isEmpty())
+ .test(str_)
+ -> "<empty>";
+ case String str_ -> str_;
+ }): { echo(str); break; }
+ case null: default: { echo("Other"); }
+ }
+
+ echo(switch (null) {
+ case String str when !"<empty>".equals(
+ switch (str) {
+ case String str_ when
+ Predicate.<String>not(text ->
+ !text.isEmpty())
+ .test(str_)
+ -> "<empty>";
+ case String str_ -> str_;
+ }) -> str;
+ case null, default -> "Other";
+ });
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_lambda_expressions_signature.java b/mnv/runtime/syntax/testdir/input/java_lambda_expressions_signature.java
new file mode 100644
index 0000000000..f15c379f17
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_lambda_expressions_signature.java
@@ -0,0 +1,154 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'style'
+// MNV_TEST_SETUP let g:java_highlight_signature = 1
+
+import java.lang.annotation.ElementType;
+import java.util.function.BinaryOperator;
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+class LambdaExpressions$Tests // JDK 21+.
+{
+ <I1, C1, C2, T1, T2, T3, Z1, Z2, Z3, S1, S2, S3> void test()
+ { // Schönfinkel's functions.
+ I<I1> i = x -> x;
+ C<C1, C2> c = x -> y -> x;
+ T<T1, T2, T3> t = f -> y -> x -> f.apply(x).apply(y);
+ Z<Z1, Z2, Z3> z = f -> g -> x -> f.apply(g.apply(x));
+ S<S1, S2, S3> s = f -> g -> x -> f.apply(x)
+ .apply(g.apply(x));
+
+ I<I1> i01 = (var x) -> x;
+ I<I1> i02 = (@Taggable var x) -> x;
+ I<I1> i03 = (@Taggable @Taggable var x) -> x;
+ I<I1> i04 = (final var x) -> x;
+ I<I1> i05 = (@Taggable final var x) -> x;
+ I<I1> i06 = (@Taggable @Taggable final var x) -> x;
+ I<I1> i07 = (I1 x) -> x;
+ I<I1> i08 = (@Taggable I1 x) -> x;
+ I<I1> i09 = (@Taggable @Taggable I1 x) -> x;
+ I<I1> i10 = (final I1 x) -> x;
+ I<I1> i11 = (@Taggable final I1 x) -> x;
+ I<I1> i12 = (@Taggable @Taggable final I1 x) -> x;
+
+ I<I1[]> ii01 = (I1... x) -> x;
+ I<I1[]> ii02 = (@Taggable I1... x) -> x;
+ I<I1[]> ii03 = (@Taggable @Taggable I1... x) -> x;
+ I<I1[]> ii04 = (final I1... x) -> x;
+ I<I1[]> ii05 = (@Taggable final I1... x) -> x;
+ I<I1[]> ii06 = (@Taggable @Taggable final I1... x) -> x;
+
+ BinaryOperator<I1> leftConst01 = (var x, var y) -> x;
+ BinaryOperator<I1> leftConst02 = (@Taggable var x,
+ @Taggable var y) -> x;
+ BinaryOperator<I1> leftConst03 = (@Taggable @Taggable var
+ x, @Taggable @Taggable var y) -> x;
+ BinaryOperator<I1> leftConst04 = (final var x,
+ final var y) -> x;
+ BinaryOperator<I1> leftConst05 = (@Taggable final
+ var x, @Taggable final var y) -> x;
+ BinaryOperator<I1> leftConst06 = (@Taggable
+ @Taggable final var x,
+ @Taggable
+ @Taggable final var y) -> x;
+ BinaryOperator<I1> leftConst07 = (I1 x, I1 y) -> x;
+ BinaryOperator<I1> leftConst08 = (@Taggable I1 x,
+ @Taggable I1 y) -> x;
+ BinaryOperator<I1> leftConst09 = (@Taggable @Taggable I1
+ x, @Taggable @Taggable I1 y) -> x;
+ BinaryOperator<I1> leftConst10 = (final I1 x,
+ final I1 y) -> x;
+ BinaryOperator<I1> leftConst11 = (@Taggable final
+ I1 x, @Taggable final I1 y) -> x;
+ BinaryOperator<I1> leftConst12 = (@Taggable
+ @Taggable final I1 x,
+ @Taggable
+ @Taggable final I1 y) -> x;
+
+ Runnable noOp = () -> {};
+ BinaryOperator<I1> leftConst = (x, y) -> x;
+ I<I1> id1 = (x) -> (x);
+ @SuppressWarnings("unchecked") I<I1> id2 =
+ ((I<I<I1>>) (I<?>) (Function<I1,
+ I1> x) -> x).apply(switch (0) {
+ case ((int) (byte) 1) -> (I1 x) -> x;
+ default -> (@Taggable I1 x) -> x; });
+ C<C1, C2> const1 = (x) -> (y) -> (x);
+ C<C1, C2> const2 = switch(switch ("") {
+ case "->"->"(s)->(s)";
+ default->"default"; }) {
+ case ("->")->(var x)->(var y)->(x);
+ default->(@Taggable var x)->(@Taggable var y)
+ ->(x);
+ };
+ }
+
+ @java.lang.annotation.Target(ElementType.PARAMETER)
+ @java.lang.annotation.Repeatable(Taggables.class)
+ @interface Taggable { String[] value() default ""; }
+
+ @java.lang.annotation.Target(ElementType.PARAMETER)
+ @interface Taggables { Taggable[] value(); }
+
+ interface I<A1> extends Function<A1, A1> { }
+ interface C<A1, A2> extends Function<A1, Function<A2, A1>> { }
+ interface T<A1, A2, A3> extends
+ Function<Function<A1, Function<A2, A3>>,
+ Function<A2,
+ Function<A1, A3>>> { }
+ interface Z<A1, A2, A3> extends Function<Function<A2, A3>,
+ Function<Function<A1, A2>,
+ Function<A1, A3>>> { }
+ interface S<A1, A2, A3> extends
+ Function<Function<A1, Function<A2, A3>>,
+ Function<Function<A1, A2>,
+ Function<A1, A3>>> { }
+
+ static void echo(Object o) { System.out.println(o); }
+
+ static {
+ enum Letters { OTHER, ALPHA, BETA }
+
+ Letters other = Letters.OTHER;
+
+ switch (other) {
+ case Letters alpha when Letters.ALPHA == alpha:
+ { echo(alpha); break; }
+ case Letters beta when Letters.BETA == beta:
+ { echo(beta); break; }
+ default: { echo(other); }
+ }
+
+ echo(switch (other) {
+ case Letters alpha when Letters.ALPHA == alpha
+ -> alpha;
+ case Letters beta when Letters.BETA == beta
+ -> beta;
+ default -> other;
+ });
+
+ switch (null) {
+ case String str when !"<empty>".equals(switch (str) {
+ case String str_ when
+ Predicate.<String>not(text ->
+ !text.isEmpty())
+ .test(str_)
+ -> "<empty>";
+ case String str_ -> str_;
+ }): { echo(str); break; }
+ case null: default: { echo("Other"); }
+ }
+
+ echo(switch (null) {
+ case String str when !"<empty>".equals(
+ switch (str) {
+ case String str_ when
+ Predicate.<String>not(text ->
+ !text.isEmpty())
+ .test(str_)
+ -> "<empty>";
+ case String str_ -> str_;
+ }) -> str;
+ case null, default -> "Other";
+ });
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_method_references.java b/mnv/runtime/syntax/testdir/input/java_method_references.java
new file mode 100644
index 0000000000..7942308148
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_method_references.java
@@ -0,0 +1,192 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'style'
+// MNV_TEST_SETUP let g:java_highlight_generics = 1
+
+
+import java.lang.invoke.MethodHandle;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.IntSupplier;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.function.ToIntFunction;
+import java.util.function.UnaryOperator;
+
+class MethodReferencesTests
+{
+ static {
+ // Primary :: [TypeArguments] Identifier
+ try {
+ Runnable r1 = ((Runtime) null)::gc;
+ } catch (NullPointerException expected) {
+ }
+
+ Supplier<Integer> s1 = ((Number) 0)::hashCode;
+ Supplier<Integer> s2 = ((Comparable<?>) '\0')::hashCode;
+ Supplier<Integer> s3 = ((Comparable<?>) false)::hashCode;
+ Supplier<Integer> s4 = "::"::hashCode;
+ Supplier<Class<?>> s5 = int[].class::arrayType;
+ Supplier<Integer> s6 = new MethodReferencesTests() ::
+ hashCode;
+ Supplier<Integer> s7 = ((Number)
+ (new MethodReferencesTests().xy)[0])::intValue;
+ Supplier<int[]> s8 = new MethodReferencesTests().xy::
+ clone;
+ Consumer<Object> c1 = System.out :: println;
+ Supplier<byte[]> s9 = ((Supplier<String>) ()->"()").get()
+ ::getBytes;
+ Supplier<String> sa = ((Supplier<String>)
+ ((Supplier<String>) ((Supplier<String>)
+ ((Supplier<String>) ((Supplier<String>)
+ () -> "() -> ()")
+ ::toString)
+ ::toString)
+ ::get)
+ ::toString)
+ ::toString;
+
+ // ExpressionName :: [TypeArguments] Identifier
+ // ReferenceType :: [TypeArguments] Identifier
+ Function<String, IntSupplier> f1 = s ->
+ s :: length;
+ Function<int[][], Supplier<int[]>> f2 = ii ->
+ ((int[]) (ii.length > 0 ? ii[0] : ii))
+ :: clone;
+ UnaryOperator<String> uo1 = String::valueOf;
+ ToIntFunction<String> tif1 = s -> s.transform(
+ String :: length);
+
+ // ClassType :: [TypeArguments] new
+ // ArrayType :: new
+ Function<Object, C2> f3 = C2::<Object>new;
+ Function<C2, C2.C21> f4 = pci -> pci.new
+ <String>C21(null); // Cf. "d".
+ Supplier<C1<?>> sb = C1::new;
+ Function<Byte, C1<?>> f5 = C1<Void> :: <Byte> new;
+ IntFunction<C1<?>[]> if1 = C1<?>[] :: new;
+ IntFunction<byte[]> if2 = byte[] :: new;
+ }
+
+ final int[] xy = { 0, 1 };
+
+ // super :: [TypeArguments] Identifier
+ // TypeName . super :: [TypeArguments] Identifier
+ <T> MethodReferencesTests()
+ {
+ Predicate<T> p1 = MethodReferencesTests.super::equals;
+ Predicate<T> p2 = MethodReferencesTests.this::equals;
+ }
+
+ interface I4<T> extends I3<T>
+ {
+ default Predicate<T> superEqualist()
+ {
+ return I3
+ .super::equals; /* "a" */
+ }
+ }
+
+ interface I3<T> extends I2<T>
+ {
+ default Predicate<T> superEqualist()
+ {
+ return I2.
+ super::equals; /* "b" */
+ }
+ }
+
+ interface I2<T> extends I1<T>
+ {
+ default Predicate<T> superEqualist()
+ { /* Non-capturing gymnastics for super::equals. */
+ return Function.<Function<MethodHandle,
+ Predicate<T>>>
+ identity()
+ .apply(mh -> o -> MethodReferencesTests
+ .invokePredicate(mh, o))
+ .apply(EQUALS.bindTo(this));
+ }
+ }
+
+ interface I1<T>
+ {
+ default Predicate<T> equalist()
+ { /* Non-capturing gymnastics for this::equals. */
+ return Function.<Function<I1<T>, Predicate<T>>>
+ identity()
+ .apply(that -> o -> Function
+ .<BiPredicate<I1<T>, T>>
+ identity()
+ .apply(I1<T>:: /* "c" */
+ equals)
+ .test(that, o))
+ .apply(I1.this);
+ }
+ }
+
+ static <T> boolean invokePredicate(MethodHandle mh, T o)
+ {
+ try {
+ return (boolean) mh.invokeExact(o);
+ } catch (Throwable th) {
+ throw new RuntimeException(th);
+ }
+ }
+
+ private static final MethodHandle EQUALS;
+
+ static {
+ try {
+ EQUALS = java.lang.invoke.MethodHandles.lookup()
+ .findSpecial(
+ I1.class,
+ "equals",
+ java.lang.invoke.MethodType.methodType(
+ boolean.class,
+ Object.class),
+ I2.class);
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
+ }
+
+ static class C1<T>
+ {
+ C1() { }
+ <A> C1(A dummy) { }
+ }
+
+ static class C2
+ {
+ C2() { <String> this(""); }
+
+ <A> C2(A dummy)
+ {
+ C2.stringer().apply(((Function<C2, C2.C21>)
+ C2.C21::new) /* "d" */
+ .apply(C2.this));
+ }
+
+ class C21
+ {
+ C21() { <String> this(""); }
+
+ <B> C21(B dummy)
+ {
+ C2.stringer().apply(C2.this);
+ }
+ }
+
+ static <T extends Object> Function<T, String> stringer()
+ {
+ return T::toString; /* "e" */
+ }
+ }
+
+ static {
+ ((Supplier<Class<?>>)((Supplier<C2.C21>)()->new
+ <Object>C2().new <Object> C21(new<Object>
+ C1< Object >((C1<?>)null)))::getClass).get();
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_method_references_signature.java b/mnv/runtime/syntax/testdir/input/java_method_references_signature.java
new file mode 100644
index 0000000000..8abfa1af8e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_method_references_signature.java
@@ -0,0 +1,192 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'style'
+// MNV_TEST_SETUP let g:java_highlight_signature = 1
+// MNV_TEST_SETUP let g:java_highlight_generics = 1
+
+import java.lang.invoke.MethodHandle;
+import java.util.function.BiPredicate;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.IntFunction;
+import java.util.function.IntSupplier;
+import java.util.function.Predicate;
+import java.util.function.Supplier;
+import java.util.function.ToIntFunction;
+import java.util.function.UnaryOperator;
+
+class MethodReferences$Tests
+{
+ static {
+ // Primary :: [TypeArguments] Identifier
+ try {
+ Runnable r1 = ((Runtime) null)::gc;
+ } catch (NullPointerException expected) {
+ }
+
+ Supplier<Integer> s1 = ((Number) 0)::hashCode;
+ Supplier<Integer> s2 = ((Comparable<?>) '\0')::hashCode;
+ Supplier<Integer> s3 = ((Comparable<?>) false)::hashCode;
+ Supplier<Integer> s4 = "::"::hashCode;
+ Supplier<Class<?>> s5 = int[].class::arrayType;
+ Supplier<Integer> s6 = new MethodReferences$Tests() ::
+ hashCode;
+ Supplier<Integer> s7 = ((Number)
+ (new MethodReferences$Tests().xy)[0])::intValue;
+ Supplier<int[]> s8 = new MethodReferences$Tests().xy::
+ clone;
+ Consumer<Object> c1 = System.out :: println;
+ Supplier<byte[]> s9 = ((Supplier<String>) ()->"()").get()
+ ::getBytes;
+ Supplier<String> sa = ((Supplier<String>)
+ ((Supplier<String>) ((Supplier<String>)
+ ((Supplier<String>) ((Supplier<String>)
+ () -> "() -> ()")
+ ::toString)
+ ::toString)
+ ::get)
+ ::toString)
+ ::toString;
+
+ // ExpressionName :: [TypeArguments] Identifier
+ // ReferenceType :: [TypeArguments] Identifier
+ Function<String, IntSupplier> f1 = s ->
+ s :: length;
+ Function<int[][], Supplier<int[]>> f2 = ii ->
+ ((int[]) (ii.length > 0 ? ii[0] : ii))
+ :: clone;
+ UnaryOperator<String> uo1 = String::valueOf;
+ ToIntFunction<String> tif1 = s -> s.transform(
+ String :: length);
+
+ // ClassType :: [TypeArguments] new
+ // ArrayType :: new
+ Function<Object, C2> f3 = C2::<Object>new;
+ Function<C2, C2.C21> f4 = pci -> pci.new
+ <String>C21(null); // Cf. "d".
+ Supplier<C1<?>> sb = C1::new;
+ Function<Byte, C1<?>> f5 = C1<Void> :: <Byte> new;
+ IntFunction<C1<?>[]> if1 = C1<?>[] :: new;
+ IntFunction<byte[]> if2 = byte[] :: new;
+ }
+
+ final int[] xy = { 0, 1 };
+
+ // super :: [TypeArguments] Identifier
+ // TypeName . super :: [TypeArguments] Identifier
+ <T> MethodReferences$Tests()
+ {
+ Predicate<T> p1 = MethodReferences$Tests.super::equals;
+ Predicate<T> p2 = MethodReferences$Tests.this::equals;
+ }
+
+ interface I4<T> extends I3<T>
+ {
+ default Predicate<T> superEqualist()
+ {
+ return I3
+ .super::equals; /* "a" */
+ }
+ }
+
+ interface I3<T> extends I2<T>
+ {
+ default Predicate<T> superEqualist()
+ {
+ return I2.
+ super::equals; /* "b" */
+ }
+ }
+
+ interface I2<T> extends I1<T>
+ {
+ default Predicate<T> superEqualist()
+ { /* Non-capturing gymnastics for super::equals. */
+ return Function.<Function<MethodHandle,
+ Predicate<T>>>
+ identity()
+ .apply(mh -> o -> MethodReferences$Tests
+ .invokePredicate(mh, o))
+ .apply(EQUALS.bindTo(this));
+ }
+ }
+
+ interface I1<T>
+ {
+ default Predicate<T> equalist()
+ { /* Non-capturing gymnastics for this::equals. */
+ return Function.<Function<I1<T>, Predicate<T>>>
+ identity()
+ .apply(that -> o -> Function
+ .<BiPredicate<I1<T>, T>>
+ identity()
+ .apply(I1<T>:: /* "c" */
+ equals)
+ .test(that, o))
+ .apply(I1.this);
+ }
+ }
+
+ static <T> boolean invokePredicate(MethodHandle mh, T o)
+ {
+ try {
+ return (boolean) mh.invokeExact(o);
+ } catch (Throwable th) {
+ throw new RuntimeException(th);
+ }
+ }
+
+ private static final MethodHandle EQUALS;
+
+ static {
+ try {
+ EQUALS = java.lang.invoke.MethodHandles.lookup()
+ .findSpecial(
+ I1.class,
+ "equals",
+ java.lang.invoke.MethodType.methodType(
+ boolean.class,
+ Object.class),
+ I2.class);
+ } catch (ReflectiveOperationException e) {
+ throw new Error(e);
+ }
+ }
+
+ static class C1<T>
+ {
+ C1() { }
+ <A> C1(A dummy) { }
+ }
+
+ static class C2
+ {
+ C2() { <String> this(""); }
+
+ <A> C2(A dummy)
+ {
+ C2.stringer().apply(((Function<C2, C2.C21>)
+ C2.C21::new) /* "d" */
+ .apply(C2.this));
+ }
+
+ class C21
+ {
+ C21() { <String> this(""); }
+
+ <B> C21(B dummy)
+ {
+ C2.stringer().apply(C2.this);
+ }
+ }
+
+ static <T extends Object> Function<T, String> stringer()
+ {
+ return T::toString; /* "e" */
+ }
+ }
+
+ static {
+ ((Supplier<Class<?>>)((Supplier<C2.C21>)()->new
+ <Object>C2().new <Object> C21(new<Object>
+ C1< Object >((C1<?>)null)))::getClass).get();
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_methods_indent2.java b/mnv/runtime/syntax/testdir/input/java_methods_indent2.java
new file mode 100644
index 0000000000..ed904eaccb
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_methods_indent2.java
@@ -0,0 +1,139 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'indent2'
+// MNV_TEST_SETUP let g:java_highlight_generics = 1
+// MNV_TEST_SETUP set encoding=utf-8 termencoding=utf-8
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+abstract class Indent2MethodsTests
+{ // DO NOT retab! THIS FILE; REMEMBER ABOUT testdir/ftplugin.
+ // TYPES.
+ record Τʬ<α>(α a) { }
+
+ enum E
+ {
+ A("a"), B("b"), C("c"), D("d"),
+ E("e"), F("f"), G("g"), H("h");
+ final String s;
+ private E(String s) { this.s = s; }
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @java.lang.annotation.Repeatable(Tɐggablɘs.class)
+ @interface Tɐggablɘ
+ {
+ String[] value() default "";
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @interface Tɐggablɘs
+ {
+ Tɐggablɘ[] value();
+ }
+
+ interface Stylable<Α>
+ {
+ default void ascii$0_() { }
+ default Α μʭʭ$0_() { return null; }
+ }
+
+ // FIELDS.
+ private static final Class<?> CLASS_LOCK = classLock();
+
+ private final Object instanceLock = new Object();
+
+ // CONSTRUCTORS.
+ @Tɐggablɘ @Tɐggablɘ protected Indent2MethodsTests() { }
+ <T extends Comparable<T>> Indent2MethodsTests(T t, Void v) { }
+ private <T extends Comparable<T>> Indent2MethodsTests(T t) { }
+
+ // METHODS.
+ @Tɐggablɘ @Tɐggablɘ abstract void ascii$0_(////////////////
+ );
+ @Tɐggablɘ @Tɐggablɘ abstract <α, β> Τʬ<α> μʭʭ$0_(
+ @SuppressWarnings("bespoke") β b);
+
+ @Tɐggablɘ private native void ascii$1_(/*////////////*/);
+ @Tɐggablɘ private native <α, β> Τʬ<α>[] μʭʭ$1_(
+ java.util.function.Function<β, Τʬ<α>[]> ƒ);
+
+ void Ascii$2_() { }
+ <T, U extends Stylable<T>> void Μʭʭ$2_(U u) { }
+
+ static final native synchronized void ascii$98_();
+ static final native synchronized <α, β> Τʬ<α>[][] μʭʭ$98_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ);
+
+ @SuppressWarnings("strictfp")
+ protected static final synchronized strictfp void ascii$99_()
+ { ascii$98_(); }
+
+ @SuppressWarnings("strictfp") protected
+ static final synchronized strictfp <α, β> Τʬ<α>[] μʭʭ$99_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ)
+ {
+ return
+ Indent2MethodsTests.<α, β>μʭʭ$98_(ƒ)[0];
+ }
+
+ public static Class<?> classLock() { return Indent2MethodsTests.class; }
+
+ public <E extends Comparable<? super E>> java.util.List<E> filter(
+ java.util.function.Predicate<? super E> filter,
+ java.util.List<? extends E> cs)
+ {
+ return cs.stream().filter(filter)
+ .collect(java.util.stream.Collectors.toUnmodifiableList());
+ }
+
+ @Override @SuppressWarnings("cast")
+ public String toString() { return (String) "Indent2MethodsTests"; }
+}
+
+enum E2
+{
+ @SuppressWarnings("bespoke") A("a"),
+ B("b"
+ /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/),
+ C("c", new Thread(
+
+ () -> {
+ })), D("d", (java.util.function.BooleanSupplier) () -> true),
+ E("e", new char[] { 'a', 'b', 'c', 'd' }), F("f", new Object() {
+ transient String name = "";
+ @Override public String toString() { return this.name; }
+ }), //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//
+ G("g"), @Deprecated H("h");
+
+ final String s;
+ private E2(String s) { this.s = s; }
+ private <δ> E2(String s, δ dummy) { this(s); }
+
+ @Override public String toString() { return name().toUpperCase(); }
+}
+
+class C2Alias<T>
+{
+ final T name; C2Alias(T name) { this.name = name; }
+
+ class Builder
+ {
+ final java.util.stream.Stream.Builder<T> builder =
+ java.util.stream.Stream.<T>builder();
+
+ C2Alias<T>.Builder add(T x)
+ {
+ builder.accept(x);
+ return this;
+ }
+
+ java.util.stream.Stream<T> build()
+ {
+ return builder.<T>build();
+ }
+ }
+
+ static <A> C2Alias<A>.Builder builder(A name)
+ {
+ return new C2Alias<>(name).new Builder();
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_methods_indent2_signature.java b/mnv/runtime/syntax/testdir/input/java_methods_indent2_signature.java
new file mode 100644
index 0000000000..1594f4f46a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_methods_indent2_signature.java
@@ -0,0 +1,131 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'indent2'
+// MNV_TEST_SETUP let g:java_highlight_signature = 1
+// MNV_TEST_SETUP set encoding=utf-8 termencoding=utf-8
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+abstract class Indent2$MethodsTests
+{ // DO NOT retab! THIS FILE; REMEMBER ABOUT testdir/ftplugin.
+ // TYPES.
+ record Τʬ<α>(α a) { }
+
+ enum E
+ {
+ A("a"), B("b"), C("c"), D("d"),
+ E("e"), F("f"), G("g"), H("h");
+ final String s;
+ private E(String s) { this.s = s; }
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @java.lang.annotation.Repeatable(Tɐggablɘs.class)
+ @interface Tɐggablɘ
+ {
+ String[] value() default "";
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @interface Tɐggablɘs
+ {
+ Tɐggablɘ[] value();
+ }
+
+ interface Stylable<Α>
+ {
+ default void ascii$0_() { }
+ default Α μʭʭ$0_() { return null; }
+ }
+
+ // FIELDS.
+ private static final Class<?> CLASS_LOCK = classLock();
+
+ private final Object instanceLock = new Object();
+
+ // CONSTRUCTORS.
+ @Tɐggablɘ @Tɐggablɘ protected Indent2$MethodsTests() { }
+ <T extends Comparable<T>> Indent2$MethodsTests(T t, Void v) { }
+ private <T extends Comparable<T>> Indent2$MethodsTests(T t) { }
+
+ // METHODS.
+ @Tɐggablɘ @Tɐggablɘ abstract void ascii$0_(////////////////
+ );
+ @Tɐggablɘ @Tɐggablɘ abstract <α, β> Τʬ<α> μʭʭ$0_(
+ @SuppressWarnings("bespoke") β b);
+
+ @Tɐggablɘ private native void ascii$1_(/*////////////*/);
+ @Tɐggablɘ private native <α, β> Τʬ<α>[] μʭʭ$1_(
+ java.util.function.Function<β, Τʬ<α>[]> ƒ);
+
+ void Ascii$2_() { }
+ <T, U extends Stylable<T>> void Μʭʭ$2_(U u) { }
+
+ static final native synchronized void ascii$98_();
+ static final native synchronized <α, β> Τʬ<α>[][] μʭʭ$98_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ);
+
+ @SuppressWarnings("strictfp")
+ protected static final synchronized strictfp void ascii$99_()
+ { ascii$98_(); }
+
+ @SuppressWarnings("strictfp") protected
+ static final synchronized strictfp <α, β> Τʬ<α>[] μʭʭ$99_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ)
+ {
+ return
+ Indent2$MethodsTests.<α, β>μʭʭ$98_(ƒ)[0];
+ }
+
+ public static Class<?> classLock() { return Indent2$MethodsTests.class; }
+
+ @Override @SuppressWarnings("cast")
+ public String toString() { return (String) "Indent2$MethodsTests"; }
+}
+
+enum E2$
+{
+ @SuppressWarnings("bespoke") A("a"),
+ B("b"
+ /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/),
+ C("c", new Thread(
+
+ () -> {
+ })), D("d", (java.util.function.BooleanSupplier) () -> true),
+ E("e", new char[] { 'a', 'b', 'c', 'd' }), F("f", new Object() {
+ transient String name = "";
+ @Override public String toString() { return this.name; }
+ }), //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//
+ G("g"), @Deprecated H("h");
+
+ final String s;
+ private E2$(String s) { this.s = s; }
+ private <δ> E2$(String s, δ dummy) { this(s); }
+
+ @Override public String toString() { return name().toUpperCase(); }
+}
+
+class C2$Alias<T>
+{
+ final T name; C2$Alias(T name) { this.name = name; }
+
+ class Builder
+ {
+ final java.util.stream.Stream.Builder<T> builder =
+ java.util.stream.Stream.<T>builder();
+
+ C2$Alias<T>.Builder add(T x)
+ {
+ builder.accept(x);
+ return this;
+ }
+
+ java.util.stream.Stream<T> build()
+ {
+ return builder.<T>build();
+ }
+ }
+
+ static <A> C2$Alias<A>.Builder builder(A name)
+ {
+ return new C2$Alias<>(name).new Builder();
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_methods_indent4.java b/mnv/runtime/syntax/testdir/input/java_methods_indent4.java
new file mode 100644
index 0000000000..96ed361c11
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_methods_indent4.java
@@ -0,0 +1,139 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'indent4'
+// MNV_TEST_SETUP let g:java_highlight_generics = 1
+// MNV_TEST_SETUP set encoding=utf-8 termencoding=utf-8
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+abstract class Indent4MethodsTests
+{ // DO NOT retab! THIS FILE; REMEMBER ABOUT testdir/ftplugin.
+ // TYPES.
+ record Τʬ<α>(α a) { }
+
+ enum E
+ {
+ A("a"), B("b"), C("c"), D("d"),
+ E("e"), F("f"), G("g"), H("h");
+ final String s;
+ private E(String s) { this.s = s; }
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @java.lang.annotation.Repeatable(Tɐggablɘs.class)
+ @interface Tɐggablɘ
+ {
+ String[] value() default "";
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @interface Tɐggablɘs
+ {
+ Tɐggablɘ[] value();
+ }
+
+ interface Stylable<Α>
+ {
+ default void ascii$0_() { }
+ default Α μʭʭ$0_() { return null; }
+ }
+
+ // FIELDS.
+ private static final Class<?> CLASS_LOCK = classLock();
+
+ private final Object instanceLock = new Object();
+
+ // CONSTRUCTORS.
+ @Tɐggablɘ @Tɐggablɘ protected Indent4MethodsTests() { }
+ <T extends Comparable<T>> Indent4MethodsTests(T t, Void v) { }
+ private <T extends Comparable<T>> Indent4MethodsTests(T t) { }
+
+ // METHODS.
+ @Tɐggablɘ @Tɐggablɘ abstract void ascii$0_(////////////////
+ );
+ @Tɐggablɘ @Tɐggablɘ abstract <α, β> Τʬ<α> μʭʭ$0_(
+ @SuppressWarnings("bespoke") β b);
+
+ @Tɐggablɘ private native void ascii$1_(/*////////////*/);
+ @Tɐggablɘ private native <α, β> Τʬ<α>[] μʭʭ$1_(
+ java.util.function.Function<β, Τʬ<α>[]> ƒ);
+
+ void Ascii$2_() { }
+ <T, U extends Stylable<T>> void Μʭʭ$2_(U u) { }
+
+ static final native synchronized void ascii$98_();
+ static final native synchronized <α, β> Τʬ<α>[][] μʭʭ$98_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ);
+
+ @SuppressWarnings("strictfp")
+ protected static final synchronized strictfp void ascii$99_()
+ { ascii$98_(); }
+
+ @SuppressWarnings("strictfp") protected
+ static final synchronized strictfp <α, β> Τʬ<α>[] μʭʭ$99_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ)
+ {
+ return
+ Indent4MethodsTests.<α, β>μʭʭ$98_(ƒ)[0];
+ }
+
+ public static Class<?> classLock() { return Indent4MethodsTests.class; }
+
+ public <E extends Comparable<? super E>> java.util.List<E> filter(
+ java.util.function.Predicate<? super E> filter,
+ java.util.List<? extends E> cs)
+ {
+ return cs.stream().filter(filter)
+ .collect(java.util.stream.Collectors.toUnmodifiableList());
+ }
+
+ @Override @SuppressWarnings("cast")
+ public String toString() { return (String) "Indent4MethodsTests"; }
+}
+
+enum E4
+{
+ @SuppressWarnings("bespoke") A("a"),
+ B("b"
+ /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/),
+ C("c", new Thread(
+
+ () -> {
+ })), D("d", (java.util.function.BooleanSupplier) () -> true),
+ E("e", new char[] { 'a', 'b', 'c', 'd' }), F("f", new Object() {
+ transient String name = "";
+ @Override public String toString() { return this.name; }
+ }), //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//
+ G("g"), @Deprecated H("h");
+
+ final String s;
+ private E4(String s) { this.s = s; }
+ private <δ> E4(String s, δ dummy) { this(s); }
+
+ @Override public String toString() { return name().toUpperCase(); }
+}
+
+class C4Alias<T>
+{
+ final T name; C4Alias(T name) { this.name = name; }
+
+ class Builder
+ {
+ final java.util.stream.Stream.Builder<T> builder =
+ java.util.stream.Stream.<T>builder();
+
+ C4Alias<T>.Builder add(T x)
+ {
+ builder.accept(x);
+ return this;
+ }
+
+ java.util.stream.Stream<T> build()
+ {
+ return builder.<T>build();
+ }
+ }
+
+ static <A> C4Alias<A>.Builder builder(A name)
+ {
+ return new C4Alias<>(name).new Builder();
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_methods_indent4_signature.java b/mnv/runtime/syntax/testdir/input/java_methods_indent4_signature.java
new file mode 100644
index 0000000000..6da95e30df
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_methods_indent4_signature.java
@@ -0,0 +1,131 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'indent4'
+// MNV_TEST_SETUP let g:java_highlight_signature = 1
+// MNV_TEST_SETUP set encoding=utf-8 termencoding=utf-8
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+abstract class Indent4$MethodsTests
+{ // DO NOT retab! THIS FILE; REMEMBER ABOUT testdir/ftplugin.
+ // TYPES.
+ record Τʬ<α>(α a) { }
+
+ enum E
+ {
+ A("a"), B("b"), C("c"), D("d"),
+ E("e"), F("f"), G("g"), H("h");
+ final String s;
+ private E(String s) { this.s = s; }
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @java.lang.annotation.Repeatable(Tɐggablɘs.class)
+ @interface Tɐggablɘ
+ {
+ String[] value() default "";
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @interface Tɐggablɘs
+ {
+ Tɐggablɘ[] value();
+ }
+
+ interface Stylable<Α>
+ {
+ default void ascii$0_() { }
+ default Α μʭʭ$0_() { return null; }
+ }
+
+ // FIELDS.
+ private static final Class<?> CLASS_LOCK = classLock();
+
+ private final Object instanceLock = new Object();
+
+ // CONSTRUCTORS.
+ @Tɐggablɘ @Tɐggablɘ protected Indent4$MethodsTests() { }
+ <T extends Comparable<T>> Indent4$MethodsTests(T t, Void v) { }
+ private <T extends Comparable<T>> Indent4$MethodsTests(T t) { }
+
+ // METHODS.
+ @Tɐggablɘ @Tɐggablɘ abstract void ascii$0_(////////////////
+ );
+ @Tɐggablɘ @Tɐggablɘ abstract <α, β> Τʬ<α> μʭʭ$0_(
+ @SuppressWarnings("bespoke") β b);
+
+ @Tɐggablɘ private native void ascii$1_(/*////////////*/);
+ @Tɐggablɘ private native <α, β> Τʬ<α>[] μʭʭ$1_(
+ java.util.function.Function<β, Τʬ<α>[]> ƒ);
+
+ void Ascii$2_() { }
+ <T, U extends Stylable<T>> void Μʭʭ$2_(U u) { }
+
+ static final native synchronized void ascii$98_();
+ static final native synchronized <α, β> Τʬ<α>[][] μʭʭ$98_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ);
+
+ @SuppressWarnings("strictfp")
+ protected static final synchronized strictfp void ascii$99_()
+ { ascii$98_(); }
+
+ @SuppressWarnings("strictfp") protected
+ static final synchronized strictfp <α, β> Τʬ<α>[] μʭʭ$99_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ)
+ {
+ return
+ Indent4$MethodsTests.<α, β>μʭʭ$98_(ƒ)[0];
+ }
+
+ public static Class<?> classLock() { return Indent4$MethodsTests.class; }
+
+ @Override @SuppressWarnings("cast")
+ public String toString() { return (String) "Indent4$MethodsTests"; }
+}
+
+enum E4$
+{
+ @SuppressWarnings("bespoke") A("a"),
+ B("b"
+ /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/),
+ C("c", new Thread(
+
+ () -> {
+ })), D("d", (java.util.function.BooleanSupplier) () -> true),
+ E("e", new char[] { 'a', 'b', 'c', 'd' }), F("f", new Object() {
+ transient String name = "";
+ @Override public String toString() { return this.name; }
+ }), //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//
+ G("g"), @Deprecated H("h");
+
+ final String s;
+ private E4$(String s) { this.s = s; }
+ private <δ> E4$(String s, δ dummy) { this(s); }
+
+ @Override public String toString() { return name().toUpperCase(); }
+}
+
+class C4$Alias<T>
+{
+ final T name; C4$Alias(T name) { this.name = name; }
+
+ class Builder
+ {
+ final java.util.stream.Stream.Builder<T> builder =
+ java.util.stream.Stream.<T>builder();
+
+ C4$Alias<T>.Builder add(T x)
+ {
+ builder.accept(x);
+ return this;
+ }
+
+ java.util.stream.Stream<T> build()
+ {
+ return builder.<T>build();
+ }
+ }
+
+ static <A> C4$Alias<A>.Builder builder(A name)
+ {
+ return new C4$Alias<>(name).new Builder();
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_methods_indent8.java b/mnv/runtime/syntax/testdir/input/java_methods_indent8.java
new file mode 100644
index 0000000000..ed41f39f44
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_methods_indent8.java
@@ -0,0 +1,139 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'indent8'
+// MNV_TEST_SETUP let g:java_highlight_generics = 1
+// MNV_TEST_SETUP set encoding=utf-8 termencoding=utf-8
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+abstract class Indent8MethodsTests
+{ // DO NOT retab! THIS FILE; REMEMBER ABOUT testdir/ftplugin.
+ // TYPES.
+ record Τʬ<α>(α a) { }
+
+ enum E
+ {
+ A("a"), B("b"), C("c"), D("d"),
+ E("e"), F("f"), G("g"), H("h");
+ final String s;
+ private E(String s) { this.s = s; }
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @java.lang.annotation.Repeatable(Tɐggablɘs.class)
+ @interface Tɐggablɘ
+ {
+ String[] value() default "";
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @interface Tɐggablɘs
+ {
+ Tɐggablɘ[] value();
+ }
+
+ interface Stylable<Α>
+ {
+ default void ascii$0_() { }
+ default Α μʭʭ$0_() { return null; }
+ }
+
+ // FIELDS.
+ private static final Class<?> CLASS_LOCK = classLock();
+
+ private final Object instanceLock = new Object();
+
+ // CONSTRUCTORS.
+ @Tɐggablɘ @Tɐggablɘ protected Indent8MethodsTests() { }
+ <T extends Comparable<T>> Indent8MethodsTests(T t, Void v) { }
+ private <T extends Comparable<T>> Indent8MethodsTests(T t) { }
+
+ // METHODS.
+ @Tɐggablɘ @Tɐggablɘ abstract void ascii$0_(////////////////
+ );
+ @Tɐggablɘ @Tɐggablɘ abstract <α, β> Τʬ<α> μʭʭ$0_(
+ @SuppressWarnings("bespoke") β b);
+
+ @Tɐggablɘ private native void ascii$1_(/*////////////*/);
+ @Tɐggablɘ private native <α, β> Τʬ<α>[] μʭʭ$1_(
+ java.util.function.Function<β, Τʬ<α>[]> ƒ);
+
+ void Ascii$2_() { }
+ <T, U extends Stylable<T>> void Μʭʭ$2_(U u) { }
+
+ static final native synchronized void ascii$98_();
+ static final native synchronized <α, β> Τʬ<α>[][] μʭʭ$98_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ);
+
+ @SuppressWarnings("strictfp")
+ protected static final synchronized strictfp void ascii$99_()
+ { ascii$98_(); }
+
+ @SuppressWarnings("strictfp") protected
+ static final synchronized strictfp <α, β> Τʬ<α>[] μʭʭ$99_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ)
+ {
+ return
+ Indent8MethodsTests.<α, β>μʭʭ$98_(ƒ)[0];
+ }
+
+ public static Class<?> classLock() { return Indent8MethodsTests.class; }
+
+ public <E extends Comparable<? super E>> java.util.List<E> filter(
+ java.util.function.Predicate<? super E> filter,
+ java.util.List<? extends E> cs)
+ {
+ return cs.stream().filter(filter)
+ .collect(java.util.stream.Collectors.toUnmodifiableList());
+ }
+
+ @Override @SuppressWarnings("cast")
+ public String toString() { return (String) "Indent8MethodsTests"; }
+}
+
+enum E8
+{
+ @SuppressWarnings("bespoke") A("a"),
+ B("b"
+ /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/),
+ C("c", new Thread(
+
+ () -> {
+ })), D("d", (java.util.function.BooleanSupplier) () -> true),
+ E("e", new char[] { 'a', 'b', 'c', 'd' }), F("f", new Object() {
+ transient String name = "";
+ @Override public String toString() { return this.name; }
+ }), //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//
+ G("g"), @Deprecated H("h");
+
+ final String s;
+ private E8(String s) { this.s = s; }
+ private <δ> E8(String s, δ dummy) { this(s); }
+
+ @Override public String toString() { return name().toUpperCase(); }
+}
+
+class C8Alias<T>
+{
+ final T name; C8Alias(T name) { this.name = name; }
+
+ class Builder
+ {
+ final java.util.stream.Stream.Builder<T> builder =
+ java.util.stream.Stream.<T>builder();
+
+ C8Alias<T>.Builder add(T x)
+ {
+ builder.accept(x);
+ return this;
+ }
+
+ java.util.stream.Stream<T> build()
+ {
+ return builder.<T>build();
+ }
+ }
+
+ static <A> C8Alias<A>.Builder builder(A name)
+ {
+ return new C8Alias<>(name).new Builder();
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_methods_indent8_signature.java b/mnv/runtime/syntax/testdir/input/java_methods_indent8_signature.java
new file mode 100644
index 0000000000..f2f7de17a0
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_methods_indent8_signature.java
@@ -0,0 +1,131 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'indent8'
+// MNV_TEST_SETUP let g:java_highlight_signature = 1
+// MNV_TEST_SETUP set encoding=utf-8 termencoding=utf-8
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+abstract class Indent8$MethodsTests
+{ // DO NOT retab! THIS FILE; REMEMBER ABOUT testdir/ftplugin.
+ // TYPES.
+ record Τʬ<α>(α a) { }
+
+ enum E
+ {
+ A("a"), B("b"), C("c"), D("d"),
+ E("e"), F("f"), G("g"), H("h");
+ final String s;
+ private E(String s) { this.s = s; }
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @java.lang.annotation.Repeatable(Tɐggablɘs.class)
+ @interface Tɐggablɘ
+ {
+ String[] value() default "";
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @interface Tɐggablɘs
+ {
+ Tɐggablɘ[] value();
+ }
+
+ interface Stylable<Α>
+ {
+ default void ascii$0_() { }
+ default Α μʭʭ$0_() { return null; }
+ }
+
+ // FIELDS.
+ private static final Class<?> CLASS_LOCK = classLock();
+
+ private final Object instanceLock = new Object();
+
+ // CONSTRUCTORS.
+ @Tɐggablɘ @Tɐggablɘ protected Indent8$MethodsTests() { }
+ <T extends Comparable<T>> Indent8$MethodsTests(T t, Void v) { }
+ private <T extends Comparable<T>> Indent8$MethodsTests(T t) { }
+
+ // METHODS.
+ @Tɐggablɘ @Tɐggablɘ abstract void ascii$0_(////////////////
+ );
+ @Tɐggablɘ @Tɐggablɘ abstract <α, β> Τʬ<α> μʭʭ$0_(
+ @SuppressWarnings("bespoke") β b);
+
+ @Tɐggablɘ private native void ascii$1_(/*////////////*/);
+ @Tɐggablɘ private native <α, β> Τʬ<α>[] μʭʭ$1_(
+ java.util.function.Function<β, Τʬ<α>[]> ƒ);
+
+ void Ascii$2_() { }
+ <T, U extends Stylable<T>> void Μʭʭ$2_(U u) { }
+
+ static final native synchronized void ascii$98_();
+ static final native synchronized <α, β> Τʬ<α>[][] μʭʭ$98_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ);
+
+ @SuppressWarnings("strictfp")
+ protected static final synchronized strictfp void ascii$99_()
+ { ascii$98_(); }
+
+ @SuppressWarnings("strictfp") protected
+ static final synchronized strictfp <α, β> Τʬ<α>[] μʭʭ$99_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ)
+ {
+ return
+ Indent8$MethodsTests.<α, β>μʭʭ$98_(ƒ)[0];
+ }
+
+ public static Class<?> classLock() { return Indent8$MethodsTests.class; }
+
+ @Override @SuppressWarnings("cast")
+ public String toString() { return (String) "Indent8$MethodsTests"; }
+}
+
+enum E8$
+{
+ @SuppressWarnings("bespoke") A("a"),
+ B("b"
+ /*\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/),
+ C("c", new Thread(
+
+ () -> {
+ })), D("d", (java.util.function.BooleanSupplier) () -> true),
+ E("e", new char[] { 'a', 'b', 'c', 'd' }), F("f", new Object() {
+ transient String name = "";
+ @Override public String toString() { return this.name; }
+ }), //\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//\//
+ G("g"), @Deprecated H("h");
+
+ final String s;
+ private E8$(String s) { this.s = s; }
+ private <δ> E8$(String s, δ dummy) { this(s); }
+
+ @Override public String toString() { return name().toUpperCase(); }
+}
+
+class C8$Alias<T>
+{
+ final T name; C8$Alias(T name) { this.name = name; }
+
+ class Builder
+ {
+ final java.util.stream.Stream.Builder<T> builder =
+ java.util.stream.Stream.<T>builder();
+
+ C8$Alias<T>.Builder add(T x)
+ {
+ builder.accept(x);
+ return this;
+ }
+
+ java.util.stream.Stream<T> build()
+ {
+ return builder.<T>build();
+ }
+ }
+
+ static <A> C8$Alias<A>.Builder builder(A name)
+ {
+ return new C8$Alias<>(name).new Builder();
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_methods_style.java b/mnv/runtime/syntax/testdir/input/java_methods_style.java
new file mode 100644
index 0000000000..e927b817c7
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_methods_style.java
@@ -0,0 +1,117 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'style'
+// MNV_TEST_SETUP let g:java_highlight_generics = 1
+// MNV_TEST_SETUP set encoding=utf-8 termencoding=utf-8
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+abstract class StyleMethodsTests
+{
+ // TYPES.
+ record Τʬ<α>(α a) { }
+
+ enum E
+ {
+ A("a"), B("b"), C("c"), D("d"),
+ E("e"), F("f"), G("g"), H("h");
+ final String s;
+ private E(String s) { this.s = s; }
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @java.lang.annotation.Repeatable(Tɐggablɘs.class)
+ @interface Tɐggablɘ
+ {
+ String[] value() default "";
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @interface Tɐggablɘs
+ {
+ Tɐggablɘ[] value();
+ }
+
+ interface Stylable<Α>
+ {
+ default void ascii$0_() { }
+ default Α μʭʭ$0_() { return null; }
+ }
+
+ // FIELDS.
+ private static final Class<?> CLASS_LOCK = classLock();
+
+ private final Object instanceLock = new Object();
+
+ // CONSTRUCTORS.
+ @Tɐggablɘ @Tɐggablɘ protected StyleMethodsTests() { }
+ <T extends Comparable<T>> StyleMethodsTests(T t, Void v) { }
+ private <T extends Comparable<T>> StyleMethodsTests(T t) { }
+
+ // METHODS.
+ @Tɐggablɘ @Tɐggablɘ abstract void ascii$0_(////////////////
+ );
+ @Tɐggablɘ @Tɐggablɘ abstract <α, β> Τʬ<α> μʭʭ$0_(
+ @SuppressWarnings("bespoke") β b);
+
+ @Tɐggablɘ private native void ascii$1_(/*////////////*/);
+ @Tɐggablɘ private native <α, β> Τʬ<α>[] μʭʭ$1_(
+ java.util.function.Function<β, Τʬ<α>[]> ƒ);
+
+ void Ascii$2_() { }
+ <T, U extends Stylable<T>> void Μʭʭ$2_(U u) { }
+
+ static final native synchronized void ascii$98_();
+ static final native synchronized <α, β> Τʬ<α>[][] μʭʭ$98_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ);
+
+ @SuppressWarnings("strictfp")
+ protected static final synchronized strictfp void ascii$99_()
+ { ascii$98_(); }
+
+ @SuppressWarnings("strictfp") protected
+ static final synchronized strictfp <α, β> Τʬ<α>[] μʭʭ$99_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ)
+ {
+ return
+ StyleMethodsTests.<α, β>μʭʭ$98_(ƒ)[0];
+ }
+
+ public static Class<?> classLock() { return StyleMethodsTests.class; }
+
+ public <E extends Comparable<? super E>> java.util.List<E> filter(
+ java.util.function.Predicate<? super E> filter,
+ java.util.List<? extends E> cs)
+ {
+ return cs.stream().filter(filter)
+ .collect(java.util.stream.Collectors.toUnmodifiableList());
+ }
+
+ @Override @SuppressWarnings("cast")
+ public String toString() { return (String) "StyleMethodsTests"; }
+}
+
+class StyleAlias<T>
+{
+ final T name; StyleAlias(T name) { this.name = name; }
+
+ class Builder
+ {
+ final java.util.stream.Stream.Builder<T> builder =
+ java.util.stream.Stream.<T>builder();
+
+ StyleAlias<T>.Builder add(T x)
+ {
+ builder.accept(x);
+ return this;
+ }
+
+ java.util.stream.Stream<T> build()
+ {
+ return builder.<T>build();
+ }
+ }
+
+ static <A> StyleAlias<A>.Builder builder(A name)
+ {
+ return new StyleAlias<>(name).new Builder();
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_methods_style_signature.java b/mnv/runtime/syntax/testdir/input/java_methods_style_signature.java
new file mode 100644
index 0000000000..f713ebeae6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_methods_style_signature.java
@@ -0,0 +1,109 @@
+// MNV_TEST_SETUP let g:java_highlight_functions = 'style'
+// MNV_TEST_SETUP let g:java_highlight_signature = 1
+// MNV_TEST_SETUP set encoding=utf-8 termencoding=utf-8
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+abstract class Style$MethodsTests
+{
+ // TYPES.
+ record Τʬ<α>(α a) { }
+
+ enum E
+ {
+ A("a"), B("b"), C("c"), D("d"),
+ E("e"), F("f"), G("g"), H("h");
+ final String s;
+ private E(String s) { this.s = s; }
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @java.lang.annotation.Repeatable(Tɐggablɘs.class)
+ @interface Tɐggablɘ
+ {
+ String[] value() default "";
+ }
+
+ @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
+ @interface Tɐggablɘs
+ {
+ Tɐggablɘ[] value();
+ }
+
+ interface Stylable<Α>
+ {
+ default void ascii$0_() { }
+ default Α μʭʭ$0_() { return null; }
+ }
+
+ // FIELDS.
+ private static final Class<?> CLASS_LOCK = classLock();
+
+ private final Object instanceLock = new Object();
+
+ // CONSTRUCTORS.
+ @Tɐggablɘ @Tɐggablɘ protected Style$MethodsTests() { }
+ <T extends Comparable<T>> Style$MethodsTests(T t, Void v) { }
+ private <T extends Comparable<T>> Style$MethodsTests(T t) { }
+
+ // METHODS.
+ @Tɐggablɘ @Tɐggablɘ abstract void ascii$0_(////////////////
+ );
+ @Tɐggablɘ @Tɐggablɘ abstract <α, β> Τʬ<α> μʭʭ$0_(
+ @SuppressWarnings("bespoke") β b);
+
+ @Tɐggablɘ private native void ascii$1_(/*////////////*/);
+ @Tɐggablɘ private native <α, β> Τʬ<α>[] μʭʭ$1_(
+ java.util.function.Function<β, Τʬ<α>[]> ƒ);
+
+ void Ascii$2_() { }
+ <T, U extends Stylable<T>> void Μʭʭ$2_(U u) { }
+
+ static final native synchronized void ascii$98_();
+ static final native synchronized <α, β> Τʬ<α>[][] μʭʭ$98_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ);
+
+ @SuppressWarnings("strictfp")
+ protected static final synchronized strictfp void ascii$99_()
+ { ascii$98_(); }
+
+ @SuppressWarnings("strictfp") protected
+ static final synchronized strictfp <α, β> Τʬ<α>[] μʭʭ$99_(
+ java.util.function.Function<β, Τʬ<α>[][]> ƒ)
+ {
+ return
+ Style$MethodsTests.<α, β>μʭʭ$98_(ƒ)[0];
+ }
+
+ public static Class<?> classLock() { return Style$MethodsTests.class; }
+
+ @Override @SuppressWarnings("cast")
+ public String toString() { return (String) "Style$MethodsTests"; }
+}
+
+class Style$Alias<T>
+{
+ final T name; Style$Alias(T name) { this.name = name; }
+
+ class Builder
+ {
+ final java.util.stream.Stream.Builder<T> builder =
+ java.util.stream.Stream.<T>builder();
+
+ Style$Alias<T>.Builder add(T x)
+ {
+ builder.accept(x);
+ return this;
+ }
+
+ java.util.stream.Stream<T> build()
+ {
+ return builder.<T>build();
+ }
+ }
+
+ static <A> Style$Alias<A>.Builder builder(A name)
+ {
+ return new Style$Alias<>(name).new Builder();
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_module_info.java b/mnv/runtime/syntax/testdir/input/java_module_info.java
new file mode 100644
index 0000000000..0fe49efecd
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_module_info.java
@@ -0,0 +1,35 @@
+// This module declaration belongs to the sample project published at
+// https://github.com/zzzyxwvut/module-info.git .
+import module java.base;
+import java.util.ServiceLoader;
+
+/**
+ * Defines demo related support.
+ *
+ * Note that the {@code Testable} service is not exported.
+ *
+ * @uses org.demo.internal.Testable
+ * @provides org.demo.internal.Testable
+ * @see ServiceLoader
+ */
+module org.module.info.demo // JDK 23+ (--enable-preview --release 23).
+{
+ requires static jdk.jfr;
+ requires java.base;
+ requires transitive java.logging;
+ requires transitive static org.module.info.tester;
+
+ exports org.demo;
+ exports org.demo.internal to
+ org.module.info.demo;
+
+ opens org.demo.internal to
+ org.module.info.demo;
+ opens org.demo.tests to
+ org.module.info.demo, org.module.info.tester;
+
+ uses org.demo.internal.Testable;
+
+ provides org.demo.internal.Testable with
+ org.demo.tests.ArithmeticOperationTests;
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_numbers.java b/mnv/runtime/syntax/testdir/input/java_numbers.java
new file mode 100644
index 0000000000..e9265349a4
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_numbers.java
@@ -0,0 +1,88 @@
+class NumbersTests
+{
+ static {
+ double[] dd = {
+ 0x.0p0, 0x0.p0, 0x0.0p0, 0x0P0,
+ 0x.0p0d, 0x0.p0d, 0x0.0p0d, 0x0P0D,
+ 0x.0p0f, 0x0.p0f, 0x0.0p0f, 0x0P0F,
+ 0x.0p0, 0x0.p0, 0x0.0p0, 0x0P0,
+ 0x.0p0d, 0x0.p0d, 0x0.0p0d, 0x0P0D,
+ 0x.0p0f, 0x0.p0f, 0x0.0p0f, 0x0P0F,
+ 0x.0p-0, 0x0.p-0, 0x0.0p-0, 0x0P-0,
+ 0x.0p-0d, 0x0.p-0d, 0x0.0p-0d, 0x0P-0D,
+ 0x.0p-0f, 0x0.p-0f, 0x0.0p-0f, 0x0P-0F,
+ 0x.0p+0, 0x0.p+0, 0x0.0p+0, 0x0P+0,
+ 0x.0p+0d, 0x0.p+0d, 0x0.0p+0d, 0x0P+0D,
+ 0x.0p+0f, 0x0.p+0f, 0x0.0p+0f, 0x0P+0F,
+
+ 1., 1.2, 1.2e3, 1.2e3d, 1.2e3f,
+ 1.2e-3, 1.2e-3d, 1.2E-3F,
+ 1.2e+3, 1.2E+3D, 1.2e+3f,
+ .2, .2e3, .2e3d, .2e3f,
+ .2e-3, .2e-3d, .2E-3F,
+ .2e+3, .2E+3D, .2e+3f,
+ 1e3, 1e3d, 1e3f,
+ 1e-3, 1e-3d, 1E-3F,
+ 1e+3, 1E+3D, 1e+3f,
+ 1d, 1D, 1f, 1F,
+
+//// MALFORMED: :let g:java_comment_strings = 1 | doautocmd Syntax
+// 0_x.0p0, 0x._0p0, 0x.0_p0, 0x.0p_0, 0x.0p0_,
+// 0x0_.0p0, 0x_0.0p0, 0xp0,
+ };
+
+ int O = 0;
+ int OO = 00;
+ int OxO = 0x0;
+
+ int x = 0x12_345_678;
+ int y = 0b01_01_01_01_01;
+ int z = 0__1__2__3__4__5__6__7;
+
+ // String.format("%a", -1.0)
+ double minus_one_d = -0x1.0p0;
+
+ double z_d = -0x.0p0;
+ double y_d = 0xap1__0__0;
+ double x_d = .0__1__2__3__4__5__6__7__8__9;
+ double dot_O = .0;
+
+ // JLS, §3.10.2:
+ float max_dec_f = 3.4028235e38f;
+ float max_hex_f = 0x1.fffffeP+127f;
+ float min_dec_f = 1.4e-45f;
+ float min_hex_f_a = 0x0.000002P-126f;
+ float min_hex_f_b = 0x1.0P-149f;
+
+ double max_dec_d = 1.7976931348623157e3__0__8;
+ double max_hex_d = 0x1.f_ffff_ffff_ffffP+1023;
+ double min_dec_d = 4.9e-3__2__4;
+ double min_hex_d_a = 0x0.0_0000_0000_0001P-1022;
+ double min_hex_d_b = 0x1.0P-1074;
+
+ // JLS, §3.10.1:
+ int max_hex = 0x7fff_ffff;
+ int max_oct = 0177_7777_7777;
+ int max_bin = 0b0111_1111_1111_1111_1111_1111_1111_1111;
+
+ int min_hex = 0x8000_0000;
+ int min_oct = 0200_0000_0000;
+ int min_bin = 0b1000_0000_0000_0000_0000_0000_0000_0000;
+
+ int minus_one_hex = 0xffff_ffff;
+ int minus_one_oct = 0377_7777_7777;
+ int minus_one_bin = 0b1111_1111_1111_1111_1111_1111_1111_1111;
+
+ long max_hex_l = 0x7fff_ffff_ffff_ffffL;
+ long max_oct_l = 07_7777_7777_7777_7777_7777L;
+ long max_bin_l = 0b0111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L;
+
+ long min_hex_l = 0x8000_0000_0000_0000L;
+ long min_oct_l = 010_0000_0000_0000_0000_0000L;
+ long min_bin_l = 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000L;
+
+ long minus_one_hex_l = 0xffff_ffff_ffff_ffffL;
+ long minus_one_oct_l = 017_7777_7777_7777_7777_7777L;
+ long minus_one_bin_l = 0b1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111_1111L;
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_previews_430.java b/mnv/runtime/syntax/testdir/input/java_previews_430.java
new file mode 100644
index 0000000000..34f0078ff5
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_previews_430.java
@@ -0,0 +1,68 @@
+// MNV_TEST_SETUP let g:java_syntax_previews = [430]
+
+
+
+class StringTemplateTests // JDK 21+ (--enable-preview --release 21).
+{
+ static {
+ System.out.println(STR."""
+ "
+ \{"\"\""}
+ \{"\"\""}\{"\u005c\u0022"}
+ \{"\"\""}\{"\u005c\u0022"}"
+ \{"\"\""}\"\{"\u005c\u0022\u005c\u0022"}
+ \{"\"\""}\"\{"\"\""}\{"\u005c\u0022"}
+ \{"\"\""}\"\{"\"\""}\""
+ \{"\"\""}\"\{"\"\""}\""\"""");
+
+ String woof = "Woof", dog = "dog", fox = "fox";
+
+ String s1 = STR
+ ."A quick brown \{fox} jumps over the lazy \{dog}";
+ String s2 = STR.process(StringTemplate.RAW
+ ."\"\{woof}\s!\"");
+ String s3 = STR."""
+ A\s\
+ quick \
+ brown\s\
+ \{fox} \
+ jumps\s\
+ over \
+ the\s\
+ lazy \
+ \{dog}""";
+ String s4 = STR.process(StringTemplate.RAW
+ .
+ """
+ "\{woof}\s!\"""");
+ String s5 = java.util.FormatProcessor.FMT
+ . "%-14s\{"A\s" + STR . "quick" + "brown"}%s\{fox} "
+ + java.util.FormatProcessor.FMT
+ . "%-20s\{"jumps\sover the\s"
+ + STR . "lazy"}%s\{dog}";
+ String s6 = STR."""
+ \"\{ // A nested comment.
+ (new java.util.function.Function<String, String>() {
+ public String apply(String bay) { return bay; };
+ }).apply(woof)
+ }\s!\"""";
+ String s7 = java.util.FormatProcessor.FMT
+ ."""
+ %-14s\{STR."""
+ A\s\
+ \{ "quick" } \
+ brown"""}\
+ %s\{ fox } \
+ %-20s\{STR."""
+ jumps\s\
+ over \
+ the\s\
+ \{ "lazy" } """}\
+ %s\{ dog }""";
+ String s8 = STR
+ ."\"\{ /* A nested comment. */
+ ((java.util.function.Function<String, String>) bay -> bay)
+ .apply(woof)
+ }\s!\"";
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_previews_455.java b/mnv/runtime/syntax/testdir/input/java_previews_455.java
new file mode 100644
index 0000000000..ebd9ba0829
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_previews_455.java
@@ -0,0 +1,64 @@
+// MNV_TEST_SETUP let g:java_syntax_previews = [455, 488, 507, 530]
+
+
+
+class PrimitiveSwitchTests // JDK 23+ (--enable-preview --release 23).
+{
+ static void echo(Object o) { System.out.println(o); }
+
+ static {
+ long g = 2L;
+
+ switch (g) {
+ case 0L: { echo(0L); break; }
+ case 1L: { echo(1L); break; }
+ default: { echo(-1L); break; }
+ }
+
+ echo(switch (g) {
+ case 0L -> 0L;
+ case 1L -> 1L;
+ default -> -1L;
+ });
+
+ boolean bool = false;
+
+ switch (bool) {
+ case true: { echo(true); break; }
+ case false: { echo(false); break; }
+ }
+
+ echo(switch (bool) {
+ case true -> true;
+ case false -> false;
+ });
+
+ float f = 2.0f;
+
+ switch (f) {
+ case 0.0f: { echo(0.0f); break; }
+ case 1.0f: { echo(1.0f); break; }
+ default: { echo(-1.0f); break; }
+ }
+
+ echo(switch (f) {
+ case 0.0f -> 0.0f;
+ case 1.0f -> 1.0f;
+ default -> -1.0f;
+ });
+
+ double d = 2.0;
+
+ switch (d) {
+ case 0.0: { echo(0.0); break; }
+ case 1.0: { echo(1.0); break; }
+ default: { echo(-1.0); break; }
+ }
+
+ echo(switch (d) {
+ case 0.0 -> 0.0;
+ case 1.0 -> 1.0;
+ default -> -1.0;
+ });
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_string.java b/mnv/runtime/syntax/testdir/input/java_string.java
new file mode 100644
index 0000000000..51c30b9da8
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_string.java
@@ -0,0 +1,44 @@
+class StringTests
+{
+ static {
+ String s1 = "A quick brown fox jumps over the lazy dog";
+ String s2 = "\"Woof\s!\"";
+ String s3 = """
+ A\s\
+ quick \
+ brown\s\
+ fox \
+ jumps\s\
+ over \
+ the\s\
+ lazy \
+ dog""";
+ String s4 = """
+ "Woof\s!\"""";
+ String s5 = """
+ String s3 = \"""
+ A\\s\\
+ quick \\
+ brown\\s\\
+ fox \\
+ jumps\\s\\
+ over \\
+ the\\s\\
+ lazy \\
+ dog\""";""";
+
+ // There are SPACE, FF, HT, CR, and LF after """.
+ String empty = """
+ """;
+
+ System.out.println("""
+ "
+ ""
+ ""\u005c"
+ ""\u005c""
+ ""\"\u0022\u0022
+ ""\"""\u005c\u0022
+ ""\"""\""
+ ""\"""\""\"""");
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_switch.java b/mnv/runtime/syntax/testdir/input/java_switch.java
new file mode 100644
index 0000000000..d82fcb1832
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_switch.java
@@ -0,0 +1,122 @@
+class SwitchTests // JDK 21+.
+{
+ static void echo(Object o) { System.out.println(o); }
+
+ static {
+ interface Yieldable<T>
+ {
+ T yield();
+ default Yieldable<T> default_() { return this; }
+ default Yieldable<T> when() { return this; }
+ }
+
+ // There are 80 bytes (\@80<!) between "::" and "yield;".
+ Yieldable<?> y = ((Yieldable<?>) () -> 0)::
+ yield;
+ ((Yieldable<?>) () -> 0).when().default_().yield();
+
+ enum Letters { OTHER, ALPHA, BETA }
+
+ Letters when = Letters.OTHER;
+
+ switch (when) {
+ case ALPHA: { echo(Letters.ALPHA); break; }
+ case BETA: { echo(Letters.BETA); break; }
+ default: { echo(Letters.OTHER); }
+ }
+
+ echo(switch (when) {
+ case ALPHA -> Letters.ALPHA;
+ case BETA -> Letters.BETA;
+ default -> { yield(Letters.OTHER); }
+ });
+
+ String yield = null;
+
+ switch (yield) {
+ case "A": case "B": { echo("A or B"); break; }
+ case ":": { echo("Colon"); break; }
+ case String str when !str.equals(""):
+ { echo("<non-empty>"); break; }
+ case null: default: { echo("Other"); }
+ }
+
+ echo(switch (yield) {
+ case "A", "B" -> { yield("A or B"); }
+ case "->" -> "Arrow";
+ case String str when !str.equals("")
+ -> "<non-empty>";
+ case null, default -> "Other";
+ });
+
+ Object o = new Object();
+
+ switch (o) {
+ case null: { echo("null"); break; }
+ case Letters[] ll: { echo("SwitchTests$1Letters[]"); break; }
+ default: { echo("java.lang.Object"); break; }
+ }
+
+ echo(switch (o) {
+ case null -> "null";
+ case Letters[] ll -> "SwitchTests$1Letters[]";
+ default -> "java.lang.Object";
+ });
+
+ char ch = 'c';
+
+ switch (ch) {
+ case 'a': { echo('a'); break; }
+ case 'b': { echo('b'); break; }
+ default: { echo('\u0000'); break; }
+ }
+
+ echo(switch (ch) {
+ case 'a' -> 'a';
+ case 'b' -> 'b';
+ default -> '\u0000';
+ });
+
+ byte b = (byte) 2;
+
+ switch (b) {
+ case ((byte) 0): { echo((byte) 0); break; }
+ case ((byte) 1): { echo((byte) 1); break; }
+ default: { echo((byte) -1); break; }
+ }
+
+ echo(switch (b) {
+ case ((byte) 0) -> (byte) 0;
+ case ((byte) 1) -> (byte) 1;
+ default -> (byte) -1;
+ });
+
+ short sh = (short) 2;
+
+ switch (sh) {
+ case ((short) 0): { echo((short) 0); break; }
+ case ((short) 1): { echo((short) 1); break; }
+ default: { echo((short) -1); break; }
+ }
+
+ echo(switch (sh) {
+ case ((short) 0) -> (short) 0;
+ case ((short) 1) -> (short) 1;
+ default -> (short) -1;
+ });
+
+ int i = 2;
+
+ switch (i) {
+ case 0b0__00___000: { echo(0); break; }
+ case 0x000___00__1: { echo(1); break; }
+ default: { echo(-1); break; }
+ }
+
+ echo(switch (i) {
+ case 0_0_0_0_0 -> 0;
+ case 1 -> 1;
+ default -> -1;
+ });
+ }
+}
diff --git a/mnv/runtime/syntax/testdir/input/java_unfoldment.java b/mnv/runtime/syntax/testdir/input/java_unfoldment.java
new file mode 100644
index 0000000000..ca8760245a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/java_unfoldment.java
@@ -0,0 +1,145 @@
+// MNV_TEST_SETUP setlocal fen fdc=2 fdl=8 fdm=syntax
+// MNV_TEST_SETUP let g:java_highlight_java_lang = 1
+// MNV_TEST_SETUP let g:java_ignore_folding = "bcdi"
+// MNV_TEST_SETUP let g:java_lookbehind_byte_counts = {'javaBlock': -1}
+// MNV_TEST_SETUP let g:java_mark_braces_in_parens_as_errors = 1
+
+
+
+
+
+// MNV_TEST_SETUP highlight link javaBlockOtherStart Structure
+// MNV_TEST_SETUP highlight link javaBlockStart Todo
+
+
+
+/***/ import java.lang.Comparable; /*
+import java.lang.Object;
+import java.lang.String;
+*/
+import java.lang.String;
+
+import java.lang.Comparable; /***/
+import java.lang.Object; // //
+import java.lang.String; /***/
+
+import java.util.function.Function;
+ @SuppressWarnings({
+ """
+ bespoke
+ /*
+ *
+ */
+ /**
+ *
+ */
+ ///
+ ///
+ ///
+ //
+ //
+ //
+ {
+ }
+"""
+})
+class UnfoldingTests {
+ interface Unfoldable
+ {
+ }
+
+ static {
+ String import⁠$ = """
+import java.lang.String;
+""";
+ new Object() {
+ {
+ {
+ new Object() {{{
+ new Object() {{{}}};
+ }}};
+ }
+ }
+ };
+
+ switch (0) {
+ case 0:
+ case 1: {
+ break;
+ }
+ default: ;
+ }
+ }
+
+ { Object bb = ((Object) new byte[]{}); }
+ {
+out: {
+ do {
+ if (true)
+ break out;
+ } while (false);
+}
+ }
+/*\\\*/ {
+ (new Function<Object, Object>() {
+ /**
+ * {@inheritDoc} */
+ public Object apply(Object o) { return o; };
+ }).apply(
+ (new Function<Object, Object>() {
+ /** {@inheritDoc}
+ */
+ public Object apply(Object o) { return o; };
+ }));
+ }
+
+ /**
+ * No operation.
+ */
+ void noOp1() { }
+ /** No operation. */
+ void noOp2()
+ {
+ }
+ /** No operation. */
+ void noOp3() {
+ }
+ /** No operation. */
+ void noOp4() {
+ /*/\/\/\*/ ; }
+
+ /// No operation.
+ ///
+ ///
+ void noOp5() { }
+ /// No operation.
+ void noOp6()
+ {
+ }
+ /// No operation.
+ void noOp7() {
+ }
+ /// No operation.
+ void noOp8() {
+ /*/\/\/\*/ ; }
+}
+
+/*
+ * Some note.
+ * {
+ * }
+ */
+/**
+ * A summary.
+ * {
+ * }
+ */
+/// A summary.
+/// {
+/// }
+//
+// {
+// }
+
+/* 120|........................................................................................*/ interface Unfoldable {
+}
diff --git a/mnv/runtime/syntax/testdir/input/leex.xrl b/mnv/runtime/syntax/testdir/input/leex.xrl
new file mode 100644
index 0000000000..c901b8b87d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/leex.xrl
@@ -0,0 +1,28 @@
+% Header comment
+%% Header comment
+%%% Header comment
+
+Definitions.
+floats = (\+|-)?[0-9]+\.[0-9]+((E|e)(\+|-)?[0-9]+)?
+D = [0-9]
+A = ({D}|_|@)
+WS = ([\000-\s]|%.*) % whitespace
+
+Rules.
+{D}+ :
+ % Comment
+ {token,{integer,TokenLine,list_to_integer(TokenChars)}}.
+{D}+\.{D}+((E|e)(\+|\-)?{D}+)? :
+ % Coment with period.
+ {token,{float,TokenLine,list_to_float(TokenChars)}}.
+{A} : ErlangCode. % comment
+{WS} : ErlangCode.
+:= :{token,{':=',TokenLine}}.
+
+Erlang code.
+
+-export([reserved_word/1]).
+
+%% reserved_word(Atom) -> Bool
+reserved_word('reserved') -> true;
+reserved_word(_) -> false.
diff --git a/mnv/runtime/syntax/testdir/input/make_01.mak b/mnv/runtime/syntax/testdir/input/make_01.mak
new file mode 100644
index 0000000000..e97c13c0aa
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/make_01.mak
@@ -0,0 +1,16 @@
+# comment
+
+a = b
+$(a) = 1
+
+$(a)::
+ @echo double-colon rule
+
+$(a) += output
+
+define say
+ echo $1
+endef
+
+default:
+ $(call say,"Hello (world)!")
diff --git a/mnv/runtime/syntax/testdir/input/markdown_circularity.markdown b/mnv/runtime/syntax/testdir/input/markdown_circularity.markdown
new file mode 100644
index 0000000000..8f442a9ee2
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/markdown_circularity.markdown
@@ -0,0 +1,54 @@
+No code is recognised in HTML snippets.
+
+~~~html
+<pre><code>
+/** HTML syntax circularity tests. */
+class HTMLSyntaxCircularityTests
+{
+ /// @hidden
+ ///
+ /// @param args optional command-line arguments
+ public static void main(String[] args)
+ {
+ System.out.println("""
+ ```java
+ class SyntaxCircularityTests
+ {
+ public static void main(String[] args)
+ {
+ System.out.println(".");
+ }
+ }
+ ```
+ """);
+ }
+}
+</code></pre>
+~~~
+
+
+Markdown documentation comments are not recognised in Java snippets.
+
+```java
+/** Java syntax circularity tests. */
+class JavaSyntaxCircularityTests
+{
+ /// @hidden
+ ///
+ /// @param args optional command-line arguments
+ public static void main(String[] args)
+ {
+ System.out.println("""
+ <pre><code>
+ class SyntaxCircularityTests
+ {
+ public static void main(String[] args)
+ {
+ System.out.println(".");
+ }
+ }
+ </code></pre>
+ """);
+ }
+}
+```
diff --git a/mnv/runtime/syntax/testdir/input/markdown_conceal.markdown b/mnv/runtime/syntax/testdir/input/markdown_conceal.markdown
new file mode 100644
index 0000000000..8049d68a34
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/markdown_conceal.markdown
@@ -0,0 +1,15 @@
+_Italic_, *Italic*. __Bold__, **Bold**.
+___Bold Italic___, ***Bold Italic***.
+~~Strikethrough~~, S̶t̶r̶i̶k̶e̶t̶h̶r̶o̶u̶g̶h̶.
+
+~~~html
+<p>
+<del>Strikethrough</del>, <s>Strikethrough</s>.<br />
+~~~
+
+```html
+<strong><em>Bold Italic</em></strong>.
+<strong><em>Bold Italic</em></strong>.<br />
+<strong>Bold</strong>, <strong>Bold</strong>.
+<em>Italic</em>, <em>Italic</em>.
+```
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_blocks.mnv b/mnv/runtime/syntax/testdir/input/mnv9_blocks.mnv
new file mode 100644
index 0000000000..26bbbb388c
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_blocks.mnv
@@ -0,0 +1,49 @@
+mnv9script
+# MNV9 blocks
+# MNV_TESTSETUP set list listchars=trail:-
+
+
+{
+ var foo = 42
+}
+
+
+{
+ {
+ {
+ {
+ var foo = 42
+ }
+ var foo = 42
+ }
+ var foo = 42
+ }
+ var foo = 42
+}
+
+
+def Foo()
+ {
+ var foo = 42
+ echo foo
+ }
+enddef
+
+
+# start/end patterns
+
+{
+ var foo = 42
+}
+
+{ # comment
+ var foo = 42
+} # comment
+
+echo "Foo" | { | echo "Bar"
+ var foo = 42
+} | echo "Baz"
+
+# dictionary
+{}->items()
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_builtin_object_methods.mnv b/mnv/runtime/syntax/testdir/input/mnv9_builtin_object_methods.mnv
new file mode 100644
index 0000000000..b05b36ea88
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_builtin_object_methods.mnv
@@ -0,0 +1,114 @@
+mnv9script
+# MNV9 special methods - new*(), empty(), len(), string()
+
+
+def new()
+enddef
+
+def newOther()
+enddef
+
+def newyetanother()
+enddef
+
+def empty(): bool
+ return true
+enddef
+
+def len(): number
+ return 0
+enddef
+
+def string(): string
+ return ""
+enddef
+
+class A
+ def new()
+ def newNested()
+ enddef
+ def empty(): bool
+ return true
+ enddef
+ def len(): number
+ return 0
+ enddef
+ def string(): string
+ return ""
+ enddef
+ enddef
+
+ def newOther()
+ def newNested()
+ enddef
+ def empty(): bool
+ return true
+ enddef
+ def len(): number
+ return 0
+ enddef
+ def string(): string
+ return ""
+ enddef
+ enddef
+
+ def newyetanother()
+ def newNested()
+ enddef
+ def empty(): bool
+ return true
+ enddef
+ def len(): number
+ return 0
+ enddef
+ def string(): string
+ return ""
+ enddef
+ enddef
+
+ def empty(): bool
+ def newNested()
+ enddef
+ def empty(): bool
+ return true
+ enddef
+ def len(): number
+ return 0
+ enddef
+ def string(): string
+ return ""
+ enddef
+ return true
+ enddef
+
+ def len(): number
+ def newNested()
+ enddef
+ def empty(): bool
+ return true
+ enddef
+ def len(): number
+ return 0
+ enddef
+ def string(): string
+ return ""
+ enddef
+ return 0
+ enddef
+
+ def string(): string
+ def newNested()
+ enddef
+ def empty(): bool
+ return true
+ enddef
+ def len(): number
+ return 0
+ enddef
+ def string(): string
+ return ""
+ enddef
+ return ""
+ enddef
+endclass
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_builtin_object_methods2.mnv b/mnv/runtime/syntax/testdir/input/mnv9_builtin_object_methods2.mnv
new file mode 100644
index 0000000000..8bfbdccc38
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_builtin_object_methods2.mnv
@@ -0,0 +1,58 @@
+mnv9script
+# MNV |builtin-object-methods| and namesake builtin functions
+# MNV_TEST_SETUP hi link mnv9MethodName Special
+# MNV_TEST_SETUP hi link mnv9This Todo
+
+
+class PairClassTest
+ public const a: any
+ public const b: any
+
+ def new(a: any, b: any)
+ this.a = a
+ this.b = b
+ enddef
+
+ def empty(): bool
+ return false
+ enddef
+ def len(): number
+ return 2
+ enddef
+ def string(): string
+ return printf('(%s, %s)', this.a, this.b)
+ enddef
+endclass
+
+enum MarkerEnumTest
+ INSTANCE
+
+ def NoOp()
+ enddef
+
+ def empty(): bool
+ return true
+ enddef
+ def len(): number
+ return 0
+ enddef
+ def string(): string
+ return this.name
+ enddef
+endenum
+
+const b1: bool = empty(MarkerEnumTest.INSTANCE)
+const n1: number = len(MarkerEnumTest.INSTANCE)
+const s1: string = string(MarkerEnumTest.INSTANCE)
+echo b1 && MarkerEnumTest.INSTANCE.empty()
+echo n1 == 0 && MarkerEnumTest.INSTANCE.len() == 0
+echo s1 == 'INSTANCE' && MarkerEnumTest.INSTANCE.string() == 'INSTANCE'
+
+const pair: PairClassTest = PairClassTest.new(0, 1)
+const b2: bool = !pair.empty()
+const n2: number = pair.len()
+const s2: string = pair.string()
+echo b2 && !empty(pair)
+echo n2 == 2 && len(pair) == 2
+echo s2 == '(0, 1)' && string(pair) == '(0, 1)'
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_comment_strings.mnv b/mnv/runtime/syntax/testdir/input/mnv9_comment_strings.mnv
new file mode 100644
index 0000000000..adfae6493e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_comment_strings.mnv
@@ -0,0 +1,27 @@
+mnv9script
+# MNV9 comment strings
+# MNV_TEST_SETUP let g:mnvsyn_comment_strings = v:true
+
+
+# pre "string" post
+
+function Foo()
+ " pre "string" post
+endfunction
+
+def Bar()
+ # pre "string" post
+enddef
+
+command Foo {
+ # pre "string" post
+}
+
+autocmd BufNewFile * {
+ # pre "string" post
+}
+
+{
+ # pre "string" post
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_comments.mnv b/mnv/runtime/syntax/testdir/input/mnv9_comments.mnv
new file mode 100644
index 0000000000..0aafc3114a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_comments.mnv
@@ -0,0 +1,99 @@
+mnv9script
+# MNV9 comments
+
+
+# MNV9-script comment
+
+ # string only recognised with leading char
+ "useless string"
+
+function! Foo()
+ " Legacy-script comment
+ # 42 " comment
+endfunction
+
+def! Bar()
+ # MNV9-script comment
+ "useless string" # comment
+enddef
+
+command -count FooCommand {
+ # MNV9-script comment
+ "useless string" # comment
+}
+
+autocmd BufNewFile * {
+ # MNV9-script comment
+ "useless string" # comment
+}
+
+
+# Multiline comments
+
+# comment
+ \ continuing comment
+ \ continuing comment
+
+var foo = 42 # commment
+ \ continuing comment
+ \ continuing comment
+
+# :Foo
+ \ arg1
+ #\ comment
+ \ arg2
+
+echo "TOP"
+
+
+# Line-continuation comments
+
+:Foo
+ #\ line continuation comment
+ \ arg1
+ #\ line continuation comment
+ \ arg2
+
+
+# Expression comments
+
+var foo = { # comment
+ # comment
+ bar: 42, # comment
+ # comment
+ # comment
+ baz: 42 # comment
+ # comment
+} # comment
+
+
+# Issue: #13047
+
+if !exists(":DiffOrig")
+ command DiffOrig vert new | set bt=nofile | r ++edit %% | 0d_ | diffthis
+ \ | wincmd p | diffthis
+endif
+
+
+# Issue: #11307 and #11560
+
+# This is what we call " blah
+
+
+# PR: #14975
+# https://github.com/Project-Tick/Project-Tick/pull/14975#issuecomment-2832643115
+
+var d = {
+ a: 0,
+# a ' quote {{{
+#}}}
+b: 0,
+}
+
+
+# PR: #19390
+# https://github.com/Project-Tick/Project-Tick/pull/19390#issue-3933755846
+
+# E1234: should not have mnv9CommentTitle on 'E1234:'
+# ERR34: should have mnv9CommentTitle on 'ERR34:'
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_constructors.mnv b/mnv/runtime/syntax/testdir/input/mnv9_constructors.mnv
new file mode 100644
index 0000000000..ca424a53c4
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_constructors.mnv
@@ -0,0 +1,18 @@
+mnv9script
+# MNV9 constructors
+
+
+class A
+ static var _instance: A
+ var str: string
+ def _new(str: string)
+ this.str = str
+ enddef
+ static def GetInstance(str: string): A
+ if _instance == null
+ _instance = A._new(str)
+ endif
+ return _instance
+ enddef
+endclass
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_def_variables.mnv b/mnv/runtime/syntax/testdir/input/mnv9_def_variables.mnv
new file mode 100644
index 0000000000..4c0d8aae78
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_def_variables.mnv
@@ -0,0 +1,226 @@
+mnv9script
+# MNV9 function variables
+
+
+def Foo()
+
+ # Declarations
+
+ var foo = expr
+
+ b:foo = expr
+ g:foo = expr
+ t:foo = expr
+ w:foo = expr
+
+ v:true = expr
+
+ $FOO = expr
+
+ var [foo, bar] = expr
+ var [foo,
+ \ bar] = expr
+ var [$foo, $bar] = expr
+ var [$foo,
+ \ $bar] = expr
+
+ var [foo, bar; baz] = expr
+ var [foo,
+ \ bar;
+ \ baz] = expr
+ var [$foo, $bar; $baz] = expr
+ var [$foo,
+ \ $bar;
+ \ $baz] = expr
+
+ var foo =<< END
+...
+END
+ var foo =<< trim END
+ ...
+ END
+ var foo =<< eval END
+...
+END
+ var foo =<< trim eval END
+ ...
+ END
+ var foo =<< eval trim END
+ ...
+ END
+
+ # Assignments
+
+ foo = expr
+
+ foo[0] = expr
+
+ foo[1:2] = expr
+ foo[:2] = expr
+ foo[1:] = expr
+ foo[:] = expr
+
+ foo["key"] = expr
+ foo['key'] = expr
+
+ foo += expr
+ foo -= expr
+ foo *= expr
+ foo /= expr
+ foo %= expr
+ foo ..= expr
+
+ b:foo = expr
+ g:foo = expr
+ t:foo = expr
+ w:foo = expr
+
+ b:foo += expr
+ g:foo += expr
+ t:foo += expr
+ w:foo += expr
+
+ b:foo -= expr
+ g:foo -= expr
+ t:foo -= expr
+ w:foo -= expr
+
+ b:foo *= expr
+ g:foo *= expr
+ t:foo *= expr
+ w:foo *= expr
+
+ b:foo /= expr
+ g:foo /= expr
+ t:foo /= expr
+ w:foo /= expr
+
+ b:foo %= expr
+ g:foo %= expr
+ t:foo %= expr
+ w:foo %= expr
+
+ b:foo ..= expr
+ g:foo ..= expr
+ t:foo ..= expr
+ w:foo ..= expr
+
+ $FOO = expr
+ $FOO ..= expr
+
+ @f = expr
+ @f ..= expr
+
+ &ari = expr
+
+ &t_k1 = "\<Esc>[234;"
+
+ &ari ..= expr
+
+ &ari += expr
+ &ari -= expr
+
+ &l:aleph = expr
+
+ &l:aleph ..= expr
+ &l:aleph += expr
+ &l:aleph -= expr
+
+ &g:aleph = expr
+
+ &g:aleph ..= expr
+ &g:aleph += expr
+ &g:aleph -= expr
+
+ [foo, bar] = expr
+ [foo,
+ \ bar] = expr
+ [v:true, v:false] = expr
+ [v:true,
+ \ v:false] = expr
+ [&ari, &bkc] = expr
+ [&ari,
+ \ &bkc] = expr
+ [$foo, $bar] = expr
+ [$foo,
+ \ $bar] = expr
+ [@a, @b] = expr
+ [@a,
+ \ @a] = expr
+
+ [foo, bar] ..= expr
+ [foo, bar] += expr
+ [foo, bar] -= expr
+ [foo, bar] *= expr
+ [foo, bar] /= expr
+ [foo, bar] %= expr
+
+ [foo, bar; baz] = expr
+ [foo,
+ \ bar;
+ \ baz] = expr
+ [v:true, v:false; v:none] = expr
+ [v:true,
+ \ v:false;
+ \ v:none] = expr
+ [$foo, $bar; $baz] = expr
+ [$foo,
+ \ $bar;
+ \ $baz] = expr
+ [&ari, &bkc; &cmp] = expr
+ [&ari,
+ \ &bkc;
+ \ &cmp] = expr
+ [@a, @b; @c] = expr
+ [@a,
+ \ @b;
+ \ @c] = expr
+
+ foo =<< END
+...
+END
+ foo =<< trim END
+ ...
+ END
+ foo =<< eval END
+...
+END
+ foo =<< trim eval END
+ ...
+ END
+ foo =<< eval trim END
+ ...
+ END
+
+ # :for
+
+ for foo in expr
+ endfor
+
+ for [foo, bar] in expr
+ endfor
+
+# Scope dictionaries
+
+echo get(b:, 'foo', 42)
+echo get(w:, 'foo', 42)
+echo get(t:, 'foo', 42)
+echo get(g:, 'foo', 42)
+echo get(v:, 'foo', 42)
+
+for k in keys(b:) | echo b:[k] | endfor
+for k in keys(w:) | echo w:[k] | endfor
+for k in keys(t:) | echo t:[k] | endfor
+for k in keys(g:) | echo g:[k] | endfor
+for k in keys(v:) | echo v:[k] | endfor
+
+# Neomnv-specific variables (not highlighted by default)
+
+echo v:lua v:msgpack_types v:relnum v:stderr v:termrequest v:virtnum
+
+echo &channel &inccommand &mousescroll &pumblend &redrawdebug &scrollback
+echo &shada &shadafile &statuscolumn &termpastefilter &termsync &winbar
+echo &winblend
+
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_class_fold.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_class_fold.mnv
new file mode 100644
index 0000000000..35f953011e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_class_fold.mnv
@@ -0,0 +1,71 @@
+mnv9script
+# MNV9 :class command
+# MNV_TEST_SETUP let g:mnvsyn_folding = 'cfi'
+# MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+
+
+interface Interface1
+endinterface
+interface Interface2
+endinterface
+
+class Class1
+endclass
+
+export class Class2
+endclass
+
+abstract class Class3
+endclass
+
+export abstract class Class4
+endclass
+
+class Class5 extends Class1
+endclass
+
+export class Class6 extends Class1
+endclass
+
+class Class7 implements Interface1, Interface2
+endclass
+
+export class Class8 implements Interface1, Interface2
+endclass
+
+class Class9
+ def new()
+ enddef
+ def Method1(): void
+ def Nested1(): void
+ def Nested2(): void
+ enddef
+ enddef
+ enddef
+ def _Method2(): void
+ enddef
+ static def Method3(): void
+ enddef
+endclass
+
+abstract class Class10
+ abstract def Method1(): void
+ abstract def string(): string
+endclass
+
+
+# Issue: #14393
+
+interface Testable
+ def SetUp()
+ def TearDown()
+endinterface
+
+abstract class TestTemplate implements Testable
+ var failed: number
+ var passed: number
+
+ abstract def SetUp()
+ abstract def TearDown()
+endclass
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_commands.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_commands.mnv
new file mode 100644
index 0000000000..f484b2b254
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_commands.mnv
@@ -0,0 +1,1211 @@
+mnv9script
+# MNV9 Ex commands
+
+
+# START NOT MATCHED
+:Next
+:X
+# END NOT MATCHED
+
+:help
+ :help
+: help
+ : help # FIXME
+
+:@
+
+:abbreviate
+:abclear
+:aboveleft
+:abstract
+:all
+:amenu
+:anoremenu
+:argadd
+:argdedupe
+:argdelete
+:argdo
+:argedit
+:argglobal
+:arglocal
+:args
+:argument
+:ascii
+:augroup Foo
+:augroup END
+:aunmenu
+:autocmd
+:badd
+:ball
+:balt
+:bdelete
+:behave mswin
+:behave xterm
+:belowright
+:bfirst
+:blast
+:bmodified
+:bnext
+:bNext
+:botright
+:bprevious
+:break
+:breakadd
+:breakdel
+:breaklist
+:brewind
+:browse
+:bufdo
+:buffer
+:buffers
+:bunload
+:bwipeout
+:cabbrev
+:cabclear
+:cabove
+:caddbuffer
+:caddexpr
+:caddfile
+:cafter
+:call
+:catch
+:cbefore
+:cbelow
+:cbottom
+:cbuffer
+:cc
+:cclose
+:cd
+:cdo
+:center
+:cexpr
+:cfdo
+:cfile
+:cfirst
+:cgetbuffer
+:cgetexpr
+:cgetfile
+:changes
+:chdir
+:checkpath
+:checktime
+:chistory
+:class
+:clast
+:clearjumps
+:clist
+:close
+:cmap
+:cmapclear
+:cmenu
+:cnewer
+:cnext
+:cNext
+:cnfile
+:cNfile
+:cnoreabbrev
+:cnoremap
+:cnoremenu
+:colder
+:colorscheme
+:comclear
+:command
+:compiler
+:confirm
+:const
+:continue
+:copen
+:copy
+:cpfile
+:cprevious
+:cquit
+:crewind
+:cscope
+:cstag
+:cunabbrev
+:cunmap
+:cunmenu
+:cwindow
+:debug
+:debuggreedy
+:def
+:defcompile
+:defcompile
+:defer
+:delcommand
+:delete
+:delfunction
+:delmarks
+:diffget
+:diffoff
+:diffpatch
+:diffput
+:diffsplit
+:diffthis
+:diffupdate
+:digraphs
+:disassemble
+:disassemble
+:display
+:djump
+:dl
+:dlist
+:doautoall
+:doautocmd
+:dp
+:drop
+:dsearch
+:dsplit
+:earlier
+:echo
+:echoconsole
+:echoerr
+:echohl
+:echomsg
+:echon
+:echowindow
+:edit
+:else
+:elseif
+:emenu
+:endclass
+:enddef
+:endenum
+:endfor
+:endfunction
+:endif
+:endinterface
+:endtry
+:endwhile
+:enew
+:enum
+:eval
+:ex
+:execute
+:exit
+:export
+:export
+:exusage
+:file
+:files
+:filetype
+:filter
+:final
+:finally
+:find
+:finish
+:first
+:fixdel
+:fold
+:foldclose
+:folddoclosed
+:folddoopen
+:foldopen
+:for foo in bar | endfor
+:function
+:global/.../
+:goto
+:grep
+:grepadd
+:gui
+:gmnv
+:hardcopy
+:help
+:helpclose
+:helpfind
+:helpgrep
+:helptags
+:hide
+:highlight
+:history
+:horizontal
+:iabbrev
+:iabclear
+:if
+:ijump
+:ilist
+:imap
+:imapclear
+:imenu
+:import
+:inoreabbrev
+:inoremap
+:inoremenu
+:interface
+:intro
+:isearch
+:isplit
+:iunabbrev
+:iunmap
+:iunmenu
+:join
+:jumps
+:k
+:keepalt
+:keepjumps
+:keepmarks
+:keeppatterns
+:labove
+:laddbuffer
+:laddexpr
+:laddfile
+:lafter
+:language
+:last
+:later
+:lbefore
+:lbelow
+:lbottom
+:lbuffer
+:lcd
+:lchdir
+:lclose
+:lcscope
+:ldo
+:left
+:leftabove
+:legacy
+:lexpr
+:lfdo
+:lfile
+:lfirst
+:lgetbuffer
+:lgetexpr
+:lgetfile
+:lgrep
+:lgrepadd
+:lhelpgrep
+:lhistory
+:list
+:ll
+:llast
+:llist
+:lmake
+:lmap
+:lmapclear
+:lnewer
+:lnext
+:lNext
+:lnfile
+:lNfile
+:lnoremap
+# :loadkeymap # disabled - runs until EOF
+:loadview
+:lockmarks
+:lockvar
+:lolder
+:lopen
+:lpfile
+:lprevious
+:lrewind
+:ls
+:ltag
+:lua
+:luado
+:luafile
+:lunmap
+:lmnvgrep
+:lmnvgrepadd
+:lwindow
+:make
+:mapclear
+:map
+:mark
+:marks
+:match
+:menu
+:menutranslate
+:messages
+:mkexrc
+:mksession
+:mkspell
+:mkview
+:mkmnvrc
+:move
+:mzfile
+:mzscheme
+:nbclose
+:nbkey
+:nbstart
+:new
+:next
+:nmap
+:nmapclear
+:nmenu
+:nnoremap
+:nnoremenu
+:noautocmd
+:nohlsearch
+:noreabbrev
+:noremap
+:noremenu
+:normal
+:noswapfile
+:number
+:nunmap
+:nunmenu
+:oldfiles
+:omap
+:omapclear
+:omenu
+:only
+:onoremap
+:onoremenu
+:options
+:ounmap
+:ounmenu
+:ownsyntax
+:packadd
+:packloadall
+:pclose
+:pedit
+:perl
+:perldo
+:pop
+:popup
+:ppop
+:preserve
+:previous
+:print
+:profdel
+:profile
+:promptfind
+:promptrepl
+:psearch
+:ptag
+:ptfirst
+:ptjump
+:ptlast
+:ptnext
+:ptNext
+:ptprevious
+:ptrewind
+:ptselect
+:put
+:pwd
+:py3
+:py3do
+:py3file
+:pydo
+:pyfile
+:python
+:python3
+:pythonx
+:pyx
+:pyxdo
+:pyxfile
+:qall
+:quit
+:quitall
+:read
+:recover
+:redir
+:redo
+:redraw
+:redrawstatus
+:redrawtabline
+:registers
+:resize
+:retab
+:return
+:rewind
+:right
+:rightbelow
+:ruby
+:rubydo
+:rubyfile
+:rundo
+:runtime
+:rmnvinfo
+:sall
+:sandbox
+:sargument
+:saveas
+:sball
+:sbfirst
+:sblast
+:sbmodified
+:sbnext
+:sbNext
+:sbprevious
+:sbrewind
+:sbuffer
+:scriptencoding
+:scriptnames
+:scriptversion
+:scscope
+:set
+:setfiletype
+:setglobal
+:setlocal
+:sfind
+:sfirst
+:shell
+:sign
+:silent
+:simalt
+:slast
+:sleep
+:sleep!
+:smagic
+:smap
+:smapclear
+:smenu
+:smile
+:snext
+:sNext
+:snomagic
+:snoremap
+:snoremenu
+:sort
+:source
+:spelldump
+:spellgood
+:spellinfo
+:spellrare
+:spellrepall
+:spellundo
+:spellwrong
+:split
+:sprevious
+:srewind
+:stag
+:startgreplace
+:startinsert
+:startreplace
+:stjump
+:stop
+:stopinsert
+:stselect
+:substitute
+:sunhide
+:sunmap
+:sunmenu
+:suspend
+:sview
+:swapname
+:syncbind
+:syntax
+:syntime
+:tab
+:tabclose
+:tabdo
+:tabedit
+:tabfind
+:tabfirst
+:tablast
+:tabmove
+:tabnew
+:tabnext
+:tabNext
+:tabonly
+:tabprevious
+:tabrewind
+:tabs
+:tag
+:tags
+:tcd
+:tchdir
+:tcl
+:tcldo
+:tclfile
+:tearoff
+:terminal
+:tfirst
+:throw
+:tjump
+:tlast
+:tlmenu
+:tlnoremenu
+:tlunmenu
+:tmap
+:tmapclear
+:tmenu
+:tnext
+:tNext
+:tnoremap
+:topleft
+:tprevious
+:trewind
+:try
+:tselect
+:tunmap
+:tunmenu
+:type
+:unabbreviate
+:unabbreviate
+:undo
+:undojoin
+:undolist
+:unhide
+:uniq
+:unlockvar
+:unmap
+:unmenu
+:unsilent
+:update
+:var
+:verbose
+:version
+:vertical
+:vglobal/.../
+:view
+:mnv9cmd
+# :mnv9script
+:mnvgrep
+:mnvgrepadd
+:visual
+:viusage
+:vmap
+:vmapclear
+:vmenu
+:vnew
+:vnoremap
+:vnoremenu
+:vsplit
+:vunmap
+:vunmenu
+:wall
+:while
+:wincmd
+:windo
+:winpos
+:winsize
+:wnext
+:wNext
+:wprevious
+:wq
+:wqall
+:write
+:wundo
+:wmnvinfo
+:xall
+:xmap
+:xmapclear
+:xmenu
+:xnoremap
+:xnoremenu
+:xrestore
+:xunmap
+:xunmenu
+:yank
+:z
+
+Foo()|help
+Foo() | help
+Foo() |help
+Foo()| help
+
+Foo() | abbreviate
+Foo() | abclear
+Foo() | aboveleft
+Foo() | abstract
+Foo() | all
+Foo() | amenu
+Foo() | anoremenu
+Foo() | argadd
+Foo() | argdedupe
+Foo() | argdelete
+Foo() | argdo
+Foo() | argedit
+Foo() | argglobal
+Foo() | arglocal
+Foo() | args
+Foo() | argument
+Foo() | ascii
+Foo() | augroup Foo | augroup END
+Foo() | aunmenu
+Foo() | autocmd
+Foo() | badd
+Foo() | ball
+Foo() | balt
+Foo() | bdelete
+Foo() | behave mswin
+Foo() | behave xterm
+Foo() | belowright
+Foo() | bfirst
+Foo() | blast
+Foo() | bmodified
+Foo() | bnext
+Foo() | bNext
+Foo() | botright
+Foo() | bprevious
+Foo() | break
+Foo() | breakadd
+Foo() | breakdel
+Foo() | breaklist
+Foo() | brewind
+Foo() | browse
+Foo() | bufdo
+Foo() | buffer
+Foo() | buffers
+Foo() | bunload
+Foo() | bwipeout
+Foo() | cabbrev
+Foo() | cabclear
+Foo() | cabove
+Foo() | caddbuffer
+Foo() | caddexpr
+Foo() | caddfile
+Foo() | cafter
+Foo() | call
+Foo() | catch
+Foo() | cbefore
+Foo() | cbelow
+Foo() | cbottom
+Foo() | cbuffer
+Foo() | cc
+Foo() | cclose
+Foo() | cd
+Foo() | cdo
+Foo() | center
+Foo() | cexpr
+Foo() | cfdo
+Foo() | cfile
+Foo() | cfirst
+Foo() | cgetbuffer
+Foo() | cgetexpr
+Foo() | cgetfile
+Foo() | changes
+Foo() | chdir
+Foo() | checkpath
+Foo() | checktime
+Foo() | chistory
+Foo() | class
+Foo() | clast
+Foo() | clearjumps
+Foo() | clist
+Foo() | close
+Foo() | cmap
+Foo() | cmapclear
+Foo() | cmenu
+Foo() | cnewer
+Foo() | cnext
+Foo() | cNext
+Foo() | cnfile
+Foo() | cNfile
+Foo() | cnoreabbrev
+Foo() | cnoremap
+Foo() | cnoremenu
+Foo() | colder
+Foo() | colorscheme
+Foo() | comclear
+Foo() | command
+Foo() | compiler
+Foo() | confirm
+Foo() | const
+Foo() | continue
+Foo() | copen
+Foo() | copy
+Foo() | cpfile
+Foo() | cprevious
+Foo() | cquit
+Foo() | crewind
+Foo() | cscope
+Foo() | cstag
+Foo() | cunabbrev
+Foo() | cunmap
+Foo() | cunmenu
+Foo() | cwindow
+Foo() | debug
+Foo() | debuggreedy
+Foo() | def
+Foo() | defcompile
+Foo() | defcompile
+Foo() | defer
+Foo() | delcommand
+Foo() | delete
+Foo() | delfunction
+Foo() | delmarks
+Foo() | diffget
+Foo() | diffoff
+Foo() | diffpatch
+Foo() | diffput
+Foo() | diffsplit
+Foo() | diffthis
+Foo() | diffupdate
+Foo() | digraphs
+Foo() | disassemble
+Foo() | disassemble
+Foo() | display
+Foo() | djump
+Foo() | dl
+Foo() | dlist
+Foo() | doautoall
+Foo() | doautocmd
+Foo() | dp
+Foo() | drop
+Foo() | dsearch
+Foo() | dsplit
+Foo() | earlier
+Foo() | echo
+Foo() | echoconsole
+Foo() | echoerr
+Foo() | echohl
+Foo() | echomsg
+Foo() | echon
+Foo() | echowindow
+Foo() | edit
+Foo() | else
+Foo() | elseif
+Foo() | emenu
+Foo() | endclass
+Foo() | enddef
+Foo() | endenum
+Foo() | endfor
+Foo() | endfunction
+Foo() | endif
+Foo() | endinterface
+Foo() | endtry
+Foo() | endwhile
+Foo() | enew
+Foo() | enum
+Foo() | eval
+Foo() | ex
+Foo() | execute
+Foo() | exit
+Foo() | export
+Foo() | export
+Foo() | exusage
+Foo() | file
+Foo() | files
+Foo() | filetype
+Foo() | filter
+Foo() | final
+Foo() | finally
+Foo() | find
+Foo() | finish
+Foo() | first
+Foo() | fixdel
+Foo() | fold
+Foo() | foldclose
+Foo() | folddoclosed
+Foo() | folddoopen
+Foo() | foldopen
+Foo() | for foo in bar | endfor
+Foo() | function
+Foo() | global/.../
+Foo() | goto
+Foo() | grep
+Foo() | grepadd
+Foo() | gui
+Foo() | gmnv
+Foo() | hardcopy
+Foo() | help
+Foo() | helpclose
+Foo() | helpfind
+Foo() | helpgrep
+Foo() | helptags
+Foo() | hide
+Foo() | highlight
+Foo() | history
+Foo() | horizontal
+Foo() | iabbrev
+Foo() | iabclear
+Foo() | if
+Foo() | ijump
+Foo() | ilist
+Foo() | imap
+Foo() | imapclear
+Foo() | imenu
+Foo() | import
+Foo() | inoreabbrev
+Foo() | inoremap
+Foo() | inoremenu
+Foo() | interface
+Foo() | intro
+Foo() | isearch
+Foo() | isplit
+Foo() | iunabbrev
+Foo() | iunmap
+Foo() | iunmenu
+Foo() | join
+Foo() | jumps
+Foo() | keepalt
+Foo() | keepjumps
+Foo() | keepmarks
+Foo() | keeppatterns
+Foo() | labove
+Foo() | laddbuffer
+Foo() | laddexpr
+Foo() | laddfile
+Foo() | lafter
+Foo() | language
+Foo() | last
+Foo() | later
+Foo() | lbefore
+Foo() | lbelow
+Foo() | lbottom
+Foo() | lbuffer
+Foo() | lcd
+Foo() | lchdir
+Foo() | lclose
+Foo() | lcscope
+Foo() | ldo
+Foo() | left
+Foo() | leftabove
+Foo() | legacy
+Foo() | lexpr
+Foo() | lfdo
+Foo() | lfile
+Foo() | lfirst
+Foo() | lgetbuffer
+Foo() | lgetexpr
+Foo() | lgetfile
+Foo() | lgrep
+Foo() | lgrepadd
+Foo() | lhelpgrep
+Foo() | lhistory
+Foo() | list
+Foo() | ll
+Foo() | llast
+Foo() | llist
+Foo() | lmake
+Foo() | lmap
+Foo() | lmapclear
+Foo() | lnewer
+Foo() | lnext
+Foo() | lNext
+Foo() | lnfile
+Foo() | lNfile
+Foo() | lnoremap
+# Foo() | loadkeymap # disabled - runs until EOF
+Foo() | loadview
+Foo() | lockmarks
+Foo() | lockvar
+Foo() | lolder
+Foo() | lopen
+Foo() | lpfile
+Foo() | lprevious
+Foo() | lrewind
+Foo() | ls
+Foo() | ltag
+Foo() | lua
+Foo() | luado
+Foo() | luafile
+Foo() | lunmap
+Foo() | lmnvgrep
+Foo() | lmnvgrepadd
+Foo() | lwindow
+Foo() | make
+Foo() | mark
+Foo() | move
+Foo() | map
+Foo() | mapclear
+Foo() | marks
+Foo() | match
+Foo() | menu
+Foo() | menutranslate
+Foo() | messages
+Foo() | mkexrc
+Foo() | mksession
+Foo() | mkspell
+Foo() | mkview
+Foo() | mkmnvrc
+Foo() | mzfile
+Foo() | mzscheme
+Foo() | nbclose
+Foo() | nbkey
+Foo() | nbstart
+Foo() | new
+Foo() | next
+Foo() | nmap
+Foo() | nmapclear
+Foo() | nmenu
+Foo() | nnoremap
+Foo() | nnoremenu
+Foo() | noautocmd
+Foo() | nohlsearch
+Foo() | noreabbrev
+Foo() | noremap
+Foo() | noremenu
+Foo() | normal
+Foo() | noswapfile
+Foo() | number
+Foo() | nunmap
+Foo() | nunmenu
+Foo() | oldfiles
+Foo() | omap
+Foo() | omapclear
+Foo() | omenu
+Foo() | only
+Foo() | onoremap
+Foo() | onoremenu
+Foo() | options
+Foo() | ounmap
+Foo() | ounmenu
+Foo() | ownsyntax
+Foo() | packadd
+Foo() | packloadall
+Foo() | pclose
+Foo() | pedit
+Foo() | perl
+Foo() | perldo
+Foo() | pop
+Foo() | popup
+Foo() | ppop
+Foo() | preserve
+Foo() | previous
+Foo() | print
+Foo() | profdel
+Foo() | profile
+Foo() | promptfind
+Foo() | promptrepl
+Foo() | psearch
+Foo() | ptag
+Foo() | ptfirst
+Foo() | ptjump
+Foo() | ptlast
+Foo() | ptnext
+Foo() | ptNext
+Foo() | ptprevious
+Foo() | ptrewind
+Foo() | ptselect
+Foo() | put
+Foo() | pwd
+Foo() | py3
+Foo() | py3do
+Foo() | py3file
+Foo() | pydo
+Foo() | pyfile
+Foo() | python
+Foo() | python3
+Foo() | pythonx
+Foo() | pyx
+Foo() | pyxdo
+Foo() | pyxfile
+Foo() | qall
+Foo() | quit
+Foo() | quitall
+Foo() | read
+Foo() | recover
+Foo() | redir
+Foo() | redo
+Foo() | redraw
+Foo() | redrawstatus
+Foo() | redrawtabline
+Foo() | registers
+Foo() | resize
+Foo() | retab
+Foo() | return
+Foo() | rewind
+Foo() | right
+Foo() | rightbelow
+Foo() | ruby
+Foo() | rubydo
+Foo() | rubyfile
+Foo() | rundo
+Foo() | runtime
+Foo() | rmnvinfo
+Foo() | sall
+Foo() | sandbox
+Foo() | sargument
+Foo() | saveas
+Foo() | sball
+Foo() | sbfirst
+Foo() | sblast
+Foo() | sbmodified
+Foo() | sbnext
+Foo() | sbNext
+Foo() | sbprevious
+Foo() | sbrewind
+Foo() | sbuffer
+Foo() | scriptencoding
+Foo() | scriptnames
+Foo() | scriptversion
+Foo() | scscope
+Foo() | set
+Foo() | setfiletype
+Foo() | setglobal
+Foo() | setlocal
+Foo() | sfind
+Foo() | sfirst
+Foo() | shell
+Foo() | sign
+Foo() | silent
+Foo() | simalt
+Foo() | slast
+Foo() | sleep
+Foo() | sleep!
+Foo() | smagic
+Foo() | smap
+Foo() | smapclear
+Foo() | smenu
+Foo() | smile
+Foo() | snext
+Foo() | sNext
+Foo() | snomagic
+Foo() | snoremap
+Foo() | snoremenu
+Foo() | sort
+Foo() | source
+Foo() | spelldump
+Foo() | spellgood
+Foo() | spellinfo
+Foo() | spellrare
+Foo() | spellrepall
+Foo() | spellundo
+Foo() | spellwrong
+Foo() | split
+Foo() | sprevious
+Foo() | srewind
+Foo() | stag
+Foo() | startgreplace
+Foo() | startinsert
+Foo() | startreplace
+Foo() | stjump
+Foo() | stop
+Foo() | stopinsert
+Foo() | stselect
+Foo() | substitute
+Foo() | sunhide
+Foo() | sunmap
+Foo() | sunmenu
+Foo() | suspend
+Foo() | sview
+Foo() | swapname
+Foo() | syncbind
+Foo() | syntax
+Foo() | syntime
+Foo() | tab
+Foo() | tabclose
+Foo() | tabdo
+Foo() | tabedit
+Foo() | tabfind
+Foo() | tabfirst
+Foo() | tablast
+Foo() | tabmove
+Foo() | tabnew
+Foo() | tabnext
+Foo() | tabNext
+Foo() | tabonly
+Foo() | tabprevious
+Foo() | tabrewind
+Foo() | tabs
+Foo() | tag
+Foo() | tags
+Foo() | tcd
+Foo() | tchdir
+Foo() | tcl
+Foo() | tcldo
+Foo() | tclfile
+Foo() | tearoff
+Foo() | terminal
+Foo() | tfirst
+Foo() | throw
+Foo() | tjump
+Foo() | tlast
+Foo() | tlmenu
+Foo() | tlnoremenu
+Foo() | tlunmenu
+Foo() | tmap
+Foo() | tmapclear
+Foo() | tmenu
+Foo() | tnext
+Foo() | tNext
+Foo() | tnoremap
+Foo() | topleft
+Foo() | tprevious
+Foo() | trewind
+Foo() | try
+Foo() | tselect
+Foo() | tunmap
+Foo() | tunmenu
+Foo() | type
+Foo() | unabbreviate
+Foo() | unabbreviate
+Foo() | undo
+Foo() | undojoin
+Foo() | undolist
+Foo() | unhide
+Foo() | uniq
+Foo() | unlockvar
+Foo() | unmap
+Foo() | unmenu
+Foo() | unsilent
+Foo() | update
+Foo() | var
+Foo() | verbose
+Foo() | version
+Foo() | vertical
+Foo() | vglobal/.../
+Foo() | mnv9cmd
+# call Foo() | mnv9script
+Foo() | mnvgrep
+Foo() | mnvgrepadd
+Foo() | visual
+Foo() | viusage
+Foo() | view
+Foo() | vmap
+Foo() | vmapclear
+Foo() | vmenu
+Foo() | vnew
+Foo() | vnoremap
+Foo() | vnoremenu
+Foo() | vsplit
+Foo() | vunmap
+Foo() | vunmenu
+Foo() | windo
+Foo() | write
+Foo() | wNext
+Foo() | wall
+Foo() | while
+Foo() | winsize
+Foo() | wincmd
+Foo() | winpos
+Foo() | wnext
+Foo() | wprevious
+Foo() | wq
+Foo() | wqall
+Foo() | wundo
+Foo() | wmnvinfo
+Foo() | xall
+Foo() | xmapclear
+Foo() | xmap
+Foo() | xmenu
+Foo() | xrestore
+Foo() | xnoremap
+Foo() | xnoremenu
+Foo() | xunmap
+Foo() | xunmenu
+Foo() | yank
+Foo() | z
+
+
+# Legacy-script only
+
+:Print
+:append
+ text
+.
+:change
+ text
+.
+:insert
+ text
+.
+:k
+:let
+:mode
+:open
+:t
+:unlet
+:xit
+
+Foo() | append
+ text
+.
+Foo() | change
+ text
+.
+Foo() | insert
+ text
+.
+Foo() | k
+Foo() | let
+Foo() | mode
+Foo() | open
+Foo() | t
+Foo() | unlet
+Foo() | xit
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_echo.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_echo.mnv
new file mode 100644
index 0000000000..c08b43322f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_echo.mnv
@@ -0,0 +1,36 @@
+mnv9script
+# MNV9 :echo commands
+# MNV_TEST_SETUP hi link mnvVar Identifier
+
+
+echo # comment
+echo "Foo" # comment
+echo foo[0] # comment
+echo Foo() # comment
+echo "Foo" | # comment
+
+def Foo()
+ echo # comment
+ echo "Foo" # comment
+ echo foo[0] # comment
+ echo Foo() # comment
+ echo "Foo" | # comment
+enddef
+
+
+echo "4"
+ # comment
+ .. "2" # comment
+
+echo "4" ..
+ # comment
+ "2" # comment
+
+echo "4" # comment
+ # comment
+ .. "2" # comment
+
+echo "4" .. # comment
+ # comment
+ "2" # comment
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_enum.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_enum.mnv
new file mode 100644
index 0000000000..4f6eec4da6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_enum.mnv
@@ -0,0 +1,111 @@
+mnv9script
+# MNV :enum command
+# MNV_TEST_SETUP hi link mnv9EnumValue Todo
+
+
+interface Interface1
+ def Def1()
+endinterface
+interface Interface2
+endinterface
+
+# enum-implements clause with interspersed comments
+
+enum Enum1 implements Interface1, Interface2
+ Value1
+ def Def1()
+ enddef
+endenum
+
+enum Enum2
+ \ implements Interface1, Interface2
+ Value1
+ def Def1()
+ enddef
+endenum
+
+enum Enum3 # comment
+ \ implements Interface1, Interface2
+ Value1
+endenum
+
+enum Enum4
+ # comment
+ \ implements Interface1, Interface2
+ Value1
+endenum
+
+enum Enum5
+ \ implements Interface1, Interface2 # comment
+ Value1
+ def Def1()
+ enddef
+endenum
+
+enum Enum6
+ #\ comment
+ \ implements Interface1, Interface2
+ Value1
+ def Def1()
+ enddef
+endenum
+
+# [enum Enum7.Value1 {name: 'Value1', ordinal: 0, val1: 0, val2: 0}, enum Enum7.Value2 {name: 'Value2', ordinal: 1, val1: 1, val2: 0}, enum Enum7.Value3 {name: 'Value3', ordinal: 2, val1: 2, val2: 0}]
+# comment
+enum Enum7
+ \
+ #\ comment
+ \
+ #\ comment
+ \ implements Interface1, Interface2 # comment
+ # comment
+ # comment
+ Value1, # comment
+ # comment
+ # comment
+ Value2(1 + 0), # comment
+ # comment
+ # comment
+ Value3( # comment
+ # comment
+ 1 # comment
+ # comment
+ + # comment
+ # comment
+ 1 # comment
+ ) # comment
+ # comment
+ var val1: number # comment
+ # comment
+ def Def1()
+ enddef
+ # comment
+ static def Def2() # comment
+ # comment
+ enddef # comment
+ # comment
+ public var val2: number # comment
+endenum
+
+# [enum Enum8.implements {name: 'implements', ordinal: 0}]
+enum Enum8 implements Interface1, Interface2
+ implements
+ def Def1()
+ enddef
+endenum
+
+# [enum Enum9.Value1 {name: 'Value1', ordinal: 0, implements: 0}]
+enum Enum9 implements Interface1, Interface2
+ Value1
+ var implements: number
+ def Def1()
+ enddef
+endenum
+
+# [enum Enum10.implements {name: 'implements', ordinal: 0}]
+enum Enum10 implements Interface1, Interface2
+ implements
+ def Def1()
+ enddef
+endenum
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_enum2.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_enum2.mnv
new file mode 100644
index 0000000000..84d1096857
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_enum2.mnv
@@ -0,0 +1,31 @@
+mnv9script
+# MNV9 :enum command
+# MNV_TEST_SETUP hi link mnv9EnumValue Todo
+# See: https://github.com/Project-Tick/Project-Tick/pull/16365#issuecomment-2571420551
+
+
+enum Letter
+ #
+ #########################################
+ A("(\" # not a comment NOR_ANOTHER_VALUE,
+ \ "), B(")\""), C($"'')
+ \('"), D($'""(),"'), E,
+ F(
+ ")" .. # FA,
+ "(" # FB,
+ ), G
+ #enum NotSupported
+ #endenum
+
+ def new(this.value = v:none)
+ return
+ enddef
+ const value: string
+endenum
+
+for letter in Letter.values
+ echo letter
+endfor
+
+echo Letter.D
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_enum_fold.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_enum_fold.mnv
new file mode 100644
index 0000000000..e05220622c
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_enum_fold.mnv
@@ -0,0 +1,50 @@
+mnv9script
+# MNV9 :enum command
+# MNV_TEST_SETUP let g:mnvsyn_folding = 'efi'
+# MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+# MNV_TEST_SETUP hi link mnv9EnumValue Todo
+
+
+interface Interface1
+endinterface
+interface Interface2
+endinterface
+
+enum Enum1
+endenum
+
+export enum Enum2
+endenum
+
+enum Enum3
+ Value1,
+ Value2,
+ Value3
+endenum
+
+enum Enum4
+ Value1,
+ Value2,
+ Value3
+ def Method1()
+ enddef
+endenum
+
+enum Enum5 implements Interface1, Interface2
+ Value1,
+ Value2,
+ Value3
+ def Method1()
+ def Nested()
+ enddef
+ enddef
+endenum
+
+enum Enum6
+ #\ comment
+ \ implements Interface1, Interface2
+ Value1,
+ Value2,
+ Value3
+endenum
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_for.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_for.mnv
new file mode 100644
index 0000000000..95efb2f0f1
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_for.mnv
@@ -0,0 +1,88 @@
+mnv9script
+# MNV9 :for command
+
+
+# :for {var} in {object}
+
+var expr = [42]
+
+for foo in expr
+ echo foo
+endfor
+
+for foo in expr # comment
+ echo foo
+endfor
+
+for foo in
+ # comment
+ expr
+ echo foo
+endfor
+
+for foo in expr | echo foo | endfor
+
+for foo in [42]
+ echo foo
+endfor
+
+for foo in [42] | echo foo | endfor
+
+for foo: number in [42] | echo foo | endfor
+
+echo "foo" | for foo in expr
+ echo foo
+endfor
+
+
+# :for [{var1}, {var2}, ...] in {listlist}
+
+var expr2 = [[42, 83]]
+
+for [foo, bar] in expr2
+ echo foo bar
+endfor
+
+for [foo, bar] in expr2 # comment
+ echo foo bar
+endfor
+
+for [foo, bar] in
+ # comment
+ expr2
+ echo foo bar
+endfor
+
+for [foo, bar] in expr2 | echo foo bar | endfor
+
+for [foo, bar] in [[42, 83]]
+ echo foo bar
+endfor
+
+for [foo, bar] in [[42, 83]] | echo foo bar | endfor
+
+for [foo: number, bar: number] in expr2
+ echo foo bar
+endfor
+
+
+# Issue #7961 (Builtin types are not highlighted in item-variable declarations
+# of :for commands)
+
+var m: number
+var n: number
+for x: number in range(2) | m = x | endfor
+###### ^^^^^^
+echo m
+for [x: number, y: number] in [[0, 0], [1, 1]] | [m, n] = [x, y] | endfor
+echo m n
+
+var F: func
+for t: tuple<func> in ((function('tolower'),),) | F = t[0] | endfor
+###### ^^^^^^^^^^^
+echo F('HELLO')
+for [L: func, U: func] in [[function('tolower'), function('toupper')]]
+ [_, F] = [L, U]
+endfor
+echo F('hello') F('world')
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_function_def_tail_comment_errors.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_function_def_tail_comment_errors.mnv
new file mode 100644
index 0000000000..2db5cdee53
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_function_def_tail_comment_errors.mnv
@@ -0,0 +1,45 @@
+mnv9script
+# MNV9 :function and :def tail comment errors
+# MNV_TEST_SETUP unlet! g:mnvsyn_folding
+
+
+fun Test1() abort # fun
+ return 1
+endfun # endfun
+
+def Test2(): number " def
+ return 2
+enddef " enddef
+
+fun Test3() abort # fun
+ fun s:DoTest3() abort # fun
+ return 3
+ endfun # endfun
+ return s:DoTest3()
+endfun # endfun
+
+def Test4(): number " def
+ def DoTest4(): number " def
+ return 4
+ enddef " enddef
+ return DoTest4()
+enddef " enddef
+
+def Test5(): number " def
+ fun DoTest5() abort # fun
+ return 5
+ endfun # endfun
+ return DoTest5()
+enddef " enddef
+
+fun Test6() abort # fun
+ def s:DoTest6(): number " def
+ return 6
+ enddef " enddef
+ return s:DoTest6()
+endfun # endfun
+
+for d in range(1, 6)
+ exec $'echo Test{d}()'
+endfor
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_function_def_tail_comments.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_function_def_tail_comments.mnv
new file mode 100644
index 0000000000..cac7aeefde
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_function_def_tail_comments.mnv
@@ -0,0 +1,45 @@
+mnv9script
+# MNV9 :function and :def tail comments
+# MNV_TEST_SETUP unlet! g:mnvsyn_folding
+
+
+fun Test1() abort " fun
+ return 1
+endfun " endfun
+
+def Test2(): number # def
+ return 2
+enddef # enddef
+
+fun Test3() abort " fun
+ fun s:DoTest3() abort " fun
+ return 3
+ endfun " endfun
+ return s:DoTest3()
+endfun " endfun
+
+def Test4(): number # def
+ def DoTest4(): number # def
+ return 4
+ enddef # enddef
+ return DoTest4()
+enddef # enddef
+
+def Test5(): number # def
+ fun DoTest5() abort " fun
+ return 5
+ endfun " endfun
+ return DoTest5()
+enddef # enddef
+
+fun Test6() abort " fun
+ def s:DoTest6(): number # def
+ return 6
+ enddef # enddef
+ return s:DoTest6()
+endfun " endfun
+
+for d in range(1, 6)
+ exec $'echo Test{d}()'
+endfor
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_import.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_import.mnv
new file mode 100644
index 0000000000..9b6be57ce2
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_import.mnv
@@ -0,0 +1,120 @@
+mnv9script
+# MNV9 :import command
+# MNV_TEST_SETUP hi link mnvImportName Todo
+
+
+import "foo.mnv"
+import true ? "foo.mnv" : "bar.mnv"
+
+import true ?
+ "foo.mnv" :
+ "bar.mnv"
+
+import true
+ ? "foo.mnv"
+ : "bar.mnv"
+
+import true ? # comment
+ # comment
+ "foo.mnv" :
+ # comment
+ "bar.mnv"
+
+import true # comment
+ # comment
+ ? "foo.mnv"
+ # comment
+ : "bar.mnv"
+
+import "foo.mnv" as bar
+import true ? "foo.mnv" : "bar.mnv" as baz
+
+import true ?
+ "foo.mnv" :
+ "bar.mnv"
+ as baz
+
+import true
+ ? "foo.mnv"
+ : "bar.mnv"
+ as baz
+
+import true ? # comment
+ # comment
+ "foo.mnv" :
+ # comment
+ "bar.mnv"
+ # comment
+ as baz
+
+import true # comment
+ # comment
+ ? "foo.mnv"
+ # comment
+ : "bar.mnv"
+ # comment
+ as baz
+
+echo "Foo" | import "foo.mnv"
+
+
+# autoload
+
+import autoload "foo.mnv"
+import autoload true ? "foo.mnv" : "bar.mnv"
+
+import autoload true ?
+ "foo.mnv" :
+ "bar.mnv"
+
+import autoload true
+ ? "foo.mnv"
+ : "bar.mnv"
+
+import autoload true ? # comment
+ # comment
+ "foo.mnv" :
+ # comment
+ "bar.mnv"
+
+import autoload true # comment
+ # comment
+ ? "foo.mnv"
+ # comment
+ : "bar.mnv"
+
+import autoload "foo.mnv" as bar
+import autoload true ? "foo.mnv" : "bar.mnv" as baz
+
+import autoload true ?
+ "foo.mnv" :
+ "bar.mnv"
+ as baz
+
+import autoload true
+ ? "foo.mnv"
+ : "bar.mnv"
+ as baz
+
+import autoload true ? # comment
+ # comment
+ "foo.mnv" :
+ # comment
+ "bar.mnv"
+ # comment
+ as baz
+
+import autoload true # comment
+ # comment
+ ? "foo.mnv"
+ # comment
+ : "bar.mnv"
+ # comment
+ as baz
+
+
+# "as" keyword in expr
+
+var as = "modules/"
+import true ? as .. "foo.mnv" : as .. "bar.mnv" as other
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_interface_fold.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_interface_fold.mnv
new file mode 100644
index 0000000000..a64302c682
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_interface_fold.mnv
@@ -0,0 +1,38 @@
+mnv9script
+# MNV9 :interface command
+# MNV_TEST_SETUP let g:mnvsyn_folding = 'i'
+# MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+
+
+interface Interface1
+endinterface
+
+export interface Interface2
+endinterface
+
+interface Interface2
+ # comment
+ var var1: number
+endinterface
+
+interface Interface3
+ # comment
+ def Meth1(): number
+endinterface
+
+interface Interface4
+ # comment
+ var var1: number
+ # comment
+ def Meth1(): number
+endinterface
+
+interface Interface5
+ # comment
+ var var1: number
+ var var2: number
+ # comment
+ def Meth1(): number
+ def Meth2(): number
+endinterface
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_let_heredoc.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_let_heredoc.mnv
new file mode 100644
index 0000000000..9697d91de2
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_let_heredoc.mnv
@@ -0,0 +1,299 @@
+mnv9script
+# MNV9 heredoc
+# MNV_TEST_SETUP let g:mnvsyn_folding = "h"
+# MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+
+
+var foo =<< END
+line1
+line2
+END
+
+ var foo =<< END
+line1
+line2
+END
+
+var [foo, bar] =<< EOS
+line1
+line2
+EOS
+
+ var [foo, bar] =<< EOS
+line1
+line2
+EOS
+
+var [foo,
+ \ bar] =<< EOS
+line1
+line2
+EOS
+
+ var [foo,
+ \ bar] =<< EOS
+line1
+line2
+EOS
+
+# assignment
+
+foo =<< END
+line1
+line2
+END
+
+ foo =<< END
+line1
+line2
+END
+
+g:foo =<< END
+line1
+line2
+END
+
+ g:foo =<< END
+line1
+line2
+END
+
+[foo, bar] =<< EOS
+line1
+line2
+EOS
+
+ [foo, bar] =<< EOS
+line1
+line2
+EOS
+
+[foo,
+ \ bar] =<< EOS
+line1
+line2
+EOS
+
+ [foo,
+ \ bar] =<< EOS
+line1
+line2
+EOS
+
+[g:foo, g:bar] =<< EOS
+line1
+line2
+EOS
+
+ [g:foo, g:bar] =<< EOS
+line1
+line2
+EOS
+
+[g:foo,
+ \ g:bar] =<< EOS
+line1
+line2
+EOS
+
+ [g:foo,
+ \ g:bar] =<< EOS
+line1
+line2
+EOS
+
+
+# typed
+
+var foo: list<string> =<< END
+line1
+line2
+END
+
+var [foo: string, bar: string] =<< END
+line1
+line2
+END
+
+# assignment
+
+# trim
+
+var foo =<< trim END
+ line1
+ line2
+END
+
+ var foo =<< trim END
+ line1
+ line2
+ END
+
+
+# interpolation
+
+var foo =<< eval END
+line{1 + 0}
+line{1 + 1}
+END
+
+ var foo =<< eval END
+line{1 + 0}
+line{1 + 1}
+END
+
+var foo =<< trim eval END
+ line{1 + 0}
+ line{1 + 1}
+END
+
+ var foo =<< trim eval END
+ line{1 + 0}
+ line{1 + 1}
+ END
+
+# no interpolation (escaped { and })
+
+var foo =<< eval END
+line{{1 + 0}}
+line{{1 + 1}}
+END
+
+ var foo =<< eval END
+line{{1 + 0}}
+line{{1 + 1}}
+END
+
+var foo =<< trim eval END
+ line{{1 + 0}}
+ line{{1 + 1}}
+END
+
+ var foo =<< trim eval END
+ line{{1 + 0}}
+ line{{1 + 1}}
+ END
+
+
+# no interpolation
+
+var foo =<< END
+line{1 + 0}
+line{1 + 1}
+END
+
+ var foo =<< END
+line{1 + 0}
+line{1 + 1}
+END
+
+var foo =<< trim END
+ line{1 + 0}
+ line{1 + 1}
+END
+
+ var foo =<< trim END
+ line{1 + 0}
+ line{1 + 1}
+ END
+
+
+# end marker must not be followed by whitespace
+
+# assert_equal(foo, ["END "])
+var foo =<< END
+END
+END
+
+# assert_equal(foo, [" END "])
+var foo =<< END
+ END
+END
+
+# assert_equal(foo, ["END "])
+var foo =<< trim END
+ END
+END
+
+# assert_equal(foo, ["END "])
+ var foo =<< trim END
+ END
+ END
+
+
+# end marker must be vertically aligned with :var (if preceded by whitespace)
+
+# assert_equal(foo, ["END"])
+var foo =<< trim END
+ END
+END
+
+ # assert_equal(foo, ["END"])
+ var foo =<< trim END
+ END
+ END
+
+# assert_equal(foo, ["END "])
+var foo =<< trim END
+END
+END
+
+ # assert_equal(foo, ["END"])
+ var foo =<< trim END
+ END
+ END
+
+ # assert_equal(foo, ["END "])
+ var foo =<< trim END
+ END
+ END
+
+ # assert_equal(foo, ["END"])
+ var foo =<< trim END
+ END
+ END
+
+ # assert_equal(foo, ["END "])
+ var foo =<< trim END
+ END
+ END
+
+ # assert_equal(foo, ["END "])
+ var foo =<< trim END
+END
+END
+
+ # assert_equal(foo, ["END"])
+ var foo =<< trim END
+ END
+END
+
+ # assert_equal(foo, ["END"])
+ var foo =<< trim END
+ END
+END
+
+
+# end markers
+
+var foo =<< !@#$%^&*()_+
+line1
+line2
+!@#$%^&*()_+
+
+var foo =<< 0!@#$%^&*()_+
+line1
+line2
+0!@#$%^&*()_+
+
+var foo =<< A!@#$%^&*()_+
+line1
+line2
+A!@#$%^&*()_+
+
+# error - leading lowercase character
+var foo =<< a!@#$%^&*()_+
+line1
+line2
+a!@#$%^&*()_+
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_loadkeymap.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_loadkeymap.mnv
new file mode 100644
index 0000000000..5fd5bc36b3
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_loadkeymap.mnv
@@ -0,0 +1,28 @@
+mnv9script
+# MNV9 :loadkeymap command
+
+
+scriptencoding utf-8
+
+b:keymap_name = "syntax-test"
+
+loadkeymap
+
+# Line comment
+
+ # Another line comment
+
+a A Basic mapping
+'a á More than one char in first column
+
+# Special notation
+<char-62> B Special notation allowed in LHS - decimal
+c <char-0103> Special notation allowed in RHS - octal
+<char-0x0064> <char-0x0044> Special notation allowed in LHS and RHS - hexadecimal
+
+# MNV-script comment characters
+\# <char-0x00a3> Line should not match as a MNV9-script comment
+# Line should not match as a legacy-script comment
+" “
+: # Line should not match as a MNV9-script comment
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_ex_type.mnv b/mnv/runtime/syntax/testdir/input/mnv9_ex_type.mnv
new file mode 100644
index 0000000000..af82f9912c
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_ex_type.mnv
@@ -0,0 +1,12 @@
+mnv9script
+# MNV9 :type command
+
+
+type Foo = string
+type Bar = list<string>
+type Baz = Foo
+
+export type Qux = Baz
+
+type foo = string
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_expressions.mnv b/mnv/runtime/syntax/testdir/input/mnv9_expressions.mnv
new file mode 100644
index 0000000000..5fd25b024a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_expressions.mnv
@@ -0,0 +1,215 @@
+mnv9script
+# MNV9 expressions
+
+
+# Boolean
+
+echo true false
+
+# Number
+
+# ' separated
+
+echo 1'000'000
+echo 1'000'000.00
+echo -1'000'000
+echo -1'000'000.00
+
+echo 0b1000'0000
+echo 0o1000'0000
+echo 0x1000'0000
+echo -0b1000'0000
+echo -0o1000'0000
+echo -0x1000'0000
+
+# Null
+
+echo null null_blob null_channel null_class null_dict null_function null_job
+echo null_list null_object null_partial null_string null_tuple
+
+# Dictionary
+
+echo {}
+echo { foo: 21 * 2 }
+echo { -foo-: 21 * 2 }
+echo { 42: 21 * 2 }
+echo { 'foo': 21 * 2 }
+echo { "foo": 21 * 2 }
+
+echo { foo: { bar: 21 * 2 } }
+echo { foo: { -bar-: 21 * 2 } }
+echo { foo: { 42: 21 * 2 } }
+echo { foo: { 'bar': 21 * 2 } }
+echo { foo: { "bar": 21 * 2 } }
+
+echo { -foo-: { bar: 21 * 2 } }
+echo { -foo-: { -bar-: 21 * 2 } }
+echo { -foo-: { 42: 21 * 2 } }
+echo { -foo-: { 'bar': 21 * 2 } }
+echo { -foo-: { "bar": 21 * 2 } }
+
+echo { 42: { bar: 21 * 2 } }
+echo { 42: { -bar-: 21 * 2 } }
+echo { 42: { 42: 21 * 2 } }
+echo { 42: { 'bar': 21 * 2 } }
+echo { 42: { "bar": 21 * 2 } }
+
+echo { 'foo': { bar: 21 * 2 } }
+echo { 'foo': { -bar-: 21 * 2 } }
+echo { 'foo': { 42: 21 * 2 } }
+echo { 'foo': { "bar": 21 * 2 } }
+echo { 'foo': { 'bar': 21 * 2 } }
+
+echo { "foo": { bar: 21 * 2 } }
+echo { "foo": { -bar-: 21 * 2 } }
+echo { "foo": { 42: 21 * 2 } }
+echo { "foo": { 'bar': 21 * 2 } }
+echo { "foo": { "bar": 21 * 2 } }
+
+echo {
+ # comment
+ foo: {
+ bar: 21 * 2
+ }
+}
+
+# match as keys not scope dictionaries
+echo { b: 42, w: 42, t: 42, g: 42, l: 42, s: 42, a: 42, v: 42 }
+
+# Register
+
+echo @" @@
+echo @0 @1 @2 @3 @4 @5 @6 @7 @8 @9
+echo @a @b @c @d @e @f @g @h @i @j @k @l @m @n @o @p @q @r @s @t @u @v @w @x @y @z
+echo @A @B @C @D @E @F @G @H @I @J @K @L @M @N @O @P @Q @R @S @T @U @V @W @X @Y @Z
+echo @- @: @. @% @# @= @* @+ @~ @_ @/
+
+# read-only @:, @., @%, @~
+@" = "foo"
+@0 = "foo"
+@1 = "foo"
+@9 = "foo"
+@a = "foo"
+@k = "foo"
+@z = "foo"
+@A = "foo"
+@K = "foo"
+@Z = "foo"
+@- = "foo"
+@# = "foo"
+@= = "foo"
+@* = "foo"
+@+ = "foo"
+@_ = "foo"
+@/ = "foo"
+
+# Operators
+
+# Ternary
+
+echo expr ? expr : expr
+
+echo lnum == 1 ? "top" : lnum
+echo lnum == 1 ? "top" : lnum == 1000 ? "last" : lnum
+
+echo lnum == 1
+ ? "top"
+ : lnum == 1000
+ ? "last"
+ : lnum
+echo lnum == 1 ?
+ "top" :
+ lnum == 1000 ?
+ "last" :
+ lnum
+
+echo true ? true : false
+echo 1 ? 1 : 0
+echo "foo" ? "foo" : "bar"
+echo foo ? foo : bar
+echo g:foo ? g:foo : g:bar
+echo $FOO ? $FOO : $BAR
+echo True() ? True() : False()
+echo @a ? @a : @b
+echo (true) ? (true) : (false)
+echo (1) ? (1) : (0)
+
+# Falsy
+
+echo expr ?? expr
+
+echo theList ?? 'list is empty'
+echo GetName() ?? 'unknown'
+
+echo theList
+ \ ?? 'list is empty'
+echo theList ??
+ \ 'list is empty'
+
+echo true ?? true
+echo 1 ?? 1
+echo "foo" ?? "foo"
+echo foo ?? foo
+echo g:foo ?? g:foo
+echo $FOO ?? $FOO
+echo True() ?? True()
+echo @a ?? @a
+echo (true) ?? (true)
+echo (1) ?? (1)
+
+
+# Function calls
+
+Foo(true, false, null)
+
+
+# Command {expr} arguments
+
+if true
+ echo true
+elseif false
+ echo false
+endif
+
+while true
+ break
+endwhile
+
+def Foo(): bool
+ return true
+enddef
+
+
+# Issue #14423 (mnv.mnv: Opt out of mnvSearch*)
+
+:?truthy
+const truthy: number = false
+ ? (0
+ )
+ : (1
+ )
+echo truthy
+
+def Foo()
+ :?truthy
+ const truthy: number = false
+ ? (0
+ )
+ : (1
+ )
+ echo truthy
+enddef
+
+
+# Issue #16227 (MNV script ternary expression highlighting)
+
+var foo = 'foo' # comment
+var bar = foo == 'foo' ? 'bar' : 'baz'
+var baz = foo == 'foo'
+ \ ? 'baz'
+ \ : 'bar'
+var qux = foo == 'foo'
+ ? 'qux' # comment
+ : 'qux' # comment
+echo qux ?? 'quux'
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_function_calls.mnv b/mnv/runtime/syntax/testdir/input/mnv9_function_calls.mnv
new file mode 100644
index 0000000000..65369c66c9
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_function_calls.mnv
@@ -0,0 +1,317 @@
+mnv9script
+# MNV9 function calls
+# MNV_TEST_SETUP hi link mnvUserFunc Todo
+# MNV_TEST_SETUP hi link mnv9UserFunc Todo
+
+
+call abs(42)
+abs(42)
+
+
+# Command/function distinction
+
+# append browse call chdir confirm copy delete eval execute filter function
+# insert join map match mode sort split substitute swapname type
+
+var append = append(42)
+call append(42)
+# function
+append(42)
+# Legacy command
+# append (42)
+
+var browse = browse(42)
+call browse(42)
+# function
+browse(42)
+# command
+browse (42)
+
+var call = call(42)
+call call(42)
+# function
+call(42)
+# command
+call (42)
+
+var chdir = chdir(42)
+call chdir(42)
+# function
+chdir(42)
+# command
+chdir (42)
+
+var confirm = confirm(42)
+call confirm(42)
+# function
+confirm(42)
+# command
+confirm (42)
+
+var copy = copy(42)
+call copy(42)
+# function
+copy(42)
+# command
+copy (42)
+
+var delete = delete(42)
+call delete(42)
+# function
+delete(42)
+# command
+delete (42)
+
+var eval = eval(42)
+call eval(42)
+# function
+eval(42)
+# command
+eval (42)
+
+var execute = execute(42)
+call execute(42)
+# function
+execute(42)
+# command
+execute (42)
+
+var filter = filter(42)
+call filter(42)
+# function
+filter(42)
+# command
+filter (42)
+
+var function = function(42)
+call function(42)
+# function
+function(42)
+# command
+function (42)
+
+var insert = insert(42)
+call insert(42)
+# function
+insert(42)
+# Legacy command
+# insert (42)
+
+var join = join(42)
+call join(42)
+# function
+join(42)
+# command
+join (42)
+
+var map = map(42)
+call map(42)
+# function
+map(42)
+# command
+map (42)
+
+var match = match(42)
+call match(42)
+# function
+match(42)
+# command
+match (42)
+
+var sort = sort(42)
+call sort(42)
+# function
+sort(42)
+# command
+sort (42)
+
+var split = split(42)
+call split(42)
+# function
+split(42)
+# command
+split (42)
+
+var substitute = substitute(42)
+call substitute(42)
+# function
+substitute(42)
+# command
+substitute (42)
+
+var swapname = swapname(42)
+call swapname(42)
+# function
+swapname(42)
+# command
+swapname (42)
+
+var type = type(42)
+call type(42)
+# function
+type(42)
+# command
+type (42)
+
+var uniq = uniq(42)
+call uniq(42)
+# function
+uniq(42)
+# command
+uniq (42)
+
+
+# Errors
+
+var foo = foo(42)
+call foo(42)
+foo(42)
+
+var if = if(42)
+call if(42)
+# function
+if(42) | .. | endif
+# command
+if (42) | .. | endif
+
+var echo = echo(42)
+call echo(42)
+# function
+echo(42)
+# command
+echo (42)
+
+
+# Expressions
+
+var foo = abs(42)
+
+abs(42)
+call abs(42)
+echo "Foo" | abs(42)
+
+echo abs(42)
+echo (abs(42))
+echo abs(42) + foo
+echo foo + abs(42)
+
+Foo()
+call Foo()
+echo "Foo" | Foo()
+
+echo Foo()
+echo (Foo())
+echo Foo() + bar
+echo bar + Foo()
+
+
+# Scope modifiers and qualified names
+
+var foo = g:foo(42)
+call g:foo(42)
+
+var foo = b:foo(42)
+call b:foo(42)
+
+var foo = w:foo(42)
+call w:foo(42)
+
+var foo = t:foo(42)
+call t:foo(42)
+
+var foo = v:foo(42)
+call v:foo(42)
+
+
+var foo = module.foo(42)
+call module.foo(42)
+module.foo(42)
+
+var foo = g:module.foo(42)
+call g:module.foo(42)
+g:module.foo(42)
+
+var foo = b:module.foo(42)
+call b:module.foo(42)
+b:module.foo(42)
+
+var foo = w:module.foo(42)
+call w:module.foo(42)
+w:module.foo(42)
+
+var foo = t:module.foo(42)
+call t:module.foo(42)
+t:module.foo(42)
+
+var foo = v:module.foo(42)
+call v:module.foo(42)
+v:module.foo(42)
+
+
+var foo = module#foo(42)
+call module#foo(42)
+module#foo(42)
+
+var foo = g:module#foo(42)
+call g:module#foo(42)
+g:module#foo(42)
+
+
+# User, not builtin, functions
+
+call g:substitute()
+call b:substitute()
+call w:substitute()
+call t:substitute()
+call v:substitute()
+
+call <SID>substitute()
+
+call g:substitute.substitute()
+call b:substitute.substitute()
+call w:substitute.substitute()
+call t:substitute.substitute()
+call v:substitute.substitute()
+
+call substitute#substitute()
+call g:substitute#substitute()
+
+g:substitute()
+b:substitute()
+w:substitute()
+t:substitute()
+v:substitute()
+
+<SID>substitute()
+
+g:substitute.substitute()
+b:substitute.substitute()
+w:substitute.substitute()
+t:substitute.substitute()
+v:substitute.substitute()
+
+substitute#substitute()
+g:substitute#substitute()
+
+
+# Chained function calls
+
+module.foo().bar()
+module.foo().substitute()
+
+
+# Issue 16721 (MNV script highlight of builtin function after |)
+
+&directory = $'{$MYMNVDIR}/.data/swap/'
+&backupdir = $'{$MYMNVDIR}/.data/backup//'
+&undodir = $'{$MYMNVDIR}/.data/undo//'
+if !isdirectory(&undodir) | mkdir(&undodir, "p") | endif
+if !isdirectory(&backupdir) | mkdir(&backupdir, "p") | endif
+if !isdirectory(&directory) | mkdir(&directory, "p") | endif
+
+
+# Issue #17766 (valid function call highlighted as error)
+
+module[0].foo()
+module[0].substitute()
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_enum.mnv b/mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_enum.mnv
new file mode 100644
index 0000000000..00621dea4d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_enum.mnv
@@ -0,0 +1,36 @@
+mnv9script
+# MNV_TEST_SETUP highlight link mnv9DefTypeParam Todo
+# MNV_TEST_SETUP highlight link mnv9EnumValue Identifier
+# MNV_TEST_SETUP let g:mnvsyn_folding = "ef"
+# MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+# See: https://github.com/Project-Tick/Project-Tick/pull/17313#issuecomment-3033537127 (Aliaksei Budavei)
+
+
+enum CommonPair
+ HelloWorld<string, string>('hello', 'world'),
+ Booleans<bool, bool>(true, false)
+
+ const _fst: any
+ const _snd: any
+
+ def new<T, U>(fst: T, snd: U)
+ this._fst = fst
+ this._snd = snd
+ enddef
+
+ def First<T>(): T
+ return this._fst
+ enddef
+
+ def Second<T>(): T
+ return this._snd
+ enddef
+
+ def string(): string
+ return printf("(%s, %s)", this._fst, this._snd)
+ enddef
+endenum
+
+echo CommonPair.HelloWorld
+echo CommonPair.Booleans
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_list.mnv b/mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_list.mnv
new file mode 100644
index 0000000000..8fb745ad1a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_list.mnv
@@ -0,0 +1,215 @@
+mnv9script
+# MNV_TEST_SETUP let g:mnvsyn_folding = "cfi"
+# MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+# MNV_TEST_SETUP hi link mnv9DefTypeParam Todo
+# See: https://github.com/Project-Tick/Project-Tick/pull/17313#issuecomment-3046696820 (Aliaksei Budavei)
+
+
+# See https://github.com/Project-Tick/Project-Tick/pull/16604#issuecomment-265202845 .
+export interface Listable
+ def Cons<E>(_: E): Listable
+ def Reverse<E>(): Listable
+ def Rest(): Listable
+ def First<E>(): E
+ def empty(): bool
+ def len(): number
+ def string(): string
+endinterface
+
+enum EmptyList implements Listable
+ INSTANCE
+
+ def Cons<E>(value: E): Listable
+ return List.new<E>(value)
+ enddef
+
+ def Reverse<E>(): Listable
+ return this
+ enddef
+
+ def Rest(): Listable
+ return this
+ enddef
+
+ def First<E>(): E
+ return null
+ enddef
+
+ def empty(): bool
+ return true
+ enddef
+
+ def len(): number
+ return 0
+ enddef
+
+ def string(): string
+ return '[]'
+ enddef
+endenum
+
+class List implements Listable
+ const _value: any
+ const _size: number
+ var _next: Listable
+
+ def new<E>(value: E)
+ this._value = value
+ this._size = 1
+ this._next = EmptyList.INSTANCE
+ enddef
+
+ def _newCons<E>(value: E, size: number)
+ this._value = value
+ this._size = size
+ enddef
+
+ def Cons<E>(value: E): Listable
+ const list: List = List._newCons<E>(value, (this._size + 1))
+ list._next = this
+ return list
+ enddef
+
+ def Reverse<E>(): Listable
+ var result: Listable = List.new<E>(this.First<E>())
+ var list: Listable = this.Rest()
+
+ while !list.empty()
+ result = result.Cons<E>(list.First<E>())
+ list = list.Rest()
+ endwhile
+
+ return result
+ enddef
+
+ def Rest(): Listable
+ return this._next
+ enddef
+
+ def First<E>(): E
+ return this._value
+ enddef
+
+ def empty(): bool
+ return (this._size == 0)
+ enddef
+
+ def len(): number
+ return this._size
+ enddef
+
+ def string(): string
+ if this.empty()
+ return '[]'
+ endif
+
+ var text: string = '[' .. string(this.First<any>()) .. ', '
+ var list: Listable = this.Rest()
+
+ while !list.empty()
+ text ..= string(list.First<any>()) .. ', '
+ list = list.Rest()
+ endwhile
+
+ return strpart(text, 0, (strlen(text) - 2)) .. ']'
+ enddef
+endclass
+
+export def MakeEmptyList(): Listable
+ return EmptyList.INSTANCE
+enddef
+
+export def MakeList<E>(value: E): Listable
+ return List.new<E>(value)
+enddef
+
+export def Map<T, U>(listable: Listable, Mapper: func(T): U): Listable
+ var result: Listable = EmptyList.INSTANCE
+ var list: Listable = listable
+
+ while !list.empty()
+ result = result.Cons<U>(Mapper(list.First<T>()))
+ list = list.Rest()
+ endwhile
+
+ return result.Reverse<U>()
+enddef
+
+export def Filter<T>(listable: Listable, Predicate: func(T): bool): Listable
+ var result: Listable = EmptyList.INSTANCE
+ var list: Listable = listable
+
+ while !list.empty()
+ if Predicate(list.First<T>())
+ result = result.Cons<T>(list.First<T>())
+ endif
+
+ list = list.Rest()
+ endwhile
+
+ return result.Reverse<T>()
+enddef
+
+############################################################
+
+echo MakeEmptyList()
+
+const listX: Listable = MakeEmptyList()
+ .Cons<number>(0).Cons<number>(1).Cons<number>(2).Cons<number>(3)
+const listY: Listable = MakeList<number>(0)
+ .Cons<number>(1).Cons<number>(2).Cons<number>(3)
+echo listX == listY
+echo listX
+echo listX.Reverse<number>()
+echo MakeEmptyList().Reverse<any>()
+echo Filter<number>(listX, (value: number) => value % 2 != 0)
+echo Map<number, string>(listX, (value: number) => nr2char((value + 60), 1))
+
+echo 4 listX.len() listY.len()
+echo listX
+echo listY
+
+const list3X: Listable = listX.Rest()
+const list3Y: Listable = listY.Rest()
+echo 3 list3X.len() list3Y.len()
+echo list3X
+echo list3Y
+
+const list2X: Listable = list3X.Rest()
+const list2Y: Listable = list3Y.Rest()
+echo 2 list2X.len() list2Y.len()
+echo list2X
+echo list2Y
+
+const list1X: Listable = list2X.Rest()
+const list1Y: Listable = list2Y.Rest()
+echo 1 list1X.len() list1Y.len()
+echo list1X
+echo list1Y
+
+const list0X: Listable = list1X.Rest()
+const list0Y: Listable = list1Y.Rest()
+echo 0 list0X.len() list0Y.len()
+echo list0X
+echo list0Y
+
+const list0X_: Listable = list0X.Rest()
+const list0Y_: Listable = list0Y.Rest()
+echo 0 list0X_.len() list0Y_.len()
+echo list0X_
+echo list0Y_
+
+const list0X__: Listable = list0X_.Rest()
+const list0Y__: Listable = list0Y_.Rest()
+echo 0 list0X__.len() list0Y__.len()
+echo list0X__
+echo list0Y__
+
+
+const listZ: Listable = MakeList<Listable>(MakeList<number>(-1))
+const listZZ: Listable = listZ.Cons<Listable>(MakeList<number>(0))
+ .Cons<Listable>(MakeList<number>(1))
+ .Cons<Listable>(MakeList<number>(2))
+ .Cons<Listable>(MakeList<number>(3))
+echo listZZ
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_set.mnv b/mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_set.mnv
new file mode 100644
index 0000000000..71c8912cd4
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_generic_function_example_set.mnv
@@ -0,0 +1,177 @@
+mnv9script
+# MNV_TEST_SETUP let g:mnvsyn_folding = "cf"
+# MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+# MNV_TEST_SETUP hi link mnv9DefTypeParam Todo
+# See: https://github.com/Project-Tick/Project-Tick/pull/17313#issuecomment-3046696820 (Aliaksei Budavei)
+
+# See https://github.com/Project-Tick/Project-Tick/issues/14330#issuecomment-2028938515 .
+export class Set
+ final _elements: dict<number>
+ const _Mapper: func(number, string): any
+ const ToStringer: func(any): string
+ const FromStringer: func(string): any
+
+ static def _Mapper<E>(F: func(string): E): func(number, string): E
+ return ((G: func(string): E) => (_: number, v: string): E => G(v))(F)
+ enddef
+
+ def new<E>()
+ this._elements = {}
+ this._Mapper = _Mapper<E>((s: string): E => eval(s))
+ this.ToStringer = (a: E): string => string(a)
+ this.FromStringer = (s: string): E => eval(s)
+ enddef
+
+ def newFromList<E>(elements: list<E>, ToStringer: func(E): string,
+ FromStringer: func(string): E)
+ this._elements = elements
+ ->reduce(((F: func(E): string) => (d: dict<number>, v: E) =>
+ extend({[F(v)]: 1}, d))(ToStringer),
+ {})
+ this._Mapper = _Mapper<E>(FromStringer)
+ this.ToStringer = ToStringer
+ this.FromStringer = FromStringer
+ enddef
+
+ def _FromList<E>(elements: list<E>): Set
+ return Set.newFromList<E>(elements, this.ToStringer, this.FromStringer)
+ enddef
+
+ def Contains<E>(element: E): bool
+ return has_key(this._elements, this.ToStringer(element))
+ enddef
+
+ def Elements<E>(): list<E>
+ return keys(this._elements)->mapnew(this._Mapper)
+ enddef
+
+ def empty(): bool
+ return empty(this._elements)
+ enddef
+
+ def len(): number
+ return len(this._elements)
+ enddef
+
+ def string(): string
+ return string(keys(this._elements))
+ enddef
+
+ # {1, 2, 3} ⊇ {1, 2}.
+ def Superset(that: Set): bool
+ return (len(this._elements) >= len(that._elements)) && that._elements
+ ->keys()
+ ->indexof(((set: Set) => (_: number, v: string) => !set._elements
+ ->has_key(v))(this)) < 0
+ enddef
+
+ # {1, 2} ⊆ {1, 2, 3}.
+ def Subset(that: Set): bool
+ return (len(this._elements) <= len(that._elements)) && this._elements
+ ->keys()
+ ->indexof(((set: Set) => (_: number, v: string) => !set._elements
+ ->has_key(v))(that)) < 0
+ enddef
+
+ # {1, 2, 3} ∪ {2, 3, 4} = {1, 2, 3, 4}.
+ def Union(that: Set): Set
+ return this._FromList<any>({}
+ ->extend(that._elements)
+ ->extend(this._elements)
+ ->keys()
+ ->map(this._Mapper))
+ enddef
+
+ # {1, 2, 3} ∩ {2, 3, 4} = {2, 3}.
+ def Intersection(that: Set): Set
+ return this._FromList<any>(this._elements
+ ->keys()
+ ->filter(((set: Set) => (_: number, v: string) => set._elements
+ ->has_key(v))(that))
+ ->map(this._Mapper))
+ enddef
+
+ # {1, 2, 3} \ {2, 3, 4} = {1}.
+ # {2, 3, 4} \ {1, 2, 3} = {4}.
+ def SetDifference(that: Set): Set
+ return this._FromList<any>(this._elements
+ ->keys()
+ ->filter(((set: Set) => (_: number, v: string) => !set._elements
+ ->has_key(v))(that))
+ ->map(this._Mapper))
+ enddef
+
+ # {1, 2, 3} △ {2, 3, 4} = {1, 4}.
+ def SymmetricDifference(that: Set): Set
+ return this.Union(that).SetDifference(this.Intersection(that))
+ enddef
+endclass
+
+############################################################
+
+const ToStr: func(number): string = (s: number) => string(s)
+const FromStr: func(string): number = (s: string) => str2nr(s)
+
+echo Set.newFromList<number>([1, 2, 3], ToStr, FromStr)
+ .Subset(Set.newFromList<number>([1, 2], ToStr, FromStr))
+echo Set.newFromList<number>([1, 2], ToStr, FromStr)
+ .Subset(Set.newFromList<number>([1, 2, 3], ToStr, FromStr))
+echo Set.newFromList<number>([1, 2], ToStr, FromStr)
+ .Superset(Set.newFromList<number>([1, 2, 3], ToStr, FromStr))
+echo Set.newFromList<number>([1, 2, 3], ToStr, FromStr)
+ .Superset(Set.newFromList<number>([1, 2], ToStr, FromStr))
+
+echo Set.newFromList<number>([1, 2, 3], ToStr, FromStr)
+ .Union(Set.newFromList<number>([2, 3, 4], ToStr, FromStr))
+ .Elements<number>()
+echo Set.newFromList<number>([2, 3, 4], ToStr, FromStr)
+ .Union(Set.newFromList<number>([1, 2, 3], ToStr, FromStr))
+ .Elements<number>()
+
+echo Set.newFromList<number>([1, 2, 3], ToStr, FromStr)
+ .Intersection(Set.newFromList<number>([2, 3, 4], ToStr, FromStr))
+ .Elements<number>()
+echo Set.newFromList<number>([2, 3, 4], ToStr, FromStr)
+ .Intersection(Set.newFromList<number>([1, 2, 3], ToStr, FromStr))
+ .Elements<number>()
+
+echo Set.newFromList<number>([1, 2, 3], ToStr, FromStr)
+ .SetDifference(Set.newFromList<number>([2, 3, 4], ToStr, FromStr))
+ .Elements<number>()
+echo Set.newFromList<number>([2, 3, 4], ToStr, FromStr)
+ .SetDifference(Set.newFromList<number>([1, 2, 3], ToStr, FromStr))
+ .Elements<number>()
+
+echo Set.newFromList<number>([1, 2, 3], ToStr, FromStr)
+ .SymmetricDifference(Set.newFromList<number>([2, 3, 4], ToStr, FromStr))
+ .Elements<number>()
+echo Set.newFromList<number>([2, 3, 4], ToStr, FromStr)
+ .SymmetricDifference(Set.newFromList<number>([1, 2, 3], ToStr, FromStr))
+ .Elements<number>()
+
+############################################################
+
+const none: Set = Set.new<any>()
+echo none.len()
+echo none.empty()
+echo none.string()
+echo string(none.Elements<any>())
+
+const sets: Set = Set.newFromList<Set>(
+ [Set.new<any>(), Set.new<any>(), Set.new<any>(), Set.new<any>()],
+ (o: Set): string => string(o),
+ (_: string): Set => Set.new<any>())
+echo sets.len()
+echo sets.empty()
+echo sets.string()
+echo string(sets.Elements<Set>())
+
+const lists: Set = Set.newFromList<list<any>>(
+ [[[[[]]]]],
+ (o: list<any>): string => string(o),
+ (s: string): list<any> => eval(s))
+echo lists.len()
+echo lists.empty()
+echo lists.string()
+echo string(lists.Elements<list<any>>())
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_generic_functions.mnv b/mnv/runtime/syntax/testdir/input/mnv9_generic_functions.mnv
new file mode 100644
index 0000000000..fed2cced45
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_generic_functions.mnv
@@ -0,0 +1,97 @@
+mnv9script
+# MNV9 generic functions
+# MNV_TEST_SETUP let g:mnvsyn_folding = "cf"
+# MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+# MNV_TEST_SETUP hi link mnv9DefTypeParam Todo
+
+
+# :help generic-functions
+
+def MyFunc<T, A, B>(param1: T): T
+ var f: A
+ var x = param1
+ return x
+enddef
+
+MyFunc<number, string, list<number>>()
+
+
+def Flatten<T>(x: list<list<T>>): list<T>
+ var result: list<T> = []
+ for inner in x
+ result += inner
+ endfor
+ return result
+enddef
+
+echo Flatten<number>([[1, 2], [3]])
+
+
+class A
+ def Foo<X, Y>()
+ enddef
+endclass
+var a = A.new()
+a.Foo<number, string>()
+
+
+def MakeEcho<T>(): func(T): T
+ return (x: T): T => x
+enddef
+
+var EchoNumber = MakeEcho<number>()
+echo EchoNumber(123)
+
+var EchoString = MakeEcho<string>()
+echo EchoString('abc')
+
+# FIXME: add specific command handling
+# defcompile MyFunc<number, list<number>, dict<string>>
+
+# disassemble MyFunc<string, dict<string>>
+# disassemble MyFunc<number, list<blob>>
+
+
+# funcrefs
+
+var Foo = Bar<number>
+Execute(Bar<number>)
+
+var Foo = bar.Baz<string>
+Execute(bar.Baz<string>)
+
+class Foo
+ def _MethodA<T>(arg: T)
+ echo arg
+ enddef
+ def MethodB()
+ var F = this._MethodA<number>
+ F("text")
+ enddef
+endclass
+
+class Bar extends Foo
+ def MethodC()
+ var F = super._MethodA<number>
+ F("text")
+ enddef
+endclass
+
+
+# Issue: https://github.com/Project-Tick/Project-Tick/pull/17722#issuecomment-3075531052
+
+export def Id<U>(): func(U): U
+ return (X_: U) => X_
+enddef
+
+export def Const<U, V>(): func(U): func(V): U
+ return (X_: U) => (_: V) => X_
+enddef
+
+export def Flip<U, V, W>(): func(func(U): func(V): W): func(V): func(U): W
+ return (F_: func(U): func(V): W) => (Y_: V) => (X_: U) => F_(X_)(Y_)
+enddef
+
+echo Const<number, any>()(2)(null)
+ == Flip<number, any, number>()(Const<number, any>())(null)(2)
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_lambdas.mnv b/mnv/runtime/syntax/testdir/input/mnv9_lambdas.mnv
new file mode 100644
index 0000000000..667dcd2bac
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_lambdas.mnv
@@ -0,0 +1,161 @@
+mnv9script
+# MNV9 lambda expressions
+# MNV_TEST_SETUP hi link mnv9LambdaOperator Todo
+# MNV_TEST_SETUP hi link mnv9LambdaParen Todo
+
+
+var Foo: func
+var expr = 0
+
+# without return type
+
+Foo = () => expr
+Foo = (_) => expr
+Foo = (x) => expr
+
+Foo = (...y) => expr
+Foo = (_, ...y) => expr
+Foo = (x, ...y) => expr
+
+Foo = (x, y) => expr
+
+Foo = (_: number) => expr
+Foo = (x: number) => expr
+
+Foo = (...y: list<number>) => expr
+Foo = (_: number, ...y: list<number>) => expr
+Foo = (x: number, ...y: list<number>) => expr
+
+Foo = (x: number, y: number) => expr
+
+# with return type
+
+Foo = (): number => expr
+Foo = (_): number => expr
+Foo = (x): number => expr
+
+Foo = (...y): number => expr
+Foo = (_, ...y): number => expr
+Foo = (x, ...y): number => expr
+
+Foo = (x, y): number => expr
+
+Foo = (_: number): number => expr
+Foo = (x: number): number => expr
+
+Foo = (...y: list<number>): number => expr
+Foo = (_: number, ...y: list<number>): number => expr
+Foo = (x: number, ...y: list<number>): number => expr
+
+Foo = (x: number, y: number): number => expr
+
+# with compound return type
+
+Foo = (): list<number> => expr
+Foo = (_): list<number> => expr
+Foo = (x): list<number> => expr
+
+Foo = (...y): list<number> => expr
+Foo = (_, ...y): list<number> => expr
+Foo = (x, ...y): list<number> => expr
+
+Foo = (x, y): list<number> => expr
+
+Foo = (_: number): list<number> => expr
+Foo = (x: number): list<number> => expr
+
+Foo = (...y: list<number>): list<number> => expr
+Foo = (_: number, ...y: list<number>): list<number> => expr
+Foo = (x: number, ...y: list<number>): list<number> => expr
+
+Foo = (x: number, y: number): list<number> => expr
+
+
+# Post-operator comments
+
+Foo = () => # comment
+ expr
+Foo = () =>
+ # comment
+ expr
+Foo = () =>
+
+ # comment
+
+ expr
+
+
+# Line continuations
+
+Foo = (x: string,
+ \ y: number,
+ \ z: bool) => expr
+
+Foo = (x: string,
+ \ y: number,
+ \ z: bool)
+ \ => expr
+
+Foo = (x: string,
+ \ y: number,
+ \ z: bool): number => expr
+
+Foo = (x: string,
+ \ y: number,
+ \ z: bool): number
+ \ => expr
+
+Foo = (x: string,
+ \ y: number,
+ \ z: bool):
+ \ number => expr
+
+
+# Funcref call
+
+echo (() => 42)()
+echo ((x: string): number => 42)("foo")
+
+
+# :help mnv9-lambda
+
+var list = [1, 2, 3]
+echo filter(list, (k, v) =>
+ v > 0)
+echo filter(list, (k,
+ \ v)
+ \ => v > 0)
+
+var Callback = (..._) => 'anything'
+echo Callback(1, 2, 3) # displays "anything"
+
+var Lambda = (arg) => {
+ g:was_called = 'yes'
+ return expr
+ }
+
+var count = 0
+var timer = timer_start(500, (_) => {
+ count += 1
+ echom 'Handler called ' .. count
+ }, {repeat: 3})
+
+var dict = {}
+var d = mapnew(dict, (k, v): string => {
+ return 'value'
+ })
+
+
+# Issue #15970 (mnv9: Restore and extend the recognition of Enum body items)
+
+def Op(): func(func(number, number): number): func(number, Digit): number
+ return (F: func(number, number): number) =>
+ (x: number, y: Digit): number => F(x, y.value)
+enddef ####################### ^ mnvCommand?
+
+
+# Issue #16965 (mnv syntax: wrong highlight with lambda, autoload, and false keyword)
+
+autocmd BufRead * timer_start(0, (_) => f#a(false, false))
+autocmd
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_legacy_header.mnv b/mnv/runtime/syntax/testdir/input/mnv9_legacy_header.mnv
new file mode 100644
index 0000000000..d9afd0c86c
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_legacy_header.mnv
@@ -0,0 +1,20 @@
+" MNV9 legacy script header
+
+
+" comment
+
+if !has('mnv9script')
+ # 42 " comment
+ source foo.mnv
+ finish
+endif
+
+" comment
+
+mnv9script noclear
+
+# comment
+
+ # string only recognised with leading char
+ "useless string"
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_legacy_header_fold.mnv b/mnv/runtime/syntax/testdir/input/mnv9_legacy_header_fold.mnv
new file mode 100644
index 0000000000..e6b0751ae3
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_legacy_header_fold.mnv
@@ -0,0 +1,22 @@
+" MNV9 legacy script header
+" MNV_TEST_SETUP let g:mnvsyn_folding = "H"
+" MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+
+
+" comment
+
+if !has('mnv9script')
+ # 42 " comment
+ source foo.mnv
+ finish
+endif
+
+" comment
+
+mnv9script noclear
+
+# comment
+
+ # string only recognised with leading char
+ "useless string"
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_no_comment_strings.mnv b/mnv/runtime/syntax/testdir/input/mnv9_no_comment_strings.mnv
new file mode 100644
index 0000000000..270f2cf31c
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_no_comment_strings.mnv
@@ -0,0 +1,27 @@
+mnv9script
+# MNV9 no comment strings
+# MNV_TEST_SETUP let g:mnvsyn_comment_strings = v:false
+
+
+# pre "string" post
+
+function Foo()
+ " pre "string" post
+endfunction
+
+def Bar()
+ # pre "string" post
+enddef
+
+command Foo {
+ # pre "string" post
+}
+
+autocmd BufNewFile * {
+ # pre "string" post
+}
+
+{
+ # pre "string" post
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_shebang.mnv b/mnv/runtime/syntax/testdir/input/mnv9_shebang.mnv
new file mode 100644
index 0000000000..60f8f0fc7e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_shebang.mnv
@@ -0,0 +1,8 @@
+#!/usr/bin/env mnv -S
+mnv9script
+# MNV9 shebang line
+
+
+# just a line comment
+#!/usr/bin/env mnv -S
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords.mnv b/mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords.mnv
new file mode 100644
index 0000000000..fbb35ae5d6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords.mnv
@@ -0,0 +1,87 @@
+mnv9script
+# MNV9 this and super keywords
+# MNV_TEST_SETUP hi link mnv9This Todo
+# MNV_TEST_SETUP hi link mnv9Super Todo
+
+
+def Echo(...args: list<any>)
+ echo args
+enddef
+
+class Foo
+ var x: number = 42
+ var y: number = this.x + 41
+ var z: number = this.x + this.y
+
+ def new()
+ echo this.x this.y this.z
+ enddef
+
+ def newXY(this.x, this.y, this.z)
+ enddef
+
+ def Def1(arg = this.x)
+ this.y = arg
+ this.z += arg
+ enddef
+
+ def Def2(arg = (this.x + this.y + this.z))
+ Echo(this, this.x, this.y, this.z)
+ this->Echo(this.x, this.y, this.z)
+ enddef
+
+ def Def3(): Foo
+ return this
+ enddef
+
+ def Def4(arg: Foo = this): Foo
+ return arg
+ enddef
+endclass
+
+class Bar extends Foo
+ def Def1()
+ super.Def1()
+ enddef
+
+ def Def2()
+ var a = super.x * super.y * super.z
+ var b = [super.x, super.y, super.z]
+ var c = {super: super.x, this: super.y, true: super.z}
+ var d = {super: c, this: c}
+ echo c.super
+ echo c.this
+ echo d.super.this
+ echo d.this.super
+ echo a b c
+ enddef
+
+ def Def5()
+ var a = this.x * this.y
+ var b = (this.x * this.y)
+ var c = [this.x, this.y]
+ var d = {super: this.x, this: this.y}
+ echo a b c d
+ enddef
+
+ def Def6()
+ var x = this#super#x
+ var y = super#this#y
+ this#super#Func()
+ super#this#Func()
+ enddef
+
+ def Def7(arg = super.Def3())
+ echo arg
+ enddef
+
+ def Def8(): number
+ var F = () => this.x
+ var G = () => super.x
+ return F() + G()
+ enddef
+endclass
+
+defcompile Foo
+defcompile Bar
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords2.mnv b/mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords2.mnv
new file mode 100644
index 0000000000..dbf20dfc92
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords2.mnv
@@ -0,0 +1,63 @@
+mnv9script
+# MNV9 this and super keywords
+# MNV_TEST_SETUP hi link mnv9Super Todo
+# MNV_TEST_SETUP hi link mnv9This Todo
+# See: https://github.com/Project-Tick/Project-Tick/pull/16476#issuecomment-2638191110
+
+
+class A
+ var _value: any
+
+ def new(value: any)
+ this._BaseInit(value)
+ enddef
+
+ def _BaseInit(value: any)
+ this._value = value
+ enddef
+
+ def Value(): any
+ return this._value
+ enddef
+endclass
+
+class B extends A
+ def new(value: number)
+ super._BaseInit(value)
+ enddef
+
+ def Value(): number
+ echo this
+ return super._value
+ enddef
+endclass
+
+class C extends A
+ #### E117
+ # def new(value: string)
+ # super(value)
+ # enddef
+
+ #### E1034
+ # def new(super._value)
+ # enddef
+
+ #### E1034
+ # def new(value: string)
+ # super._value = value
+ # enddef
+
+ #### E1356
+ # def Super(): A
+ # return super
+ # enddef
+
+ def This(): C
+ return this
+ enddef
+endclass
+
+echo 1 == A.new(1).Value()
+echo 2 == B.new(2).Value()
+defcompile C
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords3.mnv b/mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords3.mnv
new file mode 100644
index 0000000000..6412cf2b95
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_super_this_keywords3.mnv
@@ -0,0 +1,27 @@
+mnv9script
+# MNV9 this and super keywords
+# MNV_TEST_SETUP hi link mnv9Super Todo
+# MNV_TEST_SETUP hi link mnv9This Todo
+# See: https://github.com/Project-Tick/Project-Tick/pull/16476#issuecomment-2635119478
+
+
+class A
+ const _value: number
+
+ def new(this._value)
+ enddef
+
+ def K(): func(any): number
+ return ((_: any) => this._value)
+ enddef
+endclass
+
+class B extends A
+ def K(): func(any): number
+ return ((_: any) => super._value)
+ enddef
+endclass
+
+echo 1 == A.new(1).K()(null)
+echo 2 == B.new(2).K()(null)
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_tuples.mnv b/mnv/runtime/syntax/testdir/input/mnv9_tuples.mnv
new file mode 100644
index 0000000000..946a6be1b7
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_tuples.mnv
@@ -0,0 +1,25 @@
+mnv9script
+# MNV9 tuples
+
+
+# https://github.com/Project-Tick/Project-Tick/pull/16935#issuecomment-2738310273
+
+function LegacyMakeEntry(key, value) abort
+ return (a:key, a:value)
+endfunction
+
+def MakeEntry(key: string, value: any): tuple<string, any>
+ return (key, value)
+enddef
+
+function LegacyMakeLazyList(e1, e2) abort
+ return ({e1_, e2_ -> {-> [e1_, e2_]}}(a:e1, a:e2))
+endfunction
+
+def MakeLazyList(e1: any, e2: any): func(): list<any>
+ return (((e1_: any, e2_: any) => () => [e1_, e2_])(e1, e2))
+enddef
+
+echo MakeEntry('key', 'value') == list2tuple(MakeLazyList('key', 'value')())
+echo LegacyMakeEntry('key', 'value') == list2tuple(LegacyMakeLazyList('key', 'value')())
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_types.mnv b/mnv/runtime/syntax/testdir/input/mnv9_types.mnv
new file mode 100644
index 0000000000..b68d2a2126
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_types.mnv
@@ -0,0 +1,17 @@
+mnv9script
+# MNV9 types
+# MNV_TEST_SETUP hi link mnvTypeAny Todo
+# MNV_TEST_SETUP hi link mnv9VariableTypeAny Todo
+
+
+# builtin types (distinct any highlighting)
+
+var foo: bool
+var bar: any
+
+def Foo(arg: bool): bool
+enddef
+
+def Bar(arg: any): any
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_types_example_object.mnv b/mnv/runtime/syntax/testdir/input/mnv9_types_example_object.mnv
new file mode 100644
index 0000000000..11ac3cd68d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_types_example_object.mnv
@@ -0,0 +1,29 @@
+mnv9script
+# MNV9 object type constructor
+
+
+# Issue #18677 (No recognition of object<any> types - Aliaksei Budavei)
+
+interface I
+ def string(): string
+endinterface
+
+class C implements I
+ def string(): string
+ return "C"
+ enddef
+endclass
+
+enum E implements I
+ INSTANCE
+
+ def string(): string
+ return "E"
+ enddef
+endenum
+
+var c: object<C> = C.new()
+var e: object<E> = E.INSTANCE
+var os: tuple<object<any>, object<I>> = (c, e)
+echo (c, e) == os
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_types_object.mnv b/mnv/runtime/syntax/testdir/input/mnv9_types_object.mnv
new file mode 100644
index 0000000000..266aa02c71
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_types_object.mnv
@@ -0,0 +1,27 @@
+mnv9script
+# MNV9 object type constructor
+# MNV_TEST_SETUP hi link mnvTypeObject Todo
+# MNV_TEST_SETUP hi link mnvTypeObjectBracket Title
+
+
+interface I
+endinterface
+
+var a: object<I>
+var b: object<any>
+var c: object<object<I>>
+var d: object<object<any>>
+
+def Foo(
+ arg1: object<I>,
+ arg2: object<any>,
+ arg3: object<object<I>>,
+ arg4: object<object<any>>)
+enddef
+
+def Bar(): object<I>
+enddef
+
+def Baz(): object<object<I>>
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv9_variables.mnv b/mnv/runtime/syntax/testdir/input/mnv9_variables.mnv
new file mode 100644
index 0000000000..8e307f060f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv9_variables.mnv
@@ -0,0 +1,269 @@
+mnv9script
+# MNV9 variable highlighting
+
+
+# Declarations
+
+var foo = expr
+
+b:foo = expr
+g:foo = expr
+t:foo = expr
+w:foo = expr
+
+v:true = expr
+
+$FOO = expr
+
+var [foo, bar] = expr
+var [foo,
+ \ bar] = expr
+var [$foo, $bar] = expr
+var [$foo,
+ \ $bar] = expr
+
+var [foo, bar; baz] = expr
+var [foo,
+ \ bar;
+ \ baz] = expr
+var [$foo, $bar; $baz] = expr
+var [$foo,
+ \ $bar;
+ \ $baz] = expr
+
+var foo =<< END
+...
+END
+var foo =<< trim END
+...
+END
+var foo =<< eval END
+...
+END
+var foo =<< trim eval END
+...
+END
+var foo =<< eval trim END
+...
+END
+
+# Typed declarations
+
+var foo: tuple<any> = expr
+var foo: tuple<number> = expr
+var foo: tuple<number, string, bool> = expr
+var foo: tuple<...list<any>> = expr
+var foo: tuple<...list<number>> = expr
+var foo: tuple<number, ...list<string>> = expr
+
+var foo: tuple<
+ #\ comment
+ \number,
+ #\ comment
+ \string,
+ #\ comment
+ \bool
+ \>
+
+# Assignments
+
+foo = expr
+
+foo[0] = expr
+
+foo[1:2] = expr
+foo[:2] = expr
+foo[1:] = expr
+foo[:] = expr
+
+foo["key"] = expr
+foo['key'] = expr
+
+foo += expr
+foo -= expr
+foo *= expr
+foo /= expr
+foo %= expr
+foo ..= expr
+
+b:foo = expr
+g:foo = expr
+t:foo = expr
+w:foo = expr
+
+b:foo += expr
+g:foo += expr
+t:foo += expr
+w:foo += expr
+
+b:foo -= expr
+g:foo -= expr
+t:foo -= expr
+w:foo -= expr
+
+b:foo *= expr
+g:foo *= expr
+t:foo *= expr
+w:foo *= expr
+
+b:foo /= expr
+g:foo /= expr
+t:foo /= expr
+w:foo /= expr
+
+b:foo %= expr
+g:foo %= expr
+t:foo %= expr
+w:foo %= expr
+
+b:foo ..= expr
+g:foo ..= expr
+t:foo ..= expr
+w:foo ..= expr
+
+$FOO = expr
+$FOO ..= expr
+
+@f = expr
+@f ..= expr
+
+&ari = expr
+
+&t_k1 = "\<Esc>[234;"
+
+&ari ..= expr
+
+&ari += expr
+&ari -= expr
+
+&l:aleph = expr
+
+&l:aleph ..= expr
+&l:aleph += expr
+&l:aleph -= expr
+
+&g:aleph = expr
+
+&g:aleph ..= expr
+&g:aleph += expr
+&g:aleph -= expr
+
+[foo, bar] = expr
+[foo,
+ \ bar] = expr
+[v:true, v:false] = expr
+[v:true,
+ \ v:false] = expr
+[&ari, &bkc] = expr
+[&ari,
+ \ &bkc] = expr
+[$foo, $bar] = expr
+[$foo,
+ \ $bar] = expr
+[@a, @b] = expr
+[@a,
+ \ @a] = expr
+
+[foo, bar] ..= expr
+[foo, bar] += expr
+[foo, bar] -= expr
+[foo, bar] *= expr
+[foo, bar] /= expr
+[foo, bar] %= expr
+
+[foo, bar; baz] = expr
+[foo,
+ \ bar;
+ \ baz] = expr
+[v:true, v:false; v:none] = expr
+[v:true,
+ \ v:false;
+ \ v:none] = expr
+[$foo, $bar; $baz] = expr
+[$foo,
+ \ $bar;
+ \ $baz] = expr
+[&ari, &bkc; &cmp] = expr
+[&ari,
+ \ &bkc;
+ \ &cmp] = expr
+[@a, @b; @c] = expr
+[@a,
+ \ @b;
+ \ @c] = expr
+
+foo =<< END
+...
+END
+foo =<< trim END
+...
+END
+foo =<< eval END
+...
+END
+foo =<< trim eval END
+...
+END
+foo =<< eval trim END
+...
+END
+
+# :unlet
+
+unlet foo
+unlet foo bar
+unlet foo
+ #\ comment
+ \ bar
+
+unlet! foo
+unlet! foo bar
+unlet! foo
+ #\ comment
+ \ bar
+
+unlet $FOO
+unlet! $FOO
+
+unlet list[3]
+unlet list[3:]
+unlet dict['two']
+unlet dict.two
+
+unlet foo # comment
+unlet foo #\ comment
+unlet foo | echo "Foo"
+unlet foo bar # comment
+unlet foo bar #\ comment
+unlet foo bar | echo "Foo"
+
+# :for
+
+for foo in expr
+endfor
+
+for [foo, bar] in expr
+endfor
+
+# Scope dictionaries
+
+echo get(b:, 'foo', 42)
+echo get(w:, 'foo', 42)
+echo get(t:, 'foo', 42)
+echo get(g:, 'foo', 42)
+echo get(v:, 'foo', 42)
+
+for k in keys(b:) | echo b:[k] | endfor
+for k in keys(w:) | echo w:[k] | endfor
+for k in keys(t:) | echo t:[k] | endfor
+for k in keys(g:) | echo g:[k] | endfor
+for k in keys(v:) | echo v:[k] | endfor
+
+# Neomnv-specific variables (not highlighted by default)
+
+echo v:lua v:msgpack_types v:relnum v:stderr v:termrequest v:virtnum
+
+echo &channel &inccommand &mousescroll &pumblend &redrawdebug &scrollback
+echo &shada &shadafile &statuscolumn &termpastefilter &termsync &winbar
+echo &winblend &winhighlight
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_comment_strings.mnv b/mnv/runtime/syntax/testdir/input/mnv_comment_strings.mnv
new file mode 100644
index 0000000000..11707b045a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_comment_strings.mnv
@@ -0,0 +1,22 @@
+" MNV comment strings
+" MNV_TEST_SETUP let g:mnvsyn_comment_strings = v:true
+
+
+" pre "string" post
+
+function Foo()
+ " pre "string" post
+endfunction
+
+def Bar()
+ # pre "string" post
+enddef
+
+command Foo {
+ # pre "string" post
+}
+
+autocmd BufNewFile * {
+ # pre "string" post
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_comments.mnv b/mnv/runtime/syntax/testdir/input/mnv_comments.mnv
new file mode 100644
index 0000000000..6bfa03aec3
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_comments.mnv
@@ -0,0 +1,83 @@
+" MNV comments
+
+
+" Legacy-script comment
+
+# 42 " comment
+
+function! Foo()
+ " Legacy-script comment
+ # 42 " comment
+endfunction
+
+def! Bar()
+ # MNV9-script comment
+ "useless string" # comment
+enddef
+
+command -nargs=1 FooCommand {
+ # MNV9-script comment
+ "useless string" # comment
+}
+
+autocmd BufNewFile * {
+ # MNV9-script comment
+ "useless string" # comment
+}
+
+
+" Multiline comments
+
+" comment
+ \ continuing comment
+ \ continuing comment
+
+let foo = 42 " commment
+ \ continuing comment
+ \ continuing comment
+
+" :Foo
+ \ arg1
+ "\ comment
+ \ arg2
+
+echo "TOP"
+
+
+" Line-continuation comments
+
+:Foo
+ "\ line continuation comment
+ \ arg1
+ "\ line continuation comment
+ \ arg2
+
+
+" Issue: #13047
+
+if !exists(":DiffOrig")
+ command DiffOrig vert new | set bt=nofile | r ++edit # | 0d_ | diffthis
+ \ | wincmd p | diffthis
+endif
+
+
+" Issue: #11307 and #11560
+
+" This is what we call " blah
+
+
+" Issue # #9587
+
+def CommentTitle()
+ # Title: ...
+enddef
+
+
+" PR: #19390
+" https://github.com/Project-Tick/Project-Tick/pull/19390#issue-3933755846
+
+def CommentTitle2()
+ # E1234: should not have mnv9CommentTitle on 'E1234:'
+ # ERR34: should have mnv9CommentTitle on 'ERR34:'
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_abbreviate.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_abbreviate.mnv
new file mode 100644
index 0000000000..c40b47e229
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_abbreviate.mnv
@@ -0,0 +1,54 @@
+" MNV :abbreviate commands
+" MNV_TEST_SETUP hi link mnvMapLhs Identifier
+" MNV_TEST_SETUP hi link mnvMapRhs Todo
+" MNV_TEST_SETUP hi link mnvMapRhsContinue Todo
+
+
+abbrev <buffer> foo foobar
+cabbrev <buffer> cfoo cfoobar
+iabbrev <buffer> ifoo ifoobar
+
+abbrev <expr> <buffer> foo foobar
+cabbrev <expr> <buffer> cfoo cfoobar
+iabbrev <expr> <buffer> ifoo ifoobar
+
+noreabbrev <buffer> foo foobar
+cnoreabbrev <buffer> cfoo cfoobar
+inoreabbrev <buffer> ifoo ifoobar
+
+abbrev <expr> <buffer> foo foobar
+cabbrev <expr> <buffer> cfoo cfoobar
+iabbrev <expr> <buffer> ifoo ifoobar
+
+unabbrev <buffer> foo
+cunabbrev <buffer> cfoo
+iunabbrev <buffer> ifoo
+
+abclear <buffer>
+cabclear <buffer>
+iabclear <buffer>
+
+
+" Multiline RHS
+
+abbrev foo
+ \ foobar
+
+abbrev foo
+ \
+ \ foobar
+
+abbrev foo
+ "\ comment
+ \ foobar
+
+abbrev foo
+ "\ comment
+ \ foo
+ "\ comment
+ \bar
+
+abbrev lhs
+ "\ comment (matches as RHS but harmless)
+echo "clear"
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_at.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_at.mnv
new file mode 100644
index 0000000000..c0674a4945
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_at.mnv
@@ -0,0 +1,66 @@
+" MNV :@ command
+
+
+@0
+@1
+@2
+@3
+@4
+@5
+@6
+@7
+@8
+@9
+
+@a
+@k
+@z
+
+@"
+@.
+@=
+@*
+@+
+
+@:
+
+" repeats
+@
+@@
+
+@a | echo "..."
+@a " comment
+
+
+def MNV9Context()
+ :@0
+ :@1
+ :@2
+ :@3
+ :@4
+ :@5
+ :@6
+ :@7
+ :@8
+ :@9
+
+ :@a
+ :@k
+ :@z
+
+ :@"
+ :@.
+ :@=
+ :@*
+ :@+
+
+ :@:
+
+ # repeats
+ :@
+ :@@
+
+ :@a | echo "..."
+ :@a # comment
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_augroup.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_augroup.mnv
new file mode 100644
index 0000000000..c5a34ea9ba
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_augroup.mnv
@@ -0,0 +1,71 @@
+" MNV :augroup command
+" MNV_TEST_SETUP let g:mnvsyn_folding = "a"
+" MNV_TEST_SETUP setl fdc=2 fdl=999 fdm=syntax
+" MNV_TEST_SETUP hi link mnvAugroupName Todo
+
+
+augroup foo
+ autocmd!
+ autocmd BufRead * echo "Foo"
+augroup END
+
+augroup foo | autocmd! | augroup END
+augroup! foo
+
+augroup !@#$%^&*()_+
+ autocmd BufRead * echomsg "Foo"
+augroup END
+
+augroup !@#$%^&*()_+ | autocmd! | augroup END
+augroup! !@#$%^&*()_+
+
+augroup !@#$%^&*()_+ | autocmd! | augroup END
+augroup! !@#$%^&*()_+
+
+augroup no\|echo | autocmd! | augroup END
+augroup! no\|echo
+
+augroup no\"echo | autocmd! | augroup END
+augroup! no\"echo
+
+augroup \|echo\| | autocmd! | augroup END
+augroup! \|echo\|
+
+augroup \"echo\" | autocmd! | augroup END
+augroup! \"echo\"
+
+augroup \|\" | autocmd! | augroup END
+augroup! \|\"
+
+augroup \"\| | autocmd! | augroup END
+augroup! \"\|
+
+
+" trailing bar and tail comments
+
+augroup foo"comment
+ autocmd!
+ autocmd BufRead * echo "Foo"
+augroup END"comment
+
+augroup foo|echo "Foo"
+ autocmd!
+ autocmd BufRead * echo "Foo"
+augroup END|echo "Foo"
+
+augroup! foo"comment
+augroup! foo|echo "Foo"
+
+
+" list groups
+
+augroup
+augroup | echo "Foo"
+augroup " comment
+
+
+" groups named END*
+
+augroup ending
+augroup END
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_autocmd.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_autocmd.mnv
new file mode 100644
index 0000000000..e864479641
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_autocmd.mnv
@@ -0,0 +1,257 @@
+" MNV :autocmd command
+" MNV_TEST_SETUP hi link mnvAutoCmdGroup Todo
+" MNV_TEST_SETUP hi link mnvUserAutoEvent Title
+
+
+" Define
+
+autocmd foogroup BufRead *.txt echo "Foo" | echo "Bar"
+autocmd BufRead *.txt echo "Foo" | echo "Bar"
+autocmd BufRead,BufNewFile *.txt echo "Foo" | echo "Bar"
+autocmd User FooEvent echo "Foo" | echo "Bar"
+
+autocmd foogroup BufRead *.txt ++once echo "Foo" | echo "Bar"
+autocmd BufRead *.txt ++once echo "Foo" | echo "Bar"
+autocmd BufRead,BufNewFile *.txt ++once echo "Foo" | echo "Bar"
+autocmd User FooEvent ++once echo "Foo" | echo "Bar"
+
+autocmd foogroup BufRead *.txt ++nested echo "Foo" | echo "Bar"
+autocmd BufRead *.txt ++nested echo "Foo" | echo "Bar"
+autocmd BufRead,BufNewFile *.txt ++nested echo "Foo" | echo "Bar"
+autocmd User FooEvent ++nested echo "Foo" | echo "Bar"
+
+autocmd foogroup BufRead *.txt ++once ++nested echo "Foo" | echo "Bar"
+autocmd BufRead *.txt ++once ++nested echo "Foo" | echo "Bar"
+autocmd BufRead,BufNewFile *.txt ++once ++nested echo "Foo" | echo "Bar"
+autocmd User FooEvent ++once ++nested echo "Foo" | echo "Bar"
+
+autocmd foogroup BufRead <buffer> ++once ++nested echo "Foo" | echo "Bar"
+autocmd foogroup BufRead <buffer=42> ++once ++nested echo "Foo" | echo "Bar"
+autocmd foogroup BufRead <buffer=abuf> ++once ++nested echo "Foo" | echo "Bar"
+autocmd BufRead <buffer> ++once ++nested echo "Foo" | echo "Bar"
+autocmd BufRead <buffer=42> ++once ++nested echo "Foo" | echo "Bar"
+autocmd BufRead <buffer=abuf> ++once ++nested echo "Foo" | echo "Bar"
+autocmd BufRead,BufNewFile <buffer> ++once ++nested echo "Foo" | echo "Bar"
+autocmd BufRead,BufNewFile <buffer=42> ++once ++nested echo "Foo" | echo "Bar"
+autocmd BufRead,BufNewFile <buffer=abuf> ++once ++nested echo "Foo" | echo "Bar"
+autocmd User FooEvent,BarEvent ++once ++nested echo "Foo" | echo "Bar"
+
+autocmd foogroup BufRead f<buffer>oo ++once ++nested echo "Foo" | echo "Bar"
+
+autocmd BufRead *.txt {
+ echo "Foo"
+ echo "Bar"
+}
+autocmd BufRead,BufNewFile *.txt {
+ echo "Foo"
+ echo "Bar"
+}
+autocmd User FooEvent {
+ echo "Foo"
+ echo "Bar"
+}
+autocmd foogroup BufRead *.txt {
+ echo "Foo"
+ echo "Bar"
+}
+
+
+" Multiline {cmd} arg
+
+autocmd BufRead *.txt echo "Foo"
+ \| echo "Bar"
+ \| echo "Baz"
+
+autocmd BufRead *.txt echo "Foo" |
+ \ echo "Bar" |
+ \ echo "Baz"
+
+autocmd BufRead *.txt
+ "\ comment
+ \ echo "Foo" |
+ "\ comment
+ \ echo "Bar"
+ "\ comment
+ \| echo "Baz"
+
+autocmd BufRead,BufNewFile *.txt
+ "\ comment
+ \ echo "Foo" |
+ "\ comment
+ \ echo "Bar"
+ "\ comment
+ \| echo "Baz"
+autocmd User FooEvent
+ "\ comment
+ \ echo "Foo" |
+ "\ comment
+ \ echo "Bar"
+ "\ comment
+ \| echo "Baz"
+autocmd foogroup BufRead *.txt
+ "\ comment
+ \ echo "Foo" |
+ "\ comment
+ \ echo "Bar"
+ "\ comment
+ \| echo "Baz"
+
+
+" Multiple patterns
+
+autocmd BufRead *.txt,*.mnv,*.c echo "Foo" | echo "Bar"
+autocmd BufRead <buffer>,*.mnv,*.c echo "Foo" | echo "Bar"
+autocmd BufRead *.txt,<buffer>,*.c echo "Foo" | echo "Bar"
+autocmd BufRead *.txt,*.mnv,<buffer> echo "Foo" | echo "Bar"
+
+autocmd BufRead <buffer=1>,<buffer=2>,<buffer=3> echo "Foo" | echo "Bar"
+
+
+" FIXME: "BufRead" and "*" are valid group names, however, :help :augroup
+" explicitly directs the user NOT to shadow event names with group names
+autocmd BufRead BufRead *.txt ++once ++nested echo "Foo"
+autocmd * BufRead *.txt ++once ++nested echo "Foo"
+
+
+" Remove
+
+autocmd! foogroup BufRead *.txt ++once ++nested echo "Foo" | echo "Bar"
+autocmd! BufRead *.txt ++once ++nested echo "Foo" | echo "Bar"
+autocmd! foogroup User FooEvent ++once ++nested echo "Foo" | echo "Bar"
+autocmd! User FooEvent ++once ++nested echo "Foo" | echo "Bar"
+
+autocmd! foogroup BufRead *.txt
+autocmd! BufRead *.txt
+autocmd! foogroup User FooEvent
+autocmd! User FooEvent
+
+autocmd! foogroup * *.txt
+autocmd! * *.txt
+
+autocmd! foogroup BufRead
+autocmd! BufRead
+autocmd! foogroup User FooEvent
+autocmd! User FooEvent
+
+autocmd! foogroup
+autocmd!
+
+" command -> bang -> group "!foogroup!"
+autocmd!!foogroup!
+" command -> bang -> group "foogroup"
+autocmd!foogroup
+" command -> bang -> event
+autocmd!BufRead
+" command -> bang -> user event
+autocmd!User FooEvent
+
+" FIXME: "*" and "BufRead" are valid group names, however, :help :augroup
+" explicitly directs the user NOT to shadow event names
+" command -> group "*" -> event glob -> pattern
+autocmd!* * *.txt
+" command -> group "BufRead" -> event "BufRead" -> pattern
+autocmd!BufRead BufRead *.txt
+
+
+" List
+
+autocmd foogroup BufRead *.txt
+autocmd BufRead *.txt
+
+autocmd foogroup * *.txt
+autocmd * *.txt
+
+autocmd foogroup BufRead
+autocmd BufRead
+autocmd foogroup User FooEvent
+autocmd User FooEvent
+
+autocmd foogroup
+autocmd
+
+
+" :doautoall
+
+doautoall BufRead
+
+doautoall BufRead *.txt
+doautoall foogroup BufRead
+doautoall <nomodeline> BufRead
+
+doautoall <nomodeline> foogroup BufRead *.txt
+
+doautoall User FooEvent
+doautoall foogroup User FooEvent
+doautoall <nomodeline> User FooEvent
+
+doautoall <nomodeline> foogroup User FooEvent
+
+doautoall <nomodeline> foogroup BufRead *.txt | echo "Foo"
+doautoall <nomodeline> foogroup BufRead *.txt " comment
+
+
+" :doautocmd
+
+doautocmd BufRead
+
+doautocmd BufRead *.txt
+doautocmd foogroup BufRead
+doautocmd <nomodeline> BufRead
+
+doautocmd <nomodeline> foogroup BufRead *.txt
+
+doautocmd User FooEvent
+doautocmd User FooEvent,BarEvent
+doautocmd foogroup User FooEvent
+doautocmd <nomodeline> User FooEvent
+
+doautocmd <nomodeline> foogroup User FooEvent
+
+doautocmd <nomodeline> foogroup BufRead *.txt | echo "Foo"
+doautocmd <nomodeline> foogroup BufRead *.txt | " comment
+
+
+" Patterns
+
+au BufRead */*.txt
+
+au BufRead */*.*
+au BufRead */*.???
+au BufRead */*.[t][x]t
+
+au BufRead */*.[a-z][a-z]t
+au BufRead */*.[[:alpha:][:alpha:]]t
+
+au BufRead */*.[tx]\\\{2\}t
+au BufRead */*.[a-z]\\\{2\}t
+au BufRead */*.[[:alpha:]]\\\{2\}t
+au BufRead */*.[^[:punct:]]\\\{2\}t
+
+au BufRead */*.[]]xt
+au BufRead */*.[^]]xt
+
+au BufRead */*.[t\]]xt
+au BufRead */*.[^t\]]xt
+
+au BufRead */*.[[]xt
+au BufRead */*.[^[]xt
+
+au BufRead */*.[-]xt
+au BufRead */*.[^-]xt
+
+au BufRead */*.[-t-]xt
+au BufRead */*.[^-t-]xt
+
+au BufRead */*.[\^]xt
+au BufRead */*.[^^]xt
+
+au BufRead */*.txt,*/*.mnv
+au BufRead */*.{txt,mnv}
+au BufRead */*.{t{x,t},v{i,m}}
+
+" literal
+au BufRead */*.[]xt
+au BufRead */*.[\]xt
+au BufRead */*.[^]xt
+au BufRead */*.[^\]xt
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_behave.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_behave.mnv
new file mode 100644
index 0000000000..7f06fe6076
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_behave.mnv
@@ -0,0 +1,9 @@
+" MNV :behave command
+
+
+behave mswin
+behave xterm
+
+behave! mswin
+behave! xterm
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_breakpoint_commands.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_breakpoint_commands.mnv
new file mode 100644
index 0000000000..671646908c
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_breakpoint_commands.mnv
@@ -0,0 +1,95 @@
+" MNV :break* commands
+" MNV_TEST_SETUP hi link mnvBreakpointNumber Number
+" MNV_TEST_SETUP hi link mnvBreakpointFunctionLine Number
+" MNV_TEST_SETUP hi link mnvBreakpointFileLine Number
+" MNV_TEST_SETUP hi link mnvBreakpointFilename Identifier
+" MNV_TEST_SETUP hi link mnvBreakpointFunction Type
+
+
+breakadd func Foo
+breakadd func 42 Foo
+breakadd file foo.txt
+breakadd file 42 foo.txt
+breakadd here
+breakadd expr g:foo
+
+breaklist
+
+breakdel 42
+breakdel *
+breakdel func Foo
+breakdel func 42 Foo
+breakdel file foo.txt
+breakdel file 42 foo.txt
+
+function Foo()
+ breakadd func Foo
+ breakadd func 42 Foo
+ breakadd file foo.txt
+ breakadd file 42 foo.txt
+ breakadd here
+ breakadd expr g:foo
+
+ breaklist
+
+ breakdel 42
+ breakdel *
+ breakdel func Foo
+ breakdel func 42 Foo
+ breakdel file foo.txt
+ breakdel file 42 foo.txt
+endfunction
+
+def MNV9Context()
+ breakadd func Foo
+ breakadd func 42 Foo
+ breakadd file foo.txt
+ breakadd file 42 foo.txt
+ breakadd here
+ breakadd expr g:foo
+
+ breaklist
+
+ breakdel 42
+ breakdel *
+ breakdel func Foo
+ breakdel func 42 Foo
+ breakdel file foo.txt
+ breakdel file 42 foo.txt
+enddef
+
+
+" tail comment and trailing bar
+
+breakadd func Foo " comment
+breakadd func 42 Foo " comment
+breakadd file foo.txt " comment
+breakadd file 42 foo.txt " comment
+breakadd here " comment
+breakadd expr g:foo " comment
+
+breaklist " comment
+
+breakdel 42 " comment
+breakdel * " comment
+breakdel func Foo " comment
+breakdel func 42 Foo " comment
+breakdel file foo.txt " comment
+breakdel file 42 foo.txt " comment
+
+breakadd func Foo | echo "..."
+breakadd func 42 Foo | echo "..."
+breakadd file foo.txt | echo "..."
+breakadd file 42 foo.txt | echo "..."
+breakadd here | echo "..."
+breakadd expr g:foo | echo "..."
+
+breaklist | echo "..."
+
+breakdel 42 | echo "..."
+breakdel * | echo "..."
+breakdel func Foo | echo "..."
+breakdel func 42 Foo | echo "..."
+breakdel file foo.txt | echo "..."
+breakdel file 42 foo.txt | echo "..."
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_call.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_call.mnv
new file mode 100644
index 0000000000..5e2a8caf9f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_call.mnv
@@ -0,0 +1,52 @@
+" MNV :call command
+
+
+" Functions with same-named Ex commands
+
+call browse(save, title, initdir, default)
+call call(func, arglist, dict)
+call chdir(dir)
+call confirm(msg, choices, default, type)
+call copy(expr)
+call delete(fname, flags)
+call eval(string)
+call execute(command)
+call filter(expr1, expr2)
+call function(name, arglist, dict)
+call insert(object, item, idx)
+call join(list, sep)
+call map(expr1, expr2)
+call match(expr, pat, start, count)
+call mode(expr)
+call sort(list, how, dict)
+call split(string, pattern, keepempty)
+call substitute(str, pat, sub, flags)
+call swapname(buf)
+
+call browse (save, title, initdir, default)
+call call (func, arglist, dict)
+call chdir (dir)
+call confirm (msg, choices, default, type)
+call copy (expr)
+call delete (fname, flags)
+call eval (string)
+call execute (command)
+call filter (expr1, expr2)
+call function (name, arglist, dict)
+call insert (object, item, idx)
+call join (list, sep)
+call map (expr1, expr2)
+call match (expr, pat, start, count)
+call mode (expr)
+call sort (list, how, dict)
+call split (string, pattern, keepempty)
+call substitute (str, pat, sub, flags)
+call swapname (buf)
+
+call Foo()
+call Foo(arg1)
+call Foo(arg1, arg2)
+
+let res = call(func, arglist, dict)
+let res = call (func, arglist, dict)
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_catch.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_catch.mnv
new file mode 100644
index 0000000000..20bf351551
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_catch.mnv
@@ -0,0 +1,19 @@
+" MNV :catch command
+
+
+" :help :catch
+
+catch /^MNV:Interrupt$/ " catch interrupts (CTRL-C)
+catch /^MNV\%((\a\+)\)\=:E/ " catch all MNV errors
+catch /^MNV\%((\a\+)\)\=:/ " catch errors and interrupts
+catch /^MNV(write):/ " catch all errors in :write
+catch /^MNV\%((\a\+)\)\=:E123:/ " catch error E123
+catch /my-exception/ " catch user exception
+catch /.*/ " catch everything
+catch " same as /.*/
+
+" :help :try
+
+try | sleep 100 | catch /^MNV:Interrupt$/ | endtry
+try | edit | catch /^MNV(edit):E\d\+/ | echo "error" | endtry
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_cd.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_cd.mnv
new file mode 100644
index 0000000000..6ed6f779e6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_cd.mnv
@@ -0,0 +1,110 @@
+" MNV :cd commands
+" MNV_TEST_SETUP hi link mnvCdArg Todo
+
+
+cd
+cd!
+cd foo
+cd! foo
+cd %:h/foo
+cd! %:h/foo
+cd foo bar/baz
+cd! foo bar/baz
+cd -
+cd! -
+
+cd \"foo\"bar\"
+cd \|foo\|bar\|
+cd \#foo\#bar\#
+cd \ foo\ bar\
+cd \\foo\\bar\\
+
+cd " comment
+cd | echo "..."
+cd! " comment
+cd! | echo "..."
+
+
+function Foo()
+ cd
+ cd!
+ cd foo
+ cd! foo
+ cd -
+ cd! -
+
+ cd " comment
+ cd | echo "..."
+ cd! " comment
+ cd! | echo "..."
+endfunction
+
+def Foo()
+ cd
+ cd!
+ cd foo
+ cd! foo
+ cd -
+ cd! -
+
+ cd # comment
+ cd | echo "..."
+ cd! # comment
+ cd! | echo "..."
+enddef
+
+
+cd | lcd | tcd | chdir | lchdir | tchdir | echo "..."
+cd - | lcd - | tcd - | chdir - | lchdir - | tchdir - | echo "..."
+cd foo | lcd foo | tcd foo | chdir foo | lchdir foo | tchdir foo | echo "..."
+cd! | lcd! | tcd! | chdir! | lchdir! | tchdir! | echo "..."
+cd! - | lcd! - | tcd! - | chdir! - | lchdir! - | tchdir! - | echo "..."
+cd! foo | lcd! foo | tcd! foo | chdir! foo | lchdir! foo | tchdir! foo | echo "..."
+
+cd " comment
+cd! " comment
+cd - " comment
+cd! - " comment
+cd foo " comment
+cd! foo " comment
+lcd " comment
+lcd! " comment
+lcd - " comment
+lcd! - " comment
+lcd foo " comment
+lcd! foo " comment
+tcd " comment
+tcd! " comment
+tcd - " comment
+tcd! - " comment
+tcd foo " comment
+tcd! foo " comment
+chdir " comment
+chdir! " comment
+chdir - " comment
+chdir! - " comment
+chdir foo " comment
+chdir! foo " comment
+lchdir " comment
+lchdir! " comment
+lchdir - " comment
+lchdir! - " comment
+lchdir foo " comment
+lchdir! foo " comment
+tchdir " comment
+tchdir! " comment
+tchdir - " comment
+tchdir! - " comment
+tchdir foo " comment
+tchdir! foo " comment
+
+
+" Issue #17964 (MNV script highlight: endif is not highlighted after lcd)
+
+def LcdBack()
+ if get(g:, "lcd", 0)
+ g:lcd = 0
+ lcd -
+ endif
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_command.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_command.mnv
new file mode 100644
index 0000000000..79ac94b702
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_command.mnv
@@ -0,0 +1,196 @@
+" MNV :command, :delcommand and :comclear commands
+" MNV_TEST_SETUP hi link mnvUserCmdName Todo
+" MNV_TEST_SETUP hi link mnvDelcommandName Todo
+
+
+" List
+
+command
+command F
+
+
+" Define
+
+command Foo echo "Foo"
+command! Foo echo "Foo"
+
+command! Foo echo "Foo" | echo "Bar"
+
+command! Foo {
+ echo "Foo"
+ echo "Bar"
+ echo "Baz"
+}
+
+command! -addr=arguments -bang -bar -buffer -complete=arglist -count=1 -keepscript -nargs=* -range=% -register Foo echo "Foo"
+
+command! -addr=arguments -bang -bar -buffer -complete=arglist -count=1 -keepscript -nargs=* -range=% -register Foo
+ \ echo "Foo"
+
+command! -addr=arguments -bang -bar -buffer -complete=arglist -count=1 -keepscript -nargs=* -range=% -register
+ \ Foo
+ \ echo "Foo"
+
+command! -addr=arguments -bang -bar -buffer -complete=arglist -count=1 -keepscript -nargs=* -range=% -register Foo
+ "\ comment
+ \ echo "Foo"
+
+command! -addr=arguments -bang -bar -buffer -complete=arglist -count=1 -keepscript -nargs=* -range=% -register
+ "\ comment
+ \ Foo
+ "\ comment
+ \ echo "Foo"
+
+command! -complete=custom,s:Completer1 Foo echo "Foo"
+command! -complete=customlist,s:Completer2 Foo echo "Foo"
+
+function Foo()
+ command! Foo echo "Foo (defined in :function)"
+endfunction
+
+def Foo2()
+ command! Foo echo "Foo (defined in :def)"
+enddef
+
+
+" Multiline define
+
+command! -addr=lines
+ \ -bang
+ \ -bar
+ \ -buffer
+ \ -complete=buffer
+ \ -count
+ \ -nargs=*
+ \ -range
+ \ -register
+ \ -keepscript
+ \ Foo
+ \ echo "Foo" |
+ \ echo "Bar"
+
+command!
+ \ -addr=lines
+ \ -bang
+ \ -bar
+ \ -buffer
+ \ -complete=buffer
+ \ -count
+ \ -nargs=*
+ \ -range
+ \ -register
+ \ -keepscript
+ \ Foo
+ \ echo "Foo" |
+ \ echo "Bar"
+
+command!
+ "\ comment
+ \ -addr=lines
+ \ -bang
+ "\ comment
+ "\ comment
+ \ -bar
+ \ -buffer
+ "\ comment
+ \ -complete=buffer
+ "\ comment
+ \ -count
+ "\ comment
+ \ -nargs=*
+ "\ comment
+ \ -range
+ "\ comment
+ \ -register
+ "\ comment
+ \ -keepscript
+ "\ comment
+ \ Foo
+ "\ comment
+ \ echo "Foo" |
+ "\ comment
+ \ echo "Bar"
+
+
+" Errors
+
+command! -badattr=arguments -bang -badattr -nargs=* Foo echo "Foo"
+
+
+" Delete
+
+delcommand Foo
+delcommand -buffer Foo
+
+delcommand Foo | echo "Foo"
+delcommand -buffer Foo | echo "Foo"
+
+delcommand Foo " comment
+delcommand -buffer Foo " comment
+
+comclear
+comclear " comment
+comclear | echo "Foo"
+
+
+" Issue #14135 (mnv.mnv syntax highlighting broken wrt system())
+
+com Foo call system('ls')
+
+
+" Issue #17001 (Wrong mnvUserCmdAttrError highlighting in mnv.mnv)
+
+command! -bang -nargs=* -complete=file Make AsyncRun -program=make @ <args>
+
+
+" Issue #17326 (syntax highlighting breaks with complex :s comamnd)
+
+command -range=% -nargs=? -bang Tb {
+ if "<bang>" == "!"
+ :<line1>,<line2>s/\v"[^"]*"/\=substitute(submatch(0), " ", "•", "g")/ge
+ endif
+ if "<args>" == ""
+ :<line1>,<line2>!column -t
+ else
+ :<line1>,<line2>!column -t -s'<args>'
+ endif
+ if "<bang>" == "!"
+ :<line1>,<line2>s/•/ /ge
+ endif
+}
+
+command -range=% -nargs=? -bang Tb :<line1>,<line2>s/\v"[^"]*"/\=substitute(submatch(0), " ", "•", "g")/ge
+
+
+" Unreported issue (:map with trailing bar in replacement text)
+
+command! Foo
+ \ map lhs rhs |
+ \ abbreviate foo bar |
+ \ echo "Foo"
+
+
+" Issue #18414 (Syntax group mnvUserCmdReplacement lacking a keepend?)
+
+def MNV9Context()
+ command! MyFunction MyFunc()
+ # I am a comment
+
+ command! ToggleWrap setlocal wrap!
+ # I am a comment but I didn't get highlighted
+enddef
+
+command! MyFunction call MyFunc()
+" I am a comment
+
+command! ToggleWrap setlocal wrap!
+" I am a comment but I didn't get highlighted
+
+
+" Issue #18448 (comment for subsequent command is not highlighted)
+
+def MNV9Context()
+ command! -nargs=1 -complete=file Rg :term rg <args>
+ # command! -nargs=1 -complete=file Rg :term ++shell rg <args>
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_command_modifiers.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_command_modifiers.mnv
new file mode 100644
index 0000000000..5c4443a667
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_command_modifiers.mnv
@@ -0,0 +1,135 @@
+" MNV Ex command modifiers
+
+
+ aboveleft echo "Foo"
+
+aboveleft echo "Foo"
+belowright echo "Foo"
+botright echo "Foo"
+browse echo "Foo"
+confirm echo "Foo"
+filter /pattern/ echo "Foo"
+filter! /pattern/ echo "Foo"
+hide echo "Foo"
+horizontal echo "Foo"
+keepalt echo "Foo"
+keepjumps echo "Foo"
+keepmarks echo "Foo"
+keeppatterns echo "Foo"
+leftabove echo "Foo"
+legacy echo "Foo"
+lockmarks echo "Foo"
+noautocmd echo "Foo"
+noswapfile echo "Foo"
+rightbelow echo "Foo"
+sandbox echo "Foo"
+silent echo "Foo"
+silent! echo "Foo"
+tab echo "Foo"
+topleft echo "Foo"
+unsilent echo "Foo"
+verbose echo "Foo"
+vertical echo "Foo"
+mnv9cmd echo "Foo"
+
+
+: aboveleft echo "Foo"
+ " FIXME: not a ternary operator ':'
+ : aboveleft echo "Foo"
+ :aboveleft echo "Foo"
+
+:aboveleft echo "Foo"
+:belowright echo "Foo"
+:botright echo "Foo"
+:browse echo "Foo"
+:confirm echo "Foo"
+:filter /pattern/ echo "Foo"
+:filter! /pattern/ echo "Foo"
+:hide echo "Foo"
+:horizontal echo "Foo"
+:keepalt echo "Foo"
+:keepjumps echo "Foo"
+:keepmarks echo "Foo"
+:keeppatterns echo "Foo"
+:leftabove echo "Foo"
+:legacy echo "Foo"
+:lockmarks echo "Foo"
+:noautocmd echo "Foo"
+:noswapfile echo "Foo"
+:rightbelow echo "Foo"
+:sandbox echo "Foo"
+:silent echo "Foo"
+:silent! echo "Foo"
+:tab echo "Foo"
+:topleft echo "Foo"
+:unsilent echo "Foo"
+:verbose echo "Foo"
+:vertical echo "Foo"
+:mnv9cmd echo "Foo"
+
+
+echo|aboveleft echo "Foo"
+echo| aboveleft echo "Foo"
+echo |aboveleft echo "Foo"
+
+echo | aboveleft echo "Foo"
+echo | belowright echo "Foo"
+echo | botright echo "Foo"
+echo | browse echo "Foo"
+echo | confirm echo "Foo"
+echo | filter /pattern/ echo "Foo"
+echo | filter! /pattern/ echo "Foo"
+echo | hide echo "Foo"
+echo | horizontal echo "Foo"
+echo | keepalt echo "Foo"
+echo | keepjumps echo "Foo"
+echo | keepmarks echo "Foo"
+echo | keeppatterns echo "Foo"
+echo | leftabove echo "Foo"
+echo | legacy echo "Foo"
+echo | lockmarks echo "Foo"
+echo | noautocmd echo "Foo"
+echo | noswapfile echo "Foo"
+echo | rightbelow echo "Foo"
+echo | sandbox echo "Foo"
+echo | silent echo "Foo"
+echo | silent! echo "Foo"
+echo | tab echo "Foo"
+echo | topleft echo "Foo"
+echo | unsilent echo "Foo"
+echo | verbose echo "Foo"
+echo | vertical echo "Foo"
+echo | mnv9cmd echo "Foo"
+
+
+aboveleft belowright botright browse confirm filter /pattern/ filter! /pattern/ hide horizontal keepalt keepjumps keepmarks keeppatterns leftabove legacy lockmarks noautocmd noswapfile rightbelow sandbox silent silent! tab topleft unsilent verbose vertical mnv9cmd echo "Foo"
+aboveleft
+ \ belowright
+ \ botright
+ \ browse
+ \ confirm
+ \ filter /pattern/
+ \ filter! /pattern/
+ \ hide
+ \ horizontal
+ \ keepalt
+ \ keepjumps
+ \ keepmarks
+ \ keeppatterns
+ \ leftabove
+ \ legacy
+ \ lockmarks
+ \ noautocmd
+ \ noswapfile
+ \ rightbelow
+ \ sandbox
+ \ silent
+ \ silent!
+ \ tab
+ \ topleft
+ \ unsilent
+ \ verbose
+ \ vertical
+ \ mnv9cmd
+ \ echo "Foo"
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_commands.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_commands.mnv
new file mode 100644
index 0000000000..a573f6a4b1
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_commands.mnv
@@ -0,0 +1,1210 @@
+" Ex commands
+
+
+" START NOT MATCHED
+:Next
+:Print
+:X
+" END NOT MATCHED
+
+:help
+ :help
+: help
+ : help # FIXME
+
+:@
+
+:append
+ text
+.
+:abbreviate
+:abclear
+:aboveleft
+:all
+:amenu
+:anoremenu
+:args
+:argadd
+:argdedupe
+:argdelete
+:argedit
+:argdo
+:argglobal
+:arglocal
+:argument
+:ascii
+:autocmd
+:augroup Foo
+:augroup END
+:aunmenu
+:buffer
+:bNext
+:ball
+:badd
+:balt
+:bdelete
+:behave mswin
+:behave xterm
+:belowright
+:bfirst
+:blast
+:bmodified
+:bnext
+:botright
+:bprevious
+:brewind
+:break
+:breakadd
+:breakdel
+:breaklist
+:browse
+:bufdo
+:buffers
+:bunload
+:bwipeout
+:change
+ text
+.
+:cNext
+:cNfile
+:cabbrev
+:cabclear
+:cabove
+:caddbuffer
+:caddexpr
+:caddfile
+:cafter
+:call
+:catch
+:cbefore
+:cbelow
+:cbottom
+:cbuffer
+:cc
+:cclose
+:cd
+:cdo
+:cfdo
+:center
+:cexpr
+:cfile
+:cfirst
+:cgetbuffer
+:cgetexpr
+:cgetfile
+:changes
+:chdir
+:checkpath
+:checktime
+:chistory
+:clast
+:clearjumps
+:clist
+:close
+:cmap
+:cmapclear
+:cmenu
+:cnext
+:cnewer
+:cnfile
+:cnoremap
+:cnoreabbrev
+:cnoremenu
+:copy
+:colder
+:colorscheme
+:command
+:comclear
+:compiler
+:continue
+:confirm
+:const
+:copen
+:cprevious
+:cpfile
+:cquit
+:crewind
+:cscope
+:cstag
+:cunmap
+:cunabbrev
+:cunmenu
+:cwindow
+:delete
+:debug
+:debuggreedy
+:def
+:defcompile
+:defer
+:delcommand
+:delfunction
+:delmarks
+:diffupdate
+:diffget
+:diffoff
+:diffpatch
+:diffput
+:diffsplit
+:diffthis
+:digraphs
+:display
+:disassemble
+:djump
+:dl
+:dlist
+:doautocmd
+:doautoall
+:dp
+:drop
+:dsearch
+:dsplit
+:edit
+:earlier
+:echo
+:echoconsole
+:echoerr
+:echohl
+:echomsg
+:echon
+:echowindow
+:else
+:elseif
+:emenu
+:enddef
+:endif
+:endfor
+:endfunction
+:endtry
+:endwhile
+:enew
+:eval
+:ex
+:execute
+:exit
+:exusage
+:file
+:files
+:filetype
+:filter
+:find
+:final
+:finally
+:finish
+:first
+:fixdel
+:fold
+:foldclose
+:folddoopen
+:folddoclosed
+:foldopen
+:for foo in bar | endfor
+:function
+:global/.../
+:goto
+:grep
+:grepadd
+:gui
+:gmnv
+:hardcopy
+:help
+:helpclose
+:helpfind
+:helpgrep
+:helptags
+:highlight
+:hide
+:history
+:horizontal
+:insert
+ text
+.
+:iabbrev
+:iabclear
+:if
+:ijump
+:ilist
+:imap
+:imapclear
+:imenu
+:import
+:inoremap
+:inoreabbrev
+:inoremenu
+:intro
+:isearch
+:isplit
+:iunmap
+:iunabbrev
+:iunmenu
+:join
+:jumps
+:k
+:keepalt
+:keepmarks
+:keepjumps
+:keeppatterns
+:lNext
+:lNfile
+:list
+:labove
+:laddexpr
+:laddbuffer
+:laddfile
+:lafter
+:last
+:language
+:later
+:lbefore
+:lbelow
+:lbottom
+:lbuffer
+:lcd
+:lchdir
+:lclose
+:lcscope
+:ldo
+:lfdo
+:left
+:leftabove
+:legacy
+:let
+:lexpr
+:lfile
+:lfirst
+:lgetbuffer
+:lgetexpr
+:lgetfile
+:lgrep
+:lgrepadd
+:lhelpgrep
+:lhistory
+:ll
+:llast
+:llist
+:lmake
+:lmap
+:lmapclear
+:lnext
+:lnewer
+:lnfile
+:lnoremap
+" :loadkeymap " disabled - runs until EOF
+:loadview
+:lockmarks
+:lockvar
+:lolder
+:lopen
+:lprevious
+:lpfile
+:lrewind
+:ls
+:ltag
+:lunmap
+:lua
+:luado
+:luafile
+:lmnvgrep
+:lmnvgrepadd
+:lwindow
+:move
+:mark
+:make
+:map
+:mapclear
+:marks
+:match
+:menu
+:menutranslate
+:messages
+:mkexrc
+:mksession
+:mkspell
+:mkmnvrc
+:mkview
+:mode
+:mzscheme
+:mzfile
+:nbclose
+:nbkey
+:nbstart
+:next
+:new
+:nmap
+:nmapclear
+:nmenu
+:nnoremap
+:nnoremenu
+:noautocmd
+:noremap
+:nohlsearch
+:noreabbrev
+:noremenu
+:normal
+:noswapfile
+:number
+:nunmap
+:nunmenu
+:oldfiles
+:open
+:omap
+:omapclear
+:omenu
+:only
+:onoremap
+:onoremenu
+:options
+:ounmap
+:ounmenu
+:ownsyntax
+:packadd
+:packloadall
+:pclose
+:pedit
+:perl
+:print
+:profdel
+:profile
+:promptfind
+:promptrepl
+:perldo
+:pop
+:popup
+:ppop
+:preserve
+:previous
+:psearch
+:ptag
+:ptNext
+:ptfirst
+:ptjump
+:ptlast
+:ptnext
+:ptprevious
+:ptrewind
+:ptselect
+:put
+:pwd
+:py3
+:python3
+:py3do
+:py3file
+:python
+:pydo
+:pyfile
+:pyx
+:pythonx
+:pyxdo
+:pyxfile
+:quit
+:quitall
+:qall
+:read
+:recover
+:redo
+:redir
+:redraw
+:redrawstatus
+:redrawtabline
+:registers
+:resize
+:retab
+:return
+:rewind
+:right
+:rightbelow
+:ruby
+:rubydo
+:rubyfile
+:rundo
+:runtime
+:rmnvinfo
+:substitute
+:sNext
+:sandbox
+:sargument
+:sall
+:saveas
+:sbuffer
+:sbNext
+:sball
+:sbfirst
+:sblast
+:sbmodified
+:sbnext
+:sbprevious
+:sbrewind
+:scriptnames
+:scriptencoding
+:scriptversion
+:scscope
+:set
+:setfiletype
+:setglobal
+:setlocal
+:sfind
+:sfirst
+:shell
+:simalt
+:sign
+:silent
+:sleep
+:sleep!
+:slast
+:smagic
+:smap
+:smapclear
+:smenu
+:smile
+:snext
+:snomagic
+:snoremap
+:snoremenu
+:sort
+:source
+:spelldump
+:spellgood
+:spellinfo
+:spellrare
+:spellrepall
+:spellundo
+:spellwrong
+:split
+:sprevious
+:srewind
+:stop
+:stag
+:startinsert
+:startgreplace
+:startreplace
+:stopinsert
+:stjump
+:stselect
+:sunhide
+:sunmap
+:sunmenu
+:suspend
+:sview
+:swapname
+:syntax
+:syntime
+:syncbind
+:t
+:tNext
+:tabNext
+:tabclose
+:tabdo
+:tabedit
+:tabfind
+:tabfirst
+:tablast
+:tabmove
+:tabnew
+:tabnext
+:tabonly
+:tabprevious
+:tabrewind
+:tabs
+:tab
+:tag
+:tags
+:tcd
+:tchdir
+:tcl
+:tcldo
+:tclfile
+:tearoff
+:terminal
+:tfirst
+:throw
+:tjump
+:tlast
+:tlmenu
+:tlnoremenu
+:tlunmenu
+:tmapclear
+:tmap
+:tmenu
+:tnext
+:tnoremap
+:topleft
+:tprevious
+:trewind
+:try
+:tselect
+:tunmap
+:tunmenu
+:undo
+:undojoin
+:undolist
+:unabbreviate
+:unabbreviate
+:unhide
+:uniq
+:unlet
+:unlockvar
+:unmap
+:unmenu
+:unsilent
+:update
+:vglobal/.../
+:version
+:verbose
+:vertical
+:mnv9cmd
+:mnvgrep
+:mnvgrepadd
+:visual
+:viusage
+:view
+:vmap
+:vmapclear
+:vmenu
+:vnew
+:vnoremap
+:vnoremenu
+:vsplit
+:vunmap
+:vunmenu
+:windo
+:write
+:wNext
+:wall
+:while
+:winsize
+:wincmd
+:winpos
+:wnext
+:wprevious
+:wq
+:wqall
+:wundo
+:wmnvinfo
+:xit
+:xall
+:xmapclear
+:xmap
+:xmenu
+:xrestore
+:xnoremap
+:xnoremenu
+:xunmap
+:xunmenu
+:yank
+:z
+
+call Foo()|help
+call Foo() | help
+call Foo() |help
+call Foo()| help
+
+" FIXME
+call Foo() | append
+ text
+.
+call Foo() | abbreviate
+call Foo() | abclear
+call Foo() | aboveleft
+call Foo() | all
+call Foo() | amenu
+call Foo() | anoremenu
+call Foo() | args
+call Foo() | argadd
+call Foo() | argdedupe
+call Foo() | argdelete
+call Foo() | argedit
+call Foo() | argdo
+call Foo() | argglobal
+call Foo() | arglocal
+call Foo() | argument
+call Foo() | ascii
+call Foo() | autocmd
+call Foo() | augroup Foo | augroup END
+call Foo() | aunmenu
+call Foo() | buffer
+call Foo() | bNext
+call Foo() | ball
+call Foo() | badd
+call Foo() | balt
+call Foo() | bdelete
+call Foo() | behave mswin
+call Foo() | behave xterm
+call Foo() | belowright
+call Foo() | bfirst
+call Foo() | blast
+call Foo() | bmodified
+call Foo() | bnext
+call Foo() | botright
+call Foo() | bprevious
+call Foo() | brewind
+call Foo() | break
+call Foo() | breakadd
+call Foo() | breakdel
+call Foo() | breaklist
+call Foo() | browse
+call Foo() | bufdo
+call Foo() | buffers
+call Foo() | bunload
+call Foo() | bwipeout
+" FIXME
+call Foo() | change
+ text
+.
+call Foo() | cNext
+call Foo() | cNfile
+call Foo() | cabbrev
+call Foo() | cabclear
+call Foo() | cabove
+call Foo() | caddbuffer
+call Foo() | caddexpr
+call Foo() | caddfile
+call Foo() | cafter
+call Foo() | call
+call Foo() | catch
+call Foo() | cbefore
+call Foo() | cbelow
+call Foo() | cbottom
+call Foo() | cbuffer
+call Foo() | cc
+call Foo() | cclose
+call Foo() | cd
+call Foo() | cdo
+call Foo() | cfdo
+call Foo() | center
+call Foo() | cexpr
+call Foo() | cfile
+call Foo() | cfirst
+call Foo() | cgetbuffer
+call Foo() | cgetexpr
+call Foo() | cgetfile
+call Foo() | changes
+call Foo() | chdir
+call Foo() | checkpath
+call Foo() | checktime
+call Foo() | chistory
+call Foo() | clast
+call Foo() | clearjumps
+call Foo() | clist
+call Foo() | close
+call Foo() | cmap
+call Foo() | cmapclear
+call Foo() | cmenu
+call Foo() | cnext
+call Foo() | cnewer
+call Foo() | cnfile
+call Foo() | cnoremap
+call Foo() | cnoreabbrev
+call Foo() | cnoremenu
+call Foo() | copy
+call Foo() | colder
+call Foo() | colorscheme
+call Foo() | command
+call Foo() | comclear
+call Foo() | compiler
+call Foo() | continue
+call Foo() | confirm
+call Foo() | const
+call Foo() | copen
+call Foo() | cprevious
+call Foo() | cpfile
+call Foo() | cquit
+call Foo() | crewind
+call Foo() | cscope
+call Foo() | cstag
+call Foo() | cunmap
+call Foo() | cunabbrev
+call Foo() | cunmenu
+call Foo() | cwindow
+call Foo() | delete
+call Foo() | debug
+call Foo() | debuggreedy
+call Foo() | def
+call Foo() | defcompile
+call Foo() | defer
+call Foo() | delcommand
+call Foo() | delfunction
+call Foo() | delmarks
+call Foo() | diffupdate
+call Foo() | diffget
+call Foo() | diffoff
+call Foo() | diffpatch
+call Foo() | diffput
+call Foo() | diffsplit
+call Foo() | diffthis
+call Foo() | digraphs
+call Foo() | display
+call Foo() | disassemble
+call Foo() | djump
+call Foo() | dl
+call Foo() | dlist
+call Foo() | doautocmd
+call Foo() | doautoall
+call Foo() | dp
+call Foo() | drop
+call Foo() | dsearch
+call Foo() | dsplit
+call Foo() | edit
+call Foo() | earlier
+call Foo() | echo
+call Foo() | echoconsole
+call Foo() | echoerr
+call Foo() | echohl
+call Foo() | echomsg
+call Foo() | echon
+call Foo() | echowindow
+call Foo() | else
+call Foo() | elseif
+call Foo() | emenu
+call Foo() | enddef
+call Foo() | endif
+call Foo() | endfor
+call Foo() | endfunction
+call Foo() | endtry
+call Foo() | endwhile
+call Foo() | enew
+call Foo() | eval
+call Foo() | ex
+call Foo() | execute
+call Foo() | exit
+call Foo() | exusage
+call Foo() | file
+call Foo() | files
+call Foo() | filetype
+call Foo() | filter
+call Foo() | find
+call Foo() | final
+call Foo() | finally
+call Foo() | finish
+call Foo() | first
+call Foo() | fixdel
+call Foo() | fold
+call Foo() | foldclose
+call Foo() | folddoopen
+call Foo() | folddoclosed
+call Foo() | foldopen
+call Foo() | for foo in bar | endfor
+call Foo() | function
+call Foo() | global/.../
+call Foo() | goto
+call Foo() | grep
+call Foo() | grepadd
+call Foo() | gui
+call Foo() | gmnv
+call Foo() | hardcopy
+call Foo() | help
+call Foo() | helpclose
+call Foo() | helpfind
+call Foo() | helpgrep
+call Foo() | helptags
+call Foo() | highlight
+call Foo() | hide
+call Foo() | history
+call Foo() | horizontal
+" FIXME
+call Foo() | insert
+ text
+.
+call Foo() | iabbrev
+call Foo() | iabclear
+call Foo() | if
+call Foo() | ijump
+call Foo() | ilist
+call Foo() | imap
+call Foo() | imapclear
+call Foo() | imenu
+call Foo() | import
+call Foo() | inoremap
+call Foo() | inoreabbrev
+call Foo() | inoremenu
+call Foo() | intro
+call Foo() | isearch
+call Foo() | isplit
+call Foo() | iunmap
+call Foo() | iunabbrev
+call Foo() | iunmenu
+call Foo() | join
+call Foo() | jumps
+call Foo() | k
+call Foo() | keepalt
+call Foo() | keepmarks
+call Foo() | keepjumps
+call Foo() | keeppatterns
+call Foo() | lNext
+call Foo() | lNfile
+call Foo() | list
+call Foo() | labove
+call Foo() | laddexpr
+call Foo() | laddbuffer
+call Foo() | laddfile
+call Foo() | lafter
+call Foo() | last
+call Foo() | language
+call Foo() | later
+call Foo() | lbefore
+call Foo() | lbelow
+call Foo() | lbottom
+call Foo() | lbuffer
+call Foo() | lcd
+call Foo() | lchdir
+call Foo() | lclose
+call Foo() | lcscope
+call Foo() | ldo
+call Foo() | lfdo
+call Foo() | left
+call Foo() | leftabove
+call Foo() | legacy
+call Foo() | let
+call Foo() | lexpr
+call Foo() | lfile
+call Foo() | lfirst
+call Foo() | lgetbuffer
+call Foo() | lgetexpr
+call Foo() | lgetfile
+call Foo() | lgrep
+call Foo() | lgrepadd
+call Foo() | lhelpgrep
+call Foo() | lhistory
+call Foo() | ll
+call Foo() | llast
+call Foo() | llist
+call Foo() | lmake
+call Foo() | lmap
+call Foo() | lmapclear
+call Foo() | lnext
+call Foo() | lnewer
+call Foo() | lnfile
+call Foo() | lnoremap
+" call Foo() | loadkeymap " disabled - runs until EOF
+call Foo() | loadview
+call Foo() | lockmarks
+call Foo() | lockvar
+call Foo() | lolder
+call Foo() | lopen
+call Foo() | lprevious
+call Foo() | lpfile
+call Foo() | lrewind
+call Foo() | ls
+call Foo() | ltag
+call Foo() | lunmap
+call Foo() | lua
+call Foo() | luado
+call Foo() | luafile
+call Foo() | lmnvgrep
+call Foo() | lmnvgrepadd
+call Foo() | lwindow
+call Foo() | move
+call Foo() | mark
+call Foo() | make
+call Foo() | map
+call Foo() | mapclear
+call Foo() | marks
+call Foo() | match
+call Foo() | menu
+call Foo() | menutranslate
+call Foo() | messages
+call Foo() | mkexrc
+call Foo() | mksession
+call Foo() | mkspell
+call Foo() | mkmnvrc
+call Foo() | mkview
+call Foo() | mode
+call Foo() | mzscheme
+call Foo() | mzfile
+call Foo() | nbclose
+call Foo() | nbkey
+call Foo() | nbstart
+call Foo() | next
+call Foo() | new
+call Foo() | nmap
+call Foo() | nmapclear
+call Foo() | nmenu
+call Foo() | nnoremap
+call Foo() | nnoremenu
+call Foo() | noautocmd
+call Foo() | noremap
+call Foo() | nohlsearch
+call Foo() | noreabbrev
+call Foo() | noremenu
+call Foo() | normal
+call Foo() | noswapfile
+call Foo() | number
+call Foo() | nunmap
+call Foo() | nunmenu
+call Foo() | oldfiles
+call Foo() | open
+call Foo() | omap
+call Foo() | omapclear
+call Foo() | omenu
+call Foo() | only
+call Foo() | onoremap
+call Foo() | onoremenu
+call Foo() | options
+call Foo() | ounmap
+call Foo() | ounmenu
+call Foo() | ownsyntax
+call Foo() | packadd
+call Foo() | packloadall
+call Foo() | pclose
+call Foo() | pedit
+call Foo() | perl
+call Foo() | print
+call Foo() | profdel
+call Foo() | profile
+call Foo() | promptfind
+call Foo() | promptrepl
+call Foo() | perldo
+call Foo() | pop
+call Foo() | popup
+call Foo() | ppop
+call Foo() | preserve
+call Foo() | previous
+call Foo() | psearch
+call Foo() | ptag
+call Foo() | ptNext
+call Foo() | ptfirst
+call Foo() | ptjump
+call Foo() | ptlast
+call Foo() | ptnext
+call Foo() | ptprevious
+call Foo() | ptrewind
+call Foo() | ptselect
+call Foo() | put
+call Foo() | pwd
+call Foo() | py3
+call Foo() | python3
+call Foo() | py3do
+call Foo() | py3file
+call Foo() | python
+call Foo() | pydo
+call Foo() | pyfile
+call Foo() | pyx
+call Foo() | pythonx
+call Foo() | pyxdo
+call Foo() | pyxfile
+call Foo() | quit
+call Foo() | quitall
+call Foo() | qall
+call Foo() | read
+call Foo() | recover
+call Foo() | redo
+call Foo() | redir
+call Foo() | redraw
+call Foo() | redrawstatus
+call Foo() | redrawtabline
+call Foo() | registers
+call Foo() | resize
+call Foo() | retab
+call Foo() | return
+call Foo() | rewind
+call Foo() | right
+call Foo() | rightbelow
+call Foo() | ruby
+call Foo() | rubydo
+call Foo() | rubyfile
+call Foo() | rundo
+call Foo() | runtime
+call Foo() | rmnvinfo
+call Foo() | substitute
+call Foo() | sNext
+call Foo() | sandbox
+call Foo() | sargument
+call Foo() | sall
+call Foo() | saveas
+call Foo() | sbuffer
+call Foo() | sbNext
+call Foo() | sball
+call Foo() | sbfirst
+call Foo() | sblast
+call Foo() | sbmodified
+call Foo() | sbnext
+call Foo() | sbprevious
+call Foo() | sbrewind
+call Foo() | scriptnames
+call Foo() | scriptencoding
+call Foo() | scriptversion
+call Foo() | scscope
+call Foo() | set
+call Foo() | setfiletype
+call Foo() | setglobal
+call Foo() | setlocal
+call Foo() | sfind
+call Foo() | sfirst
+call Foo() | shell
+call Foo() | simalt
+call Foo() | sign
+call Foo() | silent
+call Foo() | sleep
+call Foo() | sleep!
+call Foo() | slast
+call Foo() | smagic
+call Foo() | smap
+call Foo() | smapclear
+call Foo() | smenu
+call Foo() | smile
+call Foo() | snext
+call Foo() | snomagic
+call Foo() | snoremap
+call Foo() | snoremenu
+call Foo() | sort
+call Foo() | source
+call Foo() | spelldump
+call Foo() | spellgood
+call Foo() | spellinfo
+call Foo() | spellrare
+call Foo() | spellrepall
+call Foo() | spellundo
+call Foo() | spellwrong
+call Foo() | split
+call Foo() | sprevious
+call Foo() | srewind
+call Foo() | stop
+call Foo() | stag
+call Foo() | startinsert
+call Foo() | startgreplace
+call Foo() | startreplace
+call Foo() | stopinsert
+call Foo() | stjump
+call Foo() | stselect
+call Foo() | sunhide
+call Foo() | sunmap
+call Foo() | sunmenu
+call Foo() | suspend
+call Foo() | sview
+call Foo() | swapname
+call Foo() | syntax
+call Foo() | syntime
+call Foo() | syncbind
+call Foo() | t
+call Foo() | tNext
+call Foo() | tabNext
+call Foo() | tabclose
+call Foo() | tabdo
+call Foo() | tabedit
+call Foo() | tabfind
+call Foo() | tabfirst
+call Foo() | tablast
+call Foo() | tabmove
+call Foo() | tabnew
+call Foo() | tabnext
+call Foo() | tabonly
+call Foo() | tabprevious
+call Foo() | tabrewind
+call Foo() | tabs
+call Foo() | tab
+call Foo() | tag
+call Foo() | tags
+call Foo() | tcd
+call Foo() | tchdir
+call Foo() | tcl
+call Foo() | tcldo
+call Foo() | tclfile
+call Foo() | tearoff
+call Foo() | terminal
+call Foo() | tfirst
+call Foo() | throw
+call Foo() | tjump
+call Foo() | tlast
+call Foo() | tlmenu
+call Foo() | tlnoremenu
+call Foo() | tlunmenu
+call Foo() | tmapclear
+call Foo() | tmap
+call Foo() | tmenu
+call Foo() | tnext
+call Foo() | tnoremap
+call Foo() | topleft
+call Foo() | tprevious
+call Foo() | trewind
+call Foo() | try
+call Foo() | tselect
+call Foo() | tunmap
+call Foo() | tunmenu
+call Foo() | undo
+call Foo() | undojoin
+call Foo() | undolist
+call Foo() | unabbreviate
+call Foo() | unabbreviate
+call Foo() | unhide
+call Foo() | uniq
+call Foo() | unlet
+call Foo() | unlockvar
+call Foo() | unmap
+call Foo() | unmenu
+call Foo() | unsilent
+call Foo() | update
+call Foo() | vglobal/.../
+call Foo() | version
+call Foo() | verbose
+call Foo() | vertical
+call Foo() | mnv9cmd
+call Foo() | mnvgrep
+call Foo() | mnvgrepadd
+call Foo() | visual
+call Foo() | viusage
+call Foo() | view
+call Foo() | vmap
+call Foo() | vmapclear
+call Foo() | vmenu
+call Foo() | vnew
+call Foo() | vnoremap
+call Foo() | vnoremenu
+call Foo() | vsplit
+call Foo() | vunmap
+call Foo() | vunmenu
+call Foo() | windo
+call Foo() | write
+call Foo() | wNext
+call Foo() | wall
+call Foo() | while
+call Foo() | winsize
+call Foo() | wincmd
+call Foo() | winpos
+call Foo() | wnext
+call Foo() | wprevious
+call Foo() | wq
+call Foo() | wqall
+call Foo() | wundo
+call Foo() | wmnvinfo
+call Foo() | xit
+call Foo() | xall
+call Foo() | xmapclear
+call Foo() | xmap
+call Foo() | xmenu
+call Foo() | xrestore
+call Foo() | xnoremap
+call Foo() | xnoremenu
+call Foo() | xunmap
+call Foo() | xunmenu
+call Foo() | yank
+call Foo() | z
+
+
+" MNV9-script only
+
+:abstract
+:class
+:endclass
+:endinterface
+:endenum
+:enum
+:export
+:final
+:interface
+:public
+:static
+:type
+:var
+
+Foo() | abstract
+Foo() | class
+Foo() | endclass
+Foo() | endenum
+Foo() | endinterface
+Foo() | enum
+Foo() | export
+Foo() | final
+Foo() | interface
+Foo() | public
+Foo() | static
+Foo() | type
+Foo() | var
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_debug.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_debug.mnv
new file mode 100644
index 0000000000..cf6b71e85e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_debug.mnv
@@ -0,0 +1,13 @@
+" MNV :debug command
+
+
+debug echo "..."
+
+function Foo()
+ debug echo "..."
+endfunction
+
+def Bar()
+ debug echo "..."
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_debuggreedy.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_debuggreedy.mnv
new file mode 100644
index 0000000000..3a0f9cf35d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_debuggreedy.mnv
@@ -0,0 +1,34 @@
+" MNV :debuggreedy command
+
+
+debuggreedy
+0debuggreedy
+
+debuggreedy " comment
+0debuggreedy " comment
+
+debuggreedy | echo "Foo"
+0debuggreedy | echo "Foo"
+
+function Foo()
+ debuggreedy
+ 0debuggreedy
+
+ debuggreedy " comment
+ 0debuggreedy " comment
+
+ debuggreedy | echo "Foo"
+ 0debuggreedy | echo "Foo"
+endfunction
+
+def Bar()
+ debuggreedy
+ 0debuggreedy
+
+ debuggreedy # comment
+ 0debuggreedy # comment
+
+ debuggreedy | echo "Foo"
+ 0debuggreedy | echo "Foo"
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_def.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_def.mnv
new file mode 100644
index 0000000000..c4d29ba1be
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_def.mnv
@@ -0,0 +1,126 @@
+" MNV :def command
+
+
+" List
+
+def
+def Foo
+def /Foo.*
+
+def | echo "Foo"
+def " comment
+def Foo | echo "Foo"
+def Foo " comment
+
+
+" Definition
+
+" empty definition
+def Foo()
+enddef
+
+def Foo(): number
+ return 42
+enddef
+
+" trailing whitespace
+def Foo(): number
+ return 42
+enddef
+
+def Foo() # comment
+enddef
+
+def Foo(): number # comment
+ return 42
+enddef
+
+def! Foo(): number
+ return 42
+enddef
+
+def g:Foo(): number
+ return 42
+enddef
+
+def s:Foo(): number
+ return 42
+enddef
+
+def <SID>Foo(): number
+ return 42
+enddef
+
+def foo#bar#Foo(): number
+ return 42
+enddef
+
+" same name as an Ex command
+def s:ls()
+enddef
+
+
+" Return types
+
+def Foo(): void
+enddef
+
+def Foo(): void # comment
+enddef
+
+def Foo(): list<dict<number>>
+enddef
+
+def Foo(): func(dict<list<number>>, func, bool, func(number, list<number>)): bool
+enddef
+
+
+" :enddef trailing
+
+def Foo()
+ # trailing whitespace
+enddef
+
+def Foo()
+enddef | echo "Foo"
+
+def Foo()
+enddef # comment
+
+
+" Parameters
+
+def Foo(x: bool, y = 42, z: string = "zed")
+enddef
+
+def Foo(
+ x: bool,
+ y = 42,
+ z: string = "zed")
+enddef
+
+" Issue #16243 (MNV script def parameters syntax highlight is wrong)
+
+def Test(lines: list<number> = [line('.'), line('.')]): void
+enddef
+
+
+" Comments
+
+def Foo()
+ # MNV9-script comment
+ "useless string"
+enddef
+
+
+" Leading command separator
+
+echo "Foo" | def Foo()
+enddef
+
+
+" Command modifiers
+
+silent! def Foo()
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_def_fold.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_def_fold.mnv
new file mode 100644
index 0000000000..30e6b4ae71
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_def_fold.mnv
@@ -0,0 +1,185 @@
+" MNV :def command
+" MNV_TEST_SETUP let g:mnvsyn_folding = "f"
+" MNV_TEST_SETUP setl fdc=2 fdl=999 fdm=syntax
+
+
+" List
+
+def
+def Foo
+def /Foo.*
+
+def | echo "Foo"
+def " comment
+def Foo | echo "Foo"
+def Foo " comment
+
+
+" Definition
+
+" empty definition
+def Foo()
+enddef
+
+def Foo(): number
+ return 42
+enddef
+
+" trailing whitespace
+def Foo(): number
+ return 42
+enddef
+
+def Foo() # comment
+enddef
+
+def Foo(): number # comment
+ return 42
+enddef
+
+def! Foo(): number
+ return 42
+enddef
+
+def g:Foo(): number
+ return 42
+enddef
+
+def s:Foo(): number
+ return 42
+enddef
+
+def <SID>Foo(): number
+ return 42
+enddef
+
+def foo#bar#Foo(): number
+ return 42
+enddef
+
+" same name as an Ex command
+def s:ls()
+enddef
+
+
+" Return types
+
+def Foo(): void
+enddef
+
+def Foo(): void # comment
+enddef
+
+def Foo(): list<dict<number>>
+enddef
+
+def Foo(): func(dict<list<number>>, func, bool, func(number, list<number>)): bool
+enddef
+
+
+" :enddef trailing
+
+def Foo()
+ # trailing whitespace
+enddef
+
+def Foo()
+enddef | echo "Foo"
+
+def Foo()
+enddef # comment
+
+
+" Parameters
+
+def Foo(x: bool, y = 42, z: string = "zed")
+enddef
+
+def Foo(
+ x: bool,
+ y = 42,
+ z: string = "zed")
+enddef
+
+
+" Comments
+
+def Foo()
+ # MNV9-script comment
+ "useless string"
+enddef
+
+
+" Command modifiers
+
+silent! def Foo()
+enddef
+
+
+" Leading command separator
+
+echo "Foo" | def Foo()
+enddef
+
+
+" Fold-region ending
+
+def Foo()
+ # enddef
+enddef
+
+def Foo()
+ echo "enddef"
+enddef
+
+def Foo()
+ var x =<< trim END
+ endfunction
+ END
+enddef
+
+:def Foo()
+:enddef
+
+
+" Issue #15671
+" No recognition of :fun or :def bodies commencing with empty lines if
+" g:mnvsyn_folding contains "f"
+
+def MA1()
+
+
+ return
+enddef
+
+def MA2()
+ return
+enddef
+
+def MB1(): void
+
+ return
+enddef
+
+def MB2(): void
+ return
+enddef
+
+def MC1(_: any)
+
+ return
+enddef
+
+def MC2(_: any)
+ return
+enddef
+
+def MD1(_: any): void
+
+ return
+enddef
+
+def MD2(_: any): void
+ return
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_def_nested.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_def_nested.mnv
new file mode 100644
index 0000000000..18fc4bc1fb
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_def_nested.mnv
@@ -0,0 +1,23 @@
+mnv9script
+# MNV9 :def command (nested)
+# MNV_TEST_SETUP hi link mnv9This Todo
+
+
+class Test
+ const name: string
+
+ def new()
+ def Name(): string
+ function GiveName()
+ return "any"
+ endfunction
+
+ return GiveName()
+ enddef
+
+ this.name = Name()
+ enddef
+endclass
+
+echo Test.new()
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_def_nested_fold.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_def_nested_fold.mnv
new file mode 100644
index 0000000000..a1f55d0701
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_def_nested_fold.mnv
@@ -0,0 +1,25 @@
+mnv9script
+# MNV9 :def command (nested)
+# MNV_TEST_SETUP let g:mnvsyn_folding = 'f'
+# MNV_TEST_SETUP setl fdc=2 fdm=syntax
+# MNV_TEST_SETUP hi link mnv9This Todo
+
+
+class Test
+ const name: string
+
+ def new()
+ def Name(): string
+ function GiveName()
+ return "any"
+ endfunction
+
+ return GiveName()
+ enddef
+
+ this.name = Name()
+ enddef
+endclass
+
+echo Test.new()
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_def_return_type.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_def_return_type.mnv
new file mode 100644
index 0000000000..004f99c011
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_def_return_type.mnv
@@ -0,0 +1,60 @@
+mnv9script
+# MNV9 function return types
+# MNV_TEST_SETUP hi link mnvUserType Todo
+
+
+# Issue #14442 (mnv.mnv: confusion for function return types starting on another line)
+
+def TestA______________________________________________________________():
+ \ void
+enddef
+
+def TestB____(result: dict<list<number>>, fs: list<func(number): number>):
+ \ void
+enddef
+
+def TestC____(maybe: bool, F: func(): dict<func(number): number>): func():
+ \ void
+ return () => {
+ }
+enddef
+
+def TestD____(fs: list<func(): dict<func(number): bool>>): func(): func():
+ \ void
+ return () => () => {
+ }
+enddef
+
+class Tests
+ def TestA__________________________________________________________():
+ \ void
+ enddef
+
+ def TestB(result: dict<list<number>>, fs: list<func(number): number>):
+ \ void
+ enddef
+
+ def TestC(maybe: bool, F: func(): dict<func(number): number>): func():
+ \ void
+ return () => {
+ }
+ enddef
+
+ def TestD(fs: list<func(): dict<func(number): bool>>): func(): func():
+ \ void
+ return () => () => {
+ }
+ enddef
+endclass
+
+def F(G: func(number, number, number): lib.Trampoline):
+ \ func(number, number, number):
+ \ func(): lib.Trampoline
+ return ((H: func(number, number, number): lib.Trampoline) =>
+ (a1: number, a2: number, n: number) =>
+ () =>
+ H(a2, (a1 + a2), (n - 1)))(G)
+enddef
+
+defcompile
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_defer.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_defer.mnv
new file mode 100644
index 0000000000..5db0a26f0d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_defer.mnv
@@ -0,0 +1,17 @@
+" MNV :defer command
+" MNV_TEST_SETUP hi link mnvUserFunc Todo
+
+
+function Foo()
+ defer delete("tmpfile")
+ defer Delete("tmpfile")
+endfunction
+
+def Bar()
+ defer delete("tmpfile")
+ defer Delete("tmpfile")
+ defer () => {
+ echo "..."
+ }()
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_delfunction.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_delfunction.mnv
new file mode 100644
index 0000000000..910cb4502e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_delfunction.mnv
@@ -0,0 +1,34 @@
+" MNV :delfunction command
+
+
+delfunction Foo
+delfunction <SID>Foo
+delfunction foo.bar
+delfunction g:foo.bar
+delfunction s:foo.bar
+delfunction foo#bar
+delfunction g:foo#bar
+delfunction foo#bar.baz
+delfunction g:foo#bar.baz
+
+
+delfunction! Foo
+delfunction! <SID>Foo
+delfunction! foo.bar
+delfunction! g:foo.bar
+delfunction! s:foo.bar
+delfunction! foo#bar
+delfunction! g:foo#bar
+delfunction! foo#bar.baz
+delfunction! g:foo#bar.baz
+
+
+delfunction Foo | echo "Foo"
+delfunction Foo " comment
+
+
+" Issue https://github.com/Project-Tick/Project-Tick/pull/17420#issuecomment-2927798687
+" (arg named /fu%\[nction]/)
+
+silent! delfunc! func
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_do_commands.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_do_commands.mnv
new file mode 100644
index 0000000000..c327cc661e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_do_commands.mnv
@@ -0,0 +1,58 @@
+" MNV :*do commands
+
+
+argdo echo "..."
+argdo! echo "..."
+
+bufdo echo "..."
+bufdo! echo "..."
+
+cdo echo "..."
+cdo! echo "..."
+
+cfdo echo "..."
+cfdo! echo "..."
+
+folddoclosed echo "..."
+
+folddoopen echo "..."
+
+ldo echo "..."
+ldo! echo "..."
+
+lfdo echo "..."
+lfdo! echo "..."
+
+tabdo echo "..."
+
+windo echo "..."
+
+
+def MNV9Context()
+ argdo echo "..."
+ argdo! echo "..."
+
+ bufdo echo "..."
+ bufdo! echo "..."
+
+ cdo echo "..."
+ cdo! echo "..."
+
+ cfdo echo "..."
+ cfdo! echo "..."
+
+ folddoclosed echo "..."
+
+ folddoopen echo "..."
+
+ ldo echo "..."
+ ldo! echo "..."
+
+ lfdo echo "..."
+ lfdo! echo "..."
+
+ tabdo echo "..."
+
+ windo echo "..."
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_echo.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_echo.mnv
new file mode 100644
index 0000000000..7ce2b1287f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_echo.mnv
@@ -0,0 +1,58 @@
+" MNV :echo commands
+
+
+echo "Answer = " 42
+echon "Answer = " 42
+echomsg "Answer = " 42
+echowindow "Answer = " 42
+echoerr "Answer = " 42
+echoconsole "Answer = " 42
+
+
+" Trailing bar vs OR operator
+
+" OR operator
+echo foo || bar
+echo foo ||
+ \ bar
+
+" following command is :|
+echo "Foo" | |
+
+" invalid expression
+echo "Foo" ||
+
+echohl WarningMsg | echo "Don't panic!" | echohl None
+
+
+" Line continuations
+
+echo "Answer = "
+ "\ comment
+ \ 42
+
+echo
+ \ "Answer = "
+ "\ comment
+ \ 42
+
+
+" Trailing bar and comments
+
+" :echo without {expr}
+echo| echo "Foo"
+
+" trailing comment needs |
+echo "Foo" | " comment
+
+
+" Issue #9987 (parenthesised argument - not a function call)
+
+let foo = {'end': 123}
+
+if 123
+ echo (foo.end)
+else
+ echo 'bar'
+endif
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_eval.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_eval.mnv
new file mode 100644
index 0000000000..91bba9661b
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_eval.mnv
@@ -0,0 +1,20 @@
+" MNV :eval command
+
+
+eval "Foo"->append(0)
+
+eval "Foo"
+ \ ->append(
+ \ 0
+ \ )
+
+eval "Foo"->append(0) | echo "Foo"
+
+echo "Foo" | eval "Foo"->append(0)
+
+eval "Foo"->append(0) " comment
+
+def MNV9Context()
+ eval "Foo"->append(0) # comment
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_execute.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_execute.mnv
new file mode 100644
index 0000000000..683d0a9d33
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_execute.mnv
@@ -0,0 +1,64 @@
+" MNV :execute command
+
+
+" :help :execute
+
+execute "buffer" nextbuf
+execute "normal" count .. "w"
+execute '!ls' | echo "theend"
+execute "normal ixxx\<Esc>"
+execute "e " .. fnameescape(filename)
+execute "!ls " .. shellescape(filename, 1)
+if 0
+ execute 'while i > 5'
+ echo "test"
+ endwhile
+endif
+execute 'while i < 5 | echo i | let i = i + 1 | endwhile'
+
+
+" Trailing bar vs OR operator
+
+" OR operator
+execute foo || bar ? "Foo" : "NotFoo"
+execute foo ||
+ \ bar ? "Foo" : "NotFoo"
+
+" following command is :|"
+execute "Foo" | |
+
+" invalid expression
+execute "Foo" ||
+
+
+" Line continuations
+
+execute "call"
+ "\ comment
+ \ "Foo()"
+
+execute
+ \ "call"
+ "\ comment
+ \ "Foo()"
+
+
+" Trailing bar and comments
+
+" :execute without {expr}
+execute| echo "Foo"
+
+" trailing comment needs |
+execute "Foo" | " comment
+
+def MNV9Context()
+ # trailing comment allowed
+ execute "Foo" # comment
+enddef
+
+
+" Issue #9987 (parenthesised argument - not a function call)
+
+let foo = {'arg': "call Foo()"}
+execute (foo.arg)
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_filetype.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_filetype.mnv
new file mode 100644
index 0000000000..14fcf92c97
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_filetype.mnv
@@ -0,0 +1,30 @@
+" MNV :filetype command
+
+
+filetype
+filetype on
+filetype off
+filetype plugin on
+filetype plugin off
+filetype indent on
+filetype indent off
+filetype plugin indent on
+filetype plugin indent off
+
+filetype | echo "Foo"
+filetype " comment
+
+function Foo()
+ filetype
+ filetype on
+ filetype off
+ filetype plugin on
+ filetype plugin off
+ filetype indent on
+ filetype indent off
+ filetype plugin indent on
+ filetype plugin indent off
+ filetype | echo "Foo"
+ filetype " comment
+endfunction
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_filter.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_filter.mnv
new file mode 100644
index 0000000000..276aee25ea
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_filter.mnv
@@ -0,0 +1,16 @@
+" MNV :filter command
+" MNV_TEST_SETUP hi link mnvCmdSep Operator
+
+
+filter pa\%(tt\)ern oldfiles
+filter! pa\%(tt\)ern oldfiles
+
+filter /pa\%(tt\)ern/ oldfiles
+filter! /pa\%(tt\)ern/ oldfiles
+
+filter !pa\%(tt\)ern! oldfiles
+filter! !pa\%(tt\)ern! oldfiles
+
+filter /pa\%(t|t\)ern/ oldfiles | echo "Foo"
+filter! /pa\%(t|t\)ern/ oldfiles | echo "Foo"
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_for.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_for.mnv
new file mode 100644
index 0000000000..7649d5dfe6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_for.mnv
@@ -0,0 +1,60 @@
+" MNV :for command
+
+
+" :for {var} in {object}
+
+let expr = [42]
+
+for foo in expr
+ echo foo
+endfor
+
+for foo in expr " comment
+ echo foo
+endfor
+
+for foo in
+ "\ comment
+ \ expr
+ echo foo
+endfor
+
+for foo in expr | echo foo | endfor
+
+for foo in [42]
+ echo foo
+endfor
+
+for foo in [42] | echo foo | endfor
+
+echo "foo" | for foo in expr
+ echo foo
+endfor
+
+
+" :for [{var1}, {var2}, ...] in {listlist}
+
+let expr = [[42, 83]]
+
+for [foo, bar] in expr
+ echo foo bar
+endfor
+
+for [foo, bar] in expr " comment
+ echo foo bar
+endfor
+
+for [foo, bar] in
+ "\ comment
+ \ expr
+ echo foo bar
+endfor
+
+for [foo, bar] in expr | echo foo bar | endfor
+
+for [foo, bar] in [[42, 83]]
+ echo foo bar
+endfor
+
+for [foo, bar] in [[42, 83]] | echo foo bar | endfor
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_function.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_function.mnv
new file mode 100644
index 0000000000..ef509f62dd
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_function.mnv
@@ -0,0 +1,266 @@
+" MNV :function command
+
+
+" List
+
+function
+function Foo
+function /Foo.*
+
+function | echo "Foo"
+function " comment
+function Foo | echo "Foo"
+function Foo " comment
+
+
+" Definition
+
+" empty definition
+function Foo()
+endfunction
+
+" curly-brace names
+function {"F"}oo()
+endfunction
+
+function F{"o"}o()
+endfunction
+
+function Fo{"o"}()
+endfunction
+
+function {"F"}o{"o"}()
+endfunction
+
+function {"F"}{"o"}{"o"}()
+endfunction
+
+function Foo()
+ return 42
+endfunction
+
+" trailing whitespace
+function Foo()
+ return 42
+endfunction
+
+function Foo() " comment
+ return 42
+endfunction
+
+function! Foo()
+ return 42
+endfunction
+
+function g:Foo()
+ return 42
+endfunction
+
+function s:Foo()
+ return 42
+endfunction
+
+function <SID>Foo()
+ return 42
+endfunction
+
+function b:dict.Foo()
+ return 42
+endfunction
+
+function w:dict.Foo()
+ return 42
+endfunction
+
+function t:dict.Foo()
+ return 42
+endfunction
+
+function g:dict.Foo()
+ return 42
+endfunction
+
+function s:dict.Foo()
+ return 42
+endfunction
+
+function v:dict.Foo()
+ return 42
+endfunction
+
+function Foo(arg)
+ let l:dict = {}
+ function l:dict.BAR()
+ return 42
+ endfunction
+ function a:arg.BAR()
+ return 42
+ endfunction
+endfunction
+
+function foo#bar#Foo()
+ return 42
+endfunction
+
+function g:foo#bar#Foo()
+ return 42
+endfunction
+
+" same name as an Ex command
+function s:ls()
+endfunction
+
+
+" Modifiers
+
+function Foo() range
+endfunction
+
+function Foo() range " comment
+endfunction
+
+function Foo() range
+ return 42
+endfunction
+
+function Foo() abort
+ return 42
+endfunction
+
+function Foo() dict
+ return 42
+endfunction
+
+function Foo() closure
+ return 42
+endfunction
+
+function Foo() range abort dict closure
+ return 42
+endfunction
+
+function! Foo() range
+ return 42
+endfunction
+
+function! Foo() abort
+ return 42
+endfunction
+
+function! Foo() dict
+ return 42
+endfunction
+
+function! Foo() closure
+ return 42
+endfunction
+
+function! Foo() range abort dict closure
+ return 42
+endfunction
+
+
+" :endfunction trailing
+
+function Foo()
+ return 42
+ " trailing whitespace
+endfunction
+
+function Foo()
+ return 42
+endfunction | echo "Foo"
+
+function Foo()
+ return 42
+endfunction " comment
+
+
+" Parameters
+
+function Foo(x, y, z, ...)
+ return 42
+endfunction
+
+function Foo(
+ \ x,
+ \ y,
+ \ z,
+ \ ...)
+ return 42
+endfunction
+
+function Foo(
+ x,
+ y,
+ z,
+ ...)
+ return 42
+endfunction
+
+function Foo(x, y = 42, z = "zed")
+ return 42
+endfunction
+
+function Foo(
+ \ x,
+ \ y = 42,
+ \ z = "zed")
+ return 42
+endfunction
+
+function Foo(
+ x,
+ y = 42,
+ z = "zed")
+ return 42
+endfunction
+
+
+" Arguments
+
+function Foo(a, b, c)
+ echo a:a a:b a:c
+endfunction
+
+function Foo(...)
+ echo a:000
+ echo a:0
+ echo a:1 a:2 a:3 a:4 a:5 a:6 a:7 a:8 a:9 a:10 a:11 a:12 a:13 a:14 a:15 a:16 a:17 a:18 a:19 a:20
+endfunction
+
+
+" Issue #16243 (MNV script def parameters syntax highlight is wrong)
+
+function Test(lines = [line('.'), line('.')])
+endfunction
+
+
+" Comments
+
+function Foo()
+ " Legacy-script comment
+ # 42 " comment
+ return 42
+endfunction
+
+
+" Command modifiers
+
+silent! function Foo()
+endfunction
+
+
+" Leading command separator
+
+echo "Foo" | function Foo()
+endfunction
+
+
+" Issue https://github.com/Project-Tick/Project-Tick/pull/17420#issuecomment-2927798687
+" (function named /s:fu%\[nction]/)
+
+func! s:func(_, func)
+ return a:func
+endfunc
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_function_def_tail_comment_errors.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_function_def_tail_comment_errors.mnv
new file mode 100644
index 0000000000..020b42d888
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_function_def_tail_comment_errors.mnv
@@ -0,0 +1,45 @@
+" MNV :function and :def tail comment errors
+" MNV_TEST_SETUP unlet! g:mnvsyn_folding
+
+
+fun s:Test1() abort # fun
+ return 1
+endfun # endfun
+
+def s:Test2(): number " def
+ return 2
+enddef " enddef
+
+fun s:Test3() abort # fun
+ fun s:DoTest3() abort # fun
+ return 3
+ endfun # endfun
+ return s:DoTest3()
+endfun # endfun
+
+def s:Test4(): number " def
+ def DoTest4(): number " def
+ return 4
+ enddef " enddef
+ return DoTest4()
+enddef " enddef
+
+def s:Test5(): number " def
+ fun DoTest5() abort # fun
+ return 5
+ endfun # endfun
+ return DoTest5()
+enddef " enddef
+
+fun s:Test6() abort # fun
+ def s:DoTest6(): number " def
+ return 6
+ enddef " enddef
+ return s:DoTest6()
+endfun # endfun
+
+for d in range(1, 6)->reverse()
+ exec $'echo s:Test{d}()'
+ exec $'delfunction s:Test{d}'
+endfor
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_function_def_tail_comments.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_function_def_tail_comments.mnv
new file mode 100644
index 0000000000..353e6f68ec
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_function_def_tail_comments.mnv
@@ -0,0 +1,45 @@
+" MNV :function and :def tail comments
+" MNV_TEST_SETUP unlet! g:mnvsyn_folding
+
+
+fun s:Test1() abort " fun
+ return 1
+endfun " endfun
+
+def s:Test2(): number # def
+ return 2
+enddef # enddef
+
+fun s:Test3() abort " fun
+ fun s:DoTest3() abort " fun
+ return 3
+ endfun " endfun
+ return s:DoTest3()
+endfun " endfun
+
+def s:Test4(): number # def
+ def DoTest4(): number # def
+ return 4
+ enddef # enddef
+ return DoTest4()
+enddef # enddef
+
+def s:Test5(): number # def
+ fun DoTest5() abort " fun
+ return 5
+ endfun " endfun
+ return DoTest5()
+enddef # enddef
+
+fun s:Test6() abort " fun
+ def s:DoTest6(): number # def
+ return 6
+ enddef # enddef
+ return s:DoTest6()
+endfun " endfun
+
+for d in range(1, 6)->reverse()
+ exec $'echo s:Test{d}()'
+ exec $'delfunction s:Test{d}'
+endfor
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_function_fold.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_function_fold.mnv
new file mode 100644
index 0000000000..20d74929fd
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_function_fold.mnv
@@ -0,0 +1,349 @@
+" MNV :function command
+" MNV_TEST_SETUP let g:mnvsyn_folding = "f"
+" MNV_TEST_SETUP setl fdc=2 fdl=999 fdm=syntax
+
+
+" List
+
+function
+function Foo
+function /Foo.*
+
+function | echo "Foo"
+function " comment
+function Foo | echo "Foo"
+function Foo " comment
+
+
+" Definition
+
+" empty definition
+function Foo()
+endfunction
+
+" curly-brace names
+function {"F"}oo()
+endfunction
+
+function F{"o"}o()
+endfunction
+
+function Fo{"o"}()
+endfunction
+
+function {"F"}o{"o"}()
+endfunction
+
+function {"F"}{"o"}{"o"}()
+endfunction
+
+function Foo()
+ return 42
+endfunction
+
+" trailing whitespace
+function Foo()
+ return 42
+endfunction
+
+function Foo() " comment
+ return 42
+endfunction
+
+function! Foo()
+ return 42
+endfunction
+
+function g:Foo()
+ return 42
+endfunction
+
+function s:Foo()
+ return 42
+endfunction
+
+function <SID>Foo()
+ return 42
+endfunction
+
+function b:dict.Foo()
+ return 42
+endfunction
+
+function w:dict.Foo()
+ return 42
+endfunction
+
+function t:dict.Foo()
+ return 42
+endfunction
+
+function g:dict.Foo()
+ return 42
+endfunction
+
+function s:dict.Foo()
+ return 42
+endfunction
+
+function v:dict.Foo()
+ return 42
+endfunction
+
+function Foo(arg)
+ let l:dict = {}
+ function l:dict.BAR()
+ return 42
+ endfunction
+ function a:arg.BAR()
+ return 42
+ endfunction
+endfunction
+
+function foo#bar#Foo()
+ return 42
+endfunction
+
+function g:foo#bar#Foo()
+ return 42
+endfunction
+
+" same name as an Ex command
+function s:ls()
+endfunction
+
+
+" Modifiers
+
+function Foo() range
+endfunction
+
+function Foo() range " comment
+endfunction
+
+function Foo() range
+ return 42
+endfunction
+
+function Foo() abort
+ return 42
+endfunction
+
+function Foo() dict
+ return 42
+endfunction
+
+function Foo() closure
+ return 42
+endfunction
+
+function Foo() range abort dict closure
+ return 42
+endfunction
+
+function! Foo() range
+ return 42
+endfunction
+
+function! Foo() abort
+ return 42
+endfunction
+
+function! Foo() dict
+ return 42
+endfunction
+
+function! Foo() closure
+ return 42
+endfunction
+
+function! Foo() range abort dict closure
+ return 42
+endfunction
+
+
+" :endfunction trailing
+
+function Foo()
+ return 42
+ " trailing whitespace
+endfunction
+
+function Foo()
+ return 42
+endfunction | echo "Foo"
+
+function Foo()
+ return 42
+endfunction " comment
+
+
+" Parameters
+
+function Foo(x, y, z, ...)
+ return 42
+endfunction
+
+function Foo(
+ \ x,
+ \ y,
+ \ z,
+ \ ...)
+ return 42
+endfunction
+
+function Foo(
+ x,
+ y,
+ z,
+ ...)
+ return 42
+endfunction
+
+function Foo(x, y = 42, z = "zed")
+ return 42
+endfunction
+
+function Foo(
+ \ x,
+ \ y = 42,
+ \ z = "zed")
+ return 42
+endfunction
+
+function Foo(
+ x,
+ y = 42,
+ z = "zed")
+ return 42
+endfunction
+
+
+" Arguments
+
+function Foo(a, b, c)
+ echo a:a a:b a:c
+endfunction
+
+function Foo(...)
+ echo a:000
+ echo a:0
+ echo a:1 a:2 a:3 a:4 a:5 a:6 a:7 a:8 a:9 a:10 a:11 a:12 a:13 a:14 a:15 a:16 a:17 a:18 a:19 a:20
+endfunction
+
+
+" Issue #16243 (MNV script def parameters syntax highlight is wrong)
+
+function Test(lines = [line('.'), line('.')])
+endfunction
+
+
+" Comments
+
+function Foo()
+ " Legacy-script comment
+ # 42 " comment
+ return 42
+endfunction
+
+
+" Command modifiers
+
+silent! function Foo()
+endfunction
+
+
+" Leading command separator
+
+echo "Foo" | function Foo()
+endfunction
+
+
+" Issue https://github.com/Project-Tick/Project-Tick/pull/17420#issuecomment-2927798687
+" (function named /s:fu%\[nction]/)
+
+func! s:func(_, func)
+ return a:func
+endfunc
+
+
+" Fold-region ending
+
+function Foo()
+ " endfunction
+endfunction
+
+function Foo()
+ echo "endfunction"
+endfunction
+
+function Foo()
+ let x =<< trim END
+ endfunction
+ END
+endfunction
+
+function Foo()
+ append
+ endfunction
+.
+endfunction
+
+function Foo()
+ change
+ endfunction
+.
+
+endfunction
+
+function Foo()
+ insert
+ endfunction
+.
+endfunction
+
+:function Foo()
+:endfunction
+
+
+" Issue #15671
+" No recognition of :fun or :def bodies commencing with empty lines if
+" g:mnvsyn_folding contains "f"
+
+fun FA1()
+
+
+ return
+endfun
+
+fun FA2()
+ return
+endfun
+
+fun FB1() abort
+
+ return
+endfun
+
+fun FB2() abort
+ return
+endfun
+
+fun FC1(_)
+
+ return
+endfun
+
+fun FC2(_)
+ return
+endfun
+
+fun FD1(_) abort
+
+ return
+endfun
+
+fun FD2(_) abort
+ return
+endfun
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_function_nested.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_function_nested.mnv
new file mode 100644
index 0000000000..a0e787a1ab
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_function_nested.mnv
@@ -0,0 +1,40 @@
+" MNV :def and :function commands (nested)
+
+
+def FunA(): string
+ def DoFunA(): string
+ return "."
+ enddef
+
+ return DoFunA()
+enddef
+
+def FunB(): string
+ function DoFunB()
+ return ".."
+ endfunction
+
+ return DoFunB()
+enddef
+
+function FunC()
+ def DoFunC(): string
+ return "..."
+ enddef
+
+ return DoFunC()
+endfunction
+
+function FunD()
+ function DoFunD()
+ return "...."
+ endfunction
+
+ return DoFunD()
+endfunction
+
+echo FunA()
+echo FunB()
+echo FunC()
+echo FunD()
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_function_nested_fold.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_function_nested_fold.mnv
new file mode 100644
index 0000000000..6aa403cb41
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_function_nested_fold.mnv
@@ -0,0 +1,42 @@
+" MNV :def and :function commands (nested)
+" MNV_TEST_SETUP let g:mnvsyn_folding = 'f'
+" MNV_TEST_SETUP setl fdc=2 fdm=syntax
+
+
+def FunA(): string
+ def DoFunA(): string
+ return "."
+ enddef
+
+ return DoFunA()
+enddef
+
+def FunB(): string
+ function DoFunB()
+ return ".."
+ endfunction
+
+ return DoFunB()
+enddef
+
+function FunC()
+ def DoFunC(): string
+ return "..."
+ enddef
+
+ return DoFunC()
+endfunction
+
+function FunD()
+ function DoFunD()
+ return "...."
+ endfunction
+
+ return DoFunD()
+endfunction
+
+echo FunA()
+echo FunB()
+echo FunC()
+echo FunD()
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_grep.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_grep.mnv
new file mode 100644
index 0000000000..9c9ca3def7
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_grep.mnv
@@ -0,0 +1,47 @@
+" MNV :*grep and :*grepadd commands
+" MNV_TEST_SETUP hi link mnvCmdSep Operator
+" MNV_TEST_SETUP hi link mnvGrepBarEscape Special
+
+
+grep 'pat\|tern' foo.txt
+lgrep 'pat\|tern' foo.txt
+
+grep! 'pat\|tern' foo.txt
+lgrep! 'pat\|tern' foo.txt
+
+grepadd 'pat\|tern' foo.txt
+lgrepadd 'pat\|tern' foo.txt
+
+grepadd! 'pat\|tern' foo.txt
+lgrepadd! 'pat\|tern' foo.txt
+
+
+" Special filename characters
+
+grep 'pat\|tern' %
+lgrep 'pat\|tern' %
+
+grep! 'pat\|tern' %
+lgrep! 'pat\|tern' %
+
+grepadd! 'pat\|tern' %
+lgrepadd! 'pat\|tern' %
+
+grepadd! 'pat\|tern' %
+lgrepadd! 'pat\|tern' %
+
+
+" Trailing bar, no tail comment
+
+grep 'pat\|tern' foo.txt | echo "Foo"
+lgrep 'pat\|tern' foo.txt | echo "Foo"
+
+grep! 'pat\|tern' foo.txt | echo "Foo"
+lgrep! 'pat\|tern' foo.txt | echo "Foo"
+
+grepadd 'pat\|tern' foo.txt | echo "Foo"
+lgrepadd 'pat\|tern' foo.txt | echo "Foo"
+
+grepadd! 'pat\|tern' foo.txt | echo "Foo"
+lgrepadd! 'pat\|tern' foo.txt | echo "Foo"
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_help.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_help.mnv
new file mode 100644
index 0000000000..c673fe6b0a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_help.mnv
Binary files differ
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_helpgrep.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_helpgrep.mnv
new file mode 100644
index 0000000000..27b811c24b
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_helpgrep.mnv
@@ -0,0 +1,18 @@
+" MNV :helpgrep command
+" MNV_TEST_SETUP hi link mnvHelpgrepPattern Todo
+
+
+helpgrep :help
+helpgrep :help@en
+helpgrep :h\%(elp\)\=
+
+lhelpgrep :help
+lhelpgrep :help@en
+lhelpgrep :h\%(elp\)\=
+
+
+" no tail comment or trailing bar
+
+helpgrep :help " not a comment
+helpgrep :help | not a command
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_highlight.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_highlight.mnv
new file mode 100644
index 0000000000..bb258b40d4
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_highlight.mnv
@@ -0,0 +1,108 @@
+" MNV :highlight command
+" MNV_TEST_SETUP hi link mnvHiGroup Todo
+
+
+" List
+
+highlight
+highlight Comment
+highlight Conceal
+highlight ErrorMsg
+highlight Foo
+
+
+" Reset
+
+highlight clear
+
+
+" Disable
+
+highlight clear Comment
+highlight clear Conceal
+highlight clear ErrorMsg
+highlight clear Foo
+
+highlight Comment NONE
+highlight Conceal NONE
+highlight ErrorMsg NONE
+highlight Foo NONE
+
+
+" Add/modify
+
+highlight Comment cterm=underline
+highlight Conceal cterm=underline
+highlight ErrorMsg cterm=underline
+highlight Foo cterm=underline
+
+highlight default Comment term=bold
+highlight default Conceal term=bold
+highlight default ErrorMsg term=bold
+highlight Foo ErrorMsg term=bold
+
+
+" Link
+
+highlight link Foo Comment
+highlight! link Foo Comment
+highlight link Foo NONE
+highlight! link Foo NONE
+highlight link Foo ErrorMsg
+highlight! link Foo ErrorMsg
+
+
+" Default link
+
+highlight default link Foo Comment
+highlight! default link Foo Comment
+highlight default link Foo NONE
+highlight! default link Foo NONE
+highlight default link Foo ErrorMsg
+highlight! default link Foo ErrorMsg
+
+
+" Line continuation and command separator
+
+hi Comment
+ "\ comment
+ \ term=bold
+ "\ comment
+ \ ctermfg=Cyan
+ \ guifg=#80a0ff
+ \ gui=bold
+
+hi Comment
+ \ term=bold
+ \ ctermfg=Cyan
+ \ guifg=#80a0ff
+ \ gui=bold | echo "Foo"
+
+hi Comment term=bold ctermfg=Cyan guifg=#80a0ff gui=bold | echo "Foo"
+
+hi default link
+ \ Foo
+ \ Comment
+
+hi default link
+ \ Foo
+ \ Comment | echo "Foo"
+
+
+" 'statusline' user groups
+
+highlight User1 ctermfg=black
+highlight User2 ctermfg=darkblue
+highlight User3 ctermfg=darkgreen
+highlight User4 ctermfg=darkcyan
+highlight User5 ctermfg=darkred
+highlight User6 ctermfg=darkmagenta
+highlight User7 ctermfg=darkyellow
+highlight User8 ctermfg=lightgray
+highlight User9 ctermfg=darkgray
+
+
+" :terminal group
+
+hi Terminal ctermbg=red ctermfg=blue
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_history.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_history.mnv
new file mode 100644
index 0000000000..e3ca50ec46
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_history.mnv
@@ -0,0 +1,89 @@
+" MNV :history command
+" MNV_TEST_SETUP hi link mnvHistoryRange Todo
+
+history 1,9
+history cmd 1,9
+history : 1,9
+history search 1,9
+history / 1,9
+history ? 1,9
+history expr 1,9
+history = 1,9
+history input 1,9
+history @ 1,9
+history debug 1,9
+history > 1,9
+history all 1,9
+
+history 1
+history -1
+history 1,
+history -1,
+history , 1
+history ,-1
+history 1, 1
+history 1,-1
+history -1, 1
+history -1,-1
+
+history 1, 1
+history 1 ,1
+history 1 , 1
+
+
+" tail comments and trailing bar
+
+history | echo "..."
+history " comment
+history all | echo "..."
+history all " comment
+history 1,9 | echo "..."
+history 1,9 " comment
+history all 1,9 | echo "..."
+history all 1,9 " comment
+
+
+def MNV9Context()
+ history 1,9
+ history cmd 1,9
+ history : 1,9
+ history search 1,9
+ history / 1,9
+ history ? 1,9
+ history expr 1,9
+ # FIXME
+ # history = 1,9
+ history input 1,9
+ history @ 1,9
+ history debug 1,9
+ history > 1,9
+ history all 1,9
+
+ history 1
+ history -1
+ history 1,
+ history -1,
+ history , 1
+ history ,-1
+ history 1, 1
+ history 1,-1
+ history -1, 1
+ history -1,-1
+
+ history 1, 1
+ history 1 ,1
+ history 1 , 1
+
+
+ # tail comments and trailing bar
+
+ history | echo "..."
+ history # comment
+ history all | echo "..."
+ history all # comment
+ history 1,9 | echo "..."
+ history 1,9 # comment
+ history all 1,9 | echo "..."
+ history all 1,9 # comment
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_import.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_import.mnv
new file mode 100644
index 0000000000..2cdce587f6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_import.mnv
@@ -0,0 +1,119 @@
+" MNV :import command
+" MNV_TEST_SETUP hi link mnvImportName Todo
+
+
+import "foo.mnv"
+impor v:true ? "foo.mnv" : "bar.mnv"
+
+import v:true ?
+ \ "foo.mnv" :
+ \ "bar.mnv"
+
+import v:true
+ \ ? "foo.mnv"
+ \ : "bar.mnv"
+
+import v:true ?
+ "\ comment
+ \ "foo.mnv" :
+ "\ comment
+ \ "bar.mnv"
+
+import v:true
+ "\ comment
+ \ ? "foo.mnv"
+ "\ comment
+ \ : "bar.mnv"
+
+import "foo.mnv" as bar
+import v:true ? "foo.mnv" : "bar.mnv" as baz
+
+import v:true ?
+ \ "foo.mnv" :
+ \ "bar.mnv"
+ \ as baz
+
+import v:true
+ \ ? "foo.mnv"
+ \ : "bar.mnv"
+ \ as baz
+
+import v:true ?
+ "\ comment
+ \ "foo.mnv" :
+ "\ comment
+ \ "bar.mnv"
+ "\ comment
+ \ as baz
+
+import v:true
+ "\ comment
+ \ ? "foo.mnv"
+ "\ comment
+ \ : "bar.mnv"
+ "\ comment
+ \ as baz
+
+echo "Foo" | import "foo.mnv"
+
+
+" autoload
+
+import autoload "foo.mnv"
+import autoload v:true ? "foo.mnv" : "bar.mnv"
+
+import autoload v:true ?
+ \ "foo.mnv" :
+ \ "bar.mnv"
+
+import autoload v:true
+ \ ? "foo.mnv"
+ \ : "bar.mnv"
+
+import autoload v:true ?
+ "\ comment
+ \"foo.mnv" :
+ "\ comment
+ \ "bar.mnv"
+
+import autoload v:true
+ "\ comment
+ \ ? "foo.mnv"
+ "\ comment
+ \ : "bar.mnv"
+
+import autoload "foo.mnv" as bar
+import autoload v:true ? "foo.mnv" : "bar.mnv" as baz
+
+import autoload v:true ?
+ \ "foo.mnv" :
+ \ "bar.mnv"
+ \ as baz
+
+import autoload v:true
+ \ ? "foo.mnv"
+ \ : "bar.mnv"
+ \ as baz
+
+import autoload v:true ?
+ "\ comment
+ \ "foo.mnv" :
+ "\ comment
+ \ "bar.mnv"
+ "\ comment
+ \ as baz
+
+import autoload v:true
+ "\ comment
+ \ ? "foo.mnv"
+ "\ comment
+ \ : "bar.mnv"
+ "\ comment
+ \ as baz
+
+
+" "as" keyword in expr
+
+let as = "modules/"
+import v:true ? as .. "foo.mnv" : as .. "bar.mnv" as other
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_language.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_language.mnv
new file mode 100644
index 0000000000..ba79cb0557
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_language.mnv
@@ -0,0 +1,172 @@
+" MNV :language command
+" MNV_TEST_SETUP hi link mnvLanguageName Todo
+
+
+" print commands
+
+language
+language collate
+language ctype
+language time
+language messages
+
+
+" set commands
+
+language C
+language collate C
+language ctype C
+language time C
+language messages C
+
+language POSIX
+language collate POSIX
+language ctype POSIX
+language time POSIX
+language messages POSIX
+
+language de_DE.UTF-8@euro
+language collate de_DE.UTF-8@euro
+language ctype de_DE.UTF-8@euro
+language time de_DE.UTF-8@euro
+language messages de_DE.UTF-8@euro
+
+" tail comment and trailing bar
+
+language " comment
+language collate " comment
+language ctype " comment
+language time " comment
+language messages " comment
+
+language de_DE.UTF-8@euro " comment
+language collate de_DE.UTF-8@euro " comment
+language ctype de_DE.UTF-8@euro " comment
+language time de_DE.UTF-8@euro " comment
+language messages de_DE.UTF-8@euro " comment
+
+language C " comment
+language collate C " comment
+language ctype C " comment
+language time C " comment
+language messages C " comment
+
+language POSIX " comment
+language collate POSIX " comment
+language ctype POSIX " comment
+language time POSIX " comment
+language messages POSIX " comment
+
+language de_DE.UTF-8@euro " comment
+language collate de_DE.UTF-8@euro " comment
+language ctype de_DE.UTF-8@euro " comment
+language time de_DE.UTF-8@euro " comment
+language messages de_DE.UTF-8@euro " comment
+
+language | echo "..."
+language collate | echo "..."
+language ctype | echo "..."
+language time | echo "..."
+language messages | echo "..."
+
+language C | echo "..."
+language collate C | echo "..."
+language ctype C | echo "..."
+language time C | echo "..."
+language messages C | echo "..."
+
+language POSIX | echo "..."
+language collate POSIX | echo "..."
+language ctype POSIX | echo "..."
+language time POSIX | echo "..."
+language messages POSIX | echo "..."
+
+language de_DE.UTF-8@euro | echo "..."
+language collate de_DE.UTF-8@euro | echo "..."
+language ctype de_DE.UTF-8@euro | echo "..."
+language time de_DE.UTF-8@euro | echo "..."
+language messages de_DE.UTF-8@euro | echo "..."
+
+def MNV9Context()
+
+ # print commands
+
+ language
+ language collate
+ language ctype
+ language time
+ language messages
+
+
+ # set commands
+
+ language C
+ language collate C
+ language ctype C
+ language time C
+ language messages C
+
+ language POSIX
+ language collate POSIX
+ language ctype POSIX
+ language time POSIX
+ language messages POSIX
+
+ language de_DE.UTF-8@euro
+ language collate de_DE.UTF-8@euro
+ language ctype de_DE.UTF-8@euro
+ language time de_DE.UTF-8@euro
+ language messages de_DE.UTF-8@euro
+
+
+ # tail comment and trailing bar
+
+ language # comment
+ language collate # comment
+ language ctype # comment
+ language time # comment
+ language messages # comment
+
+ language C # comment
+ language collate C # comment
+ language ctype C # comment
+ language time C # comment
+ language messages C # comment
+
+ language POSIX # comment
+ language collate POSIX # comment
+ language ctype POSIX # comment
+ language time POSIX # comment
+ language messages POSIX # comment
+
+ language de_DE.UTF-8@euro # comment
+ language collate de_DE.UTF-8@euro # comment
+ language ctype de_DE.UTF-8@euro # comment
+ language time de_DE.UTF-8@euro # comment
+ language messages de_DE.UTF-8@euro # comment
+
+ language | echo "..."
+ language collate | echo "..."
+ language ctype | echo "..."
+ language time | echo "..."
+ language messages | echo "..."
+
+ language C | echo "..."
+ language collate C | echo "..."
+ language ctype C | echo "..."
+ language time C | echo "..."
+ language messages C | echo "..."
+
+ language POSIX | echo "..."
+ language collate POSIX | echo "..."
+ language ctype POSIX | echo "..."
+ language time POSIX | echo "..."
+ language messages POSIX | echo "..."
+
+ language de_DE.UTF-8@euro | echo "..."
+ language collate de_DE.UTF-8@euro | echo "..."
+ language ctype de_DE.UTF-8@euro | echo "..."
+ language time de_DE.UTF-8@euro | echo "..."
+ language messages de_DE.UTF-8@euro | echo "..."
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_let_heredoc.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_let_heredoc.mnv
new file mode 100644
index 0000000000..516053a32e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_let_heredoc.mnv
@@ -0,0 +1,250 @@
+" MNV :let heredoc command
+" MNV_TEST_SETUP let g:mnvsyn_folding = "h"
+" MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+
+
+let foo =<< END
+line1
+line2
+END
+
+ let foo =<< END
+line1
+line2
+END
+
+let [foo, bar] =<< EOS
+line1
+line2
+EOS
+
+ let [foo, bar] =<< EOS
+line1
+line2
+EOS
+
+let [foo,
+ \ bar] =<< EOS
+line1
+line2
+EOS
+
+ let [foo,
+ \ bar] =<< EOS
+line1
+line2
+EOS
+
+let g:foo =<< END
+line1
+line2
+END
+
+ let g:foo =<< END
+line1
+line2
+END
+
+let [g:foo, g:bar] =<< EOS
+line1
+line2
+EOS
+
+ let [g:foo, g:bar] =<< EOS
+line1
+line2
+EOS
+
+let [g:foo,
+ \ g:bar] =<< EOS
+line1
+line2
+EOS
+
+ let [g:foo,
+ \ g:bar] =<< EOS
+line1
+line2
+EOS
+
+
+" Trim
+
+let foo =<< trim END
+ line1
+ line2
+END
+
+ let foo =<< trim END
+ line1
+ line2
+ END
+
+
+" Interpolation
+
+let foo =<< eval END
+line{1 + 0}
+line{1 + 1}
+END
+
+ let foo =<< eval END
+line{1 + 0}
+line{1 + 1}
+END
+
+let foo =<< trim eval END
+ line{1 + 0}
+ line{1 + 1}
+END
+
+ let foo =<< trim eval END
+ line{1 + 0}
+ line{1 + 1}
+ END
+
+" No interpolation (escaped { and })
+
+let foo =<< eval END
+line{{1 + 0}}
+line{{1 + 1}}
+END
+
+ let foo =<< eval END
+line{{1 + 0}}
+line{{1 + 1}}
+END
+
+let foo =<< trim eval END
+ line{{1 + 0}}
+ line{{1 + 1}}
+END
+
+ let foo =<< trim eval END
+ line{{1 + 0}}
+ line{{1 + 1}}
+ END
+
+
+" No interpolation
+
+let foo =<< END
+line{1 + 0}
+line{1 + 1}
+END
+
+ let foo =<< END
+line{1 + 0}
+line{1 + 1}
+END
+
+let foo =<< trim END
+ line{1 + 0}
+ line{1 + 1}
+END
+
+ let foo =<< trim END
+ line{1 + 0}
+ line{1 + 1}
+ END
+
+
+" End marker must not be followed by whitespace
+
+" assert_equal(foo, ["END "])
+let foo =<< END
+END
+END
+
+" assert_equal(foo, [" END "])
+let foo =<< END
+ END
+END
+
+" assert_equal(foo, ["END "])
+let foo =<< trim END
+ END
+END
+
+" assert_equal(foo, ["END "])
+ let foo =<< trim END
+ END
+ END
+
+
+" end marker must be vertically aligned with :let (if preceded by whitespace)
+
+" assert_equal(foo, ["END"])
+let foo =<< trim END
+ END
+END
+
+ " assert_equal(foo, ["END"])
+ let foo =<< trim END
+ END
+ END
+
+" assert_equal(foo, ["END "])
+let foo =<< trim END
+END
+END
+
+ " assert_equal(foo, ["END"])
+ let foo =<< trim END
+ END
+ END
+
+ " assert_equal(foo, ["END "])
+ let foo =<< trim END
+ END
+ END
+
+ " assert_equal(foo, ["END"])
+ let foo =<< trim END
+ END
+ END
+
+ " assert_equal(foo, ["END "])
+ let foo =<< trim END
+ END
+ END
+
+ " assert_equal(foo, ["END "])
+ let foo =<< trim END
+END
+END
+
+ " assert_equal(foo, ["END"])
+ let foo =<< trim END
+ END
+END
+
+ " assert_equal(foo, ["END"])
+ let foo =<< trim END
+ END
+END
+
+
+" End markers
+
+let foo =<< !@#$%^&*()_+
+line1
+line2
+!@#$%^&*()_+
+
+let foo =<< 0!@#$%^&*()_+
+line1
+line2
+0!@#$%^&*()_+
+
+let foo =<< A!@#$%^&*()_+
+line1
+line2
+A!@#$%^&*()_+
+
+" error - leading lowercase character
+let foo =<< a!@#$%^&*()_+
+line1
+line2
+a!@#$%^&*()_+
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap.mnv
new file mode 100644
index 0000000000..88fb6e16b1
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap.mnv
@@ -0,0 +1,27 @@
+" MNV :loadkeymap command
+
+
+scriptencoding utf-8
+
+let b:keymap_name = "syntax-test"
+
+loadkeymap
+
+" Line comment
+
+ " Another line comment
+
+a A Basic mapping
+'a á More than one char in first column
+
+" Special notation
+<char-62> B Special notation allowed in LHS - decimal
+c <char-0103> Special notation allowed in RHS - octal
+<char-0x0064> <char-0x0044> Special notation allowed in LHS and RHS - hexadecimal
+
+" MNV-script comment characters
+# <char-0x00a3> Line should not match as a MNV9-script comment
+" Line should not match as a legacy-script comment
+\" “
+: " Line should not match as a legacy-script comment
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap_after_bar.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap_after_bar.mnv
new file mode 100644
index 0000000000..e0a722e83d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap_after_bar.mnv
@@ -0,0 +1,11 @@
+" MNV :loadkeymap command (after "|")
+
+
+scriptencoding utf-8
+
+let b:keymap_name = "syntax-test"
+
+echo "..." | loadkeymap
+
+a A Basic mapping
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap_after_colon.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap_after_colon.mnv
new file mode 100644
index 0000000000..ee73b87969
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_loadkeymap_after_colon.mnv
@@ -0,0 +1,11 @@
+" MNV :loadkeymap command (after ":")
+
+
+scriptencoding utf-8
+
+let b:keymap_name = "syntax-test"
+
+:loadkeymap
+
+a A Basic mapping
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_lua.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_lua.mnv
new file mode 100644
index 0000000000..eace6dea3a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_lua.mnv
@@ -0,0 +1,157 @@
+" MNV :lua, :luado and :luafile commands
+" MNV_TEST_SETUP let g:mnvsyn_embed = "l"
+" MNV_TEST_SETUP let g:mnvsyn_folding = "fl"
+" MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+
+
+lua << EOF
+print("Lua script")
+EOF
+
+ lua << trim EOF
+ print("Lua script")
+ EOF
+
+lua <<
+print("Lua script")
+.
+
+ lua << trim
+ print("Lua script")
+ .
+
+function Foo()
+ lua << trim EOF
+ print("Lua script in :func")
+ EOF
+endfunction | call Foo()
+
+def Bar()
+ lua << trim EOF
+ print("Lua script in :def")
+ EOF
+enddef | call Bar()
+
+lua print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luado print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luafile foo.lua
+
+
+" :mzscheme and :mzfile
+
+mzscheme << trim EOF
+ (display "MzScheme script")
+EOF
+
+mzscheme (display "MzScheme statement")
+ "\ comment
+ \ (display "MzScheme statement again")
+
+mzfile foo.rkt
+
+
+" :perl and :perldo
+
+perl << trim EOF
+ print("Perl script\n")
+EOF
+
+perl print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+perldo print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+
+" :python, :pydo and :pyfile
+
+python << trim EOF
+ print("Python script")
+EOF
+
+python print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pydo print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pyfile foo.py
+
+
+" :python3, :py3do and :py3file
+
+python3 << trim EOF
+ print("Python3 script")
+EOF
+
+python3 print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3do print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3file foo.py
+
+
+" :pythonx, :pyxdo and :pyxfile
+
+pythonx << trim EOF
+ print("PythonX script")
+EOF
+
+pythonx print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxdo print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxfile foo.py
+
+
+" :ruby, :rubydo and :rubyfile
+
+ruby << trim EOF
+ puts "Ruby script"
+EOF
+
+ruby puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubydo puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubyfile foo.rb
+
+
+" :tcl, :tcldo and :tclfile
+
+tcl << trim EOF
+ puts "TCL script"
+EOF
+
+tcl puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tcldo puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tclfile foo.tcl
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_make.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_make.mnv
new file mode 100644
index 0000000000..31bbdace62
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_make.mnv
@@ -0,0 +1,38 @@
+" MNV :*make commands
+" MNV_TEST_SETUP hi link mnvCmdSep Operator
+" MNV_TEST_SETUP hi link mnvMakeBarEscape Special
+
+
+make
+lmake
+
+make!
+lmake!
+
+make -options target
+lmake -options target
+
+make! -options target
+lmake! -options target
+
+
+" Special filename characters
+
+make %
+lmake %
+
+
+" Trailing bar, no tail comment
+
+make tar\|get | echo "Foo"
+lmake tar\|get | echo "Foo"
+
+make! tar\|get | echo "Foo"
+lmake! tar\|get | echo "Foo"
+
+make | echo "Foo"
+lmake | echo "Foo"
+
+make! | echo "Foo"
+lmake! | echo "Foo"
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_map.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_map.mnv
new file mode 100644
index 0000000000..31103f5dd7
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_map.mnv
@@ -0,0 +1,124 @@
+" MNV :map commands
+" MNV_TEST_SETUP hi link mnvMapLhs Identifier
+" MNV_TEST_SETUP hi link mnvMapRhs Todo
+" MNV_TEST_SETUP hi link mnvMapRhsContinue Todo
+
+
+map!
+map! lhs rhs
+map
+map lhs rhs
+
+map <buffer><expr><nowait><script><silent><special><unique> lhs rhs
+map <buffer> <expr> <nowait> <script> <silent> <special> <unique> lhs rhs
+
+" :map special arguments are case sensitive, <BUFFER> is the LHS
+map <BUFFER> rhs
+
+map <Leader>lhs rhs
+map <LocalLeader>lhs rhs
+
+map lhs <Leader>rhs
+map lhs <LocalLeader>rhs
+
+map lhs <Plug>rhs
+
+mapclear <buffer>
+mapclear! <buffer>
+nmapclear <buffer>
+vmapclear <buffer>
+xmapclear <buffer>
+smapclear <buffer>
+omapclear <buffer>
+imapclear <buffer>
+lmapclear <buffer>
+cmapclear <buffer>
+tmapclear <buffer>
+
+
+" :help map-bar
+
+" <Bar> '<' is not in 'cpoptions'
+map _l :!ls <Bar> more^M:echo "rhs"<CR>
+" \| 'b' is not in 'cpoptions'
+map _l :!ls \| more^M:echo "rhs"<CR>
+" ^V| always, in MNV and Vi
+map _l :!ls | more^M:echo "rhs"<CR>
+
+map lhs :search('foo\\|bar')<CR>:echo "rhs"<CR>
+
+
+" Multiline RHS
+
+map <Leader>baz
+ \ :echo (<Bar>
+ \
+ \'bar')<CR>
+ "\ comment
+
+map lhs
+ "\ comment
+ \ echo "foo"
+
+map lhs
+ "\ comment
+ \ echo "foo"
+
+map lhs
+ "\ comment
+ \ echo "foo"
+
+map l hs
+ "\ comment
+ \ echo "foo"
+
+map l hs
+ "\ comment
+ \ echo "foo"
+
+map lhs rhs
+map l h s rhs
+
+map lhs
+ "\ comment (matches as RHS but harmless)
+echo "clear"
+
+
+" Differentiate map() from :map
+
+map ( :echo "open-paren"<CR>
+
+call map(list, 'v:val')
+call map (list, 'v:val')
+
+function Foo()
+ map ( :echo "open-paren"<CR>
+ call map(list, 'v:val')
+ call map (list, 'v:val')
+endfunction
+
+def Foo()
+ map ( :echo "open-paren"<CR>
+ map(list, 'v:val')
+ # :map LHS=(list, RHS='v:val')
+ map (list, 'v:val')
+enddef
+
+
+" Issue #12672
+
+nnoremap <Leader>foo :echo call(
+ "\ comment
+ \ {x->x},
+ \ ['foo'])<CR>
+
+nnoremap <Leader>bar :echo (
+ \
+ \ 'bar')<CR>
+
+
+" Example:
+" /autoload/netrw.mnv
+
+if !hasmapto('<Plug>NetrwOpenFile') |nmap <buffer> <silent> <nowait> % <Plug>NetrwOpenFile|endif
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_mark.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_mark.mnv
new file mode 100644
index 0000000000..59fcb3fb27
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_mark.mnv
@@ -0,0 +1,215 @@
+" MNV :mark and :k commands
+" :k not available in MNV9
+" MNV_TEST_SETUP hi link mnvMarkArg Todo
+
+
+mark `
+mark '
+mark a
+mark A
+mark k
+mark K
+mark z
+mark Z
+mark [
+mark ]
+mark <
+mark >
+
+:mark `
+:mark '
+:mark a
+:mark A
+:mark k
+:mark K
+:mark z
+:mark Z
+:mark [
+:mark ]
+:mark <
+:mark >
+
+call Foo() | mark `
+call Foo() | mark '
+call Foo() | mark a
+call Foo() | mark A
+call Foo() | mark k
+call Foo() | mark K
+call Foo() | mark z
+call Foo() | mark Z
+call Foo() | mark [
+call Foo() | mark ]
+call Foo() | mark <
+call Foo() | mark >
+
+call Foo() | :mark `
+call Foo() | :mark '
+call Foo() | :mark a
+call Foo() | :mark A
+call Foo() | :mark k
+call Foo() | :mark K
+call Foo() | :mark z
+call Foo() | :mark Z
+call Foo() | :mark [
+call Foo() | :mark ]
+call Foo() | :mark <
+call Foo() | :mark >
+
+k`
+k'
+ka
+kA
+kk
+kK
+kz
+kZ
+k[
+k]
+k<
+k>
+
+:k`
+:k'
+:ka
+:kA
+:kk
+:kK
+:kz
+:kZ
+:k[
+:k]
+:k<
+:k>
+
+call Foo() | k`
+call Foo() | k'
+call Foo() | ka
+call Foo() | kA
+call Foo() | kk
+call Foo() | kK
+call Foo() | kz
+call Foo() | kZ
+call Foo() | k[
+call Foo() | k]
+call Foo() | k<
+call Foo() | k>
+
+call Foo() | :k`
+call Foo() | :k'
+call Foo() | :ka
+call Foo() | :kA
+call Foo() | :kk
+call Foo() | :kK
+call Foo() | :kz
+call Foo() | :kZ
+call Foo() | :k[
+call Foo() | :k]
+call Foo() | :k<
+call Foo() | :k>
+
+k `
+k '
+k a
+k A
+k k
+k K
+k z
+k Z
+k [
+k ]
+k <
+k >
+
+:k `
+:k '
+:k a
+:k A
+:k k
+:k K
+:k z
+:k Z
+:k [
+:k ]
+:k <
+:k >
+
+call Foo() | k `
+call Foo() | k '
+call Foo() | k a
+call Foo() | k A
+call Foo() | k k
+call Foo() | k K
+call Foo() | k z
+call Foo() | k Z
+call Foo() | k [
+call Foo() | k ]
+call Foo() | k <
+call Foo() | k >
+
+call Foo() | :k `
+call Foo() | :k '
+call Foo() | :k a
+call Foo() | :k A
+call Foo() | :k k
+call Foo() | :k K
+call Foo() | :k z
+call Foo() | :k Z
+call Foo() | :k [
+call Foo() | :k ]
+call Foo() | :k <
+call Foo() | :k >
+
+
+mark a | echo "FOO"
+ka | echo "FOO"
+k a | echo "FOO"
+mark a " comment
+ka " comment
+k a " comment
+
+
+function Foo()
+ k a
+ ka
+ mark a
+ :k a
+ :ka
+ :mark a
+endfunction
+
+
+" Errors
+
+mark "
+mark ^
+mark .
+" TODO: matches as mnvFunc
+" mark (
+mark )
+mark {
+mark }
+mark 0
+mark 9
+
+k"
+k^
+k.
+" TODO: matches as mnvFunc
+" k(
+k)
+k{
+k}
+k0
+k9
+
+k "
+k ^
+k .
+" TODO: matches as mnvFunc
+" k (
+k )
+k {
+k }
+k 0
+k 9
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_match.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_match.mnv
new file mode 100644
index 0000000000..7866631e02
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_match.mnv
@@ -0,0 +1,64 @@
+" MNV :match command
+
+
+match FooGroup /Foo/
+match
+match none
+
+1match FooGroup /Foo/
+1match
+1match none
+
+2match FooGroup /Foo/
+2match
+2match none
+
+3match FooGroup /Foo/
+3match
+3match none
+
+1 match FooGroup /Foo/
+2 match FooGroup /Foo/
+3 match FooGroup /Foo/
+
+
+" Differentiate match() from :match
+
+call match(haystack, 'needle')
+call match (haystack, 'needle')
+
+let foo = match(haystack, 'needle')
+echo match(haystack, 'needle')
+echo (match(haystack, 'needle') + 42)
+echo (42 + match(haystack, 'needle'))
+
+
+" Containing functions
+
+function Foo()
+ match FooGroup /Foo/
+ call match(haystack, 'needle')
+ call match (haystack, 'needle')
+endfunction
+
+def Foo()
+ # command
+ match FooGroup /Foo/
+ # Error: bad :match command - trailing characters
+ match (haystack, 'needle')
+ # function
+ match(haystack, 'needle')
+ call match(haystack, 'needle')
+enddef
+
+
+" Trailing bar and comments
+
+match FooGroup /Foo/ | echo "Foo"
+match | echo "Foo"
+match none | echo "Foo"
+
+match FooGroup /Foo/ " comment
+match " comment
+match none " comment
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_menu.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_menu.mnv
new file mode 100644
index 0000000000..e0981ef46a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_menu.mnv
@@ -0,0 +1,88 @@
+" MNV :menu commands
+
+
+" :help disable menus
+menu disable &File.&Open\.\.\.
+amenu enable *
+amenu disable &Tools.*
+
+
+" :help menu-examples
+nmenu Words.Add\ Var wb"zye:menu! Words.<C-R>z <C-R>z<CR>
+nmenu Words.Remove\ Var wb"zye:unmenu! Words.<C-R>z<CR>
+vmenu Words.Add\ Var "zy:menu! Words.<C-R>z <C-R>z <CR>
+vmenu Words.Remove\ Var "zy:unmenu! Words.<C-R>z<CR>
+imenu Words.Add\ Var <Esc>wb"zye:menu! Words.<C-R>z <C-R>z<CR>a
+imenu Words.Remove\ Var <Esc>wb"zye:unmenu! Words.<C-R>z<CR>a
+
+
+" special keys
+menu <silent> &Foo\ bar :echo "Foobar"<CR>
+menu <special> &Foo\ bar :echo "Foobar"<CR>
+menu <script> &Foo\ bar :echo "Foobar"<CR>
+menu <silent> <special> &Foo\ bar :echo "Foobar"<CR>
+menu <silent> <special> <script> &Foo\ bar :echo "Foobar"<CR>
+
+
+function Foo()
+ menu <silent> &Foo\ bar :echo "Foobar"<CR>
+endfunction
+
+
+" Example: runtime/menu.mnv (modified)
+an <silent> 10.330 &File.&Close<Tab>:close :confirm close<CR>
+
+an <silent> 10.330 &File.&Close<Tab>:close
+ \ :if winheight(2) < 0 && tabpagewinnr(2) == 0 <Bar>
+ \ confirm enew <Bar>
+ \ else <Bar>
+ \ confirm close <Bar>
+ \ endif<CR>
+
+an <silent> 10.330 &File.&Close<Tab>:close
+ "\ comment
+ \ :if winheight(2) < 0 && tabpagewinnr(2) == 0 <Bar>
+ "\ comment
+ \ confirm enew <Bar>
+ "\ comment
+ \ else <Bar>
+ "\ comment
+ \ confirm close <Bar>
+ "\ comment
+ \ endif<CR>
+
+an <silent> 10.330 &File.&Close<Tab>:close :if winheight(2) < 0 && tabpagewinnr(2) == 0 <Bar>
+ \ confirm enew <Bar>
+ \ else <Bar>
+ \ confirm close <Bar>
+ \ endif<CR>
+
+an <silent> 10.330 &File.&Close<Tab>:close :if winheight(2) < 0 && tabpagewinnr(2) == 0 <Bar>
+ "\ comment
+ \ confirm enew <Bar>
+ "\ comment
+ \ else <Bar>
+ "\ comment
+ \ confirm close <Bar>
+ "\ comment
+ \ endif<CR>
+
+
+" popup menus
+popup &Foo | echo "Foo"
+popup! &Foo | echo "Foo"
+
+
+" Issue #14230
+
+" a menu item name cannot start with '.'
+
+def HistoryJumpMenu()
+ popup.FilterMenu("Jump history", dir_hist,
+ (res, _) => {
+ HistoryJump(res.text)
+ })
+enddef
+
+popup\.FilterMenu<Tab>Filter()<CR>
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_menutranslate.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_menutranslate.mnv
new file mode 100644
index 0000000000..81e67b1bf9
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_menutranslate.mnv
@@ -0,0 +1,52 @@
+" MNV :menutranslate command
+
+
+menutranslate clear
+menutranslate clear | echo "Foo"
+menutranslate clear " comment
+
+menutranslate &Foo\ bar &FuBar | echo "Foo"
+
+menutranslate &Foo\ bar &FuBar " comment
+menutranslate \"&Foo"\ bar \"&FuBar
+menutranslate &Foo\ "bar" &FuBar
+
+menutranslate &Foo\ bar
+ \ &Fubar | echo "Foo"
+
+menutranslate
+ \ &Foo\ bar
+ \ &Fubar | echo "Foo"
+
+menutranslate
+ \ &Foo\ bar
+ \ &Fubar| echo "Foo"
+
+menutranslate
+ \ &Foo\ bar
+ \ &Fubar
+ \ | echo "Foo"
+
+menutranslate &Foo\ bar
+ "\ comment
+ \ &Fubar | echo "Foo"
+
+menutranslate
+ "\ comment
+ \ &Foo\ bar
+ "\ comment
+ \ &Fubar | echo "Foo"
+
+menutranslate
+ \ &Foo\ bar
+ "\ comment
+ \ &Fubar| echo "Foo"
+ "\ comment
+
+menutranslate
+ "\ comment
+ \ &Foo\ bar
+ "\ comment
+ \ &Fubar
+ \ | echo "Foo"
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_mnvgrep.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_mnvgrep.mnv
new file mode 100644
index 0000000000..a790ba1141
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_mnvgrep.mnv
@@ -0,0 +1,69 @@
+" MNV :*mnvgrep and :*mnvgrepadd commands
+" MNV_TEST_SETUP hi link mnvMNVgrepFile Todo
+" MNV_TEST_SETUP hi link mnvCmdSep Operator
+" MNV_TEST_SETUP hi link mnvMNVgrepBarEscape Special
+
+
+mnvgrep pa\%(tt\)ern foo.txt
+mnvgrep /pa\%(tt\)ern/ foo.txt
+
+mnvgrep! pa\%(tt\)ern foo.txt
+mnvgrep! /pa\%(tt\)ern/ foo.txt
+
+mnvgrep /pa\%(tt\)ern/gjf foo.txt
+
+" trailing bar, no tail comment
+mnvgrep /pa\%(t|t\)ern/ b\|a\|r.txt | echo "Foo"
+mnvgrep /pa\%(t"t\)ern/ b"a"r.txt | echo "Foo"
+
+mnvgrepadd pa\%(tt\)ern foo.txt
+mnvgrepadd /pa\%(tt\)ern/ foo.txt
+
+mnvgrepadd! pa\%(tt\)ern foo.txt
+mnvgrepadd! /pa\%(tt\)ern/ foo.txt
+
+mnvgrepadd /pa\%(tt\)ern/gjf foo.txt
+
+" trailing bar, no tail comment
+mnvgrepadd /pa\%(t|t\)ern/ b\|a\|r.txt | echo "Foo"
+mnvgrepadd /pa\%(t"t\)ern/ b"a"r.txt | echo "Foo"
+
+lmnvgrep pa\%(tt\)ern foo.txt
+lmnvgrep /pa\%(tt\)ern/ foo.txt
+
+lmnvgrep! pa\%(tt\)ern foo.txt
+lmnvgrep! /pa\%(tt\)ern/ foo.txt
+
+lmnvgrep /pa\%(tt\)ern/gjf foo.txt
+
+" trailing bar, no tail comment
+lmnvgrep /pa\%(t|t\)ern/ b\|a\|r.txt | echo "Foo"
+lmnvgrep /pa\%(t"t\)ern/ b"a"r.txt | echo "Foo"
+
+lmnvgrepadd pa\%(tt\)ern foo.txt
+lmnvgrepadd /pa\%(tt\)ern/ foo.txt
+
+lmnvgrepadd! pa\%(tt\)ern foo.txt
+lmnvgrepadd! /pa\%(tt\)ern/ foo.txt
+
+lmnvgrepadd /pa\%(tt\)ern/gjf foo.txt
+
+" trailing bar, no tail comment
+lmnvgrepadd /pa\%(t|t\)ern/ b\|a\|r.txt | echo "Foo"
+lmnvgrepadd /pa\%(t"t\)ern/ b"a"r.txt | echo "Foo"
+
+
+" file args
+
+" multiple files
+mnvgrep pa\%(tt\)ern foo.txt bar.txt
+mnvgrep /pa\%(tt\)ern/ foo.txt bar.txt
+
+" wildcard patterns
+mnvgrep pa\%(tt\)ern **/*.txt
+mnvgrep /pa\%(tt\)ern/ **/*.txt
+
+" special filename characters
+mnvgrep pa\%(tt\)ern %
+mnvgrep /pa\%(tt\)ern/ %
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_mzscheme.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_mzscheme.mnv
new file mode 100644
index 0000000000..1e2dd6c469
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_mzscheme.mnv
@@ -0,0 +1,157 @@
+" MNV :mzscheme and :mzfile commands
+" MNV_TEST_SETUP let g:mnvsyn_embed = "m"
+" MNV_TEST_SETUP let g:mnvsyn_folding = "fm"
+" MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+
+
+lua << EOF
+print("Lua script")
+EOF
+
+ lua << trim EOF
+ print("Lua script")
+ EOF
+
+lua <<
+print("Lua script")
+.
+
+ lua << trim
+ print("Lua script")
+ .
+
+function Foo()
+ lua << trim EOF
+ print("Lua script in :func")
+ EOF
+endfunction | call Foo()
+
+def Bar()
+ lua << trim EOF
+ print("Lua script in :def")
+ EOF
+enddef | call Bar()
+
+lua print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luado print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luafile foo.lua
+
+
+" :mzscheme and :mzfile
+
+mzscheme << trim EOF
+ (display "MzScheme script")
+EOF
+
+mzscheme (display "MzScheme statement")
+ "\ comment
+ \ (display "MzScheme statement again")
+
+mzfile foo.rkt
+
+
+" :perl and :perldo
+
+perl << trim EOF
+ print("Perl script\n")
+EOF
+
+perl print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+perldo print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+
+" :python, :pydo and :pyfile
+
+python << trim EOF
+ print("Python script")
+EOF
+
+python print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pydo print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pyfile foo.py
+
+
+" :python3, :py3do and :py3file
+
+python3 << trim EOF
+ print("Python3 script")
+EOF
+
+python3 print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3do print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3file foo.py
+
+
+" :pythonx, :pyxdo and :pyxfile
+
+pythonx << trim EOF
+ print("PythonX script")
+EOF
+
+pythonx print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxdo print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxfile foo.py
+
+
+" :ruby, :rubydo and :rubyfile
+
+ruby << trim EOF
+ puts "Ruby script"
+EOF
+
+ruby puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubydo puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubyfile foo.rb
+
+
+" :tcl, :tcldo and :tclfile
+
+tcl << trim EOF
+ puts "TCL script"
+EOF
+
+tcl puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tcldo puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tclfile foo.tcl
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_normal.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_normal.mnv
new file mode 100644
index 0000000000..7a58cb31ba
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_normal.mnv
@@ -0,0 +1,30 @@
+" MNV :normal command
+
+
+normal j
+normal! j
+normal!j
+
+
+" No trailing bar
+
+normal j 42|echo "not echo command"
+
+
+" No trailing comment
+
+normal j "0p
+
+
+" Multiline arg
+
+normal j
+ \k
+ "\ comment
+ \j
+
+
+" Issue: word-boundary required after name (old bug)
+
+normalj
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_perl.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_perl.mnv
new file mode 100644
index 0000000000..a7eceedbc9
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_perl.mnv
@@ -0,0 +1,157 @@
+" MNV :perl and :perldo commands
+" MNV_TEST_SETUP let g:mnvsyn_embed = "p"
+" MNV_TEST_SETUP let g:mnvsyn_folding = "fp"
+" MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+
+
+lua << EOF
+print("Lua script")
+EOF
+
+ lua << trim EOF
+ print("Lua script")
+ EOF
+
+lua <<
+print("Lua script")
+.
+
+ lua << trim
+ print("Lua script")
+ .
+
+function Foo()
+ lua << trim EOF
+ print("Lua script in :func")
+ EOF
+endfunction | call Foo()
+
+def Bar()
+ lua << trim EOF
+ print("Lua script in :def")
+ EOF
+enddef | call Bar()
+
+lua print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luado print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luafile foo.lua
+
+
+" :mzscheme and :mzfile
+
+mzscheme << trim EOF
+ (display "MzScheme script")
+EOF
+
+mzscheme (display "MzScheme statement")
+ "\ comment
+ \ (display "MzScheme statement again")
+
+mzfile foo.rkt
+
+
+" :perl and :perldo
+
+perl << trim EOF
+ print("Perl script\n")
+EOF
+
+perl print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+perldo print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+
+" :python, :pydo and :pyfile
+
+python << trim EOF
+ print("Python script")
+EOF
+
+python print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pydo print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pyfile foo.py
+
+
+" :python3, :py3do and :py3file
+
+python3 << trim EOF
+ print("Python3 script")
+EOF
+
+python3 print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3do print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3file foo.py
+
+
+" :pythonx, :pyxdo and :pyxfile
+
+pythonx << trim EOF
+ print("PythonX script")
+EOF
+
+pythonx print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxdo print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxfile foo.py
+
+
+" :ruby, :rubydo and :rubyfile
+
+ruby << trim EOF
+ puts "Ruby script"
+EOF
+
+ruby puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubydo puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubyfile foo.rb
+
+
+" :tcl, :tcldo and :tclfile
+
+tcl << trim EOF
+ puts "TCL script"
+EOF
+
+tcl puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tcldo puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tclfile foo.tcl
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_profile.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_profile.mnv
new file mode 100644
index 0000000000..38df8fced6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_profile.mnv
@@ -0,0 +1,48 @@
+" MNV :profile and :profdel commands
+
+
+profile start /tmp/myprofile
+profile stop
+profile pause
+profile continue
+profile func MyFunc
+profile file MyScript.mnv
+profile! file MyScript.mnv
+profile dump
+
+profdel func MyFunc
+profdel file MyScript.mnv
+profdel here
+
+
+" Tail comment
+
+profile start /tmp/myprofile " comment
+profile stop " comment
+profile pause " comment
+profile continue " comment
+profile func MyFunc " comment
+profile file MyScript.mnv " comment
+profile! file MyScript.mnv " comment
+profile dump " comment
+
+profdel func MyFunc " comment
+profdel file MyScript.mnv " comment
+profdel here " comment
+
+
+" Trailing command
+
+profile start /tmp/myprofile | echo "Foo"
+profile stop | echo "Foo"
+profile pause | echo "Foo"
+profile continue | echo "Foo"
+profile func MyFunc | echo "Foo"
+profile file MyScript.mnv | echo "Foo"
+profile! file MyScript.mnv | echo "Foo"
+profile dump | echo "Foo"
+
+profdel func MyFunc | echo "Foo"
+profdel file MyScript.mnv | echo "Foo"
+profdel here | echo "Foo"
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_prompt_commands.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_prompt_commands.mnv
new file mode 100644
index 0000000000..d02246add2
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_prompt_commands.mnv
@@ -0,0 +1,46 @@
+" MNV :prompt{find,repl} commands
+
+
+promptfind foo
+promptrepl foo
+
+promptfind a
+ \ really
+ \ long
+ \ search
+ \ string
+promptrepl a
+ \ really
+ \ long
+ \ search
+ \ string
+
+
+" no tail comment or trailing bar
+
+promptfind foo " more search string
+promptfind foo | more search string
+
+
+def MNV9Context()
+ promptfind foo
+ promptrepl foo
+
+ promptfind a
+ \ really
+ \ long
+ \ search
+ \ string
+ promptrepl a
+ \ really
+ \ long
+ \ search
+ \ string
+
+
+ # no tail comment or trailing bar
+
+ promptfind foo # more search string
+ promptfind foo | more search string
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_python.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_python.mnv
new file mode 100644
index 0000000000..4e92e9af3f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_python.mnv
@@ -0,0 +1,159 @@
+" MNV :python, :pydo and :pyfile commands
+" MNV :python3, :py3do and :py3file commands
+" MNV :pythonx, :pyxdo and :pyxfile commands
+" MNV_TEST_SETUP let g:mnvsyn_embed = "P"
+" MNV_TEST_SETUP let g:mnvsyn_folding = "fP"
+" MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+
+
+lua << EOF
+print("Lua script")
+EOF
+
+ lua << trim EOF
+ print("Lua script")
+ EOF
+
+lua <<
+print("Lua script")
+.
+
+ lua << trim
+ print("Lua script")
+ .
+
+function Foo()
+ lua << trim EOF
+ print("Lua script in :func")
+ EOF
+endfunction | call Foo()
+
+def Bar()
+ lua << trim EOF
+ print("Lua script in :def")
+ EOF
+enddef | call Bar()
+
+lua print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luado print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luafile foo.lua
+
+
+" :mzscheme and :mzfile
+
+mzscheme << trim EOF
+ (display "MzScheme script")
+EOF
+
+mzscheme (display "MzScheme statement")
+ "\ comment
+ \ (display "MzScheme statement again")
+
+mzfile foo.rkt
+
+
+" :perl and :perldo
+
+perl << trim EOF
+ print("Perl script\n")
+EOF
+
+perl print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+perldo print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+
+" :python, :pydo and :pyfile
+
+python << trim EOF
+ print("Python script")
+EOF
+
+python print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pydo print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pyfile foo.py
+
+
+" :python3, :py3do and :py3file
+
+python3 << trim EOF
+ print("Python3 script")
+EOF
+
+python3 print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3do print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3file foo.py
+
+
+" :pythonx, :pyxdo and :pyxfile
+
+pythonx << trim EOF
+ print("PythonX script")
+EOF
+
+pythonx print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxdo print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxfile foo.py
+
+
+" :ruby, :rubydo and :rubyfile
+
+ruby << trim EOF
+ puts "Ruby script"
+EOF
+
+ruby puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubydo puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubyfile foo.rb
+
+
+" :tcl, :tcldo and :tclfile
+
+tcl << trim EOF
+ puts "TCL script"
+EOF
+
+tcl puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tcldo puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tclfile foo.tcl
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_range.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_range.mnv
new file mode 100644
index 0000000000..88e7ad4715
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_range.mnv
@@ -0,0 +1,90 @@
+" Ex command ranges
+
+
+'<,'>print
+'(,')print
+'{,'}print
+'[,']print
+
+:'<,'>print
+:'(,')print
+:'{,'}print
+:'[,']print
+
+echo | '<,'>print
+echo | '(,')print
+echo | '{,'}print
+echo | '[,']print
+
+" bare mark ranges
+
+'a
+'k
+'z
+'A
+'K
+'Z
+'0
+'9
+'[
+']
+'{
+'}
+'(
+')
+'<
+'>
+'`
+''
+'"
+'^
+'.
+
+ :'a
+: 'a
+:'a
+:'k
+:'z
+:'A
+:'K
+:'Z
+:'0
+:'9
+:'[
+:']
+:'{
+:'}
+:'(
+:')
+:'<
+:'>
+:'`
+:''
+:'"
+:'^
+:'.
+
+echo |'a
+echo| 'a
+echo | 'a
+echo | 'k
+echo | 'z
+echo | 'A
+echo | 'K
+echo | 'Z
+echo | '0
+echo | '9
+echo | '[
+echo | ']
+echo | '{
+echo | '}
+echo | '(
+echo | ')
+echo | '<
+echo | '>
+echo | '`
+echo | ''
+echo | '"
+echo | '^
+echo | '.
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_redir.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_redir.mnv
new file mode 100644
index 0000000000..1bc2c8a1b1
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_redir.mnv
@@ -0,0 +1,71 @@
+" MNV :redir command
+
+
+redir > filename
+redir! > filename
+redir > file name
+redir! > file name
+
+redir >> filename
+redir! >> filename
+redir >> file name
+redir! >> file name
+
+redir > filename " comment
+redir > filename | echo "Foo"
+redir > file name " comment
+redir > file name | echo "Foo"
+
+redir >> filename " comment
+redir >> filename | echo "Foo"
+redir >> file name " comment
+redir >> file name | echo "Foo"
+
+redir @a
+redir @A
+
+redir @a>
+redir @A>
+
+redir @a>>
+redir @A>>
+
+redir @*>
+redir @+>
+
+redir @*>>
+redir @+>>
+
+redir @">
+redir @">>
+
+redir => var
+redir =>> var
+
+redir END
+
+
+" Issue #18319 (redir command not highlighted in some cases)
+
+def MNV9Context()
+
+var foo: string
+if true
+ redir => foo
+ smile
+ redir END
+endif
+echo foo
+
+command Foo {
+ redir => foo
+ echo "hello from cmd"
+ redir END
+}
+
+redir => foo
+echom "hello global"
+redir END
+
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_ruby.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_ruby.mnv
new file mode 100644
index 0000000000..8a872640b9
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_ruby.mnv
@@ -0,0 +1,157 @@
+" MNV :ruby, :rubydo and :rubyfile commands
+" MNV_TEST_SETUP let g:mnvsyn_embed = "r"
+" MNV_TEST_SETUP let g:mnvsyn_folding = "fr"
+" MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+
+
+lua << EOF
+print("Lua script")
+EOF
+
+ lua << trim EOF
+ print("Lua script")
+ EOF
+
+lua <<
+print("Lua script")
+.
+
+ lua << trim
+ print("Lua script")
+ .
+
+function Foo()
+ lua << trim EOF
+ print("Lua script in :func")
+ EOF
+endfunction | call Foo()
+
+def Bar()
+ lua << trim EOF
+ print("Lua script in :def")
+ EOF
+enddef | call Bar()
+
+lua print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luado print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luafile foo.lua
+
+
+" :mzscheme and :mzfile
+
+mzscheme << trim EOF
+ (display "MzScheme script")
+EOF
+
+mzscheme (display "MzScheme statement")
+ "\ comment
+ \ (display "MzScheme statement again")
+
+mzfile foo.rkt
+
+
+" :perl and :perldo
+
+perl << trim EOF
+ print("Perl script\n")
+EOF
+
+perl print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+perldo print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+
+" :python, :pydo and :pyfile
+
+python << trim EOF
+ print("Python script")
+EOF
+
+python print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pydo print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pyfile foo.py
+
+
+" :python3, :py3do and :py3file
+
+python3 << trim EOF
+ print("Python3 script")
+EOF
+
+python3 print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3do print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3file foo.py
+
+
+" :pythonx, :pyxdo and :pyxfile
+
+pythonx << trim EOF
+ print("PythonX script")
+EOF
+
+pythonx print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxdo print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxfile foo.py
+
+
+" :ruby, :rubydo and :rubyfile
+
+ruby << trim EOF
+ puts "Ruby script"
+EOF
+
+ruby puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubydo puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubyfile foo.rb
+
+
+" :tcl, :tcldo and :tclfile
+
+tcl << trim EOF
+ puts "TCL script"
+EOF
+
+tcl puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tcldo puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tclfile foo.tcl
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_set.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_set.mnv
new file mode 100644
index 0000000000..3ce3efa3b9
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_set.mnv
@@ -0,0 +1,131 @@
+" MNV :set command
+
+
+set
+set!
+set all
+set! all
+set termcap
+set! termcap
+
+set aleph?
+set aleph
+
+set noallowrevins
+
+set allowrevins!
+set invallowrevins
+
+set aleph&
+set aleph&vi
+set aleph&mnv
+
+set all&
+
+set aleph=128
+set aleph:128
+
+set aleph =128
+set aleph :128
+
+set aleph+=96
+set aleph^=2
+set aleph-=96
+
+set backspace+=nostop
+set backspace^=nostop
+set backspace-=nostop
+
+set ai nosi sw=3 tw=3
+
+set <t_#4>=^[Ot
+set <M-b>=^[b
+
+setlocal autoread
+setglobal noautoread
+set autoread<
+
+set " comment
+set | echo "Foo"
+set! " comment
+set! | echo "Foo"
+
+
+" :help option-backslash
+
+" When setting options using |:let| and |literal-string|, you need to use one
+" fewer layer of backslash. A few examples:
+set makeprg=make\ file " results in "make file"
+let &makeprg='make file' " (same as above)
+set makeprg=make\\\ file " results in "make\ file"
+set tags=tags\ /usr/tags " results in "tags" and "/usr/tags"
+set tags=tags\\\ file " results in "tags file"
+let &tags='tags\ file' " (same as above)
+
+set makeprg=make,file " results in "make,file"
+set makeprg=make\\,file " results in "make\,file"
+set tags=tags,file " results in "tags" and "file"
+set tags=tags\\,file " results in "tags,file"
+let &tags='tags\,file' " (same as above)
+
+" This example sets the 'titlestring' option to "hi|there":
+set titlestring=hi\|there
+" This sets the 'titlestring' option to "hi" and 'iconstring' to "there":
+set titlestring=hi|set iconstring=there
+
+set dir=\\machine\path " results in "\\machine\path"
+set dir=\\\\machine\\path " results in "\\machine\path"
+set dir=\\path\\file " results in "\\path\file" (wrong!)
+
+
+" :help :set_env
+
+set term=$TERM.new
+set path=/usr/$INCLUDE,$HOME/include,.
+
+
+" Multiline :set and option values
+
+set path=abc,def,ghi
+ "\ def is the 'define' option
+ \ def=abc,def,ghi
+
+set path=abc,
+ "\ def is a 'path' directory value
+ \def,ghi
+
+set path=
+ "\ def is a 'path' directory value
+ \abc,def
+
+
+" :CompilerSet
+
+CompilerSet makeprg=ant
+CompilerSet errorformat=\ %#[%.%#]\ %#%f:%l:%v:%*\\d:%*\\d:\ %t%[%^:]%#:%m,
+ \%A\ %#[%.%#]\ %f:%l:\ %m,%-Z\ %#[%.%#]\ %p^,%C\ %#[%.%#]\ %#%m
+
+
+" Unreported issue (double backslash)
+
+setlocal com=s1:/*,mb:*,ex:*/,b:--,be:\\
+echo "Foo"
+setlocal include=^\\s*\\%(so\\%[urce]\\\|ru\\%[ntime]\\)[!\ ]\ *\\zs[^\\|]*
+echo "Foo"
+set quoteescape=\\
+echo "Foo"
+set quoteescape=\
+echo "Foo"
+
+
+" Issue #16913 (mnv syntax: set langmap may have wrong highlight)
+
+set langmap+=ФЫВАПРОЛДЖЭЁ;ASDFGHJKL\\:\\"\\|
+set langmap+=ЯЧСМИТЬБЮ;ZXCVBNM<>
+
+set langmap+=ФЫВАПРОЛДЖЭЁ;ASDFGHJKL\\:\\"\\|
+ \ langmap+=ЯЧСМИТЬБЮ;ZXCVBNM<>
+
+set langmap+=ФЫВАПР;ASDFGH langmap+=ОЛДЖЭЁ;JKL\\:\\"\\|
+ \ langmap+=ЯЧСМИ;ZXCVB langmap+=ТЬБЮ;NM<>
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_set_backslash.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_set_backslash.mnv
new file mode 100644
index 0000000000..161e8b1230
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_set_backslash.mnv
@@ -0,0 +1,79 @@
+" MNV :set command (escaped characters)
+" MNV_TEST_SETUP hi link mnvSetEscape DiffAdd
+" MNV_TEST_SETUP hi link mnvSetBarEscape DiffDelete
+" MNV_TEST_SETUP hi link mnvSetQuoteEscape DiffDelete
+" MNV_TEST_SETUP hi link mnvSetEqual DiffChange
+
+
+echo "-- 1 --"
+set titlestring=\afoo\abar\a " comment
+echo &titlestring
+set titlestring=\afoo\abar\a
+echo &titlestring
+set titlestring=\ foo\ bar\ " comment
+echo &titlestring
+set titlestring=\ foo\ bar\
+echo &titlestring
+set titlestring=\|foo\|bar\| " comment
+echo &titlestring
+set titlestring=\|foo\|bar\|
+echo &titlestring
+set titlestring=\"foo\"bar\" " comment
+echo &titlestring
+set titlestring=\"foo\"bar\"
+echo &titlestring
+
+echo "-- 2 --"
+set titlestring=\\afoo\\abar\\a " comment
+echo &titlestring
+set titlestring=\\afoo\\abar\\a
+echo &titlestring
+set titlestring=\\ foo\\ bar\\ " comment
+echo &titlestring
+set titlestring=\\ foo\\ bar\\
+echo &titlestring
+set titlestring=\\|foo\\|bar\\| " comment
+echo &titlestring
+set titlestring=\\|foo\\|bar\\|
+echo &titlestring
+set titlestring=\\"foo\\"bar\\" " comment
+echo &titlestring
+set titlestring=\\"foo\\"bar\\"
+echo &titlestring
+
+echo "-- 3 --"
+set titlestring=\\\afoo\\\abar\\\a " comment
+echo &titlestring
+set titlestring=\\\afoo\\\abar\\\a
+echo &titlestring
+set titlestring=\\\ foo\\\ bar\\\ " comment
+echo &titlestring
+set titlestring=\\\ foo\\\ bar\\\
+echo &titlestring
+set titlestring=\\\|foo\\\|bar\\\| " comment
+echo &titlestring
+set titlestring=\\\|foo\\\|bar\\\|
+echo &titlestring
+set titlestring=\\\"foo\\\"bar\\\" " comment
+echo &titlestring
+set titlestring=\\\"foo\\\"bar\\\"
+echo &titlestring
+
+echo "-- 4 --"
+set titlestring=\\\\afoo\\\\abar\\\\a " comment
+echo &titlestring
+set titlestring=\\\\afoo\\\\abar\\\\a
+echo &titlestring
+set titlestring=\\\\ foo\\\\ bar\\\\ " comment
+echo &titlestring
+set titlestring=\\\\ foo\\\\ bar\\\\
+echo &titlestring
+set titlestring=\\\\|foo\\\\|bar\\\\| " comment
+echo &titlestring
+set titlestring=\\\\|foo\\\\|bar\\\\|
+echo &titlestring
+set titlestring=\\\\"foo\\\\"bar\\\\" " comment
+echo &titlestring
+set titlestring=foo\\\\"\\\\"bar\\\\"
+echo &titlestring
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_sleep.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_sleep.mnv
new file mode 100644
index 0000000000..ffc731caf9
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_sleep.mnv
@@ -0,0 +1,13 @@
+" MNV :sleep command
+
+
+sleep " sleep for one second
+5 sleep " sleep for five seconds
+sleep 100m " sleep for 100 milliseconds
+100 sleep m " sleep for 100 milliseconds
+
+sleep! " sleep for one second
+5 sleep! " sleep for five seconds
+sleep! 100m " sleep for 100 milliseconds
+100 sleep! m " sleep for 100 milliseconds
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_sort.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_sort.mnv
new file mode 100644
index 0000000000..b7160c89c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_sort.mnv
@@ -0,0 +1,64 @@
+" MNV :sort command
+" MNV_TEST_SETUP hi link mnvCmdSep Operator
+
+
+sort
+sort!
+
+sort ilu
+sort! ilu
+
+sort /pa\%(tt\)ern/ ilu
+sort! /pa\%(tt\)ern/ ilu
+
+sort /pa\%(tt\)ern/ rilu
+sort! /pa\%(tt\)ern/ rilu
+
+sort ilu /pa\%(tt\)ern/
+sort! ilu /pa\%(tt\)ern/
+
+sort rilu /pa\%(tt\)ern/
+sort! rilu /pa\%(tt\)ern/
+
+sort nilu
+sort! nilu
+sort filu
+sort! filu
+sort xilu
+sort! xilu
+sort oilu
+sort! oilu
+sort bilu
+sort! bilu
+
+sort /pa\%(tt\)ern/ nilu
+sort! /pa\%(tt\)ern/ nilu
+sort /pa\%(tt\)ern/ filu
+sort! /pa\%(tt\)ern/ filu
+sort /pa\%(tt\)ern/ xilu
+sort! /pa\%(tt\)ern/ xilu
+sort /pa\%(tt\)ern/ oilu
+sort! /pa\%(tt\)ern/ oilu
+sort /pa\%(tt\)ern/ bilu
+sort! /pa\%(tt\)ern/ bilu
+
+sort /pa\%(tt\)ern/ rnilu
+sort! /pa\%(tt\)ern/ rnilu
+sort /pa\%(tt\)ern/ rfilu
+sort! /pa\%(tt\)ern/ rfilu
+sort /pa\%(tt\)ern/ rxilu
+sort! /pa\%(tt\)ern/ rxilu
+sort /pa\%(tt\)ern/ roilu
+sort! /pa\%(tt\)ern/ roilu
+sort /pa\%(tt\)ern/ rbilu
+sort! /pa\%(tt\)ern/ rbilu
+
+sort | echo "Foo"
+sort! | echo "Foo"
+
+sort /pa\%(t|t\)ern/ rilu | echo "Foo"
+sort! /pa\%(t|t\)ern/ rilu | echo "Foo"
+
+sort rilu /pa\%(t|t\)ern/ | echo "Foo"
+sort! rilu /pa\%(t|t\)ern/ | echo "Foo"
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_substitute.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_substitute.mnv
new file mode 100644
index 0000000000..a57d577c5d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_substitute.mnv
@@ -0,0 +1,208 @@
+" MNV :substitute command
+
+
+substitute/foo/bar/&
+substitute/foo/bar/cegiInp#lr
+
+snomagic/foo/bar/&
+snomagic/foo/bar/cegiInp#lr
+
+smagic/foo/bar/&
+smagic/foo/bar/cegiInp#lr
+
+:substitute/foo/bar/&
+:substitute/foo/bar/cegiInp#lr
+
+:snomagic/foo/bar/&
+:snomagic/foo/bar/cegiInp#lr
+
+:smagic/foo/bar/&
+:smagic/foo/bar/cegiInp#lr
+
+call Foo() | substitute/foo/bar/&
+call Foo() | substitute/foo/bar/cegiInp#lr
+
+call Foo() | snomagic/foo/bar/&
+call Foo() | snomagic/foo/bar/cegiInp#lr
+
+call Foo() | smagic/foo/bar/&
+call Foo() | smagic/foo/bar/cegiInp#lr
+
+let foo = str->substitute(str, pat, sub, flags)
+
+function Foo()
+ substitute/foo/bar/
+ let bar = str->substitute(str, pat, sub, flags)
+endfunction
+
+def Foo()
+ substitute/foo/bar/
+ let bar = str->substitute(str, pat, sub, flags)
+enddef
+
+
+" various delimiters
+
+s!/!//! " comment
+" s"/"//" " comment (works but disallowed)
+s#/#//# " comment
+s$/$//$ " comment
+s%/%//% " comment
+s&/&//& " comment
+s'/'//' " comment
+" FIXME - matches mnvUserFunc
+" s(/(//( " comment
+s)/)//) " comment
+s*/*//* " comment
+s+/+//+ " comment
+s,/,//, " comment
+s-/-//- " comment
+s././/. " comment
+s/X/XX/ " comment
+s:/://: " comment
+s;/;//; " comment
+s</<//< " comment
+s=/=//= " comment
+s>/>//> " comment
+s?/?//? " comment
+s@/@//@ " comment
+s[/[//[ " comment
+" s\/\//\ " comment (disallowed)
+s]/]//] " comment
+s^/^//^ " comment
+s_/_//_ " comment
+s`/`//` " comment
+s{/{//{ " comment
+" s|/|//| " comment (disallowed)
+s}/}//} " comment
+s~/~//~ " comment
+
+s !/!//! " comment
+" s "/"//" " comment (works but disallowed)
+s #/#//# " comment
+s $/$//$ " comment
+s %/%//% " comment
+s &/&//& " comment
+s '/'//' " comment
+" FIXME - matches mnvUserFunc
+" s (/(//( " comment
+s )/)//) " comment
+s */*//* " comment
+s +/+//+ " comment
+s ,/,//, " comment
+s -/-//- " comment
+s ././/. " comment
+s /X/XX/ " comment
+s :/://: " comment
+s ;/;//; " comment
+s </<//< " comment
+s =/=//= " comment
+s >/>//> " comment
+s ?/?//? " comment
+s @/@//@ " comment
+s [/[//[ " comment
+" s \/\//\ " comment (disallowed)
+s ]/]//] " comment
+s ^/^//^ " comment
+s _/_//_ " comment
+s `/`//` " comment
+s {/{//{ " comment
+" s |/|//| " comment (disallowed)
+s }/}//} " comment
+s ~/~//~ " comment
+
+s//{string}/
+s //{string}/
+
+
+" Repeat commands
+
+s
+:s
+s 42
+:s 42
+s42
+:s42
+
+s cegiInp#lr
+:s cegiInp#lr
+s cegiInp#lr42
+:s cegiInp#lr42
+s cegiInp#lr 42
+:s cegiInp#lr 42
+
+sg
+:sg
+sgi
+:sgi
+sg 42
+:sg 42
+sgi 42
+:sgi 42
+sg42
+:sg42
+sgi42
+:sgi42
+
+" FIXME
+&
+&&
+~
+~&
+
+" FIXME
+&cegiInp#lr
+&&cegiInp#lr
+~cegiInp#lr
+~&cegiInp#lr
+
+" 2 and 3 letter repeat-previous variants
+
+:sc | :sce | :scg | :sci | :scI | :scn | :scp | :scl |
+:sgc | :sge | :sg | :sgi | :sgI | :sgn | :sgp | :sgl | :sgr
+:sic | :sie | | :si | :siI | :sin | :sip | | :sir
+:sIc | :sIe | :sIg | :sIi | :sI | :sIn | :sIp | :sIl | :sIr
+:src | | :srg | :sri | :srI | :srn | :srp | :srl | :sr
+
+
+" exceptions
+:scr " is `:scriptnames`
+:se " is `:set`
+:sig " is `:sign`
+:sil " is `:silent`
+:sn " is `:snext`
+:sp " is `:split`
+:sl " is `:sleep`
+:sre " is `:srewind`
+
+
+" Vi compatibility
+
+s\/{string}/
+s\?{string}?
+s\&{string}&
+
+s \/{string}/
+s \?{string}?
+s \&{string}&
+
+
+" Trailing comment and bar
+
+s" comment
+s| echo "Foo"
+
+s " comment
+s | echo "Foo"
+
+
+" Issue #13883
+
+str[s]
+str(s)
+
+def Test()
+ str[s]
+ str(s)
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_syntax.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_syntax.mnv
new file mode 100644
index 0000000000..4b9d81c1ac
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_syntax.mnv
@@ -0,0 +1,377 @@
+" MNV :syntax command
+" MNV_TEST_SETUP hi link mnvGroupList Todo
+
+
+" :syn-case
+
+syntax case
+syntax case match
+syntax case ignore
+
+" :syn clear
+
+syntax clear @testCluster
+syntax clear testGroup
+syntax clear @testCluster testGroup
+syntax clear testGroup @testCluster
+
+" :syn-conceal
+
+syntax conceal
+syntax conceal on
+syntax conceal off
+
+" :syn-foldlevel
+
+syntax foldlevel
+syntax foldlevel start
+syntax foldlevel minimum
+
+" :syn-include
+
+syntax include @Foo <sfile>:p:h/foo.mnv
+syntax include <sfile>:p:h/foo.mnv
+
+" :syn-iskeyword
+
+syntax iskeyword
+syntax iskeyword clear
+syntax iskeyword @,48-57,192-255,$,_
+
+" :syn-list
+
+syntax list
+syntax list Foo
+syntax list @Bar
+
+" :syn-spell
+
+syntax spell
+syntax spell toplevel
+syntax spell notoplevel
+syntax spell default
+
+" :syn-sync-ccomment
+
+syntax sync ccomment
+syntax sync ccomment Foo
+syntax sync ccomment minlines=42 maxlines=42 linebreaks=1 linecont "pattern"
+syntax sync ccomment Foo minlines=42 maxlines=42 linebreaks=1 linecont "pattern"
+
+" :syn-sync-fromstart
+
+syntax sync fromstart
+syntax sync fromstart minlines=42 maxlines=42 linebreaks=1 linecont "pattern"
+
+" :syn-sync-linebreaks
+
+syntax sync linebreaks=1
+syntax sync linebreaks=1 minlines=42 maxlines=42 linecont "pattern"
+
+" :syn-sync-linecont
+
+syntax sync linecont "pattern"
+syntax sync linecont "pattern" minlines=42 maxlines=42 linebreaks=1
+
+" :syn-sync-(min|max)lines
+
+syntax sync minlines=42 maxlines=42
+syntax sync minlines=42 maxlines=42 linebreaks=1 linecont "pattern"
+" obsolete
+syntax sync lines=42
+
+" :syn-sync sync patterns
+
+syntax sync match testSyncMatch grouphere testFoo "pattern"
+syntax sync match testSyncMatch groupthere testBar "pattern"
+syntax sync match testSyncMatch grouphere NONE "pattern"
+syntax sync match testSyncMatch groupthere NONE "pattern"
+
+" :syn-sync skip groups
+
+syn sync match testMatch "pattern"
+syn sync region testRegion start="start-pattern" skip="skip-pattern" end="end-pattern"
+
+" :syn-sync-clear
+
+syntax sync clear
+syntax sync clear Foo
+
+" tail comments are not explicitly supported by :syntax, see :help :comment
+syn match testMatch "pattern" contained " tail comment
+" NOTE: comments not currently supported
+syn keyword testKeyword keyword contained " tail comment
+syn region testRegion start="start-pattern" skip="skip-pattern" end="end-pattern" contained " tail comment
+
+" Multiline commands
+
+syn keyword testKeyword
+ "\ OPTIONS
+ "\ conceal option
+ \ conceal
+ "\ cchar option
+ \ cchar=&
+ "\ contained option
+ \ contained
+ "\ containedin option
+ \ containedin=testContainer
+ "\ nextgroup option
+ \ nextgroup=testNext0,@testCluster
+ "\ transparent option
+ \ transparent
+ "\ skipwhite option
+ \ skipwhite
+ "\ skipempty option
+ \ skipempty
+ "\ skipnl option
+ \ skipnl
+ "\ KEYWORDS LIST
+ "\ keyword 1
+ \ keyword1
+ "\ keyword 2
+ \ keyword2
+ "\ keyword 3
+ \ keyword3
+
+syn match testMatch
+ "\ MATCH PATTERN
+ "\ pattern start
+ \ /
+ "\ part 1 description
+ \pat1a .* pat1b
+ "\ part 2 description
+ \pat2a .* pat2b
+ "\ part 3 description
+ \pat3a .* pat3b
+ "\ pattern end
+ \/
+ "\ OPTIONS
+ "\ conceal option
+ \ conceal
+ "\ cchar option
+ \ cchar=&
+ "\ contained option
+ \ contained
+ "\ containedin option
+ \ containedin=testContainer
+ "\ nextgroup option
+ \ nextgroup=testNext0,@testCluster
+ "\ transparent option
+ \ transparent
+ "\ skipwhite option
+ \ skipwhite
+ "\ skipempty option
+ \ skipempty
+ "\ skipnl option
+ \ skipnl
+ "\ contains option
+ \ contains=testContained1,testContained2
+ "\ fold option
+ \ fold
+ "\ display option
+ \ display
+ "\ extend option
+ \ extend
+ "\ excludenl option
+ \ excludenl
+ "\ keepend option
+ \ keepend
+
+syn region testRegion
+ "\ OPTIONS
+ "\ start option
+ \ start="start-pattern"
+ "\ skip option
+ \ skip="skip-pattern"
+ "\ end option
+ \ end="end-pattern"
+ "\ conceal option
+ \ conceal
+ "\ cchar option
+ \ cchar=&
+ "\ contained option
+ \ contained
+ "\ containedin option
+ \ containedin=testContainer
+ "\ nextgroup option
+ \ nextgroup=testNext0,@testCluster
+ "\ transparent option
+ \ transparent
+ "\ skipwhite option
+ \ skipwhite
+ "\ skipempty option
+ \ skipempty
+ "\ skipnl option
+ \ skipnl
+ "\ contains option
+ \ contains=testContained1,testContained2
+ "\ oneline option
+ \ oneline
+ "\ fold option
+ \ fold
+ "\ display option
+ \ display
+ "\ extend option
+ \ extend
+ "\ concealends option
+ \ concealends
+ "\ excludenl option
+ \ excludenl
+ "\ keepend option
+ \ keepend
+
+syn cluster testCluster
+ "\ OPTIONS
+ "\ contains option
+ \ contains=testContained1,testContained2,testContained3
+
+syn cluster testCluster
+ "\ OPTIONS
+ "\ add option
+ \ add=testAdd
+ "\ remove option
+ \ remove=testRemove
+
+
+" multiline group list
+
+syn keyword testNext0 keyword
+syn keyword testNext1 keyword
+syn keyword testNext2 keyword
+syn keyword testNext3 keyword
+syn keyword testNext4 keyword
+syn keyword testNext5 keyword
+syn keyword testNext6 keyword
+syn keyword testNext7 keyword
+syn keyword testNext8 keyword
+syn keyword testNext9 keyword
+
+syn keyword testKeyword
+ "\ nextgroup option
+ \ nextgroup=
+ "\ a comment
+ \ testNext0 , testNext1 ,
+ "\ a comment
+ \ testNext[2-8].* ,
+ "\ a comment
+ \ testNext9 , @testCluster skipwhite
+ "\ KEYWORDS LIST
+ \ keyword4
+ \ keyword5
+ \ keyword6
+
+syn keyword testKeyword
+ "\ nextgroup option
+ \ nextgroup= testNext0,
+ "\ comment
+ \ , testNext1
+ "\ comment
+ \, testNext2
+ "\ comment
+ \ ,textNext3
+ "\ comment
+ \,textNext4
+ "\ comment
+ \ , textNext5 ,
+ "\ comment
+ \ textNext6,
+ "\ comment
+ \ textNext7 ,
+ "\ comment
+ \textNext8,
+ "\ comment
+ \textNext9 ,
+ "\ comment
+ \ textNext10
+ "\ comment
+ \ ,textNext11,
+ "\ comment
+ \ textNext12,textNext13,
+ "\ comment
+ \ textNext13,textNext14
+ "\ comment
+ \ ,textNext15,textNext16
+ "\ comment
+ \ , textNext17 , textNext18 ,
+ "\ comment
+ \ textNext19, @testCluster
+ \ skipnl
+ "\ KEYWORDS LIST
+ "\ keyword 1
+ \ keyword1
+ "\ keyword 2
+ \ keyword2
+ "\ keyword 3
+ \ keyword3
+
+
+" leaking contained groups
+
+" Example: runtime/syntax/zsh.mnv
+" "cluster" should not be highlighted outside of :syntax commands
+
+function! s:ContainedGroup()
+ " ...
+ for cluster in ['markdownHighlight_zsh', 'zsh']
+ " ...
+ endfor
+ " ...
+endfunction
+
+
+" early termination of mnvSynRegion
+
+syn region testRegion
+ "\ | does not end the args region
+ "\ start="foo\|bar"
+ \ start="start"
+ \ end="end"
+
+
+" Issue #18491 (Two ")"s are incorrectly colored 'mnvOperError' in syntax/mail.mnv)
+
+syn match mailHeaderKey contained contains=mailHeaderEmail,mailEmail,@NoSpell "\v(^(\> ?)*)@<=(from|reply-to):.*$" fold
+
+
+" Issue #19366 (highlight error for contains elements in a new line)
+" syntax/typst.mnv
+
+" Code {{{1
+syntax cluster typstCode
+ \ contains=@typstCommon
+ \ ,@typstCodeKeywords
+ \ ,@typstCodeConstants
+ \ ,@typstCodeIdentifiers
+ \ ,@typstCodeFunctions
+ \ ,@typstCodeParens
+
+" Code > Keywords {{{2
+syntax cluster typstCodeKeywords
+ \ contains=typstCodeConditional
+ \ ,typstCodeRepeat
+ \ ,typstCodeKeyword
+ \ ,typstCodeStatement
+
+syntax cluster typstCodeKeywords
+ \ contains=
+ "\ comment
+ \ typstCodeConditional
+ \ ,typstCodeRepeat
+ \ ,typstCodeKeyword
+ \ ,typstCodeStatement
+
+
+syntax cluster typstCodeKeywords
+ \ contains=
+ "\ comment
+ \ typstCodeConditional
+ \ ,typstCodeRepeat
+ \ ,typstCodeKeyword
+ \ ,typstCodeStatement
+
+
+" Examples from distributed syntax files
+
+syn match slrnrcColorInit contained "^\s*color\s\+\S\+" skipwhite nextgroup=slrnrcColorVal\(Str\)\= contains=slrnrcColor\(Obj\|ObjStr\)\=
+syn region slrnrcCmdLine matchgroup=slrnrcCmd start="\<\(autobaud\|...\|visible_headers\)\>" end="$" oneline contains=slrnrc\(String\|Comment\)
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_syntime.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_syntime.mnv
new file mode 100644
index 0000000000..a2065d4c78
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_syntime.mnv
@@ -0,0 +1,38 @@
+" MNV :syntime command
+
+
+syntime on
+syntime off
+syntime clear
+syntime report
+
+syntime on | redraw! | syntime report
+
+syntime on | echo "..."
+syntime on " comment
+syntime off | echo "..."
+syntime off " comment
+syntime clear | echo "..."
+syntime clear " comment
+syntime report | echo "..."
+syntime report " comment
+
+
+def MNV9Context()
+ syntime on
+ syntime off
+ syntime clear
+ syntime report
+
+ syntime on | redraw! | syntime report
+
+ syntime on | echo "..."
+ syntime on # comment
+ syntime off | echo "..."
+ syntime off # comment
+ syntime clear | echo "..."
+ syntime clear # comment
+ syntime report | echo "..."
+ syntime report # comment
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_tcl.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_tcl.mnv
new file mode 100644
index 0000000000..cda19e6fe5
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_tcl.mnv
@@ -0,0 +1,157 @@
+" MNV :tcl, :tcldo and :tclfile commands
+" MNV_TEST_SETUP let g:mnvsyn_embed = "t"
+" MNV_TEST_SETUP let g:mnvsyn_folding = "ft"
+" MNV_TEST_SETUP setl fdc=2 fdl=99 fdm=syntax
+
+
+lua << EOF
+print("Lua script")
+EOF
+
+ lua << trim EOF
+ print("Lua script")
+ EOF
+
+lua <<
+print("Lua script")
+.
+
+ lua << trim
+ print("Lua script")
+ .
+
+function Foo()
+ lua << trim EOF
+ print("Lua script in :func")
+ EOF
+endfunction | call Foo()
+
+def Bar()
+ lua << trim EOF
+ print("Lua script in :def")
+ EOF
+enddef | call Bar()
+
+lua print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luado print("Lua statement")
+ "\ comment
+ \ print("Lua statement again")
+
+luafile foo.lua
+
+
+" :mzscheme and :mzfile
+
+mzscheme << trim EOF
+ (display "MzScheme script")
+EOF
+
+mzscheme (display "MzScheme statement")
+ "\ comment
+ \ (display "MzScheme statement again")
+
+mzfile foo.rkt
+
+
+" :perl and :perldo
+
+perl << trim EOF
+ print("Perl script\n")
+EOF
+
+perl print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+perldo print("Perl statement\n");
+ "\ comment
+ \ print("Perl statement again\n")
+
+
+" :python, :pydo and :pyfile
+
+python << trim EOF
+ print("Python script")
+EOF
+
+python print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pydo print("Python statement");
+ "\ comment
+ \ print("Python statement again")
+
+pyfile foo.py
+
+
+" :python3, :py3do and :py3file
+
+python3 << trim EOF
+ print("Python3 script")
+EOF
+
+python3 print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3do print("Python3 statement");
+ "\ comment
+ \ print("Python3 statement")
+
+py3file foo.py
+
+
+" :pythonx, :pyxdo and :pyxfile
+
+pythonx << trim EOF
+ print("PythonX script")
+EOF
+
+pythonx print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxdo print("PythonX statement");
+ "\ comment
+ \ print("PythonX statement")
+
+pyxfile foo.py
+
+
+" :ruby, :rubydo and :rubyfile
+
+ruby << trim EOF
+ puts "Ruby script"
+EOF
+
+ruby puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubydo puts "Ruby statement";
+ "\ comment
+ \ puts "Ruby statement again"
+
+rubyfile foo.rb
+
+
+" :tcl, :tcldo and :tclfile
+
+tcl << trim EOF
+ puts "TCL script"
+EOF
+
+tcl puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tcldo puts "TCL statement";
+ "\ comment
+ \ puts "TCL statement again"
+
+tclfile foo.tcl
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_terminal.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_terminal.mnv
new file mode 100644
index 0000000000..289e2e51fb
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_terminal.mnv
@@ -0,0 +1,69 @@
+" MNV :terminal command
+" MNV_TEST_SETUP hi link mnvTerminalCommand Todo
+
+
+terminal
+terminal ++kill=term tail -f /tmp/log
+terminal ++hidden ++open make
+
+
+" line continuations
+
+terminal ++kill=term ++hidden tail
+ \ -f
+ \ /tmp/log
+terminal ++kill=term ++hidden
+ \ tail
+ \ -f
+ \ /tmp/log
+terminal ++kill=term
+ \ ++hidden
+ \ tail
+ \ -f
+ \ /tmp/log
+terminal
+ \ ++kill=term
+ \ ++hidden
+ \ tail
+ \ -f
+ \ /tmp/log
+terminal
+ "\ comment
+ \ ++kill=term
+ "\ comment
+ \ ++hidden
+ "\ comment
+ \ tail
+ "\ comment
+ \ -f
+ "\ comment
+ \ /tmp/log
+
+
+" all options
+
+terminal ++close ++noclose ++open ++curwin ++hidden ++norestore ++shell ++kill=term ++rows=42 ++cols=42 ++eof=exit ++type=conpty ++api=Tapi_ tail -f /tmp/log
+terminal
+ \ ++close
+ \ ++noclose
+ \ ++open
+ \ ++curwin
+ \ ++hidden
+ \ ++norestore
+ \ ++shell
+ \ ++kill=term
+ \ ++rows=42
+ \ ++cols=42
+ \ ++eof=exit
+ \ ++type=conpty
+ \ ++api=Tapi_
+ \ tail
+ \ -f
+ \ /tmp/log
+
+
+" escaped option prefix ++
+
+terminal \++close
+terminal ++close \++noclose
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_throw.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_throw.mnv
new file mode 100644
index 0000000000..53b919d683
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_throw.mnv
@@ -0,0 +1,7 @@
+" MNV :throw command
+
+
+" :help :throw
+
+try | throw "oops" | catch /^oo/ | echo "caught" | endtry
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_uniq.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_uniq.mnv
new file mode 100644
index 0000000000..3279449e06
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_uniq.mnv
@@ -0,0 +1,31 @@
+" MNV :uniq command
+" MNV_TEST_SETUP hi link mnvCmdSep Operator
+
+
+uniq
+uniq!
+
+uniq ilu
+uniq! ilu
+
+uniq /pa\%(tt\)ern/ ilu
+uniq! /pa\%(tt\)ern/ ilu
+
+uniq /pa\%(tt\)ern/ rilu
+uniq! /pa\%(tt\)ern/ rilu
+
+uniq ilu /pa\%(tt\)ern/
+uniq! ilu /pa\%(tt\)ern/
+
+uniq rilu /pa\%(tt\)ern/
+uniq! rilu /pa\%(tt\)ern/
+
+uniq | echo "Foo"
+uniq! | echo "Foo"
+
+uniq /pa\%(t|t\)ern/ rilu | echo "Foo"
+uniq! /pa\%(t|t\)ern/ rilu | echo "Foo"
+
+uniq rilu /pa\%(t|t\)ern/ | echo "Foo"
+uniq! rilu /pa\%(t|t\)ern/ | echo "Foo"
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_ex_wincmd.mnv b/mnv/runtime/syntax/testdir/input/mnv_ex_wincmd.mnv
new file mode 100644
index 0000000000..701f5bd0ff
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_ex_wincmd.mnv
@@ -0,0 +1,67 @@
+" MNV :wincmd command
+" MNV_TEST_SETUP hi link mnvWincmdArg Todo
+" MNV_TEST_SETUP hi link mnvCmdSep Special
+
+
+wincmd s
+wincmd S
+wincmd v
+wincmd n
+wincmd ^
+wincmd :
+wincmd q
+wincmd o
+wincmd j
+wincmd k
+wincmd h
+wincmd l
+wincmd w
+wincmd W
+wincmd t
+wincmd b
+wincmd p
+wincmd P
+wincmd r
+wincmd R
+wincmd x
+wincmd K
+wincmd J
+wincmd H
+wincmd L
+wincmd T
+wincmd =
+wincmd -
+wincmd +
+wincmd _
+wincmd <
+wincmd >
+wincmd |
+wincmd ]
+wincmd g ]
+wincmd f
+wincmd F
+wincmd gf
+wincmd gF
+wincmd gt
+wincmd gT
+wincmd z
+wincmd }
+wincmd g }
+
+
+wincmd | | echo "Foo"
+wincmd | " comment
+wincmd s | echo "Foo"
+wincmd s " comment
+
+
+def MNV9Context()
+ var wincmd = 42
+ wincmd = 42
+ :wincmd =
+ wincmd = # comment
+ wincmd = | echo "Foo"
+ # KNOWN: incorrectly matches as the Ex command rather than a variable
+ wincmd =
+enddef
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_expressions.mnv b/mnv/runtime/syntax/testdir/input/mnv_expressions.mnv
new file mode 100644
index 0000000000..ba4f7de153
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_expressions.mnv
@@ -0,0 +1,426 @@
+" MNV expressions
+
+
+" String
+
+echo 'It''s a string'
+echo 'tab: \t, new line: \n, backslash: \\'
+echo "tab: \t, new line: \n, backslash: \\"
+
+" string starts immediately after line continuation character - tests a
+" comment/string distinguishing implementation quirk
+echo "foo"
+ \"bar"
+ \ "baz"
+echo 'foo'
+ \'bar'
+ \ 'baz'
+
+" String escape sequences
+
+echo "\316 - \31 - \3 - \x1f - \xf - \X1F - \XF - \u02a4 - \U000002a4 - \b - \e - \f - \n - \r - \t - \\ - \" - \<C-W>"
+echo '\316 \31 \3 \x1f \xf \X1F \XF \u02a4 \U000002a4 \b \e \f \n \r \t \\ \" \<C-W>'
+echo "\3160 - \x1f0 - \X1F0 - \u02a40 - \U000002a40"
+
+echo $"\316 - \31 - \3 - \x1f - \xf - \X1F - \XF - \u02a4 - \U000002a4 - \b - \e - \f - \n - \r - \t - \\ - \" - \<C-W>"
+echo $'\316 \31 \3 \x1f \xf \X1F \XF \u02a4 \U000002a4 \b \e \f \n \r \t \\ \" \<C-W>'
+echo $"\3160 - \x1f0 - \X1F0 - \u02a40 - \U000002a40"
+
+echo "\<C-a>"
+echo "\<*C-a>"
+echo "\<C->>"
+echo "\<*C->>"
+echo "\<C->>>"
+echo "\<*C->>>"
+
+echo ""
+echo "\""
+echo "foo\""
+echo "\"foo"
+echo "foo\"bar"
+
+echo ''
+echo ''''
+echo '''foo'
+echo 'foo'''
+echo 'foo''bar'
+
+" Unreported issue (incorrectly matches as mnvString mnvMark mnvOper NONE)
+" https://github.com/tpope/mnv-unimpaired/blob/6d44a6dc2ec34607c41ec78acf81657248580bf1/plugin/unimpaired.mnv#L232
+let cmd = 'put!=repeat(nr2char(10), v:count1)|silent '']+'
+
+
+" String interpolation
+
+echo 'Don''t highlight interpolation: {{ {1 + 2} }}'
+echo "Don't highlight interpolation: {{ {1 + 2} }}"
+echo $'Highlight interpolation:\t{{ { string({'foo': 'bar'}) } }}'
+echo $'Highlight interpolation:\t{{ { $'nested: {{ {1 + 2} }}' } }}'
+echo $"Highlight interpolation:\t{{ { string({"foo": "bar"}) } }}"
+echo $"Highlight interpolation:\t{{ { $"nested: {{ {1 + 2} }}" } }}"
+
+
+" Continued string
+
+let s = "
+ "\ comment
+ \ part 1
+ "\ comment
+ \ part 2
+ "\ comment
+ \" " tail comment
+
+let s = "\"
+ \\" part 1 \"
+ "\ escape sequence
+ \ \"part 2\"
+ \\"" " tail comment
+
+let s = '
+ "\ comment
+ \ part 1
+ "\ comment
+ \ part 2
+ "\ comment
+ \' " tail comment
+
+let s = '''
+ \'' part 1 ''
+ "\ escape sequence
+ \ ''part 2''
+ \''' " tail comment
+
+let s = $"
+ "\ comment
+ \ part 1
+ "\ comment
+ \ part 2
+ "\ comment
+ \" " tail comment
+
+let s = $'
+ "\ comment
+ \ part 1
+ "\ comment
+ \ part 2
+ "\ comment
+ \' " tail comment
+
+call strlen("part 1
+ "\ comment
+ \ part 2")
+
+call append(0, "part 1
+ "\ comment
+ \ part 2")
+
+
+" Number
+
+" Hexadecimal
+echo 0xFF
+echo 0XFF
+echo -0xFF
+echo -0XFF
+
+" Decimal
+echo 255
+echo -255
+
+" Octal
+echo 0377
+echo 0o377
+echo 0O377
+echo -0377
+echo -0o377
+echo -0O377
+
+" Binary
+echo 0b11111111
+echo 0B11111111
+echo -0b11111111
+echo -0B11111111
+
+" Float
+echo 123.456
+echo +0.0001
+echo 55.0
+echo -0.123
+echo 1.234e03
+echo 1.0E-6
+echo -3.1416e+88
+
+" Blob
+echo 0z
+echo 0zFF00ED015DAF
+echo 0zFF00.ED01.5DAF
+echo 0zFF.00.ED.01.5D.AF
+
+" List
+
+echo []
+echo [42]
+echo [[11, 12], [21, 22], [31, 32]]
+echo [1,
+ \ 2,
+ \ 3,
+ \ 4
+ \]
+echo [1, 'two', 1 + 2, "fo" .. "ur"]
+
+" Issue #5830 (Incorrect syntax highlighting in MNV script when omitting space in list of string)
+let l = ['a','b','c']
+
+" Dictionary
+
+echo {}
+echo { 'foo': 21 * 2 }
+echo { "foo": 21 * 2 }
+echo { 42: 21 * 2 }
+
+echo { "foo": { 'bar': 21 * 2 } }
+echo { "foo": { "bar": 21 * 2 } }
+echo { "foo": { 42: 21 * 2 } }
+echo { "foo": #{ bar: 21 * 2 } }
+echo { "foo": #{ -bar-: 21 * 2 } }
+echo { "foo": #{ 42: 21 * 2 } }
+
+echo { 'foo': { 'bar': 21 * 2 } }
+echo { 'foo': { "bar": 21 * 2 } }
+echo { 'foo': { 42: 21 * 2 } }
+echo { 'foo': #{ bar: 21 * 2 } }
+echo { 'foo': #{ -bar-: 21 * 2 } }
+echo { 'foo': #{ 42: 21 * 2 } }
+
+echo { 42: { 'bar': 21 * 2 } }
+echo { 42: { "bar": 21 * 2 } }
+echo { 42: { 42: 21 * 2 } }
+echo { 42: #{ bar: 21 * 2 } }
+echo { 42: #{ -bar-: 21 * 2 } }
+echo { 42: #{ 42: 21 * 2 } }
+
+echo {
+ "\ comment
+ \ "foo": { "bar": 21 * 2 }
+ \}
+
+" TODO: arbitrary expression keys
+
+" Literal Dictionary
+
+echo #{}
+echo #{ foo: 21 * 2 }
+echo #{ -foo-: 21 * 2 }
+echo #{ 42: 21 * 2 }
+
+echo #{ foo: #{ bar: 21 * 2 } }
+echo #{ foo: #{ -bar-: 21 * 2 } }
+echo #{ foo: #{ 42: 21 * 2 } }
+echo #{ foo: { "bar": 21 * 2 } }
+echo #{ foo: { 'bar': 21 * 2 } }
+echo #{ foo: { 42: 21 * 2 } }
+
+echo #{ -foo-: #{ bar: 21 * 2 } }
+echo #{ -foo-: #{ -bar-: 21 * 2 } }
+echo #{ -foo-: #{ 42: 21 * 2 } }
+echo #{ -foo-: { "bar": 21 * 2 } }
+echo #{ -foo-: { 'bar': 21 * 2 } }
+echo #{ -foo-: { 42: 21 * 2 } }
+
+echo #{ 42: #{ bar: 21 * 2 } }
+echo #{ 42: #{ -bar-: 21 * 2 } }
+echo #{ 42: #{ 42: 21 * 2 } }
+echo #{ 42: { "bar": 21 * 2 } }
+echo #{ 42: { 'bar': 21 * 2 } }
+echo #{ 42: { 42: 21 * 2 } }
+
+echo #{
+ "\ comment
+ \ foo: #{
+ \ bar: 21 * 2
+ \ }
+ \}
+
+" match as keys not scope dictionaries
+echo #{ b: 42, w: 42, t: 42, g: 42, l: 42, s: 42, a: 42, v: 42 }
+
+" Tuple
+
+echo ()
+echo (42,)
+echo ((11, 12), (21, 22), (31, 32))
+echo (1,
+ \ 2,
+ \ 3,
+ \ 4
+ \)
+echo (1, 'two', 1 + 2, "fo" .. "ur")
+
+echo foo + (42, 87)
+echo (42, 87) + foo
+
+" Register
+
+echo @" @@
+echo @0 @1 @2 @3 @4 @5 @6 @7 @8 @9
+echo @a @b @c @d @e @f @g @h @i @j @k @l @m @n @o @p @q @r @s @t @u @v @w @x @y @z
+echo @A @B @C @D @E @F @G @H @I @J @K @L @M @N @O @P @Q @R @S @T @U @V @W @X @Y @Z
+echo @- @: @. @% @# @= @* @+ @~ @_ @/
+
+" read-only @:, @., @%, @~
+let @" = "foo"
+let @0 = "foo"
+let @1 = "foo"
+let @9 = "foo"
+let @a = "foo"
+let @k = "foo"
+let @z = "foo"
+let @A = "foo"
+let @K = "foo"
+let @Z = "foo"
+let @- = "foo"
+let @# = "foo"
+let @= = "foo"
+let @* = "foo"
+let @+ = "foo"
+let @_ = "foo"
+let @/ = "foo"
+
+" Operators
+
+" Ternary
+echo expr ? expr : expr
+
+echo lnum == 1 ? "top" : lnum
+echo lnum == 1 ? "top" : lnum == 1000 ? "last" : lnum
+
+echo lnum == 1
+ \ ? "top"
+ \ : lnum == 1000
+ \ ? "last"
+ \ : lnum
+echo lnum == 1 ?
+ \ "top" :
+ \ lnum == 1000 ?
+ \ "last" :
+ \ lnum
+
+echo 1 ? 1 : 0
+echo "foo" ? "foo" : "bar"
+echo foo ? foo : bar
+echo g:foo ? g:foo : g:bar
+echo $FOO ? $FOO : $BAR
+echo True() ? True() : False()
+echo @a ? @a : @b
+echo (1) ? (1) : (0)
+
+" Falsy
+echo expr ?? expr
+
+echo theList ?? 'list is empty'
+echo GetName() ?? 'unknown'
+
+echo theList
+ \ ?? 'list is empty'
+echo theList ??
+ \ 'list is empty'
+
+echo 1 ?? 1
+echo "foo" ?? "foo"
+echo foo ?? foo
+echo g:foo ?? g:foo
+echo $FOO ?? $FOO
+echo True() ?? True()
+echo @a ?? @a
+echo (1) ?? (1)
+
+" Comparison - using 'ignorcase'
+echo expr == expr
+echo expr != expr
+echo expr > expr
+echo expr >= expr
+echo expr < expr
+echo expr <= expr
+echo expr =~ expr
+echo expr !~ expr
+echo expr is expr
+echo expr isnot expr
+
+" Comparison - match case
+echo expr ==# expr
+echo expr !=# expr
+echo expr ># expr
+echo expr >=# expr
+echo expr <# expr
+echo expr <=# expr
+echo expr =~# expr
+echo expr !~# expr
+echo expr is# expr
+echo expr isnot# expr
+
+" Comparison - ignore case
+echo expr ==? expr
+echo expr !=? expr
+echo expr >? expr
+echo expr >=? expr
+echo expr <? expr
+echo expr <=? expr
+echo expr =~? expr
+echo expr !~? expr
+echo expr is? expr
+echo expr isnot? expr
+
+" Unreported issue ("is" incorrectly matches as "echo mnvNumber *mnvCommand* mnvNumber")
+echo 42 is 42
+
+" Line continuation
+let foo = foo +
+ \
+ "\ comment
+ \
+ "\ comment
+ \ bar +
+ \ "baz"
+
+let foo = foo +
+ "\ comment
+ \
+ "\ comment
+ \
+ \ bar +
+ \ "baz"
+
+let foo = foo +
+ "\ "comment string"
+ \ bar
+
+" Function calls
+
+call Foo(v:true, v:false, v:null)
+
+
+" Issue #16221 (mnvString becomes mnvVar when preceded by !)
+
+let bar = !'g:bar'->exists()
+
+
+" Issue #14423 (mnv.mnv: Opt out of mnvSearch*)
+
+?truthy
+let truthy = 0
+\ ? (0
+\ )
+\ : (1
+\ )
+echo truthy
+
+function Foo()
+ ?truthy
+ let truthy = 0
+ \ ? (0
+ \ )
+ \ : (1
+ \ )
+ echo truthy
+endfunction
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_function_calls.mnv b/mnv/runtime/syntax/testdir/input/mnv_function_calls.mnv
new file mode 100644
index 0000000000..aa563d1c7a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_function_calls.mnv
@@ -0,0 +1,277 @@
+" MNV function calls
+" MNV_TEST_SETUP hi link mnvUserFunc Todo
+
+
+call abs(42)
+
+
+" Command/function distinction
+
+" append browse call chdir confirm copy delete eval execute filter function
+" insert join map match mode sort split substitute swapname type
+
+let append = append(42)
+call append(42)
+" command
+append
+.
+" bad command
+append(42)
+append (42)
+
+let browse = browse(42)
+call browse(42)
+" command
+browse(42)
+browse (42)
+
+let call = call(42)
+call call(42)
+" command
+call(42)
+call (42)
+
+let chdir = chdir(42)
+call chdir(42)
+" command
+chdir(42)
+chdir (42)
+
+let confirm = confirm(42)
+call confirm(42)
+" command
+confirm(42)
+confirm (42)
+
+let copy = copy(42)
+call copy(42)
+" command
+copy(42)
+copy (42)
+
+let delete = delete(42)
+call delete(42)
+" command
+delete(42)
+delete (42)
+
+let eval = eval(42)
+call eval(42)
+" command
+eval(42)
+eval (42)
+
+let execute = execute(42)
+call execute(42)
+" command
+execute(42)
+execute (42)
+
+let filter = filter(42)
+call filter(42)
+" command
+filter(42)
+filter (42)
+
+let function = function(42)
+call function(42)
+" command
+function(42)
+function (42)
+
+let insert = insert(42)
+call insert(42)
+" command
+insert
+.
+" bad command
+insert(42)
+insert (42)
+
+let join = join(42)
+call join(42)
+" command
+join(42)
+join (42)
+
+let map = map(42)
+call map(42)
+" command
+map(42)
+map (42)
+
+let match = match(42)
+call match(42)
+" command
+match(42)
+match (42)
+
+let sort = sort(42)
+call sort(42)
+" command
+sort(42)
+sort (42)
+
+let split = split(42)
+call split(42)
+" command
+split(42)
+split (42)
+
+let substitute = substitute(42)
+call substitute(42)
+" command
+substitute(42)
+substitute (42)
+
+let swapname = swapname(42)
+call swapname(42)
+" command
+swapname(42)
+swapname (42)
+
+let type = type(42)
+call type(42)
+" MNV9 command
+" type(42)
+" type (42)
+
+let uniq = uniq(42)
+call uniq(42)
+" command
+uniq(42)
+uniq (42)
+
+
+" Errors
+
+let foo = foo(42)
+call foo(42)
+
+let if = if(42)
+call if(42)
+" command
+if(42) | .. | endif
+if (42) | .. | endif
+
+let echo = echo(42)
+call echo(42)
+" command
+echo(42)
+echo (42)
+
+
+" Expressions
+
+let foo = abs(42)
+
+echo abs(42)
+echo (abs(42))
+echo abs(42) + foo
+echo foo + abs(42)
+
+echo Foo()
+echo (Foo())
+echo Foo() + bar
+echo bar + Foo()
+
+
+" Scope modifiers and qualified names
+
+let foo = s:foo(42)
+call s:foo(42)
+
+let foo = g:foo(42)
+call g:foo(42)
+
+let foo = b:foo(42)
+call b:foo(42)
+
+let foo = w:foo(42)
+call w:foo(42)
+
+let foo = t:foo(42)
+call t:foo(42)
+
+let foo = l:foo(42)
+call l:foo(42)
+
+let foo = a:foo(42)
+call a:foo(42)
+
+let foo = v:foo(42)
+call v:foo(42)
+
+
+let foo = module.foo(42)
+call module.foo(42)
+
+let foo = s:module.foo(42)
+call module.foo(42)
+
+let foo = g:module.foo(42)
+call g:module.foo(42)
+
+let foo = b:module.foo(42)
+call b:module.foo(42)
+
+let foo = w:module.foo(42)
+call w:module.foo(42)
+
+let foo = t:module.foo(42)
+call t:module.foo(42)
+
+let foo = l:module.foo(42)
+call l:module.foo(42)
+
+let foo = a:module.foo(42)
+call a:module.foo(42)
+
+let foo = v:module.foo(42)
+call v:module.foo(42)
+
+
+let foo = module#foo(42)
+call module#foo(42)
+
+let foo = g:module#foo(42)
+call g:module#foo(42)
+
+
+" Not builtin functions
+
+call s:substitute()
+call g:substitute()
+call b:substitute()
+call w:substitute()
+call t:substitute()
+call l:substitute()
+call a:substitute()
+call v:substitute()
+
+call <SID>substitute()
+
+call s:substitute.substitute()
+call g:substitute.substitute()
+call b:substitute.substitute()
+call w:substitute.substitute()
+call t:substitute.substitute()
+call l:substitute.substitute()
+call a:substitute.substitute()
+call v:substitute.substitute()
+
+call substitute#substitute()
+call g:substitute#substitute()
+
+
+" Chained function calls
+
+call module.foo().bar()
+call module.foo().substitute()
+
+
+" Issue #17766 (valid function call highlighted as error)
+
+call module[0].foo()
+call module[0].substitute()
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_function_variables.mnv b/mnv/runtime/syntax/testdir/input/mnv_function_variables.mnv
new file mode 100644
index 0000000000..adf2d26f58
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_function_variables.mnv
@@ -0,0 +1,414 @@
+" MNV function variable highlighting
+
+
+function Foo()
+ " :let
+
+ let foo = expr
+
+ let foo[0] = expr
+
+ let foo[1:2] = expr
+ let foo[:2] = expr
+ let foo[1:] = expr
+ let foo[:] = expr
+
+ let foo["key"] = expr
+ let foo['key'] = expr
+
+ let foo += expr
+ let foo -= expr
+ let foo *= expr
+ let foo /= expr
+ let foo %= expr
+ let foo .= expr
+ let foo ..= expr
+
+ let b:foo = expr
+
+ let b:foo[0] = expr
+
+ let b:foo[1:2] = expr
+ let b:foo[:2] = expr
+ let b:foo[1:] = expr
+ let b:foo[:] = expr
+
+ let b:foo["key"] = expr
+ let b:foo['key'] = expr
+
+ let b:foo += expr
+ let b:foo -= expr
+ let b:foo *= expr
+ let b:foo /= expr
+ let b:foo %= expr
+ let b:foo .= expr
+ let b:foo ..= expr
+
+ let g:foo = expr
+
+ let g:foo[0] = expr
+
+ let g:foo[1:2] = expr
+ let g:foo[:2] = expr
+ let g:foo[1:] = expr
+ let g:foo[:] = expr
+
+ let g:foo["key"] = expr
+ let g:foo['key'] = expr
+
+ let g:foo += expr
+ let g:foo -= expr
+ let g:foo *= expr
+ let g:foo /= expr
+ let g:foo %= expr
+ let g:foo .= expr
+ let g:foo ..= expr
+
+ let s:foo = expr
+
+ let s:foo[0] = expr
+
+ let s:foo[1:2] = expr
+ let s:foo[:2] = expr
+ let s:foo[1:] = expr
+ let s:foo[:] = expr
+
+ let s:foo["key"] = expr
+ let s:foo['key'] = expr
+
+ let s:foo += expr
+ let s:foo -= expr
+ let s:foo *= expr
+ let s:foo /= expr
+ let s:foo %= expr
+ let s:foo .= expr
+ let s:foo ..= expr
+
+ let t:foo = expr
+
+ let t:foo[0] = expr
+
+ let t:foo[1:2] = expr
+ let t:foo[:2] = expr
+ let t:foo[1:] = expr
+ let t:foo[:] = expr
+
+ let t:foo["key"] = expr
+ let t:foo['key'] = expr
+
+ let t:foo += expr
+ let t:foo -= expr
+ let t:foo *= expr
+ let t:foo /= expr
+ let t:foo %= expr
+ let t:foo .= expr
+ let t:foo ..= expr
+
+ let v:true = expr
+
+ let v:true[0] = expr
+
+ let v:true[1:2] = expr
+ let v:true[:2] = expr
+ let v:true[1:] = expr
+ let v:true[:] = expr
+
+ let v:true["key"] = expr
+ let v:true['key'] = expr
+
+ let v:true += expr
+ let v:true -= expr
+ let v:true *= expr
+ let v:true /= expr
+ let v:true %= expr
+ let v:true .= expr
+ let v:true ..= expr
+
+ let w:foo = expr
+
+ let w:foo[0] = expr
+
+ let w:foo[1:2] = expr
+ let w:foo[:2] = expr
+ let w:foo[1:] = expr
+ let w:foo[:] = expr
+
+ let w:foo["key"] = expr
+ let w:foo['key'] = expr
+
+ let w:foo += expr
+ let w:foo -= expr
+ let w:foo *= expr
+ let w:foo /= expr
+ let w:foo %= expr
+ let w:foo .= expr
+ let w:foo ..= expr
+
+ let $FOO = expr
+ let $FOO .= expr
+ let $FOO ..= expr
+
+ let @f = expr
+ let @f .= expr
+ let @f ..= expr
+
+ let &ari = expr
+
+ let &t_k1 = "\<Esc>[234;"
+
+ let &ari .= expr
+ let &ari ..= expr
+ let &ari += expr
+ let &ari -= expr
+
+ let &l:aleph = expr
+
+ let &l:aleph .= expr
+ let &l:aleph ..= expr
+ let &l:aleph += expr
+ let &l:aleph -= expr
+
+ let &g:aleph = expr
+
+ let &g:aleph .= expr
+ let &g:aleph ..= expr
+ let &g:aleph += expr
+ let &g:aleph -= expr
+
+ let [foo, bar] = expr
+ let [foo,
+ \ bar] = expr
+ let [v:true, v:false] = expr
+ let [v:true,
+ \ v:false] = expr
+ let [&ari, &bkc] = expr
+ let [&ari,
+ \ &bkc] = expr
+ let [$foo, $bar] = expr
+ let [$foo,
+ \ $bar] = expr
+ let [@a, @b] = expr
+ let [@a,
+ \ @b] = expr
+
+ let [foo, bar] .= expr
+ let [foo, bar] ..= expr
+ let [foo, bar] += expr
+ let [foo, bar] -= expr
+
+ let [foo, bar; baz] = expr
+ let [foo,
+ \ bar;
+ \ baz] = expr
+ let [v:true, v:false; v:none] = expr
+ let [v:true,
+ \ v:false;
+ \ v:none] = expr
+ let [$foo, $bar; $baz] = expr
+ let [$foo,
+ \ $bar;
+ \ $baz] = expr
+ let [&ari, &bkc; &cmp] = expr
+ let [&ari,
+ \ &bkc;
+ \ &cmp] = expr
+ let [@a, @b; @c] = expr
+ let [@a,
+ \ @b;
+ \ @c] = expr
+
+ let foo =<< END
+...
+END
+ let foo =<< trim END
+ ...
+ END
+ let foo =<< eval END
+...
+END
+ let foo =<< trim eval END
+ ...
+ END
+ let foo =<< eval trim END
+ ...
+ END
+
+ " :let list values
+
+ let foo
+ let foo bar
+ let foo
+ "\ comment
+ \ bar
+
+ let foo " comment
+ let foo "\ comment
+ let foo | echo "Foo"
+ let foo bar " comment
+ let foo bar | echo "Foo"
+ let foo bar "\ comment
+
+ " :unlet
+
+ unlet foo
+ unlet foo bar
+ unlet foo
+ "\ comment
+ \ bar
+
+ unlet! foo
+ unlet! foo bar
+ unlet! foo
+ "\ comment
+ \ bar
+
+ unlet $FOO
+ unlet! $FOO
+
+ unlet list[3]
+ unlet list[3:]
+ unlet dict['two']
+ unlet dict.two
+
+ unlet foo " comment
+ unlet foo "\ comment
+ unlet foo | echo "Foo"
+ unlet foo bar " comment
+ unlet foo bar "\ comment
+ unlet foo bar | echo "Foo"
+
+ " :const
+
+ const foo = expr
+
+ const [foo, bar] = expr
+
+ const [foo, bar; baz] = expr
+
+ const foo =<< END
+...
+END
+ const foo =<< trim END
+ ...
+ END
+ const foo =<< eval END
+...
+END
+ const foo =<< trim eval END
+ ...
+ END
+ const foo =<< eval trim END
+ ...
+ END
+
+ const foo
+ const foo bar
+
+ " :for
+
+ for foo in expr
+ endfor
+
+ for [foo, bar] in expr
+ endfor
+
+ " :lockvar
+
+ lockvar foo
+ lockvar foo bar
+ lockvar foo
+ "\ comment
+ \ bar
+
+ lockvar foo " comment
+ lockvar foo | echo "Foo"
+ lockvar foo bar " comment
+ lockvar foo bar | echo "Foo"
+
+ lockvar! foo
+ lockvar! foo bar
+ lockvar! foo
+ "\ comment
+ \ bar
+
+ lockvar! foo " comment
+ lockvar! foo | echo "Foo"
+ lockvar! foo bar " comment
+ lockvar! foo bar | echo "Foo"
+
+ lockvar 2 foo
+ lockvar 2 foo bar
+ lockvar 2 foo
+ "\ comment
+ \ bar
+
+ lockvar 2 foo " comment
+ lockvar 2 foo | echo "Foo"
+ lockvar 2 foo bar " comment
+ lockvar 2 foo bar | echo "Foo"
+
+ " :unlockvar
+
+ unlockvar foo
+ unlockvar foo bar
+ unlockvar foo
+ "\ comment
+ \ bar
+
+ unlockvar foo " comment
+ unlockvar foo | echo "Foo"
+ unlockvar foo bar " comment
+ unlockvar foo bar | echo "Foo"
+
+ unlockvar! foo
+ unlockvar! foo bar
+ unlockvar! foo
+ "\ comment
+ \ bar
+
+ unlockvar! foo " comment
+ unlockvar! foo | echo "Foo"
+ unlockvar! foo bar " comment
+ unlockvar! foo bar | echo "Foo"
+
+ unlockvar 2 foo
+ unlockvar 2 foo bar
+ unlockvar 2 foo
+ "\ comment
+ \ bar
+
+ unlockvar 2 foo " comment
+ unlockvar 2 foo | echo "Foo"
+ unlockvar 2 foo bar " comment
+ unlockvar 2 foo bar | echo "Foo"
+
+" Scope dictionaries
+
+echo get(b:, 'foo', 42)
+echo get(w:, 'foo', 42)
+echo get(t:, 'foo', 42)
+echo get(g:, 'foo', 42)
+echo get(l:, 'foo', 42)
+echo get(s:, 'foo', 42)
+echo get(a:, 'foo', 42)
+echo get(v:, 'foo', 42)
+
+for k in keys(b:) | echo b:[k] | endfor
+for k in keys(w:) | echo w:[k] | endfor
+for k in keys(t:) | echo t:[k] | endfor
+for k in keys(g:) | echo g:[k] | endfor
+for k in keys(l:) | echo l:[k] | endfor
+for k in keys(s:) | echo s:[k] | endfor
+for k in keys(a:) | echo a:[k] | endfor
+for k in keys(v:) | echo v:[k] | endfor
+
+" Neomnv-specific variables (not highlighted by default)
+
+echo v:lua v:msgpack_types v:relnum v:stderr v:termrequest v:virtnum
+
+echo &channel &inccommand &mousescroll &pumblend &redrawdebug &scrollback
+echo &shada &shadafile &statuscolumn &termpastefilter &termsync &winbar
+echo &winblend
+
+endfunction
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_key_notation.mnv b/mnv/runtime/syntax/testdir/input/mnv_key_notation.mnv
new file mode 100644
index 0000000000..5730e62bf6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_key_notation.mnv
@@ -0,0 +1,166 @@
+" Key notation
+
+
+map foo
+ \ <Space>
+ \ <Tab>
+ \ <Tab>
+ \ <NL>
+ \ <NewLine>
+ \ <LineFeed>
+ \ <LF>
+ \ <CR>
+ \ <Return>
+ \ <Enter>
+ \ <BS>
+ \ <BackSpace>
+ \ <Esc>
+ \ <CSI>
+ \ <xCSI>
+ \ <Bar>
+ \ <Bslash>
+ \ <Del>
+ \ <Delete>
+ \ <kDel>
+ \ <Up>
+ \ <Down>
+ \ <Left>
+ \ <Right>
+ \ <xUp>
+ \ <xDown>
+ \ <xLeft>
+ \ <xRight>
+ \ <PasteStart>
+ \ <PasteEnd>
+ \ <F1>
+ \ <F2>
+ \ <F3>
+ \ <F4>
+ \ <F5>
+ \ <F6>
+ \ <F7>
+ \ <F8>
+ \ <F9>
+ \ <F10>
+ \ <F11>
+ \ <F12>
+ \ <F13>
+ \ <F14>
+ \ <F15>
+ \ <F16>
+ \ <F17>
+ \ <F18>
+ \ <F19>
+ \ <F20>
+ \ <F21>
+ \ <F22>
+ \ <F23>
+ \ <F24>
+ \ <F25>
+ \ <F26>
+ \ <F27>
+ \ <F28>
+ \ <F29>
+ \ <F30>
+ \ <F31>
+ \ <F32>
+ \ <F33>
+ \ <F34>
+ \ <F35>
+ \ <F36>
+ \ <F37>
+ \ <xF1>
+ \ <xF2>
+ \ <xF3>
+ \ <xF4>
+ \ <Help>
+ \ <Undo>
+ \ <Insert>
+ \ <Ins>
+ \ <kInsert>
+ \ <Home>
+ \ <kHome>
+ \ <xHome>
+ \ <zHome>
+ \ <End>
+ \ <kEnd>
+ \ <xEnd>
+ \ <zEnd>
+ \ <PageUp>
+ \ <PageDown>
+ \ <kPageUp>
+ \ <kPageDown>
+ \ <kPlus>
+ \ <kMinus>
+ \ <kDivide>
+ \ <kMultiply>
+ \ <kEnter>
+ \ <kPoint>
+ \ <k0>
+ \ <k1>
+ \ <k2>
+ \ <k3>
+ \ <k4>
+ \ <k5>
+ \ <k6>
+ \ <k7>
+ \ <k8>
+ \ <k9>
+ \ <lt>
+ \ <Mouse>
+ \ <NetMouse>
+ \ <DecMouse>
+ \ <JsbMouse>
+ \ <PtermMouse>
+ \ <UrxvtMouse>
+ \ <SgrMouse>
+ \ <SgrMouseRelease>
+ \ <LeftMouse>
+ \ <LeftMouseNM>
+ \ <LeftDrag>
+ \ <LeftRelease>
+ \ <LeftReleaseNM>
+ \ <MouseMove>
+ \ <MiddleMouse>
+ \ <MiddleDrag>
+ \ <MiddleRelease>
+ \ <RightMouse>
+ \ <RightDrag>
+ \ <RightRelease>
+ \ <ScrollWheelUp>
+ \ <ScrollWheelDown>
+ \ <ScrollWheelRight>
+ \ <ScrollWheelLeft>
+ \ <MouseDown>
+ \ <MouseUp>
+ \ <X1Mouse>
+ \ <X1Drag>
+ \ <X1Release>
+ \ <X2Mouse>
+ \ <X2Drag>
+ \ <X2Release>
+ \ <Drop>
+ \ <Nul>
+ \ <SNR>
+ \ <Plug>
+ \ <CursorHold>
+ \ <Ignore>
+ \ <Cmd>
+ \ <ScriptCmd>
+ \ <FocusGained>
+ \ <FocusLost>
+ \
+ \ <cword>
+ \ <cWORD>
+ \ <cexpr>
+ \ <cfile>
+ \ <afile>
+ \ <abuf>
+ \ <amatch>
+ \ <sfile>
+ \ <stack>
+ \ <script>
+ \ <slnum>
+ \ <sflnum>
+ \ <client>
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_lambdas.mnv b/mnv/runtime/syntax/testdir/input/mnv_lambdas.mnv
new file mode 100644
index 0000000000..a26530f63e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_lambdas.mnv
@@ -0,0 +1,135 @@
+" MNV lambda expressions
+" MNV_TEST_SETUP hi link mnvLambdaOperator Todo
+" MNV_TEST_SETUP hi link mnvLambdaBrace Todo
+" MNV_TEST_SETUP hi link mnvFuncParam Identifier
+
+
+let expr = 42
+
+let Foo = {-> expr}
+let Foo = {_ -> expr}
+let Foo = {... -> expr}
+let Foo = {x -> expr}
+let Foo = {x, _ -> expr}
+let Foo = {x, ... -> expr}
+let Foo = {x, y -> expr}
+
+
+" Line continuations
+
+let Foo = {->
+ "\ comment
+ \ expr
+ \ }
+let Foo = {_ ->
+ "\ comment
+ \ expr
+ \ }
+let Foo = {... ->
+ "\ comment
+ \ expr
+ \ }
+let Foo = {x ->
+ \ expr
+ "\ comment
+ \ }
+let Foo = {x, y ->
+ "\ comment
+ \ expr
+ \ }
+
+let Foo = {
+ \ ->
+ "\ comment
+ \ expr
+ \ }
+let Foo = {x
+ \ ->
+ "\ comment
+ \ expr
+ \ }
+let Foo = {x, y
+ \ ->
+ "\ comment
+ \ expr
+ \ }
+
+let Foo = {x,
+ \ y,
+ \ z -> expr}
+
+let Foo = {
+ "\ comment
+ \ x,
+ "\ comment
+ \ y,
+ "\ comment
+ \ z
+ "\ comment
+ \ ->
+ "\ comment
+ \ expr
+ "\ comment
+ \ }
+
+let Foo = {-> [
+ \ 42,
+ \ 83
+ \]}
+
+let Foo = {-> {
+ \ 'a': 42,
+ \ 'b': 83
+ \}}
+
+let Foo = {-> #{
+ \ a: 42,
+ \ b: 83
+ \}}
+
+let Foo = {-> {->[
+ \ 42,
+ \ 83
+ \]}}
+
+let Foo = {-> {-> {
+ \ 'a': 42,
+ \ 'b': 83
+ \}}}
+
+let Foo = {-> {-> #{
+ \ a: 42,
+ \ b: 83
+ \}}}
+
+
+" :help lambda
+
+:let F = {arg1, arg2 -> arg1 - arg2}
+:echo F(5, 2)
+
+:let F = {-> 'error function'}
+:echo F('ignored')
+
+:function Foo(arg)
+: let i = 3
+: return {x -> x + i - a:arg}
+:endfunction
+:let Bar = Foo(4)
+:echo Bar(6)
+
+:echo map([1, 2, 3], {idx, val -> val + 1})
+" [2, 3, 4]
+
+:echo sort([3,7,2,1,4], {a, b -> a - b})
+" [1, 2, 3, 4, 7]
+:let timer = timer_start(500,
+ \ {-> execute("echo 'Handler called'", "")},
+ \ {'repeat': 3})
+
+
+" Issue https://github.com/Project-Tick/Project-Tick/pull/17420#issuecomment-2927798687
+" (string immediately after -> operator)
+
+let [func, _func_] = [{->"func"}(), 'func']
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_line_continuation.mnv b/mnv/runtime/syntax/testdir/input/mnv_line_continuation.mnv
new file mode 100644
index 0000000000..cd092f56b6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_line_continuation.mnv
@@ -0,0 +1,51 @@
+" MNV line continuations with interspersed comments
+
+
+function Foo(
+ "\ param a
+ \ a,
+ "\ param b
+ \ b,
+ "\ param c
+ \ c
+ \)
+ echomsg
+ "\ start string
+ \ $"
+ "\ print a
+ \ a = {a:a},
+ "\ print b
+ \ b = {a:b},
+ "\ print c
+ \ c = {a:c}
+ "\ end string
+ \"
+endfunction
+
+call Foo(
+ "\ arg 1
+ \ 11,
+ "\ arg 2
+ \ 22,
+ "\ arg 3
+ \ 33
+ \)
+
+let dict = #{
+ "\ pair 1
+ \ a: 1,
+ "\ pair 2
+ \ b: 2,
+ "\ pair 3
+ \ c: 3
+ \}
+
+let array = [
+ "\ element 1
+ \ 1,
+ "\ element 2
+ \ 2,
+ "\ element 3
+ \ 3
+ \]
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_new.mnv b/mnv/runtime/syntax/testdir/input/mnv_new.mnv
new file mode 100644
index 0000000000..979446a0c4
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_new.mnv
@@ -0,0 +1,21 @@
+mnv9script
+# MNV :new command and class constructors
+# TODO: move to mnv9_constructor and create new mnv_ex_new and mnv9_ex_new
+# tests
+
+
+class Test
+ def new()
+ enddef
+ def newOther()
+ enddef
+ def newyetanother()
+ enddef
+endclass
+
+Test.new()
+Test.newOther()
+Test.newyetanother()
+new
+quit
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_nmnv_features.mnv b/mnv/runtime/syntax/testdir/input/mnv_nmnv_features.mnv
new file mode 100644
index 0000000000..1ccf1e4d04
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_nmnv_features.mnv
@@ -0,0 +1,229 @@
+" Neomnv-specific highlighting
+" MNV_TEST_SETUP let g:mnvsyn_mnv_features = ["nmnv"]
+
+
+echo v:lua v:msgpack_types v:relnum v:stderr v:termrequest v:virtnum
+
+
+echo &channel &inccommand &mousescroll &pumblend &redrawdebug &scrollback
+echo &shada &shadafile &statuscolumn &termpastefilter &termsync &winbar
+echo &winblend &winhighlight
+
+
+call api_info()
+call buffer_exists()
+call buffer_name()
+call buffer_number()
+call chanclose()
+call chansend()
+call ctxget()
+call ctxpop()
+call ctxpush()
+call ctxset()
+call ctxsize()
+call dictwatcheradd()
+call dictwatcherdel()
+call file_readable()
+call highlight_exists()
+call highlightID()
+call jobclose()
+call jobpid()
+call jobresize()
+call jobsend()
+call jobstart()
+call jobstop()
+call jobwait()
+call last_buffer_nr()
+call menu_get()
+call msgpackdump()
+call msgpackparse()
+call reg_recorded()
+call rpcnotify()
+call rpcrequest()
+call rpcstart()
+call rpcstop()
+call serverstart()
+call serverstop()
+call sockconnect()
+call stdioopen()
+call stdpath()
+call termopen()
+call test_write_list_log()
+call wait()
+
+call nmnv_buf_add_highlight()
+call nmnv_buf_attach()
+call nmnv_buf_clear_highlight()
+call nmnv_buf_clear_namespace()
+call nmnv_buf_create_user_command()
+call nmnv__buf_debug_extmarks()
+call nmnv_buf_delete()
+call nmnv_buf_del_extmark()
+call nmnv_buf_del_keymap()
+call nmnv_buf_del_mark()
+call nmnv_buf_del_user_command()
+call nmnv_buf_del_var()
+call nmnv_buf_get_changedtick()
+call nmnv_buf_get_commands()
+call nmnv_buf_get_extmark_by_id()
+call nmnv_buf_get_extmarks()
+call nmnv_buf_get_keymap()
+call nmnv_buf_get_lines()
+call nmnv_buf_get_mark()
+call nmnv_buf_get_name()
+call nmnv_buf_get_number()
+call nmnv_buf_get_offset()
+call nmnv_buf_get_option()
+call nmnv_buf_get_text()
+call nmnv_buf_get_var()
+call nmnv_buf_is_loaded()
+call nmnv_buf_is_valid()
+call nmnv_buf_line_count()
+call nmnv_buf_set_extmark()
+call nmnv_buf_set_keymap()
+call nmnv_buf_set_lines()
+call nmnv_buf_set_mark()
+call nmnv_buf_set_name()
+call nmnv_buf_set_option()
+call nmnv_buf_set_text()
+call nmnv_buf_set_var()
+call nmnv_buf_set_virtual_text()
+call nmnv__buf_stats()
+call nmnv_call_dict_function()
+call nmnv_call_function()
+call nmnv_clear_autocmds()
+call nmnv_cmd()
+call nmnv_command()
+call nmnv_command_output()
+call nmnv__complete_set()
+call nmnv_create_augroup()
+call nmnv_create_autocmd()
+call nmnv_create_buf()
+call nmnv_create_namespace()
+call nmnv_create_user_command()
+call nmnv_del_augroup_by_id()
+call nmnv_del_augroup_by_name()
+call nmnv_del_autocmd()
+call nmnv_del_current_line()
+call nmnv_del_keymap()
+call nmnv_del_mark()
+call nmnv_del_user_command()
+call nmnv_del_var()
+call nmnv_echo()
+call nmnv_err_write()
+call nmnv_err_writeln()
+call nmnv_eval()
+call nmnv_eval_statusline()
+call nmnv_exec()
+call nmnv_exec2()
+call nmnv_exec_autocmds()
+call nmnv_feedkeys()
+call nmnv_get_all_options_info()
+call nmnv_get_autocmds()
+call nmnv_get_chan_info()
+call nmnv_get_color_by_name()
+call nmnv_get_color_map()
+call nmnv_get_commands()
+call nmnv_get_context()
+call nmnv_get_current_buf()
+call nmnv_get_current_line()
+call nmnv_get_current_tabpage()
+call nmnv_get_current_win()
+call nmnv_get_hl()
+call nmnv_get_hl_by_id()
+call nmnv_get_hl_by_name()
+call nmnv_get_hl_id_by_name()
+call nmnv_get_hl_ns()
+call nmnv_get_keymap()
+call nmnv__get_lib_dir()
+call nmnv_get_mark()
+call nmnv_get_mode()
+call nmnv_get_namespaces()
+call nmnv_get_option()
+call nmnv_get_option_info()
+call nmnv_get_option_info2()
+call nmnv_get_option_value()
+call nmnv_get_proc()
+call nmnv_get_proc_children()
+call nmnv__get_runtime()
+call nmnv_get_runtime_file()
+call nmnv_get_var()
+call nmnv_get_vvar()
+call nmnv__id()
+call nmnv__id_array()
+call nmnv__id_dict()
+call nmnv__id_float()
+call nmnv_input()
+call nmnv_input_mouse()
+call nmnv__inspect_cell()
+call nmnv__invalidate_glyph_cache()
+call nmnv_list_bufs()
+call nmnv_list_chans()
+call nmnv_list_runtime_paths()
+call nmnv_list_tabpages()
+call nmnv_list_uis()
+call nmnv_list_wins()
+call nmnv_load_context()
+call nmnv_notify()
+call nmnv__ns_get()
+call nmnv__ns_set()
+call nmnv_open_term()
+call nmnv_open_win()
+call nmnv_out_write()
+call nmnv_parse_cmd()
+call nmnv_parse_expression()
+call nmnv_paste()
+call nmnv_put()
+call nmnv__redraw()
+call nmnv_replace_termcodes()
+call nmnv__runtime_inspect()
+call nmnv__screenshot()
+call nmnv_select_popupmenu_item()
+call nmnv_set_current_buf()
+call nmnv_set_current_dir()
+call nmnv_set_current_line()
+call nmnv_set_current_tabpage()
+call nmnv_set_current_win()
+call nmnv_set_hl()
+call nmnv_set_hl_ns()
+call nmnv_set_hl_ns_fast()
+call nmnv_set_keymap()
+call nmnv_set_option()
+call nmnv_set_option_value()
+call nmnv_set_var()
+call nmnv_set_vvar()
+call nmnv__stats()
+call nmnv_strwidth()
+call nmnv_tabpage_del_var()
+call nmnv_tabpage_get_number()
+call nmnv_tabpage_get_var()
+call nmnv_tabpage_get_win()
+call nmnv_tabpage_is_valid()
+call nmnv_tabpage_list_wins()
+call nmnv_tabpage_set_var()
+call nmnv_tabpage_set_win()
+call nmnv__unpack()
+call nmnv_win_close()
+call nmnv_win_del_var()
+call nmnv_win_get_buf()
+call nmnv_win_get_config()
+call nmnv_win_get_cursor()
+call nmnv_win_get_height()
+call nmnv_win_get_number()
+call nmnv_win_get_option()
+call nmnv_win_get_position()
+call nmnv_win_get_tabpage()
+call nmnv_win_get_var()
+call nmnv_win_get_width()
+call nmnv_win_hide()
+call nmnv_win_is_valid()
+call nmnv_win_set_buf()
+call nmnv_win_set_config()
+call nmnv_win_set_cursor()
+call nmnv_win_set_height()
+call nmnv_win_set_hl_ns()
+call nmnv_win_set_option()
+call nmnv_win_set_var()
+call nmnv_win_set_width()
+call nmnv_win_text_height()
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_no_comment_strings.mnv b/mnv/runtime/syntax/testdir/input/mnv_no_comment_strings.mnv
new file mode 100644
index 0000000000..87da706e26
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_no_comment_strings.mnv
@@ -0,0 +1,22 @@
+" MNV comment strings
+" MNV_TEST_SETUP let g:mnvsyn_comment_strings = v:false
+
+
+" pre "string" post
+
+function Foo()
+ " pre "string" post
+endfunction
+
+def Bar()
+ # pre "string" post
+enddef
+
+command Foo {
+ # pre "string" post
+}
+
+autocmd BufNewFile * {
+ # pre "string" post
+}
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_predefined_user_commands.mnv b/mnv/runtime/syntax/testdir/input/mnv_predefined_user_commands.mnv
new file mode 100644
index 0000000000..ac0d0a3fc7
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_predefined_user_commands.mnv
@@ -0,0 +1,21 @@
+" MNV predefined user commands
+
+
+" :CompilerSet - runtime/compiler/
+
+CompilerSet makeprg=ant
+CompilerSet errorformat=\ %#[%.%#]\ %#%f:%l:%v:%*\\d:%*\\d:\ %t%[%^:]%#:%m,
+ \%A\ %#[%.%#]\ %f:%l:\ %m,%-Z\ %#[%.%#]\ %p^,%C\ %#[%.%#]\ %#%m
+
+
+" :SynMenu - runtime/makemenu.mnv
+
+SynMenu AB.A2ps\ config:a2ps
+SynMenu AB.Aap:aap
+SynMenu AB.ABAP/4:abap
+SynMenu AB.Abaqus:abaqus
+SynMenu AB.ABC\ music\ notation:abc
+SynMenu AB.ABEL:abel
+SynMenu AB.AceDB\ model:acedb
+SynMenu AB.Ada:ada
+
diff --git a/mnv/runtime/syntax/testdir/input/mnv_shebang.mnv b/mnv/runtime/syntax/testdir/input/mnv_shebang.mnv
new file mode 100644
index 0000000000..8f08db98b6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_shebang.mnv
@@ -0,0 +1,5 @@
+#!/usr/bin/env mnv -S
+" MNV shebang line
+
+
+#!/usr/bin/env mnv -S
diff --git a/mnv/runtime/syntax/testdir/input/mnv_variables.mnv b/mnv/runtime/syntax/testdir/input/mnv_variables.mnv
new file mode 100644
index 0000000000..03a169dde2
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/mnv_variables.mnv
@@ -0,0 +1,411 @@
+" MNV variable highlighting
+
+
+" :let
+
+let foo = expr
+
+let foo[0] = expr
+
+let foo[1:2] = expr
+let foo[:2] = expr
+let foo[1:] = expr
+let foo[:] = expr
+
+let foo["key"] = expr
+let foo['key'] = expr
+
+let foo += expr
+let foo -= expr
+let foo *= expr
+let foo /= expr
+let foo %= expr
+let foo .= expr
+let foo ..= expr
+
+let b:foo = expr
+
+let b:foo[0] = expr
+
+let b:foo[1:2] = expr
+let b:foo[:2] = expr
+let b:foo[1:] = expr
+let b:foo[:] = expr
+
+let b:foo["key"] = expr
+let b:foo['key'] = expr
+
+let b:foo += expr
+let b:foo -= expr
+let b:foo *= expr
+let b:foo /= expr
+let b:foo %= expr
+let b:foo .= expr
+let b:foo ..= expr
+
+let g:foo = expr
+
+let g:foo[0] = expr
+
+let g:foo[1:2] = expr
+let g:foo[:2] = expr
+let g:foo[1:] = expr
+let g:foo[:] = expr
+
+let g:foo["key"] = expr
+let g:foo['key'] = expr
+
+let g:foo += expr
+let g:foo -= expr
+let g:foo *= expr
+let g:foo /= expr
+let g:foo %= expr
+let g:foo .= expr
+let g:foo ..= expr
+
+let s:foo = expr
+
+let s:foo[0] = expr
+
+let s:foo[1:2] = expr
+let s:foo[:2] = expr
+let s:foo[1:] = expr
+let s:foo[:] = expr
+
+let s:foo["key"] = expr
+let s:foo['key'] = expr
+
+let s:foo += expr
+let s:foo -= expr
+let s:foo *= expr
+let s:foo /= expr
+let s:foo %= expr
+let s:foo .= expr
+let s:foo ..= expr
+
+let t:foo = expr
+
+let t:foo[0] = expr
+
+let t:foo[1:2] = expr
+let t:foo[:2] = expr
+let t:foo[1:] = expr
+let t:foo[:] = expr
+
+let t:foo["key"] = expr
+let t:foo['key'] = expr
+
+let t:foo += expr
+let t:foo -= expr
+let t:foo *= expr
+let t:foo /= expr
+let t:foo %= expr
+let t:foo .= expr
+let t:foo ..= expr
+
+let v:true = expr
+
+let v:true[0] = expr
+
+let v:true[1:2] = expr
+let v:true[:2] = expr
+let v:true[1:] = expr
+let v:true[:] = expr
+
+let v:true["key"] = expr
+let v:true['key'] = expr
+
+let v:true += expr
+let v:true -= expr
+let v:true *= expr
+let v:true /= expr
+let v:true %= expr
+let v:true .= expr
+let v:true ..= expr
+
+let w:foo = expr
+
+let w:foo[0] = expr
+
+let w:foo[1:2] = expr
+let w:foo[:2] = expr
+let w:foo[1:] = expr
+let w:foo[:] = expr
+
+let w:foo["key"] = expr
+let w:foo['key'] = expr
+
+let w:foo += expr
+let w:foo -= expr
+let w:foo *= expr
+let w:foo /= expr
+let w:foo %= expr
+let w:foo .= expr
+let w:foo ..= expr
+
+let $FOO = expr
+let $FOO .= expr
+let $FOO ..= expr
+
+let @f = expr
+let @f .= expr
+let @f ..= expr
+
+let &ari = expr
+
+let &t_k1 = "\<Esc>[234;"
+
+let &ari .= expr
+let &ari ..= expr
+let &ari += expr
+let &ari -= expr
+
+let &l:aleph = expr
+
+let &l:aleph .= expr
+let &l:aleph ..= expr
+let &l:aleph += expr
+let &l:aleph -= expr
+
+let &g:aleph = expr
+
+let &g:aleph .= expr
+let &g:aleph ..= expr
+let &g:aleph += expr
+let &g:aleph -= expr
+
+let [foo, bar] = expr
+let [foo,
+ \ bar] = expr
+let [v:true, v:false] = expr
+let [v:true,
+ \ v:false] = expr
+let [&ari, &bkc] = expr
+let [&ari,
+ \ &bkc] = expr
+let [$foo, $bar] = expr
+let [$foo,
+ \ $bar] = expr
+let [@a, @b] = expr
+let [@a,
+ \ @b] = expr
+
+let [foo, bar] .= expr
+let [foo, bar] ..= expr
+let [foo, bar] += expr
+let [foo, bar] -= expr
+
+let [foo, bar; baz] = expr
+let [foo,
+ \ bar;
+ \ baz] = expr
+let [v:true, v:false; v:none] = expr
+let [v:true,
+ \ v:false;
+ \ v:none] = expr
+let [$foo, $bar; $baz] = expr
+let [$foo,
+ \ $bar;
+ \ $baz] = expr
+let [&ari, &bkc; &cmp] = expr
+let [&ari,
+ \ &bkc;
+ \ &cmp] = expr
+let [@a, @b; @c] = expr
+let [@a,
+ \ @b;
+ \ @c] = expr
+
+let foo =<< END
+...
+END
+let foo =<< trim END
+...
+END
+let foo =<< eval END
+...
+END
+let foo =<< trim eval END
+...
+END
+let foo =<< eval trim END
+...
+END
+
+" :let list values
+
+let foo
+let foo bar
+let foo
+ "\ comment
+ \ bar
+
+let foo " comment
+let foo "\ comment
+let foo | echo "Foo"
+let foo bar " comment
+let foo bar | echo "Foo"
+let foo bar "\ comment
+
+" :unlet
+
+unlet foo
+unlet foo bar
+unlet foo
+ "\ comment
+ \ bar
+
+unlet! foo
+unlet! foo bar
+unlet! foo
+ "\ comment
+ \ bar
+
+unlet $FOO
+unlet! $FOO
+
+unlet list[3]
+unlet list[3:]
+unlet dict['two']
+unlet dict.two
+
+unlet foo " comment
+unlet foo "\ comment
+unlet foo | echo "Foo"
+unlet foo bar " comment
+unlet foo bar "\ comment
+unlet foo bar | echo "Foo"
+
+" :const
+
+const foo = expr
+
+const [foo, bar] = expr
+
+const [foo, bar; baz] = expr
+
+const foo =<< END
+...
+END
+const foo =<< trim END
+...
+END
+const foo =<< eval END
+...
+END
+const foo =<< trim eval END
+...
+END
+const foo =<< eval trim END
+...
+END
+
+const foo
+const foo bar
+
+" :for
+
+for foo in expr
+endfor
+
+for [foo, bar] in expr
+endfor
+
+" :lockvar
+
+lockvar foo
+lockvar foo bar
+lockvar foo
+ "\ comment
+ \ bar
+
+lockvar foo " comment
+lockvar foo | echo "Foo"
+lockvar foo bar " comment
+lockvar foo bar | echo "Foo"
+
+lockvar! foo
+lockvar! foo bar
+lockvar! foo
+ "\ comment
+ \ bar
+
+lockvar! foo " comment
+lockvar! foo | echo "Foo"
+lockvar! foo bar " comment
+lockvar! foo bar | echo "Foo"
+
+lockvar 2 foo
+lockvar 2 foo bar
+lockvar 2 foo
+ "\ comment
+ \ bar
+
+lockvar 2 foo " comment
+lockvar 2 foo | echo "Foo"
+lockvar 2 foo bar " comment
+lockvar 2 foo bar | echo "Foo"
+
+" :unlockvar
+
+unlockvar foo
+unlockvar foo bar
+unlockvar foo
+ "\ comment
+ \ bar
+
+unlockvar foo " comment
+unlockvar foo | echo "Foo"
+unlockvar foo bar " comment
+unlockvar foo bar | echo "Foo"
+
+unlockvar! foo
+unlockvar! foo bar
+unlockvar! foo
+ "\ comment
+ \ bar
+
+unlockvar! foo " comment
+unlockvar! foo | echo "Foo"
+unlockvar! foo bar " comment
+unlockvar! foo bar | echo "Foo"
+
+unlockvar 2 foo
+unlockvar 2 foo bar
+unlockvar 2 foo
+ "\ comment
+ \ bar
+
+unlockvar 2 foo " comment
+unlockvar 2 foo | echo "Foo"
+unlockvar 2 foo bar " comment
+unlockvar 2 foo bar | echo "Foo"
+
+" Scope dictionaries
+
+echo get(b:, 'foo', 42)
+echo get(w:, 'foo', 42)
+echo get(t:, 'foo', 42)
+echo get(g:, 'foo', 42)
+echo get(l:, 'foo', 42)
+echo get(s:, 'foo', 42)
+echo get(a:, 'foo', 42)
+echo get(v:, 'foo', 42)
+
+for k in keys(b:) | echo b:[k] | endfor
+for k in keys(w:) | echo w:[k] | endfor
+for k in keys(t:) | echo t:[k] | endfor
+for k in keys(g:) | echo g:[k] | endfor
+for k in keys(l:) | echo l:[k] | endfor
+for k in keys(s:) | echo s:[k] | endfor
+for k in keys(a:) | echo a:[k] | endfor
+for k in keys(v:) | echo v:[k] | endfor
+
+" Neomnv-specific variables (not highlighted by default)
+
+echo v:lua v:msgpack_types v:relnum v:stderr v:termrequest v:virtnum
+
+echo &channel &inccommand &mousescroll &pumblend &redrawdebug &scrollback
+echo &shada &shadafile &statuscolumn &termpastefilter &termsync &winbar
+echo &winblend
+
diff --git a/mnv/runtime/syntax/testdir/input/modula2_iso.def b/mnv/runtime/syntax/testdir/input/modula2_iso.def
new file mode 100644
index 0000000000..356a31c1ca
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/modula2_iso.def
@@ -0,0 +1,114 @@
+(* Modula-2 ISO Test File for MNV Syntax Colouring *)
+
+(* --------------------------------------------------
+ * THIS FILE IS LICENSED UNDER THE MNV LICENSE
+ * see https://github.com/Project-Tick/Project-Tick/blob/master/LICENSE
+ * -------------------------------------------------- *)
+
+
+DEFINITION MODULE Foobar; (*!m2iso*)
+
+FROM SYSTEM IMPORT LOC, WORD, ADDRESS;
+
+CONST MaxFoo = 1.0; LF = CHR(10);
+
+TYPE Foo = POINTER TO Bar;
+
+(* predefined constants *)
+FALSE NIL TRUE INTERRUPTIBLE UNINTERRUPTIBLE
+
+(* predefined types *)
+BITSET BOOLEAN CHAR PROC CARDINAL INTEGER LONGINT REAL LONGREAL
+COMPLEX LONGCOMPLEX PROTECTION
+
+(* predefined procedures *)
+CAP DEC EXCL HALT INC INCL
+
+(* predefined functions *)
+ABS CHR CMPLX FLOAT HIGH IM INT LENGTH LFLOAT MAX MIN ODD ORD RE SIZE TRUNC VAL
+
+(* predefined macros *)
+NEW DISPOSE
+
+(* unsafe builtins *)
+ADDRESS BYTE LOC WORD ADR CAST TSIZE SYSTEM
+MAKEADR ADDADR SUBADR DIFADR ROTATE SHIFT
+
+(* non-standard language extensions *)
+LONGCARD LONGBITSET
+
+(* user defined identifiers *)
+foobar Foobar FooBar foo123 foo_bar
+
+(* string literals *)
+str := "foo 'bar' baz";
+str := 'foo "bar" baz';
+
+(* numeric literals *)
+0FFFH, 1.23, 1.23e-45, 1000
+
+(* octal literals *)
+n := 0377B; ch := 0377C;
+
+(* pragmas *)
+<*$foo*>
+
+(* block comments with emphasis *)
+(* copyright (c) Jurrasic Inc.
+ author Fred Flintstone Sr.
+ license see LICENSE file. *)
+
+(* pre-conditions: foo bar baz bam boo doodle wah.
+ post-conditions: foodle babble bozo bim bam dang.
+ error-conditions: dada jingle jungle boggle dee boo. *)
+
+(* technical debt markers *)
+(* TODO: ... *)
+(* FIXME *)
+(* DEPRECATED *)
+
+(* procedures *)
+PROCEDURE NewFooWithBar ( VAR foo: Foo; bar : INTEGER );
+BEGIN
+ NEW(foo);
+ foo^.bar := bar;
+ RETURN
+END SetBar;
+
+(* functions *)
+PROCEDURE bar ( foo : Foo ) : INTEGER;
+BEGIN
+ IF foo = NIL THEN
+ HALT
+ ELSE
+ RETURN foo^.bar
+ END (* IF *)
+END bar;
+
+(* disabled code *)
+?<
+WHILE foo = bar DO
+ baz(bam, boo)
+END (* WHILE *);
+>?
+
+(* synonyms *)
+@ & ~
+
+(* illegal characters *)
+` ! $ % \ ? _
+
+(* illegal identifiers *)
+
+_bar _bar_baz _bar_baz__bam _bar_baz__bam_boo
+
+bar_ bar_baz_ bar_baz__bam_ bar_baz__bam_boo_
+
+__bar __bar_baz __bar_baz__bam __bar_baz__bam_boo
+
+bar__ bar_baz__ bar_baz__bam__ bar_baz__bam_boo__
+
+bar__baz __bar_baz__ __bar__baz__ __
+
+
+END Foobar.
diff --git a/mnv/runtime/syntax/testdir/input/modula2_pim.def b/mnv/runtime/syntax/testdir/input/modula2_pim.def
new file mode 100644
index 0000000000..4042e3c086
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/modula2_pim.def
@@ -0,0 +1,111 @@
+(* Modula-2 PIM Test File for MNV Syntax Colouring *)
+
+(* --------------------------------------------------
+ * THIS FILE IS LICENSED UNDER THE MNV LICENSE
+ * see https://github.com/Project-Tick/Project-Tick/blob/master/LICENSE
+ * -------------------------------------------------- *)
+
+DEFINITION MODULE Foobar; (*!m2pim*)
+
+FROM SYSTEM IMPORT WORD, ADDRESS;
+
+CONST MaxFoo = 1.0; LF = CHR(10);
+
+TYPE Foo = POINTER TO Bar;
+
+(* predefined constants *)
+FALSE NIL TRUE
+
+(* predefined types *)
+BITSET BOOLEAN CHAR PROC CARDINAL INTEGER LONGINT REAL LONGREAL
+
+(* predefined procedures *)
+CAP DEC EXCL HALT INC INCL
+
+(* predefined functions *)
+ABS CHR FLOAT HIGH MAX MIN ODD ORD SIZE TRUNC VAL
+
+(* predefined macros *)
+NEW DISPOSE
+
+(* unsafe builtins *)
+ADDRESS PROCESS WORD ADR TSIZE NEWPROCESS TRANSFER SYSTEM
+
+(* non-standard language extensions *)
+BYTE LONGCARD LONGBITSET
+
+(* user defined identifiers *)
+foobar Foobar FooBar foo123 foo_bar
+
+(* string literals *)
+str := "foo 'bar' baz";
+str := 'foo "bar" baz';
+
+(* numeric literals *)
+0FFFH, 1.23, 1.23e-45, 1000
+
+(* octal literals *)
+n := 0377B; ch := 0377C;
+
+(* pragmas *)
+(*$foo*)
+
+(* block comments with emphasis *)
+(* copyright (c) Jurrasic Inc.
+ author Fred Flintstone Sr.
+ license see LICENSE file. *)
+
+(* pre-conditions: foo bar baz bam boo doodle wah.
+ post-conditions: foodle babble bozo bim bam dang.
+ error-conditions: dada jingle jungle boggle dee boo. *)
+
+(* technical debt markers *)
+(* TODO: ... *)
+(* FIXME *)
+(* DEPRECATED *)
+
+(* procedures *)
+PROCEDURE NewFooWithBar ( VAR foo: Foo; bar : INTEGER );
+BEGIN
+ NEW(foo);
+ foo^.bar := bar;
+ RETURN
+END SetBar;
+
+(* functions *)
+PROCEDURE bar ( foo : Foo ) : INTEGER;
+BEGIN
+ IF foo = NIL THEN
+ HALT
+ ELSE
+ RETURN foo^.bar
+ END (* IF *)
+END bar;
+
+(* disabled code *)
+?<
+WHILE foo = bar DO
+ baz(bam, boo)
+END (* WHILE *);
+>?
+
+(* synonyms *)
+& ~
+
+(* illegal characters *)
+` ! @ $ % \ ? _
+
+(* illegal identifiers *)
+
+_bar _bar_baz _bar_baz__bam _bar_baz__bam_boo
+
+bar_ bar_baz_ bar_baz__bam_ bar_baz__bam_boo_
+
+__bar __bar_baz __bar_baz__bam __bar_baz__bam_boo
+
+bar__ bar_baz__ bar_baz__bam__ bar_baz__bam_boo__
+
+bar__baz __bar_baz__ __bar__baz__ __
+
+
+END Foobar.
diff --git a/mnv/runtime/syntax/testdir/input/modula2_r10.def b/mnv/runtime/syntax/testdir/input/modula2_r10.def
new file mode 100644
index 0000000000..6c75c40b7b
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/modula2_r10.def
@@ -0,0 +1,146 @@
+(* Modula-2 R10 Test File for MNV Syntax Colouring *)
+
+(* --------------------------------------------------
+ * THIS FILE IS LICENSED UNDER THE MNV LICENSE
+ * see https://github.com/Project-Tick/Project-Tick/blob/master/LICENSE
+ * -------------------------------------------------- *)
+
+DEFINITION MODULE Foobar; (*!m2r10*)
+
+IMPORT UNSAFE ALIAS BYTE, WORD, ADDRESS;
+
+CONST MaxFoo = 1.0;
+
+TYPE Foo = ALIAS OF Bar;
+
+(* predefined constants *)
+NIL FALSE TRUE
+
+(* predefined types *)
+BOOLEAN CHAR UNICHAR OCTET CARDINAL LONGCARD INTEGER LONGINT REAL LONGREAL
+
+(* predefined procedures *)
+APPEND INSERT REMOVE SORT SORTNEW
+
+(* predefined functions *)
+CHR ORD ODD ABS SGN MIN MAX LOG2 POW2 ENTIER PRED SUCC PTR CAPACITY COUNT LENGTH
+
+(* predefined macros *)
+NOP TMIN TMAX TSIZE TLIMIT
+
+(* unsafe builtins *)
+UNSAFE
+
+(* unsafe builtin types *)
+BYTE WORD LONGWORD ADDRESS OCTETSEQ
+
+(* unsafe builtin procedures *)
+ADD SUB DEC INC SETBIT HALT
+
+(* unsafe builtin functions *)
+ADR CAST BIT SHL SHR BWNOT BWAND BWOR
+
+(* non-portable language extensions *)
+ASSEMBLER ASM REG
+
+(* user defined identifiers *)
+foobar Foobar FooBar foo_bar foo0
+
+
+(* string literals *)
+str := "foo 'bar' baz";
+str := 'foo "bar" baz';
+
+(* numeric literals *)
+0b0110'0011'0110'0000, 0u0A, 0x0123, 0xCAFE'D00D
+1'000'000.00, 1.23, 1.23e+10, 1.234'567'890e-1'000
+
+
+(* language defined pragmas *)
+<*MSG=INFO:"foobar"*> <*ENCODING="UTF8"*> <*INLINE*> <*NOINLINE*> <*FFI="C"*>
+
+(* implementation defined pragmas *)
+<*GM2.Foobar|W=Bazbam*>
+
+
+(* single line comment *)
+! foo bar baz bam boo
+
+(* block comments with emphasis *)
+(* copyright (c) 2016 Modula-2 Foundation.
+ authors B.Kowarsch and R.Sutcliffe
+ license see LICENSE *)
+
+(* pre-conditions: foo bar baz bam boo doodle wah.
+ post-conditions: foodle babble bozo bim bam dang.
+ error-conditions: dada jingle jungle boggle dee boo. *)
+
+(* (* *) *)
+
+(* bindings *)
+PROCEDURE [+] sum ( a, b : BCD ) : BCD;
+
+PROCEDURE [MOD] modulus ( n, m : INT64 ) : INT64;
+
+PROCEDURE [RETAIN] Retain ( foo : Foo );
+
+PROCEDURE [LENGTH] length ( str : String ) : LONGCARD;
+
+
+(* procedures *)
+PROCEDURE NewFooWithBar ( VAR foo: Foo; bar : INTEGER );
+BEGIN
+ NEW(foo);
+ foo^.bar := bar;
+ RETURN
+END NewFooWithBar;
+
+END END;
+
+(* functions *)
+PROCEDURE bar ( foo : Foo ) : INTEGER;
+BEGIN
+ IF foo = NIL THEN
+ UNSAFE.HALT
+ ELSE
+ RETURN foo^.bar
+ END (* IF *)
+END bar;
+
+
+(* technical debt *)
+TO DO ( 1234, Weight.Major ) (* foo *)
+ "redesign foo", 2d;
+ "replace foo", 2d;
+ "test new foo", 1d
+END (* TO DO *);
+
+PROCEDURE SetBaba <*DEPRECATED*> ( n : CARDINAL );
+
+
+(* disabled code *)
+?<
+WHILE foo = bar DO
+ baz(bam, boo)
+END (* WHILE *);
+>?
+
+
+(* illegal characters *)
+` ~ $ % ? _
+
+(* illegal identifiers *)
+
+_bar _bar_baz _bar_baz__bam _bar_baz__bam_boo
+
+bar_ bar_baz_ bar_baz__bam_ bar_baz__bam_boo_
+
+__bar __bar_baz __bar_baz__bam __bar_baz__bam_boo
+
+bar__ bar_baz__ bar_baz__bam__ bar_baz__bam_boo__
+
+bar__baz __bar_baz__ __bar__baz__ __
+
+
+(* module end *)
+END Foobar.
diff --git a/mnv/runtime/syntax/testdir/input/po.po b/mnv/runtime/syntax/testdir/input/po.po
new file mode 100644
index 0000000000..15226d467f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/po.po
@@ -0,0 +1,51 @@
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"POT-Creation-Date: 2026-03-02 13:23+0900\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
+"X-Generator: ManuallyGenerated\n"
+
+#: path/to/file.c:123
+#, fuzzy, c-format
+#| msgid "Hi, %s.\n"
+msgid "Hello, %s.\n"
+msgstr ""
+"Hi, %s.\n"
+
+#: path/to/file.py:123
+#, python-format
+msgid "%(num) word"
+msgid_plural "%(num) words"
+msgstr[0] ""
+msgstr[1] ""
+
+#. comment for translator
+#: path/to/file.cpp:234
+#: path/to/file.cpp:256
+#, qt-format
+msgctxt "%1 is a variable"
+msgid "value of %1:\t%L2"
+msgstr ""
+
+#: path/to/file.rs:123
+#, rust-format
+msgid "Hello, \"{:?}\"."
+msgstr "Hallo, »{:?}«."
+
+#= no-wrap
+msgid "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
+msgstr "いろはにほへと"
+
+# outdated entries
+#~ msgid "foo"
+#~ msgstr "foo"
diff --git a/mnv/runtime/syntax/testdir/input/progress_comments.p b/mnv/runtime/syntax/testdir/input/progress_comments.p
new file mode 100644
index 0000000000..053f8a4405
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/progress_comments.p
@@ -0,0 +1,45 @@
+/*
+ * MNV_TEST_SETUP set filetype=progress
+ */
+
+define variable customer_name as character no-undo.
+
+/* The test setup above is an example of a multi-line comment.
+This is too; the leading * and left-hand alignment are not required. */
+for each customer no-lock
+ where customer.customer_id = 12345
+:
+ assign cust_name = customer.customer_name. /* Comments can also appear
+ at the end of a line. */
+end. /* for each customer */
+
+/* Comments can be /* nested */. Here's the same query as above, but
+commented out this time:
+
+for each customer no-lock
+ where customer.customer_id = 12345
+:
+ assign cust_name = customer.customer_name. /* Comments can also appear
+ at the end of a line. */
+end. /* for each customer */
+
+TODO: Note that /*/ does not end the comment, because it actually starts a
+new comment whose first character is a '/'. Now we need two end-comment
+markers to return to actual code. */ */
+
+display customer_name.
+
+// This is the single-line comment syntax.
+
+//No space is required after the slashes. Also, a /* here does not begin a
+//new block comment.
+
+for each supplier no-lock:
+ /* However, a block comment can end inside (what looks like) a
+ single-line comment, because the slashes are just text as far as the
+ // block comment is concerned. */
+ display supplier.
+
+ // TODO: Observe that todo highlighting works in line comments too.
+end.
+
diff --git a/mnv/runtime/syntax/testdir/input/python2_strings.py b/mnv/runtime/syntax/testdir/input/python2_strings.py
new file mode 100644
index 0000000000..3a68742787
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/python2_strings.py
@@ -0,0 +1,82 @@
+# String literals
+# https://docs.python.org/2/reference/lexical_analysis.html#string-literals
+
+# Strings: Source encoding, no Unicode escape sequences
+test = 'String with escapes \' and \" and \t'
+test = "String with escapes \040 and \xFF"
+test = 'String with literal \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = "String with escaped \\ backslash and ignored \
+newline"
+test = '''String with quotes ' and "
+and escapes \t and \040 and \xFF
+and literal \u00A1 and \U00010605'''
+test = """String with quotes ' and "
+and escapes \t and \040 and \xFF
+and literal \u00A1 and \U00010605"""
+
+# Raw strings
+test = r'Raw string with literal \' and \" and \t'
+test = R"Raw string with literal \040 and \xFF"
+test = r'Raw string with literal \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = R"Raw string with literal \\ backslashes and literal \
+newline"
+test = r'''Raw string with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605'''
+test = R"""Raw string with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605"""
+
+# B-strings: Prefix is allowed but ignored (https://peps.python.org/pep-3112)
+test = b'String with escapes \' and \" and \t'
+test = B"String with escapes \040 and \xFF"
+test = b'String with literal \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = B"String with escaped \\ backslash and ignored \
+newline"
+test = b'''String with quotes ' and "
+and escapes \t and \040 and \xFF
+and literal \u00A1 and \U00010605'''
+test = B"""String with quotes ' and "
+and escapes \t and \040 and \xFF
+and literal \u00A1 and \U00010605"""
+
+# Raw b-strings
+test = br'Raw string with literal \' and \" and \t'
+test = bR"Raw string with literal \040 and \xFF"
+test = Br'Raw string with literal \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = BR"Raw string with literal \\ backslashes and literal \
+newline"
+test = br'''Raw string with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605'''
+test = BR"""Raw string with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605"""
+
+# Unicode strings
+test = u'String with escapes \' and \" and \t'
+test = U"String with escapes \040 and \xFF"
+test = u'String with escapes \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = U"String with escaped \\ backslash and ignored \
+newline"
+test = u'''String with quotes ' and "
+and escapes \t and \040 and \xFF
+and escapes \u00A1 and \U00010605'''
+test = U"""String with quotes ' and "
+and escapes \t and \040 and \xFF
+and escapes \u00A1 and \U00010605"""
+
+# Raw Unicode strings: Only Unicode escape sequences
+test = ur'Raw Unicode string with literal \' and \" and \t'
+test = uR"Raw Unicode string with literal \040 and \xFF"
+test = Ur'Raw Unicode string with escapes \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = UR"Raw Unicode string with literal \\ backslashes and literal \
+newline"
+test = ur'''Raw Unicode string with quotes ' and "
+and literal \t and \040 and \xFF
+and escapes \u00A1 and \U00010605'''
+test = UR"""Raw Unicode string with quotes ' and "
+and literal \t and \040 and \xFF
+and escapes \u00A1 and \U00010605"""
+
+# mnv: syntax=python2
diff --git a/mnv/runtime/syntax/testdir/input/python_constants_builtin_default.py b/mnv/runtime/syntax/testdir/input/python_constants_builtin_default.py
new file mode 100644
index 0000000000..075feb2211
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/python_constants_builtin_default.py
@@ -0,0 +1,11 @@
+# Built-in Constants
+# https://docs.python.org/3/library/constants.html
+
+# MNV_TEST_SETUP unlet g:python_constant_highlight
+# MNV_TEST_SETUP unlet g:python_no_builtin_highlight
+test = False
+test = True
+test = None
+test = NotImplemented
+test = Ellipsis
+test = __debug__
diff --git a/mnv/runtime/syntax/testdir/input/python_constants_builtin_highlight.py b/mnv/runtime/syntax/testdir/input/python_constants_builtin_highlight.py
new file mode 100644
index 0000000000..6a6d5d60e5
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/python_constants_builtin_highlight.py
@@ -0,0 +1,11 @@
+# Built-in Constants
+# https://docs.python.org/3/library/constants.html
+
+# MNV_TEST_SETUP let g:python_constant_highlight = 1
+# MNV_TEST_SETUP unlet g:python_no_builtin_highlight
+test = False
+test = True
+test = None
+test = NotImplemented
+test = Ellipsis
+test = __debug__
diff --git a/mnv/runtime/syntax/testdir/input/python_constants_keyword_default.py b/mnv/runtime/syntax/testdir/input/python_constants_keyword_default.py
new file mode 100644
index 0000000000..5bd43e5a0e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/python_constants_keyword_default.py
@@ -0,0 +1,11 @@
+# Built-in Constants
+# https://docs.python.org/3/library/constants.html
+
+# MNV_TEST_SETUP unlet g:python_constant_highlight
+# MNV_TEST_SETUP let g:python_no_builtin_highlight = 1
+test = False
+test = True
+test = None
+test = NotImplemented
+test = Ellipsis
+test = __debug__
diff --git a/mnv/runtime/syntax/testdir/input/python_constants_keyword_highlight.py b/mnv/runtime/syntax/testdir/input/python_constants_keyword_highlight.py
new file mode 100644
index 0000000000..86e4892cdf
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/python_constants_keyword_highlight.py
@@ -0,0 +1,11 @@
+# Built-in Constants
+# https://docs.python.org/3/library/constants.html
+
+# MNV_TEST_SETUP let g:python_constant_highlight = 1
+# MNV_TEST_SETUP let g:python_no_builtin_highlight = 1
+test = False
+test = True
+test = None
+test = NotImplemented
+test = Ellipsis
+test = __debug__
diff --git a/mnv/runtime/syntax/testdir/input/python_ellipsis.py b/mnv/runtime/syntax/testdir/input/python_ellipsis.py
new file mode 100644
index 0000000000..ac8ecc3932
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/python_ellipsis.py
@@ -0,0 +1,46 @@
+# Ellipsis Literal
+# https://docs.python.org/3/library/constants.html#Ellipsis
+
+# Placeholders
+...
+ ...
+x = ...
+y = ... # Comment
+class C: ...
+lambda: ...
+
+# Annotations
+numbers: Tuple[int, ...]
+
+# Doctests
+"""A doctest
+
+>>> class A:
+... def __init__(self):
+... ...
+>>> class B: ...
+>>> x = ...
+>>> raise ValueError('multi\n line\ndetail')
+Traceback (most recent call last):
+ ...
+ValueError: multi
+ line
+detail
+>>> print(list(range(20))) # doctest: +ELLIPSIS
+[0, 1, ..., 18, 19]
+>>> exec(s) #doctest: +ELLIPSIS
+-3.21716034272e-0...7
+"""
+
+class C:
+ """
+ >>> class C:
+ ... def __init__(self):
+ ... ...
+ """
+
+# Numpy
+x[..., 0]
+
+# Issue #18263 (Python highlighting ellipsis, false positive)
+a = ".." # comment
diff --git a/mnv/runtime/syntax/testdir/input/python_strings_bytes.py b/mnv/runtime/syntax/testdir/input/python_strings_bytes.py
new file mode 100644
index 0000000000..569168637e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/python_strings_bytes.py
@@ -0,0 +1,249 @@
+# String and Bytes literals
+# https://docs.python.org/3/reference/lexical_analysis.html#string-and-bytes-literals
+
+# Strings
+test = 'String with escapes \' and \" and \t'
+test = "String with escapes \040 and \xFF"
+test = 'String with escapes \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = "String with escaped \\ backslash and ignored \
+newline"
+test = '''String with quotes ' and "
+and escapes \t and \040 and \xFF
+and escapes \u00A1 and \U00010605'''
+test = """String with quotes ' and "
+and escapes \t and \040 and \xFF
+and escapes \u00A1 and \U00010605"""
+
+# Raw strings
+test = r'Raw string with literal \' and \" and \t'
+test = R"Raw string with literal \040 and \xFF"
+test = r'Raw string with literal \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = R"Raw string with literal \\ backslashes and literal \
+newline"
+test = r'''Raw string with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605'''
+test = R"""Raw string with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605"""
+
+# Unicode literals: Prefix is allowed but ignored (https://peps.python.org/pep-0414)
+test = u'String with escapes \' and \" and \t'
+test = U"String with escapes \040 and \xFF"
+test = u'String with escapes \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = U"String with escaped \\ backslash and ignored \
+newline"
+test = u'''String with quotes ' and "
+and escapes \t and \040 and \xFF
+and escapes \u00A1 and \U00010605'''
+test = U"""String with quotes ' and "
+and escapes \t and \040 and \xFF
+and escapes \u00A1 and \U00010605"""
+
+# Raw Unicode literals are not allowed
+test = ur'Invalid string with \' and \" and \t'
+test = uR"Invalid string with \040 and \xFF"
+test = Ur'Invalid string with \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = UR"Invalid string with \\ backslashes and literal \
+newline"
+test = ru'Invalid string with \' and \" and \t'
+test = rU"Invalid string with \040 and \xFF"
+test = Ru'Invalid string with \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = RU"Invalid string with \\ backslashes and literal \
+newline"
+test = ur'''Invalid string with ' and "
+and \t and \040 and \xFF
+and \u00A1 and \U00010605'''
+test = RU"""Invalid string with ' and "
+and \t and \040 and \xFF
+and \u00A1 and \U00010605"""
+
+# Formatted string literals (f-strings)
+# https://docs.python.org/3/reference/lexical_analysis.html#f-strings
+test = f'F-string with escapes \' and \" and \t and fields {foo} and {bar}'
+test = F"F-string with escapes \040 and \xFF and fields {foo} and {bar}"
+test = f'F-string with escapes \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK} and fields {foo} and {bar}'
+test = F"F-string with literal {{field}} and fields {foo} and {bar}"
+test = f'''F-string with quotes ' and "
+and escapes \t and \040 and \xFF
+and escapes \u00A1 and \U00010605
+and fields {1}, {2} and {1
+ +
+ 2}'''
+test = F"""F-string with quotes ' and "
+and escapes \t and \040 and \xFF
+and escapes \u00A1 and \U00010605
+and fields {1}, {2} and {1
+ +
+ 2}"""
+
+# Raw formatted string literals
+test = fr'Raw f-string with literal \' and \" and \t and fields {foo} and {bar}'
+test = fR"Raw f-string with literal \040 and \xFF and fields {foo} and {bar}"
+test = Fr'Raw f-string with literal \u00A1 and \U00010605 and fields \N{FIELD, NOT, ESCAPE} and {foo} and {bar}'
+test = FR"Raw f-string with literal {{field}} and fields {foo} and {bar}"
+test = rf'Raw f-string with literal \' and \" and \t and fields {foo} and {bar}'
+test = rF"Raw f-string with literal \040 and \xFF and fields {foo} and {bar}"
+test = Rf'Raw f-string with literal \u00A1 and \U00010605 and fields \N{FIELD, NOT, ESCAPE} and {foo} and {bar}'
+test = RF"Raw f-string with literal {{field}} and fields {foo} and {bar}"
+test = fr'''Raw f-string with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605
+and fields {1}, {2} and {1
+ +
+ 2}'''
+test = RF"""Raw f-string with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605
+and fields {1}, {2} and {1
+ +
+ 2}"""
+
+# Template string literals (t-strings)
+# https://docs.python.org/3/reference/lexical_analysis.html#template-string-literals
+test = t'T-string with escapes \' and \" and \t and fields {foo} and {bar}'
+test = T"T-string with escapes \040 and \xFF and fields {foo} and {bar}"
+test = t'T-string with escapes \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK} and fields {foo} and {bar}'
+test = T"T-string with literal {{field}} and fields {foo} and {bar}"
+test = t'''T-string with quotes ' and "
+and escapes \t and \040 and \xFF
+and escapes \u00A1 and \U00010605
+and fields {1}, {2} and {1
+ +
+ 2}'''
+test = T"""T-string with quotes ' and "
+and escapes \t and \040 and \xFF
+and escapes \u00A1 and \U00010605
+and fields {1}, {2} and {1
+ +
+ 2}"""
+
+# Raw template string literals
+test = tr'Raw t-string with literal \' and \" and \t and fields {foo} and {bar}'
+test = tR"Raw t-string with literal \040 and \xFF and fields {foo} and {bar}"
+test = tr'Raw t-string with literal \u00A1 and \U00010605 and fields \N{FIELD, NOT, ESCAPE} and {foo} and {bar}'
+test = tR"Raw t-string with literal {{field}} and fields {foo} and {bar}"
+test = rt'Raw t-string with literal \' and \" and \t and fields {foo} and {bar}'
+test = rT"Raw t-string with literal \040 and \xFF and fields {foo} and {bar}"
+test = Rt'Raw t-string with literal \u00A1 and \U00010605 and fields \N{FIELD, NOT, ESCAPE} and {foo} and {bar}'
+test = RT"Raw t-string with literal {{field}} and fields {foo} and {bar}"
+test = tr'''Raw t-string with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605
+and fields {1}, {2} and {1
+ +
+ 2}'''
+test = RT"""Raw t-string with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605
+and fields {1}, {2} and {1
+ +
+ 2}"""
+
+# F-string replacement fields
+test = f"String is {
+ "one plus "
+ "two plus "
+ "three"}"
+test = f"Number is {
+ 1 +
+ 2 +
+ 3}"
+test = f"Float is {1.23}"
+test = f"abc{a # This is a comment }
+ + 1}"
+test = f"def{a # So is this :
+ + 2}"
+test = f"ghi{a # And this "
+ + 3}"
+test = f"He said his name is {name!r}."
+test = f"He said his name is {repr(name)}."
+test = f"result: {value:{width}}"
+test = f"result: {value:{width}.{precision}}"
+test = f"result: {value:{
+ width
+ }.{
+ precision
+ }}"
+test = f"result: {value:{width:d}.{precision!s}}"
+test = f"result: {value:{options}{width}{grouping}{precision}{type}}"
+test = f"{number:#0x}"
+test = f"{number:+#0x}"
+test = f"{number:<+#0x}"
+test = f"{number: <+#0x}"
+test = f"{number:<#0x}"
+test = f"{number: <#0x}"
+test = f"{string=}"
+test = f"{string=!r}"
+test = f"{string=:20}"
+test = f"{string=!r:20}"
+test = f"{ string = }"
+test = f"{ string = !r}"
+test = f"{ string = !r }"
+test = f"{ string = :20}"
+test = f"{ string = !r:20}"
+test = f"{ string = !r :20}"
+test = f"abc {a["x"]} def"
+test = f"List contains:\n{"\n".join(a)}"
+test = f"Today's date is {datetime.now()}"
+test = f"Today's formatted date is {datetime.now():%Y-%m-%d %H:%M:%S}"
+test = f"Date is {datetime.datetime(2010, 7, 4, 12, 15, 58)}"
+test = f"Formatted date is {datetime.datetime(2010, 7, 4, 12, 15, 58):%Y-%m-%d %H:%M:%S}"
+test = f"Lambda returns {(lambda x: x**2)}"
+test = f"Zero padded lambda returns {(lambda x: x**2):09}"
+test = f"Space padded lambda returns {(lambda x: x**2):{width}}"
+test = f"List copy is {items[:]}"
+test = f"List slice is {items[1:]}"
+test = f"List slice is {items[:9]}"
+test = f"List elements are {items[:2:]}"
+test = f"Padded list copy is {items[:]:99}"
+test = f"Left-aligned list slice is {items[1:]:<99}"
+test = f"Right aligned list slice is {items[:9]:>99}"
+test = f"Center-aligned list elements are {items[:2:]:^99}"
+test = f"Expression is {x == 1}"
+test = f"Expression is {x != 1}"
+test = f"Expression is {(x := 1)}"
+test = f"Debug expression is {x == 1=}"
+test = f"Debug expression is {x != 1=}"
+test = f"Debug expression is {(x := 1)=}"
+test = f"List comprehension returns { [x**2 for x in range(10)] }"
+test = f"List comprehension returns { [
+ x**2 for x in range(10)
+ ] }"
+test = f"Padded list comprehension returns { [x**2 for x in range(10)] :99}"
+test = f"Dict comprehension returns { {x: x**2 for x in range(10)} }"
+test = f"Dict comprehension returns { {
+ x: x**2 for x in range(10)
+ } }"
+test = f"Padded dict comprehension returns { {x: x**2 for x in range(10)} :99}"
+
+# Bytes
+test = b'Bytes with escapes \' and \" and \t'
+test = B"Bytes with escapes \040 and \xFF"
+test = b'Bytes with SyntaxWarning \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = B"Bytes with escaped \\ backslash and ignored \
+newline"
+test = b'''Bytes with quotes ' and "
+and escapes \t and \040 and \xFF
+and SyntaxWarning \u00A1 and \U00010605'''
+test = B"""Bytes with quotes ' and "
+and escapes \t and \040 and \xFF
+and SyntaxWarning \u00A1 and \U00010605"""
+
+# Raw bytes
+test = br'Raw bytes with literal \' and \" and \t'
+test = bR"Raw bytes with literal \040 and \xFF"
+test = Br'Raw bytes with literal \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = BR"Raw bytes with literal \\ backslashes and literal \
+newline"
+test = rb'Raw bytes with literal \' and \" and \t'
+test = rB"Raw bytes with literal \040 and \xFF"
+test = Rb'Raw bytes with literal \u00A1 and \U00010605 and \N{INVERTED EXCLAMATION MARK}'
+test = RB"Raw bytes with literal \\ backslashes and literal \
+newline"
+test = br'''Raw bytes with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605'''
+test = RB"""Raw bytes with quotes ' and "
+and literal \t and \040 and \xFF
+and literal \u00A1 and \U00010605"""
diff --git a/mnv/runtime/syntax/testdir/input/python_type.py b/mnv/runtime/syntax/testdir/input/python_type.py
new file mode 100644
index 0000000000..513b97fbd8
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/python_type.py
@@ -0,0 +1,8 @@
+# Builtin
+type()
+
+# Statement
+type Point = tuple[float, float]
+
+# Should not match
+typename = ''
diff --git a/mnv/runtime/syntax/testdir/input/sed.sed b/mnv/runtime/syntax/testdir/input/sed.sed
new file mode 100644
index 0000000000..a6f248e9fb
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sed.sed
@@ -0,0 +1,65 @@
+# sed(1)
+
+
+# Addresses
+
+
+# line number
+
+42p
+$p
+
+/foobar/p
+/foo[/]bar/p
+/foo\/bar/p
+
+\xfoobarxp
+\xfoo\xbarxp
+\xfoo[x]barxp
+
+# skip bracket expressions
+\a_\a_[a[:ascii:]a[.a.]a[=a=]a]_ap
+\a_\a_[^a[:ascii:]a[.a.]a[=a=]a]_ap
+\a_\a_[]a[:ascii:]a[.a.]a[=a=]a]_ap
+\a_\a_[^]a[:ascii:]a[.a.]a[=a=]a]_ap
+
+
+# range
+
+42,84p
+/foo/,/bar/p
+
+/foo/,42p
+42,/bar/p
+
+
+# GNU extensions
+
+
+# step
+
+1~2p
+
+
+# ignore case, multiline
+
+/foobar/Ip
+/foobar/Mp
+/foobar/IMp
+/foobar/MIp
+
+\afoob\araIp
+\afoob\araMp
+\afoob\araIMp
+\afoob\araMIp
+
+
+# increment
+
+42,+42p
+
+
+# step
+
+42,~2p
+
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/README.txt b/mnv/runtime/syntax/testdir/input/selftestdir/README.txt
new file mode 100644
index 0000000000..dea112ad5c
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/README.txt
@@ -0,0 +1,10 @@
+The test files with made-up syntax in this directory serve for additional
+linewise checks to be manually performed whenever the algorithm managing
+screen dump file generation is modified (../../runtest.mnv#RunTest()).
+
+This is mainly used for debugging and testing the syntax test suite.
+
+Please test any changes as follows:
+ cd runtime/syntax/
+ make clean self-testing test
+
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_01 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_01
new file mode 100644
index 0000000000..cf78d974cb
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_01
@@ -0,0 +1,60 @@
+..........................................................................1
+..........................................................................2
+..........................................................................3
+..........................................................................4
+..............................winwidth(0): 75.............................5
+.............................winheight(0): 19.............................6
+.................................ruler....................................7
+..........................................................................8
+..........................................................................9
+.........................................................................10
+.........................................................................11
+.........................................................................12
+.........................................................................13
+.........................................................................14
+.........................................................................15
+.........................................................................16
+.........................................................................17
+.........................................................................18
+.........................................................................19
+.........................................................................20
+.........................................................................21
+.........................................................................22
+.........................................................................23
+.........................................................................24
+.........................................................................25
+.........................................................................26
+.........................................................................27
+.........................................................................28
+.........................................................................29
+.........................................................................30
+.........................................................................31
+.........................................................................32
+.........................................................................33
+.........................................................................34
+.........................................................................35
+.........................................................................36
+.........................................................................37
+.........................................................................38
+.........................................................................39
+.........................................................................40
+.........................................................................41
+.........................................................................42
+.........................................................................43
+.........................................................................44
+.........................................................................45
+.........................................................................46
+.........................................................................47
+.........................................................................48
+.........................................................................49
+.........................................................................50
+.........................................................................51
+.........................................................................52
+.........................................................................53
+.........................................................................54
+.........................................................................55
+.........................................................................56
+.........................................................................57
+.........................................................................58
+.........................................................................59
+.........................................................................60
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_02 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_02
new file mode 100644
index 0000000000..4748fa117f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_02
@@ -0,0 +1,30 @@
+1..........................................................................2
+3..........................................................................4
+5..........................................................................6
+7..........................................................................8
+9............................winwidth(0): 75...............................10
+11..........................winheight(0): 19...............................12
+13..............................ruler......................................14
+15.........................................................................16
+17.........................................................................18
+19.........................................................................20
+21.........................................................................22
+23.........................................................................24
+25.........................................................................26
+27.........................................................................28
+29.........................................................................30
+31.........................................................................32
+33.........................................................................34
+35.........................................................................36
+37.........................................................................38
+39.........................................................................40
+41.........................................................................42
+43.........................................................................44
+45.........................................................................46
+47.........................................................................48
+49.........................................................................50
+51.........................................................................52
+53.........................................................................54
+55.........................................................................56
+57.........................................................................58
+59.........................................................................60
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_03 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_03
new file mode 100644
index 0000000000..a8a16e98cc
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_03
@@ -0,0 +1,20 @@
+1..........................................................................2..........................................................................3
+4..........................................................................5..........................................................................6
+7..........................................................................8..........................................................................9
+10.........................................................................11.........................................................................12
+13...........................winwidth(0): 75...............................14.........................................................................15
+16..........................winheight(0): 19...............................17.........................................................................18
+19..............................ruler......................................20.........................................................................21
+22.........................................................................23.........................................................................24
+25.........................................................................26.........................................................................27
+28.........................................................................29.........................................................................30
+31.........................................................................32.........................................................................33
+34.........................................................................35.........................................................................36
+37.........................................................................38.........................................................................39
+40.........................................................................41.........................................................................42
+43.........................................................................44.........................................................................45
+46.........................................................................47.........................................................................48
+49.........................................................................50.........................................................................51
+52.........................................................................53.........................................................................54
+55.........................................................................56.........................................................................57
+58.........................................................................59.........................................................................60
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_04 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_04
new file mode 100644
index 0000000000..ac0a26a284
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_04
@@ -0,0 +1,15 @@
+1..........................................................................2..........................................................................3..........................................................................4
+5..........................................................................6..........................................................................7..........................................................................8
+9..........................................................................10.........................................................................11.........................................................................12
+13.........................................................................14.........................................................................15.........................................................................16
+17...........................winwidth(0): 75...............................18.........................................................................19.........................................................................20
+21..........................winheight(0): 19...............................22.........................................................................23.........................................................................24
+25..............................ruler......................................26.........................................................................27.........................................................................28
+29.........................................................................30.........................................................................31.........................................................................32
+33.........................................................................34.........................................................................35.........................................................................36
+37.........................................................................38.........................................................................39.........................................................................40
+41.........................................................................42.........................................................................43.........................................................................44
+45.........................................................................46.........................................................................47.........................................................................48
+49.........................................................................50.........................................................................51.........................................................................52
+53.........................................................................54.........................................................................55.........................................................................56
+57.........................................................................58.........................................................................59.........................................................................60
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_05 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_05
new file mode 100644
index 0000000000..2dfb5be08e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_05
@@ -0,0 +1,12 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5
+6..........................................................................7..........................................................................8..........................................................................9..........................................................................10
+11.........................................................................12.........................................................................13.........................................................................14.........................................................................15
+16.........................................................................17.........................................................................18.........................................................................19.........................................................................20
+21...........................winwidth(0): 75...............................22.........................................................................23.........................................................................24.........................................................................25
+26..........................winheight(0): 19...............................27.........................................................................28.........................................................................29.........................................................................30
+31..............................ruler......................................32.........................................................................33.........................................................................34.........................................................................35
+36.........................................................................37.........................................................................38.........................................................................39.........................................................................40
+41.........................................................................42.........................................................................43.........................................................................44.........................................................................45
+46.........................................................................47.........................................................................48.........................................................................49.........................................................................50
+51.........................................................................52.........................................................................53.........................................................................54.........................................................................55
+56.........................................................................57.........................................................................58.........................................................................59.........................................................................60
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_06 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_06
new file mode 100644
index 0000000000..87eaf76d0b
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_06
@@ -0,0 +1,10 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6
+7..........................................................................8..........................................................................9..........................................................................10.........................................................................11.........................................................................12
+13.........................................................................14.........................................................................15.........................................................................16.........................................................................17.........................................................................18
+19.........................................................................20.........................................................................21.........................................................................22.........................................................................23.........................................................................24
+25...........................winwidth(0): 75...............................26.........................................................................27.........................................................................28.........................................................................29.........................................................................30
+31..........................winheight(0): 19...............................32.........................................................................33.........................................................................34.........................................................................35.........................................................................36
+37..............................ruler......................................38.........................................................................39.........................................................................40.........................................................................41.........................................................................42
+43.........................................................................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48
+49.........................................................................50.........................................................................51.........................................................................52.........................................................................53.........................................................................54
+55.........................................................................56.........................................................................57.........................................................................58.........................................................................59.........................................................................60
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_07 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_07
new file mode 100644
index 0000000000..801c470767
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_07
@@ -0,0 +1,9 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7
+8..........................................................................9..........................................................................10.........................................................................11.........................................................................12.........................................................................13.........................................................................14
+15.........................................................................16.........................................................................17.........................................................................18.........................................................................19.........................................................................20.........................................................................21
+22.........................................................................23.........................................................................24.........................................................................25.........................................................................26.........................................................................27.........................................................................28
+29...........................winwidth(0): 75...............................30.........................................................................31.........................................................................32.........................................................................33.........................................................................34.........................................................................35
+36..........................winheight(0): 19...............................37.........................................................................38.........................................................................39.........................................................................40.........................................................................41.........................................................................42
+43..............................ruler......................................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48.........................................................................49
+50.........................................................................51.........................................................................52.........................................................................53.........................................................................54.........................................................................55.........................................................................56
+57.........................................................................58.........................................................................59.........................................................................60.........................................................................61.........................................................................62.........................................................................63
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_08 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_08
new file mode 100644
index 0000000000..2b7bdd94aa
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_08
@@ -0,0 +1,8 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8
+9..........................................................................10.........................................................................11.........................................................................12.........................................................................13.........................................................................14.........................................................................15.........................................................................16
+17.........................................................................18.........................................................................19.........................................................................20.........................................................................21.........................................................................22.........................................................................23.........................................................................24
+25.........................................................................26.........................................................................27.........................................................................28.........................................................................29.........................................................................30.........................................................................31.........................................................................32
+33...........................winwidth(0): 75...............................34.........................................................................35.........................................................................36.........................................................................37.........................................................................38.........................................................................39.........................................................................40
+41..........................winheight(0): 19...............................42.........................................................................43.........................................................................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48
+49..............................ruler......................................50.........................................................................51.........................................................................52.........................................................................53.........................................................................54.........................................................................55.........................................................................56
+57.........................................................................58.........................................................................59.........................................................................60.........................................................................61.........................................................................62.........................................................................63.........................................................................64
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_09 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_09
new file mode 100644
index 0000000000..76b25e6c90
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_09
@@ -0,0 +1,7 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8..........................................................................9
+10.........................................................................11.........................................................................12.........................................................................13.........................................................................14.........................................................................15.........................................................................16.........................................................................17.........................................................................18
+19.........................................................................20.........................................................................21.........................................................................22.........................................................................23.........................................................................24.........................................................................25.........................................................................26.........................................................................27
+28.........................................................................29.........................................................................30.........................................................................31.........................................................................32.........................................................................33.........................................................................34.........................................................................35.........................................................................36
+37...........................winwidth(0): 75...............................38.........................................................................39.........................................................................40.........................................................................41.........................................................................42.........................................................................43.........................................................................44.........................................................................45
+46..........................winheight(0): 19...............................47.........................................................................48.........................................................................49.........................................................................50.........................................................................51.........................................................................52.........................................................................53.........................................................................54
+55..............................ruler......................................56.........................................................................57.........................................................................58.........................................................................59.........................................................................60.........................................................................61.........................................................................62.........................................................................63
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_10 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_10
new file mode 100644
index 0000000000..9d6a15851a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_10
@@ -0,0 +1,6 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8..........................................................................9..........................................................................10
+11.........................................................................12.........................................................................13.........................................................................14.........................................................................15.........................................................................16.........................................................................17.........................................................................18.........................................................................19.........................................................................20
+21.........................................................................22.........................................................................23.........................................................................24.........................................................................25.........................................................................26.........................................................................27.........................................................................28.........................................................................29.........................................................................30
+31...........................winwidth(0): 75...............................32.........................................................................33.........................................................................34.........................................................................35.........................................................................36.........................................................................37.........................................................................38.........................................................................39.........................................................................40
+41..........................wihheight(0): 19...............................42.........................................................................43.........................................................................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48.........................................................................49.........................................................................50
+51..............................ruler......................................52.........................................................................53.........................................................................54.........................................................................55.........................................................................56.........................................................................57.........................................................................58.........................................................................59.........................................................................60
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_11 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_11
new file mode 100644
index 0000000000..503b734d21
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_11
@@ -0,0 +1,6 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8..........................................................................9..........................................................................10.........................................................................11
+12.........................................................................13.........................................................................14.........................................................................15.........................................................................16.........................................................................17.........................................................................18.........................................................................19.........................................................................20.........................................................................21.........................................................................22
+23.........................................................................24.........................................................................25.........................................................................26.........................................................................27.........................................................................28.........................................................................29.........................................................................30.........................................................................31.........................................................................32.........................................................................33
+34...........................winwidth(0): 75...............................35.........................................................................36.........................................................................37.........................................................................38.........................................................................39.........................................................................40.........................................................................41.........................................................................42.........................................................................43.........................................................................44
+45..........................winheight(0): 19...............................46.........................................................................47.........................................................................48.........................................................................49.........................................................................50.........................................................................51.........................................................................52.........................................................................53.........................................................................54.........................................................................55
+56..............................ruler......................................57.........................................................................58.........................................................................59.........................................................................60.........................................................................61.........................................................................62.........................................................................63.........................................................................64.........................................................................65.........................................................................66
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_12 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_12
new file mode 100644
index 0000000000..347feb223f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_12
@@ -0,0 +1,5 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8..........................................................................9..........................................................................10.........................................................................11.........................................................................12
+13.........................................................................14.........................................................................15.........................................................................16.........................................................................17.........................................................................18.........................................................................19.........................................................................20.........................................................................21.........................................................................22.........................................................................23.........................................................................24
+25...........................winwidth(0): 75...............................26.........................................................................27.........................................................................28.........................................................................29.........................................................................30.........................................................................31.........................................................................32.........................................................................33.........................................................................34.........................................................................35.........................................................................36
+37..........................winheight(0): 19...............................38.........................................................................39.........................................................................40.........................................................................41.........................................................................42.........................................................................43.........................................................................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48
+49..............................ruler......................................50.........................................................................51.........................................................................52.........................................................................53.........................................................................54.........................................................................55.........................................................................56.........................................................................57.........................................................................58.........................................................................59.........................................................................60
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_13 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_13
new file mode 100644
index 0000000000..b177614a16
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_13
@@ -0,0 +1,5 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8..........................................................................9..........................................................................10.........................................................................11.........................................................................12.........................................................................13
+14.........................................................................15.........................................................................16.........................................................................17.........................................................................18.........................................................................19.........................................................................20.........................................................................21.........................................................................22.........................................................................23.........................................................................24.........................................................................25.........................................................................26
+27...........................winwidth(0): 75...............................28.........................................................................29.........................................................................30.........................................................................31.........................................................................32.........................................................................33.........................................................................34.........................................................................35.........................................................................36.........................................................................37.........................................................................38.........................................................................39
+40..........................winheight(0): 19...............................41.........................................................................42.........................................................................43.........................................................................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48.........................................................................49.........................................................................50.........................................................................51.........................................................................52
+53..............................ruler......................................54.........................................................................55.........................................................................56.........................................................................57.........................................................................58.........................................................................59.........................................................................60.........................................................................61.........................................................................62.........................................................................63.........................................................................64.........................................................................65
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_14 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_14
new file mode 100644
index 0000000000..9a46c3e08f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_14
@@ -0,0 +1,5 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8..........................................................................9..........................................................................10.........................................................................11.........................................................................12.........................................................................13.........................................................................14
+15.........................................................................16.........................................................................17.........................................................................18.........................................................................19.........................................................................20.........................................................................21.........................................................................22.........................................................................23.........................................................................24.........................................................................25.........................................................................26.........................................................................27.........................................................................28
+29...........................winwidth(0): 75...............................30.........................................................................31.........................................................................32.........................................................................33.........................................................................34.........................................................................35.........................................................................36.........................................................................37.........................................................................38.........................................................................39.........................................................................40.........................................................................41.........................................................................42
+43..........................winheight(0): 19...............................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48.........................................................................49.........................................................................50.........................................................................51.........................................................................52.........................................................................53.........................................................................54.........................................................................55.........................................................................56
+57..............................ruler......................................58.........................................................................59.........................................................................60.........................................................................61.........................................................................62.........................................................................63.........................................................................64.........................................................................65.........................................................................66.........................................................................67.........................................................................68.........................................................................69.........................................................................70
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_15 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_15
new file mode 100644
index 0000000000..45fbef949f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_15
@@ -0,0 +1,4 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8..........................................................................9..........................................................................10.........................................................................11.........................................................................12.........................................................................13.........................................................................14.........................................................................15
+16...........................winwidth(0): 75...............................17.........................................................................18.........................................................................19.........................................................................20.........................................................................21.........................................................................22.........................................................................23.........................................................................24.........................................................................25.........................................................................26.........................................................................27.........................................................................28.........................................................................29.........................................................................30
+31..........................winheight(0): 19...............................32.........................................................................33.........................................................................34.........................................................................35.........................................................................36.........................................................................37.........................................................................38.........................................................................39.........................................................................40.........................................................................41.........................................................................42.........................................................................43.........................................................................44.........................................................................45
+46..............................ruler......................................47.........................................................................48.........................................................................49.........................................................................50.........................................................................51.........................................................................52.........................................................................53.........................................................................54.........................................................................55.........................................................................56.........................................................................57.........................................................................58.........................................................................59.........................................................................60
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_16 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_16
new file mode 100644
index 0000000000..1af3caa605
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_16
@@ -0,0 +1,4 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8..........................................................................9..........................................................................10.........................................................................11.........................................................................12.........................................................................13.........................................................................14.........................................................................15.........................................................................16
+17...........................winwidth(0): 75...............................18.........................................................................19.........................................................................20.........................................................................21.........................................................................22.........................................................................23.........................................................................24.........................................................................25.........................................................................26.........................................................................27.........................................................................28.........................................................................29.........................................................................30.........................................................................31.........................................................................32
+33..........................winheight(0): 19...............................34.........................................................................35.........................................................................36.........................................................................37.........................................................................38.........................................................................39.........................................................................40.........................................................................41.........................................................................42.........................................................................43.........................................................................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48
+49..............................ruler......................................50.........................................................................51.........................................................................52.........................................................................53.........................................................................54.........................................................................55.........................................................................56.........................................................................57.........................................................................58.........................................................................59.........................................................................60.........................................................................61.........................................................................62.........................................................................63.........................................................................64
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_17 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_17
new file mode 100644
index 0000000000..6dc5050846
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_17
@@ -0,0 +1,4 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8..........................................................................9..........................................................................10.........................................................................11.........................................................................12.........................................................................13.........................................................................14.........................................................................15.........................................................................16.........................................................................17
+18...........................winwidth(0): 75...............................19.........................................................................20.........................................................................21.........................................................................22.........................................................................23.........................................................................24.........................................................................25.........................................................................26.........................................................................27.........................................................................28.........................................................................29.........................................................................30.........................................................................31.........................................................................32.........................................................................33.........................................................................34
+35..........................winheight(0): 19...............................36.........................................................................37.........................................................................38.........................................................................39.........................................................................40.........................................................................41.........................................................................42.........................................................................43.........................................................................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48.........................................................................49.........................................................................50.........................................................................51
+52...............................ruler.....................................53.........................................................................54.........................................................................55.........................................................................56.........................................................................57.........................................................................58.........................................................................59.........................................................................60.........................................................................61.........................................................................62.........................................................................63.........................................................................64.........................................................................65.........................................................................66.........................................................................67.........................................................................68
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_18 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_18
new file mode 100644
index 0000000000..f84a827a7d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_18
@@ -0,0 +1,4 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8..........................................................................9..........................................................................10.........................................................................11.........................................................................12.........................................................................13.........................................................................14.........................................................................15.........................................................................16.........................................................................17.........................................................................18
+19...........................winwidth(0): 75...............................20.........................................................................21.........................................................................22.........................................................................23.........................................................................24.........................................................................25.........................................................................26.........................................................................27.........................................................................28.........................................................................29.........................................................................30.........................................................................31.........................................................................32.........................................................................33.........................................................................34.........................................................................35.........................................................................36
+37..........................winheight(0): 19...............................38.........................................................................39.........................................................................40.........................................................................41.........................................................................42.........................................................................43.........................................................................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48.........................................................................49.........................................................................50.........................................................................51.........................................................................52.........................................................................53.........................................................................54
+55...............................ruler.....................................56.........................................................................57.........................................................................58.........................................................................59.........................................................................60.........................................................................61.........................................................................62.........................................................................63.........................................................................64.........................................................................65.........................................................................66.........................................................................67.........................................................................68.........................................................................69.........................................................................70.........................................................................71.........................................................................72
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_19 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_19
new file mode 100644
index 0000000000..9f0ad00d1a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_19
@@ -0,0 +1,4 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5..........................................................................6..........................................................................7..........................................................................8..........................................................................9..........................................................................10.........................................................................11.........................................................................12.........................................................................13.........................................................................14.........................................................................15.........................................................................16.........................................................................17.........................................................................18.........................................................................19
+20...........................winwidth(0): 75...............................21.........................................................................22.........................................................................23.........................................................................24.........................................................................25.........................................................................26.........................................................................27.........................................................................28.........................................................................29.........................................................................30.........................................................................31.........................................................................32.........................................................................33.........................................................................34.........................................................................35.........................................................................36.........................................................................37.........................................................................38
+39..........................winheight(0): 19...............................40.........................................................................41.........................................................................42.........................................................................43.........................................................................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48.........................................................................49.........................................................................50.........................................................................51.........................................................................52.........................................................................53.........................................................................54.........................................................................55.........................................................................56.........................................................................57
+58...............................ruler.....................................59.........................................................................60.........................................................................61.........................................................................62.........................................................................63.........................................................................64.........................................................................65.........................................................................66.........................................................................67.........................................................................68.........................................................................69.........................................................................70.........................................................................71.........................................................................72.........................................................................73.........................................................................74.........................................................................75.........................................................................76
diff --git a/mnv/runtime/syntax/testdir/input/selftestdir/dots_20 b/mnv/runtime/syntax/testdir/input/selftestdir/dots_20
new file mode 100644
index 0000000000..ca3a93d252
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/selftestdir/dots_20
@@ -0,0 +1,2 @@
+1..........................................................................2..........................................................................3..........................................................................4..........................................................................5.............................winwidth(0): 75..............................6............................winheight(0): 19..............................7................................ruler.....................................8..........................................................................9..........................................................................10.........................................................................11.........................................................................12.........................................................................13.........................................................................14.........................................................................15.........................................................................16.........................................................................17.........................................................................18.........................................................................19.........................................................................20.........................................................................21.........................................................................22.........................................................................23.........................................................................24.........................................................................25.........................................................................26.........................................................................27.........................................................................28.........................................................................29.........................................................................30.........................................................................31.........................................................................32.........................................................................33.........................................................................34.........................................................................35.........................................................................36.........................................................................37.........................................................................38
+39.........................................................................40.........................................................................41.........................................................................42.........................................................................43.........................................................................44.........................................................................45.........................................................................46.........................................................................47.........................................................................48.........................................................................49.........................................................................50.........................................................................51.........................................................................52.........................................................................53.........................................................................54.........................................................................55.........................................................................56.........................................................................57.........................................................................58.........................................................................59.........................................................................60.........................................................................61.........................................................................62.........................................................................63.........................................................................64.........................................................................65.........................................................................66.........................................................................67.........................................................................68.........................................................................69.........................................................................70.........................................................................71.........................................................................72.........................................................................73.........................................................................74.........................................................................75.........................................................................76
diff --git a/mnv/runtime/syntax/testdir/input/setup/help.mnv b/mnv/runtime/syntax/testdir/input/setup/help.mnv
new file mode 100644
index 0000000000..038175adaa
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/help.mnv
@@ -0,0 +1 @@
+set conceallevel=2
diff --git a/mnv/runtime/syntax/testdir/input/setup/help_ex_version.mnv b/mnv/runtime/syntax/testdir/input/setup/help_ex_version.mnv
new file mode 100644
index 0000000000..22953b8c45
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/help_ex_version.mnv
@@ -0,0 +1 @@
+set conceallevel=2 concealcursor=nc
diff --git a/mnv/runtime/syntax/testdir/input/setup/html_fold_expr.mnv b/mnv/runtime/syntax/testdir/input/setup/html_fold_expr.mnv
new file mode 100644
index 0000000000..e8daae0e74
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/html_fold_expr.mnv
@@ -0,0 +1,2 @@
+let g:html_expr_folding = 1
+filetype plugin on
diff --git a/mnv/runtime/syntax/testdir/input/setup/java_module_info.mnv b/mnv/runtime/syntax/testdir/input/setup/java_module_info.mnv
new file mode 100644
index 0000000000..6d3d634a4d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/java_module_info.mnv
@@ -0,0 +1,30 @@
+mnv9script
+
+# Test filenames are required to begin with the filetype name prefix,
+# whereas the name of a Java module declaration must be "module-info".
+const name_a: string = 'input/java_module_info.java'
+const name_b: string = 'input/module-info.java'
+
+def ChangeFilename()
+ exec 'saveas! ' .. name_b
+enddef
+
+def RestoreFilename()
+ exec 'saveas! ' .. name_a
+ delete(name_b)
+enddef
+
+autocmd_add([{
+ replace: true,
+ group: 'java_syntax_tests',
+ event: 'BufEnter',
+ pattern: name_a,
+ cmd: 'ChangeFilename()',
+ once: true,
+}, {
+ group: 'java_syntax_tests',
+ event: ['BufLeave', 'ExitPre'],
+ pattern: name_b,
+ cmd: 'RestoreFilename()',
+ once: true,
+}])
diff --git a/mnv/runtime/syntax/testdir/input/setup/markdown_circularity.mnv b/mnv/runtime/syntax/testdir/input/setup/markdown_circularity.mnv
new file mode 100644
index 0000000000..a0b2d985a3
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/markdown_circularity.mnv
@@ -0,0 +1,4 @@
+unlet! g:java_ignore_javadoc g:java_ignore_markdown
+let g:java_highlight_debug = 1
+let g:java_highlight_java_lang = 1
+let g:markdown_fenced_languages = ['html', 'java']
diff --git a/mnv/runtime/syntax/testdir/input/setup/markdown_conceal.mnv b/mnv/runtime/syntax/testdir/input/setup/markdown_conceal.mnv
new file mode 100644
index 0000000000..a1585b18bb
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/markdown_conceal.mnv
@@ -0,0 +1,8 @@
+if has('conceal')
+ let g:markdown_syntax_conceal = 1
+ setlocal conceallevel=3 concealcursor=n
+endif
+
+let g:markdown_fenced_languages = ['html']
+highlight link markdownBold Todo
+highlight link htmlBold Todo
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_blocks.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_blocks.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_blocks.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_builtin_object_methods2.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_builtin_object_methods2.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_builtin_object_methods2.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_comments.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_comments.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_comments.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_def_variables.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_def_variables.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_def_variables.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_class_fold.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_class_fold.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_class_fold.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_commands.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_commands.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_commands.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_enum.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_enum.mnv
new file mode 100644
index 0000000000..531177ca35
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_enum.mnv
@@ -0,0 +1 @@
+hi link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_enum2.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_enum2.mnv
new file mode 100644
index 0000000000..531177ca35
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_enum2.mnv
@@ -0,0 +1 @@
+hi link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_for.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_for.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_for.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_function_def_tail_comment_errors.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_function_def_tail_comment_errors.mnv
new file mode 100644
index 0000000000..9029f40087
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_function_def_tail_comment_errors.mnv
@@ -0,0 +1,2 @@
+highlight link mnvVar Identifier
+highlight link mnvFunctionScope Special
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_function_def_tail_comments.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_function_def_tail_comments.mnv
new file mode 100644
index 0000000000..9029f40087
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_function_def_tail_comments.mnv
@@ -0,0 +1,2 @@
+highlight link mnvVar Identifier
+highlight link mnvFunctionScope Special
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_import.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_import.mnv
new file mode 100644
index 0000000000..531177ca35
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_import.mnv
@@ -0,0 +1 @@
+hi link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_interface_fold.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_interface_fold.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_interface_fold.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_let_heredoc.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_let_heredoc.mnv
new file mode 100644
index 0000000000..e6aa760ca5
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_let_heredoc.mnv
@@ -0,0 +1,2 @@
+highlight link mnvVar Identifier
+
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_loadkeymap.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_loadkeymap.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_ex_loadkeymap.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_expressions.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_expressions.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_expressions.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_lambdas.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_lambdas.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_lambdas.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_legacy_header.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_legacy_header.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_legacy_header.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords2.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords2.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords2.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords3.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords3.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_super_this_keywords3.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv9_variables.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv9_variables.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv9_variables.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_comments.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_comments.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_comments.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_call.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_call.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_call.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_command.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_command.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_command.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_commands.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_commands.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_commands.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def.mnv
new file mode 100644
index 0000000000..9029f40087
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def.mnv
@@ -0,0 +1,2 @@
+highlight link mnvVar Identifier
+highlight link mnvFunctionScope Special
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_fold.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_fold.mnv
new file mode 100644
index 0000000000..9029f40087
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_fold.mnv
@@ -0,0 +1,2 @@
+highlight link mnvVar Identifier
+highlight link mnvFunctionScope Special
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_nested.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_nested.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_nested.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_nested_fold.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_nested_fold.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_def_nested_fold.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_echo.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_echo.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_echo.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_execute.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_execute.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_execute.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_for.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_for.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_for.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function.mnv
new file mode 100644
index 0000000000..9029f40087
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function.mnv
@@ -0,0 +1,2 @@
+highlight link mnvVar Identifier
+highlight link mnvFunctionScope Special
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_def_tail_comment_errors.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_def_tail_comment_errors.mnv
new file mode 100644
index 0000000000..9029f40087
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_def_tail_comment_errors.mnv
@@ -0,0 +1,2 @@
+highlight link mnvVar Identifier
+highlight link mnvFunctionScope Special
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_def_tail_comments.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_def_tail_comments.mnv
new file mode 100644
index 0000000000..9029f40087
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_def_tail_comments.mnv
@@ -0,0 +1,2 @@
+highlight link mnvVar Identifier
+highlight link mnvFunctionScope Special
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_fold.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_fold.mnv
new file mode 100644
index 0000000000..9029f40087
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_function_fold.mnv
@@ -0,0 +1,2 @@
+highlight link mnvVar Identifier
+highlight link mnvFunctionScope Special
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_import.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_import.mnv
new file mode 100644
index 0000000000..531177ca35
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_import.mnv
@@ -0,0 +1 @@
+hi link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_let_heredoc.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_let_heredoc.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_let_heredoc.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap_after_bar.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap_after_bar.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap_after_bar.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap_after_colon.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap_after_colon.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_loadkeymap_after_colon.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_map.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_map.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_map.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_match.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_match.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_match.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_menu.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_menu.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_menu.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_redir.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_redir.mnv
new file mode 100644
index 0000000000..7d027095ca
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_redir.mnv
@@ -0,0 +1,2 @@
+highlight link mnvVar Identifier
+highlight link mnvRedirFile String
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_substitute.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_substitute.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_substitute.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_ex_syntax.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_syntax.mnv
new file mode 100644
index 0000000000..9029f40087
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_ex_syntax.mnv
@@ -0,0 +1,2 @@
+highlight link mnvVar Identifier
+highlight link mnvFunctionScope Special
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_expressions.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_expressions.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_expressions.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_function_variables.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_function_variables.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_function_variables.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_lambdas.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_lambdas.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_lambdas.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_line_continuation.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_line_continuation.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_line_continuation.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/setup/mnv_variables.mnv b/mnv/runtime/syntax/testdir/input/setup/mnv_variables.mnv
new file mode 100644
index 0000000000..153907d0c6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/setup/mnv_variables.mnv
@@ -0,0 +1 @@
+highlight link mnvVar Identifier
diff --git a/mnv/runtime/syntax/testdir/input/sh_01.sh b/mnv/runtime/syntax/testdir/input/sh_01.sh
new file mode 100644
index 0000000000..bd27c99bde
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_01.sh
@@ -0,0 +1,4 @@
+#! /bin/dash
+export `echo 'A=B'`
+printenv A
+echo a `#foo` b
diff --git a/mnv/runtime/syntax/testdir/input/sh_02.sh b/mnv/runtime/syntax/testdir/input/sh_02.sh
new file mode 100644
index 0000000000..81d5613e1d
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_02.sh
@@ -0,0 +1,30 @@
+#! /bin/ksh
+# sh2
+# Jul 28, 2018: introduced shCommandSubBQ, which is *not* included in a shSubCommandList (so its not recursive)
+ccc=`echo "test"`
+ ccc=`echo "test"`
+
+# comment
+case $VAR in
+# comment
+ x|y|z) echo xyz ;;
+# comment
+ a|b|c) echo abc ;;
+# comment
+esac
+
+# Jul 26, 2018: why isn't `..` being terminated properly?
+# comment
+case "$aaa" in
+# comment
+ bbb) ccc=`echo $ddd|cut -b4-`
+ echo "test"
+# comment
+ ;;
+# comment
+ esac
+# comment
+
+echo $VAR abc
+export $VAR abc
+set $VAR abc
diff --git a/mnv/runtime/syntax/testdir/input/sh_03.sh b/mnv/runtime/syntax/testdir/input/sh_03.sh
new file mode 100644
index 0000000000..8dd6dab9c3
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_03.sh
@@ -0,0 +1,33 @@
+#!/bin/ksh
+# Test variable modifiers
+# Variable=value
+Variable='value'
+Variable="value"
+VariableA="pat1xxpat2"
+VariableB="pat2xxpat1"
+echo ${#}
+echo ${#VariableA}
+echo ${VariableA#pat1}
+echo ${VariableA##pat1}
+echo ${VariableB%pat1}
+echo ${VariableB%%pat1}
+
+# This gets marked as an error
+Variable=${VariableB:+${VariableC:=eng}} # :+ seems to work for ksh as well as bash
+Variable=${VariableB:-${VariableC:-eng}} # :- is ksh and bash
+
+# This is OK
+Variable='${VariableB:+${VariableC:=eng}}'
+Variable='${VariableB:-${VariableC:-eng}}'
+Variable="${VariableB:+${VariableC:=eng}}" # :+ seems to work for ksh as well as bash
+Variable="${VariableB:-${VariableC:-eng}}" # :- is ksh and bash
+
+# These are OK
+: ${VariableB:-${VariableC:-eng}}
+: "${VariableB:-${VariableC:-eng}}"
+: '${VariableB:-${VariableC:-eng}}'
+
+# Another test
+Variable=${VariableB:-${VariableC:-${VariableD:-${VariableE:=eng}}}}
+ : ${VariableB:=${VariableC:-${VariableD:-${VariableE:=eng}}}}
+
diff --git a/mnv/runtime/syntax/testdir/input/sh_04.sh b/mnv/runtime/syntax/testdir/input/sh_04.sh
new file mode 100644
index 0000000000..150379060c
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_04.sh
@@ -0,0 +1,22 @@
+#!/bin/dash
+# sh4
+Variable=${VariableB:-{VariableC}}
+Variable=${VariableB:-${VariableC:-{Var3:=eng}}}
+
+# This gets marked as an error while its ok
+Variable=${VariableB:-${VariableC:-{Var3:=eng}}}
+Variable=${VariableB:=${VariableC:={Var3:=${Var4:-eng}}}}
+Variable=${VariableB:=${VariableC:={Var3:=${Var4:-${Var5:-eng}}}}}
+Variable=${VariableB:=${VariableC:={Var3:=${Var4:-${Var5:-$Var6}}}}}
+
+# These are OK
+Variable="${VariableB:-${VariableC:-{Var3:=eng}}}"
+Variable="${VariableB:=${VariableC:={Var3:=${Var4:-eng}}}}"
+
+# This gets marked as an error too
+: ${VariableB:-${VariableC:-{Var3:=eng}}}
+: ${VariableB:=${VariableC:={Var3:=${Var4:-eng}}}}
+
+# This is OK
+: ${VariableB:-${VariableC:-eng}}
+: "${VariableB:-${VariableC:-eng}}"
diff --git a/mnv/runtime/syntax/testdir/input/sh_05.sh b/mnv/runtime/syntax/testdir/input/sh_05.sh
new file mode 100644
index 0000000000..87381e12ea
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_05.sh
@@ -0,0 +1,373 @@
+#!/bin/dash -x
+# sh5
+# Note that this is special for sh. ksh will be an extra file later.
+# Note too, that sh and ksh allow ${var:-sub} as well as ${var-sub}!
+# The ':' is optional!
+
+# This all should be OK
+# Case 0a
+[ -t 0 ] && date
+Variable1=value1
+Variable2='value2'
+Variable3="value3"
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 0b
+[ -t 0 ] && echo "\ndate"
+Variable1=$HOME
+Variable2='$HOME'
+Variable3="$HOME"
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 0c
+[ -t 0 ] && echo "\ndate"
+Variable1=$HOME$SHELL
+Variable2=$HOME.$SHELL
+Variable3=$HOME.$SHELL+$HOME-$SHELL/$HOME
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 0d
+[ -t 0 ] && echo "\ndate"
+Variable1=`date`
+Variable2=`id -ng`
+Variable3=`id -ng | wc -c`
+echo "$Variable1" "$Variable2" "$Variable3"
+
+################################################################################
+#
+# Case 1a with constants
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:=eng1}
+Variable2=${VariableA:-eng2}
+Variable3=${VariableA:?eng3}
+Variable3=${VariableA:+eng3}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 1b with constants in single quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:='eng1'}
+Variable2=${VariableA:-'eng2'}
+Variable3=${VariableA:?'eng3'}
+Variable3=${VariableA:+'eng3'}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 1c with constants in double quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:="eng1"}
+Variable2=${VariableA:-"eng2"}
+Variable3=${VariableA:?"eng3"}
+Variable3=${VariableA:+"eng3"}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 1d: constants but missing colons
+Variable1=${VariableA=eng1}
+Variable2=${VariableA-eng2}
+Variable3=${VariableA?eng3}
+Variable3=${VariableA+eng3}
+Variable1=${VariableA='eng1'}
+Variable2=${VariableA-'eng2'}
+Variable3=${VariableA?'eng3'}
+Variable3=${VariableA+'eng3'}
+Variable1=${VariableA="eng1"}
+Variable2=${VariableA-"eng2"}
+Variable3=${VariableA?"eng3"}
+Variable3=${VariableA+"eng3"}
+
+# Case 2a with a variable
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:=$HOME}
+Variable2=${VariableA:-$HOME}
+Variable3=${VariableA:?$HOME}
+Variable3=${VariableA:+$HOME}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 2b with a variable in single quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:='$HOME'}
+Variable2=${VariableA:-'$HOME'}
+Variable3=${VariableA:?'$HOME'}
+Variable3=${VariableA:+'$HOME'}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 2c with a variable in double quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:="$HOME"}
+Variable2=${VariableA:-"$HOME"}
+Variable3=${VariableA:?"$HOME"}
+Variable3=${VariableA:+"$HOME"}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3a with a command substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:=`date`}
+Variable2=${VariableA:-`date`}
+Variable3=${VariableA:?`date`}
+Variable3=${VariableA:+`date`}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3b with a command + option substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:=`id -ng`}
+Variable2=${VariableA:-`id -ng`}
+Variable3=${VariableA:?`id -ng`}
+Variable3=${VariableA:+`id -ng`}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3c with a command + pipe substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:=`id -ng | wc -c`}
+Variable2=${VariableA:-`id -ng | wc -c`}
+Variable3=${VariableA:?`id -ng | wc -c`}
+Variable3=${VariableA:+`id -ng | wc -c`}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+################################################################################
+#
+# The same with one nestet ${} level
+# Case 1a with constants
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:=eng1}}
+Variable2=${VariableA:-${VarB:-eng2}}
+Variable3=${VariableA:-${VarB:?eng3}}
+Variable3=${VariableA:-${VarB:+eng3}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 1b with constants in single quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:='eng1'}}
+Variable2=${VariableA:-${VarB:-'eng2'}}
+Variable3=${VariableA:-${VarB:?'eng3'}}
+Variable3=${VariableA:-${VarB:+'eng3'}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 1c with constants in double quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:="eng1"}}
+Variable2=${VariableA:-${VarB:-"eng2"}}
+Variable3=${VariableA:-${VarB:?"eng3"}}
+Variable3=${VariableA:-${VarB:+"eng3"}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 2a with a variable
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:=$HOME}}
+Variable2=${VariableA:-${VarB:-$HOME}}
+Variable3=${VariableA:-${VarB:?$HOME}}
+Variable3=${VariableA:-${VarB:+$HOME}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 2b with a variable in single quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:='$HOME'}}
+Variable2=${VariableA:-${VarB:-'$HOME'}}
+Variable3=${VariableA:-${VarB:?'$HOME'}}
+Variable3=${VariableA:-${VarB:+'$HOME'}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 2c with a variable in double quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:="$HOME"}}
+Variable2=${VariableA:-${VarB:-"$HOME"}}
+Variable3=${VariableA:-${VarB:?"$HOME"}}
+Variable3=${VariableA:-${VarB:+"$HOME"}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3a with a command substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:=`date`}}
+Variable2=${VariableA:-${VarB:-`date`}}
+Variable3=${VariableA:-${VarB:?`date`}}
+Variable3=${VariableA:-${VarB:+`date`}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3b with a command + option substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:=`id -ng`}}
+Variable2=${VariableA:-${VarB:-`id -ng`}}
+Variable3=${VariableA:-${VarB:?`id -ng`}}
+Variable3=${VariableA:-${VarB:+`id -ng`}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3c with a command + pipe substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:=`id -ng | wc -c`}}
+Variable2=${VariableA:-${VarB:-`id -ng | wc -c`}}
+Variable3=${VariableA:-${VarB:?`id -ng | wc -c`}}
+Variable3=${VariableA:-${VarB:+`id -ng | wc -c`}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+################################################################################
+#
+# The same with two nestet ${} level
+# Case 1a with constants
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:=eng1}}}
+Variable2=${VariableA:-${VarB:-${VarC:-eng2}}}
+Variable3=${VariableA:-${VarB:-${VarC:?eng3}}}
+Variable3=${VariableA:-${VarB:-${VarC:+eng3}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 1b with constants in single quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:='eng1'}}}
+Variable2=${VariableA:-${VarB:-${VarC:-'eng2'}}}
+Variable3=${VariableA:-${VarB:-${VarC:?'eng3'}}}
+Variable3=${VariableA:-${VarB:-${VarC:+'eng3'}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 1c with constants in double quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:="eng1"}}}
+Variable2=${VariableA:-${VarB:-${VarC:-"eng2"}}}
+Variable3=${VariableA:-${VarB:-${VarC:?"eng3"}}}
+Variable3=${VariableA:-${VarB:-${VarC:+"eng3"}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 2a with a variable
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:=$HOME}}}
+Variable2=${VariableA:-${VarB:-${VarC:-$HOME}}}
+Variable3=${VariableA:-${VarB:-${VarC:?$HOME}}}
+Variable3=${VariableA:-${VarB:-${VarC:+$HOME}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 2b with a variable in single quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:='$HOME'}}}
+Variable2=${VariableA:-${VarB:-${VarC:-'$HOME'}}}
+Variable3=${VariableA:-${VarB:-${VarC:?'$HOME'}}}
+Variable3=${VariableA:-${VarB:-${VarC:+'$HOME'}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 2c with a variable in double quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:="$HOME"}}}
+Variable2=${VariableA:-${VarB:-${VarC:-"$HOME"}}}
+Variable3=${VariableA:-${VarB:-${VarC:?"$HOME"}}}
+Variable3=${VariableA:-${VarB:-${VarC:?"$HOME"}}}
+Variable3=${VariableA:-${VarB:-${VarC:+"$HOME"}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3a with a command substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:=`date`}}}
+Variable2=${VariableA:-${VarB:-${VarC:-`date`}}}
+Variable3=${VariableA:-${VarB:-${VarC:?`date`}}}
+Variable3=${VariableA:-${VarB:-${VarC:+`date`}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3b with a command + option substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:=`id -ng`}}}
+Variable2=${VariableA:-${VarB:-${VarC:-`id -ng`}}}
+Variable3=${VariableA:-${VarB:-${VarC:?`id -ng`}}}
+Variable3=${VariableA:-${VarB:-${VarC:+`id -ng`}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3c with a command + pipe substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:=`id -ng | wc -c`}}}
+Variable2=${VariableA:-${VarB:-${VarC:-`id -ng | wc -c`}}}
+Variable3=${VariableA:-${VarB:-${VarC:?`id -ng | wc -c`}}}
+Variable3=${VariableA:-${VarB:-${VarC:+`id -ng | wc -c`}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+
+################################################################################
+#
+# The same with three nestet ${} level
+# Case 1a with constants
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:-${VarD:=eng1}}}}
+Variable2=${VariableA:-${VarB:-${VarC:-${VarD:-eng2}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:?eng3}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:+eng3}}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 1b with constants in single quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:-${VarD:='eng1'}}}}
+Variable2=${VariableA:-${VarB:-${VarC:-${VarD:-'eng2'}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:?'eng3'}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:+'eng3'}}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 1c with constants in double quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:-${VarD:="eng1"}}}}
+Variable2=${VariableA:-${VarB:-${VarC:-${VarD:-"eng2"}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:?"eng3"}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:+"eng3"}}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 2a with a variable
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:-${VarD:=$HOME}}}}
+Variable2=${VariableA:-${VarB:-${VarC:-${VarD:-$HOME}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:?$HOME}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:+$HOME}}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 2b with a variable in single quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:-${VarD:='$HOME'}}}}
+Variable2=${VariableA:-${VarB:-${VarC:-${VarD:-'$HOME'}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:?'$HOME'}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:+'$HOME'}}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 2c with a variable in double quotes
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:-${VarD:="$HOME"}}}}
+Variable2=${VariableA:-${VarB:-${VarC:-${VarD:-"$HOME"}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:?"$HOME"}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:+"$HOME"}}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3a with a command substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:-${VarD:=`date`}}}}
+Variable2=${VariableA:-${VarB:-${VarC:-${VarD:-`date`}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:?`date`}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:+`date`}}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3b with a command + option substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:-${VarD:=`id -ng`}}}}
+Variable2=${VariableA:-${VarB:-${VarC:-${VarD:-`id -ng`}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:?`id -ng`}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:+`id -ng`}}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+# Case 3c with a command + pipe substitution
+[ -t 0 ] && echo "\ndate"
+Variable1=${VariableA:-${VarB:-${VarC:-${VarD:=`id -ng | wc -c`}}}}
+Variable2=${VariableA:-${VarB:-${VarC:-${VarD:-`id -ng | wc -c`}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:?`id -ng | wc -c`}}}}
+Variable3=${VariableA:-${VarB:-${VarC:-${VarD:+`id -ng | wc -c`}}}}
+echo "$Variable1" "$Variable2" "$Variable3"
+
+
+################################################################################
+#
+# This is also allowed:
+Variable1=${VariableA-${VarB-${VarC-${VarD=`id -ng | wc -c`}}}}
+
+################################################################################
+#
+# All cases with ${Var:?} which works for the sh:
+Variable4=${Variable4:?}
+Variable4=${Variable4:?OK}
+Variable4=${Variable4:?`date`}
+Variable4=${Variable4:?'an OK string'}
+Variable4=${Variable4:?"an OK string"}
+Variable4=${Variable4:?$HOME$SHELL}
+Variable4=${Variable4:?$HOME:$SHELL}
+
+# All cases with ${Var:?} which works also for ksh:
+Variable4=${Variable4:?This is OK}
+Variable4=${Variable4:?This is OK, too: `date`}
+
+# What happens with ${#identifier[*]}:
+Variable5=${#identifier[*]}
diff --git a/mnv/runtime/syntax/testdir/input/sh_06.sh b/mnv/runtime/syntax/testdir/input/sh_06.sh
new file mode 100644
index 0000000000..cec6cc30af
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_06.sh
@@ -0,0 +1,71 @@
+#!/bin/ksh
+# Shall we debug this script? If so, remove the '#' before '#DebugScript=set'
+DebugScript=set
+
+# Show that we are busy.
+[ -t 0 ] && echo "Please wait ... \c" >`tty`
+
+################################################################################
+#
+# Display some Help
+#
+Usage () {
+
+# does this comment work?
+VariableName="${BasicConfigName}_*"
+
+# Echo some ksh special variables
+echo "CDPATH="${CDPATH}
+
+# Get also a short description of the backuptype/method
+eval BackupMethod=\$mess09${BackupType}B
+
+case $BackupType in
+ 3) DefaultDevice=$MountDevice ;;
+ 1|2) DefaultDevice=$TapeDrive ;;
+esac
+
+# If we have more the 53 characters in the variables below split them up
+# into several lines and add 3 tabs before them
+for Variable in DefaultExclude DefaultFindOption DoNotBackupList
+do
+ eval VarValue=\$$Variable
+ VarValue=`echo $VarValue | FoldS 53 | sed "2,\\$s/^/$Tab$Tab$Tab/"`
+ eval $Variable=\$VarValue
+done
+
+echo "
+Usage: $ScriptName [-Options]
+
+Options List:
+ -v The current version of '$ScriptName'
+ -h | -H | ? Display this list
+
+"
+
+} # End of Usage
+
+
+################################################################################
+#
+# Create a backup using fbackup/frecover
+#
+ExecuteFbackup () { # TESTING
+
+[ "$DebugScript" ] && set -x || set +x
+
+cd $cwd
+
+} # End of ExecuteFbackup
+
+
+################################################################################
+# main ### main ### main ### main ### main ### main ### main ### main ### main #
+################################################################################
+#
+# Here is the heart of this script:
+#
+Usage
+
+# And exit
+Exit $Result
diff --git a/mnv/runtime/syntax/testdir/input/sh_07.sh b/mnv/runtime/syntax/testdir/input/sh_07.sh
new file mode 100644
index 0000000000..23219a0cdb
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_07.sh
@@ -0,0 +1,93 @@
+#!/bin/dash
+# Test file to test 'for do done' loops.
+# You can start this script like: $0 {-ne -gt -le ...} (all numeric operators
+# are allowed!
+
+# All this works and should be OK
+
+################################################################################
+#
+# For loop without 'in list'. Uses $1 $2 ... This is a special case!
+# This 'for Var, do, done' is a very handy solution AND no real replacement
+# available!
+#
+Function1 () {
+
+echo "Function1: for loop inside a function:\t\c"
+[ "$*" ] || echo "none\c"
+
+for Var
+do
+ [ 1 $Var 2 ] && echo "OK \c" || echo "no \c"
+done
+echo
+
+} # End of Function1
+
+################################################################################
+#
+# For loop with 'in list' $*
+#
+Function2 () {
+
+echo "Function2: for loop inside a function:\t\c"
+for Var in $*
+do
+ [ 1 $Var 2 ] && echo "OK \c" || echo "no \c"
+done ; echo
+
+} # End of Function2
+
+################################################################################
+#
+# For loop with 'in list' $@. Works the same way as $*
+#
+Function3 () {
+
+echo "Function3: for loop inside a function:\t\c"
+for Var in $@
+do
+ [ 1 $Var 2 ] && echo "OK \c" || echo "no \c"
+done ; echo
+
+} # End of Function3
+
+################################################################################
+#
+# For loop with 'in list' "$@". Special case. Works like "$1" "$2" ...
+#
+Function4 () {
+
+echo "Function4: for loop inside a function:\t\c"
+for Var in "$@"
+do
+ [ 1 $Var 2 ] && echo "OK \c" || echo "no \c"
+done ; echo
+
+} # End of Function4
+
+
+################################################################################
+# main ### main ### main ### main ### main ### main ### main ### main ### main #
+################################################################################
+#
+# Here is the heart of this script:
+#
+echo "Processing the following command line arguments: ${*:-none}"
+echo "Script: for loop outside a function:\t\c"
+for Var
+do
+ [ 1 $Var 2 ] && echo "OK \c" || echo "no \c"
+done ; echo
+
+# Same as function calls
+Function1 -eq -ne -gt -ge -le -lt
+Function2 -eq -ne -gt -ge -le -lt
+Function3 -eq -ne -gt -ge -le -lt
+Function4 -eq -ne -gt -ge -le -lt '-ge 1 -a 2 -ge'
+
+# Now the same call like Function4 but with Function1
+Function1 -eq -ne -gt -ge -le -lt '-ge 1 -a 2 -ge'
+Function1
+
+exit $?
diff --git a/mnv/runtime/syntax/testdir/input/sh_08.sh b/mnv/runtime/syntax/testdir/input/sh_08.sh
new file mode 100644
index 0000000000..2b80d43ba6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_08.sh
@@ -0,0 +1,82 @@
+#!/bin/ksh -p
+
+# Note that this is special test file for ksh. sh is an extra file.
+# Note too, that this file contains ONLY things which works for ksh BUT NOT
+# for sh
+
+# This all should be OK
+
+# Several keywords without any quotes!
+# Case 1a. Several Constants
+[ -t 0 ] && date
+Variable1=${VariableA:-This is a Text}
+Variable2=${VariableA:=This is a Text}
+Variable3=${VariableA:?This is a Text}
+echo "$Variable1" ; echo "$Variable2" ; echo "$Variable3"
+
+# Case 1b. Variable and Constant
+[ -t 0 ] && echo "\n`date`" && unset VariableA
+Variable1=${VariableA:-$HOME This is a Text}
+Variable2=${VariableA:=$HOME This is a Text}
+Variable3=${VariableA:?$HOME This is a Text}
+echo "$Variable1" ; echo "$Variable2" ; echo "$Variable3"
+
+# Case 1c. Constant and Variable
+[ -t 0 ] && echo "\n`date`" && unset VariableA
+Variable1=${VariableA:-This is a Text in $HOME}
+Variable2=${VariableA:=This is a Text in $HOME}
+Variable3=${VariableA:+This is a Text in $HOME} #! :+ is bash-only, error here expected
+Variable1=${VariableA:-This is a Text in $HOME too}
+Variable2=${VariableA:=This is a Text in $HOME too}
+Variable3=${VariableA:+This is a Text in $HOME too}
+echo "$Variable1" ; echo "$Variable2" ; echo "$Variable3"
+
+# Case 1d. More Variables and Constants. Starting with a Variable.
+[ -t 0 ] && echo "\n`date`" && unset VariableA
+Variable1=${VariableA:-$SHELL}
+Variable1=${VariableA:-$SHELL This is a Text in $HOME}
+Variable2=${VariableA:=$SHELL This is a Text in $HOME}
+Variable3=${VariableA:+$SHELL This is a Text in $HOME}
+echo "$Variable1" ; echo "$Variable2" ; echo "$Variable3"
+
+# Case 1e. More Constants and Variables. Starting with a Constant.
+[ -t 0 ] && echo "\n`date`" && unset VariableA
+Variable1=${VariableA:-"This is a Text in $HOME $SHELL"}
+Variable1=${VariableA:-This is a Text in $HOME $SHELL}
+Variable2=${VariableA:=This is a Text in $HOME $SHELL}
+Variable3=${VariableA:+This is a Text in $HOME $SHELL}
+echo "$Variable1" ; echo "$Variable2" ; echo "$Variable3"
+
+# Case 1x. The same with ':'
+[ -t 0 ] && echo "\n`date`" && unset VariableA
+: ${VariableA:-This is a Text}
+: ${VariableA:-$HOME This is a Text}
+: ${VariableA:-This is a Text in $HOME}
+: ${VariableA:-$SHELL This is a Text in $HOME}
+: ${VariableA:-This is a Text in $HOME $SHELL}
+
+# Case 1y. The same with ':' and without the ':' in the parameter substitution
+[ -t 0 ] && echo "\n`date`" && unset VariableA
+: ${VariableA-This is a Text}
+: ${VariableA-$HOME This is a Text}
+: ${VariableA-This is a Text in $HOME}
+: ${VariableA-$SHELL This is a Text in $HOME}
+: ${VariableA-This is a Text in $HOME $SHELL}
+
+################################################################################
+#
+# This are valid usages for ${Var:?} in ksh!
+#
+Variable4=${Variable4:?This is an Error Message}
+Variable4=${Variable4:?This is an Error Message from `date`}
+
+: ${Variable4:?This is an Error Message}
+: ${Variable4:?This is an Error Message from `date`}
+
+exit $?
+
+# Michael Soulier
+if [ $# -ne 1 ]; then
+ echo whatever
+ exit 1
+fi
diff --git a/mnv/runtime/syntax/testdir/input/sh_09.sh b/mnv/runtime/syntax/testdir/input/sh_09.sh
new file mode 100644
index 0000000000..c999d624af
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_09.sh
@@ -0,0 +1,20 @@
+#!/bin/dash
+# Test file for mnv the check () subshells
+( cd ; $pwd ) | wc -c
+( cd $1 ; $pwd ) | wc -c
+( cd ${1} ; $pwd ) | wc -c
+( cd ; $pwd ) | wc -c
+( cd ${1:-.} ; $pwd ) | sed -e 's!$!/!' -e 's!//*$!/!'
+( cd ; $pwd ) | wc -c
+( cd ${1:+.} ; $pwd ) | wc -c
+( cd ; $pwd ) | wc -c
+( cd ${1:=.} ; $pwd ) | wc -c
+( cd ; $pwd ) | wc -c
+( cd ${1:?} ; $pwd ) | wc -c
+( cd ; $pwd ) | wc -c
+( cd $HOME ; $pwd ) | wc -c
+( cd ${HOME} ; $pwd ) | wc -c
+( cd ${HOME} ) | wc -c
+((n=1+2))
+# this is a syntax error, "let" is not a keyword in dash
+let n=1+2
diff --git a/mnv/runtime/syntax/testdir/input/sh_10.sh b/mnv/runtime/syntax/testdir/input/sh_10.sh
new file mode 100644
index 0000000000..70059b5cd6
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_10.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+curl --http2 --tlsv1.2 -O https://example.com/file.txt
+wget --inet6-only https://example.com/file.txt
+gzip -9 file
+xz -T0 file
+find /tmp -type f -print0 | xargs -0 echo
+cut -f1 file
+nice -n10 make -j4
+kill -9 12345
+tail -n10 error.log
+git log -n10
diff --git a/mnv/runtime/syntax/testdir/input/sh_11.sh b/mnv/runtime/syntax/testdir/input/sh_11.sh
new file mode 100644
index 0000000000..6e192fc3c4
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_11.sh
@@ -0,0 +1,20 @@
+#!/bin/bash
+
+# Issue #962
+
+arr=(
+ 1 2 3 4
+) # ok
+
+if true; then
+
+ arr=(1 2 3 4) # ok
+
+ arr=( 1 2 3 4 ) # ok
+
+ arr=(
+ 1 2 3 4
+ ) # paren error!
+
+fi
+
diff --git a/mnv/runtime/syntax/testdir/input/sh_12.sh b/mnv/runtime/syntax/testdir/input/sh_12.sh
new file mode 100644
index 0000000000..b3d43b6d29
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_12.sh
@@ -0,0 +1,206 @@
+#!/bin/bash
+# MNV_TEST_SETUP highlight link shArrayValue Identifier
+# MNV_TEST_SETUP highlight link shBracketExprDelim Structure
+# MNV_TEST_SETUP highlight link shCharClass Todo
+# MNV_TEST_SETUP highlight link shRange CursorLine
+
+
+
+
+[[ ( "$1" == ?(-)+([0-9]) && "$1" =~ ^-?[[:digit:]]+$ &&
+'^?(-)+([[:digit:]])$' == "$2" && ! "^-?[0-9]+$" =~ "$2" ) ]] || :
+
+[ \( "$1" != "?(-)+([0-9])" -a "$1" != '?(-)+([[:digit:]])' \) ] &&
+[ \( "?(-)+([[:digit:]])" != "$2" -a '?(-)+([0-9])' != "$2" \) ] || :
+
+# Match "\[0\]\[0\]", "{0}{0}", etc.
+: [[{][0-9]*[]}][[{][[:digit:]]*[]}]
+: [\
+[{][0-9]*[]}][[{][[:digit:]]*[]}]
+: [[\
+{][0-9]*[]}][[{][[:digit:]]*[]}]
+: [[{\
+][0-9]*[]}][[{][[:digit:]]*[]}]
+: [[{]\
+[0-9]*[]}][[{][[:digit:]]*[]}]
+: [[{][\
+0-9]*[]}][[{][[:digit:]]*[]}]
+: [[{][0-9\
+]*[]}][[{][[:digit:]]*[]}]
+: [[{][0-9]\
+*[]}][[{][[:digit:]]*[]}]
+: [[{][0-9]*\
+[]}][[{][[:digit:]]*[]}]
+: [[{][0-9]*[]\
+}][[{][[:digit:]]*[]}]
+: [[{][0-9]*[]}\
+][[{][[:digit:]]*[]}]
+: [[{][0-9]*[]}]\
+[[{][[:digit:]]*[]}]
+: [[{][0-9]*[]}][\
+[{][[:digit:]]*[]}]
+: [[{][0-9]*[]}][[\
+{][[:digit:]]*[]}]
+: [[{][0-9]*[]}][[{\
+][[:digit:]]*[]}]
+: [[{][0-9]*[]}][[{]\
+[[:digit:]]*[]}]
+: [[{][0-9]*[]}][[{][\
+[:digit:]]*[]}]
+: [[{][0-9]*[]}][[{][[:digit:]\
+]*[]}]
+: [[{][0-9]*[]}][[{][[:digit:]]\
+*[]}]
+: [[{][0-9]*[]}][[{][[:digit:]]*\
+[]}]
+: [[{][0-9]*[]}][[{][[:digit:]]*[]\
+}]
+: [[{][0-9]*[]}][[{][[:digit:]]*[]}\
+]
+: [[{][0-9]*[]}][[{][[:digit:]]*[[.].]}]
+: [[{][0-9]*[]}][[{][[:digit:]]*[\
+[.].]}]
+: [[{][0-9]*[]}][[{][[:digit:]]*[[.].]\
+}]
+: [[{][0-9]*[]}][[{][[:digit:]]*[[.].]}\
+]
+
+# Match "\[0\]\[0\]", "{0}{0}", etc.
+case "$1" in
+[[{][0-9]*[]}][[{][[:digit:]]*[]}]*) : [0-9]; : [!0-9]; : [^0-9];;
+[\
+[{][0-9]*[]}][[{][[:digit:]]*[]}]*) : [0123]; : [!0123]; : [^0123];;
+[[\
+{][0-9]*[]}][[{][[:digit:]]*[]}]*) : [1[.0.]]; : [![.0.]]; : [^[.0.]^];;
+[[{\
+][0-9]*[]}][[{][[:digit:]]*[]}]*) : [1[=0=]]; : [![=0=]!]; : [^[=0=]];;
+[[{]\
+[0-9]*[]}][[{][[:digit:]]*[]}]*) ;;
+[[{][\
+0-9]*[]}][[{][[:digit:]]*[]}]*) ;;
+[[{][0-9\
+]*[]}][[{][[:digit:]]*[]}]*) : ?[[:foo:]]?; : [![:foo:]]?; : ?[^[:foo:]];;
+[[{][0-9]\
+*[]}][[{][[:digit:]]*[]}]*) : [[:digit:]]; : [![:digit:]]; : [^[:digit:]];;
+[[{][0-9]*\
+[]}][[{][[:digit:]]*[]}]*) : "${1^[[:lower:]]}"; : "${1^^[a-z]}";;
+[[{][0-9]*[]\
+}][[{][[:digit:]]*[]}]*) : "${1,[[:upper:]]}"; : "${1,,[A-Z]}";;
+[[{][0-9]*[]}\
+][[{][[:digit:]]*[]}]*) ;;
+[[{][0-9]*[]}]\
+[[{][[:digit:]]*[]}]*) ;;
+[[{][0-9]*[]}][\
+[{][[:digit:]]*[]}]*) : "${1#[[:digit:]]}"; : "${1##[0-9]}";;
+[[{][0-9]*[]}][[\
+{][[:digit:]]*[]}]*) : "${1%[[:digit:]]}"; : "${1%%[0-9]}";;
+[[{][0-9]*[]}][[{\
+][[:digit:]]*[]}]*) : "${1/[][:digit:][]/[0-9]}"; : "${1//[]0-9[]/[0-9]}";;
+[[{][0-9]*[]}][[{]\
+[[:digit:]]*[]}]*) : "${1/#[][:digit:][]/[0-9]}"; : "${1/%[]0-9[]/[0-9]}";;
+[[{][0-9]*[]}][[{][\
+[:digit:]]*[]}]*) ;;
+[[{][0-9]*[]}][[{][[:digit:]\
+]*[]}]*) ;;
+[[{][0-9]*[]}][[{][[:digit:]]\
+*[]}]*) : "${1#*[[.[.][.].]]}"; : "${1%[[.].][.[.]]*}"; : "${1#*" "[][]}";;
+[[{][0-9]*[]}][[{][[:digit:]]*\
+[]}]*) : "${1#*[[=[=][=]=]]}"; : "${1%[[=]=][=[=]]*}"; : "${1#*\ [!][]}";;
+[[{][0-9]*[]}][[{][[:digit:]]*[]\
+}]*) : "${1#*[!]]}"; : "${1#*[^]]}"; : "${1%[![]*}"; : "${1%[^[]*}";;
+[[{][0-9]*[]}][[{][[:digit:]]*[]}\
+]*) : "${1#*[!\]]}"; : "${1#*[^\]]}"; : "${1%[!\[]*}"; : "${1%[^\[]*}";;
+[[{][0-9]*[]}][[{][[:digit:]]*[]}]\
+*) ;;
+[[{][0-9]*[]}][[{][[:digit:]]*[[.].]}]\
+*) ;;
+[[{][0-9]*[]}][[{][[:digit:]]*[\
+[.].]}]*) ;;
+[[{][0-9]*[]}][[{][[:digit:]]*[[.].]\
+}]*) ;;
+[[{][0-9]*[]}][[{][[:digit:]]*[[.].]}\
+]*) ;;
+[!][:digit:][:xdigit:]\ [^[:lower:]![:upper:]]*) ;;
+[^][:digit:]0-9a-fA-F\ [![:lower:]^[:upper:]]*) ;;
+[!!] | [!![] | [!]!] | [!^] | [!^[] | [!]^]) ;;
+[^!] | [^![] | [^]!] | [^^] | [^^[] | [^]^]) ;;
+esac
+
+# Match "\[0\]\[0\]", "{0}{0}", etc.
+: "${1#*[[{][0-9]*[]}][[{][[:digit:]]*[]}]}"
+: "${1#*\
+[[{][0-9]*[]}][[{][[:digit:]]*[]}]}"
+: "${1#*[\
+[{][0-9]*[]}][[{][[:digit:]]*[]}]}"
+: "${1#*[[\
+{][0-9]*[]}][[{][[:digit:]]*[]}]}"
+: "${1#*[[{\
+][0-9]*[]}][[{][[:digit:]]*[]}]}"
+: "${1#*[[{]\
+[0-9]*[]}][[{][[:digit:]]*[]}]}"
+: "${1#*[[{][\
+0-9]*[]}][[{][[:digit:]]*[]}]}"
+: "${1#*[[{][0-9\
+]*[]}][[{][[:digit:]]*[]}]}"
+: "${1#*[[{][0-9]\
+*[]}][[{][[:digit:]]*[]}]}"
+: "${1#*[[{][0-9]*\
+[]}][[{][[:digit:]]*[]}]}"
+: "${1#*[[{][0-9]*[]\
+}][[{][[:digit:]]*[]}]}"
+: "${1#*[[{][0-9]*[]}\
+][[{][[:digit:]]*[]}]}"
+: "${1#*[[{][0-9]*[]}]\
+[[{][[:digit:]]*[]}]}"
+: "${1#*[[{][0-9]*[]}][\
+[{][[:digit:]]*[]}]}"
+: "${1#*[[{][0-9]*[]}][[\
+{][[:digit:]]*[]}]}"
+: "${1#*[[{][0-9]*[]}][[{\
+][[:digit:]]*[]}]}"
+: "${1#*[[{][0-9]*[]}][[{]\
+[[:digit:]]*[]}]}"
+: "${1#*[[{][0-9]*[]}][[{][\
+[:digit:]]*[]}]}"
+: "${1#*[[{][0-9]*[]}][[{][[:digit:]\
+]*[]}]}"
+: "${1#*[[{][0-9]*[]}][[{][[:digit:]]\
+*[]}]}"
+: "${1#*[[{][0-9]*[]}][[{][[:digit:]]*\
+[]}]}"
+: "${1#*[[{][0-9]*[]}][[{][[:digit:]]*[]\
+}]}"
+: "${1#*[[{][0-9]*[]}][[{][[:digit:]]*[]}\
+]}"
+: "${1#*[[{][0-9]*[]}][[{][[:digit:]]*[]}]\
+}"
+: "${1#*[[{][0-9]*[]}][[{][[:digit:]]*[[.].]}]}"
+: "${1#*[[{][0-9]*[]}][[{][[:digit:]]*[\
+[.].]}]}"
+: "${1#*[[{][0-9]*[]}][[{][[:digit:]]*[[.].]\
+}]}"
+: "${1#*[[{][0-9]*[]}][[{][[:digit:]]*[[.].]}]\
+}"
+
+: *[x[=[=][=]=]]; : [x[=]=][=[=]]*; : *[x[.[.][.].]]; : [x[.].][.[.]]*
+: *[[=[=]x[=]=]]; : [[=]=]x[=[=]]*; : *[[.[.]x[.].]]; : [[.].]x[.[.]]*
+: *[[=[=][=]=]x]; : [[=]=][=[=]x]*; : *[[.[.][.].]x]; : [[.].][.[.]x]*
+: [!]]; : [^]]; : [![]; : [^[]; : [!\]]; : [^\]]; : [!\[]; : [^\[]
+: [$'\x5b']; : [$'\x5d']; : []]; : [[]; : [\]]; : [\[]
+: [$'\x20'[]; : [" "[]; : [' '[]; : [\ []; : [\ \[]; : "${1#[ ]}"
+: [[$'\x20']; : [[" "]; : [[' ']; : [[\ ]; : [\[\ ]; : "${1#[ ]}"
+: [^$'\x20'[]; : [!" "[]; : [^' '[]; : [!\ []; : "${1#[^ ]}"
+: [![$'\x20']; : [^[" "]; : [![' ']; : [^[\ ]; : "${1#[! ]}"
+
+nl='
+'
+echo "${1#${1%%[!"${nl}"]*}}"; echo "${1#${1%%[!'${nl}']*}}"
+echo "${1#${1%%[!\"${nl}]*}}"; echo "${1#${1%%[!\'${nl}]*}}"
+echo "${1#${1%%[!${nl}\"]*}}"; echo "${1#${1%%[!${nl}\']*}}"
+
+bins=(); bins=(0 1); eval bins+=({0..1})
+bins[0]=0; bins[1]=1; eval bins+=(\${bins[{1..0}]}); unset bins[3] bins[2]
+bins=([8#0]=$((2#100)) [$((8#1))]=$((2#10)) [3]=${bins[2#1]} ${bins[0]})
+(echo sum[$((bins[16#3] + bins[8#2] + bins[2#1] + bins[0]))])
+eval unset bins[{0..$((${#bins[*]} - 1))}]
+:
diff --git a/mnv/runtime/syntax/testdir/input/sh_13.sh b/mnv/runtime/syntax/testdir/input/sh_13.sh
new file mode 100644
index 0000000000..b959e0e399
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_13.sh
@@ -0,0 +1,9 @@
+#!/bin/dash
+# Issue #17026 (bash highlighting requires space after $())
+# https://github.com/Project-Tick/Project-Tick/issues/17026#issuecomment-2774112284
+
+_comp_compgen_split -l -- "$(
+ tmux list-commands -F "#{command_list_name}"
+ tmux list-commands -F "#{command_list_alias}"
+)"
+
diff --git a/mnv/runtime/syntax/testdir/input/sh_14.sh b/mnv/runtime/syntax/testdir/input/sh_14.sh
new file mode 100644
index 0000000000..bfa3d93a44
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_14.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+# Issue #17221 (sh syntax: escaped square brackets don't work in [[ ]])
+
+[[ foo == [bar] ]]
+[[ foo == \[bar\] ]]
+
+echo [foo]
+echo \[foo\]
diff --git a/mnv/runtime/syntax/testdir/input/sh_15.sh b/mnv/runtime/syntax/testdir/input/sh_15.sh
new file mode 100644
index 0000000000..fe3dc93cfe
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_15.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+# Issue #19053 (sh syntax: escaped characters followed by # in double quotes)
+
+CLEANURL='http://localhost:8077/test'
+
+FILENAME=$(sed -r -e "s#[:/]+#\.#g" -e "s#[^a-zA-Z0-9\._]*##g" <<<${CLEANURL})
+FILENAME=$(sed -r -e 's#[:/]+#\.#g' -e 's#[^a-zA-Z0-9\._]*##g' <<<${CLEANURL})
+HDRFILE="${FILENAME}.hdr"
+
+: "\\# not a comment"
+# \\" a comment
+echo "\\#"
+:
diff --git a/mnv/runtime/syntax/testdir/input/sh_bash.bash b/mnv/runtime/syntax/testdir/input/sh_bash.bash
new file mode 100644
index 0000000000..35b536c4e3
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_bash.bash
@@ -0,0 +1,33 @@
+#!/bin/bash
+
+# bash 5.3+ supports command substitution that is very similar
+# (but not identical) to ksh/mksh.
+echo ${ echo one;}
+echo ${ echo two
+}
+echo ${
+echo three ;}
+echo ${ echo 'four'; }
+echo ${ echo 'five' ;}
+echo ${ echo 'six'
+}
+echo ${ echo 'seven' ;}
+echo ${ echo 'eight'; }
+typeset nine=${ pwd; }
+echo ${ echo 'nine' ;
+ }
+
+valsubfunc() {
+ REPLY=$1
+}
+echo ${|valsubfunc ten;}
+echo "${|valsubfunc eleven; }"
+printf '%s\n' "${|valsubfunc twelve ;}"
+unlucky=${|valsubfunc thirteen
+}
+typeset notafloat=${|valsubfunc notanumber ;
+ }
+echo $unlucky $notanumber
+${|echo fourteen;}
+${|echo fifteen
+}
diff --git a/mnv/runtime/syntax/testdir/input/sh_bash_alias.sh b/mnv/runtime/syntax/testdir/input/sh_bash_alias.sh
new file mode 100644
index 0000000000..7302fdf8a0
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_bash_alias.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/bash
+
+alias ls='ls --color=auto'
diff --git a/mnv/runtime/syntax/testdir/input/sh_functions_bash.sh b/mnv/runtime/syntax/testdir/input/sh_functions_bash.sh
new file mode 100644
index 0000000000..1c56592376
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_functions_bash.sh
@@ -0,0 +1,55 @@
+#!/bin/bash
+# MNV_TEST_SETUP setlocal fen fdc=2 fdl=8 fdm=syntax
+# MNV_TEST_SETUP let g:sh_fold_enabled = 1 + 2 + 4
+
+
+typeset -i n=0
+doosie() ((n+=1)); doosie
+donee() [[ -n $# ]]; donee
+
+thence()
+until :
+do
+ :
+done
+thence
+
+whiles() while false; do :; done; whiles
+
+elsewhere() if :
+then :; fi; elsewhere
+
+selector() select x in 1 2; do
+ break
+done
+selector 0</dev/null 2>/dev/null || :
+
+cased() case "$#" in *) :;; esac; cased
+
+fore()
+for x in 1 2
+do
+ :
+done
+fore
+
+iffy() for ((;;))
+do
+ break
+done
+iffy
+
+if :; then
+ function !?#()
+ (
+ function @α! {
+ echo "$1"
+ }
+ @α! "$1"
+ )
+ eval !?\# "$1"
+fi
+
+namespace ()
+{ echo $#;
+}; namespace $@
diff --git a/mnv/runtime/syntax/testdir/input/sh_functions_dash.sh b/mnv/runtime/syntax/testdir/input/sh_functions_dash.sh
new file mode 100644
index 0000000000..e6be9260c7
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_functions_dash.sh
@@ -0,0 +1,40 @@
+#!/bin/dash
+# MNV_TEST_SETUP setlocal fen fdc=2 fdl=8 fdm=syntax
+# MNV_TEST_SETUP let g:sh_fold_enabled = 1 + 2 + 4
+
+
+thence()
+until :
+do
+ :
+done
+thence
+
+whiles() while false; do :; done; whiles
+
+elsewhere() if :
+then :; fi; elsewhere
+
+cased() case "$#" in *) :;; esac; cased
+
+fore()
+for x in 1 2
+do
+ :
+done
+fore
+
+if :; then
+ id2()
+ (
+ id1() {
+ echo "$1"
+ }
+ id1 "$1"
+ )
+ id2 "$1"
+fi
+
+function ()
+{ echo $#;
+}; function $@
diff --git a/mnv/runtime/syntax/testdir/input/sh_functions_ksh2020.sh b/mnv/runtime/syntax/testdir/input/sh_functions_ksh2020.sh
new file mode 100644
index 0000000000..14a99f0e68
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_functions_ksh2020.sh
@@ -0,0 +1,51 @@
+#!/bin/ksh2020
+# MNV_TEST_SETUP setlocal fen fdc=2 fdl=8 fdm=syntax
+# MNV_TEST_SETUP let g:sh_fold_enabled = 1 + 2 + 4
+
+
+typeset -i 10 n=0
+doosie() ((n+=1)); doosie
+donee() [[ -n $# ]]; donee
+
+thence()
+until :
+do
+ :
+done
+thence
+
+whiles() while false; do :; done; whiles
+
+elsewhere() if :
+then :; fi; elsewhere
+
+selector() select x in 1 2; do
+ break
+done
+selector 0</dev/null 2>/dev/null || :
+
+cased() case "$#" in *) :;; esac; cased
+
+fore()
+for x in 1 2
+do
+ :
+done
+fore
+
+iffy() for ((;;))
+do
+ break
+done
+iffy
+
+if :; then
+ id_()
+ (
+ function n.set {
+ echo "$n"
+ }
+ doosie
+ )
+ id_ "$1"
+fi
diff --git a/mnv/runtime/syntax/testdir/input/sh_functions_ksh88.sh b/mnv/runtime/syntax/testdir/input/sh_functions_ksh88.sh
new file mode 100644
index 0000000000..030a5fa59c
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_functions_ksh88.sh
@@ -0,0 +1,45 @@
+#!/bin/ksh88
+# MNV_TEST_SETUP setlocal fen fdc=2 fdl=8 fdm=syntax
+# MNV_TEST_SETUP let g:sh_fold_enabled = 1 + 2 + 4
+
+
+typeset -i 10 n=0
+doosie() ((n+=1)); doosie
+donee() [[ -n $# ]]; donee
+
+thence()
+until :
+do
+ :
+done
+thence
+
+whiles() while false; do :; done; whiles
+
+elsewhere() if :
+then :; fi; elsewhere
+
+selector() select x in 1 2; do
+ break
+done
+selector 0</dev/null 2>/dev/null || :
+
+cased() case "$#" in *) :;; esac; cased
+
+fore()
+for x in 1 2
+do
+ :
+done
+fore
+
+if :; then
+ id2()
+ (
+ function id1 {
+ echo "$1"
+ }
+ id1 "$1"
+ )
+ id2 "$1"
+fi
diff --git a/mnv/runtime/syntax/testdir/input/sh_functions_mksh.sh b/mnv/runtime/syntax/testdir/input/sh_functions_mksh.sh
new file mode 100644
index 0000000000..2eba028344
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_functions_mksh.sh
@@ -0,0 +1,45 @@
+#!/bin/mksh
+# MNV_TEST_SETUP setlocal fen fdc=2 fdl=8 fdm=syntax
+# MNV_TEST_SETUP let g:sh_fold_enabled = 1 + 2 + 4
+
+
+typeset -i10 n=0
+doosie() ((n+=1)); doosie
+donee() [[ -n $# ]]; donee
+
+thence()
+until :
+do
+ :
+done
+thence
+
+whiles() while false; do :; done; whiles
+
+elsewhere() if :
+then :; fi; elsewhere
+
+selector() select x in 1 2; do
+ break
+done
+selector 0</dev/null 2>/dev/null || :
+
+cased() case "$#" in *) :;; esac; cased
+
+fore()
+for x in 1 2
+do
+ :
+done
+fore
+
+if :; then
+ %%%()
+ (
+ function @a:() {
+ echo "$1"
+ }
+ @a: "$1"
+ )
+ %%% "$1"
+fi
diff --git a/mnv/runtime/syntax/testdir/input/sh_generic.ksh b/mnv/runtime/syntax/testdir/input/sh_generic.ksh
new file mode 100644
index 0000000000..277bddaa0a
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_generic.ksh
@@ -0,0 +1,206 @@
+#!/bin/ksh
+
+# Rendering namespace variables
+echo ${.foo.bar[adsf]} ${foo.bar[1][2]} ${foo.bar[1][az]} ${.foo.bar[1][2]}
+echo ${.foo[var]} ${.foo.bar[1]} ${.foo.bar[*]} ${foo.bar##baz} ${.foo.bar##baz}
+echo ${.foo.bar[3]##baz} ${.foo.bar[z]##baz} ${sh.version/V/b} ${.sh.version/V/b}
+echo ${foo/%bar/foo} ${foo/#bar/foo} ${foo.bar/%bar/foo} ${foo.bar[d]/#bar/foo}
+echo ${.foo/%barfoo} ${.foo.bar/#bar/foo} ${.bar.foo/%bar/foo} ${.bar/#bar/foo}
+echo ${foo/%barfoo} ${foo/bar/foo} ${barfoo//bar/foo} ${bar/#bar/foo}
+echo ${.sh.version^^} ${.sh.version,,} ${KSH_VERSION^} ${KSH_VERSION,}
+
+# 'alarm' builtin (present in ksh93u+, ksh93v- and the 93u+m dev branch).
+alarm --man
+# The fds and pids builtins. These ksh93 builtins have existed since 2005-05-22
+# and 2008-06-02, respectively. However, these were not readily enabled; in
+# 93u+m these can be enabled with the builtin command if libcmd.so is present,
+# either via 'builtin -f' or (in more recent commits) with a regular invocation
+# of the 'builtin' built-in.
+# cf. https://github.com/ksh93/ksh/commit/f15e2c41
+builtin fds pids
+fds; pids
+
+# Unix commands which are provided by ksh as builtins via libcmd.so
+basename
+cat
+chgrp
+chmod
+chown
+cksum
+cmp
+comm
+cp
+cut
+date
+dirname
+egrep # Obsolescent
+expr
+fgrep # Obsolescent
+fmt
+fold
+getconf
+grep
+head
+iconv # 93v-
+id
+join
+ln
+logname
+ls # 93v-
+md5sum
+mkdir
+mkfifo
+mktemp
+mv
+od # 93v-
+paste
+pathchk
+readlink # 93v-
+realpath # 93v-
+rev
+rm
+rmdir
+sha1sum # 93v-
+sha256sum # 93v-
+sha2sum # 93v-
+sha384sum # 93v-
+sha512sum # 93v-
+stty
+sum
+sync
+tail
+tee
+tr # 93v-
+tty
+uname
+uniq
+vmstate # Obsolescent; only available in 93v- and older
+wc
+xargs # 93v-
+xgrep # Obsolescent; only 93v- allows invoking 'grep -X' as 'xgrep'
+
+# SHA command not provided as a builtin but included here for completeness
+sha224sum
+
+# poll builtin (93v-)
+poll --man
+
+# mkservice and eloop (rarely provided; requires SHOPT_MKSERVICE)
+mkservice --man; eloop --help
+
+# some mksh builtins, rename should be highlighted as an external command
+bind; rename
+
+# ;& and ;;& in case statements
+case x in
+ bar) false ${baz:1} ;&
+ foo) true ${foo:0:0} ;;&
+ *) print ${$bar} ;; # 93v-
+esac
+
+# Below is subshare syntax supported by both ksh93 and mksh.
+print ${ echo one }
+print ${ echo two
+}
+print ${
+echo three }
+print ${ echo 'four'; }
+print ${ echo 'five' ;}
+print ${ echo 'six'
+}
+print ${ echo 'seven' }
+echo ${ print 'eight' }
+typeset nine=${ pwd; }
+
+# Value substitutions of the form ${|command} are only
+# supported by mksh, not ksh93.
+if ! command eval '((.sh.version >= 20070703))' 2>/dev/null; then
+ valsubfunc() {
+ REPLY=$1
+ }
+ echo ${|valsubfunc ten}
+ print "${|valsubfunc eleven;}"
+ printf '%s' "${|valsubfunc twelve }"
+ unlucky=${|valsubfunc thirteen
+}
+ typeset notafloat=${|valsubfunc notanumber }
+ print $unlucky $notanumber
+ ${|echo foo}
+ ${|echo bar
+}
+fi
+
+# ======
+# Shared-state command substitutions using the syntax ${<file;}
+# are only supported by ksh93, not mksh.
+echo ${
+ printf %s str
+} > /tmp/strfile
+echo ${</tmp/strfile;}
+
+# ksh88 and ksh93 non-dot special variables
+print ${ RANDOM= SRANDOM= SHLVL= JOBMAX= KSH_VERSION= FIGNORE= LC_TIME= LC_NUMERIC= LC_MESSAGES= LC_CTYPE= LC_COLLATE= LC_ALL= LANG= FPATH= PS4= OPTIND= OPTARG= true ;}
+print $(LINENO= SECONDS= TMOUT= PPID= LINES= COLUMNS= VISUAL= OLDPWD= PS3= MAILPATH= CDPATH= FCEDIT= HISTCMD= HISTEDIT= HISTSIZE= HISTFILE= ENV= MAILCHECK= EDITOR= SHELL= false)
+print $(REPLY= MAIL= HOME= PWD= IFS= PS2= PS1= PATH= SH_OPTIONS= ERRNO= COMP_CWORD= COMP_LINE= COMP_POINT= COMP_WORDS= COMP_KEY= COMPREPLY= COMP_WORDBREAKS= COMP_TYPE= compgen)
+print $(BASHPID= EPOCHREALTIME= EXECSHELL= KSHEGID= KSHGID= KSHUID= KSH_MATCH= PATHSEP= PGRP= PIPESTATUS= TMPDIR= USER_ID= VPATH= CSWIDTH= complete)
+
+# ksh93 namespace (dot) special variables
+print $(.sh= .sh.edchar= .sh.edcol= .sh.edtext= .sh.edmode= .sh.name= .sh.subscript= .sh.value= .sh.version= .sh.match= .sh.command= .sh.file= .sh.fun= .sh.subshell= .sh.level= .sh.lineno= .sh.stats= .sh.math= .sh.pid= .sh.ppid= .sh.tilde= .sh.dollar= .sh.pool= .sh.pgrp= .sh.pwdfd= .sh.op_astbin= .sh.sig= .sh.sig.addr= .sh.sig.band= .sh.sig.code= .sh.sig.errno= .sh.sig.name= .sh.sig.pid= .sh.sig.signo= .sh.sig.status= .sh.sig.uid= .sh.sig.value= .sh.sig.value.q= .sh.sig.value.Q= .sh.stats= .sh.stats.arg_cachehits= .sh.stats.arg_expands= .sh.stats.comsubs= .sh.stats.forks= .sh.stats.funcalls= .sh.stats.globs= .sh.stats.linesread= .sh.stats.nv_cachehit= .sh.stats.nv_opens= .sh.stats.pathsearch= .sh.stats.posixfuncall= .sh.stats.simplecmds= .sh.stats.spawns= .sh.stats.subshell= .sh.install_prefix= complete)
+
+.sh.tilde.get() {
+ true
+}
+
+function .sh.tilde.set {
+ false
+}
+
+function foo() {
+ : # Bash-style function (mksh-only)
+}
+
+function foo2 {
+ : # KornShell-style function
+}
+
+foo3() {
+ : # POSIX function
+}
+
+foo4.get() {
+ : # POSIX-style ksh93 discipline function
+}
+
+function foo5.set {
+ : # KornShell-style ksh93 discipline function
+}
+
+_foo6.unset() (
+ : # POSIX-style subshell discipline function
+)
+
+namespace _foo {
+ :
+}
+
+namespace 1bad.invalid {
+ :
+}
+
+namespace foo1() {
+ : # Bad syntax
+}
+
+# Bad syntax (no name)
+function {
+ false
+}
+
+# Bad syntax also
+ () {
+ false
+}
+()
+{
+ false
+}
diff --git a/mnv/runtime/syntax/testdir/input/sh_ksh2020.ksh b/mnv/runtime/syntax/testdir/input/sh_ksh2020.ksh
new file mode 100644
index 0000000000..67a578b03f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_ksh2020.ksh
@@ -0,0 +1,206 @@
+#!/bin/ksh2020
+
+# Rendering namespace variables
+echo ${.foo.bar[adsf]} ${foo.bar[1][2]} ${foo.bar[1][az]} ${.foo.bar[1][2]}
+echo ${.foo[var]} ${.foo.bar[1]} ${.foo.bar[*]} ${foo.bar##baz} ${.foo.bar##baz}
+echo ${.foo.bar[3]##baz} ${.foo.bar[z]##baz} ${sh.version/V/b} ${.sh.version/V/b}
+echo ${foo/%bar/foo} ${foo/#bar/foo} ${foo.bar/%bar/foo} ${foo.bar[d]/#bar/foo}
+echo ${.foo/%barfoo} ${.foo.bar/#bar/foo} ${.bar.foo/%bar/foo} ${.bar/#bar/foo}
+echo ${foo/%barfoo} ${foo/bar/foo} ${barfoo//bar/foo} ${bar/#bar/foo}
+echo ${.sh.version^^} ${.sh.version,,} ${KSH_VERSION^} ${KSH_VERSION,}
+
+# 'alarm' builtin (present in ksh93u+, ksh93v- and the 93u+m dev branch).
+alarm --man
+# The fds and pids builtins. These ksh93 builtins have existed since 2005-05-22
+# and 2008-06-02, respectively. However, these were not readily enabled; in
+# 93u+m these can be enabled with the builtin command if libcmd.so is present,
+# either via 'builtin -f' or (in more recent commits) with a regular invocation
+# of the 'builtin' built-in.
+# cf. https://github.com/ksh93/ksh/commit/f15e2c41
+builtin fds pids
+fds; pids
+
+# Unix commands which are provided by ksh as builtins via libcmd.so
+basename
+cat
+chgrp
+chmod
+chown
+cksum
+cmp
+comm
+cp
+cut
+date
+dirname
+egrep # Obsolescent
+expr
+fgrep # Obsolescent
+fmt
+fold
+getconf
+grep
+head
+iconv # 93v-
+id
+join
+ln
+logname
+ls # 93v-
+md5sum
+mkdir
+mkfifo
+mktemp
+mv
+od # 93v-
+paste
+pathchk
+readlink # 93v-
+realpath # 93v-
+rev
+rm
+rmdir
+sha1sum # 93v-
+sha256sum # 93v-
+sha2sum # 93v-
+sha384sum # 93v-
+sha512sum # 93v-
+stty
+sum
+sync
+tail
+tee
+tr # 93v-
+tty
+uname
+uniq
+vmstate # Obsolescent; only available in 93v- and older
+wc
+xargs # 93v-
+xgrep # Obsolescent; only 93v- allows invoking 'grep -X' as 'xgrep'
+
+# SHA command not provided as a builtin but included here for completeness
+sha224sum
+
+# poll builtin (93v-)
+poll --man
+
+# mkservice and eloop (rarely provided; requires SHOPT_MKSERVICE)
+mkservice --man; eloop --help
+
+# some mksh builtins, rename should be highlighted as an external command
+bind; rename
+
+# ;& and ;;& in case statements
+case x in
+ bar) false ${baz:1} ;&
+ foo) true ${foo:0:0} ;;&
+ *) print ${$bar} ;; # 93v-
+esac
+
+# Below is subshare syntax supported by both ksh93 and mksh.
+print ${ echo one }
+print ${ echo two
+}
+print ${
+echo three }
+print ${ echo 'four'; }
+print ${ echo 'five' ;}
+print ${ echo 'six'
+}
+print ${ echo 'seven' }
+echo ${ print 'eight' }
+typeset nine=${ pwd; }
+
+# Value substitutions of the form ${|command} are only
+# supported by mksh, not ksh93.
+if ! command eval '((.sh.version >= 20070703))' 2>/dev/null; then
+ valsubfunc() {
+ REPLY=$1
+ }
+ echo ${|valsubfunc ten}
+ print "${|valsubfunc eleven;}"
+ printf '%s' "${|valsubfunc twelve }"
+ unlucky=${|valsubfunc thirteen
+}
+ typeset notafloat=${|valsubfunc notanumber }
+ print $unlucky $notanumber
+ ${|echo foo}
+ ${|echo bar
+}
+fi
+
+# ======
+# Shared-state command substitutions using the syntax ${<file;}
+# are only supported by ksh93, not mksh.
+echo ${
+ printf %s str
+} > /tmp/strfile
+echo ${</tmp/strfile;}
+
+# ksh88 and ksh93 non-dot special variables
+print ${ RANDOM= SRANDOM= SHLVL= JOBMAX= KSH_VERSION= FIGNORE= LC_TIME= LC_NUMERIC= LC_MESSAGES= LC_CTYPE= LC_COLLATE= LC_ALL= LANG= FPATH= PS4= OPTIND= OPTARG= true ;}
+print $(LINENO= SECONDS= TMOUT= PPID= LINES= COLUMNS= VISUAL= OLDPWD= PS3= MAILPATH= CDPATH= FCEDIT= HISTCMD= HISTEDIT= HISTSIZE= HISTFILE= ENV= MAILCHECK= EDITOR= SHELL= false)
+print $(REPLY= MAIL= HOME= PWD= IFS= PS2= PS1= PATH= SH_OPTIONS= ERRNO= COMP_CWORD= COMP_LINE= COMP_POINT= COMP_WORDS= COMP_KEY= COMPREPLY= COMP_WORDBREAKS= COMP_TYPE= compgen)
+print $(BASHPID= EPOCHREALTIME= EXECSHELL= KSHEGID= KSHGID= KSHUID= KSH_MATCH= PATHSEP= PGRP= PIPESTATUS= TMPDIR= USER_ID= VPATH= CSWIDTH= complete)
+
+# ksh93 namespace (dot) special variables
+print $(.sh= .sh.edchar= .sh.edcol= .sh.edtext= .sh.edmode= .sh.name= .sh.subscript= .sh.value= .sh.version= .sh.match= .sh.command= .sh.file= .sh.fun= .sh.subshell= .sh.level= .sh.lineno= .sh.stats= .sh.math= .sh.pid= .sh.ppid= .sh.tilde= .sh.dollar= .sh.pool= .sh.pgrp= .sh.pwdfd= .sh.op_astbin= .sh.sig= .sh.sig.addr= .sh.sig.band= .sh.sig.code= .sh.sig.errno= .sh.sig.name= .sh.sig.pid= .sh.sig.signo= .sh.sig.status= .sh.sig.uid= .sh.sig.value= .sh.sig.value.q= .sh.sig.value.Q= .sh.stats= .sh.stats.arg_cachehits= .sh.stats.arg_expands= .sh.stats.comsubs= .sh.stats.forks= .sh.stats.funcalls= .sh.stats.globs= .sh.stats.linesread= .sh.stats.nv_cachehit= .sh.stats.nv_opens= .sh.stats.pathsearch= .sh.stats.posixfuncall= .sh.stats.simplecmds= .sh.stats.spawns= .sh.stats.subshell= .sh.install_prefix= complete)
+
+.sh.tilde.get() {
+ true
+}
+
+function .sh.tilde.set {
+ false
+}
+
+function foo() {
+ : # Bash-style function (mksh-only)
+}
+
+function foo2 {
+ : # KornShell-style function
+}
+
+foo3() {
+ : # POSIX function
+}
+
+foo4.get() {
+ : # POSIX-style ksh93 discipline function
+}
+
+function foo5.set {
+ : # KornShell-style ksh93 discipline function
+}
+
+_foo6.unset() (
+ : # POSIX-style subshell discipline function
+)
+
+namespace _foo {
+ :
+}
+
+namespace 1bad.invalid {
+ :
+}
+
+namespace foo1() {
+ : # Bad syntax
+}
+
+# Bad syntax (no name)
+function {
+ false
+}
+
+# Bad syntax also
+ () {
+ false
+}
+()
+{
+ false
+}
diff --git a/mnv/runtime/syntax/testdir/input/sh_ksh88.ksh b/mnv/runtime/syntax/testdir/input/sh_ksh88.ksh
new file mode 100644
index 0000000000..53b1b5fcc3
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_ksh88.ksh
@@ -0,0 +1,206 @@
+#!/bin/ksh88
+
+# Rendering namespace variables
+echo ${.foo.bar[adsf]} ${foo.bar[1][2]} ${foo.bar[1][az]} ${.foo.bar[1][2]}
+echo ${.foo[var]} ${.foo.bar[1]} ${.foo.bar[*]} ${foo.bar##baz} ${.foo.bar##baz}
+echo ${.foo.bar[3]##baz} ${.foo.bar[z]##baz} ${sh.version/V/b} ${.sh.version/V/b}
+echo ${foo/%bar/foo} ${foo/#bar/foo} ${foo.bar/%bar/foo} ${foo.bar[d]/#bar/foo}
+echo ${.foo/%barfoo} ${.foo.bar/#bar/foo} ${.bar.foo/%bar/foo} ${.bar/#bar/foo}
+echo ${foo/%barfoo} ${foo/bar/foo} ${barfoo//bar/foo} ${bar/#bar/foo}
+echo ${.sh.version^^} ${.sh.version,,} ${KSH_VERSION^} ${KSH_VERSION,}
+
+# 'alarm' builtin (present in ksh93u+, ksh93v- and the 93u+m dev branch).
+alarm --man
+# The fds and pids builtins. These ksh93 builtins have existed since 2005-05-22
+# and 2008-06-02, respectively. However, these were not readily enabled; in
+# 93u+m these can be enabled with the builtin command if libcmd.so is present,
+# either via 'builtin -f' or (in more recent commits) with a regular invocation
+# of the 'builtin' built-in.
+# cf. https://github.com/ksh93/ksh/commit/f15e2c41
+builtin fds pids
+fds; pids
+
+# Unix commands which are provided by ksh as builtins via libcmd.so
+basename
+cat
+chgrp
+chmod
+chown
+cksum
+cmp
+comm
+cp
+cut
+date
+dirname
+egrep # Obsolescent
+expr
+fgrep # Obsolescent
+fmt
+fold
+getconf
+grep
+head
+iconv # 93v-
+id
+join
+ln
+logname
+ls # 93v-
+md5sum
+mkdir
+mkfifo
+mktemp
+mv
+od # 93v-
+paste
+pathchk
+readlink # 93v-
+realpath # 93v-
+rev
+rm
+rmdir
+sha1sum # 93v-
+sha256sum # 93v-
+sha2sum # 93v-
+sha384sum # 93v-
+sha512sum # 93v-
+stty
+sum
+sync
+tail
+tee
+tr # 93v-
+tty
+uname
+uniq
+vmstate # Obsolescent; only available in 93v- and older
+wc
+xargs # 93v-
+xgrep # Obsolescent; only 93v- allows invoking 'grep -X' as 'xgrep'
+
+# SHA command not provided as a builtin but included here for completeness
+sha224sum
+
+# poll builtin (93v-)
+poll --man
+
+# mkservice and eloop (rarely provided; requires SHOPT_MKSERVICE)
+mkservice --man; eloop --help
+
+# some mksh builtins, rename should be highlighted as an external command
+bind; rename
+
+# ;& and ;;& in case statements
+case x in
+ bar) false ${baz:1} ;&
+ foo) true ${foo:0:0} ;;&
+ *) print ${$bar} ;; # 93v-
+esac
+
+# Below is subshare syntax supported by both ksh93 and mksh.
+print ${ echo one }
+print ${ echo two
+}
+print ${
+echo three }
+print ${ echo 'four'; }
+print ${ echo 'five' ;}
+print ${ echo 'six'
+}
+print ${ echo 'seven' }
+echo ${ print 'eight' }
+typeset nine=${ pwd; }
+
+# Value substitutions of the form ${|command} are only
+# supported by mksh, not ksh93.
+if ! command eval '((.sh.version >= 20070703))' 2>/dev/null; then
+ valsubfunc() {
+ REPLY=$1
+ }
+ echo ${|valsubfunc ten}
+ print "${|valsubfunc eleven;}"
+ printf '%s' "${|valsubfunc twelve }"
+ unlucky=${|valsubfunc thirteen
+}
+ typeset notafloat=${|valsubfunc notanumber }
+ print $unlucky $notanumber
+ ${|echo foo}
+ ${|echo bar
+}
+fi
+
+# ======
+# Shared-state command substitutions using the syntax ${<file;}
+# are only supported by ksh93, not mksh.
+echo ${
+ printf %s str
+} > /tmp/strfile
+echo ${</tmp/strfile;}
+
+# ksh88 and ksh93 non-dot special variables
+print ${ RANDOM= SRANDOM= SHLVL= JOBMAX= KSH_VERSION= FIGNORE= LC_TIME= LC_NUMERIC= LC_MESSAGES= LC_CTYPE= LC_COLLATE= LC_ALL= LANG= FPATH= PS4= OPTIND= OPTARG= true ;}
+print $(LINENO= SECONDS= TMOUT= PPID= LINES= COLUMNS= VISUAL= OLDPWD= PS3= MAILPATH= CDPATH= FCEDIT= HISTCMD= HISTEDIT= HISTSIZE= HISTFILE= ENV= MAILCHECK= EDITOR= SHELL= false)
+print $(REPLY= MAIL= HOME= PWD= IFS= PS2= PS1= PATH= SH_OPTIONS= ERRNO= COMP_CWORD= COMP_LINE= COMP_POINT= COMP_WORDS= COMP_KEY= COMPREPLY= COMP_WORDBREAKS= COMP_TYPE= compgen)
+print $(BASHPID= EPOCHREALTIME= EXECSHELL= KSHEGID= KSHGID= KSHUID= KSH_MATCH= PATHSEP= PGRP= PIPESTATUS= TMPDIR= USER_ID= VPATH= CSWIDTH= complete)
+
+# ksh93 namespace (dot) special variables
+print $(.sh= .sh.edchar= .sh.edcol= .sh.edtext= .sh.edmode= .sh.name= .sh.subscript= .sh.value= .sh.version= .sh.match= .sh.command= .sh.file= .sh.fun= .sh.subshell= .sh.level= .sh.lineno= .sh.stats= .sh.math= .sh.pid= .sh.ppid= .sh.tilde= .sh.dollar= .sh.pool= .sh.pgrp= .sh.pwdfd= .sh.op_astbin= .sh.sig= .sh.sig.addr= .sh.sig.band= .sh.sig.code= .sh.sig.errno= .sh.sig.name= .sh.sig.pid= .sh.sig.signo= .sh.sig.status= .sh.sig.uid= .sh.sig.value= .sh.sig.value.q= .sh.sig.value.Q= .sh.stats= .sh.stats.arg_cachehits= .sh.stats.arg_expands= .sh.stats.comsubs= .sh.stats.forks= .sh.stats.funcalls= .sh.stats.globs= .sh.stats.linesread= .sh.stats.nv_cachehit= .sh.stats.nv_opens= .sh.stats.pathsearch= .sh.stats.posixfuncall= .sh.stats.simplecmds= .sh.stats.spawns= .sh.stats.subshell= .sh.install_prefix= complete)
+
+.sh.tilde.get() {
+ true
+}
+
+function .sh.tilde.set {
+ false
+}
+
+function foo() {
+ : # Bash-style function (mksh-only)
+}
+
+function foo2 {
+ : # KornShell-style function
+}
+
+foo3() {
+ : # POSIX function
+}
+
+foo4.get() {
+ : # POSIX-style ksh93 discipline function
+}
+
+function foo5.set {
+ : # KornShell-style ksh93 discipline function
+}
+
+_foo6.unset() (
+ : # POSIX-style subshell discipline function
+)
+
+namespace _foo {
+ :
+}
+
+namespace 1bad.invalid {
+ :
+}
+
+namespace foo1() {
+ : # Bad syntax
+}
+
+# Bad syntax (no name)
+function {
+ false
+}
+
+# Bad syntax also
+ () {
+ false
+}
+()
+{
+ false
+}
diff --git a/mnv/runtime/syntax/testdir/input/sh_ksh93_generic.ksh b/mnv/runtime/syntax/testdir/input/sh_ksh93_generic.ksh
new file mode 100644
index 0000000000..be4c3c1102
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_ksh93_generic.ksh
@@ -0,0 +1,206 @@
+#!/bin/ksh93
+
+# Rendering namespace variables
+echo ${.foo.bar[adsf]} ${foo.bar[1][2]} ${foo.bar[1][az]} ${.foo.bar[1][2]}
+echo ${.foo[var]} ${.foo.bar[1]} ${.foo.bar[*]} ${foo.bar##baz} ${.foo.bar##baz}
+echo ${.foo.bar[3]##baz} ${.foo.bar[z]##baz} ${sh.version/V/b} ${.sh.version/V/b}
+echo ${foo/%bar/foo} ${foo/#bar/foo} ${foo.bar/%bar/foo} ${foo.bar[d]/#bar/foo}
+echo ${.foo/%barfoo} ${.foo.bar/#bar/foo} ${.bar.foo/%bar/foo} ${.bar/#bar/foo}
+echo ${foo/%barfoo} ${foo/bar/foo} ${barfoo//bar/foo} ${bar/#bar/foo}
+echo ${.sh.version^^} ${.sh.version,,} ${KSH_VERSION^} ${KSH_VERSION,}
+
+# 'alarm' builtin (present in ksh93u+, ksh93v- and the 93u+m dev branch).
+alarm --man
+# The fds and pids builtins. These ksh93 builtins have existed since 2005-05-22
+# and 2008-06-02, respectively. However, these were not readily enabled; in
+# 93u+m these can be enabled with the builtin command if libcmd.so is present,
+# either via 'builtin -f' or (in more recent commits) with a regular invocation
+# of the 'builtin' built-in.
+# cf. https://github.com/ksh93/ksh/commit/f15e2c41
+builtin fds pids
+fds; pids
+
+# Unix commands which are provided by ksh as builtins via libcmd.so
+basename
+cat
+chgrp
+chmod
+chown
+cksum
+cmp
+comm
+cp
+cut
+date
+dirname
+egrep # Obsolescent
+expr
+fgrep # Obsolescent
+fmt
+fold
+getconf
+grep
+head
+iconv # 93v-
+id
+join
+ln
+logname
+ls # 93v-
+md5sum
+mkdir
+mkfifo
+mktemp
+mv
+od # 93v-
+paste
+pathchk
+readlink # 93v-
+realpath # 93v-
+rev
+rm
+rmdir
+sha1sum # 93v-
+sha256sum # 93v-
+sha2sum # 93v-
+sha384sum # 93v-
+sha512sum # 93v-
+stty
+sum
+sync
+tail
+tee
+tr # 93v-
+tty
+uname
+uniq
+vmstate # Obsolescent; only available in 93v- and older
+wc
+xargs # 93v-
+xgrep # Obsolescent; only 93v- allows invoking 'grep -X' as 'xgrep'
+
+# SHA command not provided as a builtin but included here for completeness
+sha224sum
+
+# poll builtin (93v-)
+poll --man
+
+# mkservice and eloop (rarely provided; requires SHOPT_MKSERVICE)
+mkservice --man; eloop --help
+
+# some mksh builtins, rename should be highlighted as an external command
+bind; rename
+
+# ;& and ;;& in case statements
+case x in
+ bar) false ${baz:1} ;&
+ foo) true ${foo:0:0} ;;&
+ *) print ${$bar} ;; # 93v-
+esac
+
+# Below is subshare syntax supported by both ksh93 and mksh.
+print ${ echo one }
+print ${ echo two
+}
+print ${
+echo three }
+print ${ echo 'four'; }
+print ${ echo 'five' ;}
+print ${ echo 'six'
+}
+print ${ echo 'seven' }
+echo ${ print 'eight' }
+typeset nine=${ pwd; }
+
+# Value substitutions of the form ${|command} are only
+# supported by mksh, not ksh93.
+if ! command eval '((.sh.version >= 20070703))' 2>/dev/null; then
+ valsubfunc() {
+ REPLY=$1
+ }
+ echo ${|valsubfunc ten}
+ print "${|valsubfunc eleven;}"
+ printf '%s' "${|valsubfunc twelve }"
+ unlucky=${|valsubfunc thirteen
+}
+ typeset notafloat=${|valsubfunc notanumber }
+ print $unlucky $notanumber
+ ${|echo foo}
+ ${|echo bar
+}
+fi
+
+# ======
+# Shared-state command substitutions using the syntax ${<file;}
+# are only supported by ksh93, not mksh.
+echo ${
+ printf %s str
+} > /tmp/strfile
+echo ${</tmp/strfile;}
+
+# ksh88 and ksh93 non-dot special variables
+print ${ RANDOM= SRANDOM= SHLVL= JOBMAX= KSH_VERSION= FIGNORE= LC_TIME= LC_NUMERIC= LC_MESSAGES= LC_CTYPE= LC_COLLATE= LC_ALL= LANG= FPATH= PS4= OPTIND= OPTARG= true ;}
+print $(LINENO= SECONDS= TMOUT= PPID= LINES= COLUMNS= VISUAL= OLDPWD= PS3= MAILPATH= CDPATH= FCEDIT= HISTCMD= HISTEDIT= HISTSIZE= HISTFILE= ENV= MAILCHECK= EDITOR= SHELL= false)
+print $(REPLY= MAIL= HOME= PWD= IFS= PS2= PS1= PATH= SH_OPTIONS= ERRNO= COMP_CWORD= COMP_LINE= COMP_POINT= COMP_WORDS= COMP_KEY= COMPREPLY= COMP_WORDBREAKS= COMP_TYPE= compgen)
+print $(BASHPID= EPOCHREALTIME= EXECSHELL= KSHEGID= KSHGID= KSHUID= KSH_MATCH= PATHSEP= PGRP= PIPESTATUS= TMPDIR= USER_ID= VPATH= CSWIDTH= complete)
+
+# ksh93 namespace (dot) special variables
+print $(.sh= .sh.edchar= .sh.edcol= .sh.edtext= .sh.edmode= .sh.name= .sh.subscript= .sh.value= .sh.version= .sh.match= .sh.command= .sh.file= .sh.fun= .sh.subshell= .sh.level= .sh.lineno= .sh.stats= .sh.math= .sh.pid= .sh.ppid= .sh.tilde= .sh.dollar= .sh.pool= .sh.pgrp= .sh.pwdfd= .sh.op_astbin= .sh.sig= .sh.sig.addr= .sh.sig.band= .sh.sig.code= .sh.sig.errno= .sh.sig.name= .sh.sig.pid= .sh.sig.signo= .sh.sig.status= .sh.sig.uid= .sh.sig.value= .sh.sig.value.q= .sh.sig.value.Q= .sh.stats= .sh.stats.arg_cachehits= .sh.stats.arg_expands= .sh.stats.comsubs= .sh.stats.forks= .sh.stats.funcalls= .sh.stats.globs= .sh.stats.linesread= .sh.stats.nv_cachehit= .sh.stats.nv_opens= .sh.stats.pathsearch= .sh.stats.posixfuncall= .sh.stats.simplecmds= .sh.stats.spawns= .sh.stats.subshell= .sh.install_prefix= complete)
+
+.sh.tilde.get() {
+ true
+}
+
+function .sh.tilde.set {
+ false
+}
+
+function foo() {
+ : # Bash-style function (mksh-only)
+}
+
+function foo2 {
+ : # KornShell-style function
+}
+
+foo3() {
+ : # POSIX function
+}
+
+foo4.get() {
+ : # POSIX-style ksh93 discipline function
+}
+
+function foo5.set {
+ : # KornShell-style ksh93 discipline function
+}
+
+_foo6.unset() (
+ : # POSIX-style subshell discipline function
+)
+
+namespace _foo {
+ :
+}
+
+namespace 1bad.invalid {
+ :
+}
+
+namespace foo1() {
+ : # Bad syntax
+}
+
+# Bad syntax (no name)
+function {
+ false
+}
+
+# Bad syntax also
+ () {
+ false
+}
+()
+{
+ false
+}
diff --git a/mnv/runtime/syntax/testdir/input/sh_ksh93u.ksh b/mnv/runtime/syntax/testdir/input/sh_ksh93u.ksh
new file mode 100644
index 0000000000..156f4ac293
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_ksh93u.ksh
@@ -0,0 +1,206 @@
+#!/bin/ksh93u+
+
+# Rendering namespace variables
+echo ${.foo.bar[adsf]} ${foo.bar[1][2]} ${foo.bar[1][az]} ${.foo.bar[1][2]}
+echo ${.foo[var]} ${.foo.bar[1]} ${.foo.bar[*]} ${foo.bar##baz} ${.foo.bar##baz}
+echo ${.foo.bar[3]##baz} ${.foo.bar[z]##baz} ${sh.version/V/b} ${.sh.version/V/b}
+echo ${foo/%bar/foo} ${foo/#bar/foo} ${foo.bar/%bar/foo} ${foo.bar[d]/#bar/foo}
+echo ${.foo/%barfoo} ${.foo.bar/#bar/foo} ${.bar.foo/%bar/foo} ${.bar/#bar/foo}
+echo ${foo/%barfoo} ${foo/bar/foo} ${barfoo//bar/foo} ${bar/#bar/foo}
+echo ${.sh.version^^} ${.sh.version,,} ${KSH_VERSION^} ${KSH_VERSION,}
+
+# 'alarm' builtin (present in ksh93u+, ksh93v- and the 93u+m dev branch).
+alarm --man
+# The fds and pids builtins. These ksh93 builtins have existed since 2005-05-22
+# and 2008-06-02, respectively. However, these were not readily enabled; in
+# 93u+m these can be enabled with the builtin command if libcmd.so is present,
+# either via 'builtin -f' or (in more recent commits) with a regular invocation
+# of the 'builtin' built-in.
+# cf. https://github.com/ksh93/ksh/commit/f15e2c41
+builtin fds pids
+fds; pids
+
+# Unix commands which are provided by ksh as builtins via libcmd.so
+basename
+cat
+chgrp
+chmod
+chown
+cksum
+cmp
+comm
+cp
+cut
+date
+dirname
+egrep # Obsolescent
+expr
+fgrep # Obsolescent
+fmt
+fold
+getconf
+grep
+head
+iconv # 93v-
+id
+join
+ln
+logname
+ls # 93v-
+md5sum
+mkdir
+mkfifo
+mktemp
+mv
+od # 93v-
+paste
+pathchk
+readlink # 93v-
+realpath # 93v-
+rev
+rm
+rmdir
+sha1sum # 93v-
+sha256sum # 93v-
+sha2sum # 93v-
+sha384sum # 93v-
+sha512sum # 93v-
+stty
+sum
+sync
+tail
+tee
+tr # 93v-
+tty
+uname
+uniq
+vmstate # Obsolescent; only available in 93v- and older
+wc
+xargs # 93v-
+xgrep # Obsolescent; only 93v- allows invoking 'grep -X' as 'xgrep'
+
+# SHA command not provided as a builtin but included here for completeness
+sha224sum
+
+# poll builtin (93v-)
+poll --man
+
+# mkservice and eloop (rarely provided; requires SHOPT_MKSERVICE)
+mkservice --man; eloop --help
+
+# some mksh builtins, rename should be highlighted as an external command
+bind; rename
+
+# ;& and ;;& in case statements
+case x in
+ bar) false ${baz:1} ;&
+ foo) true ${foo:0:0} ;;&
+ *) print ${$bar} ;; # 93v-
+esac
+
+# Below is subshare syntax supported by both ksh93 and mksh.
+print ${ echo one }
+print ${ echo two
+}
+print ${
+echo three }
+print ${ echo 'four'; }
+print ${ echo 'five' ;}
+print ${ echo 'six'
+}
+print ${ echo 'seven' }
+echo ${ print 'eight' }
+typeset nine=${ pwd; }
+
+# Value substitutions of the form ${|command} are only
+# supported by mksh, not ksh93.
+if ! command eval '((.sh.version >= 20070703))' 2>/dev/null; then
+ valsubfunc() {
+ REPLY=$1
+ }
+ echo ${|valsubfunc ten}
+ print "${|valsubfunc eleven;}"
+ printf '%s' "${|valsubfunc twelve }"
+ unlucky=${|valsubfunc thirteen
+}
+ typeset notafloat=${|valsubfunc notanumber }
+ print $unlucky $notanumber
+ ${|echo foo}
+ ${|echo bar
+}
+fi
+
+# ======
+# Shared-state command substitutions using the syntax ${<file;}
+# are only supported by ksh93, not mksh.
+echo ${
+ printf %s str
+} > /tmp/strfile
+echo ${</tmp/strfile;}
+
+# ksh88 and ksh93 non-dot special variables
+print ${ RANDOM= SRANDOM= SHLVL= JOBMAX= KSH_VERSION= FIGNORE= LC_TIME= LC_NUMERIC= LC_MESSAGES= LC_CTYPE= LC_COLLATE= LC_ALL= LANG= FPATH= PS4= OPTIND= OPTARG= true ;}
+print $(LINENO= SECONDS= TMOUT= PPID= LINES= COLUMNS= VISUAL= OLDPWD= PS3= MAILPATH= CDPATH= FCEDIT= HISTCMD= HISTEDIT= HISTSIZE= HISTFILE= ENV= MAILCHECK= EDITOR= SHELL= false)
+print $(REPLY= MAIL= HOME= PWD= IFS= PS2= PS1= PATH= SH_OPTIONS= ERRNO= COMP_CWORD= COMP_LINE= COMP_POINT= COMP_WORDS= COMP_KEY= COMPREPLY= COMP_WORDBREAKS= COMP_TYPE= compgen)
+print $(BASHPID= EPOCHREALTIME= EXECSHELL= KSHEGID= KSHGID= KSHUID= KSH_MATCH= PATHSEP= PGRP= PIPESTATUS= TMPDIR= USER_ID= VPATH= CSWIDTH= complete)
+
+# ksh93 namespace (dot) special variables
+print $(.sh= .sh.edchar= .sh.edcol= .sh.edtext= .sh.edmode= .sh.name= .sh.subscript= .sh.value= .sh.version= .sh.match= .sh.command= .sh.file= .sh.fun= .sh.subshell= .sh.level= .sh.lineno= .sh.stats= .sh.math= .sh.pid= .sh.ppid= .sh.tilde= .sh.dollar= .sh.pool= .sh.pgrp= .sh.pwdfd= .sh.op_astbin= .sh.sig= .sh.sig.addr= .sh.sig.band= .sh.sig.code= .sh.sig.errno= .sh.sig.name= .sh.sig.pid= .sh.sig.signo= .sh.sig.status= .sh.sig.uid= .sh.sig.value= .sh.sig.value.q= .sh.sig.value.Q= .sh.stats= .sh.stats.arg_cachehits= .sh.stats.arg_expands= .sh.stats.comsubs= .sh.stats.forks= .sh.stats.funcalls= .sh.stats.globs= .sh.stats.linesread= .sh.stats.nv_cachehit= .sh.stats.nv_opens= .sh.stats.pathsearch= .sh.stats.posixfuncall= .sh.stats.simplecmds= .sh.stats.spawns= .sh.stats.subshell= .sh.install_prefix= complete)
+
+.sh.tilde.get() {
+ true
+}
+
+function .sh.tilde.set {
+ false
+}
+
+function foo() {
+ : # Bash-style function (mksh-only)
+}
+
+function foo2 {
+ : # KornShell-style function
+}
+
+foo3() {
+ : # POSIX function
+}
+
+foo4.get() {
+ : # POSIX-style ksh93 discipline function
+}
+
+function foo5.set {
+ : # KornShell-style ksh93 discipline function
+}
+
+_foo6.unset() (
+ : # POSIX-style subshell discipline function
+)
+
+namespace _foo {
+ :
+}
+
+namespace 1bad.invalid {
+ :
+}
+
+namespace foo1() {
+ : # Bad syntax
+}
+
+# Bad syntax (no name)
+function {
+ false
+}
+
+# Bad syntax also
+ () {
+ false
+}
+()
+{
+ false
+}
diff --git a/mnv/runtime/syntax/testdir/input/sh_ksh93v.ksh b/mnv/runtime/syntax/testdir/input/sh_ksh93v.ksh
new file mode 100644
index 0000000000..fe5f35e147
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_ksh93v.ksh
@@ -0,0 +1,206 @@
+#!/bin/ksh93v-
+
+# Rendering namespace variables
+echo ${.foo.bar[adsf]} ${foo.bar[1][2]} ${foo.bar[1][az]} ${.foo.bar[1][2]}
+echo ${.foo[var]} ${.foo.bar[1]} ${.foo.bar[*]} ${foo.bar##baz} ${.foo.bar##baz}
+echo ${.foo.bar[3]##baz} ${.foo.bar[z]##baz} ${sh.version/V/b} ${.sh.version/V/b}
+echo ${foo/%bar/foo} ${foo/#bar/foo} ${foo.bar/%bar/foo} ${foo.bar[d]/#bar/foo}
+echo ${.foo/%barfoo} ${.foo.bar/#bar/foo} ${.bar.foo/%bar/foo} ${.bar/#bar/foo}
+echo ${foo/%barfoo} ${foo/bar/foo} ${barfoo//bar/foo} ${bar/#bar/foo}
+echo ${.sh.version^^} ${.sh.version,,} ${KSH_VERSION^} ${KSH_VERSION,}
+
+# 'alarm' builtin (present in ksh93u+, ksh93v- and the 93u+m dev branch).
+alarm --man
+# The fds and pids builtins. These ksh93 builtins have existed since 2005-05-22
+# and 2008-06-02, respectively. However, these were not readily enabled; in
+# 93u+m these can be enabled with the builtin command if libcmd.so is present,
+# either via 'builtin -f' or (in more recent commits) with a regular invocation
+# of the 'builtin' built-in.
+# cf. https://github.com/ksh93/ksh/commit/f15e2c41
+builtin fds pids
+fds; pids
+
+# Unix commands which are provided by ksh as builtins via libcmd.so
+basename
+cat
+chgrp
+chmod
+chown
+cksum
+cmp
+comm
+cp
+cut
+date
+dirname
+egrep # Obsolescent
+expr
+fgrep # Obsolescent
+fmt
+fold
+getconf
+grep
+head
+iconv # 93v-
+id
+join
+ln
+logname
+ls # 93v-
+md5sum
+mkdir
+mkfifo
+mktemp
+mv
+od # 93v-
+paste
+pathchk
+readlink # 93v-
+realpath # 93v-
+rev
+rm
+rmdir
+sha1sum # 93v-
+sha256sum # 93v-
+sha2sum # 93v-
+sha384sum # 93v-
+sha512sum # 93v-
+stty
+sum
+sync
+tail
+tee
+tr # 93v-
+tty
+uname
+uniq
+vmstate # Obsolescent; only available in 93v- and older
+wc
+xargs # 93v-
+xgrep # Obsolescent; only 93v- allows invoking 'grep -X' as 'xgrep'
+
+# SHA command not provided as a builtin but included here for completeness
+sha224sum
+
+# poll builtin (93v-)
+poll --man
+
+# mkservice and eloop (rarely provided; requires SHOPT_MKSERVICE)
+mkservice --man; eloop --help
+
+# some mksh builtins, rename should be highlighted as an external command
+bind; rename
+
+# ;& and ;;& in case statements
+case x in
+ bar) false ${baz:1} ;&
+ foo) true ${foo:0:0} ;;&
+ *) print ${$bar} ;; # 93v-
+esac
+
+# Below is subshare syntax supported by both ksh93 and mksh.
+print ${ echo one }
+print ${ echo two
+}
+print ${
+echo three }
+print ${ echo 'four'; }
+print ${ echo 'five' ;}
+print ${ echo 'six'
+}
+print ${ echo 'seven' }
+echo ${ print 'eight' }
+typeset nine=${ pwd; }
+
+# Value substitutions of the form ${|command} are only
+# supported by mksh, not ksh93.
+if ! command eval '((.sh.version >= 20070703))' 2>/dev/null; then
+ valsubfunc() {
+ REPLY=$1
+ }
+ echo ${|valsubfunc ten}
+ print "${|valsubfunc eleven;}"
+ printf '%s' "${|valsubfunc twelve }"
+ unlucky=${|valsubfunc thirteen
+}
+ typeset notafloat=${|valsubfunc notanumber }
+ print $unlucky $notanumber
+ ${|echo foo}
+ ${|echo bar
+}
+fi
+
+# ======
+# Shared-state command substitutions using the syntax ${<file;}
+# are only supported by ksh93, not mksh.
+echo ${
+ printf %s str
+} > /tmp/strfile
+echo ${</tmp/strfile;}
+
+# ksh88 and ksh93 non-dot special variables
+print ${ RANDOM= SRANDOM= SHLVL= JOBMAX= KSH_VERSION= FIGNORE= LC_TIME= LC_NUMERIC= LC_MESSAGES= LC_CTYPE= LC_COLLATE= LC_ALL= LANG= FPATH= PS4= OPTIND= OPTARG= true ;}
+print $(LINENO= SECONDS= TMOUT= PPID= LINES= COLUMNS= VISUAL= OLDPWD= PS3= MAILPATH= CDPATH= FCEDIT= HISTCMD= HISTEDIT= HISTSIZE= HISTFILE= ENV= MAILCHECK= EDITOR= SHELL= false)
+print $(REPLY= MAIL= HOME= PWD= IFS= PS2= PS1= PATH= SH_OPTIONS= ERRNO= COMP_CWORD= COMP_LINE= COMP_POINT= COMP_WORDS= COMP_KEY= COMPREPLY= COMP_WORDBREAKS= COMP_TYPE= compgen)
+print $(BASHPID= EPOCHREALTIME= EXECSHELL= KSHEGID= KSHGID= KSHUID= KSH_MATCH= PATHSEP= PGRP= PIPESTATUS= TMPDIR= USER_ID= VPATH= CSWIDTH= complete)
+
+# ksh93 namespace (dot) special variables
+print $(.sh= .sh.edchar= .sh.edcol= .sh.edtext= .sh.edmode= .sh.name= .sh.subscript= .sh.value= .sh.version= .sh.match= .sh.command= .sh.file= .sh.fun= .sh.subshell= .sh.level= .sh.lineno= .sh.stats= .sh.math= .sh.pid= .sh.ppid= .sh.tilde= .sh.dollar= .sh.pool= .sh.pgrp= .sh.pwdfd= .sh.op_astbin= .sh.sig= .sh.sig.addr= .sh.sig.band= .sh.sig.code= .sh.sig.errno= .sh.sig.name= .sh.sig.pid= .sh.sig.signo= .sh.sig.status= .sh.sig.uid= .sh.sig.value= .sh.sig.value.q= .sh.sig.value.Q= .sh.stats= .sh.stats.arg_cachehits= .sh.stats.arg_expands= .sh.stats.comsubs= .sh.stats.forks= .sh.stats.funcalls= .sh.stats.globs= .sh.stats.linesread= .sh.stats.nv_cachehit= .sh.stats.nv_opens= .sh.stats.pathsearch= .sh.stats.posixfuncall= .sh.stats.simplecmds= .sh.stats.spawns= .sh.stats.subshell= .sh.install_prefix= complete)
+
+.sh.tilde.get() {
+ true
+}
+
+function .sh.tilde.set {
+ false
+}
+
+function foo() {
+ : # Bash-style function (mksh-only)
+}
+
+function foo2 {
+ : # KornShell-style function
+}
+
+foo3() {
+ : # POSIX function
+}
+
+foo4.get() {
+ : # POSIX-style ksh93 discipline function
+}
+
+function foo5.set {
+ : # KornShell-style ksh93 discipline function
+}
+
+_foo6.unset() (
+ : # POSIX-style subshell discipline function
+)
+
+namespace _foo {
+ :
+}
+
+namespace 1bad.invalid {
+ :
+}
+
+namespace foo1() {
+ : # Bad syntax
+}
+
+# Bad syntax (no name)
+function {
+ false
+}
+
+# Bad syntax also
+ () {
+ false
+}
+()
+{
+ false
+}
diff --git a/mnv/runtime/syntax/testdir/input/sh_ksh_array.sh b/mnv/runtime/syntax/testdir/input/sh_ksh_array.sh
new file mode 100644
index 0000000000..22806ffc5c
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_ksh_array.sh
@@ -0,0 +1,21 @@
+#!/bin/ksh
+
+foo=(
+ ( 00 01 )
+ ( 10 11 )
+)
+
+bar=(
+ [0]=(
+ [0]=00
+ [1]=01
+ )
+ [1]=(
+ [0]=10
+ [1]=11
+ )
+)
+
+
+echo ${foo[1][1]} # => 11
+echo ${bar[1][1]} # => 11
diff --git a/mnv/runtime/syntax/testdir/input/sh_mksh.ksh b/mnv/runtime/syntax/testdir/input/sh_mksh.ksh
new file mode 100644
index 0000000000..4396bc269e
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_mksh.ksh
@@ -0,0 +1,206 @@
+#!/bin/mksh
+
+# Rendering namespace variables
+echo ${.foo.bar[adsf]} ${foo.bar[1][2]} ${foo.bar[1][az]} ${.foo.bar[1][2]}
+echo ${.foo[var]} ${.foo.bar[1]} ${.foo.bar[*]} ${foo.bar##baz} ${.foo.bar##baz}
+echo ${.foo.bar[3]##baz} ${.foo.bar[z]##baz} ${sh.version/V/b} ${.sh.version/V/b}
+echo ${foo/%bar/foo} ${foo/#bar/foo} ${foo.bar/%bar/foo} ${foo.bar[d]/#bar/foo}
+echo ${.foo/%barfoo} ${.foo.bar/#bar/foo} ${.bar.foo/%bar/foo} ${.bar/#bar/foo}
+echo ${foo/%barfoo} ${foo/bar/foo} ${barfoo//bar/foo} ${bar/#bar/foo}
+echo ${.sh.version^^} ${.sh.version,,} ${KSH_VERSION^} ${KSH_VERSION,}
+
+# 'alarm' builtin (present in ksh93u+, ksh93v- and the 93u+m dev branch).
+alarm --man
+# The fds and pids builtins. These ksh93 builtins have existed since 2005-05-22
+# and 2008-06-02, respectively. However, these were not readily enabled; in
+# 93u+m these can be enabled with the builtin command if libcmd.so is present,
+# either via 'builtin -f' or (in more recent commits) with a regular invocation
+# of the 'builtin' built-in.
+# cf. https://github.com/ksh93/ksh/commit/f15e2c41
+builtin fds pids
+fds; pids
+
+# Unix commands which are provided by ksh as builtins via libcmd.so
+basename
+cat
+chgrp
+chmod
+chown
+cksum
+cmp
+comm
+cp
+cut
+date
+dirname
+egrep # Obsolescent
+expr
+fgrep # Obsolescent
+fmt
+fold
+getconf
+grep
+head
+iconv # 93v-
+id
+join
+ln
+logname
+ls # 93v-
+md5sum
+mkdir
+mkfifo
+mktemp
+mv
+od # 93v-
+paste
+pathchk
+readlink # 93v-
+realpath # 93v-
+rev
+rm
+rmdir
+sha1sum # 93v-
+sha256sum # 93v-
+sha2sum # 93v-
+sha384sum # 93v-
+sha512sum # 93v-
+stty
+sum
+sync
+tail
+tee
+tr # 93v-
+tty
+uname
+uniq
+vmstate # Obsolescent; only available in 93v- and older
+wc
+xargs # 93v-
+xgrep # Obsolescent; only 93v- allows invoking 'grep -X' as 'xgrep'
+
+# SHA command not provided as a builtin but included here for completeness
+sha224sum
+
+# poll builtin (93v-)
+poll --man
+
+# mkservice and eloop (rarely provided; requires SHOPT_MKSERVICE)
+mkservice --man; eloop --help
+
+# some mksh builtins, rename should be highlighted as an external command
+bind; rename
+
+# ;& and ;;& in case statements
+case x in
+ bar) false ${baz:1} ;&
+ foo) true ${foo:0:0} ;;&
+ *) print ${$bar} ;; # 93v-
+esac
+
+# Below is subshare syntax supported by both ksh93 and mksh.
+print ${ echo one }
+print ${ echo two
+}
+print ${
+echo three }
+print ${ echo 'four'; }
+print ${ echo 'five' ;}
+print ${ echo 'six'
+}
+print ${ echo 'seven' }
+echo ${ print 'eight' }
+typeset nine=${ pwd; }
+
+# Value substitutions of the form ${|command} are only
+# supported by mksh, not ksh93.
+if ! command eval '((.sh.version >= 20070703))' 2>/dev/null; then
+ valsubfunc() {
+ REPLY=$1
+ }
+ echo ${|valsubfunc ten}
+ print "${|valsubfunc eleven;}"
+ printf '%s' "${|valsubfunc twelve }"
+ unlucky=${|valsubfunc thirteen
+}
+ typeset notafloat=${|valsubfunc notanumber }
+ print $unlucky $notanumber
+ ${|echo foo}
+ ${|echo bar
+}
+fi
+
+# ======
+# Shared-state command substitutions using the syntax ${<file;}
+# are only supported by ksh93, not mksh.
+echo ${
+ printf %s str
+} > /tmp/strfile
+echo ${</tmp/strfile;}
+
+# ksh88 and ksh93 non-dot special variables
+print ${ RANDOM= SRANDOM= SHLVL= JOBMAX= KSH_VERSION= FIGNORE= LC_TIME= LC_NUMERIC= LC_MESSAGES= LC_CTYPE= LC_COLLATE= LC_ALL= LANG= FPATH= PS4= OPTIND= OPTARG= true ;}
+print $(LINENO= SECONDS= TMOUT= PPID= LINES= COLUMNS= VISUAL= OLDPWD= PS3= MAILPATH= CDPATH= FCEDIT= HISTCMD= HISTEDIT= HISTSIZE= HISTFILE= ENV= MAILCHECK= EDITOR= SHELL= false)
+print $(REPLY= MAIL= HOME= PWD= IFS= PS2= PS1= PATH= SH_OPTIONS= ERRNO= COMP_CWORD= COMP_LINE= COMP_POINT= COMP_WORDS= COMP_KEY= COMPREPLY= COMP_WORDBREAKS= COMP_TYPE= compgen)
+print $(BASHPID= EPOCHREALTIME= EXECSHELL= KSHEGID= KSHGID= KSHUID= KSH_MATCH= PATHSEP= PGRP= PIPESTATUS= TMPDIR= USER_ID= VPATH= CSWIDTH= complete)
+
+# ksh93 namespace (dot) special variables
+print $(.sh= .sh.edchar= .sh.edcol= .sh.edtext= .sh.edmode= .sh.name= .sh.subscript= .sh.value= .sh.version= .sh.match= .sh.command= .sh.file= .sh.fun= .sh.subshell= .sh.level= .sh.lineno= .sh.stats= .sh.math= .sh.pid= .sh.ppid= .sh.tilde= .sh.dollar= .sh.pool= .sh.pgrp= .sh.pwdfd= .sh.op_astbin= .sh.sig= .sh.sig.addr= .sh.sig.band= .sh.sig.code= .sh.sig.errno= .sh.sig.name= .sh.sig.pid= .sh.sig.signo= .sh.sig.status= .sh.sig.uid= .sh.sig.value= .sh.sig.value.q= .sh.sig.value.Q= .sh.stats= .sh.stats.arg_cachehits= .sh.stats.arg_expands= .sh.stats.comsubs= .sh.stats.forks= .sh.stats.funcalls= .sh.stats.globs= .sh.stats.linesread= .sh.stats.nv_cachehit= .sh.stats.nv_opens= .sh.stats.pathsearch= .sh.stats.posixfuncall= .sh.stats.simplecmds= .sh.stats.spawns= .sh.stats.subshell= .sh.install_prefix= complete)
+
+.sh.tilde.get() {
+ true
+}
+
+function .sh.tilde.set {
+ false
+}
+
+function foo() {
+ : # Bash-style function (mksh-only)
+}
+
+function foo2 {
+ : # KornShell-style function
+}
+
+foo3() {
+ : # POSIX function
+}
+
+foo4.get() {
+ : # POSIX-style ksh93 discipline function
+}
+
+function foo5.set {
+ : # KornShell-style ksh93 discipline function
+}
+
+_foo6.unset() (
+ : # POSIX-style subshell discipline function
+)
+
+namespace _foo {
+ :
+}
+
+namespace 1bad.invalid {
+ :
+}
+
+namespace foo1() {
+ : # Bad syntax
+}
+
+# Bad syntax (no name)
+function {
+ false
+}
+
+# Bad syntax also
+ () {
+ false
+}
+()
+{
+ false
+}
diff --git a/mnv/runtime/syntax/testdir/input/sh_mksh_gibberish.ksh b/mnv/runtime/syntax/testdir/input/sh_mksh_gibberish.ksh
new file mode 100644
index 0000000000..a731abf618
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_mksh_gibberish.ksh
@@ -0,0 +1,126 @@
+#!/bin/mksh
+# Welcome to mksh wild west gibberish!
+
+# Valid function names
+
+function 7fo@o.f() {
+ echo "Gibberish not-KornShell function (the ending '()' is a bashism mksh allows)"
+}
+!:@-+.8vfo%o,_() {
+ echo 'Gibberish POSIX function'
+}
+
+,() {
+ foo
+}
+
+function a%a() {
+ foo
+}
+
+%() {
+ foo
+}
+
+.() {
+ foo
+}
+
+-() {
+ foo
+}
+
+_() {
+ foo
+}
+
++a() {
+ foo
+}
+
+.b() {
+ foo
+}
+
+!a() {
+ foo
+}
+
+@a() {
+ foo
+}
+
+!!a() {
+ foo
+}
+
+!a!a() {
+ foo
+}
+
+@a@@a() {
+ foo
+}
+
++a+a() {
+ foo
+}
+
+a:() {
+ foo
+}
+
+# Invalid function names
+@a@() {
+ foo
+}
+
+@() {
+ foo
+}
+
+@@() {
+ foo
+}
+
+a@() {
+ foo
+}
+
+!() {
+ foo
+}
+
+!!() {
+ foo
+}
+
+!a!() {
+ foo
+}
+
++() {
+ foo
+}
+
+++() {
+ foo
+}
+
++a+() {
+ foo
+}
+
+-#a() {
+ foo
+}
+
+-?a() {
+ foo
+}
+
+ () {
+ no name
+}
+
+!:@-+.8vfo%o,_
diff --git a/mnv/runtime/syntax/testdir/input/sh_quoting.sh b/mnv/runtime/syntax/testdir/input/sh_quoting.sh
new file mode 100644
index 0000000000..dc6a5152f1
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_quoting.sh
@@ -0,0 +1,4 @@
+#!/bin/dash
+
+echo ${foo:-'string \'}
+
diff --git a/mnv/runtime/syntax/testdir/input/sh_sundrous.bash b/mnv/runtime/syntax/testdir/input/sh_sundrous.bash
new file mode 100644
index 0000000000..2f4df51f2b
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sh_sundrous.bash
@@ -0,0 +1,58 @@
+#!/bin/bash
+basename
+cat
+chgrp
+chmod
+chown
+cksum
+cmp
+comm
+cp
+cut
+date
+dirname
+egrep # Obsolescent
+expr
+fgrep # Obsolescent
+fmt
+fold
+getconf
+grep
+head
+iconv
+id
+join
+ln
+logname
+ls
+md5sum
+mkdir
+mkfifo
+mktemp
+mv
+od
+paste
+pathchk
+readlink
+realpath
+rev
+rm
+rmdir
+sha1sum
+sha256sum
+sha224sum
+sha384sum
+sha512sum
+stty
+sum
+sync
+tail
+tee
+tr
+tty
+uname
+uniq
+wc
+xargs
+# xgrep is neither a builtin for bash nor an external program
+xgrep
diff --git a/mnv/runtime/syntax/testdir/input/skhdrc.skhdrc b/mnv/runtime/syntax/testdir/input/skhdrc.skhdrc
new file mode 100644
index 0000000000..60911562c9
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/skhdrc.skhdrc
@@ -0,0 +1,104 @@
+# skhd configuration file
+# This is a comment
+
+# Basic key bindings with modifiers
+alt - h : yabai -m window --focus west
+shift + cmd - j : yabai -m window --focus south
+ctrl + alt + shift - k : yabai -m window --focus north
+fn - l : yabai -m window --focus east
+
+# Using hex keycodes
+cmd - 0x2A : open -a "Finder"
+
+# Function keys
+cmd - f1 : echo "F1 pressed"
+alt - f12 : echo "F12 pressed"
+
+# Special keys
+cmd - return : open -a "Terminal"
+alt - tab : yabai -m window --focus recent
+ctrl - escape : yabai -m space --balance
+shift - delete : rm -rf ~/.Trash/*
+cmd - space : open -a "Spotlight"
+
+# Arrow keys
+alt - left : yabai -m window --focus west
+alt - right : yabai -m window --focus east
+alt - up : yabai -m window --focus north
+alt - down : yabai -m window --focus south
+
+# Media keys
+cmd - sound_up : osascript -e "set volume output volume 100"
+cmd - mute : osascript -e "set volume output muted true"
+cmd - play : osascript -e "tell app \"Music\" to playpause"
+cmd - brightness_up : echo "brightness up"
+
+# yabai subcommands
+alt - w : yabai -m window --close
+alt - s : yabai -m space --create
+alt - d : yabai -m display --focus next
+
+# Mode definitions
+:: default : yabai -m config active_window_border_color 0xff775759
+:: resize @ : yabai -m config active_window_border_color 0xffd75f5f
+
+# Mode switching
+default < alt - r ; resize
+resize < escape ; default
+resize < alt - r ; default
+
+# Mode with passthrough
+:: passthrough
+
+passthrough < cmd + shift + alt - p ; default
+
+# Application-specific bindings
+alt - t [
+ "iTerm2" : echo "iTerm2 specific"
+ "Google Chrome" : echo "Chrome specific"
+ * : open -a "Terminal"
+]
+
+ctrl - n [
+ "Finder" : open -a "Notes"
+ * ~
+]
+
+# .blacklist directive
+.blacklist [
+ "Alfred"
+ "1Password"
+]
+
+# .load directive
+.load "/path/to/other/skhdrc"
+
+# Multi-line command with backslash continuation
+alt + shift - m : yabai -m window --toggle zoom-fullscreen; \
+ yabai -m window --toggle border
+
+# Complex binding with subcommands
+hyper - 1 : yabai -m window --space 1; \
+ yabai -m space --focus 1
+
+# Using lalt, ralt, lcmd, rcmd, lshift, rshift, lctrl, rctrl
+lalt - a : echo "left alt"
+ralt - a : echo "right alt"
+lcmd - b : echo "left cmd"
+rcmd - b : echo "right cmd"
+lshift - c : echo "left shift"
+rshift - c : echo "right shift"
+lctrl - d : echo "left ctrl"
+rctrl - d : echo "right ctrl"
+
+# Meh and hyper modifiers
+meh - x : echo "meh (ctrl+alt+shift)"
+hyper - y : echo "hyper (ctrl+alt+shift+cmd)"
+
+# Additional modifiers: option and super are aliases
+option - z : echo "option is alt alias"
+super - z : echo "super is cmd alias"
+
+# End of configuration
+
+# mnv:ft=skhd:
diff --git a/mnv/runtime/syntax/testdir/input/sml.sml b/mnv/runtime/syntax/testdir/input/sml.sml
new file mode 100644
index 0000000000..dab0b82b92
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sml.sml
@@ -0,0 +1,71 @@
+(* Integer constants *)
+
+val _ = 0;
+val _ = 42;
+val _ = 0x2A;
+val _ = ~42; (* single token *)
+val _ = ~0x2A; (* single token *)
+
+
+(* Word constants *)
+
+val _ = 0w0;
+val _ = 0w42;
+val _ = 0wx2A;
+val _ = ~0w42; (* nonfix ~ *)
+val _ = ~0wx2A; (* nonfix ~ *)
+
+
+(* Real constants *)
+
+val _ = 0.0;
+val _ = 42.42;
+val _ = 42E42;
+val _ = 42E~42;
+val _ = 42.42E42;
+val _ = 42.42E~42;
+val _ = ~42.42; (* single token *)
+val _ = ~42.42; (* single token *)
+val _ = ~42E42; (* single token *)
+val _ = ~42E~42; (* single token *)
+val _ = ~42.42E42; (* single token *)
+val _ = ~42.42E~42; (* single token *)
+
+
+(* Character constants *)
+
+val _ = #"a";
+val _ = #"\a";
+val _ = #"\b";
+val _ = #"\t";
+val _ = #"\n";
+val _ = #"\v";
+val _ = #"\f";
+val _ = #"\r";
+val _ = #"\"";
+val _ = #"\\";
+val _ = #"\^@";
+val _ = #"\^A";
+val _ = #"\^K";
+val _ = #"\^Z";
+val _ = #"\^[";
+val _ = #"\^\";
+val _ = #"\^]";
+val _ = #"\^^";
+val _ = #"\^_";
+val _ = #"\000";
+val _ = #"\999";
+val _ = #"\u0000";
+val _ = #"\uFFFF";
+
+
+(* String constants *)
+
+val _ = "";
+val _ = "abc";
+val _ = "...\a...\b...\t...\n...\v...\f...\r...\"...\\...";
+val _ = "...\^@...\^A...\^K...\^Z...\^[...\^\...\^]...\^^...\^_...";
+val _ = "\000...\999...\u0000...\uFFFF...";
+val _ = "...\
+ \...";
+
diff --git a/mnv/runtime/syntax/testdir/input/sudoers_Defaults.sudoers b/mnv/runtime/syntax/testdir/input/sudoers_Defaults.sudoers
new file mode 100644
index 0000000000..0c7faf4ca9
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sudoers_Defaults.sudoers
@@ -0,0 +1,43 @@
+# vi:ft=sudoers
+Host_Alias NODES = ! node0, 192.168.10.1
+User_Alias ADMIN = alice, bob
+Cmnd_Alias MNV = /usr/bin/mnv, sha224:d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f /usr/bin/view, sha256:47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU= /usr/bin/mnvdiff
+Runas_Alias ROOT = charlie, dave
+
+# Boolean Flags
+Defaults authenticate
+Defaults@ ALL, NODES case_insensitive_group , ! case_insensitive_user
+Defaults@!node0, !node1 !! env_reset
+Defaults@10.0.0.1 , !172.16.0.1/12, !!192.168.0.1/255.255.0.0 !! fqdn
+Defaults:ALL, ADMIN ignore_dot
+Defaults:user0, #1000, %group0, %#1000 mail_all_cmnds
+Defaults!ALL,MNV noexec
+Defaults!list,sudoedit !path_info
+Defaults! /bin/ls requiretty
+Defaults!!/bin/less , /bin/more set_home
+Defaults> ALL,ROOT !setenv
+Defaults>!user0,!!#1000,!!!%group0,!!!!%#1000 !!!!! syslog_pid
+
+# Integers
+Defaults command_timeout=1, command_timeout=22s, command_timeout=33m, command_timeout=44h, command_timeout=55d, command_timeout=6D7H8M9S
+Defaults:ALL passwd_tries = 3, passwd_timeout = 2.5, umask = 0027
+Defaults@ALL ! passwd_timeout , !!! umask
+
+# Strings
+Defaults editor = "/usr/bin/mnv:/bin/vi"
+Defaults secure_path = /usr/sbin\:/usr/bin
+Defaults>ALL syslog_badpri=alert,syslog_goodpri=notice
+
+# Lists
+Defaults env_check = TZ
+Defaults env_delete += "PATH *PATH"
+Defaults env_keep -= "XDG_*_HOME"
+Defaults>ALL !!!!! env_keep
+
+Defaults passprompt_regex = "[Pp]assword[: ]*"
+Defaults passprompt_regex -= "(?i)PASSWORD"
+Defaults passprompt_regex += "password"
+
+# Directives
+@includedir /etc/sudoers.d
+#include /etc/sudoers.d/%h
diff --git a/mnv/runtime/syntax/testdir/input/sudoers_user-spec.sudoers b/mnv/runtime/syntax/testdir/input/sudoers_user-spec.sudoers
new file mode 100644
index 0000000000..19e79212c4
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/sudoers_user-spec.sudoers
@@ -0,0 +1,43 @@
+# vi:ft=sudoers
+ALL ALL = ALL
+ALL ALL = NOSETENV : ALL
+ALL ALL = CWD = * ALL
+ALL ALL = (ALL) ALL
+ALL ALL = (ALL) ALL
+ALL ALL = (ALL) NOSETENV : ALL
+ALL ALL = (ALL) CWD = * ALL
+ALL ALL = (ALL) CWD = * NOSETENV : ALL
+
+!user0, %group0 ALL = (user0, !user1 : !group0, group1) ALL
+#1000, %#1000 ALL = (#1000 : #1000) ALL
+ALL ALL = ( ) ALL
+ALL ALL = (ALL ) ALL
+ALL ALL = ( : ) ALL
+ALL ALL = ( :ALL) ALL
+ALL ALL = (ALL:ALL) ALL
+
+ALL node0 , ! node1 = ALL : ! node2 , node3 = (ALL:ALL) CWD=/ ALL
+
+user0 node0 = APPARMOR_PROFILE=unconfined /bin/pwd ""
+user1 node1 = (root) APPARMOR_PROFILE=prof_a//&prof_b NOEXEC: /bin/ping
+
+user0 node0 = PRIVS="proc_info,proc_session" /bin/kill
+
+#1000 node0 = NOTBEFORE= 2026013123 NOTAFTER = 20270131235959 /bin/crontab
+#1001 node1 = () NOTAFTER = 20270131235959Z NOTBEFORE= 2026013123Z MAIL : /bin/crontab
+#1002 node2 = (ALL) NOTBEFORE= 20260131235959-1200 NOTAFTER = 2027013123+1400 /bin/crontab
+
+%group0 node0 = TIMEOUT = 1 /bin/more
+%group1 node0 = TIMEOUT = 2s /bin/more, (ALL:ALL) TIMEOUT=2S NOFOLLOW: /bin/less
+%group2 node0 = TIMEOUT = 3m /bin/more, (ALL:ALL) TIMEOUT=3M NOFOLLOW: /bin/less
+%group3 node0 = TIMEOUT = 4h /bin/more, (ALL:ALL) TIMEOUT=4H NOFOLLOW: /bin/less
+%group4 node0 = TIMEOUT = 5d /bin/more, (ALL:ALL) TIMEOUT=5D NOFOLLOW: /bin/less
+%group5 node0 = TIMEOUT = 1D2h3M4s /bin/more, (ALL:ALL) TIMEOUT=1d2H3m4S NOFOLLOW: /bin/less
+
+%#1000 node0 = CWD=/srv list
+%#1001 node0 = ( ) CWD=~root list
+%#1002 node0 = (:ALL) CWD=* NOEXEC : list
+
+#65535 ALL = (ALL) NOEXEC:NOFOLLOW:NOLOG_INPUT:NOMAIL:NOINTERCEPT:NOPASSWD:NOSETENV: sudoedit
+
+ALL ALL = (ALL:ALL) TIMEOUT=1m CWD=* FOLLOW : ^/bin/[ef]?grep$
diff --git a/mnv/runtime/syntax/testdir/input/tcsh.tcsh b/mnv/runtime/syntax/testdir/input/tcsh.tcsh
new file mode 100644
index 0000000000..1dfc1fd296
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/tcsh.tcsh
@@ -0,0 +1,6 @@
+# https://github.com/Project-Tick/Project-Tick/pull/19172#issuecomment-3751574224
+
+set script_dir="" #comment
+set script_dir=""
+set script_dir="" #
+
diff --git a/mnv/runtime/syntax/testdir/input/tera.tera b/mnv/runtime/syntax/testdir/input/tera.tera
new file mode 100644
index 0000000000..161793c963
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/tera.tera
@@ -0,0 +1,165 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="UTF-8">
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
+ <title>{{ page_title | default(value="Tera Test") }}</title>
+ {% if include_styles %}
+ <style>
+ body {
+ font-family: {{ font_family | default(value="sans-serif") }};
+ color: #333;
+ line-height: 1.6;
+ }
+ .container {
+ width: 80%;
+ margin: 0 auto;
+ }
+ {% if dark_mode %}
+ body {
+ background-color: #222;
+ color: #eee;
+ }
+ {% endif %}
+ </style>
+ {% endif %}
+</head>
+<body>
+ <div class="container">
+ {# Header Section with variable interpolation #}
+ <header>
+ <h1>{{ header_text | upper }}</h1>
+ {% if subheader %}
+ <h2>{{ subheader }}</h2>
+ {% endif %}
+ </header>
+
+ {# Navigation example with for loop #}
+ <nav>
+ <ul>
+ {% for item in navigation %}
+ <li class="{{ loop.index0 == current_page ? 'active' : '' }}">
+ <a href="{{ item.url }}">{{ item.title }}</a>
+ </li>
+ {% endfor %}
+ </ul>
+ </nav>
+
+ {# Main content section with various template features #}
+ <main>
+ {# Conditionals #}
+ {% if user %}
+ <section class="welcome">
+ <h2>Welcome back, {{ user.name }}!</h2>
+ <p>Last login: {{ user.last_login | date(format="%Y-%m-%d") }}</p>
+ </section>
+ {% elif visitor_count > 0 %}
+ <section class="welcome">
+ <h2>Welcome, visitor!</h2>
+ <p>You are visitor number {{ visitor_count }}</p>
+ </section>
+ {% else %}
+ <section class="welcome">
+ <h2>Welcome to our site!</h2>
+ </section>
+ {% endif %}
+
+ {# Macro definition and usage #}
+ {% macro render_item(item, featured=false) %}
+ <div class="item {{ featured ? 'featured' : '' }}">
+ <h3>{{ item.title }}</h3>
+ <p>{{ item.description | truncate(length=100) }}</p>
+ {% if item.tags %}
+ <div class="tags">
+ {% for tag in item.tags %}
+ <span class="tag">{{ tag }}</span>
+ {% endfor %}
+ </div>
+ {% endif %}
+ </div>
+ {% endmacro render_item %}
+
+ {# Items section with macro usage #}
+ <section class="items">
+ <h2>Items ({{ items | length }})</h2>
+
+ {% for item in items %}
+ {{ self::render_item(item=item, featured=item.id == featured_id) }}
+
+ {% if not loop.last %}
+ <hr>
+ {% endif %}
+ {% endfor %}
+ </section>
+
+ {# Raw content that shouldn't be processed #}
+ {% raw %}
+ <div class="example">
+ The syntax {{ variable }} will not be processed in raw blocks.
+ Neither will {% control %} structures.
+ </div>
+ {% endraw %}
+
+ {# Includes #}
+ {% include "partials/footer.tera" %}
+
+ {# Inheritance example #}
+ {% block content %}
+ <p>This is the default content.</p>
+ {% endblock content %}
+
+ {# Set variables #}
+ {% set text_color = dark_mode ? "#fff" : "#333" %}
+ {% set items_count = items | length %}
+
+ <div style="color: {{ text_color }}">
+ We have {{ items_count }} items.
+ </div>
+
+ {# Filters with complex expressions #}
+ <p>{{ "Hello, " ~ user.name | default(value="Guest") | upper }}</p>
+ <p>{{ items | filter(attribute="featured", value=true) | length }} featured items</p>
+
+ {# With statement #}
+ {% with %}
+ {% set local_var = "Only visible in this scope" %}
+ <p>{{ local_var }}</p>
+ {% endwith %}
+
+ {# Mathematical operations #}
+ <div class="math">
+ <p>Price: ${{ price }}</p>
+ <p>Tax ({{ tax_rate * 100 }}%): ${{ price * tax_rate }}</p>
+ <p>Total: ${{ price * (1 + tax_rate) }}</p>
+ </div>
+
+ {# Boolean operations #}
+ {% if user and user.is_admin or super_user %}
+ <div class="admin-panel">Admin panel</div>
+ {% endif %}
+ </main>
+
+ {# Footer section with filters and includes #}
+ <footer>
+ <p>&copy; {{ current_year }} {{ company_name | default(value="Our Company") }}</p>
+
+ {% if debug %}
+ <div class="debug-info">
+ <p>Render time: {{ render_time }}ms</p>
+ <p>Template version: {{ version }}</p>
+ </div>
+ {% endif %}
+ </footer>
+ </div>
+
+ <script>
+ const appData = {
+ "user": {% if user %}{{ user | json_encode() }}{% else %}null{% endif %},
+ "settings": {
+ "theme": "{{ theme | default(value="light") }}",
+ "notifications": {{ notifications_enabled | string | lower }}
+ }
+ };
+ </script>
+</body>
+</html>
diff --git a/mnv/runtime/syntax/testdir/input/tex_01.tex b/mnv/runtime/syntax/testdir/input/tex_01.tex
new file mode 100644
index 0000000000..7153d0f1a9
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/tex_01.tex
@@ -0,0 +1,14 @@
+\documentclass{article}
+\begin{document}
+\texttt{test}
+(\texttt{test})
+( \texttt{test} )
+\texttt{test})
+((blahblah)\\
+\texttt{test}
+\texttt{test}
+)
+(lorem ipsum)
+\texttt{test}
+( \textit{test} \textbf{test})
+\end{document}
diff --git a/mnv/runtime/syntax/testdir/input/tex_02.tex b/mnv/runtime/syntax/testdir/input/tex_02.tex
new file mode 100644
index 0000000000..0d6e92a218
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/tex_02.tex
@@ -0,0 +1,11 @@
+\documentclass{article}
+\newcommand{\foo}{}
+\renewcommand*{\foo}[1]{#10}
+\providecommand{\foo}[1][default]{#11}
+\newenvironment*{baz}{START}{STOP}
+\renewenvironment{baz}[1]{HEAD of #12:}{TAIL}
+\renewenvironment*{baz}[1][default]{BEGINNING of #12:}{END}
+\begin{document}
+\foo{TeX} % -> TeX0
+\begin{baz} tex \end{baz} % -> BEGINNING of default2:tex END
+\end{document}
diff --git a/mnv/runtime/syntax/testdir/input/tex_03.tex b/mnv/runtime/syntax/testdir/input/tex_03.tex
new file mode 100644
index 0000000000..25d57eab3f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/tex_03.tex
@@ -0,0 +1,11 @@
+\documentclass{article}
+\usepackage{amsmath}
+\begin{document}
+\begin{align}
+ \begin{bmatrix}
+ 1 & x & x^{2} \\
+ 1 & y & y^{2} \\
+ 1 & z & z^{2} \\
+ \end{bmatrix}
+\end{align}
+\end{document}
diff --git a/mnv/runtime/syntax/testdir/input/yaml.yaml b/mnv/runtime/syntax/testdir/input/yaml.yaml
new file mode 100644
index 0000000000..72e0a0dd4f
--- /dev/null
+++ b/mnv/runtime/syntax/testdir/input/yaml.yaml
@@ -0,0 +1,128 @@
+%YAML 1.2
+%TAG ! tag:yaml.org,2002: # primary tag handle
+%TAG !! tag:yaml.org,2002: # secondary tag handle
+%TAG !yaml! tag:yaml.org,2002: # named tag handle
+---
+- !str 0 # primary tag handle
+- !!str 0 # secondary tag handle
+- !yaml!str 0 # named tag handle
+---
+
+boolean: [false, true, FALSE, TRUE, False, True]
+null: [null, ~,]
+integer: [12345, -12_345, +12_345]
+float: [
+ 12345.15, -12_345.15, +12_345.15, 1.23015e+3,
+ -12_345.15e+10, +12_345.15e-10, 1.234_515e-10
+]
+binary: [0b101010, -0b1010_1010, +0b1010_1010]
+octal: [0777, 0o777, +0777, -0o777]
+hexadecimal: [0xFEFF_0000, -0xabcd_ef00, +0x1234_5678]
+sexagesimal: [10:20:30, -19:29:39, +19:29:39]
+infinity: [.inf, -.Inf, +.INF]
+not a number: [.nan, .NaN, .NAN]
+
+plain strings:
+ - a b c
+ - a:b & c @ d# e * f # comment
+ - {{ f(' ') }} #8234
+double quoted strings:
+ - ""
+ - "a b c": "d e f" # comment
+ - "\\\"\a\b\f\n\r\t\v\0\_\ \N\L\P\x41\u0041\U00000041"
+single quoted strings:
+ - ''
+ - 'a b c': 'd e f' # comment
+ - 'a''b''c'
+
+block folded string: >
+ foo
+ bar: 1
+
+ baz: null
+
+ "qux"
+block literal string: |
+ foo
+ bar: 1
+
+ baz: null
+
+ 'qux'
+
+chomping strings:
+ - block folded string: >- # comment
+ foo
+ bar: 1
+ - block literal string: |+ # comment
+ foo
+ bar: 1
+ - |- #11517
+ foo "\"
+ bar: 1
+block indentation indicator:
+ - block folded string: >1 # comment
+ foo
+ bar: 1
+ - block literal string: |1- # comment
+ foo
+ bar: 1
+ - |-1 # comment
+ foo
+ bar: 1
+
+flow collection:
+ empty sequence: []
+ empty mapping: {}
+ flow sequence: [foo, bar, baz]
+ flow mapping: {foo: bar, baz: qux}
+ flow string:
+ foo
+ bar
+ baz
+ "double quoted \" string": "
+ foo
+ bar
+ baz"
+ 'single quoted '' string': '
+ foo
+ bar
+ baz'
+ inside block mapping:
+ foo: {bar: baz}
+ bar: ["foo": {baz: qux}]
+ flow:collection: [foo # comment
+ , {bar: [{ # comment
+ baz:
+ '
+ qux # not comment
+ ' # comment
+ }]}]
+
+explicit mapping:
+ ? foo # comment
+ : bar # comment
+ ? - foo
+ - bar
+ : - baz
+ - qux
+ ? [1, 2, 3]
+ : ? 1
+ : one
+ ? 2
+ : - ? 3
+ : three
+ - {?4: four, ? 5: five, ? # comment
+ 6: # comment
+ {7:seven}}
+
+mapping merge:
+ foo: &foo
+ bar: baz
+ bar:
+ <<: *foo
+ baz: &bar
+ foo: [*foo]
+ qux:
+ <<: [*foo, *bar]
+ baz: {<<: *foo, qux: [{<< : *foo}]}