Вопрос

Я обнаружил это при использовании Ruby Printf, но это также относится к печати C.

Если вы включите код побега ANSI в выходной строке, он посылает выравнивание.

Рубин:

ruby-1.9.2-head > printf "%20s\n%20s\n", "\033[32mGreen\033[0m", "Green"
      Green          # 6 spaces to the left of this one
               Green # correctly padded to 20 chars
 => nil

Та же линия в программе C производит тот же выход.

Есть ли в любом случае, чтобы получить printf (или что-то еще), чтобы выровнять вывод и не добавлять пробелы для непечатанных символов?

Это ошибка, или есть хорошая причина для этого?

Обновлять: Поскольку printf нельзя полагаться, чтобы выровнять данные, когда есть коды ANSI и широкие символы, есть ли лучшая практика способ выстраивания цветных табличных данных в консоли в Ruby?

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

Решение

Я не согласен с вашей характеристикой 9 пробелов после зеленого зеленого цвета ». Я использую Perl, а не Ruby, но если я использую модификацию вашего заявления, печатаю символ трубы после строки, я получаю:

perl -e 'printf "%20s|\n%20s|\n", "\033[32mGreen\033[0m", "Green";'
      Green|
               Green|

Это показывает мне, что printf() Заявление подсчитала 14 символов в строке, поэтому он предпринимает 6 пробелов для выравнивания на 5 символов. Однако терминал проглотил 9 из этих символов, интерпретируя их как изменения цвета. Итак, вывод появился 9 символов короче, чем вы этого хотели. Однако printf() не печатал 9 пробелов после первого «зеленого».


Что касается лучших практик для выровненного выхода (с колоризацией), я думаю, вам понадобится в поле каждого размера и выровненного поля, окруженного простыми полями «% s», которые касаются колоризации:

printf "%s%20.20s%s|%s%-10d%s|%s%12.12s%s|\n",
       co_green, column_1_data, co_plain,
       co_blue,  column_2_data, co_plain,
       co_red,   column_3_data, co_plain;

Где, очевидно, co_XXXX Переменные (константы?) содержат последовательности эвакуации для переключения на именованный цвет (и co_plain может быть лучше, как co_black). Если получается, что вам не нужна колоризация на каком-то поле, вы можете использовать пустую строку вместо co_XXXX переменные (или называть это co_empty).

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

Это не ошибка: нет пути Ruby должны знать (по крайней мере, в Printf, это была бы другая история для чего-то вроде проклейки), что его stdout собирается в терминал, который понимает, что escape VT100.

Если вы не корректируете фоновые цвета, что-то вроде этого может быть лучшей идеей:

GREEN = "\033[32m"
NORMAL = "\033[0m"
printf "%s%20s%s\n", GREEN, "Green", NORMAL

printf Спецификаторы ширины поля не полезны для выравнивания табличных данных, элементов интерфейса и т. Д. Помимо вопроса о контрольных символах, которые вы уже обнаружили, существуют также неразмерные и двухшимальные символы, которые ваша программа должна иметь дело, если вы не будете T Хотите ограничить вещи на устаревшие кодировки символов (которые многие пользователи считают устаревшим).

Если вы настаиваете на использовании printf Таким образом, вам, вероятно, нужно сделать что-то вроде:

printf("%*s\n%*s\n", bytestopad("\033[32mGreen\033[0m", 20), "\033[32mGreen\033[0m", bytestopad("Green", 20), "Green");

куда bytestopad(s,n) Является ли функцией, которую вы пишете, что вычисляет, сколько общих байтов нужны (строки плюс пробелов на добивках), чтобы привести к строке s взяться за n Колонны терминалов. Это будет включать разборки сбежаков и обработки многобайтовых персонажей и используя объект (например, POSIX wcwidth Функция) Чтобы найти, сколько столбцов терминалов каждый берет. Обратите внимание на использование * на месте постоянного поля ширины в printf Формат строки. Это позволяет вам пройти int аргумент printf Для ширины поля времени выполнения.

Я бы отделил любые эскогальные последовательности от фактического текста, чтобы избежать целого вопроса.

# in Ruby
printf "%s%20s\n%s%20s\n", "\033[32m", "Green", "\033[0m", "Green"

или

/* In C */
printf("%s%20s\n%s%20s\n", "\033[32m", "Green", "\033[0m", "Green");

Поскольку Ansi Escape Sequelles не является частью Ruby, либо C, не считает, что им нужно относиться к этим персонажам особенным и по праву.

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

Вот решение, с которой я придумал недавно. Это позволяет использовать color("my string", :red) в printf утверждение. Мне нравится использовать одну и ту же строку форматирования для заголовков и данных - сухой. Это делает это возможным. Кроме того, я использую радуга GEM для генерации цветовых кодов; Это не идеально, но делает работу. То CPAD Хеш содержит два значения для каждого цвета, соответствующие левой и правой прокладке соответственно. Естественно, это решение должно быть расширено, чтобы облегчить другие цвета и модификаторы, такие как жирные и подчеркивание.

CPAD = {
  :default => [0, 2],
  :green   => [0, 3],
  :yellow  => [0, 2],
  :red     => [0, 1],
}

def color(text, color)
  "%*s%s%*s" % [CPAD[color][0], '', text.color(color), CPAD[color][1], '']
end

Пример:

puts "%-10s   %-10s   %-10s   %-10s" % [
  color('apple',  :red),
  color('pear',   :green),
  color('banana', :yellow)
  color('kiwi',   :default)
]
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top