Найти в Дзене
Vim

VimScript 23 [ операторы сравнения >,<, ==, ==?, ==#]

Ранее мы рассмотрели условный оператор if но без сравнения он будет мало полезным. Да, Vim может сравнивать значения, но это не так просто, как может показаться. :if 10 > 1
: echom "foo"
:endif Пока все хорошо, Vim, выведет foo. Теперь выполните эти команды: :if 10 > 2001
: echom "bar"
:endif Vim ничего не выводит, потому что 10 не больше 2001. Пока все работает так, как ожидалось. Выполните следующие команды: :if 10 == 11
: echom "первый"
:elseif 10 == 10
: echom "второй"
:endif Vim выведет [ второй ]. Здесь тоже нет ничего удивительного. Давайте попробуем сравнить строки. Выполните следующие команды: :if "foo" == "bar"
: echom "один"
:elseif "foo" == "foo"
: echom "два"
:endif Vim выведет [ два ]. Пока все предсказуемо. Так о чём я говорил в самом начале статьи? Чувствительность к регистру Выполните следующие команды: :set noignorecase
:if "foo" == "FOO"
: echom "Vim НЕ чуствителен к регистру"
:elseif "foo" == "foo"
: echom "Vim чуствителен к регистру"
:endif
Оглавление

Ранее мы рассмотрели условный оператор if но без сравнения он будет мало полезным. Да, Vim может сравнивать значения, но это не так просто, как может показаться.

:if 10 > 1
: echom "foo"
:endif

Пока все хорошо, Vim, выведет foo. Теперь выполните эти команды:

:if 10 > 2001
: echom "bar"
:endif

Vim ничего не выводит, потому что 10 не больше 2001. Пока все работает так, как ожидалось. Выполните следующие команды:

:if 10 == 11
: echom "первый"
:elseif 10 == 10
: echom "второй"
:endif

Vim выведет [ второй ]. Здесь тоже нет ничего удивительного. Давайте попробуем сравнить строки. Выполните следующие команды:

:if "foo" == "bar"
: echom "один"
:elseif "foo" == "foo"
: echom "два"
:endif

Vim выведет [ два ]. Пока все предсказуемо. Так о чём я говорил в самом начале статьи?

Чувствительность к регистру

Выполните следующие команды:

:set noignorecase
:if "foo" == "FOO"
: echom "
Vim НЕ чуствителен к регистру"
:elseif "foo" == "foo"
: echom "Vim чуствителен к регистру"
:endif

Vim идет по ветке elseif, судя по видимому Vimscript чувствителен к регистру. Полезно, но ничего потрясающего. Теперь выполните эти команды:

:set ignorecase
:if "foo" == "FOO"
: echom "Да как такое возможно? Этого не может быть!"
:elseif "foo" == "foo"
: echom "Эта же строка должна была выводиться!"
:endif

Вот так так... Попробуйте понять что тут произошло. Да, вы правильно все поняли.

Поведение [ == ] зависит от настроек пользователя.

Серьезно, я не издеваюсь над вами. Изучите код еще раз. Я не шучу, такое я бы не смог выдумать. Это же просто полный "аллес гемахт" для того что бы свихнуться.

Защищенный код

Что это значит? Это означает, что вы никогда не сможете доверять [==] при сравнении, особенно если вы планируете написать плагин который будет использоваться другими людьми. Поэтому в ваших плагинах [ == ] он никогда не должен появляться.

Тут идея такая же, как и в "nmap" и"nnoremap". Никогда не доверяйте настройкам своих пользователей. Vim старый, обширный и сложный. При написании плагина вы должны предполагать, что у пользователей будут все варианты каждой настройки.

Итак, как нам обойти эту нелепость? Оказывается, у Vim есть два дополнительных набора операторов сравнения, чтобы справиться с этим.

Выполните следующие команды:

:set noignorecase
:if "foo" ==? "FOO"
: echom "первый"
:elseif "foo" ==? "foo"
: echom "второй"
:endif

Vim отображает [ первый ], потому что [ ==?] это оператор сравнения "без учета регистра, независимо от того, что установил пользователь". Теперь выполните следующие команды:

:set ignorecase
:if "foo" ==# "FOO"
: echom "
первый"
:elseif "foo" ==# "foo"
: echom "
второй"
:endif

Vim отображает [ второй ], потому что [ ==# ] это "чувствительный к регистру оператор сравнения, независимо от того, что установил пользователь".

Мораль всей басти такова: вы всегда должны использовать явные сравнения с учетом регистра или без учета регистра. Использование обычных форм неверно, и в какой-то момент оно сломается. Избавьте себя от лишних хлопот и введите дополнительный символ.

Когда вы сравниваете целые числа, это различие, очевидно, не имеет значения. Тем не менее, я думаю что лучше использовать сравнения с учетом регистра везде (даже там, где они не нужны), чем забыть их там, где они нужны.

Использование [ ==# ] и [ ==? ] с целыми числами будет работать просто отлично, и если вы измените их на строки потом, то это так же будет работать правильно. Если же вы предпочитаете использовать [ == ] для целых чисел, это нормально, просто помните, что если вам нужно будет изменить сравнение чисел на сравнение строк вам придется заменить оператор [==] на [ ==# ] или [ ==? ]

Упражнения

Поиграйте с :set ignorecase и :set noignorecase и посмотрите, как действуют различные сравнения.

Прочитайте :help ignorecase, чтобы понять, почему кто-то может установить эту опцию.

Прочитайте :help expr4, чтобы увидеть все доступные операторы сравнения.