Last updated August 22, 2015. Created on August 21, 2005.
Edited by jackbravo, mikejw, benjifisher, agileadam. Log in to edit this page.

Vim is an advanced text editor that seeks to provide the power of the de-facto UNIX editor 'vi', with a more complete feature set.

Vim Plugin for Drupal

The Vim Plugin for Drupal (available on provides the configuration information below along with additional goodies and hints for Drupal 6, 7, and 8.


The following commands will indent your code the right amount, using spaces rather than tabs and automatically indent after you start. The commands should be added to a .vimrc file in your home directory (~/.vimrc), you may need to create this.

set expandtab
set tabstop=2
set shiftwidth=2
set autoindent
set smartindent

If you would prefer not to have all your vim sessions use these settings, you can activate them in specific files using a "modeline". That is, within the first or last 5 lines of the file you are editing, add the following line:
// vim: set filetype=php expandtab tabstop=2 shiftwidth=2 autoindent smartindent:

Note that not everyone uses vim to edit files, so this line is for your convenience and may be removed prior to submitting changes. For more information on how to use modelines, type :help modeline in vim or gvim.

Syntax highlighting

If you enjoy syntax highlighting, it may be worth remembering that many of Drupal's PHP files are *.module or *.inc, among others.

Vim seems to syntax highlight *.inc files properly by default but doesn't know that some other files are PHP content. For *.module and *.install, use this snippet in .vimrc:

if has("autocmd")
  " Drupal *.module and *.install files.
  augroup module
    autocmd BufRead,BufNewFile *.module set filetype=php
    autocmd BufRead,BufNewFile *.install set filetype=php
    autocmd BufRead,BufNewFile *.test set filetype=php
    autocmd BufRead,BufNewFile *.inc set filetype=php
    autocmd BufRead,BufNewFile *.profile set filetype=php
    autocmd BufRead,BufNewFile *.view set filetype=php
  augroup END
syntax on


Omni completion provides smart autocompletion for programs. When invoked, the text before the cursor is inspected to guess what might follow. A popup menu offers word completion choices that may include struct and class members, system functions, and more. A similar feature in Microsoft Visual Studio is known as IntelliSense. To enable OmniCompletion for PHP just add this to you .vimrc

autocmd FileType php set omnifunc=phpcomplete#CompletePHP

OmniCompletion can also use a ctags file to provide completion for drupal functions (not only the the core PHP ones). You can use exuberant ctags to generate this file (on debian/ubuntu you can install it with "apt-get install exuberant-ctags"). From the root of your drupal folder you can run (taken from koumbit blog):

ctags --php-kinds=cdfi --languages=php --recurse --fields=+l

With this file in place, vim will load automatically it if you open your files from drupal's root directory or using this command from within vim:

:set tags=/path/to/your/ctags

Once the file is loaded you can use:

  • Ctrl-X Ctrl-O completion options after the first characters of an identifier (class, function, variable name)
  • Ctrl-] to jump to a function definition
  • Ctrl-T to move to the previous file

The Vim Plugin for Drupal takes care of setting the 'tags' and 'omnifunc' options as above. It also comes with tag files for Drupal core versions 6, 7, and 8, and it provides a drush command as a wrapper for ctags. See the project page for a screenshot of OmniCompletion in action.

You can also install the YouCompleteMe plugin ( that offers automatic auto complete (without having to use a keyboard shortcut to activate it).

Using these settings only with Drupal

  • Copy your .vimrc to .vimrc-drupal
  • Append these settings to the end
  • Run vim -u ~/.vimrc-drupal

To make this easier (using bash on UNIX or Linux), you could create an alias by typing:

alias vid="vim -u ~/.vimrc-drupal"

This allows you to just use the vid command instead of vi when you want to edit a Drupal file.
Note: To make this alias permanent add the above line to the .bashrc file in your home directory (*nix). More on the alias command
Also be aware that the -u option turns on 'compatible' (as in, compatible with vi) so you must put 'set nocompatible' at the top of your .vimrc-drupal otherwise you may get errors.

Using the snippetsEmu package for Drupal

There is a script which provides similar snippets functions to TextMate:
Just copy the php_snippets.txt to your ~/.vim/after/ftplugin/php_snippets.php and overwrite the old one
Now you can type fieldset and you get a definition for the fieldsets, if you just want to add single lines add for example #collapsed

Using the snipMate package for Drupal

There is another plugin which allows you to easily use and create snippets: . There are currently two projects that provide drupal snippets:

php_snippets.txt9.43 KB

Looking for support? Visit the forums, or join #drupal-support in IRC.


exhuma’s picture

You are missing out one of my favourite vim features... the modeline. Just put the following at the end of the source file (though in front of the ?> of course):

#vim: set expandtab tabstop=2 shiftwidth=2 autoindent smartindent:

Note: Don't forget the trailing colon!

from now on vim will use these settings once you open that file. This overrides your user-settings and is imho better than using a separate vimrc file and aliasing the command.

As a useful side-effect, these settings will then also come in effect on everybody else's box when opening your file. And hence help in a consistent coding standard. There are other ways of formatting the modeline for compatibility reasons. I prefer the above style. For more info enter :help modeline

Another note:
vim only looks for "vim: <instructions>:" so you can use whatever commenting style you like. You might argue that the usage of the pound symbol in this example is a bit out of place as the drupal coding standards discourage that character for comments. However, I personally have very similar coding style (only difference being indenting width ;) ) and use the pound symbol nevertheless. But only for 2 things. One: everything not code/logic-related, and two: a double pound for temporarily removed or debugging lines so I can grep those away ;).
As such, the vim modeline falls under the first case ;)



coofercat’s picture

I never knew this about vim... How nifty! It's going in all my source files from now on.

However, :help modeline explains you have to have a white space at the start. Adding in a reminder that it's PHP, we get:

# vim: set filetype=php expandtab tabstop=2 shiftwidth=2 autoindent smartindent:


// vim: set filetype=php expandtab tabstop=2 shiftwidth=2 autoindent smartindent:
emanaton’s picture

Also, don't the Drupal coding standards state one should wrap text at 80 chars? This helps ID such occurances:

" Highlight chars that go over the 80-column limit
:highlight OverLength ctermbg=red ctermfg=white guibg=red guifg=white
:match OverLength '\%81v.*'

Sean P. O. MacCath-Moran
Programmer Analyst
Voice & Fax: (877) 313-8381
Drupal at emanaton dot com

ghoti’s picture

That's neat, but I believe it's only comments that have to stay under 80 characters.

I don't think you can recognize overlength comment data within a /* ... */ block, or even to overlength portions on lines containing "//" using a "match".

You'd have to build that into a custom syntax, presumably in ~/.vim/after/syntax/php.vim. I haven't written vim syntax files before. Perhaps someone who knows how could contribute a snippit?

matason’s picture

It could probably do with some work but I came up with this:

:highlight OverLength ctermbg=red ctermfg=white guibg=red guifg=white
:match OverLength '\(^\(\s\)\{-}\(*\|//\|/\*\)\{1}\(.\)*\(\%81v\)\)\@<=\(.\)\{1,}$'

You can also use matchadd() like this:
:highlight ExtraWhitespace ctermbg=red guibg=red
:let a = matchadd('ExtraWhitespace', '\s\+$')
:highlight OverLength ctermbg=red ctermfg=white guibg=red guifg=white
:let b = matchadd('OverLength', '\(^\(\s\)\{-}\(*\|//\|/\*\)\{1}\(.\)*\(\%81v\)\)\@<=\(.\)\{1,}$')

davev’s picture

You may also want to set some of the PHP specific vim options.

Snipped from :help vim.php:

There are the following options for the php syntax highlighting.

If you like SQL syntax highlighting inside Strings: >

  let php_sql_query = 1

For highlighting the Baselib methods: >

  let php_baselib = 1

Enable HTML syntax highlighting inside strings: >

  let php_htmlInStrings = 1

Using the old colorstyle: >

  let php_oldStyle = 1

Enable highlighting ASP-style short tags: >

  let php_asp_tags = 1

Disable short tags: >

  let php_noShortTags = 1

For highlighting parent error ] or ): >

  let php_parent_error_close = 1

For skipping an php end tag, if there exists an open ( or [ without a closing
one: >

  let php_parent_error_open = 1

Enable folding for classes and functions: >

  let php_folding = 1

Selecting syncing method: >

  let php_sync_method = x

x = -1 to sync by search (default),
x > 0 to sync at least x lines backwards,
x = 0 to sync from start.


emanaton’s picture

Well... I don't care for the notion of maintaining two .vimrc files, but I wish to maintain distinct default vim characteristics separate from my drupal editing, so I used this approach instead.

.vimrc I left alone.

I created .vimrc_drupal with the changes I wish to have from drupal (ref. comments in this article).

I then added this alias:
alias dvim='cat ~/.vimrc ~/.vimrc_drupal > /tmp/.vimrc_combined && vim -u /tmp/.vimrc_combined'

In this way, the configuration I seek is achieved each time without the need for maintaining two complete .vimrc files. Is there a better way? It occures to me that one might add some command line foo to pass a parameter in to VIM that could then be dealt with using conditional statements in the .vimrc files, but I'm not sure how (or if) this can be done. Any thoughts?

Sean P. O. MacCath-Moran
Programmer Analyst
Voice & Fax: (877) 313-8381
Drupal at emanaton dot com

akahn’s picture

Perhaps you could simply put source ~/.vimrc in your .vimrc-drupal file.

frjo’s picture

I don't remember where I found this snippet but I have found it really helpful in keeping my code clean and neat.

" Highlight redundant whitespaces and tabs.
highlight RedundantSpaces ctermbg=red guibg=red
match RedundantSpaces /\s\+$\| \+\ze\t\|\t/
edrex’s picture

Here is a readymade ~/.vimrc with most of the settings above, for those that don't want to spend 20 mins fooling:

jd developer’s picture

Edrex, in case you didn't know - the above link is broken. I've added a gist with my own implementation available here:

Thanks for contributing.

caligari’s picture

I can't edit a module with no folding and others:

set foldmethod=indent
set foldnestmax=1

and use:
zo Zap Open
zc Zap Close
zO Zap Open recursive
zC Zap Close recursive

This is my favorite modeline:

// vim:fenc=utf-8:ft=php:ai:si:ts=2:sw=2:et:nu:fdm=indent:fdn=1:

fenc (fileencoding) Set utf-8 encoding (latin1 is usual).
ft (filetype) Set .module as php file type (with syntax).
ai (autoindent) Copy indent when starting new line.
si (smartindent) Indent when starting a new line after '{'.
sw (shiftwidth) Number of spaces to use for autoindent steps.
ts (tabstop) Number of spaces that a tab counts for.
et (expandtab) Use spaces to insert a tab.
nu (number) Precede each line with its line number.
fdm (foldmethod) Fold code by indent.
fdn (foldnestmax) 1 maximum nesting (functions in module).

mcantelon’s picture

Another handy thing you can do from Vim is check your PHP syntax. You can type shift-: then enter !php -l % to check the syntax of your last saved file. For convenience you can add the line cabbr pc !php -l % to your .vimrc file to enable you to check syntax by typing shift-: then entering pc.

-Mike Cantelon

snufkin’s picture

you can also use abbreviations as a way to quickly insert hooks. for this you will need to create a custom function, and an abbreviation:

iabbr Hook <C-R>=HookFunc()<CR>

" HookFunc(): Drupal helper function
function! HookFunc()
  let f = substitute(expand("%"), ".module", "", "g")
  return "function " . f . "_"

this replaces typed in Hook with function <yourmodulename>_.

nicholasThompson’s picture

If you edit a file which is not in the current directory then the substitute picks up the entire path to the file... eg:

vim modules/cck/content.module

If you typed Hook<code> then you get get <code>function modules/cck/content_

nicholasThompson’s picture

In the substitute, instead of using expand("%"), use expand("%:t"). The :t pulls off the tail of the path (%)....

winston’s picture

Probably won't affect all, but I had a problem where I was getting a lot of error message traceable to the php.vim syntax highlighting file. After a bit of googling I was able to solve it by adding "set nocompatible" to the custom vimrc-drupal file described above. I put it first so it ended up looking like this...

set nocompatible
set expandtab
set tabstop=2
set shiftwidth=2
set autoindent
set smartindent

Maybe my ignorance, but maybe it will save you 5 min :)
acrollet’s picture

I've written a plugin to allow posting and editing Drupal content from Vim - you can find it here if you're interested.

jan.koprowski’s picture

Solution described here force us to remember that we must use "vid" command. My propostion is make something like that.
Create (path is for unix system) ~/.vim/ftplugin/drupal.vim

set expandtab
set tabstop=2
set shiftwidth=2
set autoindent
set smartindent
set filetype=php

and then, in .vimrc, do something like that:

if has("autocmd")
  " Drupal *.module and *.install files.
  augroup module
    autocmd BufRead,BufNewFile *.module set filetype=drupal
    autocmd BufRead,BufNewFile *.install set filetype=drupal
  augroup END

Now we can use this configuration with our default vimrc file :) There is one more thing. PHP coding standards are different for different projects. So when we want use *.php or *.inc file with Drupal coding standards in this configuration we write just :set filetype=drupal and that is all :) Small thing but make a lot of happy :)

claar’s picture

I couldn't get your method to work, but I found a similar approach works well:

create ~/.vimrc-drupal as:

set expandtab
set tabstop=2
set shiftwidth=2
set autoindent
set smartindent
set filetype=php

add this to ~/.vimrc:

if has("autocmd")
  " Drupal *.module and *.install files.
  augroup module
    autocmd BufRead,BufNewFile *.module source ~/.vimrc-drupal
    autocmd BufRead,BufNewFile *.install source ~/.vimrc-drupal
  augroup END
jan.koprowski’s picture

I think there must be

filetype plugin indent on must be in .vimrc to automaticaly load new filetype configurations from ~/.vimrc/ftplugin

jan.koprowski’s picture

Good point :o)

sampattuzzi’s picture

Thank you for the much more elegant solution.

However if you want syntax highlighting you might want to append syntax on to the end of .vim/ftplugin/drupal.vim to renable it (it seems to get switched off somehow).

wik’s picture

You might be interested in snipMate.vim as well :)
Which aims to be a concise vim script that implements some of TextMate's

For a quick introduction, see this screencast:

theunraveler’s picture

Thanks for the snipMate recommendation! It's much more concise than snippetsemu.

I started creating some Drupal snippets for snipMate. So far, I only have some of the more important hooks and form elements, but I'm adding to it daily. Check it out on github.

agileadam’s picture

I've always loved the omni-completion feature in Vim. It's really nice to be able to see exactly what parameters a function takes. Here is a link to the github page for a Drupal 6 omni-completion plugin I've written.

Enjoy, and make sure you follow the directions and read the help docs (they're nice and short)!

Aron Novak’s picture

" automatically remove trailing whitespace before write
function! StripTrailingWhitespace()
normal mZ
if line("'Z") != line(".")
echo "Stripped whitespace\n"
normal `Z
autocmd BufWritePre *.module,*.install,*.inc :call StripTrailingWhitespace()
Just according to , no trailing whitespaces are allowed, vim can help to enforce it.
benjifisher’s picture

If you want to avoid having your script clobber the Z mark (which the vim user may want to use for something else), then you can use the Mark() function from foo.vim. Note that if you

:normal mZ
:" Do stuff, moving out of the current window.
:normal `Z
then the current line is placed in the middle of the window at the end. The Mark() function will restore the screen position, too.
pmelab’s picture

When typing arrays (which we do a lot, don't we?) my vim indents it like this:

$test = array(
    'key' => 'value',

... instead of the drupal-standard:
$test = array(
  'key' => 'value',

I've seen this issue in has been tackled for Emacs. Is there a solution for vim too?
matason’s picture

It's working fine for me, check my .vimrc against yours, perhaps try using mine and see if it makes any difference?

pmelab’s picture

Yes! Got it. Thanks!

patcon’s picture

Thanks man! This was really useful!

benjifisher’s picture

I think the important line from your vimrc file is

:filetype plugin indent on

This enables the PHP indenting file included in the standard vim distro. See
:help 30.3

in the vim users' manual.
benjifisher’s picture

Vim has wonderful options for formatting comments. The easier it is to write our Doxygen comment blocks, the better we will document our code, right?

For starters, try

:set textwidth=80
:set formatoptions=croql
(Short option names: tw and fo.) Since the formatoptions option includes the 'c' flag but not the 't' flag, this will break comments, but not "text" (non-comments) at 80 characters. The 'r' and 'o' flags mean that the comment leader will be inserted automatically after hitting <Enter> in Insert mode or when using 'O' or 'o' to open a new line. The 'q' flag allows you to format comments (adjust the line breaks) using q<motion>. The 'l' flag means that if a line was already long before you started editing it, then it will not be broken while in Insert mode.

Now, to format the Doxygen comments:

:set comments=sr:/**,m:*\ ,ex:*/,://
The 's', 'm', and 'e' stand for start, middle, and end. The 'r' means that the comment leaders will be right-aligned. The 'x' means that, after starting a new line and having the ' * ' inserted automatically, you can just type / to close the comment block.

The last part recognizes the // style of comment. The Drupal coding standards "discourage" the use of # for comments.

By default (assuming you have loaded the PHP filetype plugin) vim recognizes HTML-style comments in PHP files. I am not sure, but I think that vim allows only one style of 3-part comments at a time.

Vim rocks!

jessehs’s picture

You can find discussion about vim, as well as a readymade vimrc file at

nyl_auster’s picture

you may also be interested by this vim configuration, specially made for drupal with hooks autocompletion.

thursday_bw’s picture

Having the latest checkout of the drupal code sniffer project. Running phpcs on code autoindented by vim with the above
configuration, fails standard indentation for arrays and switch statements.

The array indentation issue is solved in the above comment indent plugin

However the switch indentation issue is not.
To get my vim to indent my code correctly I made use of this very good php indent file available here: by installing that file in your ~/.vim/indent directory vim will be able to automatically indent your code in a way that conforms to the Drupal coding standard

benjifisher’s picture

The indent script you found is an updated version of the one included in the standard vim distribution.

  • 1.24 comes with vim 7.1.
  • 1.33 comes with vim 7.3.
  • 1.34 is the version you found.
  • 1.35 is available on GitHub

(I do not have a copy of vim 7.2 handy.)

I have not tested, but the change log suggests that 1.33 fixes the indenting of switch statements. So upgrade to vim 7.3 and you should be in good shape.

If you add this indent script to ~/.vim/indent/ then eventually you will upgrade to a newer version of vim and still be using the indent script that you downloaded today. If you want to use this version, I suggest placing it in the vim distribution directory, replacing the version that is already there.

ethanw’s picture

Vim's Syntastic plugin is a great tool for checking for both syntax errors and coding standards violations, when combined with the Drupal Code Sniffer project. I've posted instructions for how to get this set up on this EchoDitto Labs blog post.

ethan winn

ao2’s picture

Ah the smartindent option could create some issues, so you may want to remove it, see and replace it with file type indentation filetype plugin indent on or with C-style indentation set cindent.

If it is OK with you I would edit the page and remove the line about smartindent.

subhojit777’s picture

I used this code for identifying Drupal module files as php file.

if has("autocmd")
  " Drupal *.module and *.install files.
  augroup module
    autocmd BufRead,BufNewFile *.module set filetype=php
    autocmd BufRead,BufNewFile *.install set filetype=php
    autocmd BufRead,BufNewFile *.test set filetype=php
    autocmd BufRead,BufNewFile *.inc set filetype=php
    autocmd BufRead,BufNewFile *.profile set filetype=php
    autocmd BufRead,BufNewFile *.view set filetype=php
  augroup END
syntax on

This is not working for me. I was editing a template.php file and a module file, but vim was behaving in different way.. I saw that while writing block comments in template.php vim was auto inserting an *(asterick) in new line, but it was not doing the same in module file. I also saw that while writing code in module file when code gets longer than 80 characters vim creates a new line automatically(this was annoying me very much).. but no new line in template.php when code gets longer than 80 characters.

That means module file is not identified as php file. Although the syntax highlighting was working ok.. I think this is due to the <?php tag we enter in module file.

I changed the above code to this:

if has("autocmd")
  " Drupal *.module and *.install files.
  augroup filetypedetect
    au! BufRead,BufNewFile *.module setfiletype php
    au! BufRead,BufNewFile *.install setfiletype php
    au! BufRead,BufNewFile *.test setfiletype php
    au! BufRead,BufNewFile *.inc setfiletype php
    au! BufRead,BufNewFile *.profile setfiletype php
    au! BufRead,BufNewFile *.view setfiletype php
  augroup END

Just insert the above code at the end of your local vimrc. And everything is working fine now. module file editing is now same as editing a template.php :)

Got help from this stackoverflow answer

Also I noticed one thing.. when I write the new settings in global vimrc file it is not working. Writing the settings in local vimrc file works!

My vim version and plugins:
Version: 7.3.547
Plugins: delimitMate, HTML-AutoCloseTag, nerdcommenter, nerdtree, SearchParty, snipmate, syntastic, tagbar, vim-fugitive

Subhojit Paul

benjifisher’s picture


If you read the vim documentation, you can learn the difference between autocmd and autocmd!, between augroup module and augroup filetypedetect, and between set filetype=php and setfiletype php.

Or you could download the vimrc project, which already does all of this for you, and take advantage of the work done by someone who has already read the vim docs.