Check variable change location in VIM? Or how to set shfitwidth? - vim

This is not a very simple question.
I found that the "shiftwidth" for python files are set to 4, while I have these at the bottom of my .vimrc:
set tabstop=2
set shiftwidth=2
set softtabstop=2
set expandtab
The shiftwidth are 2 for all other filetypes; but it's 4 only for python.
I want to know if it's possible to see where a variable (in my case, the shiftwidth) has been changed; if this is not possible when what are the possible locations that this variable is changed..? And is there any way go make the shiftwidth=2 universally... even for the python files? (Although it's also recommended of using 4 spaces for python, but I personally prefer 2)

:verbose set shiftwidth
tells you what's the current value and where it was defined. See :help :verbose.
Filetype plugins are sourced after the corresponding FileType event was triggered so they will override the options in your vimrc.
The dirty way to add filetype-specific settings to your config is to add something like this to your vimrc:
augroup Python
autocmd!
autocmd fileType python setlocal tabstop=2 shiftwidth=2 softtabstop=2 expandtab
augroup END
See :help :autocmd.
The clean way is to put your desired settings into a custom ftplugin.
The file:
~/.vim/after/ftplugin/python.vim
Its content:
setlocal tabstop=2
setlocal shiftwidth=2
setlocal softtabstop=2
setlocal expandtab
Note the use of setlocal instead of set because you don't want those settings to be applied everywhere.

This is probably being set by the built-in ftplugin file for Python. If you
:e $VIMRUNTIME/ftplugin/python.vim
and search for shiftwidth, you’ll probably find it set there to 4.

Related

Set different settings for different languages in Vim

I want to set different settings for different languages or
filetypes.
Every language has own style guides (e.g., different tab size, spaces instead tabs, etc.) so I can't add settings below in my .vimrc since I use vim with several languages. The settings should be separate for each language
Python files settings for 4 spaces indent style:
set tabstop=4
set shiftwidth=4
JavaScript files settings for 2 spaces indent style:
set tabstop=2
set shiftwidth=2
autocmd FileType python call Python_settings()
function! Python_settings()
setlocal tabstop=4
setlocal shiftwidth=4
setlocal expandtab
endfunction
Vim comes with built-in filetype detection that, among other things, makes it possible to do things differently for different filetypes.
For that mechanism to work, you need either of the following lines in your vimrc:
filetype on
filetype indent on
filetype plugin on
filetype indent plugin on " the order of 'indent' and 'plugin' is irrelevant
The first line only enables filetype detection.
The second line is like the first, plus filetype-specific indenting.
The third line is like the first, plus filetype-specific settings.
The fourth line enables everything.
Assuming you have either of the following lines:
filetype plugin on
filetype indent plugin on
you can create $HOME/vim/after/ftplugin/javascript.vim with the following content:
setlocal tabstop=2
setlocal shiftwidth=2
:setlocal is used instead of :set to make those settings buffer-local and thus prevent them to leak into other buffers.
the after directory is used to make sure your settings are sourced last.
Still assuming you have ftplugins enabled, there is nothing to do for Python as the default ftplugin already sets those options the way you want.

Setting tab width based on file type

I'm trying to learn to use Vim. I like indenting by 4 spaces but use 2 spaces for certain languages, such as Nim and MoonScript. I tried adding this to my .vimrc:
autocmd BufNewFile,BufRead,BufEnter *.nim :setlocal tabstop=2 shiftwidth=2 softtabstop=2
Problem? It doesn't do anything! All that happens is that the tab does nothing when I press it! What am I doing wrong?
autocmd BufNewFile,BufRead *.nim setlocal tabstop=2 shiftwidth=2 softtabstop=2
This should work (after restarting Vim / re-editing an existing file via :e!) fine, but it mixes filetype detection with filetype settings. Vim has an intermediate abstraction called filetype, which you should use. With it, you map file globs like *.nim to a filetype nim, and then define settings either via an :autocmd FileType, or a filetype plugin in ~/.vim/ftplugin/nim.vim (for the latter, you need :filetype plugin on in your ~/.vimrc).
Steps
So, create a filetype detection in ~/.vim/ftdetect/nim.vim:
autocmd BufRead,BufNewFile *.nim setfiletype nim
Then, create a filetype plugin in ~/.vim/ftplugin/nim.vim:
setlocal tabstop=2 shiftwidth=2 softtabstop=2
You can check that these are loaded correctly via the :scriptnames output. After a restart of Vim, this should work, and you can add additional settings to the latter file. If your filetype is derived from another, you can also add :runtime! ftplugin/javascript.vim (for example) in there to get those settings, too.

Can I made vimrc config valid for some type of files and invalid for others? [duplicate]

Could someone explain to me in simple terms the easiest way to change the indentation behavior of Vim based on the file type? For instance, if I open a Python file it should indent with 2 spaces, but if I open a Powershell script it should use 4 spaces.
You can add .vim files to be executed whenever vim switches to a particular filetype.
For example, I have a file ~/.vim/after/ftplugin/html.vim with this contents:
setlocal shiftwidth=2
setlocal tabstop=2
Which causes vim to use tabs with a width of 2 characters for indenting (the noexpandtab option is set globally elsewhere in my configuration).
This is described here: http://vimdoc.sourceforge.net/htmldoc/usr_05.html#05.4, scroll down to the section on filetype plugins.
Use ftplugins or autocommands to set options.
ftplugin
In ~/.vim/ftplugin/python.vim:
setlocal shiftwidth=2 softtabstop=2 expandtab
And don't forget to turn them on in ~/.vimrc:
filetype plugin indent on
(:h ftplugin for more information)
autocommand
In ~/.vimrc:
autocmd FileType python setlocal shiftwidth=2 softtabstop=2 expandtab
I would also suggest learning the difference between tabstop and softtabstop. A lot of people don't know about softtabstop.
edit your ~/.vimrc, and add different file types for different indents,e.g. I want html/rb indent for 2 spaces, and js/coffee files indent for 4 spaces:
" by default, the indent is 2 spaces.
set shiftwidth=2
set softtabstop=2
set tabstop=2
" for html/rb files, 2 spaces
autocmd Filetype html setlocal ts=2 sw=2 expandtab
autocmd Filetype ruby setlocal ts=2 sw=2 expandtab
" for js/coffee/jade files, 4 spaces
autocmd Filetype javascript setlocal ts=4 sw=4 sts=0 expandtab
autocmd Filetype coffeescript setlocal ts=4 sw=4 sts=0 expandtab
autocmd Filetype jade setlocal ts=4 sw=4 sts=0 expandtab
refer to: Setting Vim whitespace preferences by filetype
Put autocmd commands based on the file suffix in your ~/.vimrc
autocmd BufRead,BufNewFile *.c,*.h,*.java set noic cin noexpandtab
autocmd BufRead,BufNewFile *.pl syntax on
The commands you're looking for are probably ts= and sw=
I usually work with expandtab set, but that's bad for makefiles. I recently added:
:autocmd FileType make set noexpandtab
to the end of my .vimrc file and it recognizes Makefile, makefile, and *.mk as makefiles and does not expand tabs. Presumably, you can extend this.
Personally, I use these settings in .vimrc:
autocmd FileType python set tabstop=8|set shiftwidth=2|set expandtab
autocmd FileType ruby set tabstop=8|set shiftwidth=2|set expandtab
This might be known by most of us, but anyway (I was puzzled my first time):
Doing :set et (:set expandtabs) does not change the tabs already existing in the file, one has to do :retab.
For example:
:set et
:retab
and the tabs in the file are replaced by enough spaces. To have tabs back simply do:
:set noet
:retab
For those using autocmd, it is a best practice to group those together. If a grouping is related to file-type detection, you might have something like this:
augroup filetype_c
autocmd!
:autocmd FileType c setlocal tabstop=2 shiftwidth=2 softtabstop=2 expandtab
:autocmd FileType c nnoremap <buffer> <localleader>c I/*<space><esc><s-a><space>*/<esc>
augroup end
Groupings help keep the .vimrc organized especially once a filetype has multiple rules associated with it. In the above example, a comment shortcut specific to .c files is defined.
The initial call to autocmd! tells vim to delete any previously defined autocommands in said grouping. This will prevent duplicate definition if .vimrc is sourced again. See the :help augroup for more info.
Today, you could try editorconfig, there is also a vim plugin for it. With this, you are able not only change indentation size in vim, but in many other editors, keep consistent coding styles.
Below is a simple editorconfig, as you can see, the python files will have 4 spaces for indentation, and pug template files will only have 2.
# 4 space indentation for python files
[*.py]
indent_style = space
indent_size = 4
# 2 space indentation for pug templates
[*.pug]
indent_size = 2
While you can configure Vim's indentation just fine using the indent plugin or manually using the settings, I recommend using a python script called Vindect that automatically sets the relevant settings for you when you open a python file. Use this tip to make using Vindect even more effective. When I first started editing python files created by others with various indentation styles (tab vs space and number of spaces), it was incredibly frustrating. But Vindect along with this indent file
Also recommend:
pythonhelper
python_match
python_ifold
In Lua (for Neovim users) you can use RUNTIMEPATH/ftplugin/*yourfiletype*.lua with options like:
vim.opt_local.shiftwidth = 2
vim.opt_local.tabstop = 2
Just be sure to use string values in quotes. For example:
vim.opt_local.foldmethod = 'marker'
I use a utility that I wrote in C called autotab. It analyzes the first few thousand lines of a file which you load and determines values for the Vim parameters shiftwidth, tabstop and expandtab.
This is compiled using, for instance, gcc -O autotab.c -o autotab. Instructions for integrating with Vim are in the comment header at the top.
Autotab is fairly clever, but can get confused from time to time, in particular by that have been inconsistently maintained using different indentation styles.
If a file evidently uses tabs, or a combination of tabs and spaces, for indentation, Autotab will figure out what tab size is being used by considering factors like alignment of internal elements across successive lines, such as comments.
It works for a variety of programming languages, and is forgiving for "out of band" elements which do not obey indentation increments, such as C preprocessing directives, C statement labels, not to mention the obvious blank lines.

Automatic Hard vs Soft tab indentation based on type of file?

I'd like to default to soft tabs, indented two spaces (but hard tabs displayed as two spaces for Makefiles), and for vim to reindent appropriately on save.
See this question. For your case, you would want this in your .vimrc:
set tabstop=2
set softtabstop=2
set expandtab
And this in ~/.vim/after/ftplugin/make.vim:
setlocal noexpandtab
You can use autocmd for this, so it pretty much becomes a oneliner in your.vimrc
autocmd Filetype jade setlocal ts=2 sw=2 expandtab
autocmd Filetype yaml setlocal ts=2 sw=2 expandtab
Everything else will still use the global defaults.

When using listchars, I can only get 2-space hardtabs

I'm using the following .vimrc. Which contains (but not limited to) the following:
set encoding=utf-8
set tabstop=4
set autoindent
set list lcs=tab:·\ ,trail:•,eol:¬
This should give me four-space hard tabs, with the first character being displayed as a small mid-line dot, and the remaining three characters as spaces. But what I get is two-space hard tabs. Something else in my vimrc is throwing off the tab spacing.
Clearly I'm doing something wrong, and giving myself two-space hard tabs. I've researched listchars, vim compile flags and trying to input non-breaking space into my vimrc. Any other ideas what I'm doing wrong??
Just looked at your _vimrc; the confusion is in the following lines
augroup htmldjango
set tabstop=2
set softtabstop=2
set shiftwidth=2
augroup END
You're using set command and rewriting your previous tabstop, softtabstop and shiftwidth settings regardless of filetype. Therefore, you're effectively setting your tab to 2.
It would be better maybe (and my guess is this is what you were trying to do) were you to use
augroup htmldjango
autocmd!
autocmd FileType html setlocal tabstop=2
autocmd FileType html setlocal softtabstop=2
autocmd FileType html setlocal shiftwidth=2
augroup END
therefore setting different tabstop, softtabstop, etc. only when HTML filetype is used.
Notice: I have no idea what is a htmldjango filetype so you might want to modify that part for what suits you best.

Resources