Можно ли отображать текст в консоли с эффектом зачеркивания?
Я уже изучил escape-коды ANSI, но похоже, что поддерживается только подчеркивание.
Я что-то пропустил или есть другой вариант?
Если это невозможно, есть ли что-то эквивалентное в значении "это устарело"?
6 ответов
В соответствии со стандартом ECMA-48 для терминалов, кодовый номер SGR (Выбор графического представления) 9 должен разрешать зачеркнутый текст. Тем не менее, на странице Википедии, посвященной escape-коду ANSI, написано, что она не поддерживается широко, и я не знаю ни одного из них. Я подозреваю, что это потому, что серии DEC VTxxx не поддерживают его.
Альтернативное решение для приложений, написанных на C11 или C++11, состоит в том, чтобы использовать Unicode, комбинирующий символ наложения длинного штриха.
В C++11 вы можете написать код примерно так:
#include <iostream>
#include <string>
std::string strikethrough(const std::string& text) {
std::string result;
for (auto ch : text) {
result.append(u8"\u0336");
result.push_back(ch);
}
return result;
}
int main() {
std::cout << strikethrough("strikethrough") << std::endl;
}
Код префикс каждого символа на входе text
с наложением мазка \u0336
, Обратите внимание, что функция предполагает, что text
кодируется в однобайтовой кодировке, такой как ASCII или латиница. Если ввод в UTF-8, он должен быть сначала преобразован в UTF-32, чтобы получить границы символов.
Выходом тогда является s̶t̶r̶i̶k̶e̶t̶h̶r̶o̶u̶g̶h
в терминале с поддержкой UTF-8. Я не знаю, почему у первого персонажа нет зачеркнутого, должно быть, это конечная проблема. Я мог бы обойти это, напечатав хотя бы один символ перед зачеркнутым вызовом функции.
Решение Unicode также генерирует немного другую блокировку в моем терминале (terminator
) по сравнению с escape-последовательностью ANSI, упомянутой выше. Первый отображает строку точно в середине текста, а второй - немного ниже.
Это работает для меня.
$ echo -e `echo "это зачеркнутый текст" | sed 's/.\{1\}/&\\\u0336/g'`
Да, используйте SGR(9)
Полный список всех возможных текстовых аспектов, включая странности, такие как Fraktur и медленное мигание, см. в разделе 8.3.117: SGR — выбор графического представления стандарта ECMA-48.
Терминалы заведомо работают
База данных ncurses terminfo отслеживает, какие функции и какие терминалы поддерживаются. Вот список терминалов, которые, как известно, поддерживают «ecma+strikeout» [^3]:
-
alacritty foot hterm kitty консоль mintty mlterm
экран MS-терминала st терминология tmux vte xterm
Обратите внимание, что некоторые терминальные проекты не обновляют свои записи terminfo. Например, терминала Gnome нет в списке, но он действительно работает, поскольку основан на vte.
[^1]: «ECMA-48» часто называют «управляющими последовательностями ANSI». Оба варианта одинаково верны, поскольку ECMA-48 и ANSI X3.64 практически идентичны и позже были объединены в ISO 6429 . Однако ANSI и ISO взимают плату за ознакомление со своими стандартами, поэтому я использую публикацию ECMA, которая предоставляется бесплатно.
[^2]: на самом деле это список последовательностей, которые поддерживает XTerm (по состоянию на 2023 год), как описано в функции CSI
.m
раздел «Управляющие последовательности для XTerm» Томаса Дики, см. ctlseqs в формате pdf или html . Не существует идеального списка наиболее часто поддерживаемых последовательностей, но XTerm широко имитируется, и многие другие терминалы пытаются быть «совместимыми с xterm».
[^3] Начиная с версии ncurses 6.4-dev 2023, через$ toe -u terminfo.src | grep strike | cut -d: -f1 | sort | column
.
ничего проще не нашел:
$ echo -e "\e[9myour text goes here\e"
Да, вот так:
console.log("\x1b[9m" + "STRIKE THROUGH" + "\x1b[29m" + " NOT STRIKE THROUGH");
// OR
const text = "STRIKE THROUGH";
console.log(`\x1b[9m${text}\x1b[29m`);