Jak określić aktualny kolor wyjścia konsoli?

14

Wiem, że jeśli dostępny jest kolorowy terminal, to można go pokolorować za pomocą znaków zmiany znaczenia .

Ale czy istnieje możliwość ustalenia, który kolor jest obecnie wyświetlany? Lub lepiej, jaki byłby kolor tekstu, gdybym go teraz wydrukował?

Proszę nie zmieniać poprzednich ustawień kolorów podczas używania tych znaków zmiany znaczenia. Znak zmiany domyślnego koloru pierwszego planu pobiera informacje ze schematu kolorów, a nie kolor tekstu, zanim go zmieniłem.

Minix
źródło
Patrząc na zmienne termcap i terminfo wydaje się, że nie jest to możliwe. Możesz na przykład uzyskać liczbę kolorów obsługiwaną przez twój terminal echotc Colub echoti colors, ale po prostu nie ma zmiennej, która przechowuje aktualną definicję kodu koloru.
jimmij
@jimmij Tak myślałem i miałem nadzieję, że coś mi umknęło. Jeśli masz pewność, że nie jest to możliwe, odpowiedz na to pytanie, a ja ostatecznie je zaakceptuję, jeśli nic więcej nie nastąpi. Dziękuję za Twój czas.
Minix,

Odpowiedzi:

11

Ogólnie rzecz biorąc, uzyskanie obecnych kolorów jest niemożliwe. Przetwarzanie sekwencji kontrolnej terminala odbywa się „wewnątrz” terminala, gdziekolwiek to się dzieje. W przypadku emulatora terminala, takiego jak xtermwbudowany w jądro systemu operacyjnego, które zapewnia wirtualne terminale jądra, wewnętrzny stan emulatora, w tym jego pojęcie bieżącego „renderowania graficznego” (tj. Koloru i atrybutów), znajduje się na komputerze i jest teoretycznie dostępny. Ale dla prawdziwego terminala informacja ta znajduje się w pewnej lokalizacji RAM na fizycznie oddzielnej maszynie połączonej przez łącze szeregowe.

To powiedziawszy, niektóre terminale zawierają mechanizm odczytu takich informacji jako część ich protokołu terminala, który jest wysyłany przez to łącze szeregowe. Zapewniają sekwencje kontrolne, które program może wysłać do terminala, co powoduje, że wysyła on informacje o swoim stanie wewnętrznym jako dane wejściowe terminala. mikeservpokazał sekwencje kontrolne, na które xtermodpowiada emulator terminala. Ale są one specyficzne dla xterm. Wbudowane emulatory terminali w jądrze Linuksa i różne jądra BSD są na przykład różnymi typami terminali i nie implementują żadnych takich sekwencji kontrolnych. To samo dotyczy całych rodzin prawdziwych terminali.

Terminale DEC VT525 implementują mechanizm odczytu, ale mają zestaw sekwencji kontrolnych, które nie mają związku z tymi, które są używane przez xterm. Jeden wysyła sekwencję DECRQSS (Żądanie wyboru lub ustawienia), aby zażądać bieżącej interpretacji grafiki, a terminal odpowiada, wysyłając DECRPSS (Wybór lub ustawienie raportu). Konkretnie:

  1. Host wysyła: DCS $ q mST (DECRQSS z częścią funkcji kontrolnej SGR jako ustawienie)
  2. Terminal odpowiada: DCS 0 $ r 0 ; 3 3 ; 4 4 mST (DECRPSS z parametrami i częścią funkcji kontrolnej sekwencji kontrolnej SGR, która ustawia bieżące kolory pierwszego planu i tła)

Oczywiście uważne przeczytanie twojego pytania pokazuje, że znów wymachujesz bananem w czekoladzie w tych europejskich systemach walutowych. To, co tak naprawdę próbujesz zrobić, dla którego wybrałeś rozwiązanie, a następnie zapytałeś, jak wykonać część tego rozwiązania, to zachowanie poprzedniego stanu podczas pisania kolorowych wyników. Do tego celu służy nie tylko sekwencja kontrolna DEC VT, ale także sekwencja terminali konsoli SCO, rozpoznawana przez xtermróżne emulatory terminali wbudowane w jądro, oraz wpis termcap / terminfo, który mówi ci, jakie są dla twojego terminala.

Wpisy termcap to sci rc. Wpisy terminfo to save_cursori restore_cursor. Nazwy są nieco mylące ze względu na działanie (chociaż działają jako ostrzeżenie, że polegasz na czymś, co jest de facto, a nie de jure ). Rzeczywiste sekwencje sterujące DECSC, DECRC, SCOSC i SCORC również zapisują i przywracają bieżące odwzorowanie grafiki.

Biorąc pod uwagę, że wskazany artykuł dotyczy generowania sekwencji sterujących ze skryptów powłoki, polecenie, którego teraz szukasz, to tput.

Dalsza lektura

JdeBP
źródło
Świetna odpowiedź. Cieszę się, że wróciłem po to. Wielkie dzięki.
Minix
@Minix - oprócz sca rc, możesz też zajrzeć do bufora alternatywnego jeśli wsporniki końcowe niego. I tak, to świetna odpowiedź. Minix, może też spójrz na to: jak używać / dev / fb0 jako konsoli z przestrzeni użytkownika . noshApartament zaleca on nie jest jego własnym.
mikeserv
@mikeserv Rzucę okiem, dzięki za linki :)
Minix
2
Zauważyłem, że „nie ma związku z tymi używanymi przez xterm” - jednak DECRQSS wspierał xterm już od dłuższego czasu. Część z odpowiedzią SGR, w tym kolor, pochodzi z 1996 r.
Thomas Dickey
2
Zobacz dalsze czytanie w dokumentacji sekwencji kontrolnych xterm, która wskazuje, że dokumentacja VT520 / etc nie była dostępna, gdy xterm zaczął dostarczać kolory DECRQSS(około 7 lat opóźnienia ...).
Thomas Dickey,
10

W jednym xtermmożna uzyskać bieżące kody kolorów RGB zgłaszane przez zmianę zmiany zmiany koloru na zapytanie. Użyj ESC ] Ps m- ale dodaj ?znak zapytania. Z dokumentów :

  • Jeśli "?"podano a, a nie nazwę lub specyfikację RGB, xtermodpowiada sekwencją kontrolną o tej samej formie, której można użyć do ustawienia odpowiedniego koloru dynamicznego. Ponieważ w jednej sekwencji kontrolnej xtermmożna podać więcej niż jedną parę numeru koloru i specyfikacji, można uzyskać więcej niż jedną odpowiedź.
    • P s = 1 0 → Zmień kolor pierwszego planu tekstu VT100 na P t.
    • P s = 1 1 → Zmień kolor tła tekstu VT100 na P t.
    • P s = 1 2 → Zmień kolor kursora tekstowego na P t.
    • P s = 1 3 → Zmień kolor pierwszego planu myszy na P t.
    • P s = 1 4 → Zmień kolor tła myszy na P t.
    • P s = 15 → Zmień kolor pierwszego planu Tektronix na P t.
    • P s = 1 6 → Zmień kolor tła Tektronix na P t.
    • P s = 1 7 → Zmień kolor tła podświetlenia na P t.
    • P s = 1 8 → Zmień kolor kursora Tektronix na P t.
    • P s = 1 9 → Zmień kolor pierwszego planu podświetlenia na P t.

Mam poważne wątpliwości, czy może to działać w innym emulatorze terminali, ale w xtermprzypadku uruchomienia ...

printf '\033]11;?\007'

... xtermwypchnie z powrotem do bufora wejściowego terminala sekwencję podobną do następującej ...

11;rgb:ffff/ffff/ffff

... w tle lub na pierwszym planie:

printf '\033]10;?\007'

10;rgb:0000/0000/0000
mikeserv
źródło
Kiedy więc biegnę printf '\033]10;rgb:8f8f/8f8f/8f8f8f\007, cały tekst w terminalu, który wcześniej był „normalny”, zmienił kolor na jasnoniebieski. Następnie uruchomienie printf '\033]10;rgb:bfbfbf/bfbfbf/bfbfbf\007'zmienia jasnoniebieski tekst z powrotem na „normalny”. Jak użyć tej wartości, aby zmienić tylko kolor tekstu przesuwającego się do przodu?
fourpastmidnight
@fourpastmidnight: może clearpierwszy?
mikeserv
Myślę, że nie rozumiem dokumentacji. Wyraźnie mówi „P s = 1 0 -> zmień kolor pierwszego planu VT100” i cóż, wydaje się, że to właśnie robi. ;) Ale nie tego się spodziewałem. Może być konieczne użycie wartości RGB uzyskanej z „P s = 1 0; Pt =?” z innym poleceniem ucieczki, aby osiągnąć to, czego chcę.
fourpastmidnight
Ok, printf '\033]10;?\007'pyta xterm o bieżący kolor pierwszego planu terminala. Jeśli twój terminal został uruchomiony z „normalnym” (np. 7 jako kolor pierwszego planu), ale uruchamiasz tput setaf 3przed uruchomieniem printfpolecenia, printfpowyższe polecenie nadal zwraca „normalny” - i to prawda, ponieważ to jest obecny kolor pierwszego planu twojego terminala. To, na co liczyłem, to sposób na odzyskanie bieżącego koloru bieżącej pozycji kursora, abym mógł go zapisać, aby później „przywrócić” - zgodnie z OP.
fourpastmidnight
1
@fourpastmidnight - czy podążałeś za linkiem w odpowiedzi tutaj? także Thomas Dickey - (skomentował inną odpowiedź na to pytanie) jest xtermopiekunem i jest tutaj aktywnym członkiem. (link znajduje się na jego stronie internetowej - xtermdokumenty ucieczki są obszerne - i zasadniczo standardowe odniesienia dla każdego innego programisty, który chce napisać terminal)
mikeserv