]> git.ipfire.org Git - thirdparty/vim.git/commitdiff
patch 9.1.1936: filetype: Erlang lexical files are not recognized v9.1.1936
authorJon Parise <jon@indelible.org>
Sun, 30 Nov 2025 14:45:48 +0000 (14:45 +0000)
committerChristian Brabandt <cb@256bit.org>
Sun, 30 Nov 2025 14:45:48 +0000 (14:45 +0000)
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>
.github/MAINTAINERS
runtime/autoload/dist/ft.vim
runtime/ftplugin/leex.vim [new file with mode: 0644]
runtime/syntax/leex.vim [new file with mode: 0644]
runtime/syntax/testdir/dumps/leex_00.dump [new file with mode: 0644]
runtime/syntax/testdir/dumps/leex_01.dump [new file with mode: 0644]
runtime/syntax/testdir/input/leex.xrl [new file with mode: 0644]
src/testdir/test_filetype.vim
src/version.c

index 5eb9a3560719926d443e4f93bfd256b62e21624f..ff59e3d657640430019d5597639627d28dae8a76 100644 (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
index df377dd6952519daf48ddd3e26ed5f6465b076ba..4312e6dca411e28e434f6ad12cfee30c64e39ca7 100644 (file)
@@ -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 (file)
index 0000000..1d5ce06
--- /dev/null
@@ -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
diff --git a/runtime/syntax/leex.vim b/runtime/syntax/leex.vim
new file mode 100644 (file)
index 0000000..05f92c3
--- /dev/null
@@ -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'
diff --git a/runtime/syntax/testdir/dumps/leex_00.dump b/runtime/syntax/testdir/dumps/leex_00.dump
new file mode 100644 (file)
index 0000000..72d4642
--- /dev/null
@@ -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 (file)
index 0000000..3fd3d72
--- /dev/null
@@ -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 (file)
index 0000000..c901b8b
--- /dev/null
@@ -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.
index 0fef5ffe9d09d0fa7d1ea63cac502e3e03bce3e8..84aa338e5c04c73c15e5fd3999166c36d827bc09 100644 (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++'],
index 7a796a89cd4837500e8310791b95168d7b90278b..8202641a5c5f6d93c519380054ed4e372230cff3 100644 (file)
@@ -729,6 +729,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1936,
 /**/
     1935,
 /**/