Как разбить длинные строки в VIM?

12

У меня довольно большой текстовый файл, состоящий из блоков, таких как

Short line.
Really long line.
Short line.

разделены пустыми строками, и я хотел бы использовать vim (в Linux) для разбиения длинных строк и получения блоков, таких как

Short line.
This was
part of
a long line.
Short line.

Моя проблема с gqgw) состоит в том, что он перекомпоновывает каждый блок как целый абзац, то есть он не сохраняет двух разрывов строк в каждом блоке, и в соответствии с :help fo-tableни одним из gqпараметров форматирования не позволил бы мне делать то, что я хочу. Я также подумал, что смог бы достичь своей цели, если бы мог определить символы новой строки в качестве разделителей абзацев, но в соответствии с ними :help paragraphони жестко закодированы.

Изменить: я знаю, что я мог бы использовать gqили gwформатировать каждую длинную строку по очереди, но так как мой файл занимает несколько тысяч строк, я ищу способ достичь этого автоматически.

AP
источник
Между прочим: я искал решения для моей проблемы в документации vim, здесь, в SU, и в Интернете. Я с удовольствием удалю этот вопрос, если я упустил что-то очевидное.
AP
Есть ли обоснование текста в Vim? в vi.sx .
Восстановите Монику - М. Шредер
@ MartinSchröder: Рад, что есть ви SE! Эти ответы не касаются моей проблемы, так как я уже знал о gqи gw. Я также рад, что не остановился на этом, иначе я бы не узнал о :gкоманде. :)
AP

Ответы:

16
:%norm! gww

Это применяет normalкоманду gww(которая форматирует текущую строку как с gw) ко всему буферу, не принимая во внимание настроенные отображения (чтобы избежать проблем, если, например gw, был сопоставлен с чем-то еще).

Видеть

  • :help :%
  • :help :norm
  • :help gww

Эта альтернатива соответствует предложению Бена в комментариях и является более простой, чем оригинальное решение, которое сохранено ниже, поскольку оно может лучше соответствовать другим подобным обстоятельствам из-за возможности сопоставления регулярных выражений. В случае «сопоставить все линии», однако, это излишне грубо.


Применение gwwк каждой отдельной строке в буфере программно:

:g/^/norm gww

Смотрите :help :gи :help norm. ^соответствует началу строки, что на практике делает это совпадением для каждой строки.

Можно также выбрать только строки длиной более 60 символов с

:g/\%>60v/norm gww

(см. :help \%<), но на практике gwwбудут переформатировать только строки длиннее, чем в textwidthлюбом случае, поэтому это может не иметь большого значения ни для скорости, ни для результата.

(Я использую vдля «виртуального столбца» вместо c«столбца», поскольку последний действительно вычисляет определенное количество байтов в строке. Это может привести к неожиданным результатам при использовании многобайтовых кодировок, что часто является причиной для осторожности. На практике это не является реальной проблемой по той же причине, что и выше, поскольку gwwона не будет переформатировать строки короче, чем в textwidthлюбом случае.)

Даниэль Андерссон
источник
По-видимому, :gне работает без шаблона, поэтому :g//norm gwwне работает, но :g/.*/norm gwwработает.
AP
@AP: Да, у меня работает. Я использую Vim 7.4.488-6 из Debian Unstable.
Даниэль Андерссон
4
:g//повторно использует последний шаблон поиска; если его нет, он терпит неудачу. Используйте :g/^/для применения ко всем линиям.
Инго Каркат
@IngoKarkat: Ах, имеет смысл, так как мой последний паттерн во время тестов был со знаком длины линии, который я продемонстрировал позже. Я обновлю ответ. Знаете ли вы, где в справке упоминается это поведение «пустого шаблона»? Я не могу легко найти это.
Даниэль Андерссон
Просматривая руководство, вероятно, подразумевается, что информация, представленная :help last-patternдля обычного поиска, относится и к :globalкоманде.
Даниэль Андерссон
4

Так как вы уже прочитали руководство для gqи gwкоманд, я полагаю , вы , вероятно , хотите что - то более удобное , чем вручную перемещение в длинные очереди , а затем использовать gw0, gw$или другую gwкоманду только форматировать текущую строку.

Я не знаю простой способ разбить длинные строки в Vim над блоком текста. Однако, поскольку вы упомянули, что вы используете Vim в системе GNU / Linux, я бы предложил отфильтровать текст с помощью команды GNU fmt.

Для всего файла:

:%!fmt --width=75 --split-only

Для текущего абзаца (используя короткие опции):

:'{,'}!fmt -75 -s

Пояснения к соответствующим fmtопциям:

  • -w, --width=WIDTH- максимальная ширина линии (по умолчанию 75 столбцов). Опция -WIDTHявляется сокращенной формой --width=DIGITS(если используется эта сокращенная версия, она должна быть первой опцией).

  • -s, --split-only- разбивать длинные строки, но не пополнять; эта опция сохраняет ваши существующие жесткие разрывы строк.

Энтони Геогеган
источник
Спасибо за упоминание fmt. Я предпочел принять другой ответ, потому что он требует только vim.
AP
@AP Не беспокойся. Это отличный ответ, и я бы принял это сам. И это, и ваш вопрос заслуживают одобрения.
Энтони Геогеган
1

Из:

Short line.
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Short line.

Поместить маркер на линию «lorem ipsum» и нажать кнопку gww( textwidth=40для наглядности):

Short line.
Lorem ipsum dolor sit amet, consectetur
adipiscing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna
aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris
nisi ut aliquip ex ea commodo consequat.
Short line.

что мне кажется, что вы просите. Если нет, пожалуйста, не стесняйтесь уточнить.

Даниэль Андерссон
источник