From: Jon Parise Date: Sun, 30 Nov 2025 14:45:48 +0000 (+0000) Subject: patch 9.1.1936: filetype: Erlang lexical files are not recognized X-Git-Tag: v9.1.1936^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b087c5452b4c12bfc9e7f6cecbee34aab64c92d8;p=thirdparty%2Fvim.git patch 9.1.1936: filetype: Erlang lexical files are not recognized Problem: filetype: Erlang lexical files are not recognized Solution: Detect *.xrl files as leex filetype, include syntax and filetype plugins (Jon Parise). leex is the lexical analyzer generator for Erlang. Its input file format follows a section-based structure and uses the `.xrl` file extension. This initial work includes file detection, an ftplugin (which inherits the Erlang configuration), and a syntax definition. Reference: - https://www.erlang.org/doc/apps/parsetools/leex.html related: #18819 closes: #18832 Signed-off-by: Jon Parise Signed-off-by: Csaba Hoch Signed-off-by: Christian Brabandt --- diff --git a/.github/MAINTAINERS b/.github/MAINTAINERS index 5eb9a35607..ff59e3d657 100644 --- a/.github/MAINTAINERS +++ b/.github/MAINTAINERS @@ -221,6 +221,7 @@ runtime/ftplugin/kivy.vim @ribru17 runtime/ftplugin/kotlin.vim @udalov runtime/ftplugin/lc.vim @ribru17 runtime/ftplugin/ldapconf.vim @ribru17 +runtime/ftplugin/leex.vim @jparise runtime/ftplugin/leo.vim @ribru17 runtime/ftplugin/less.vim @genoma runtime/ftplugin/lex.vim @ribru17 @@ -550,6 +551,7 @@ runtime/syntax/kivy.vim @prophittcorey runtime/syntax/kotlin.vim @udalov runtime/syntax/kdl.vim @imsnif @jiangyinzuo runtime/syntax/krl.vim @KnoP-01 +runtime/syntax/leex.vim @jparise runtime/syntax/less.vim @genoma runtime/syntax/lf.vim @andis-sprinkis runtime/syntax/liquid.vim @tpope diff --git a/runtime/autoload/dist/ft.vim b/runtime/autoload/dist/ft.vim index df377dd695..4312e6dca4 100644 --- a/runtime/autoload/dist/ft.vim +++ b/runtime/autoload/dist/ft.vim @@ -2226,6 +2226,8 @@ const ft_from_ext = { "ldg": "ledger", "ledger": "ledger", "journal": "ledger", + # Leex + "xrl": "leex", # Leo "leo": "leo", # Less diff --git a/runtime/ftplugin/leex.vim b/runtime/ftplugin/leex.vim new file mode 100644 index 0000000000..1d5ce06ff2 --- /dev/null +++ b/runtime/ftplugin/leex.vim @@ -0,0 +1,14 @@ +" Vim ftplugin file +" Language: Leex (Erlang Lexical Analyzer Generator) +" Maintainer: Jon Parise +" Last Change: 2025 Nov 29 +" Filenames: *.xrl +" +" References: +" - https://www.erlang.org/doc/apps/parsetools/leex.html + +if exists('b:did_ftplugin') + finish +endif + +runtime! ftplugin/erlang.vim diff --git a/runtime/syntax/leex.vim b/runtime/syntax/leex.vim new file mode 100644 index 0000000000..05f92c3748 --- /dev/null +++ b/runtime/syntax/leex.vim @@ -0,0 +1,63 @@ +" Vim syntax file +" Language: Leex (Erlang Lexical Analyzer Generator) +" Maintainer: Jon Parise +" Last Change: 2025 Nov 30 +" Filenames: *.xrl +" +" References: +" - https://www.erlang.org/doc/apps/parsetools/leex.html + +if exists('b:current_syntax') + finish +endif + +syn include @leexErlang syntax/erlang.vim +unlet! b:current_syntax + +syn match leexComment "%.*$" contains=@Spell display + +syn match leexRegexOperator "[|*+?]" contained display +syn match leexRegexDelimiter "[()[\]]" contained display +syn match leexRegexSpecial "[.^$\\]" contained display +syn match leexRegexEscape '\\\%([bfnrtevsd]\|\o\{1,3}\|x\x\{2}\|x{\x\+}\|.\)' contained display +syn match leexRegexRange "\[[^\]]*\]" contains=leexRegexDelimiter,leexRegexEscape contained display + +" Macro definitions: NAME = VALUE +syn match leexMacroName "^\s*\zs\h\w*\ze\s\+=\s\+" contained nextgroup=leexMacroEquals skipwhite display +syn match leexMacroEquals "=" contained nextgroup=leexMacroValue skipwhite display +syn match leexMacroValue "\S\+" contained contains=leexRegexOperator,leexRegexDelimiter,leexRegexSpecial,leexRegexEscape,leexRegexRange,leexMacroRef display +syn match leexMacroRef "{\h\w*}" contained display + +" Rule definitions: : . +syn match leexRuleRegex "^\s*\zs[^%].\{-}\ze\s\+:" contained contains=leexRegexOperator,leexRegexDelimiter,leexRegexSpecial,leexRegexEscape,leexRegexRange,leexMacroRef nextgroup=leexRuleColon skipwhite display +syn match leexRuleColon ":" contained nextgroup=leexRuleCode skipwhite skipnl display +syn region leexRuleCode start="" end="\.\s*\%(%.*\)\?$" skip="^\s*%.*$" contained contains=@leexErlang keepend skipnl skipwhite + +" Sections +syn match leexHeading "^\%(Definitions\|Rules\|Erlang code\)\.$" contained display +syn region leexDefinitions start="^Definitions\.$" end="^[A-Z][A-Za-z ]*\.$"me=s-1 end="\%$" keepend fold + \ contains=leexHeading,leexComment,leexMacroName +syn region leexRules start="^Rules\.$" end="^[A-Z][A-Za-z ]*\.$"me=s-1 end="\%$" keepend fold + \ contains=leexHeading,leexComment,leexRuleRegex +syn region leexErlangCode start="^Erlang code\.$" end="^[A-Z][A-Za-z ]*\.$"me=s-1 end="\%$" keepend fold + \ contains=leexHeading,@leexErlang + +hi def link leexComment Comment +hi def link leexHeading PreProc + +hi def link leexRegexOperator Operator +hi def link leexRegexDelimiter Delimiter +hi def link leexRegexSpecial Special +hi def link leexRegexRange String +hi def link leexRegexEscape SpecialChar + +hi def link leexMacroName Identifier +hi def link leexMacroEquals Operator +hi def link leexMacroValue String +hi def link leexMacroRef Macro + +hi def link leexRuleColon Operator + +syn sync fromstart + +let b:current_syntax = 'leex' diff --git a/runtime/syntax/testdir/dumps/leex_00.dump b/runtime/syntax/testdir/dumps/leex_00.dump new file mode 100644 index 0000000000..72d4642aaf --- /dev/null +++ b/runtime/syntax/testdir/dumps/leex_00.dump @@ -0,0 +1,20 @@ +>%+0#0000e05#ffffff0| |H|e|a|d|e|r| |c|o|m@1|e|n|t| +0#0000000&@58 +|%+0#0000e05&@1| |H|e|a|d|e|r| |c|o|m@1|e|n|t| +0#0000000&@57 +|%+0#0000e05&@2| |H|e|a|d|e|r| |c|o|m@1|e|n|t| +0#0000000&@56 +@75 +|D+0#e000e06&|e|f|i|n|i|t|i|o|n|s|.| +0#0000000&@62 +|f+0#00e0e07&|l|o|a|t|s| +0#0000000&@1|=+0#af5f00255&| +0#0000000&|(+0#e000e06&|\|+||+0#af5f00255&|-+0#e000002&|)+0#e000e06&|?+0#af5f00255&|[+0#e000e06&|0+0#e000002&|-|9|]+0#e000e06&|++0#af5f00255&|\+0#e000e06&|.|[|0+0#e000002&|-|9|]+0#e000e06&|++0#af5f00255&|(+0#e000e06&@1|E+0#e000002&||+0#af5f00255&|e+0#e000002&|)+0#e000e06&|(|\|+||+0#af5f00255&|-+0#e000002&|)+0#e000e06&|?+0#af5f00255&|[+0#e000e06&|0+0#e000002&|-|9|]+0#e000e06&|++0#af5f00255&|)+0#e000e06&|?+0#af5f00255&| +0#0000000&@22 +|D+0#00e0e07&| +0#0000000&@6|=+0#af5f00255&| +0#0000000&|[+0#e000e06&|0+0#e000002&|-|9|]+0#e000e06&| +0#0000000&@59 +|A+0#00e0e07&| +0#0000000&@6|=+0#af5f00255&| +0#0000000&|(+0#e000e06&|{|D|}||+0#af5f00255&|_+0#e000002&||+0#af5f00255&|@+0#e000002&|)+0#e000e06&| +0#0000000&@55 +|W+0#00e0e07&|S| +0#0000000&@5|=+0#af5f00255&| +0#0000000&|(+0#e000e06&|[|\|0@2|-+0#e000002&|\+0#e000e06&|s|]||+0#af5f00255&|%+0#e000002&|.+0#e000e06&|*+0#af5f00255&|)+0#e000e06&| +0#0000000&|%+0#0000e05&| |w|h|i|t|e|s|p|a|c|e| +0#0000000&@36 +@75 +|R+0#e000e06&|u|l|e|s|.| +0#0000000&@68 +|{+0#e000e06&|D|}|++0#af5f00255&| +0#0000000&|:+0#af5f00255&| +0#0000000&@68 +@2|%+0#0000e05&| |C|o|m@1|e|n|t| +0#0000000&@63 +@2|{+0#e000e06&|t+0#e000002&|o|k|e|n|,+0#0000000&|{+0#e000e06&|i+0#e000002&|n|t|e|g|e|r|,+0#0000000&|T+0#00e0e07&|o|k|e|n|L|i|n|e|,+0#0000000&|l+0#00e0e07&|i|s|t|_|t|o|_|i|n|t|e|g|e|r|(+0#0000000&|T+0#00e0e07&|o|k|e|n|C|h|a|r|s|)+0#0000000&|}+0#e000e06&@1|.+0#0000000&| @16 +|{+0#e000e06&|D|}|++0#af5f00255&|\+0#e000e06&|.|{|D|}|++0#af5f00255&|(+0#e000e06&@1|E+0#0000000&||+0#af5f00255&|e+0#0000000&|)+0#e000e06&|(|\|+||+0#af5f00255&|\+0#e000e06&|-|)|?+0#af5f00255&|{+0#e000e06&|D|}|++0#af5f00255&|)+0#e000e06&|?+0#af5f00255&| +0#0000000&|:+0#af5f00255&| +0#0000000&@42 +@2|%+0#0000e05&| |C|o|m|e|n|t| |w|i|t|h| |p|e|r|i|o|d|.| +0#0000000&@51 +@2|{+0#e000e06&|t+0#e000002&|o|k|e|n|,+0#0000000&|{+0#e000e06&|f+0#e000002&|l|o|a|t|,+0#0000000&|T+0#00e0e07&|o|k|e|n|L|i|n|e|,+0#0000000&|l+0#00e0e07&|i|s|t|_|t|o|_|f|l|o|a|t|(+0#0000000&|T+0#00e0e07&|o|k|e|n|C|h|a|r|s|)+0#0000000&|}+0#e000e06&@1|.+0#0000000&| @20 +|{+0#e000e06&|A|}| +0#0000000&|:+0#af5f00255&| +0#0000000&@1|E+0#00e0e07&|r|l|a|n|g|C|o|d|e|.+0#0000000&| |%+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@46 +|{+0#e000e06&|W|S|}| +0#0000000&|:+0#af5f00255&| +0#0000000&|E+0#00e0e07&|r|l|a|n|g|C|o|d|e|.+0#0000000&| @56 +@57|1|,|1| @10|T|o|p| diff --git a/runtime/syntax/testdir/dumps/leex_01.dump b/runtime/syntax/testdir/dumps/leex_01.dump new file mode 100644 index 0000000000..3fd3d7229b --- /dev/null +++ b/runtime/syntax/testdir/dumps/leex_01.dump @@ -0,0 +1,20 @@ +| +0&#ffffff0@1|{+0#e000e06&|t+0#e000002&|o|k|e|n|,+0#0000000&|{+0#e000e06&|i+0#e000002&|n|t|e|g|e|r|,+0#0000000&|T+0#00e0e07&|o|k|e|n|L|i|n|e|,+0#0000000&|l+0#00e0e07&|i|s|t|_|t|o|_|i|n|t|e|g|e|r|(+0#0000000&|T+0#00e0e07&|o|k|e|n|C|h|a|r|s|)+0#0000000&|}+0#e000e06&@1|.+0#0000000&| @16 +|{+0#e000e06&|D|}|++0#af5f00255&|\+0#e000e06&|.|{|D|}|++0#af5f00255&|(+0#e000e06&@1|E+0#0000000&||+0#af5f00255&|e+0#0000000&|)+0#e000e06&|(|\|+||+0#af5f00255&|\+0#e000e06&|-|)|?+0#af5f00255&|{+0#e000e06&|D|}|++0#af5f00255&|)+0#e000e06&|?+0#af5f00255&| +0#0000000&|:+0#af5f00255&| +0#0000000&@42 +@2|%+0#0000e05&| |C|o|m|e|n|t| |w|i|t|h| |p|e|r|i|o|d|.| +0#0000000&@51 +@2|{+0#e000e06&|t+0#e000002&|o|k|e|n|,+0#0000000&|{+0#e000e06&|f+0#e000002&|l|o|a|t|,+0#0000000&|T+0#00e0e07&|o|k|e|n|L|i|n|e|,+0#0000000&|l+0#00e0e07&|i|s|t|_|t|o|_|f|l|o|a|t|(+0#0000000&|T+0#00e0e07&|o|k|e|n|C|h|a|r|s|)+0#0000000&|}+0#e000e06&@1|.+0#0000000&| @20 +|{+0#e000e06&|A|}| +0#0000000&|:+0#af5f00255&| +0#0000000&@1|E+0#00e0e07&|r|l|a|n|g|C|o|d|e|.+0#0000000&| |%+0#0000e05&| |c|o|m@1|e|n|t| +0#0000000&@46 +>{+0#e000e06&|W|S|}| +0#0000000&|:+0#af5f00255&| +0#0000000&|E+0#00e0e07&|r|l|a|n|g|C|o|d|e|.+0#0000000&| @56 +|:|=| |:+0#af5f00255&|{+0#e000e06&|t+0#e000002&|o|k|e|n|,+0#0000000&|{+0#e000e06&|'+0#e000002&|:|=|'|,+0#0000000&|T+0#00e0e07&|o|k|e|n|L|i|n|e|}+0#e000e06&@1|.+0#0000000&| @45 +@75 +|E+0#e000e06&|r|l|a|n|g| |c|o|d|e|.| +0#0000000&@62 +@75 +|-+0#af5f00255&|e|x|p|o|r|t|(+0#0000000&|[+0#e000e06&|r+0#0000000&|e|s|e|r|v|e|d|_|w|o|r|d|/+0#af5f00255&|1+0#e000002&|]+0#e000e06&|)+0#0000000&|.| @47 +@75 +|%+0#0000e05&@1| |r|e|s|e|r|v|e|d|_|w|o|r|d|(|A|t|o|m|)| |-|>| |B|o@1|l| +0#0000000&@44 +|r|e|s|e|r|v|e|d|_|w|o|r|d|(|'+0#e000002&|r|e|s|e|r|v|e|d|'|)+0#0000000&| |-+0#af5f00255&|>| +0#0000000&|t+0#e000002&|r|u|e|;+0#0000000&| @40 +|r|e|s|e|r|v|e|d|_|w|o|r|d|(|_+0#00e0e07&|)+0#0000000&| |-+0#af5f00255&|>| +0#0000000&|f+0#e000002&|a|l|s|e|.+0#0000000&| @48 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +| +0#0000000&@56|1|9|,|1| @9|B|o|t| diff --git a/runtime/syntax/testdir/input/leex.xrl b/runtime/syntax/testdir/input/leex.xrl new file mode 100644 index 0000000000..c901b8b87d --- /dev/null +++ b/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/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index 0fef5ffe9d..84aa338e5c 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -440,6 +440,7 @@ def s:GetFilenameChecks(): dict> ldif: ['file.ldif'], lean: ['file.lean'], ledger: ['file.ldg', 'file.ledger', 'file.journal'], + leex: ['file.xrl'], leo: ['file.leo'], less: ['file.less'], lex: ['file.lex', 'file.l', 'file.lxx', 'file.l++'], diff --git a/src/version.c b/src/version.c index 7a796a89cd..8202641a5c 100644 --- a/src/version.c +++ b/src/version.c @@ -729,6 +729,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 1936, /**/ 1935, /**/