Сделайте vim indent директивы препроцессора C такими же, как и другие инструкции

Главная информация

(Примечание: пожалуйста, прочтите это до конца, потому что я потратил немного времени на его организацию, убедившись, что я рассмотрел каждую отдельную проблему, с которой я столкнулся, и почему одно предложенное решение не работает для меня.)

Я использую cindent в vim, чтобы автоматически делать отступы. В большинстве случаев он отлично работает. Однако cindent совершает три плохих дела (на мой взгляд), связанных с директивами препроцессора C (операторы, начинающиеся с решетки ('#')).

Если это актуально, я использую вкладки для отступов, и мой .vimrc содержит filetype indent on.

Плохая вещь 1

Как только я набираю директиву препроцессора, vim помещает ее в столбец 1 (полностью удаляет отступы). Например, вот что vim делает с моим кодом, когда я его набираю:

int main(void)
{
    while(1) {
        /* normal things */
#ifdef DEBUG
        printDebugInfo();
#endif
        /* normal things */
    }
}

Однако я хочу, чтобы это выглядело так:

int main(void)
{
    while(1) {
        /* normal things */
        #ifdef DEBUG
        printDebugInfo();
        #endif
        /* normal things */
    }
}

Другими словами, я бы предпочел, чтобы vim обрабатывал директивы препроцессора как любой другой оператор C / C ++.

Плохая вещь 2

Когда я использую == на (или [movement]= поперек) строке с директивой препроцессора, vim помещает ее обратно в столбец 1. (Это соответствует Bad Thing 1, но все еще является проблемой.)

Плохая вещь 3

Если (из-за Плохой вещи 1 или 2 или использования <<) директива препроцессора попадает в столбец 1, она застревает там, и >> на нее не влияет. Единственный способ увеличить отступ - I<Tab> или i<Ctrl-t>. Затем он отключается, и я могу переместить его с помощью << или >>.

Неудачные решения

Одно решение предлагает поместить set cinkeys-=0# в мой .vimrc. Это исправляет плохие вещи 1–3, но добавляет новый:

Bad Thing 4 (только с cinkeys-=0#)

Директивы препроцессора в столбце 1 не зависят от == или [movement]=, что означает, что я все еще не могу автоматически исправить их отступ, пока я вручную не сделаю отступ с помощью >> или путем вставки символа табуляции.

Вопрос

Есть ли способ разрешить Плохие вещи 1–3, не вводя Плохие вещи 4? Могу ли я заставить vim обрабатывать строки, начинающиеся с '#', как обычные операторы C?

(Или я просто использую #ifdefs во вред, и это способ vim говорит мне остановиться?)

Я бы предпочел не патчить vim и / или перекомпилировать, но сделаю это, если потребуется.


person Dr Kitty    schedule 16.04.2013    source источник
comment
Однако я хочу, чтобы это выглядело так Многие люди скажут вам, что нет, вы не хотите, чтобы это выглядело так. Предварительная обработка происходит в другое время и на другом уровне, чем собственно компиляция, и отступы, когда вы предлагаете, рискуют спутать две идеи. Во-вторых, многие (большинство?) Людей считают, что предварительную обработку следует рассматривать как исключительный случай и что должно выделяться в коде.   -  person dmckee --- ex-moderator kitten    schedule 17.04.2013
comment
@dmckee Я уверен, что это правда, но отладка проблем с областью видимости по-прежнему становится кошмаром, когда у вас есть десятки отладочных флагов с вложенными условиями if, а g ++ жалуется на эту переменную xyz was not declared in this scope, и это буквально выглядит как встроенный инопланетный код, пытающийся что-то изобразить , как Витрувианский человек Давинчи   -  person puk    schedule 29.11.2013
comment
У меня точно такая же проблема, но это происходит, когда я нахожусь в python, и это каждый комментарий. Мой cinkeys=0{,0},0),:,!^F,o,O,e, это то, что рекомендуется в решении, но иногда такое случается. Это случается даже после того, как я set nocindent   -  person Theo Belaire    schedule 10.02.2014
comment
О, понятно, smartindent настроен. Спасибо за все ссылки!   -  person Theo Belaire    schedule 10.02.2014
comment
Или я просто использую #ifdefs во вред, и это способ vim говорит мне остановиться? да.   -  person n. 1.8e9-where's-my-share m.    schedule 20.07.2017
comment
Примечание: в настоящее время использование отступов для директив - это нормально, но некоторым старым компиляторам это может не понравиться. См. здесь   -  person lucidbrot    schedule 27.11.2020
comment
@dmckee --- ex-moderatorkitten Сворачивание констант происходит раньше в компиляторе, поэтому любое постоянное выражение также должно быть слева, чтобы вы не путали его с другими вещами. Кроме того, перед компиляцией раскрываются вызовы макросов, а не только директивы #ifdef, поэтому в случае, если getchar может быть макросом, вы также должны выровнять это выравнивание с левым столбцом.   -  person Kaz    schedule 12.04.2021


Ответы (2)


Из документации Vim в разделе cinoptions:

Vim помещает строку в столбец 1, если:

  • Он начинается с '#' (директивы препроцессора), если 'cinkeys' содержит '#'.
  • Он начинается с метки (ключевое слово, за которым следует «:», кроме «case» и «default»), а «cinoptions» не содержит записи «L» с положительным значением.
  • Любая комбинация отступов приводит к тому, что строка имеет отступ менее 0.

Таким образом, удаление 0# из cinkeys должно переопределить поведение по умолчанию. (Эта идея встречается достаточно часто в Интернете.)

set cinkeys=0{,0},0),:,!^F,o,O,e

С этим изменением в cinkeys, вот что у меня есть, именно то, что вы ищете:

int main(void)
{
    while(1) {
        /* normal things */
        #ifdef DEBUG
        printDebugInfo();
        #endif
        /* normal things */
    }
}
person Mogsdad    schedule 17.04.2013
comment
Спасибо за усилия, но я специально рассмотрел удаление 0# в моем исходном вопросе в разделе «Неудачные решения». Возможно, это ближе всего к тому, что я хочу, но я все же хотел бы посмотреть, смогу ли я полностью отказаться от специальной обработки директив препроцессора. - person Dr Kitty; 17.04.2013
comment
Вы набрали set cinkeys и подтвердили, что у вас там нет 0#? А вы пробовали просто заново вставить возврат каретки? Вот что я сделал. Конечно, отстой с тысячами строк. - person Mogsdad; 17.04.2013

Решение для Bad Thing 4

set cinoptions+=#1s

Это приведет к отступу на 1 смену, если вы используете == или [movement]=. Комбинирование его с опцией cinkeys-=0# сработало для меня.

person leo    schedule 22.08.2016