The Vim help documentation on |options| makes distinctions between options and option values; and between global, local, and global-local options. It is extremely confusing, especially given |local-options|:
"It's possible to set a local window option specifically for a type of buffer.... Vim keeps a global value of the
local window options, which is used when editing another buffer. Each window has its own copy of these values. Thus these are local to the window, but
global to all buffers in the window."
In the subsequent example, it shows that :setlocal list makes the local window option local to a buffer. But what about global or global-local window options?
Can anyone explain the reason for the difference in terminology between options and values, and between the three types of options?
Well, it's pretty easy, IMO. Just think of what an option is used for.
Say, confirm is global, as it makes sense per Vim instance. Hence, even if you execute setlocal confirm, that would silently change a global option, as it's the only one existing.
Next, expandtab is local per buffer (note: some options can be local per window, such as :h 'diff', for instance). However, there exists both global expandtab (which is essentially is "the current default value" of expandtab for newly created buffers) and local expandtab (one per each existing buffer). Also note that some "defaults" are pretty much useless (e.g. filetype will be set by ftdetect anyway, but, nonetheless, the global filetype exists).
Now, what's a global-local thing? That's simply an option which may (or may not) be created for every existing buffer. But, of course, there's always a global option of this kind.
How it's different from an ordinary local option? Say you have in your vimrc:
setglobal noexpandtab noautoread
Now you run your Vim and enter:
:setlocal expandtab? autoread?
And then you get in response:
noexpandtab
--autoread
That means you have a buffer-local copy of your global expandtab, but local autoread was not created at all in the current buffer, so Vim would use a global value whatever it'd be.
To summarize said above:
"Global option" means that no local value exists at all. So global value is always used.
"Local option" means that all buffers (or windows) always have a copy of their own, and so "global" value is only meaningful as the default value.
"Global-local option" means that some buffers (or windows) may have their copy, but others may not. So Vim uses the current local option if set, otherwise it uses the global option.
Related
I am editing a python file. My current settings for tabstop are as follows(just experimenting things):
~/.vimrc: set tabstop=4
~/.vim/ftplugin/python.vim: set tabstop=2
There is no ~/.vim/after/plugin/python.vim file
set tabstop? shows tabstop=8
verbose set tabstop? shows tabstop=8. Last set from /usr/share/vim/vim80/ftplugin/python.vim
My questions:
Why is tabstop settings at 8 even though i have explicitly set it to 4 in .vimrc file or 2 in ~/.vim/ftplugin/python.vim file
When is each of the files i.e. ~/.vimrc, ~/.vim/ftplugin/python.vim, ~/.vim/after/plugin/python.vim, /usr/share/vim/vim80/ftplugin/python.vim loaded?
Which file takes priority and where should I define my settings to override the others?
How is set different from set local?
It would be great if someone answers all these questions. It will surely benefit people especially Vim beginner and intermediate users as all of these concepts are inter-related
tabstop is the width of space represented by a tab character in the file, but the width of space inserted when you press Tab on your keyboard is controlled by softtabstop (if it's set to a non-zero value). Nothing weird is going on with order of evaluation, or setlocal, or any of the other things you're asking about.
See also What is softtabstop used for? on the Vim StackExchange.
tabstop is a buffer-local setting. That means that every buffer has its own value. So by setting it from your vimrc you only set the global default which will probably be overwritten by ftplugin and such.
The plugin's code resides in $VIMRUNTIME/ftplugin.vim. Roughly speaking, what it does is runtime! ftplugin/python.vim. runtime! differs from source in two aspects: (a) it searches along :h 'runtimepath', and not in the current directory; (b) it sources all files found (that's what the "bang" stands for), not only the first one.
So, because of (b), ftplugin first sources your ~/.vim/ftplugin/python.vim, and then $VIMRUNTIME/ftplugin/python.vim. For this reason your setting gets finally overwritten.
This is why usually we want ~/.vim/after/ftplugin/python.vim instead. Also note that standard "ftplugin"-scripts have the guard against multiple sourcing:
if exists("b:did_ftplugin")
finish
endif
let b:did_ftplugin = 1
....
So if you really want it, you can put this on top of your ~/.vim/ftplugin/python.vim and exclude all the stuff from $VIMRUNTIME/ftplugin/python.vim. Rarely wanted though.
The difference between set, setglobal and setlocal is actually the difference between option types: global, local-to-buffer, local-to-window, global-local. To keep the things simple, setglobal sets a global value for an option, setlocal sets a local one, and set does something "reasonable" (tm). In particular, set tabstop=x sets both global and local (current buffer's one) values.
Im currently making a lot of changes in my .vimrc. At the same time Im also coding away on a project. To fix the new indentation and tabstop rules, and so on, I have to go through every line and re-indent them. This seems a little bit tedious.
Is there any way to apply the newest changes in my .vimrc to the whole source file?
Your problem seems to be that existing buffers do not get the updated (global) values of e.g. 'tabstop', because these are buffer-local options. Therefore, a simple :so % after editing the ~/.vimrc isn't sufficient.
There are several possible approaches:
Use sessions
With the current Vim state persisted via :mksession, you can safely :quit Vim, restart it, :so session.vim, and have the identical editing state, but with the new settings applied (this requires that you :set sessionoptions-=options)
Manually apply
You can e.g. :yank the changed :set tabstop=... commands that you've edited and reapply them to all existing buffers, e.g. by moving there and :#", or (if there are many) with the help of :bufdo.
Note that especially the indent settings can also be set from ftplugins, so your global settings may not be effective. You can check that for a buffer with :verbose set tabstop?.
In vimlanguage, you can set options for the current buffer only using setlocal.
However, I need to set a more complex expression than just a literal, which isn't possible with setlocal.
I currently have let &formatprg=s:prgpath." ".a:args, but this sets the formatprg for all buffers, which is not what I want.
How would I set the formatprg like above, only for the current buffer?
Use let &l:option instead of let &option to only change the local value, like setlocal option. Similarly, let &g:option would only set the global value, like setglobal option. See :help :let-option for more information.
Note that formatprg in particular is global (no "local to buffer" in its help).
Making a global option buffer-local requires changes to Vim's source code. Alternatively, I've just published the GlobalOptions plugin that uses autocmds to work around this, and turns any global option into a buffer- or window-local one.
Several users in this epic question put the following in the .vimrc:
" Necesary for lots of cool vim things
set nocompatible
But is it really necessary? From the docs:
'compatible' 'cp'
boolean (default on, off when a |vimrc| or |gvimrc| file is found)
If set nocompatible is going in a .vimrc, that means that a .vimrc file exists, seemingly making it pointless.
If it is the system-wide vimrc, this option won't be off. So, if you're changing the system-wide vimrc and you want it, you need to set it.
From the documentation section *compatible-default* (emphasis mine):
When Vim starts, the 'compatible'
option is on. This will be used when
Vim starts its initializations. But
as soon as a user vimrc file is found,
or a vimrc file in the current
directory, or the "VIMINIT"
environment variable is set, it will
be set to 'nocompatible'.
Another difference is that explicitly setting 'nocompatible' overrules calling vim with the -C flag.
In any other scenario, yes, setting 'nocompatible' in your vimrc is a noop.
In the end I think it's just a matter of "better safe than sorry".
Many people share their .vimrc files on GitHub and I sometimes will test out settings without replacing my .vimrc file. vim allows me to do this with the -u flag.
vim -u test_vimrc
From vim ":help nocompatible"
(Note: This doesn't happen for the system-wide vimrc or gvimrc file,
nor for a file given with the |-u| argument).
This means that if you share your .vimrc with someone and they use -u flag to load your file, vim won't be configured the same as if the file were named .vimrc and located in your home directory.
I was using vim in Cygwin on a Windows VM and every time I was in Insert Mode, pressing arrow keys would result in vim printing "A", "B", "C" or "D" on the screen instead of scrolling. I found a forum that said putting vim in nocompatible mode would fix it. Thankfully, it did.
I put "set nocompatible" in my ~/.vimrc file and the problem remains gone. So perhaps it's not 100% useless.
Based on what Johnny pointed out above, I was simply astonished when I just found THIS out:
$ cat /usr/share/vim/vimrc.tiny
" Debian system-wide default configuration Vim
set runtimepath=~/.vim,/var/lib/vim/addons,/usr/share/vim/vimfiles,/usr/share/vim/vim74,/usr/share/vim/vimfiles/after,/var/lib/vim/addons/after,~/.vim/after
set compatible
ARGH!!!
No I did NOT expect that.
Debian (or Debian Unstable aka Ubuntu) indeed DOES put up a nightmare to their users by overriding the default setting by set compatible.
I hope that you will now know why when you're coming from FreeBSD, the first thing you would have to do is override the system-wide setting by putting a set nocompatible into your own ~/.vimrc. Because otherwise you'd just produce letters instead of being able to move the cursor the way you've been used to.
I think this is a horrid idea. In other words, this set compatible line ought to be removed from the system-wide vimrc.tiny in both Debian and Ubuntu, because it will annoy new users who are not (yet) as smart as knowing how to get the cursor keys working.
It's things like these that force them to nano and others because of such entirely pointless blockers!
I would really want to talk with the dude who once propagated this change to the system-wide resource file in Debian. And maybe also to the people who acknowledged his change to the fullest.
Johnny is right: on your private PC, you may remove said line from the system-wide .vimrc (if there), and touch an empty .vimrc on your $HOME. Thanks so much for pointing that out, way less clutter again. Note that you MUST have that ~/.vimrc (even if empty!) as otherwise you will not be able to use the cursors without explicitly putting in set nocompatible.
got the same problem on using -u vimrc option, even doing set nocompatible was misbehaving with some of my older setting, after some search i found one compactible version that works for me:
" Avoid side-effects when nocompatible has already been set.
if &compatible
set nocompatible
endif
this avoid re-setting of nocompatible flag when it is already set.
vim :help nocompatible shows conditions when it set/resets the options value, scroll to that table of options and values, for quick reference, conditions that effect this behaviour are:
Option is set to the value given in {set value} when 'compatible' is
set.
Option is set to the value given in {set value} when 'compatible' is set AND is set to its Vim default value when 'compatible' is
unset.
Option is NOT changed when setting 'compatible' but IS set to its Vim default when 'compatible' is unset.
I understand that VIM makes a difference between set and setl in that the first one sets an option for all buffers while the latter one sets the option fur the current buffer only. This is evident if I have do a :set tw=80 as opposed to a :setl tw=80.
Now, when I do a :set ft=plsql, it only opperates on the current buffer although I did not do a setl. This, of course, makes sense. Yet, I fail to see if this is documented somewhere. So, the question probably boils down to: are there options that by default operate on the current buffer while others operate "everywhere" and where is that documented?
There are indeed options that operate on the current buffer (and indeed the current window in some cases). The documentation is with the documentation for the option. If you go to any option in :help option-list, it will have one of the following three strings as the third-ish line:
global
local to window
local to buffer
(or some combination of them). For example, :help 'ft' gives:
*'filetype'* *'ft'*
'filetype' 'ft' string (default: "")
local to buffer
{not in Vi}
{not available when compiled without the |+autocmd|
feature}
When this option is set, the FileType autocommand event is triggered.
All autocommands that match with the value of this option will be
executed. Thus the value of 'filetype' is used in place of the file
name.
So this option is local to the buffer. For more discussion, see:
:help option-summary
When you read a new buffer in vim, or move from one buffer to another, vim triggers the equivalent of BufEnter, which re-evaluates the filetype of the file in that buffer. You could potentially override this behavior by blowing away your ftdetectdirectory in ~/.vim and replacing it with a file containing only au BufRead,BufNewFile,BufEnter * set filetype=plsql, at which point all files would be read as SQL. If you were to unset all filetype detections, the autocommand would never trigger.