Найти тему
Блокнот математика

Рубрика "Секреты Вим". Табуляция

Привет, коллеги. Есть такой символ: табуляция, табулятор. Код у него 0x09. История символа идет от пишущих машинок, а ныне это такой "резиновый пробел": невидимый символ, занимающий переменное горизонтальное пространство, от одного пробела до восьми (это число стандартно, но его можно изменять).

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

Есть такой формат данных: CSV, comma-separated values, разделенные запятыми данные. Они не очень хорошо читаются, но в простых случаях замена запятых на табуляции превращает таблицу во вполне приличную. Как на скриншоте.

В теории программирования нет общепринятых норм о табуляции: где-то ее категорически запрещают, где-то напротив, приветствуют. В фортране, например, табуляция даже помечается при раскраске синтаксиса цветом как ошибка, и есть особые средства, чтобы их легализовать. А в GrADS табуляция вообще приводит к тому, что скрипт не выполняется, и непонятно почему.

А иногда она просто используется как часть синтаксиса: например, в makefile-ах.

Давайте обсудим способы работы с табуляцией в Вим. При случае этот символ можно использовать с своих целях (даже если сам символ вам не нужен).

Для начала, в регулярных выражениях есть символ \t, совпадающий с табуляцией.

Далее, есть опция tabstop. Она по умолчанию содержит число 8 и означает число пробелов, которому табуляция соответствует.

Попробуйте ввести несколько символов или слов, разделив их табуляцией:

1 2 3 4 5

(Здесь табуляции заменены на пробелы, но вы вводите табуляции).

Теперь измените значение опции:

:set tabstop=4

Обратите внимание, что текст заполняет место, которое занимает табуляция. Вот еще пример: введите, разделяя табами, такой текст:

1 22 3333 44444 5 — tabstop=8

и выставьте tabstop=4

Изменение опции меняет вид текста! Сам текст как набор символов тот же, но выглядит иначе. Это может быть то, чего вы добивались, например, чтобы таблица уместилась в экран, а может быть крайне нежелательно. Например, на печати всё может "съехать".

Стандартное значение равно 8, и если вы взаимодействуете с внешним миром, лучше его и придерживаться. Есть другие возможности управлять видом текста: отступами, шириной столбцов таблиц и т.п.

В их числе опция softtabstop, которая задает число пробелов на одну табуляцию при редактировании текста. Вим будет вставлять табы и пробелы так, что все будет выглядеть именно так, как вы хотите, то есть как если бы tabstop была какая вам нравится. При этом она (tabstop) сохраняет свое значение (стандартное 8, например). Равное нулю значение (по умолчанию) отключает эту возможность, а отрицательное задействует значение опции shiftwidth, о которой далее.

Пример. Введем текст при tabstop=4:

1 22 333 4

Теперь выставим tabstop=8 и softtabstop=4 и попробуем ввести тот же текст.

Выглядит так же, правда? Но символ табуляции здесь теперь только один, между 22 и 333. Вим сам рассчитал, что текст из единички, трех пробелов и двух двоек как раз занимает шесть символов и от восьмипробельной табуляции останется именно два: ровно столько, сколько останется от табуляции четырехпробельной, в которой два символа заняли двойки. А три пробела получились как четыре на табуляцию минус один на единичку. Все эти расчёты Вим проводит за вас!

Опция shiftwidth по умолчанию равна 8 и она задает число пробелов для отступа с помощью команд (>>, <<) или автоматики. Если нуль, то используется значение опции tabstop. Я, например, люблю отступы по 4 пробела, а не по 8: это много.

Есть полезный флаг: smarttab. Если он выставлен, то клавиша табуляции в начале строки вставит shiftwidth пробелов (или табуляций "по обменному курсу"), а в других местах используется tabstop или softtabstop. Без него вам придется делать отступы только командами для этого, а использовать табуляцию будет нельзя. То есть можно, но не обязательно результат будет тот, который вы желаете.

Теперь больше магии. Опция-флаг expandtab, если выставлена, предписывает заменять табы пробелами. Физически символ никогда не вставляется. Если всё-таки нужно это сделать, используйте <C-V><Tab>, как и для ввода любого управляющего символа. Текст

1 22 333 4

который мы вводим, нажимая клавишу табуляции, выглядит так же, но теперь там только пробелы. Удобно, но если я потом решу убрать тройку или дописать двойку, таблица сломается. А если между числами были бы табы, то не сломается, пока "хватает места".

Вим официально предлагает четыре стиля работы с табуляцией:

  1. tabstop всегда 8, а softtabstop и shiftwidth имеют любое значение, какое вам нравится, при этом expandtab сброшена. Реально в тексте будет смесь пробелов и табов, но клавиши табуляции и <BS> ведут себя так, как вы ожидаете. При этом текст одинаково выглядит в любом редакторе, который полагает табуляцию равной восьми пробелам.
  2. Используйте expandtab при любом значении tabstop и shiftwidth. Символов табуляции в тексте вообще не будет, изменение опции tabstop вид текста не изменит. Сама клавиша может использоваться для вставки "нужного числа" пробелов, что удобно. То есть после 1 клавиша табуляции вставит 7 пробелов, после 4444 четыре, а после 7777777 только один. Конечно, если tabstop=8.
  3. Делайте вообще что хотите, но используйте modeline для задания этих опций при загрузке документа. Текст не будет переносимым (между разными редакторами), но если работать с ним только в Вим, то это приемлемо.
  4. Задавайте tabstop и shiftwidth одинаковыми и отключите expandtab. Начальные отступы тогда должны работать правильно в любом редакторе.

Если вы откроете документ, в котором использованы символы табуляции, опция expandtab ничего не будет с ними делать.

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

Но не только. Иногда стоит изменить tabstop, чтобы таблица влезла на экран, а иногда наоборот, чтобы файл не изменил свой вид.

Итак, команда :retab. Может принимать диапазон строк, на котором отработает. Может быть снабжена восклицательным знаком. Можно указать новое значение tabstop.

Команда заменяет пробельные последовательности с табом на новые, исходя из нового значения tabstop и стараясь не изменить вид текста.

Сказано, что вид текста не должен измениться.

Если указан !, то заменяются вообще все пробельные последовательности, включая и те, что из одних пробелов. Если выставлен флаг expandtab, табы будут заменены на нужное число пробелов. Опция tabstop выставляется в новое значение.

Если вы используете символ табуляции в строках в программном коде, то они будут заменены — осторожно!

Аналогично, серии пробелов могут быть заменены на таб, что тоже не всегда желательно. Будьте внимательны и осторожны.

При выставленной expandtab все символы табуляции будут заменены на нужное число пробелов, то есть "мавр сделал своё дело".

Вот пример автокоманд, которые позволяют хранить текст с табуляциями по 8 символов, но редактировать по 4.

:auto BufReadPost *.xx retab! 4
:auto BufWritePre *.xx retab! 8
:auto BufWritePost *.xx retab! 4

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

Вот и всё про табуляцию! При правильном использовании это весьма удобный инструмент.

Научно-популярные каналы на Дзене: путеводитель
Новости популярной науки12 марта 2022