henry_flower: A melancholy wolf (Default)
henry_flower ([personal profile] henry_flower) wrote2025-03-22 09:55 pm

Respect my capabilitah

Спостерігаючи за бійкою між Поттерінґом та термінальними пуристами, я дізнався про таке собі XTGETTCAP. Це є механізма (відносно новий, ~2019?) для отримання можливостей терміналу без консалтінґу terminfo. Це означає, що брехати про тип терміналу з XTGETTCAP не вийде.

Наприклад, якщо хочеться намалювати користувачу саме монохроматичного інфобокса, зараз можна підсунути назву терміналу, для якого ув terminfo зазначено безбарвне життя:

$ TERM=vt100 dialog --infobox 'ну шо ти малá' 0 0

Це працює тому що даялоґа використовує ncurses, який дивиться ув terminfo. Якби даялоґа стріляв ув термінала XTGETTCAP'апом, замість читання змінної середовища TERM, такий хфокус би не спрацював:

$ echo $TERM
xterm-256color
$ TERM=vt100 ./XTGETTCAP TN
xterm-256color

Якщо ув теорії XTGETTCAP--майбутнє вже сьогодні, то на практиці цей механізма мені не подобається. Можливо in-band signalling було надією людства ув 1970ті, але зараз щоб імплементувати XTGETTCAP запита та прочитати результата, треба перемикати термінала ув raw режим, конвертувати ім'я capability ув hex строку і писати до tty обгорнувши її з \e (ascii 033 ув октал) з обох боків, поряд з іншим мотлохом:

printf '\033P+q%s\033'\\ "$capablity" > "`tty`"

Що для "TN" виглядає як

00000000: 1b50 2b71 3534 3465 1b5c                 .P+q544e.\

Потім треба обережно прочитати результата все ще знаходячись ув raw режимі. Якщо робити це з акуратністю, з якою нарід пише скрипти шелóві, вірогідність того, шо термінал буде заблоковано перманентно, наближається до 1.

Для wayland'у є емулятор терміналу foot, який має окрему C ютіліту для читання XTGETTCAP, але вона наглухо висне, якщо термінала не розуміє запиту. Як можна сподіватися на здібності гіпадріла звичайного, якщо це не можуть порядно зробити навіть люди, які пишуть термінального емулятора.

Окрім xterm (який вимагає увімкненого allowTcapOps, який вирублений по замовчуванню на всіх ОйБіЄм'івських дістро через цирка на дроті), найбільше просунулося у цьому напрямку індійське диво kitty (на яке я маю алергію після стількох років страждань з calibre (автор той самий)), та усілякі ghostly та ін. штукенції, якими користуються 12 людей на планеті земля. iterm2 та діфолтне еплівське одоробло також ніби має підтримку, але мені є лінь перевіряти.

Найсумніше є те, що XTGETTCAP наразі не працює через gnu screen чи tmux, що хоча є вина останніх, популярності XTGETTCAP не додає.

Скрипта, яким можна тестувати:

#!/bin/sh

set -e

eh() { echo "Error: $*" 1>&2; trap - 0; exit 1; }
text2hex() { od -A n -t x1 | tr -d ' \n'; }
hex2text() { sed 's/../0x& /g' | xargs printf '\\\\%03o\n' | xargs printf %b; }
stty_orig=`stty -g`
stty_restore() { stty "$stty_orig"; }

[ -n "$1" ] || eh Usage: XTGETTCAP capability

capablity=`printf '%s' "$1" | text2hex`
trap stty_restore 0

stty -echo raw time 1 min 0
printf '\033P+q%s\033'\\ "$capablity" > /dev/tty
buf=`dd status=none count=1`
stty_restore

[ -n "$buf" ] || eh unsupported terminal
[ "$V" ] && printf %s "$buf" | xxd

buf=`printf %s "$buf" | sed 's/[^a-zA-Z0-9+=]//g'`
[ P1 = "${buf%+*}" ] || eh unknown capabilitah
printf %s "${buf#*=}" | hex2text | xargs

Повинно працювати з пацаватими dash, busybox sh та ін.

hex2text() тут не фонтан, звичайно, але нопешіть як то можна інакше, щоб (а) було сумісно з fbsd, (б) не вимагало чогось ікстернального, як xxd.

$ ./XTGETTCAP TN
xterm-kitty
$ V=1 ./XTGETTCAP colors
00000000: 1b50 312b 7236 3336 6636 6336 6637 3237  .P1+r636f6c6f727
00000010: 333d 3332 3335 3336 1b5c                 3=323536.\
256
$ ./XTGETTCAP шо?
Error: unknown capabilitah