Как включить мин.XX Пробелы между двумя строками в Vim через замену? - PullRequest
3 голосов
/ 12 мая 2011

У меня есть текстовый файл с 2 строками в строке разной длины каждая.Для лучшего чтения я хочу, чтобы вторая строка была выровнена со следующими строками:

например До:

bla foo
barbla barfoo
foblaaaa Bablofoo

После:

bla      foo
barbla   barfoo
foblaaaa Bablofoo

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

s/^\(\w\+\)\s*\(.*\)$/\1\t\t\t\2/g

Ответы [ 2 ]

1 голос
/ 16 октября 2011

Простой способ выровнять текст в столбцах - использовать Табличный или Выровнять плагин. Как я показал в ответ на вопрос " Вставка отступ для столбцов в Vim", можно решить проблему с встроенные функции Vim только с использованием следующих команд. 1,2

:let m=0|g/\ze\>/let m=max([m,searchpos(@/,'c')[1]])
:%s//\=repeat(' ',m-col('.'))

Цель первой команды - определить ширину столбца для слева от разделителя (который я предполагаю, чтобы быть концом первого слова, \>). Ширина рассчитывается как максимальная длина текста в Первый столбец среди всех строк. Команда :global используется для перечисления строки, содержащие разделитель (другие строки не требуют выравнивания). \ze атом, расположенный сразу после начала паттерна, устанавливает конец матч в том же месте, где он начинается (см. :help \ze). изменения границы совпадения не влияют на то, как работает команда :global, шаблон написан таким образом, чтобы соответствовать потребностям следующего команда замещения: поскольку эти две команды могут использовать один и тот же шаблон, образец может быть опущен во втором.

Команда, которая запускается на совпавших строках,

:let m=max([m,searchpos(@/,'c')[1]])

вызывает функцию searchpos() для поиска того же шаблона, который использовался в родительская :global команда, и получить позицию столбца совпадения. шаблон упоминается как @/ с использованием последнего регистра шаблона поиска (см. :help "/). Это использует тот факт, что команда :global обновляет регистр /, как только он начинает выполняться. Флаг c пройден в качестве второго аргумента в вызове searchpos() допускается совпадение на первом символ строки (:global позиционирует курсор в самом начале строка для выполнения команды), потому что, возможно, нет текста слева от разделителя. Функция searchpos() возвращает список, первый элемент которого является номером строки совпадающей позиции, а второй одна позиция столбца. Если команда выполняется в строке, строка соответствует шаблон содержащей команду :global. Как выглядит searchpos() по той же схеме определенно есть совпадение на этой линии. Следовательно, интересует только столбец, начинающий совпадение, он извлекается из возвращение списка по индексу [1]. Эта самая позиция равна ширине текста в первом столбце строки, плюс один. Итак, переменная m устанавливается максимум его значения и этой позиции столбца.

Вторая команда,

:%s//\=repeat(' ',m-col('.'))

дополняет первое вхождение разделителя во всех строках, которые содержат это, с количеством пробелов, которые отсутствуют, чтобы сделать текст перед разделитель для m символов, минус один. Эта команда является глобальной замена, заменяющая пустой интервал непосредственно перед разделителем (см. комментарий о команде :global выше) с результатом оценки выражение (см. :help sub-replace-\=),

repeat(' ',m-col('.'))

Функция repeat() повторяет свой первый аргумент (в виде строки) номер времена, указанные во втором аргументе. Поскольку при каждой замене курсор переместился в начало сопоставления с шаблоном, m-col('.') равно точно количество пробелов, необходимых для смещения разделителя вправо для выравнивания столбцов (col('.') возвращает текущую позицию курсора в столбце).


1 Эта пара команд может быть переписана как одна.

:let m=0|exe'g/\ze\>/let m=max([m,searchpos(@/,"c")[1]])'|%s//\=repeat(' ',m-col('.'))

2 Оставшийся текст копирует подробное описание, приведенное в вышеупомянутый мой ответ .

1 голос
/ 12 мая 2011

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

Если вы действительно хотите избежать Tabular как @PrinceГуляш предложил, вот интересное и простое решение:

let n = system("awk '{ if (length($1) > L) { L = length($1) }}; END { print L }' ".expand("%:p"))
%s/\s\+/\=repeat(' ', n+1-system("awk '{ print length($1) }'", getline('.')))

В первой строке переменная n получит вывод небольшой программы awk.Он в основном находит наибольшую ширину для первого поля, это первая работа.Обратите внимание на expand("%:p") в конце: вместо того, чтобы просто передавать имя вашего файла, мы расширяем его до полного пути, чтобы вы могли избежать путаницы с текущим каталогом.

Следующая строка - это фактическая замена.Он заменяет первый найденный пробел выражением.Выражение возвращает строку пробелов, повторяемую определенное количество раз, что составляет n (максимальная ширина) минус длина первого слова текущей строки (снова awk help!) Плюс один буферный пробел (вы можете использовать 2 или что-то ещеномер, который вы хотите).

Это выровняет все.


Если вы хотите установить Tabular, откройте буфер и запустите:

:Tab / 

Обратите внимание на этопробел после косой черты.

Теперь вопрос на миллион долларов: хотите установить Tabular?

...