I am using Neovim (v.0.8.0) along with nvim-lspconfig and neoclide/coc.
It is working pretty well. The only problem being tab widths. If I am writing in say, Java or C, I use 4-space wide tabs, however if I am writing Javascript/Typescript, I prefer a 2-space wide tab.

How can I configure different tab sizes on a language basis?


1 Answer 1


The standard way to achieve that is to create for each type a file in: ~/.config/nvim/ftplugin:

  • ~/.config/nvim/ftplugin/java.vim
  • ~/.config/nvim/ftplugin/c.vim
  • ~/.config/nvimftplugin/javascript.vim
  • ~/.config/nvim/ftplugin/typscript.vim

In each of the file you can set the corresponding settings you would like to use for the associated file type:


setlocal expandtab
setlocal tabstop = 4
setlocal shiftwidth = 4


setlocal expandtab
setlocal tabstop = 2
setlocal shiftwidth = 2

For this mechanism to work you need to have the following option set in your ~/.config/nvim/init.vim:

filetype plugin on

If you need to override a setting that is set in the distribution $VIM/ftplugin/filetype.vim (e.g. $VIM/ftplugin/java.vim) you need to create the file in ~/.config/nvim/after/ftplugin (e.g. ~/.config/nvim/after/ftplugin/java.vim) instead and set the option there.

To have a clean solution your filetype.vim should also define the b:undo_plugin variable. It is a vim command (or a list of vim command separated by |) executed by Vim when the user decides to switch the buffer to another filetype.

In our example we should do:

let b:undo_ftplugin = ''

let b:undo_ftplugin .= 'let &expandtab = ' . 

let b:undo_ftplugin .= ' | '
let b:undo_ftplugin .= 'setlocal tabstop = ' . &tabstop
setlocal tabstop = 4

let b:undo_ftplugin .= ' | '
let b:undo_ftplugin .= 'setlocal shiftwidth = ' . &shiftwidth
setlocal shiftwidth = 4

It guarantee that when you switch the filetype you have a result that do not depend of the filetype you have 'visited'

But for tabstop the straightforward solution should work just fine.

An alternative is to have the following lines in your ~/.config/nvim/init.vim

augroup javaindent
  autocmd FileType java setlocal expandtab
  autocmd FileType java setlocal tabstop=4
  autocmd FileType java setlocal shiftwidth=4
augroup END

augroup typescriptindent
  autocmd FileType typescript setlocal expandtab
  autocmd FileType typescript setlocal tabstop=2
  autocmd FileType typescript setlocal shiftwidth=2
augroup END

Remark: The answer is edited for Neovim on Linux or MacOs. For a solution on Vim the path have to be slightly adapted:

  • ~/.config/nvim will become ~/.vim or ~/vimfiles on Windows
  • ~/.config/nvim/init.vim will become ~/.vimrc or ~/_vimrc on Windows
  • Thank you for the detailed answer! Since I am using a UNix basedOS (MacOS), I put the ftplugin directory within ~/.vim instead of ~/vimfiles. Also since I am using neovim, the ftplugin should go in ~/.config/nvim/
    – ABCDEF
    Oct 18, 2022 at 12:18
  • You are right I'll update the solution to be more unix/neovim based Oct 18, 2022 at 12:35
  • 2
    I default to ~/.vim/after/ftplugin to make sure nothing else overwrites my values. Also, don't forget b:undo_ftplugin
    – D. Ben Knoble
    Oct 19, 2022 at 19:31

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