11

I have already looked into ANSI escape codes, but it looks like only underlining is supported.

Do I miss something or is there another option?

If it is not possible, is there something equivalent in the meaning of "this is deprecated"?

Antti Haapala
  • 117,318
  • 21
  • 243
  • 279
soc
  • 27,310
  • 18
  • 99
  • 209

3 Answers3

14

According to the ECMA-48 standard for terminals, SGR (Select Graphic Rendition) code number 9 is supposed to enable crossed-out text. However, the ANSI escape code wikipedia page says that it's not widely supported, and I'm not aware of any that do. I'd suspect that's because DEC's VTxxx series didn't support it.

ak2
  • 6,262
  • 27
  • 23
  • 2
    My `libvterm`/`pangoterm` can do it just fine. See the second screenshot in [link](http://leonerds-code.blogspot.com/2011/09/libvtermpangoterm-and-tickit.html) – LeoNerd Mar 13 '12 at 11:13
  • 4
    Actually a good set of the major shell terminal seems to support it (this includes ``guake``, ``terminator``, ``gnome-terminal``, ...). http://misc.flogisoft.com/bash/tip_colors_and_formatting#terminals_compatibility . Quick test: ``echo -e "\e[9mtest\e[0m"``. – vaab Jun 12 '14 at 12:49
  • Kitty supports the SGR code 9 for crossed-out text (along with a bunch of other underused modes). Most of the common linux terminals use the libvterm so at least on Linux, this mode is widely supported. Putty however, doesn't support it. – NoelProf Sep 01 '20 at 22:45
5

An alternative solution for applications written in C11 or C++11 is to use the Unicode combining long stroke overlay character.

In C++11 you can write code something like this:

#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;
}

The code prefixes each character in the input text with the stroke overlay \u0336. Note that the function assumes that text is encoded in a singlebyte encoding such as ASCII or Latin. If the input is in UTF-8 it must be converted to UTF-32 first to get the character boundaries.

The output then is s̶t̶r̶i̶k̶e̶t̶h̶r̶o̶u̶g̶h in a UTF-8 capable terminal. I don't know why the first character has no strike-through, must be a terminal issue. I could work around this by printing at least one character before the strikethrough function call.

The Unicode solution also generates a slightly different locking in my terminal (terminator) compared to the ANSI escape sequence mentioned above. The former renders the line exactly in the middle of the text whereas the latter renders it a bit below.

  • If you add `\u0336` _after_ each character, rather than before, it sometimes has the effect of "straightening out" the characters and should also strike through each character. – jonschlinkert Jun 21 '18 at 06:40
1

This works for me.

$ echo -e `echo "this is a strikethrough text" | sed 's/.\{1\}/&\\\u0336/g'`

Nitin
  • 31
  • 1
  • 5