A Console osztály lehetÅ‘séget ad számunkra, hogy az alkalmazásunkat futtató terminálban szövegeket tudjunk megjelenÃteni. Nagyon sokáig a Windows és a Unix rendszerek terminál implementációja eltért. Ennek okai a visszafelé kompatibilitásban keresendÅ‘ek. A Unix kezdetektÅ‘l fogva egy olyan operációs rendszer volt, amit olyan gépekre szántak, ahol a memória mérete legalább pár megabyte-ban mérhetÅ‘, ezért a készÃtÅ‘knek volt lehetÅ‘ségük rendesen elválasztani a megjelenÃtendÅ‘ szöveget a megjelenÃtés módjától illesztÅ‘programokkal és egyebekkel.
A Windows konzolos gyökerei azonban a DOS idÅ‘kig és az elsÅ‘ IBM PC-ig nyúlnak vissza. Az elsÅ‘ IBM PC összesen egy megabyte memóriával rendelkezett, amibÅ‘l csupán 640 kilobyte volt használható a programok számára. A limitált memória megoldás miatt a fejlesztÅ‘k kénytelenek voltak lefaragni a komplexitásból. Az egész operációs rendszer Assembly-ben Ãródott, hogy mind a memória, mind pedig a lemez korlátokba beleférjenek. Az operációs rendszer és a PC népszerűségének köszönhetÅ‘en a Windows-nak visszafelé kompatibilisnek kellett maradnia a régi API[^1] hÃvásokkal.
A Windows 10 2016-os frissÃtése és a Windows terminál létezése óta azonban lehetÅ‘ségünk van ANSI escape kódokat is használni a konzol alkalmazásainkban Windows alatt is. De mik ezek az ANSI escape kódok?
A Unix nagy gépekre lett tervezve, amik egyszerre több felhasználót is ki tudtak szolgálni hálózaton keresztül. Ehhez a hozzáféréshez kellettek a terminálok, amik fizikai eszközök voltak egy monitorral és egy billentyűzettel és egyetlen funkciójuk az volt, hogy a hálózaton kapott információt megjelenÃtsék és a bevitelt továbbÃtsák a gép felé. A szó szoros értelmében ezek buta eszközök voltak. Az idÅ‘ fejlÅ‘désével azonban megjelent az igény, hogy a sima szöveg mellett formázott szöveget is meg tudjanak jelenÃteni.
A formázást speciális escape kódokkal oldották meg, amelyek a képernyÅ‘n nem jelennek meg, de módosÃtják a szöveg megjelenését. Ezen kódok gyártónként eltértek, Ãgy elÅ‘bb-utóbb felmerült az igény, hogy egységesÃtsék Å‘ket, Ãgy születtek meg az ANSI kódok, amiket minden terminálnak támogatnia kellett. Ennek az alapja a DEC 1978-ban megjelent VT100-as modellje volt. Manapság a terminálok emulátorok formájában élnek tovább és a VT100 mellett számos extra funkcionalitást kÃnálnak.
Az escape kódok az escape karakterrel kezdődnek, ami az \u001b karakter. Ez egy Unicode bináris formában megadott karakter. C# 13 óta a \e karakterrel hivatkozhatunk rá. Az alábbi táblázat néhány escape kódot foglal össze:
| C# kód | LeÃrás |
|---|---|
"\e[0m" |
VisszaállÃtás (minden formázás törlése) |
"\e[1m" |
Félkövér (bold) |
"\e[3m" |
Dőlt (italic) |
"\e[4m" |
Aláhúzott (underline) |
"\e[30m" |
Előtér: fekete |
"\e[31m" |
Előtér: piros |
"\e[32m" |
Előtér: zöld |
"\e[33m" |
Előtér: sárga |
"\e[34m" |
Előtér: kék |
"\e[35m" |
ElÅ‘tér: bÃbor (magenta) |
"\e[36m" |
Előtér: cián |
"\e[37m" |
Előtér: fehér |
"\e[40m" |
Háttér: fekete |
"\e[41m" |
Háttér: piros |
"\e[42m" |
Háttér: zöld |
"\e[43m" |
Háttér: sárga |
"\e[44m" |
Háttér: kék |
"\e[45m" |
Háttér: bÃbor (magenta) |
"\e[46m" |
Háttér: cián |
"\e[47m" |
Háttér: fehér |
"\e[38;2;255;128;0m" |
24 bites elÅ‘tér szÃn |
"\e[48;2;0;128;255m" |
24 bites háttér szÃn |
Ezeket behelyettesÃtve a Console.Write vagy Console.WriteLine metódusokba formázni tudjuk a kimenetet. A Windows által támogatott escape kódok listája a https://learn.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences cÃmen található meg, a https://en.wikipedia.org/wiki/ANSI_escape_code cÃmen pedig egy általános leÃrás a kódokról. Itt megjegyzem, hogy terminál és terminál között van különbség. Nem biztos, hogy minden kódot minden terminál program támogatni fog.
Az alábbi program a táblázatban szereplő kódok használatát szemlélteti:
using System;
namespace PeldaAnsiCodes
{
class Program
{
static void Main()
{
// Reset
Console.WriteLine("\e[0mAlapértelmezett szöveg");
// StÃlusok
Console.WriteLine("\e[1mFélkövér (bold)\e[0m");
Console.WriteLine("\e[3mDőlt (italic)\e[0m");
Console.WriteLine("\e[4mAláhúzott (underline)\e[0m");
// ElÅ‘tér szÃnek
Console.WriteLine("\e[30m\e[43mFekete előtér + Sárga háttér\e[0m");
Console.WriteLine("\e[31mPiros előtér\e[0m");
Console.WriteLine("\e[32mZöld előtér\e[0m");
Console.WriteLine("\e[33mSárga előtér\e[0m");
Console.WriteLine("\e[34mKék előtér\e[0m");
Console.WriteLine("\e[35mBÃbor elÅ‘tér\e[0m");
Console.WriteLine("\e[36mCián előtér\e[0m");
Console.WriteLine("\e[37mFehér előtér\e[0m");
// Háttér szÃnek
Console.WriteLine("\e[40mFekete háttér\e[0m");
Console.WriteLine("\e[41mPiros háttér\e[0m");
Console.WriteLine("\e[42mZöld háttér\e[0m");
Console.WriteLine("\e[43mSárga háttér\e[0m");
Console.WriteLine("\e[44mKék háttér\e[0m");
Console.WriteLine("\e[45mBÃbor háttér\e[0m");
Console.WriteLine("\e[46mCián háttér\e[0m");
Console.WriteLine("\e[47m\e[30mFehér háttér + Fekete szöveg\e[0m");
// 24 bites RGB szÃnek
Console.WriteLine("\e[38;2;255;128;0m24 bites előtér (narancs)\e[0m");
Console.WriteLine("\e[48;2;0;128;255m24 bites háttér (világoskék)\e[0m");
}
}
}
A program kimenete:
Alapértelmezett szöveg
Félkövér (bold)
Dőlt (italic)
Aláhúzott (underline)
Fekete elÅ‘tér + Sárga háttér
Piros elÅ‘tér
Zöld elÅ‘tér
Sárga elÅ‘tér
Kék elÅ‘tér
Bíbor elÅ‘tér
Cián elÅ‘tér
Fehér elÅ‘tér
Fekete háttér
Piros háttér
Zöld háttér
Sárga háttér
Kék háttér
Bíbor háttér
Cián háttér
Fehér háttér + Fekete szöveg
24 bites elÅ‘tér (narancs)
24 bites háttér (világoskék)