Files
zeertzjqandGrant Hutchins eee7609f30 vim-patch:9.2.1254: filetype: Bats files are detected as sh
Problem:  Bats test files are detected as "sh", so plugins and parsers
          cannot tell them apart from plain Bash scripts, and Bats
          extensions are highlighted as plain Bash: the "test" in "@test"
          is highlighted as the test command and the test body is not a
          function body, so it does not fold.
Solution: Detect *.bats files and bats shebang lines as "bats", include
          filetype, indent and syntax scripts that reuse the "sh" ones
          with b:is_bash set, highlight @test with its name and fold its
          body like a function, highlight "# bats test_tags=" and
          "file_tags=" comments and the commands bats-core provides, and
          add a syntax test (Grant Hutchins).

Bats (Bash Automated Testing System) test files are Bash with extensions
such as `@test "name" { ... }` blocks, which Bash parsers like
tree-sitter-bash do not understand.  Tools that do need a filetype to key
on: bash-language-server parses .bats files with a bats dialect, ALE has
bats linters, and tree-sitter-bats provides a grammar for editors that
use tree-sitter.  Highlighting, indenting and the "sh" filetype plugin
behave as before, the same way the "bash" filetype works.

Commands from add-on libraries such as bats-assert are not highlighted.

related: vim/vim#14039
closes:  vim/vim#21516

https://github.com/vim/vim/commit/d8ae4348a0393c7e2b03f68541c3d1d920292165

Co-authored-by: Grant Hutchins <git@nertzy.com>
2026-10-31 08:46:05 +08:00

41 lines
1.4 KiB
VimL

" Vim syntax file
" Language: Bats (Bash Automated Testing System)
" Maintainer: Grant Hutchins <git@nertzy.com>
" Last Change: 2026 Oct 14
" quit when a syntax file was already loaded
if exists("b:current_syntax")
finish
endif
" Bats test files are Bash scripts; the syntax is in sh.vim.
unlet! b:is_sh
unlet! b:is_kornshell
let b:is_bash = 1
runtime! syntax/sh.vim
unlet! b:current_syntax
" @test name { ... }: the body is a function body, folded like one when
" g:sh_fold_enabled asks for function folding. As in bats-preprocess, the
" name runs up to the last blank-preceded "{" on the line.
syn match batsTest "^\s*\zs@test\ze\s" skipwhite nextgroup=batsTestName
syn match batsTestName contained "\S\%(.*\S\)\=\ze\s\+{" contains=shDoubleQuote,shSingleQuote,shDeref,shDerefSimple skipwhite nextgroup=shFunctionExpr
" # bats test_tags=... and # bats file_tags=...
syn match batsTagComment "^\s*\zs#\s*bats\s\+\%(test\|file\)_tags=.*$"
" Commands provided by bats-core
syn cluster shCommandSubList add=batsStatement
syn cluster shCaseList add=batsStatement
syn keyword batsStatement run skip load bats_load_safe bats_load_library bats_load_library_safe bats_require_minimum_version bats_pipe bats_test_function
hi def link batsTest Keyword
hi def link batsTestName String
hi def link batsTagComment SpecialComment
hi def link batsStatement shStatement
let b:current_syntax = 'bats'
" vim: ts=8