1

В Vim поиск новой строки выполняется как \n , но новые строки в строке замены должны вводиться как \r . Я понимаю, что есть причины для такого поведения , но для моих целей я просто нахожу это раздражающим. Я хочу иметь возможность использовать \n для обозначения (по сути) одного и того же в шаблоне поиска и в строке замены: в частности, в шаблоне поиска он должен совпадать с символами новой строки, а в строке замены он должен вставлять символы новой строки.

Есть ли способ получить такое поведение? Я не думаю, что сработают простые переназначения, так как команду замены необходимо проанализировать, чтобы определить, является ли \n частью шаблона поиска или строки замены.

3 ответа3

3

Вы должны подключиться к командной строке; либо при выполнении через <CR> , либо сразу при вводе \n . С :help c_CTRL-\_e вы можете оценить функцию и изменить командную строку. Вот демонстрация, которую вы можете построить и усовершенствовать (проверка на замену сейчас упрощена):

cnoremap n <C-\>eTranslateBackslashN()<CR>
function! TranslateBackslashN()
    if getcmdtype() ==# ':' && getcmdline() =~# 's/.*/.*\\$' " Improve this!
        return getcmdline() . 'r'
    endif
    return getcmdline() . 'n'
endfunction
1

Как писал Инго Каркат, решение можно найти с помощью c_CTRL-\_e . Вот версия, которую я использую, которая идентична исходному решению, за исключением шаблона регулярных выражений. (Так как это на самом деле просто ответ Инго Карката со скромным улучшением, предложенным Инго Каркатом, я не думаю, что на самом деле он заслуживает своего собственного ответа, но я думаю, что меня обошли стороной: http://chat.stackexchange.com/transcript/message/15021397 # 15021397)

function! TranslateBackslashN()
    if getcmdtype() ==# ':' && getcmdline() =~#
      \ '[%>]s\([um]\w*\)\?\(.\).\{-}\(\\\)\@<!\2.*\\$'
        return getcmdline() . 'r'
    endif
    return getcmdline() . 'n'
endfunction
cnoremap n <C-\>eTranslateBackslashN()<CR>

Объяснение шаблона регулярных выражений:

  • [%>]s гарантирует, что замена происходит только тогда, когда s приходит сразу после диапазона
  • \([um]\w*\)\? соответствует вариантам команды s , таким как smagic .
  • \(.\) будет первым несловесным символом, поскольку все символы слова уже будут съедены \w в необязательной группе. Обратите внимание, что это группа 2 . Это символ-разделитель, который обычно / . Обратите внимание, что _ , который является символом слова, также является допустимым разделителем, поэтому шаблон не будет работать правильно, если _ используется таким образом. Я никогда не использую _ как разделитель, поэтому я не буду беспокоиться об этом. Точно так же есть некоторые символы, которые не являются символами слова, но которые не должны использоваться в качестве разделителей, но я не беспокоюсь об этом здесь, потому что в этом случае команда все равно должна завершиться неудачей. Я хотел использовать \W здесь, но по какой-то причине это не сработало, когда я его тестировал.
  • .\{-} должно соответствовать шаблону (\{-} похоже на Perl *?).
  • \(\\\)\@<!\2 соответствует следующему экземпляру символа разделителя, которому не предшествует обратная косая черта. Перл эквивалент будет (?<!\\)\2 .
  • .* соответствует тому, что находится в строке замены до сих пор.
  • \\$ соответствует, только если команда до сих пор заканчивается обратной косой чертой.
0

Альтернативный ответ с помощью плагина (это решение, которое я решил использовать, хотя оно работает только с Vim 7.4+):

Используя Enchanted Vim, поместите let g:VeryMagicSubstituteNormalise = 1 в ваш .vimrc .

(Этот плагин использует плагин CRDispatcher , который позволяет заменять текст в командах после нажатия клавиши Enter, но до фактического выполнения команды. Таким образом, переназначение \n не требуется, и подстановка невидима для пользователя, поэтому \n может иметь одинаковое значение в обоих контекстах.)

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .