I have some specifically formatted text files that I'd like to detect when I start vim. When I load these files now, the filetype is automatically set to text. I only want to override that if the first line of the text file starts with "Client:", in which case, I'd like to set the filetype to veltxt. I have already created a syntax file that works with these files.

Here's my veltxt.vim from my ftdetect folder:

if did_filetype()       " filetype already set..  
  finish                " ..don't do these checks  
if getline(1) =~ '^Client:..*'  
  setfiletype veltxt  
  • 1
    Take a look in $VIMRUNTIME (I think script.vim)
    – D. Ben Knoble
    Dec 14 '20 at 22:35
  • Hi the . (period) after the : isn't doing anything If Client: is the whole line then if getline(1) =~ '^Client:$'matches, assuming you don't have set ignorecase in _vimrc
    – Steve
    Dec 14 '20 at 23:19
  • @Steve Single "dot" matches any character (i.e. not end of a source string) what makes sense; "dot-star" always matches, so it's an excess.
    – Matt
    Dec 15 '20 at 7:02
  • @matt thanks however in this case it matched nothing as the string wasn't followed by anything except the $ EOL which is why I asked
    – Steve
    Dec 15 '20 at 22:39
  • @Steve If the whole string were "Client:" then it would not have matched regex "^Client:."
    – Matt
    Dec 16 '20 at 6:39

Yes, you should be able to set the filetype based on the contents of the file.

If you add a script to the ftdetect directory, this script should set up a new autocmd to trigger when a file of a specific extension or file name pattern (or * if any file name is possible) is opened and then set the appropriate filetype there.

The autocmd can then set the filetype in a few different ways:

  • Using the setfiletype (setf) command, which will set the filetype, but only if it wasn't set yet.
  • Using the setf FALLBACK command, which sets the filetype, but allows later setf commands to override it.
  • Using the setlocal filetype=... command to update the 'filetype' setting directly, which will override any previous settings.

In your case, since the ftdetect rules run last, you'll want to use the setlocal filetype=... variation.

So, assuming you're matching files that start with Client: on their first line and that have any extension whatsoever, you could have a ftdetect/veltxt.vim with the following rule:

au BufNewFile,BufRead * if getline(1) =~ '^Client:' | setlocal filetype=veltxt | endif

Note that you don't need to use an augroup in an ftdetect script, since Vim already takes care of running all the ftdetect scripts within the context of a filetypedetect group (see $VIMRUNTIME/filetype.vim for details, also where ftdetect/*.vim are sourced.)

You can adapt the rule above to match specific file patterns, or perhaps check that the previously set &filetype match the expected text before you inspect the file contents.

See :help ftdetect for the Vim help documentation on the procedure of configuring new file type detection.

  • 1
    Yeah! That did it! THANKS! Dec 16 '20 at 14:25

You can create $HOME/.vim/scripts.vim of your own, as $VIMRUNTIME/filetype.vim will source it by executing :runtime! scripts.vim if needed. It's enough to put only these lines:

if getline(1) =~# '^Client:.'
    setf veltxt

Note that .* at the end of a pattern does nothing (always matches).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.