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 <jon@indelible.org>
Signed-off-by: Csaba Hoch <csaba.hoch@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Jon Parise
2025-11-30 14:45:48 +00:00
committed by Christian Brabandt
parent 2b2580e61a
commit b087c5452b
9 changed files with 152 additions and 0 deletions

2
.github/MAINTAINERS vendored
View File

@ -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

View File

@ -2226,6 +2226,8 @@ const ft_from_ext = {
"ldg": "ledger",
"ledger": "ledger",
"journal": "ledger",
# Leex
"xrl": "leex",
# Leo
"leo": "leo",
# Less

14
runtime/ftplugin/leex.vim Normal file
View File

@ -0,0 +1,14 @@
" Vim ftplugin file
" Language: Leex (Erlang Lexical Analyzer Generator)
" Maintainer: Jon Parise <jon@indelible.org>
" 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

63
runtime/syntax/leex.vim Normal file
View File

@ -0,0 +1,63 @@
" Vim syntax file
" Language: Leex (Erlang Lexical Analyzer Generator)
" Maintainer: Jon Parise <jon@indelible.org>
" 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: <Regexp> : <Erlang code>.
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'

View File

@ -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|

View File

@ -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|

View File

@ -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.

View File

@ -440,6 +440,7 @@ def s:GetFilenameChecks(): dict<list<string>>
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++'],

View File

@ -729,6 +729,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
1936,
/**/
1935,
/**/