Vim: What's the difference between let and set?
:set
is for setting options, :let
for assigning a value to a variable.
It happens that the value for an option is linked to the name of the option prepended by a &
(the &option-name
construct then behaves very similar to "ordinary" variables). So, the following are equivalent:
:set tw=40
:let &tw=40
But, for example, assigning 50 to the global variable foo (:let g:foo=50
) cannot be achieved with a :set
command (because g:foo is a variable and not an option).
Some options are boolean like. When setting these, no value is needed (as in :set noic
and the opposite :set ic
).
Set is a more user-friendly interface specialized for options
E.g.
:verbose set
to display all options in effect.
:set tw=40
Will work as a shorthand for set textwidth=40
:set wrap&
Will set the default value for option wrap
:set nowrap
Will unset the option
:set wrap!
Will toggle the option
Most importantly,
:set
Tab # to get tab completion!
Few of the above can (easily) be achieved with let
.
:set
only works with options, and sehe's answer showcases some good usage examples.
:let
on the other hand can do almost everything that :set
can do, plus more. It can assign a value to
- a variable, e.g.
let vi = 'vim'
- an option, e.g.
let &tw = 40
- a register, e.g.
let @a = $HOME . '/vimfiles'
- an environment variable, e.g.
let $NOTHING = 'NOTHING'
Another major difference is that the right hand side of :let
is an expression, meaning you can do things like string concatenation (as seen in my register example above) and arithmetic operations (e.g. let &tw = 40 + 60
). This also means that you have to quote the value if it's a string. :set
on the other hand reads the value verbatim.
It's easier to use :set
with options even though :let
can also do most of it, Here are some comparison using sehe's examples ("n/a" means no way to do it with :let
)
:verbose set
vs n/a (don't think there's another way to list all options):set tw=40
vs:let &tw = 40
(yes, you can use the same shorthand inlet
too):set wrap&
vs n/a:set nowrap
vs:let &wrap = 0
(for boolean options, 0 is false and 1 is true):set wrap!
vs:let &wrap = !&wrap
A few more examples
- print the value of an option:
:set formatoptions?
vs:echo &formatoptions
(let
doesn't print values, unlikeset
) assigning to multiple options at the same time:
:set et sw=4 sts=4
vs
:let [&et, &sw, &sts] = [0, 4, 4]
set global option:
setglobal et
vslet &g:et = 1
- set local option:
setlocal et
vslet &l:et = 1
See :h :set
and :h :let
for more details
tl;dr
:set
only works with options but the syntax is much simpler. :let
works with not just options but also variables, registers, and environment variables. Unlike :set
, the right hand side of :let
is an expression.