Vim Tips Wiki
(→‎File locations: minor spelling correction)
Tag: Visual edit
 
(14 intermediate revisions by 7 users not shown)
Line 1: Line 1:
 
{{TipNew
 
{{TipNew
|id=0
+
|id=1606
|previous=
+
|previous=1605
|next=1
+
|next=1607
|created=September 30, 2008
+
|created=2008
 
|complexity=basic
 
|complexity=basic
 
|author=JeremyBarton
 
|author=JeremyBarton
Line 11: Line 11:
 
|category2=
 
|category2=
 
}}
 
}}
  +
This tip is a tutorial on the use of the file <code>filetype.vim</code> which is used to determine the "type" of a file. For example, while editing <code>example.py</code> the command <code>:set ft?</code> should display <code>filetype=python</code> if <code>:filetype indent plugin on</code> has been used. The file type determines whether any plugins for scripts, indenting rules, or syntax highlighting are loaded. See [[file type plugins]] for an overview.
Filetype.vim is the name of the file that is used by the filetype plugin ([[:Category:Filetype]]).
 
   
==File Structure==
+
==File structure==
Custom filetype.vim files should always have the following structure:
+
Custom <code>filetype.vim</code> files should always have the following structure:
 
<pre>
 
<pre>
 
if exists("did_load_filetypes")
 
if exists("did_load_filetypes")
 
finish
 
finish
 
endif
 
endif
let did_load_filetypes= 1
 
 
augroup filetypedetect
 
augroup filetypedetect
" local filetype changes go here
+
" au! commands to set the filetype go here
 
augroup END
 
augroup END
 
</pre>
 
</pre>
   
Files that are being used as fallbacks (in the <tt>after</tt> directories) should use a form such as
+
Files that are being used as fallbacks (in the <code>after</code> directories) should use a form such as
 
<pre>
 
<pre>
 
if exists("did_load_filetypes_userafter")
 
if exists("did_load_filetypes_userafter")
Line 31: Line 30:
 
endif
 
endif
 
let did_load_filetypes_userafter = 1
 
let did_load_filetypes_userafter = 1
 
 
augroup filetypedetect
 
augroup filetypedetect
" local filetype changes go here
+
" au! commands to set the filetype go here
 
augroup END
 
augroup END
 
</pre>
 
</pre>
   
because <code>did_load_filetypes</code> will be set before execution gets to the <tt>after</tt> files. Using the suffixes <tt>_userafter</tt> and <tt>_machineafter</tt> as appropriate will prevent one from interfering with the other.
+
because <code>did_load_filetypes</code> will be set before the <code>after</code> files are used. Using the suffixes <code>_userafter</code> and <code>_systemafter</code> as appropriate will prevent one from interfering with the other.
   
==File Contents==
+
==File contents==
Between <code>augroup filetypedetect</code> and <code>augroup END</code> you will have one or more <code>au[tocmd]</code> directives, registered against the <code>BufNewFile</code> and <code>BufRead</code> events, to assign the filetype.
+
Between <code>augroup filetypedetect</code> and <code>augroup END</code> there will be one or more <code>autocmd</code> statements that may assign a filetype when the <code>BufNewFile</code> and <code>BufRead</code> events occur (that is, when a new file is created, or when an existing file is read).
   
  +
Following are some examples to illustrate common scenarios.
===Common rule formats===
 
The following examples are primarily taken from the Vim default ruleset on Vim 7.1.
 
   
 
Assign the <code>dosbatch</code> filetype to any file with name ending in <code>.bat</code> or <code>.sys</code>:
====Always match a specified file extension====
 
 
<pre>
 
<pre>
au BufNewFile,BufRead *.bat,*.sys setf dosbatch
+
au! BufNewFile,BufRead *.bat,*.sys setf dosbatch
 
</pre>
 
</pre>
Always assigns the <tt>dosbatch</tt> filetype to any file ending in <tt>.bat</tt> or <tt>.sys</tt>.
 
   
 
If the first line of a <code>.cmd</code> file begins with <code>/*</code> then assign the filetype <code>rexx</code>, otherwise assign the filetype <code>dosbatch</code>:
====Match conditionally on a file extension (simple)====
 
  +
<pre>
<pre>au BufNewFile,BufRead *.cmd if getline(1) =~ '^/\*' | setf rexx | else | setf dosbatch | endif</pre>
+
au! BufNewFile,BufRead *.cmd if getline(1) =~ '^/\*' | setf rexx | else | setf dosbatch | endif
If the first line of a <tt>.cmd</tt> file begins with <tt>/*</tt> then assign the filetype <tt>rexx</tt>, otherwise assign the filetype <tt>dosbatch</tt>.
 
  +
</pre>
 
====Match conditionally on a file extension for override (simple)====
 
<pre>au! BufRead,BufNewFile *.bat if getline(1) =~ '--\*-Perl-\*--' | setf perl | endif</pre>
 
If the first line of a <tt>.bat</tt> file begins with <tt>--*-Perl-*--</tt> then assign the filetype <tt>perl</tt>, otherwise do nothing and continue processing rules. (Referenced from [[Editing ActiveState Perl batch files]].)
 
   
 
If the first line of a <code>.bat</code> file contains "<code>--*-Perl-*--</code>" then assign the filetype <code>perl</code>, otherwise do nothing and continue processing rules (see [[Editing ActiveState Perl batch files|tip]]):
====Match conditionally on a file extension (complex)====
 
 
<pre>
 
<pre>
 
au! BufRead,BufNewFile *.bat if getline(1) =~ '--\*-Perl-\*--' | setf perl | endif
au BufNewFile,BufRead *.btm call s:FTbtm()
 
  +
</pre>
   
 
When reading a <code>.btm</code> file, if the variable <code>g:dosbatch_syntax_for_btm</code> is defined and non-zero then assign the <code>dosbatch</code> filetype, otherwise assign the <code>btm</code> filetype.
func! s:FTbtm()
 
  +
<pre>
 
au! BufNewFile,BufRead *.btm call s:FTbtm()
 
function! s:FTbtm()
 
if exists("g:dosbatch_syntax_for_btm") && g:dosbatch_syntax_for_btm
 
if exists("g:dosbatch_syntax_for_btm") && g:dosbatch_syntax_for_btm
 
setf dosbatch
 
setf dosbatch
Line 69: Line 66:
 
setf btm
 
setf btm
 
endif
 
endif
  +
endfunction
endfunc
 
 
</pre>
 
</pre>
   
 
==File locations==
When reading a <tt>.btm</tt> file, if <code>g:dosbatch_syntax_for_btm</code> is defined and non-zero then assign the <tt>dosbatch</tt> filetype, otherwise assign the <tt>btm</tt> filetype.
 
 
The file <code>filetype.vim</code> is read from directories in the runtime path. The first match which executes <code>:setf</code> will set the filetype for the file Vim is creating or reading. If no rules execute <code>:setf</code> then additional <code>filetype.vim</code> files will be read.
   
  +
The file locations (in the order that the files are processed) are:
==File Locations==
 
 
;User-specific primary definitions
The plugin will load filetype.vim file(s) from the runtime path. The first match which calls <code>setf</code> will be the resulting filetype for the affected file. If no rules match, or the rule fails to eventually call <code>setf</code> then rules from successive files will be attempted.
 
 
:Rules for the current user that should be attempted before any other rule.
 
:<code>$HOME/.vim/filetype.vim</code> (Unix-based systems)
 
:<code>$HOME\vimfiles\filetype.vim</code> (Windows systems)
 
;System primary definitions
 
:Rules for all users on a system (usually requires administrative rights to edit).
 
:<code>$VIM/vimfiles/filetype.vim</code> (all systems)
 
;Vim default ruleset
 
:Rules that are part of the Vim install (do ''not'' edit this file).
 
:<code>$VIMRUNTIME/filetype.vim</code> (all systems)
 
;System fallback definitions
 
:Rules for all users if no other rule has matched so far. Useful for a rule that you would want to stop using if a future version of Vim defined a better match.
  +
:<code>$VIM/vimfiles/after/filetype.vim</code> (all systems)
 
;User-specific fallback definitions
  +
:Rules for the current user if no other rule has matched so far.
 
:<code>$HOME/.vim/after/filetype.vim</code> (Unix-based systems)
 
:<code>$HOME\vimfiles\after\filetype.vim</code> (Windows systems)
   
  +
In Vim, use commands like the following to check these locations:
* User-specific primary definitions
 
  +
<pre>
** Contains rules for the current user that should be attempted before any other rule. If your rule is conditional and does not call <code>setf</code> then later rules will still be attempted.
 
  +
:echo $HOME
*** Unix: <tt>$HOME/.vim/filetype.vim</tt>
 
  +
:echo $VIM
*** Win32: <tt>%USERPROFILE%\vimfiles\filetype.vim</tt>
 
 
:echo $VIMRUNTIME
* Machine-local primary definitions
 
  +
</pre>
** Contains rules that should apply to all users on a machine. This file usually requires some sort of administrative rights to edit.
 
*** <tt>$VIM/vimfiles/filetype.vim</tt>
 
* Vim default ruleset
 
** Contains rules that are part of the Vim install. DO NOT edit this file.
 
*** <tt>$VIMRUNTIME/filetype.vim</tt>
 
* Machine-local fallback definitions
 
** Contains rules that should apply to all users on a machine only if no other rule has matched so far. This is useful when you have a rule that you would want to stop using if a future version of Vim defined a better match.
 
*** <tt>$VIM/vimfiles/after/filetype.vim</tt>
 
* User-specific fallback definitions
 
** Contains rules for the current user that should only be attempted if no other rule has matched so far.
 
*** Unix: <tt>$HOME/.vim/after/filetype.vim</tt>
 
*** Win32: <tt>%USERPROFILE%\vimfiles\after\filetype.vim</tt>
 
   
  +
On Windows systems, <code>$HOME</code> is set from the environment variable <code>HOME</code>, if defined; or is set by joining variables <code>HOMEDRIVE</code> and <code>HOMEPATH</code>, if they are defined. At command prompt (not in Vim), enter <code>set H</code> to display the environment variables that begin with '<code>H</code>'.
==See also==
 
*{{help|filetype}}
 
*{{help|new-filetype}}
 
*{{help|ft}}
 
*{{help|setf}}
 
*{{help|augroup}}
 
*{{help|autocmd}}
 
*{{help|BufNewFile}}
 
*{{help|BufRead}}
 
*{{help|getline}}
 
*{{help|user-functions}}
 
*{{help|runtimepath}}
 
*{{help|$VIM}}
 
*{{help|$VIMRUNTIME}}
 
   
==Comments==
+
==Example==
  +
When using our [[Working with CSV files|CSV tip]], it is necessary to specify that <code>*.csv</code> files have the <code>csv</code> file type. To do this, edit the following file:
Maybe we should mention the "ftdetect" directory. {{help|ftdetect}}
 
  +
*<code>$HOME/.vim/filetype.vim</code> (Unix based systems)
  +
*<code>$HOME/vimfiles/filetype.vim</code> (Windows systems – can use forward slash or backslash in Vim)
   
  +
Check that <code>$HOME</code> has been defined, and that the <code>$HOME/.vim</code> directory (Unix) or <code>$HOME/vimfiles</code> directory (Windows) exists, and you may need to create the <code>filetype.vim</code> file in that directory.
Also, on Windows, %HOMEDRIVE%%HOMEPATH% is used before %USERPROFILE% for the location of $HOME. I'm not sure how much of the stuff in {{help|todo.txt}} regarding the setting of $HOME in Windows is implemented, but I do know that my Windows installation picks up %HOMEDRIVE%%HOMEPATH% and not %USERPROFILE%.
 
:Looks like you're right. Vim71 uses %HOMEDRIVE%%HOMEPATH%, which is arguably broken (as it has been, neither runas or (presumably) roaming profiles work right), but current implementations don't use %USERPROFILE% at all. I guess it can just be $HOME as a wiki link and in that page a Win32 section explains it. Not sure if I'm more disappointed in Windows or Vim on this one. --[[User:JeremyBarton|JeremyBarton]] 16:49, 30 September 2008 (UTC)
 
   
  +
Contents of user <code>filetype.vim</code> (which may include other rules):
----
 
  +
<pre>
Problems, problems... I'm processing the proposed new tips for September. Apart from redirects, every page in our Main namespace is a tip, and has one of these templates: [[Template:TipImported|TipImported]], [[Template:TipNew|TipNew]], [[Template:TipProposed|TipProposed]]. I'm not going to put TipProposed on this (has an ugly box). Probably there should be ''no'' template and this should just be a normal Wikipedia-style page. However, I'm not ready to make decisions like that because I'm still in frantic "must clean up the old tips" mode. Also, it's ''really'' handy having simple tip numbers to refer to pages while doing lots of maintenance work. So, I've put TipNew with a dummy tip number and will think about it later. Let's delete my comment in a week or so, when everyone has had a chance to see it. --[[User:JohnBeckett|JohnBeckett]] 00:40, 1 October 2008 (UTC)
 
 
if exists("did_load_filetypes")
  +
finish
  +
endif
  +
augroup filetypedetect
  +
au! BufNewFile,BufRead *.csv setf csv
  +
augroup END
  +
</pre>
   
  +
As well as configuring <code>filetype.vim</code>, you may need the following commands (which would normally be in your [[vimrc]]) to enable all the features available for a particular file type.
----
 
  +
<pre>
  +
:set nocompatible
  +
:filetype indent plugin on
  +
:syntax on
  +
</pre>
   
  +
==References==
I personally ''like'' the tip numbers (don't really have a reason why though, I never use them), so I see no reason ''not'' to use TipNew, TipProposed, etc. I'm not sure why this tip isn't going through the usual process, though I suppose there isn't much chance of it ''not'' being accepted. Perhaps you are saying that this page isn't really a "tip" so much as a reference page? If we want to start doing that, there are quite a few other tips (that mass add back in February comes to mind, as well as the "mapping keys" tutorials) that the same sort of thing might apply to...but how should we handle that?
 
 
*{{help|filetype}}
 
*{{help|new-filetype}}
 
*{{help|'filetype'}}
 
*{{help|:setf}}
 
*{{help|'runtimepath'}}
   
  +
==Comments==
--[[User:Fritzophrenic|Fritzophrenic]] 14:01, 1 October 2008 (UTC)
 
 
*Possibly mention the "ftdetect" directory. {{help|ftdetect}}

Latest revision as of 08:47, 9 June 2014

Tip 1606 Printable Monobook Previous Next

created 2008 · complexity basic · author JeremyBarton · version 7.0


This tip is a tutorial on the use of the file filetype.vim which is used to determine the "type" of a file. For example, while editing example.py the command :set ft? should display filetype=python if :filetype indent plugin on has been used. The file type determines whether any plugins for scripts, indenting rules, or syntax highlighting are loaded. See file type plugins for an overview.

File structure[]

Custom filetype.vim files should always have the following structure:

if exists("did_load_filetypes")
  finish
endif
augroup filetypedetect
  " au! commands to set the filetype go here
augroup END

Files that are being used as fallbacks (in the after directories) should use a form such as

if exists("did_load_filetypes_userafter")
  finish
endif
let did_load_filetypes_userafter = 1
augroup filetypedetect
  " au! commands to set the filetype go here
augroup END

because did_load_filetypes will be set before the after files are used. Using the suffixes _userafter and _systemafter as appropriate will prevent one from interfering with the other.

File contents[]

Between augroup filetypedetect and augroup END there will be one or more autocmd statements that may assign a filetype when the BufNewFile and BufRead events occur (that is, when a new file is created, or when an existing file is read).

Following are some examples to illustrate common scenarios.

Assign the dosbatch filetype to any file with name ending in .bat or .sys:

au! BufNewFile,BufRead *.bat,*.sys setf dosbatch

If the first line of a .cmd file begins with /* then assign the filetype rexx, otherwise assign the filetype dosbatch:

au! BufNewFile,BufRead *.cmd if getline(1) =~ '^/\*' | setf rexx | else | setf dosbatch | endif

If the first line of a .bat file contains "--*-Perl-*--" then assign the filetype perl, otherwise do nothing and continue processing rules (see tip):

au! BufRead,BufNewFile *.bat if getline(1) =~ '--\*-Perl-\*--' | setf perl | endif

When reading a .btm file, if the variable g:dosbatch_syntax_for_btm is defined and non-zero then assign the dosbatch filetype, otherwise assign the btm filetype.

au! BufNewFile,BufRead *.btm call s:FTbtm()
function! s:FTbtm()
  if exists("g:dosbatch_syntax_for_btm") && g:dosbatch_syntax_for_btm
    setf dosbatch
  else
    setf btm
  endif
endfunction

File locations[]

The file filetype.vim is read from directories in the runtime path. The first match which executes :setf will set the filetype for the file Vim is creating or reading. If no rules execute :setf then additional filetype.vim files will be read.

The file locations (in the order that the files are processed) are:

User-specific primary definitions
Rules for the current user that should be attempted before any other rule.
$HOME/.vim/filetype.vim (Unix-based systems)
$HOME\vimfiles\filetype.vim (Windows systems)
System primary definitions
Rules for all users on a system (usually requires administrative rights to edit).
$VIM/vimfiles/filetype.vim (all systems)
Vim default ruleset
Rules that are part of the Vim install (do not edit this file).
$VIMRUNTIME/filetype.vim (all systems)
System fallback definitions
Rules for all users if no other rule has matched so far. Useful for a rule that you would want to stop using if a future version of Vim defined a better match.
$VIM/vimfiles/after/filetype.vim (all systems)
User-specific fallback definitions
Rules for the current user if no other rule has matched so far.
$HOME/.vim/after/filetype.vim (Unix-based systems)
$HOME\vimfiles\after\filetype.vim (Windows systems)

In Vim, use commands like the following to check these locations:

:echo $HOME
:echo $VIM
:echo $VIMRUNTIME

On Windows systems, $HOME is set from the environment variable HOME, if defined; or is set by joining variables HOMEDRIVE and HOMEPATH, if they are defined. At command prompt (not in Vim), enter set H to display the environment variables that begin with 'H'.

Example[]

When using our CSV tip, it is necessary to specify that *.csv files have the csv file type. To do this, edit the following file:

  • $HOME/.vim/filetype.vim (Unix based systems)
  • $HOME/vimfiles/filetype.vim (Windows systems – can use forward slash or backslash in Vim)

Check that $HOME has been defined, and that the $HOME/.vim directory (Unix) or $HOME/vimfiles directory (Windows) exists, and you may need to create the filetype.vim file in that directory.

Contents of user filetype.vim (which may include other rules):

if exists("did_load_filetypes")
  finish
endif
augroup filetypedetect
  au! BufNewFile,BufRead *.csv setf csv
augroup END

As well as configuring filetype.vim, you may need the following commands (which would normally be in your vimrc) to enable all the features available for a particular file type.

:set nocompatible
:filetype indent plugin on
:syntax on

References[]

Comments[]