Как предотвратить добавление новой строки в начале в Vim при использовании :r!date и других команд shell?

Вопрос или проблема

Большую часть времени, когда я вставляю дату, я пытаюсь сделать это в середине строки. По умолчанию, похоже, что вставка с помощью :r! всегда помещает результат на новую строку. Это имеет некоторый смысл, так как большинство команд оболочки выводят новую строку перед результатом команды, и это, безусловно, предпочтительнее в терминале. В случае выхода из Vim для небольшой команды, такой как date +%x, это не мое предпочтительное поведение. Как мне это обойти?

В режиме вставки вы можете использовать Ctrl-R= для вставки выражения в текущую позицию курсора.

Вы могли бы использовать, например, функцию system(), к сожалению, это решает лишь половину проблемы, так как вывод system() всегда будет содержать как минимум конечный разрыв строки, что приведет к разрыву строки после ввода. Для решения вопроса о том, как избежать этих конечных разрывов строки в случае system(), посмотрите этот мой ответ на vi.stackexchange.

(так что вы можете использовать, например, Ctrl-R=systemlist(‘date’)[0]Enter).


Альтернативный способ вставки даты в текущую позицию курсора – это использование Ctrl-R=strftime(‘%c’)Enter

Ctrl-R= использует регистр выражений для вставки содержимого. Вы можете узнать больше с помощью команды :help i_ctrl-r или посмотреть документацию на appspot.

Я считаю, что проблема заключается не столько в том, что команды оболочки обычно заканчиваются новой строкой, сколько в том, что команда read предназначена для работы с строками (т.е. команда ex). Она присутствовала в оригинальной версии ed в 1970-х годах, до появления :r!команда, и чаще всего использовалась для чтения нескольких строк (например, C-функции или абзаца текста) из одного файла в другой. Большинство пользователей хотели бы вставлять их как новые, отдельные строки в большинстве случаев.

Вы можете проверить/демонстрировать это, выполнив :r!printf Tuesday. Даже если команда printf Tuesday не записывает новую строку (так как вы не указали \n), вы получите Tuesday на отдельной строке.

Возможно, самое простое решение – сделать i Enter Esc (чтобы разорвать текущую строку), - или k, чтобы вернуться на строку выше, затем выполнить вашу :r!команда и затем J, чтобы Join соединить строки вместе. Если вы часто делаете это, возможно, имеет смысл настроить макрос для этого.

Разоблачение: Я неплохо знаю vi, но многому в vim я еще не научился. Возможно, есть более простой способ сделать это в vim.

Используя комбинацию вышеперечисленных ответов

Вы можете экспортировать функцию где-нибудь, например, в .zshrc / .zshenv

export function dateTime() {
    printf "$(date +'%y/%m/%d-%H:%M')"
}

Затем создайте такое отображение

nmap <leader>D i<cr><Esc>k:r! dateTime<cr>kJJ

Это не работает идеально, если вы находитесь в конце строки.

.

Ответ или решение

Для пользователей Vim, сталкивающихся с проблемой добавления новой строки при использовании команды :r!date или других shell-команд, существует несколько решений, которые позволят вставить вывод команды прямо в середину строки без пробелов.

Проблема

Когда вы используете в Vim команду :r!, такие команды, как date +%x, распечатывают результат на новой строке. Это поведение связано с тем, что команда :r является ориентированной на строку. Исторически, она была разработана для добавления блоков текста из одного файла в другой, поэтому вставка результатов shell-команд на новой строке была ожидаемым поведением.

Решения

Использование Ctrl-R и функции

  1. Вставка выражений:

    • В режиме вставки (Insert) используйте комбинацию Ctrl-R =, чтобы вставить результат на текущую позицию курсора. Например, для вывода текущей даты можно использовать:
      Ctrl-R =strftime('%c')<Enter>

      Стандартная библиотека Vim предоставляет функцию strftime, которая аналогична команде date и позволяет форматировать дату и время без проблем с новой строкой.

  2. Использование функции systemlist:

    • Мамогущая альтернатива — использовать функцию systemlist(). Она позволяет извлечь результат shell-команды без завершающего переноса строки:
      Ctrl-R =systemlist('date')[0]<Enter>

      Эта формула позволит вам получить вывод команды без добавления ненужного разделителя, так как systemlist() возвращает список строк без лишних символов.

Обходные пути

  1. Предварительное разбиение строки:

    • Если вы часто оказываетесь в ситуации, когда необходимо вставить результат shell-команды в середину строки, можно следовать следующему процессу:
      • Вставьте новую строку (нажмите i <Enter> Esc).
      • Вернитесь на одну строку вверх с помощью клавиши k.
      • Выполните вашу команду :r!command.
      • Объедините строки обратно, использовав команду J.
  2. Создание функции в оболочке:

    • Создайте shell-функцию в вашем файле конфигурации (например, .zshrc):
      export function dateTime() {
       printf "$(date +'%y/%m/%d-%H:%M')"
      }
    • В Vim настройте соответствующую маппинг:
      nmap <leader>D i<cr><Esc>k:r! dateTime<cr>kJJ

      Этот подход вставляет вашу дату в нужное место, а затем объединяет строки обратно. Обратите внимание, что это может не работать идеально, если вы находитесь в конце строки.

Заключение

Вышеперечисленные методы должны помочь вам избежать автоматического добавления новой строки при выполнении shell-команд в Vim. Выбор конкретного метода зависит от ваших предпочтений и задач. Если вы часто сталкиваетесь с этой проблемой, создание макроса или скрипта может сэкономить время и упростить рабочий процесс в редакторе.

Оцените материал
Добавить комментарий

Капча загружается...