Jak można sprawdzić czy konsola obsługuje kolory ?

0

Czy jest jakaś metoda aby sprawdzić czy konsola na której uruchamiam program obsługuje kolory ?

Kolory uzyskuje w taki sposób:

#include <cstdio>

#define ANSI_COLOR_RED     "\x1b[31m"
#define ANSI_COLOR_GREEN   "\x1b[32m"
#define ANSI_COLOR_YELLOW  "\x1b[33m"
#define ANSI_COLOR_BLUE    "\x1b[34m"
#define ANSI_COLOR_MAGENTA "\x1b[35m"
#define ANSI_COLOR_CYAN    "\x1b[36m"
#define ANSI_COLOR_RESET   "\x1b[0m"

int main (int argc, char const *argv[]) {

  printf(ANSI_COLOR_RED     "This text is RED!"     ANSI_COLOR_RESET "\n");
  printf(ANSI_COLOR_GREEN   "This text is GREEN!"   ANSI_COLOR_RESET "\n");
  printf(ANSI_COLOR_YELLOW  "This text is YELLOW!"  ANSI_COLOR_RESET "\n");
  printf(ANSI_COLOR_BLUE    "This text is BLUE!"    ANSI_COLOR_RESET "\n");
  printf(ANSI_COLOR_MAGENTA "This text is MAGENTA!" ANSI_COLOR_RESET "\n");
  printf(ANSI_COLOR_CYAN    "This text is CYAN!"    ANSI_COLOR_RESET "\n");

  return 0;
}
2

Ciężka sprawa. Nie ma jednej metody, która działa na wszystkich systemach (nawet nie wiem czy jest to możliwe na Windowsie). Do tego musisz jeszcze sprawdzić czy wyjście to jest naprawdę terminal, by nie wypluwać kolorowania jak robisz ./foo > log lub ./foo | less oraz musisz dać użytkownikowi możliwość wyłączenia jak i wymuszenia kolorowania.

2

https://linux.die.net/man/5/terminfo

Generalnie już w zmiennej środowiskowej $TERM masz jakieś info:

$ echo $TERM
xterm-256color

Tyle że to nie gwarantuje sukcesu, ktoś może mieć czarno biały monitor!

PS. Twoim większym zmartwieniem powinno być ustalenie jakie escape cody akceptuje terminal.

PS2. Jak się już bawić to na całego: https://man7.org/linux/man-pages/man4/console_codes.4.html

0

printf (ogólnie interfejs plikowy) to tylko unixy / luinuxy i zależnie od konsoli. Niekoniecznie to musi emulować ansi, inne standardy tez (były) sa popularne.
Kody na inne typy terminala moga być zupełnie niekompatybilne z terminalem ANSI
Dla przenośności, się używa biblioteki ncurses, ale to już nie za bardzo podobne do pchania sekwencji znaków w strumień.

Na windows da się uzyskac przez Win API, ale przed plik to chyba nie....

A propos ANSI
Za DOS-a był sterownik ansi.sys, który wg założenia miał emulowac terminal ansi. W moim kręgu nie spotkałem, aby ktoś używał

1
0xmarcin napisał(a):

Tyle że to nie gwarantuje sukcesu, ktoś może mieć czarno biały monitor!

PS. Twoim większym zmartwieniem powinno być ustalenie jakie escape cody akceptuje terminal.

PS2. Jak się już bawić to na całego: https://man7.org/linux/man-pages/man4/console_codes.4.html

Nawet, jeżeli do "targetu" tego programu należy również użytkownik czarno-białego monitora, to nie jest to problem. Tekst zostanie wyświetlony poprawnie, bez śmietnika z powodu kodów sterujących. Prędzej może pojawić się śmietnik w przypadku jakiegoś SSH/telnet przez terminal, który nie obsługuje kolorów.

ZrobieDobrze napisał(a):

printf (ogólnie interfejs plikowy) to tylko unixy / luinuxy i zależnie od konsoli. Niekoniecznie to musi emulować ansi, inne standardy tez (były) sa popularne.
Kody na inne typy terminala moga być zupełnie niekompatybilne z terminalem ANSI
Dla przenośności, się używa biblioteki ncurses, ale to już nie za bardzo podobne do pchania sekwencji znaków w strumień.

Na windows da się uzyskac przez Win API, ale przed plik to chyba nie....

A propos ANSI
Za DOS-a był sterownik ansi.sys, który wg założenia miał emulowac terminal ansi. W moim kręgu nie spotkałem, aby ktoś używał

Co do standardów, to obecnie w Unix/Linux w konsoli jest de facto "standard' będący połączeniem ANSI i VT100, jeszcze są komendy dorobione specjalnie na użytek XTERM, pomimo, że system MS-DOS i terminal VT100 to już odległa historia. VT100, a także następcy, aż do VT520 nie miały kolorów, a kolory zostały wzięte z ANSI, a jeszcze dorobione dodatkowe (256 kolorów i kolory RGB mimo, że oryginalnie jest tylko 16 kolorów).

Najlepszy opis komend VTxxx/XTERM jest tutaj: https://invisible-island.net/xterm/ctlseqs/ctlseqs.html

Niedawno hobbystycznie zajmowałem się tym tematem na potrzeby https://github.com/andrzejlisek/TextPaint i sam stwierdziłem, że VT100 nie jest w pełni kompatybilny z ANSI w sensie, że nie jest możliwa jedna implementacja, która pogodzi oba standardy. Przetestowałem na dużej liczbie "obrazków" z https://16colo.rs/ (jest w wersji graficznej, z którą można porównać) i na dużej liczbie programów w Linux, z vttest i mc na czele, a także z animacjami z http://artscene.textfiles.com/vt100/ .

Żeby wszystkie uruchamiane "obrazki" i programy wyświetlały prawidłowo, musiałem umożliwić pracę w dwóch trybach, bo metodą prób i błędów dochodziłem, że zdarzają się przypadki, ze ta sama komenda musi trochę inaczej działać w przypadku DOS/ANSI, a inaczej w przypadku VT100/Linux, jak działało jedno, to drugie już nie działało. Różnice opisałem tu https://github.com/andrzejlisek/TextPaint/blob/master/Readme_ANSI.md , rozdział "DOS vs. standard terminal".

Istnieją komendy "raportowe", czyli takie, na które klient powinien niezwłocznie odpowiedzieć, opisałem w rozdziale "The request-response sequences" tego samego opisu, historycznie służyły do wykrywania modelu posiadanego terminala, a i tak niektóre klienty SSH i konsole przedstawiają się jako "tylko" VT100. Problem będzie, jak terminal nie odpowie na żądanie, będzie potrzebne naciśnięcie klawisza.

2
hauleth napisał(a):

Ciężka sprawa. Nie ma jednej metody, która działa na wszystkich systemach (nawet nie wiem czy jest to możliwe na Windowsie). Do tego musisz jeszcze sprawdzić czy wyjście to jest naprawdę terminal, by nie wypluwać kolorowania jak robisz ./foo > log lub ./foo | less oraz musisz dać użytkownikowi możliwość wyłączenia jak i wymuszenia kolorowania.

Za pomocą wyżej wymienionych komend żądanie-odpowiedź można wyczuć, czy wyjściem jest terminal obsługujący taką komendę. Jak dostanie odpowiedź i to odpowiednią (zgodną z przyjętym standardem), to na 99% jest to terminal. Jeżeli wyjście jest skierowane do pliku lub do innego programu, to odpowiedzi na pewno nie będzie. Z drugiej strony, można wyczuć, czy wejście róznię nie jest skierowane z czegoś innego niż terminal (w przypadku konsoli Linux i klientów telnet/ssh, wejście, to nie tylko klawiatura, ale też automatyczne odpowiedzi na komendy, program uruchomiony na serwerze ssh nie rozróżnia pochodzenia znaków).

Nie wiem, w jaki sposób to jest zrobione w .NET, ale na pewno da się wyczuć, czy wejście jest przekierowane, bo w C#, polecenie Console.ReadKey() rzuca wyjątek w przypadku skierowania standardowego wejścia do czegoś innego niż klawiatura/konsola.

Wracając do tematu, czyli jak wykryć obsługę kolorów, to myślę, że najprościej wysłać komendę 1Bh [ 0 c i odpowiedź będzie na przykład 1Bh [ ? 1 ; 2 c (zależy od modelu emulowanego terminala), to współcześnie na 99% konsola obsłuży kolory. Można na przykład wysłać 1Bh [ 6 n, czyli zapytać o położenie kursora, w odpowiedzi będzie 1Bh [ YY ; XX R. jeżeli odpowiedzi są poprawne, to można przyjąć, że obsługuje kolory (prawdziwe terminale firmy DEC to już przeżytek, a nawet jeśli ktoś ma, to one zignorują komendy zmieniające kolory). Jeżeli odpowiedź odbiega od standardu lub jej nie ma, to znaczy, że konsola nie jest zgodna z VTxxx lub, że wejście lub wyjście jest skierowane gdzie indziej niż konsola, np. z pliku lub do pliku. W takim przypadku należy przyjąć, że konsola nie obsługuje kolorów.

1

Odpuść. Ewentualnie zrób to wszystko w ncurses. Ncurses nawet coś tam ma do sprawdzania czy kolory działają.

0

Podsumowując watek: Odpuściłem temat !

3

Ncurses ma coś takiego jak has_colors() oraz can_change_color() także zerknąłbym jak oni podeszli do tematu.

4
several napisał(a):

Ncurses ma coś takiego jak has_colors() oraz can_change_color() także zerknąłbym jak oni podeszli do tematu.

Korzystają z terminfo, co i autorowi tematu polecam.

1

Niektóre programy mają po prostu przełącznik żeby nie pluło kolorami, sam parę razy użyłem takowego żeby w logach nie pluło losowymi ciągami typu "\x1b[34m"

0
obscurity napisał(a):

Niektóre programy mają po prostu przełącznik żeby nie pluło kolorami, sam parę razy użyłem takowego żeby w logach nie pluło losowymi ciągami typu "\x1b[34m"

Właśnie to rozwiązanie wybrałem, w cmake dodałem option() do włączania/wyłączania koloru logów. Na tą chwilę wystarczy

1 użytkowników online, w tym zalogowanych: 0, gości: 1