Можно ли отображать текст в консоли с эффектом зачеркивания?

Я уже изучил 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`);
Другие вопросы по тегам