Terminal kos
Jeg holder på med å utvikle et spill — et spill i terminalen. I denne prosessen har jeg lært litt om hvordan man temmer terminalen til å oppføre seg rett.
Up the ANSI
Først ut er ANSI escape
codes. Disse kodene
kan brukes til å manipulere teksten og markørens plass i terminalen. Om
du vil fargelegge noe tekst rødt kan du prefikse teksten med \033[31m. Prøv
f.eks. å kjøre denne i din foretrukne terminal:
$ echo -e "\033[31mDenne teksten er rød"
-esørger for atechotolker backslash escapes fremfor å gjengi dem ordrett\033starter escape sekvensen[..mforteller terminalen at du vil farge teksten som kommer etter (litt forenklet)31er fargekoden for rød
\033[0m nulstiller fargen tilbake til originalen. Om du vil ha det ekstra
gøy kan du prøve denne:
echo -e "Det \033[31msmalt\! \033[34mBukken\033[0m stupte \033[32mbums\033[0m i \033[35mbakken\033[0m."
Fantastisk 🎨
For at spillet mitt skal funke bra må jeg finne en måte å tegne opp linjene på nytt, for å unngå å printe de samme linjene under hverandre og søle til scrollback-bufferet. Tenk på forskjellen i oppførsel mellom git og vim. Jeg ønsker meg samme adferd som i vim — når du lukker programmet ser du ikke noen spor etter å ha kjørt det.
ANSI escape codes lar deg også gjøre nettopp dette! 🎉
\033[?1049h åpner et alternativt buffer – akkurat det jeg trenger, og
\033[?1049l tar deg tilbake til det vanlige bufferet. Helmaks! 👌
Men sa du ikke at du må tegne opp linjene på nytt? Dette løser jo ikke problemet 🤨
Helt riktig!
For å rense allerede printet tekst, har vi flere alternativer. Det finnes
escape-koder for å bevege markøren og viske ut tekst relativt til den, men
sammen med det alternative bufferet er det klart enklest å rense hele skjermen
med \033[H\033[2J.
Interager, da vel!
Vanlig oppførsel i terminalen er å lese input på <ENTER>. Du må skrive inn
passord — og det er først når du trykker <ENTER> at inputtet blir sendt til
programmet.
Dette kommer ikke til å funke 🤔 Hvordan skal man få slangen til å bekjempe, ødelegge og rasere uten raske tastetrykk?
stty til unnsetning 💪
stty er en kommando for å endre oppførselen til terminalen. Jeg vil særlig
fremheve to flagg: -echo og -icanon (lokale moduser). Takk til
Teodor og
bbslideshow for å hjelpe meg på
vei.
-echogjør at tastetrykk ikke blir skrevet til bufferet. Så når jeg trykkersvil det ikke komme ensi terminalen med dette flagget aktivert. Sagt med andre ord fjerner du terminalens echo-evne.-icanonendrer måten terminalen leser input. I stedet for å lese input linje for linje, blir inputtet lest tegn for tegn.
stty -icanon -echo gir oss da de perfekte forholdene for et spill i
terminalen. Vi får ikke unødvendige tegn rundt omkring og vi trenger ikke å
trykke <ENTER> hver gang vi ønsker å gjøre noe. For å gjenopprette terminalens
daglige kår er det bare å kjøre samme kommando uten strekene: stty icanon echo.
I spillet mitt har jeg planer om også å bruke ctrl-tastebindinger. Men også her
kommer jeg i veien for terminalens normale oppførsel. Om jeg vil bruke
CTRL-c f.eks. vil det ha ganske så katastrofale følger for spillet mitt.
Spillet ville bli fortalt om å lukke porten og si farvel til oss dødelige.
Dette må også tas hånd om ✋
Her kan vi også bruke stty til å rebinde tastebindingene. Vi kan rebinde
CTRL-c med stty intr ''. Dette vil i praksis deaktivere muligheten for å
avbryte en prosess – ikke for sarte sjeler. Tilbakestill med stty intr '^C'.
Med stty -e får du listet opp alle flagg, kommandoer og bindings.
I spillet mitt kan jeg da kjøre:
$ stty stop '' discard '' intr '' susp '' lnext '' reprint '' werase '' dsusp '' eof '' status '' start '' kill ''
$ stty stop '^S' discard '^O' intr '^C' susp '^Z' lnext '^V' reprint '^R' werase '^W' dsusp '^Y' eof '^D' status '^T' start '^Q' kill '^U'
og forårsake så mye kaos jeg vil 💥❤️🔥😈 — og rydde pent opp etter meg igjen 😇.
Yippie ‼ 🙌
Følg instinktene dine 👀
Noe annet som skurrer for meg, er at markøren er synlig. Den har ikke noen rolle i spillet mitt så da trenger man heller ikke beskue dens eksistens.
tput er kommandoen for dette 😁 tput civis skjuler markøren og tput cnorm
visualiserer den på nytt. Tada! 🎉
Oppsummering
\033[..mfargelegger teksten etter i den angitte fargen\033[?1049hgår til alternativt buffer\033[?1049lbringer deg tilbake til det vanlige bufferet\033[H\033[2Jrenser hele skjermen for skittenskapstty -icanon -echoleser input tegn for tegnstty icanon echoleser input linje for linjestty <ctrl> <binding>rebind tastebindingertput civisskjuler markørentput cnormbringer tilbake markøren
Hederlig omtale
trap <action> <condition>
trap lar deg innskyte et signal med ekstra kommandoer før det eksekveres eller
endre oppførselen fullstendig. F.eks. trap "exiting..." SIGINT vil printe ut
strengen "exiting..." før prosessen blir kansellert.
Man kan da bruke denne til f.eks. å rydde opp i volatile elementer før en prosess avsluttes, eller innskyte kommandoer før et vilkårlig signal blir eksekvert.

