upgrade de bash prompt
Unul din howto-urile citite pe LDP in "tinerete" a fost Bash Prompt HOWTO care descrie tot felul de scamatorii care se pot face cu prompturile bashului, in special cel primar ($PS1). Cum nu-s mare fan al customizarii nu m-am complicat niciodata sa imi fac prompturi sofisticate ca diversi cunoscuti, in special pentru ca zilnic lucrez pe foarte multe masini si pentru familiaritate prefer sa nu schimb nimic foarte tare.
Relativ recent am cedat tentatiei si am activat un prompt colorat pe laptop, asta sa identific foarte repede daca sunt deconectat de la toate sesiunile remote inainte sa dau suspend. Pe Debian treaba asta se face foarte simplu, se decomenteaza linia cu force_color_prompt="yes" din ~/.bashrc (sau daca a suferit vreun accident se poate recopia din /etc/skel/.bashrc). Ceva mai jos este definit un PS1 cu userul si masina in verde si calea curenta in albastru.
Am folosit schema asta cateva luni de zile dar recent, dat fiind ca am inceput sa ma joc cu git, am constatat ca mi-ar prinde bine sa stiu ce branch este activ in repo-ul in care sunt (daca este cazul). Ca atare, mi-am bagat ceva mai mult nasul prin .bashrc si cu ceva sugestii furate de prin rss feeds si de prin man bash, am obtinut urmatoarea chestie:
ESC="\033"
NORM=${color_prompt:+"\[$ESC[00m\]"}
RED=${color_prompt:+"\[$ESC[01;31m\]"}
GREEN=${color_prompt:+"\[$ESC[01;32m\]"}
YELLOW=${color_prompt:+"\[$ESC[01;33m\]"}
BLUE=${color_prompt:+"\[$ESC[01;34m\]"}
PURPLE=${color_prompt:+"\[$ESC[01;35m\]"}
CYAN=${color_prompt:+"\[$ESC[01;36m\]"}
WHITE=${color_prompt:+"\[$ESC[01;37m\]"}
GITPS1='$(__git_ps1 " :%s ")'
PS1="${GREEN}\u@\h${NORM}:${BLUE}\w${NORM}${YELLOW}${GITPS1}${NORM}\$ "
Okay, explicatii:
Culorile le-am definit separat ca sa-mi fie mai usor sa pricep definitia lui PS1. Toate depind de variabila $color_prompt. Constructia ${var:+ceva} inseamna in bash "daca $var e definita si nu e vida, se foloseste ce vine dupa :+, altfel nimic". O definitie mai riguroasa se gaseste in manualul lui bash, la capitolul "parameter expansion". Secventa care defineste culoarea textului este: escape (caracterul cu cod ascii 27, sau 033 in octal), caracterul [, un cod pentru text normal/bold (00 respectiv 01), urmate optional de codurile de culoare pentru foreground si background precedate fiecare de punct si virgula, iar la sfarsit caracterul m. Sincer, habar n-am istoricul acestor coduri, de-aia le copiez mereu de prin alte parti
Codurile de culoare sunt de la 30 la 37 pentru foreground si de la 40 la 47 pentru background, in ordinea de mai sus (desi am sarit peste negru, care era primul). Cred ca mai portabil de atat ar fi fost cu tput, dar o sa tin minte cand o sa folosesc alt terminal capabil de culori in afara de xterm (.bashrc-ul me mai are niste secvente care determina capabilitatile terminalului, sa nu incerce funky business in screen, de exemplu).
Mai important e ca tiparirea in terminal a unei secvente ca cea de mai sus informeaza terminalul ca textul care urmeaza sa fie tiparit cu culorile respective. Asta inseamna ca la sfarsitul textului colorat, terminalul trebuie resetat prin secventa "\033[00m", adica "text normal". Asta este definita in variabila $NORM.
Partea de git este rezolvata cu functia __git_ps1, definita in /etc/bash_completion.d/git. Daca shellul nu foloseste bash_completion, branchul curent se poate extrage cu "git symbolic-ref HEAD | cut -c 12-". Folosesc iarasi scamatoria cu :+ pentru a nu afisa nimic in cazul in care nu-s intr-un repository de git.
Neglijand partea de culori, acum promptul meu arata asa, in afara unui repository de git si in interiorul unuia:
petre@kobold:~/git$ cd scripts
petre@kobold:~/git/scripts :local $
Evident se pot face dracii similare si cu svn sau cvs, dar cu mare atentie sa fie folosite doar resurse locale, nu e foarte simpatic ca la fiecare prompt nou sa astepti 'jde secunde sa fie contactat serverul.
Si uite asa un post de tip "quickie" s-a lungit cat o zi de post
Hope this helps.
Later edit: Aparent, am neglijat un detaliu. Asa cum am descris secventele de culoare, cu \033[01;31m, terminalul le include de lungime non-zero in calculele de pozitie a cursorului, avand niste efecte secundare foarte urate cand e vorba de linii de comanda foarte lungi (dat fiind ca am terminalul foarte lat de obicei, m-am lovit de asta ceva mai tarziu si n-am facut legatura imediat). Corect e ca o astfel de secventa sa fie incadrata de \[ si \] pentru a corecta pozitia reala a cursorului. Am modificat mai sus scriptul in consecinta. Scuze.