Minule sme si ukázali, ako pomocou escape sekvencií ofarbiť terminál. Pre lepšiu navigáciu medzi oknami nám môžu poslúžiť nadpisy (window title). Tie sa vedia zobraziť v titulku grafického okna, ak také máme, prípadne v status riadku screenu. Nadpisy sa, podobne ako farby, tiež dajú nastaviť pomocou escape sekvencií.
Xterm ----
Titulok xterm-kompatibilného terminálu je možné nastaviť pomocou escape sekvencie esc]0;text^G
(kde ^G
je znak BEL, ASCII 7, resp. '\a
'). Konkrétnejšie na mieste nuly môžu byť:
- 2 – nastaví titulok okna
- 1 – nastaví titulok ikony (napr. Eterm)
- 0 – kombinácia 1+2
V praxi je najjednoduchšie veriť nule. Podporujú ju určite rxvt
, Konsole
, aj PuTTY
. Či to funguje, overíme jednoducho:
echo -en "\033]0;test\007"
Screen ----
Veľa ľudí, ktorí pracujú so vzdialeným textovým terminálom, iste používa screen
. Umožňuje mať spustených viacero okien, ktoré bežia na vzdialenom stroji, čím sa vyhneme zaveseniu programov pri strate spojenia, alebo napríklad aj ušetríme prenosové pásmo počas kompilácie niečoho (prepnutím sa dočasne do menej "ukecaného" okna). Pre tých, čo sa so screenom ešte nestretli, jednoduchý začiatok získajú prečítaním si prvých pár odstavcov z Gentoo Linux Wiki (žiaľ v tejto chvíli nefunkčné), alebo man screen(1).
Titulok terminálu, v ktorom screen beží, je nastavovaný priamo screenom, ovplyvniť ho vieme pomocou jeho príkazu hardstatus string
. Aby vedel screen povedať terminálu, že hardstatus má vypísať do titulku okna, potrebuje na to správne termcapinfo. Dobré sú napríklad takéto riadky v .screenrc
alebo /etc/screenrc
pre screen verzie 3.x, resp. 4.x:
# screen v3:
hardstatus string 'myhost: %n* %t -- %W'
hardstatus lastline
termcapinfo xterm 'hs:ts=\E]2;:fs=\007:ds=\E]2;screen\007'
# screen v4:
hardstatus string '%H: %-w%{= BW}%50>%n%f* %t%{-}%+w%<'
hardstatus lastline
termcapinfo xterm 'hs:ts=\E]2;:fs=\007:ds=\E]2;screen\007'
ctrl-a : title názov
ctrl-a A názov
- spustením programu
screen -t nazov cislo_okna prikaz
- automaticky na názov spúšťaného príkazu pomocou
shelltitle '$ |sh'
- vypísaním sekvencie
ESCknázovESC\
(ESC je znak escape, k je obyčajné písmeno)
Posledný spôsob (vypísaním escape sekvencie) nám umožní automatizovať, teda napríklad nastaviť titulok okna podľa názvu aktuálneho adresára zakomponovaním do promptu apod. Automatické nastavenie pomocou príkazu screenu shelltitle
sa zdá byť na prvý pohľad dobré, avšak má vážny nedostatok: aby fungovalo, musí byť vypísaná sekvencia ESCkESC\
, a teda nemôžeme naraz vypísať názov aktuálneho adresára a vzápätí názov spúšťaného programu.
Manuálny title ----
Predchádzajúce poznatky zhrnieme v malom skripte, ktorý nastaví názov okna pre xterm
alebo screen
(rozpozná ich podľa premennej $TERM
). Pracovne je nazvaný my-title:
#!/usr/bin/env bash
#:~/bin/my-title
#
# set window title (in xterm or screen terminal)
if [ "$1" = "" ]; then
t="`dirs`"
else
t="$1"
fi
case $TERM in
xterm*)
echo -en "\033];`whoami`@`hostname -s`: $t\007"
;;
screen*)
echo -en "\033k"
# 1=login shell, 2=this script run (not sourced) from it
if [ "$SHLVL" -le 2 ]; then
# if the shell is a login shell, screen must be
# running on a different machine - include hostname:
echo -en "`hostname -s`:"
fi
echo -en "$t\033\134"
;;
esac
Automatický title ----
Vyššie už bola spomenutá možnosť nastavovať titulok automaticky podľa názvu aktuálneho adresára. Trik spočíva v zakomponovaní escape sekvencie do promptu. Treba však rozlíšiť, či budeme vypisovať sekvenciu pre xterm, alebo pre screen, a čo vlastne chceme nastaviť ako titulok.
O niečo zložitejšie je dostať názov aktuálne bežiaceho programu do titulku okna. V zásade je niekoľko prístupov:
- alias – vytvoriť si alias pre najčastejšie spúšťané programy, napríklad:
alias p 'my-title PINE; pine -d 0 -p ~/mail/.pinerc'
- v screene pomocou shelltitle – potom však nie je vidno názov aktuálneho adresára (ako už bolo spomenuté hore)
- mágiou v shelli – vypísaním escape sekvencie s názvom spúšťaného programu tesne pred jeho spustením.
Pri poslednom spôsobe nemôžeme sekvenciu vypísať len tak priamo, pretože by pri presmerovaných výstupoch (napríklad aj cat | grep | less
) došlo k výpisu sekvencie do vnútra rúry a tým by sme mohli v horšom prípade aj niečo pokaziť. Preto treba sekvenciu doručiť nie na stdout, ale na zariadenie používateľovho terminálu. V rôznych shelloch sa to robí všelijako.
tcsh ----
Pre výpis aktuálneho adresára do titulku xtermu stačí zakomponovať do set prompt=
napríklad reťazec "%{\033]0;%n@%m: %~\007%}
". Je medzi znakmi %{
a %}
, aby shell vedel, že ich výpis neovplyvní dĺžku príkazového riadku. V titulku potom budeme mať zobrazený username@hostname:currentpath.
Vypísanie spúšťaného programu do titulku môžeme dosiahnuť pomocou aliasu postcmd, ktorý sa vykonáva vždy tesne pred spustením zadaného príkazu. Názov programu získame z histórie pomocou '!
'. Vypisovať nesmieme na stdout
, ale do /dev/$tty
. Celý alias môže potom vyzerať približne takto:
alias postcmd "echo -n "'"'"`cat ~/bin/esc`]0;`whoami`@`hostname -s`: \!#`cat ~/bin/beep`"'"'" > /dev/$tty"
echo
v tcsh
nepozná parameter -e
, teda nevieme ním vypisovať špeciálne znaky. Preto si ich vyrobíme inak – buď použijeme /bin/echo
, ak to podporuje, alebo bash
. Keďže quotovanie v tcsh je hrôza, môžeme mať špeciálne znaky dopredu vyrobené a uložené v súboroch esc
a beep
:# making special chars in tcsh:
bash -c 'echo -en "\033"' > ~/bin/esc
bash -c 'echo -en "\007"' > ~/bin/beep
bash ----
Aktuálny adresár dostaneme do titulku v bashi veľmi podobne, escape sekvenciou vo vnútri premennej $PS1
, napríklad reťazcom "\[\033]0;\u@\h: \w\007\]
". Hranaté zátvorky slúžia na rovnaký účel, ako zložené pre tcsh.
S výpisom spusteného programu do titulku je to v Bashi horšie. Nemá ekvivalent 'postcmd' v tcsh
, ani 'preexec' v zsh
. David Pashley však vykutral, že by sa na tento účel dal použiť DEBUG trap. Ten sa vykoná pre každý jednoduchý príkaz. Názov toho príkazu vidno v premennej $BASH_COMMAND
. Čo je však naozaj problém, je zistiť názov aktuálneho terminálového zariadenia. (Priamo to ide len cez prompt s '\l
', cez ktorý sa však trap nastaviť nedá – DEBUG trapy sa smerom nahor nededia [smerom k deťom len pri zapnutom set -o functrace
].) Preto na zistenie názvu tty zneužijeme tcsh
, skrátene:
trap "echo -en '\e]0;`whoami`@`hostname -s`: \$BASH_COMMAND\007' > /dev/`tcsh -c 'echo $tty'`" DEBUG
$BASH_COMMAND
totiž mení aj vo vnútri trapu, resp. je prázdna. Oproti tcsh
vieme zobraziť len jednotlivé príkazy, a nie celý zadaný riadok, s tým sa však dá žiť, dokonca niekedy je to tak prehľadnejšie.
Ultimátna kombinácia ----
Skombinovaním farieb a titulkov (pre prípady xtermu, screenu lokálne, vzdialeného stroja v screene) v univerzálne použiteľnom bash/C-shell skripte získame celkom pekný shell. Skripty sú trochu dlhšie, na stiahnutie:
- bash farby + titulky – umiestnime napr. do
/etc/profile.d/
, alebo niekam do homediru (~/bin
). Pozor, keďže bash nemá jeden konzistentný rc súbor, ktorý by púšťal zakaždým pre login aj non-login shelly, potrebujeme to spúšťať z.bashrc
:
a tiež z# part of .bashrc
. ~/bin/prompt-colors+title.bash.bash_profile
– ja v ňom štandardne používam:
# part of .bash_profile
. ~/.bashrc - tcsh farby + titulky – umiestnime napr. do
~/bin
a voláme z.cshrc
:
# part of .cshrc
source ~/bin/prompt-colors+title.csh
Keď skript dáme aj na ostatné stroje, kam sa prihlasujeme, výsledok môže vyzerať takto nejako pre screen:
a pre xterm:
Záver ----
Zobrazenie cesty aktuálneho adresára v titulku xterm
u a screen
u používam už niekoľko rokov bez žiadnych problémov. Nedokázal som vtedy vyriešiť vypisovanie bežiaceho programu, zrejme preto, že screen
to nevedel poriadne, a bash
vôbec :) – túto vymoženosť som začal používať až pred pár dňami. Zatiaľ som nenarazil na nejaké veľké neželané vedľajšie efekty, snáď okrem prebliknutia titulku, keď sa vykonávajú krátke príkazy. Zrejme tých pár znakov navyše zhorší zahltenie linky, ale nie badateľne a nastavený DEBUG trap možno trochu znižuje performance – nemám ho však s -o functrace
, platí teda len pre aktuálny shell a nie pre skripty.
Zdroje ----
Doplnenie (edit):
Medzi neželané vedľajšie efekty patrí skomolenie názvu jobu (iba v bash
i, kvôli trapu). Nedá sa potom ľahko orientovať medzi zastavenými jobmi, pretože sa všetky volajú rovnako:
^ZYou have suspended the program. Type 'fg' to return
[2]+ Stopped echo -en "\ek$BASH_COMMAND\e\134" >/dev/pts/6
matej@aelia:~$ jobs
[1]- Stopped echo -en "\ek$BASH_COMMAND\e\134" >/dev/pts/6
[2]+ Stopped echo -en "\ek$BASH_COMMAND\e\134" >/dev/pts/6
screen
e ako správu jobov na pozadí.
Zabudol som dodať, že samozrejme farby v "ultimátnom" skripte si každý môže nastaviť podľa chuti, nahradením sekvencií "\033[*m" v riadku, kde sa nastavuje premenná prompt resp. PS1.
Velmi pekny clanok, ja len doplnim, ze je prakticke (a hlavne je to prehladne) ulozit escape sekvencie pre jednotlive farby do premennych (napr do ~/.bashrc) a potom pracovat prave s tymi premennymi.
----------
tommyhot@hackingmachine:~$ microsoft &> /dev/null
Pekny clanok, dufam ze seriu ukoncis nejakym uvodom k ncurses, pokial viem v praxi sa pouziva ta, aby clovek nemusel specialne kodovat pre kazdy terminal.