Testando LS_COLORS no zsh

10

Há alguns anos, encontrei um trecho de código interessante que imprime cada tipo de arquivo em sua cor correspondente, de acordo com as cores definidas em LS_COLORS. Infelizmente, não me lembro mais do link.

Aqui está o trecho test_colors.shem questão

eval $(echo "no:global default;fi:normal file;di:directory;ln:symbolic link;pi:named pipe;so:socket;do:door;bd:block device;cd:character device;or:orphan symlink;mi:missing file;su:set uid;sg:set gid;tw:sticky other writable;ow:other w\
ritable;st:sticky;ex:executable;"|sed -e 's/:/="/g; s/\;/"\n/g')                                                                                                                                                                            
{                                                                                                                                                                                                                                           
  IFS=:                                                                                                                                                                                                                                     
  for i in $LS_COLORS                                                                                                                                                                                                                       
  do                                                                                                                                                                                                                                        
    echo -e "\e[${i#*=}m$( x=${i%=*}; [ "${!x}" ] && echo "${!x}" || echo "$x" )\e[m"                                                                                                                                                       
  done                                                                                                                                                                                                                                      
}   

O trecho funciona muito bem bash, mas não está zsh, e não sei dizer por quê. Quando o executo, zshrecebo o seguinte erro:

> sh .test_colors.sh
.eval_colors:1: * not found
[00:fi=00:di=01;34:ln=01;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.gz=01;31:*.bz2=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.avi=01;35:*.fli=01;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.flac=01;35:*.mp3=01;35:*.mpc=01;35:*.ogg=01;35:*.wav=01;35:m

Atualização (1 de novembro de 2011)

Testei o script de @ Stéphane Gimenez abaixo. Notei que alguns personagens parecem não escapar corretamente. Alguma idéia do porquê?

Resposta: Veja os comentários na resposta de @ Stéphane Gimenez.

                                                      insira a descrição da imagem aqui

Amelio Vazquez-Reina
fonte

Respostas:

7

O mesmo escrito para o zsh de uma maneira muito mais limpa:

#!/bin/zsh

typeset -A names
names[no]="global default"
names[fi]="normal file"
names[di]="directory"
names[ln]="symbolic link"
names[pi]="named pipe"
names[so]="socket"
names[do]="door"
names[bd]="block device"
names[cd]="character device"
names[or]="orphan symlink"
names[mi]="missing file"
names[su]="set uid"
names[sg]="set gid"
names[tw]="sticky other writable"
names[ow]="other writable"
names[st]="sticky"
names[ex]="executable"

for i in ${(s.:.)LS_COLORS}
do
    key=${i%\=*}
    color=${i#*\=}
    name=${names[(e)$key]-$key}
    printf '\e[%sm%s\e[m\n' $color $name
done
Stéphane Gimenez
fonte
Talvez você queira substituir \npor um espaço no final da printfcompactação, talvez.
Stéphane Gimenez
Obrigado @ Stéphane Gimenez. Atualizei meu OP com um problema que estou enfrentando ao imprimir alguns caracteres usando seu script. Não sei se isso está estritamente relacionado ao seu script embora (pode ser meu próprio terminal?)
Amelio Vazquez-Reina
1
@intrpc: executando zshcomo shvocê está usando algum modo de compatibilidade. Chame seu script como zsh ./test_color_schemeou adicione aspas duplas em torno de $colore $name.
Stéphane Gimenez
@ Stéphane Gimenez: Fui direcionado aqui da minha pergunta relacionada aqui: unix.stackexchange.com/questions/52659/… . Sua expansão de abreviações é muito útil. Eu tenho três abreviaturas, rs, cae mhque não estão incluídos acima. Você pode me dizer onde encontrar suas expansões? Obrigado.
Chandra
Interpretado de dircolors -p rs = reinicialização, ca = capacidade, MH = multi-hard_link
weldabar
3

Você precisa escapar do =in ${i%=*}porque, caso contrário, o padrão de sufixo =*sofre =expansão , portanto, =é interpretado como um nome de comando. Essa é a causa do * not founderro.

O Zsh não divide palavras em substituições de variáveis ​​por padrão, então se $LS_COLORSexpande para uma única palavra. Para que o forloop opere nas partes separadas por dois pontos $LS_COLORS, use for i in $=LS_COLORS. Ou mais idiomaticamente em zsh, não use IFSmas especificar explicitamente como dividir: for i in ${(s.:.)LS_COLORS}.

A sintaxe ${!x}para significar "o valor da variável cujo nome é $x" é específica para o bash. Zsh tem uma construção equivalente, a P bandeira de expansão parâmetro : ${(P)x}.

Gilles 'SO- parar de ser mau'
fonte
1
Há mais duas razões para esse script não estar funcionando no zsh. Nenhuma divisão automática de palavras LS_COLORSe =precisa ser escapada nos padrões de substituição.
Stéphane Gimenez
@ StéphaneGimenez Você está certo, obrigado, eu só cheguei onde bash não é padrão, mas esses são dois recursos zsh não padrão que precisam ser abordados também. Você deve expandir sua resposta para ter todas as explicações, e então eu posso excluir as minhas.
Gilles 'SO- stop be evil'