Vim: Как обрабатывать символы новой строки при хранении нескольких команд в регистрах? - PullRequest
1 голос
/ 28 апреля 2010

У меня есть файл, в котором я храню фрагменты команд vim. Когда мне нужен фрагмент, я дергаю его, а затем выполняю его с @". Фрагменты хранятся в виде скрипта, по одной строке на команду, например:

:s/foo/bar/g
:echo "hello"
:s/1/2/g

Редактировать: я удалил команды нормального режима из примера, так как они не были частью проблемы.

Теперь эта процедура больше не работает: при выполнении фрагмента она просто останавливается на первой строке, как будто ожидает новой строки.

Есть ли где-нибудь параметр, влияющий на выполнение @? Я почти уверен, что это сработало некоторое время назад ...

Замена новой строки символом ^ M работает, но делает файл более сложным для обработки.


Дополнительная информация:

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

Ответы [ 2 ]

2 голосов
/ 04 мая 2010

Я наконец нашел виновника. Каким-то образом у меня было отображение команды на <C-J> в моем файле .vimrc. При чтении со значением по умолчанию cpoptions это превратилось в отображение на <NL>.

Как я узнал: я заметил, что при запуске vim с -u ~/.vimrc он действительно будет выполнять дерганные фрагменты. Я сгенерировал файл сеанса с и без этой опции командной строки и сравнил их. Таким образом я обнаружил, что другой набор cpoptions использовался для чтения того же файла .vimrc, так что в одном случае отображение действительно было на <C-J>, в другом оно было преобразовано в отображение на <NL> !

Если у кого-то есть подобная проблема, я предлагаю внимательно посмотреть на установленные в настоящее время сопоставления команд, набрав :cmap.

2 голосов
/ 30 апреля 2010

Не думаю, что проблема в ^M против ^J. Макросы Vim будут обрабатывать любой из них как допустимый символ конца строки для записанных макросов. Я думаю, что проблема заключается в лишних переводах строки.

В вашем примере после 2j есть хотя бы одна ложная новая строка, и, если вы не особенно осторожны при копировании фрагмента, возможно, есть еще одна после 10k. Эти дополнительные новые строки похожи на нажатие <Enter> в обычном режиме - они перемещают курсор вниз на одну строку.

Вот то, что я думаю, вы хотите, чтобы фрагмент был похож:

:s/foo/bar/g
2j:s/1/2/g
10k

(Даже это немного вводит в заблуждение - вам все равно нужно быть осторожным, чтобы не копировать символ новой строки после 10k.)

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

Однако, что более важно - и это то, что, как мне кажется, происходит в вашем примере, - это то, что Vim останавливает воспроизведение макроса, если макрос пытается использовать <Enter> в последней строке буфера. (Я предполагаю, что Vim считает это ошибкой, и любая ошибка приводит к остановке макроса.)

Вот пример. Предположим, у вас есть этот фрагмент, хранящийся в регистре х:

4j
:echo "Done"

(Обратите внимание на новую строку после 4j.)

Кроме того, предположим, что у вас есть следующие пять строк (и только эти пять строк) в буфере:

line 1
line 2
line 3
line 4
line 5

Если вы сейчас нажмете @x на line 1, :echo "Done" никогда не выполнится. Vim перемещает курсор вниз на 4 строки до line 5, затем пытается переместить еще одну строку вниз из-за дополнительной новой строки, но не может. Макрос прекращает выполнение в этот момент до того, как команда :echo получит шанс на выполнение.

Однако, это работает, если вы измените регистр x на этот:

4j:echo "Done"

Итак, вернемся к исходному примеру. Держу пари, что происходит следующее: дополнительный символ новой строки после 2j пытается переместить курсор туда, куда он не может перейти, и это приводит к остановке макроса. В нижней строке экрана содержится последняя выполненная команда (:s/foo/bar/g), из-за чего Vim ждет, когда вы нажмете Return.

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

:help script

Обязательно прочитайте о команде :normal, которая позволяет вам выполнять команды в обычном режиме (например, 2j и 10k) в скриптах.

Удачи!

...