olhos vermelhos





Olá, apresento a sua atenção um pequeno tutorial sobre como projetar um prompt de linha de comando com olhos vermelhos.



Todos que trabalharam no console de algum Linux provavelmente notaram o recurso conveniente de exibir a pasta atual, nome de usuário, nome do servidor e algo mais dependendo do distra na linha de prompt. Sempre gostei também. Mas às vezes ficava assim:







É difícil "criar" em uma linha de três caracteres, é claro que o cursor se move para a próxima linha, mas isso enfurece mais do que ajuda. E a certa altura, disse a mim mesmo:







decidi retomar todo o espaço da linha de comandos e nunca mais devolvê-lo a ninguém. A questão era como mudar o texto do prompt de comando? Acabou sendo muito simples, basta alterar a variável especial do sistema `PS1`.







Sim, você pode definir um novo texto de convite diretamente no terminal. Mas como você salva as alterações? E mesmo sem informações sobre o catálogo atual, você de certa forma se sente incomodado, sempre se perguntando: "Onde estou?" O arquivo ~ / .bashrc vai ajudar , nele você pode salvar a alteração do PS1, e para que as informações sobre o diretório atual não ocupem o espaço de trabalho, decidi colocá-lo não no IN, mas SOBRE a linha de comando. Adicione a seguinte linha ao arquivo ~ / .bashrc :



PS1='$PWD\n# '


Preste atenção às aspas simples, se usarmos aspas duplas, então em vez de um ponteiro para a variável $ PWD (uma variável de sistema que armazena o caminho completo da pasta atual, análogo ao comando pwd) , seu valor (diretório atual) será escrito na string de prompt e alterado ao mover da pasta a pasta não será. Tem a seguinte aparência: A







linha de comando é totalmente gratuita, mas o nome da pasta se mescla ao conteúdo se você executar o comando ls . Teremos que separar as moscas das costeletas, o nome da pasta do conteúdo. Decidi adicionar "frames" para $ PWD adicionando linhas "-" nas partes superior e inferior. Como posso descobrir o número de caracteres em uma string? Existe também a variável de sistema $ COLUMNS para isso.... E para formar rapidamente uma string com o número necessário de caracteres "-", use o comando printf :



printf -v line "%${COLUMNS}s"


Este comando irá criar uma linha variável $ e preenchê-la com espaços no valor de $ COLUMNS mas não precisamos de espaços, mas "-", para isso usamos o seguinte truque:



line=${line// /-} #     -


Vamos adicionar este código a ~ / .bashrc



printf -v line "%${COLUMNS}s"
line=${line// /-}
PS1='\n$line\n$PWD\n$line\n# '






Ótimo, mas se mudarmos o tamanho da janela do terminal agora, o tamanho das "linhas" não vai mudar e a beleza vai desaparecer:







Para corrigir a situação, vamos transferir o novo código para a função info e adicioná-lo ao PS1:



info () {
    printf -v line "%${COLUMNS}s"
    line=${line// /-}
    printf "\n$line\n$PWD\n$line\n# "
}
PS1='$(info)'


Você pode combinar negócios com prazer adicionando uma "inserção" com o nome do host no delimitador superior. A inserção com o nome ficará no meio, para isso precisamos calcular o centro da linha (levando em consideração o comprimento do nome do host e caracteres adicionais):



info () {
    name_length="{ $HOSTNAME }"
    name_length=${#name_length}
    top_line_left=$[(COLUMNS-name_length)/2]
    top_line_right=$[COLUMNS-(top_line_left+name_length)]
    printf -v top_line "%${top_line_left}s{_S_${HOSTNAME}_S_}%${top_line_right}s"
    printf -v bot_line "%${COLUMNS}s"
    bot_line=${bot_line// /-}
    top_line=${top_line// /-}
    top_line=${top_line//_S_/ }
    printf "\n$top_line\n$PWD\n$bot_line\n# "
}
PS1='$(info)'






Coloquei o nome do host entre colchetes com espaços, mas em vez de espaços ao redor de $ HOSTNAME , os caracteres "_S_" são usados, os quais são alterados para espaços. Isso é necessário porque na linha final todos os espaços são substituídos por "-", e os espaços devem permanecer dentro da inserção. Vamos adicionar cores, para isso vamos preparar variáveis ​​com códigos para mudar a cor do texto no terminal, usei as seguintes cores:



RED='\e[31m' # 
GRN='\e[32m' # 
YLW='\e[33m' # 
BLU='\e[34m' # 
MGN='\e[35m' # 
DEF='\e[0m'  #    
BLD='\e[1m'  # 
DIM='\e[2m'  # 


Vamos adicionar essas variáveis ​​ao nosso código:



info () {
    name_length="{ $HOSTNAME }"
    name_length=${#name_length}
    top_line_left=$[(COLUMNS-name_length)/2]
    top_line_right=$[COLUMNS-(top_line_left+name_length)]
    printf -v top_line "%${top_line_left}s{_S_$DEF$BLD$HOSTNAME${DEF}_S_$GRN}%${top_line_right}s"
    printf -v bot_line "%${COLUMNS}s"
    bot_line=$GRN${bot_line// /-}$DEF
    top_line=${top_line// /-}
    top_line=$GRN${top_line//_S_/ }$DEF
    printf "\n$top_line\n$BLD$BLU$PWD$DEF\n$bot_line\n# "
}
PS1='$(info)'






Vá em frente, o lado direito parece vazio, você pode colocar a data e a hora lá:



printf -v date "%(%a %d %b %T)T"


Para colocar isso à direita, você precisa adicionar alguns espaços após $ PWD , que, vamos contar:



center_space=$[COLUMNS-${#date}-${#PWD}]
((center_space<0)) && center_space=1
...
printf "\n$top_line\n$BLD$BLU$PWD$DEF%${center_space}s$DIM$date\n$bot_line\n# "






Você pode fazer melhor? Claro, vamos adicionar a saída de status git se estivermos na pasta com o projeto git :



    git_tst= git_clr=
    [[ -d .git ]] && {
        git_tst=($(git status -c color.ui=never -sb))
        git_tst="GIT ${git_tst[*]} " #   
        git_clr=(GIT $(git -c color.ui=always status -sb))
        git_clr="GIT ${git_clr[*]} " #   
    }
    ...
    center_space=$[COLUMNS-${#date}-${#PWD}-${#git_tst}]
    ...
    printf "\n$top_line\n$BLD$BLU$PWD$DEF%${center_space}s$git_clr$DIM$date\n$bot_line\n\$ "






Observe que git_clr e git_tst são escritos primeiro como uma matriz e depois convertidos em variáveis. Isso é necessário para remover quebras de linha da saída de status do git . Mas onde estão os olhos? Agora haverá olhos O_o, vamos criar uma matriz com um conjunto básico de olhos:



eyes=(O o ∘ ◦ ⍤ ⍥)


E vamos contar o número deles:



en=${#eyes[@]}


Vamos adicionar um símbolo de boca:



mouth='_'


E vamos fazer um gerador de faces aleatórias:



face () {
    printf "$YLW${eyes[$[RANDOM%en]]}$mouth${eyes[$[RANDOM%en]]}$DEF"
}


Os olhos estarão localizados nas bordas do campo de informações, você precisa levá-los em consideração ao calcular o número de espaços no meio, vamos preparar uma variável separada para isso:



face_tst='O_o  o_O'
...
center_space=$[COLUMNS-${#date}-${#PWD}-${#git_tst}-${#face_tst}]
printf "\n$top_line\n$(face) $BLD$BLU$PWD$DEF%${center_space}s$git_clr$DIM$date $(face)\n$bot_line\n\$ "






Como fazer seus olhos corarem? Sentado no computador por um longo tempo, sem dormir. Em stackoverflow.com me deparei com uma pergunta interessante , o autor pergunta: "como mudar a cor no prompt da linha de comando para vermelho se o último comando falhar?" Isso me levou à ideia de olhos vermelhos. Vamos adicionar à função info lembrando o status de conclusão do último comando:



info () {
    error=$?
    ...
}


E vamos mudar a função do rosto para que verifique a variável $ error e, dependendo do seu valor, pinte os olhos de vermelho ou amarelo:



face () {
    [[ $error -gt 0 ]] && ecolor=$RED || ecolor=$YLW
    printf "$ecolor${eyes[$[RANDOM%en]]}$YLW$mouth$ecolor${eyes[$[RANDOM%en]]}$DEF"
}






Bem , meus olhos ficaram vermelhos, mas você pode acrescentar algo mais. Vamos adicionar uma verificação para a variável $ debian_chroot :



[[ $debian_chroot ]] && chrt="($debian_chroot)" || chrt=
...
name_length="{ $HOSTNAME$chrt }"
...
printf -v top_line "%${top_line_left}s{_S_$DEF$BLD$HOSTNAME$chrt${DEF}_S_$GRN}%${top_line_right}s"


E vamos mudar o texto no título da janela do terminal:



PS1='$(info)'; case "$TERM" in xterm*|rxvt*) PS1="\[\e]0;$(face 1) \w\a\]$PS1";; esac


O título exibirá o rosto e o diretório atual, mas você terá que modificar ligeiramente a função do rosto para que desenhe o rosto sem códigos de cores, eles serão exibidos no título como apenas texto, passaremos alguns parâmetros (por exemplo, "1") para a função do rosto , adicione uma marca de seleção dentro da função, se o primeiro argumento for dado, imprime o focinho sem colorir:



face () {
    [[ $error -gt 0 ]] && ecolor=$RED || ecolor=$YLW
    [[ $1 ]] && printf "${eyes[$[RANDOM%en]]}$mouth${eyes[$[RANDOM%en]]}" \
             || printf "$ecolor${eyes[$[RANDOM%en]]}$YLW$mouth$ecolor${eyes[$[RANDOM%en]]}$DEF"
}






Roteiro final:



RED='\e[31m' # 
GRN='\e[32m' # 
YLW='\e[33m' # 
BLU='\e[34m' # 
MGN='\e[35m' # 
DEF='\e[0m'  #    
BLD='\e[1m'  # 
DIM='\e[2m'  # 
eyes=(O o ∘ ◦ ⍤ ⍥) en=${#eyes[@]} mouth='_'
face () {
    [[ $error -gt 0 ]] && ecolor=$RED || ecolor=$YLW
    [[ $1 ]] && printf "${eyes[$[RANDOM%en]]}$mouth${eyes[$[RANDOM%en]]}" \
             || printf "$ecolor${eyes[$[RANDOM%en]]}$YLW$mouth$ecolor${eyes[$[RANDOM%en]]}$DEF"
}
info () { error=$? git_tst= git_clr=
    [[ -d .git ]] && {
        git_tst=($(git -c color.ui=never status -sb))
        git_tst="GIT ${git_tst[*]} " #   
        git_clr=($(git -c color.ui=always status -sb))
        git_clr="GIT ${git_clr[*]} " #   
    }
    [[ $debian_chroot ]] && chrt="($debian_chroot)" || chrt=
    name_length="{ $HOSTNAME$chrt }"
    name_length=${#name_length}
    face_tst='O_o  o_O'
    top_line_left=$[(COLUMNS-name_length)/2]
    top_line_right=$[COLUMNS-(top_line_left+name_length)]
    printf -v top_line "%${top_line_left}s{_S_$DEF$BLD$HOSTNAME$chrt${DEF}_S_$GRN}%${top_line_right}s"
    printf -v bot_line "%${COLUMNS}s"
    printf -v date  "%(%a %d %b %T)T"
    top_line=${top_line// /-}
    top_line=$GRN${top_line//_S_/ }$DEF
    bot_line=$GRN${bot_line// /-}$DEF
    center_space=$[COLUMNS-${#date}-${#PWD}-${#git_tst}-${#face_tst}]
    ((center_space<0)) && center_space=1
    printf "\n$top_line\n$(face) $BLD$BLU$PWD$DEF%${center_space}s$git_clr$DIM$date $(face)\n$bot_line\n\$ "
}
PS1='$(info)'; case "$TERM" in xterm*|rxvt*) PS1="\[\e]0;$(face 1) \w\a\]$PS1";; esac


Isso é tudo, obrigado por sua atenção!) Assine, tipo, isso é tudo, o projeto está no github da barra de informações Crie, invente, experimente!)



verificação de cuidado
"#" "$"?)



(*) (*)



All Articles