Заменить на чистый vimscript (без `: s`)

12

У меня есть следующее в моем vimrc:

func! AddSpaceBeforeEqual()
  s/\([a-z)_0-9"'\[\]]\)=/\1 =/ge
endfunc

Я использую vint для lint мой vimrc, и получил следующее предупреждение:

ProhibitCommandWithUnintendedSideEffect Избегайте команд с непреднамеренными побочными эффектами. Избегайте использования: s [ubstitute], поскольку он перемещает курсор и печатает сообщения об ошибках. Предпочитают функции (такие как search ()), лучше подходящие для скриптов. Для многих команд vim существуют функции, которые делают то же самое с меньшим количеством побочных эффектов. Смотрите: help functions () для списка встроенных функций. Руководство по стилю Google Vimscript

Однако я не думаю, что это способ сделать замену без использования :sкоманды.

Например, search()функция выдает строки, соответствующие шаблону, но нет способа сделать замену. substitute()Функция работает на шнурке, и не подменять на весь файл.

Должен ли я сам реализовать метод замены или это более разумный способ переписать мою функцию?

edi9999
источник

Ответы:

10

Вот упрощенная реализация вашей функции, написанная с помощью substitute():

function! AddSpaceBeforeEqualInWholeBuffer()
    let l = 1
    for line in getline(1,"$")
        call setline(l, substitute(line, '\([^= ]\)=', '\1 =', "g"))
        let l = l + 1
    endfor
endfunction

Настройте шаблон поиска по вкусу.

romainl
источник
10

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

function! StripTrailingWhitespace()
    " Save cursor position
    let l:save = winsaveview()
    " Remove trailing whitespace
    %s/\s\+$//e
    " Move cursor to original position
    call winrestview(l:save)
    echo "Stripped trailing whitespace"
endfunction

Обратите внимание, что вы также можете использовать :markкоманду для сохранения позиции курсора, но это также означает, что вы будете перезаписывать метку, которую решили использовать. Я не использовал vint прежде, но один совет по линтерам, что вы можете принять их предупреждения с небольшим количеством соли. В этом случае это правда, что :substituteесть побочные эффекты, но они являются побочными эффектами, которые можно предотвратить. Кроме того, в любом случае лучшего способа поиска и замены в файле не существует.

Вечнозеленое дерево
источник
6
Последний использованный поисковый термин автоматически восстанавливается после выхода из функции, поэтому при использовании его внутри функции сохранение и восстановление не требуется. Смотрите:help function-search-undo
Martin Tournoij
1
лучше использовать winsaveview () / winrestview () вместо курсора ()
Кристиан Брабандт
1

Команда :s- это чистый подход Vimscript.

Я предполагаю, что предупреждение означает только то, что курсор, скорее всего, будет неправильно расположен после его использования (что вы можете обойти, используя winsaveview()функцию до и winrestview()команду после ее использования). Также вам необходимо позаботиться о возможных ошибках, которые могут возникнуть. Обычно это делается с помощью eфлага. Также необходимо позаботиться о некоторых настройках, таких как gdefaultнастройка, которая инвертирует значение gфлага.

Нужно заботиться об этих особенностях, и это, вероятно, является основной причиной этих предупреждений. Но это не значит, что нужно избегать использования :sкоманды. Вполне нормально использовать :sкоманду, если вы хотите что-то заменить в текущем буфере.

(Обратите внимание, что можно, конечно, перебрать все строки и использовать подход search () / getline () / setline (). Но обычно это медленнее.)

Кристиан Брабандт
источник