6

I have come across this behaviour and the documentation does not make sense to me.

Consider this sentence:

I am 100% sure there is something I am missing.
This is the next line.

Pressing w takes me to the start of the next word. What a word is, is defined by the 'iskeyword' option. % is by default not defined as part of a word in there. Yet, pressing w jumps to %. It does not jump to the dot at the end of the first line, so why is it jumping to the % symbol?

From the documentation:

Notice that "w" moves to the start of the next word if it already is at the start of a word.

(Taken from usr_03.txt)

Well it does not behave that way as far as I can see. w moves either to the beginning of a word or to %,(,`)``, whichever it finds first.

Can someone tell me why % is somehow considered a word, even if it is not in 'iskeyword', while a . is not considered a word, unless it is part of the 'iskeyword' option?

1

2 Answers 2

8

When you're using a w (or e, or b) command to move on a word that contains both characters listed in 'iskeyword' and characters not listed in 'iskeyword', then the w command will alternate between the sequences of keyword and non-keyword characters.

The last part of section 03.1 of the docs explain that:

A word ends at a non-word character, such as a ".", "-" or ")". To change what Vim considers to be a word, see the 'iskeyword' option.

Also, to be more explicit, what the docs refer to as a "non-word" character here, and the examples of ".", "-" and ")", are characters not listed in 'iskeyword'.

The last part of that documentation section shows a detailed example, with words separated by "/" or "," (which are typically not in 'iskeyword') and how w will move to the "/", or b will move to the ",".

In your example of 100%, you're correct that "%" is not in 'iskeyword'... But the digits in "100" are! Digits are part of 'iskeyword' by default. So when using the w command in 100%, it will skip from the group of keyword characters (100) to the group of non-keyword characters (%).

One way to experiment with this behavior is to remove the digits from 'iskeyword', which you can do with:

:set iskeyword-=48-57

After updating that setting, the w command will see the 100% string as a single sequence (a sequence of non-keyword characters) and w will skip the % stop. (Of course, and alternative way to accomplish the same is to add % to the list of characters in 'iskeyword'.)

2
  • 1
    Thank you very much for this extensive answer. I am still at odds with this behaviour, but now understand that it is intended. I'll add % to iskeyword and see gow it goes.
    – Ference
    Mar 14, 2022 at 5:23
  • Glad this answer helped you @Ference! I agree that this behavior can be counter-intuitive at the start, but you definitely get used to it! If this post answered your question, note that you can "accept" it, by clicking the gray check below the vote totals for the answer. Cheers!
    – filbranden
    Mar 14, 2022 at 23:52
3

For the purposes of w/b "word" movement, vi/vim classifies characters into not two but three classes:

  • "word" (alphanumeric plus iskeyword),
  • "white space", and
  • "others".

A "word" (in the lower-case w sense) is either any run of word characters, or any run of "other" characters. Pressing w repeatedly will happily skip from alphanumeric to "other" and back, without any intervening whitespace.

Vim's classifier only hardwires the ASCII alpha characters; the numeric characters are in the default set for iskeyword, which allows you to remove them if you wish. Other versions of vi simply hardware "alphanumeric" and don't have any way of changing the "word" characters.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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