If you want to introduce a file type and that file type can only be identified by examining the contents of such files then you'll need to add appropriate logic to a file named
But first, let's take a step back and look at the bigger picture. (Skip to the "Solution" section, below, if you're not interested in the technical details.)
File type detection is enabled with the command
:filetype on. (This is typically in the user vimrc file or triggered by sourcing
The command will cause Vim to source the script named
filetype.vim found in the directory named in the
$VIMRUNTIME environment variable. Doing so sets up a bunch of
au BufNewFile,BufRead autocommands. Since detection by filename is much more common than detection by content, the bulk of
filetype.vim is made up of lines like the following:
au BufNewFile,BufRead *.clj,*.cljs,*.cljx,*.cljc setf clojure
A couple thousand lines later we get to the part that kicks off detection by content:
au BufNewFile,BufRead *
\ if !did_filetype() && expand("<amatch>") !~ g:ft_ignore_pat
\ | runtime! scripts.vim | endif
* indicates that this autocommand will be triggered for all files so some logic is needed to filter out files that already matched a file extension specific autocommand (or otherwise had their type identified).
!did_filetype() guards against this as the function returns true if the
FileType event has been triggered at least once prior and we negate (
!) the result, thus halting further execution of the line. (We'll be using this same function in a guard block in our
Following that is a check that the filename we're dealing with doesn't match certain extensions (e.g.
If those two checks are passed,
scripts.vim will be executed. But which one? The
:runtime command means that ALL files named
scripts.vim appearing in one of the paths specified in
'runtimepath' will be sourced/executed. There is always an instance of this file in the
$VIMRUNTIME directory. We're going to achieve our goal by creating our own instance of it.
Note that, by default, the first path in
$HOME/.vim (or non-Unix equivalent). That's where our script file is going to go which means our detection logic will take precedence over that in
$VIMRUNTIME or anywhere else.
(As an aside, a plugin-manager's main function is to update
'runtimepath' and add a path for each installed plugin. While these typically get inserted before any system directories, as far as I know they always come after
With the deep dive out of the way let's get down to business.
The standard place to put the local
scripts.vim file is in your personal Vim folder (usually in
$HOME) so run the following command (or your system equivalent):
Assuming the file didn't exist before now, you'll want to add a guard block based on the function
did_filetype() which we covered above. Follow that with a conditional block with appropriate detection logic. For the OP's use case that would look like this:
if did_filetype() " filetype already set..
finish " ..don't do these checks
if getline(1) =~ '^#!/usr/bin/awk -f'
If the file already existed there's presumably something like the above already in it. In that case just append your detection logic as an
" Existing two conditionals...
" Add these two lines
elseif getline(1) =~ '^#!/usr/bin/awk -f'
:h new-filetype-scripts and