From the :execute help (:h :exe):

                            *:exe* *:execute*
:exe[cute] {expr1} ..   Executes the string that results from the evaluation
            of {expr1} as an Ex command.
            Multiple arguments are concatenated, with a space in
            between.  To avoid the extra space use ------------------> ".." <----------
            operator to concatenate strings into one argument.

echo 'a' 'b' yields a b and both echo 'a'.'b' and echo 'a'..'b' yield ab.

So, are single dot and double dot the same? Also, how do I search for such things in Vim help? I tried :h ., :h dot, :h operatordot, without success.

  • Bonus tip on finding the help in addition to the answers already there: using :help ..<Tab> lists expr-.. if you have wildmenu set. Using the tab-completion is pretty useful to find the help pages, it doesn't always work and sometimes it's not clear which page to select from the completion so you need to try a few, but 95% of the time it gets me what I want pretty quickly. – Martin Tournoij Jun 24 at 0:17

The . and .. have semantically the same meaning of string concatenation. However, the . can also be used to access dictionary items and can as well be used for floating point numbers. So the meaning of . is actually ambigious. Therefore, it is not recommended to use the . for string concatenation. In fact, since vimscript-version 2, the . is no longer allowed to be used as concatenation operator.

But for legacy vimscript that must run on very old Vims, the . is still valid and can be used.

Note: regarding your second question, please have a look at :h help-summary. That will hopefully help to find the correct items, depending on the context.


Take note of the examples:

:execute "buffer" nextbuf
:execute "normal" count .. "w"

What it's indirectly saying is, to avoid a space in the resulting string that's executed, use .. instead of no operator at all. When there's no operator at all, each string or potentially variable is considered a separate argument.

The point behind using the .. operator is to do string concatenation instead of applying "simulated" varargs that have a space appended between each argument. In a manner of speaking, the way echo and execute works can be compared to Python's print() function: If you print('a', 'b'), you get a b, but if you print(a + b), you get ab. The point is, this demonstrates that . and .. do the same thing in this specific context: it does string concatenation instead of passing "multiple arguments" to echo. You've already noticed this on your own, but combined with how execute and echo work with space-separated strings, it might be more obvious that it's just normal string concatenation. Demonstration aside, let's look at some actual evidence of that from the help.

The page of the help you couldn't find is expr-. and expr-.. (they're adjacent in the help file, no need to look them up separately). To quote the help doc:

expr6 . expr6   String concatenation              *expr-.*
expr6 .. expr6  String concatenation              *expr-..*


For String concatenation ".." is preferred, since "." is ambiguous, it
is also used for |Dict| member access and floating point numbers. When
|vimscript-version| is 2 or higher, using "." is not allowed.

And from :h scriptversion-2:

<                         *scriptversion-2*  >
:scriptversion 2 
String concatenation with "." is not supported, use ".." instead.     This
avoids the ambiguity using "." for Dict member access and     floating
point numbers.  Now ".5" means the number 0.5.

Similarly, Vim9 has also decided to step away from . for string concatenation, with the same reason: the operator is ambiguous. As someone who has personally "inherited" some pretty old code with some shockingly ambiguous use of the . operator (sequential variables that look like member access instead of concatenation), this is definitely noticeable. I digress, however.

To answer your question, there is no difference. It's the same operator doing the same thing. The only difference is that . is substantially more ambiguous due to its other uses, which made Vim introduce .. to combat the ambiguity. You can use whichever you want, though the reason .. is used in the first place is because Vim overall seems to want to push in the direction of that operator.

As for finding it, I personally wrote :h .<tab> and used wildmenu to navigate until I found something that looked like it could be relevant ("expr-. looks awfully relevant given that it's used in an expression"). A more searchable option (in this case) would've been to use :helpgrep \cstring concatenation (\c means case-insensitive). This also gives a lot of additional help that covers . and .., and some of which again repeats how . is ambiguous and that .. is preferred.

See also this fantastic answer on navigating Vim's documentation - a part of it is still guessing relevant keywords, although that's not too different from using a search engine if you prefer thinking about it like that. (Documentation sprawl doesn't help either :) )

  • 1
    Nice explanations and references! It was indeed a typo, I fixed it now. – André Willik Valenti Jun 24 at 0:19

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.