henry_flower: A melancholy wolf (Default)
henry_flower ([personal profile] henry_flower) wrote2025-03-20 12:28 pm

Кольорологія терміналів

Ув вікіпідіа написано шо хадварні термінали VT100 (продавалися з 1978 року) та VT220 (1983) були монохромні (кольорові варіянти, напевно, лише для заможних верств гіпадрілів). Terminfo ув лайнаксі про ці термінали містить ту саму інформацію:

$ for i in dumb vt100 vt220 screen xterm $TERM; do printf "%-20s" $i; TERM=$i tput colors; done
dumb                -1
vt100               -1
vt220               -1
screen              8
xterm               8
xterm-256color      256

Кілька днів тому, нєкто Поттерінґ, мастодонів про діфолтне значення TERM, яке обирає systemd:

'The default fallback $TERM we so far picked has been "vt220" … This deemed us to be a good choice, since (unlike the better known vt100) these kind of terminals support PageUp/PageDown keys'

Загалом, ув terminfo дивляться зазвичай тільки ютіліти які для користувацького інтерхфейсу використовують ncurses; решта вгадує можливості терміналу шляхом слідкування за візерунками руху небесних тіл, e.g.:

  • чи є змінна середовища COLORTERM (нещодавно обраний шлях systemd);
  • змінна середовища NO_COLOR (я би віддав перевагу, навпаки, щось на кшталт COLOR=1, бо діфолтне плювання кольорами ув консолі є страшенний несмак);
  • дивитися на TERM і шукати збіг ув своїй вкомпайлений (не жарт) табличці, як то робить ls з coreutils;
  • механізма terminal-colors.d(5) з util-linux, яким користується ніхто, окрім деяких ютіліт з util-linux.

Лайнаксний ls, звичайно, перемагає ув конкурсі найдебільнішого рішення.

Воно друкує барвами для vt100, тому що протягом компіляції coreutils хапається текстовий хфайла з налаштунками для dircolors(1), який має ось такі рядки:

TERM vt100
TERM xterm*

Цей хфайл (його копія зазвичай є ув /etc/DIR_COLORS) скрипта перловий конвертує ув символьного масива

$ head -c7 src/dircolors.hin # ув ріпо coreutils
# Confi
$ (head -c61 && printf 🤡 && tail -c39) < <(src/dcgen src/dircolors.hin)
static char const G_line[] =
{
  '#',' ','C','o','n','f','i',🤡,'r','i','a','b','l','e','s','.',0,
};

який потім інклудиться як dircolors.h ув ls.c, де є хфункція

/* Check if the content of TERM is a valid name in dircolors.  */
static bool known_term_type(void) {
  char const *term = getenv("TERM");
  if (!term || !*term)
    return false;

  char const *line = G_line;
  while (line - G_line < sizeof(G_line)) {
    if (STRNCMP_LIT(line, "TERM ") == 0) {
      if (fnmatch(line + 5, term, 0) == 0)
        return true;
    }
    line += strlen(line) + 1;
  }

  return false;
}

dircolors(1) також парсить нещасну G_line та друкує 0 інструкцій для ls, коли TERM є відсутня чи несе невідоме значення:

$ env -i SHELL=/bin/sh dircolors
LS_COLORS='';
export LS_COLORS

У чому сенс тоді, навіть за відсутності LS_COLORS, розмальовуювати множинні character devices з директоріями (довгий масив color_indicator[] ув ls.c, якщо комусь цікаво), але полишати файли звичайні (кольори для яких G_line має), залишається невідомим.


Post a comment in response:

If you don't have an account you can create one now.
HTML doesn't work in the subject.
More info about formatting