Vim:Как обрабатывать переводы строк при хранении нескольких команд в регистрах?

StackOverflow https://stackoverflow.com/questions/2730922

  •  02-10-2019
  •  | 
  •  

Вопрос

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

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

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

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

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

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


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

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

Это было полезно?

Решение 2

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

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

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

Другие советы

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

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

Вот как, я думаю, вы хотите, чтобы фрагмент выглядел следующим образом:

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

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

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

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

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

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) внутри скриптов.

Удачи вам!

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top