18

I have two buffers in vim:

:ls
  1 %a   ".vimrc"                       line 1
  2 #h   "script.sh"                    line 1
Press ENTER or type command to continue

As seen above, I'm on the first buffer. Now if I execute the :set softtabstop=16 command, then I expect it to affect both buffers. However, this is not the case- while the sts value for first buffer is indeed changed and Tab key inserts four tab characters(ts=4), then for second buffer the sts value is still 4:

:ls
  1 #h + ".vimrc"                       line 1
  2 %a + "script.sh"                    line 1
  softtabstop=4
Press ENTER or type command to continue

Why is that so? I thought that set affects all the buffers and setlocal affects only the active buffer..

28

Options can be global, window-local, or buffer-local.

When you :set a global option, the new value is global.

When you :setlocal a global option, the new value is local.

When you :set a local option, the new value is local.

softtabstop being a buffer-local option, changing its value only affects the current buffer.

The "scope" of an option is indicated in :help option:

'softtabstop' 'sts'    number    (default 0)
                       local to buffer
                       {not in Vi}
Number of spaces that a <Tab> counts[...]

:help local-options, :help :setlocal, and :help global-local explain all that in more details.

| improve this answer | |
  • 3
    There's also a :setglobal. – Sato Katsura Sep 4 '16 at 7:13
  • 3
    Also, some options are global, no matter how you set them. E.g. 'encoding'. – Antony Sep 4 '16 at 20:45
  • Is there a way to set local function by buffer id and the option value with some a vimscript function call? – St.Antario Dec 2 '19 at 5:08
  • There is a function setbufvar which can be used to achieve that. Did not found it at first. – St.Antario Dec 2 '19 at 5:56
2

Not an expert, @Martin, but from reading :help set you would need to "unset" the local value of sts in each buffer to have that buffer pick up any new global value. setlocal sts= (or for boolean flags, setlocal flag<). Kinda makes sense, local settings initialized to current global values on open, then keep local values until told otherwise. If there is no local setting in play, it should pick up any new global values.

Again, not being an expert, I'd hazard a guess that that second buffer had an explicit local setting before the later set. More than 50/50 that my understanding is wrong, as I'm still unclear on what the difference between set and setglobal is.

| improve this answer | |
1

It seems to me set does both setl and setg. And they all depend if the option is global, local to buffer, or both (global-local).

Relevant vim help documentation:

                            *:se* *:set*
...
Handling of local options           *local-options*

Some of the options only apply to a window or buffer.  Each window or buffer
has its own copy of this option, thus each can have its own value.  This
allows you to set 'list' in one window but not in another.  And set
'shiftwidth' to 3 in one buffer and 4 in another.
...
When editing a new buffer, its local option values must be initialized.  Since
the local options of the current buffer might be specifically for that buffer,
these are not used.  Instead, for each buffer-local option there also is a
global value, which is used for new buffers.  With ":set" both the local and
global value is changed.  With "setlocal" only the local value is changed,
thus this value is not used when editing a new buffer
                            *:setl* *:setlocal*
:setl[ocal] ...     Like ":set" but set only the value local to the
            current buffer or window.  Not all options have a
            local value.  If the option does not have a local
            value the global value is set.
                            *:setg* *:setglobal*
:setg[lobal] ...    Like ":set" but set only the global value for a local
            option without changing the local value.

For buffer-local and window-local options:
    Command      global value       local value ~
      :set option=value      set        set
 :setlocal option=value       -         set
:setglobal option=value      set         -
      :set option?        -            display
 :setlocal option?        -            display
:setglobal option?      display      -


Global options with a local value           *global-local*
Options are global when you mostly use one value for all buffers and windows.
For some global options it's useful to sometimes have a different local value.
You can set the local value with ":setlocal".  That buffer or window will then
use the local value, while other buffers and windows continue using the global
value.
...
You can switch back to using the global value by making the local value empty: >
    :setlocal makeprg=
This only works for a string option.  For a number or boolean option you need
to use the "<" flag, like this: >
    :setlocal autoread<
Note that for non-boolean and non-number options using "<" copies the global
value to the local value, it doesn't switch back to using the global value
(that matters when the global value changes later).  You can also use: >
    :set path<
This will make the local value of 'path' empty, so that the global value is
used.  Thus it does the same as: >
    :setlocal path=
:setl[ocal] {option}<   Set the local value of {option} to its global value by
            copying the value.

:se[t] {option}<    For |global-local| options: Remove the local value of
            {option}, so that the global value will be used.
| improve this answer | |
  • 1
    Not exactly. It's setg and setl for local option, setg for global only, and setg option=value and setl option=<empty> for global-locals. – Matt Jun 7 at 8:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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