# Vim functions for file type detection
#
# Maintainer: The Vim Project <https://github.com/vim/vim>
-# Last Change: 2026 Aug 06
+# Last Change: 2026 Aug 08
# Former Maintainer: Bram Moolenaar <Bram@vim.org>
# These functions are moved here from runtime/filetype.vim to make startup
endif
enddef
+# AL (Microsoft Dynamics 365 Business Central) or Perl AutoLoader
+export def FTal()
+ if exists("g:filetype_al")
+ exe "setf " .. g:filetype_al
+ return
+ endif
+
+ # AL sources declare an object as "<kind> <id> <name>" at the start of a
+ # line, optionally preceded by namespace and using declarations. Perl
+ # AutoLoader chunks match neither. Matching a bare keyword anywhere would
+ # be wrong: table, page and report are ordinary English words, so the object
+ # name must follow. The match is case sensitive because AL tooling emits
+ # lowercase keywords, while prose in Perl comments is usually capitalised.
+ for lnum in range(1, min([line("$"), 200]))
+ var line = getline(lnum)
+ if line =~# '^\s*\%(codeunit\|page\|pageextension\|pagecustomization\|table\|tableextension\|' ..
+ 'report\|reportextension\|xmlport\|query\|enum\|enumextension\|profile\|profileextension\|' ..
+ 'controladdin\|interface\|permissionset\|permissionsetextension\|entitlement\)\>\s\+\%(\d\|"\|\u\)'
+ || line =~# '^\s*dotnet\s*$'
+ || line =~# '^\s*\%(namespace\|using\)\s\+[[:alnum:]._]\+\s*;'
+ setf al
+ return
+ endif
+ endfor
+
+ setf perl
+enddef
+
# Erlang Application Resource Files (*.app.src is matched by extension)
# See: https://erlang.org/doc/system/applications
export def FTapp()
" Vim support file to detect file types
"
" Maintainer: The Vim Project <https://github.com/vim/vim>
-" Last Change: 2026 Jul 18
+" Last Change: 2026 Aug 08
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
" If the filetype can be detected from extension or file name(the final path component),
else
au BufNewFile,BufRead *.pl call dist#ft#FTpl()
endif
-au BufNewFile,BufRead *.plx,*.al,*.psgi setf perl
+au BufNewFile,BufRead *.plx,*.psgi setf perl
+
+" Perl AutoLoader or AL (Dynamics 365 Business Central)
+au BufNewFile,BufRead *.al call dist#ft#FTal()
" Perl, XPM or XPM2
au BufNewFile,BufRead *.pm
pcmk: ['file.pcmk'],
pdf: ['file.pdf'],
pem: ['file.pem', 'file.cer', 'file.crt', 'file.csr'],
- perl: ['file.plx', 'file.al', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc', '.latexmkrc', 'latexmkrc'],
+ perl: ['file.plx', 'file.psgi', 'gitolite.rc', '.gitolite.rc', 'example.gitolite.rc', '.latexmkrc', 'latexmkrc'],
pf: ['pf.conf'],
pfmain: ['main.cf', 'main.cf.proto'],
php: ['file.php', 'file.php9', 'file.phtml', 'file.ctp', 'file.phpt', 'file.theme'],
" Keep sorted.
"""""""""""""""""""""""""""""""""""""""""""""""""
+func Test_al_file()
+ filetype on
+
+ " AL object declaration
+ call writefile(['codeunit 50100 "My Codeunit"', '{', '}'], 'Xfile.al', 'D')
+ split Xfile.al
+ call assert_equal('al', &filetype)
+ bwipe!
+
+ " AL namespace and using declarations before the object
+ call writefile(['namespace Microsoft.Sales;', '', 'using Microsoft.Foundation;'], 'Xfile.al')
+ split Xfile.al
+ call assert_equal('al', &filetype)
+ bwipe!
+
+ " Perl AutoLoader chunk
+ call writefile(['# NOTE: Derived from blib/lib/Net/SSLeay.pm.', 'package Net::SSLeay;', 'sub do_https {'], 'Xfile.al')
+ split Xfile.al
+ call assert_equal('perl', &filetype)
+ bwipe!
+
+ " AL DotNet alias object, which is a bare keyword on its own line
+ call writefile(['dotnet', '{', ' assembly("mscorlib")', '}'], 'Xfile.al')
+ split Xfile.al
+ call assert_equal('al', &filetype)
+ bwipe!
+
+ " Perl code containing AL object kinds as ordinary words
+ call writefile(['sub value {', ' my $table = shift;', ' # report page interface', '}'], 'Xfile.al')
+ split Xfile.al
+ call assert_equal('perl', &filetype)
+ bwipe!
+
+ " Perl documentation containing AL object kinds at the start of a line
+ call writefile(['package Foo;', '=pod', 'Table of contents', 'using the -x option', 'table of contents follows'], 'Xfile.al')
+ split Xfile.al
+ call assert_equal('perl', &filetype)
+ bwipe!
+
+ " Test dist#ft#FTal()
+
+ let g:filetype_al = 'perl'
+ call writefile(['codeunit 50100 "My Codeunit"'], 'Xfile.al')
+ split Xfile.al
+ call assert_equal('perl', &filetype)
+ bwipe!
+ unlet g:filetype_al
+
+ filetype off
+endfunc
+
" Since dist#ft#FTm4() looks around for configure.ac
" the test needs to isolate itself in a fresh temporary project tree,
" so that no configure.ac from another test (or from the repo root)