File Coverage

blib/lib/File/LsColor.pm
Criterion Covered Total %
statement 70 97 72.1
branch 20 60 33.3
condition 1 6 16.6
subroutine 14 17 82.3
pod 8 8 100.0
total 113 188 60.1


line stmt bran cond sub pod time code
1             package File::LsColor;
2 3     3   602201 use strict;
  3         7  
  3         135  
3             #use warnings;
4              
5             BEGIN {
6 3     3   19 use Exporter;
  3         6  
  3         184  
7 3     3   20 use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS);
  3         5  
  3         429  
8              
9 3     3   11 $VERSION = '0.544';
10 3         43 @ISA = qw(Exporter);
11              
12 3         10 @EXPORT_OK = qw(
13             ls_color
14             ls_color_custom
15             ls_color_default
16             ls_color_internal
17             get_ls_colors
18             can_ls_color
19             ls_color_lookup
20             parse_ls_colors
21             slack_code_to_ls_code
22             );
23              
24 3         194 %EXPORT_TAGS = (
25             all => [
26             qw(
27             ls_color ls_color_custom ls_color_default ls_color_internal
28             get_ls_colors can_ls_color ls_color_lookup parse_ls_colors
29             slack_code_to_ls_code
30             )
31             ],
32             );
33             }
34              
35             ################################################################################
36             # If set, skip stat:ing files for attributes like +x.
37             # This can be desired if the filename aren't real files, or for performance
38             # reasons.
39             #
40             # Interesting read: https://github.com/trapd00r/File-LsColor/issues/7
41             ################################################################################
42             our $NO_STAT = 0;
43              
44             ################################################################################
45             # If set, ignore case on file extensions.
46             ################################################################################
47             our $IGNORE_CASE = 0;
48              
49             ################################################################################
50             # If set, given a path like ~/foo/bar.flac, everything prior to the basename
51             # will be colored according to the LS_COLORS directory specification (the 'di'
52             # key), while the actual base filename will be colored according to the file
53             # extension specification.
54             #
55             # New default since v0.540, 2021-10-09!
56             ################################################################################
57             our $COLORIZE_PATH = 1;
58              
59             ################################################################################
60             # This is an alias for compatibility reasons with File::LsColor prior to v0.300.
61             ################################################################################
62             {
63 3     3   14 no warnings 'once';
  3         15  
  3         203  
64             *ls_color_lookup = *can_ls_color;
65             }
66              
67 3     3   1654 use Term::ExtendedColor qw(fg);
  3         10548  
  3         6649  
68              
69              
70             #
71             # yes, this is pretty :)
72             # colors from https://github.com/trapd00r/LS_COLORS
73             my $internal_ls_color='
74             bd=38;5;68:ca=38;5;17:cd=38;5;113;1:di=38;5;30:do=38;5;127:ex=38;5;166;1:
75             pi=38;5;126:fi=38;5;253:ln=target:mh=38;5;222;1:or=48;5;196;38;5;232;1:
76             ow=38;5;220;1:sg=48;5;3;38;5;0:su=38;5;220;1;3;100;1:so=38;5;197:
77             st=38;5;232;48;5;30:tw=48;5;235;38;5;139;3:*LS_COLORS=48;5;89;38;5;197;1;3;4;7:
78             *.msi=38;5;039:*.xys=38;5;204:*README=38;5;220;1:*LICENSE=38;5;220;1:
79             *COPYING=38;5;220;1:*INSTALL=38;5;220;1:*COPYRIGHT=38;5;220;1:
80             *AUTHORS=38;5;220;1:*HISTORY=38;5;220;1:*CONTRIBUTORS=38;5;220;1:
81             *PATENTS=38;5;220;1:*VERSION=38;5;220;1:*NOTICE=38;5;220;1:*CHANGES=38;5;220;1:
82             *.log=38;5;190:*Makefile=38;5;155:*MANIFEST=38;5;243:*pm_to_blib=38;5;240:
83             *.txt=38;5;253:*.etx=38;5;184:*.info=38;5;184:*.markdown=38;5;184:*.md=38;5;184:
84             *.mkd=38;5;184:*.nfo=38;5;184:*.pod=38;5;184:*.tex=38;5;184:*.textile=38;5;184:
85             *.json=38;5;178:*.msg=38;5;178:*.pgn=38;5;178:*.rss=38;5;178:*.xml=38;5;178:
86             *.yml=38;5;178:*.RData=38;5;178:*.rdata=38;5;178:*.csv=38;5;78:*.cbr=38;5;141:
87             *.cbz=38;5;141:*.chm=38;5;141:*.djvu=38;5;141:*.pdf=38;5;141:*.PDF=38;5;141:
88             *.docm=38;5;111;4:*.doc=38;5;111:*.docx=38;5;111:*.eps=38;5;111:*.ps=38;5;111:
89             *.odb=38;5;111:*.odt=38;5;111:*.odp=38;5;166:*.pps=38;5;166:*.ppt=38;5;166:
90             *.ods=38;5;112:*.xla=38;5;76:*.xls=38;5;112:*.xlsx=38;5;112:*.xlsxm=38;5;112;4:
91             *.xltm=38;5;73;4:*.xltx=38;5;73:*cfg=38;5;204:*conf=38;5;204:*rc=38;5;204:
92             *.ini=38;5;204:*.gws=38;5;204:*.viminfo=38;5;204:*.pcf=38;5;204:*.psf=38;5;204:
93             *.reg=38;5;203:*.git=38;5;197:*.gitignore=38;5;240:*.gitattributes=38;5;240:
94             *.gitmodules=38;5;240:*.awk=38;5;172:*.bash=38;5;172:*.bat=38;5;172:
95             *.BAT=38;5;172:*.sed=38;5;172:*.sh=38;5;138:*.zsh=38;5;137:*.vim=38;5;254;1:
96             *.ahk=38;5;41:*.py=38;5;41:*.pl=38;5;208:*.PL=38;5;160:*.t=38;5;114:
97             *.msql=38;5;222:*.mysql=38;5;222:*.pgsql=38;5;222:*.sql=38;5;222:
98             *.tcl=38;5;64;1:*.r=38;5;49:*.R=38;5;49:*.gs=38;5;81:*.asm=38;5;81:
99             *.cl=38;5;81:*.lisp=38;5;81:*.lua=38;5;81:*.moon=38;5;81:*.c=38;5;81:
100             *.C=38;5;81:*.h=38;5;110:*.H=38;5;110:*.tcc=38;5;110:*.c++=38;5;81:
101             *.h++=38;5;110:*.hpp=38;5;110:*.hxx=38;5;110:*.ii=38;5;110:*.M=38;5;110:
102             *.m=38;5;110:*.cc=38;5;81:*.cs=38;5;81:*.cp=38;5;81:*.cpp=38;5;81:*.cxx=38;5;81:
103             *.cr=38;5;81:*.go=38;5;81:*.f=38;5;81:*.for=38;5;81:*.ftn=38;5;81:*.s=38;5;110:
104             *.S=38;5;110:*.rs=38;5;81:*.sx=38;5;81:*.hi=38;5;110:*.hs=38;5;81:*.lhs=38;5;81:
105             *.pyc=38;5;240:*.css=38;5;125;1:*.less=38;5;125;1:*.sass=38;5;125;1:
106             *.scss=38;5;125;1:*.htm=38;5;125;1:*.html=38;5;125;1:*.jhtm=38;5;125;1:
107             *.mht=38;5;125;1:*.eml=38;5;125;1:*.mustache=38;5;125;1:*.coffee=38;5;074;1:
108             *.java=38;5;074;1:*.js=38;5;074;1:*.jsm=38;5;074;1:*.jsm=38;5;074;1:
109             *.jsp=38;5;074;1:*.php=38;5;81:*.ctp=38;5;81:*.twig=38;5;81:*.vb=38;5;81:
110             *.vba=38;5;81:*.vbs=38;5;81:*.am=38;5;242:*.in=38;5;242:*.hin=38;5;242:
111             *.scan=38;5;242:*.m4=38;5;242:*.old=38;5;242:*.out=38;5;242:*.SKIP=38;5;244:
112             *.diff=48;5;197;38;5;232:*.patch=48;5;197;38;5;232;1:*.bmp=38;5;129:
113             *.tiff=38;5;97:*.TIFF=38;5;97:*.cdr=38;5;97:*.gif=38;5;97:*.ico=38;5;132:
114             *.jpeg=38;5;125:*.JPG=38;5;125:*.jpg=38;5;125:*.nth=38;5;97:*.png=38;5;197:
115             *.svg=38;5;97:*.xpm=38;5;97:*.avi=38;5;114:*.divx=38;5;114:*.IFO=38;5;114:
116             *.m2v=38;5;114:*.m4v=38;5;114:*.mkv=38;5;114:*.MOV=38;5;114:*.mov=38;5;114:
117             *.mp4=38;5;114:*.mpeg=38;5;114:*.mpg=38;5;114:*.ogm=38;5;114:*.rmvb=38;5;114:
118             *.sample=38;5;114:*.wmv=38;5;114:*.3g2=38;5;115:*.3gp=38;5;115:*.gp3=38;5;115:
119             *.webm=38;5;115:*.gp4=38;5;115:*.asf=38;5;115:*.flv=38;5;115:*.ts=38;5;115:
120             *.ogv=38;5;115:*.f4v=38;5;115:*.VOB=38;5;115;1:*.vob=38;5;115;1:
121             *.3ga=38;5;137;1:*.S3M=38;5;137;1:*.aac=38;5;137;1:*.dat=38;5;137;1:
122             *.dts=38;5;137;1:*.fcm=38;5;137;1:*.m4a=38;5;137;1:*.mid=38;5;137;1:
123             *.midi=38;5;137;1:*.mod=38;5;137;1:*.mp3=38;5;137;1:*.oga=38;5;137;1:
124             *.ogg=38;5;137;1:*.s3m=38;5;137;1:*.sid=38;5;137;1:*.ape=38;5;136;1:
125             *.flac=38;5;136;1:*.alac=38;5;136;1:*.wav=38;5;136;1:*.wv=38;5;136;1:
126             *.wvc=38;5;136;1:*.afm=38;5;66:*.pfb=38;5;66:*.pfm=38;5;66:*.ttf=38;5;66:
127             *.otf=38;5;66:*.PFA=38;5;66:*.pfa=38;5;66:*.7z=38;5;40:*.a=38;5;40:
128             *.arj=38;5;40:*.bz2=38;5;40:*.gz=38;5;40:*.rar=38;5;40:*.tar=38;5;40:
129             *.tgz=38;5;40:*.xz=38;5;40:*.zip=38;5;40:*.r00=38;5;239:*.r01=38;5;239:
130             *.r02=38;5;239:*.r03=38;5;239:*.r04=38;5;239:*.r05=38;5;239:*.r06=38;5;239:
131             *.r07=38;5;239:*.r08=38;5;239:*.r09=38;5;239:*.r10=38;5;239:*.r100=38;5;239:
132             *.r101=38;5;239:*.r102=38;5;239:*.r103=38;5;239:*.r104=38;5;239:
133             *.r105=38;5;239:*.r106=38;5;239:*.r107=38;5;239:*.r108=38;5;239:
134             *.r109=38;5;239:*.r11=38;5;239:*.r110=38;5;239:*.r111=38;5;239:*.r112=38;5;239:
135             *.r113=38;5;239:*.r114=38;5;239:*.r115=38;5;239:*.r116=38;5;239:*.r12=38;5;239:
136             *.r13=38;5;239:*.r14=38;5;239:*.r15=38;5;239:*.r16=38;5;239:*.r17=38;5;239:
137             *.r18=38;5;239:*.r19=38;5;239:*.r20=38;5;239:*.r21=38;5;239:*.r22=38;5;239:
138             *.r25=38;5;239:*.r26=38;5;239:*.r27=38;5;239:*.r28=38;5;239:*.r29=38;5;239:
139             *.r30=38;5;239:*.r31=38;5;239:*.r32=38;5;239:*.r33=38;5;239:*.r34=38;5;239:
140             *.r35=38;5;239:*.r36=38;5;239:*.r37=38;5;239:*.r38=38;5;239:*.r39=38;5;239:
141             *.r40=38;5;239:*.r41=38;5;239:*.r42=38;5;239:*.r43=38;5;239:*.r44=38;5;239:
142             *.r45=38;5;239:*.r46=38;5;239:*.r47=38;5;239:*.r48=38;5;239:*.r49=38;5;239:
143             *.r50=38;5;239:*.r51=38;5;239:*.r52=38;5;239:*.r53=38;5;239:*.r54=38;5;239:
144             *.r55=38;5;239:*.r56=38;5;239:*.r57=38;5;239:*.r58=38;5;239:*.r59=38;5;239:
145             *.r60=38;5;239:*.r61=38;5;239:*.r62=38;5;239:*.r63=38;5;239:*.r64=38;5;239:
146             *.r65=38;5;239:*.r66=38;5;239:*.r67=38;5;239:*.r68=38;5;239:*.r69=38;5;239:
147             *.r69=38;5;239:*.r70=38;5;239:*.r71=38;5;239:*.r72=38;5;239:*.r73=38;5;239:
148             *.r74=38;5;239:*.r75=38;5;239:*.r76=38;5;239:*.r77=38;5;239:*.r78=38;5;239:
149             *.r79=38;5;239:*.r80=38;5;239:*.r81=38;5;239:*.r82=38;5;239:*.r83=38;5;239:
150             *.r84=38;5;239:*.r85=38;5;239:*.r86=38;5;239:*.r87=38;5;239:*.r88=38;5;239:
151             *.r89=38;5;239:*.r90=38;5;239:*.r91=38;5;239:*.r92=38;5;239:*.r93=38;5;239:
152             *.r94=38;5;239:*.r95=38;5;239:*.r96=38;5;239:*.r97=38;5;239:*.r98=38;5;239:
153             *.r99=38;5;239:*.apk=38;5;215:*.deb=38;5;215:*.jad=38;5;215:*.jar=38;5;215:
154             *.cab=38;5;215:*.pak=38;5;215:*.pk3=38;5;215:*.vdf=38;5;215:*.vpk=38;5;215:
155             *.bsp=38;5;215:*.dmg=38;5;215:*.iso=38;5;124:*.bin=38;5;124:*.nrg=38;5;124:
156             *.qcow=38;5;124:*.sparseimage=38;5;124:*.accdb=38;5;60:*.accde=38;5;60:
157             *.accdr=38;5;60:*.accdt=38;5;60:*.db=38;5;60:*.localstorage=38;5;60:
158             *.sqlite=38;5;60:*.typelib=38;5;60:*.nc=38;5;60:*.part=38;5;239:*~=38;5;241:
159             *.pacnew=38;5;33:*.un~=38;5;241:*.orig=38;5;241:*.BUP=38;5;241:*.bak=38;5;241:
160             *.o=38;5;241:*.rlib=38;5;241:*.swp=38;5;244:*.swo=38;5;244:*.tmp=38;5;244:
161             *.sassc=38;5;244:*.pid=38;5;248:*.state=38;5;248:*lockfile=38;5;248:
162             *.err=38;5;160;1:*.error=38;5;160;1:*.stderr=38;5;160;1:*.dump=38;5;241:
163             *.stackdump=38;5;241:*.zcompdump=38;5;241:*.zwc=38;5;241:*.pcap=38;5;29:
164             *.cap=38;5;29:*.dmp=38;5;29:*.allow=38;5;112:*.deny=38;5;196:
165             *.service=38;5;45:*@.service=38;5;45:*.socket=38;5;45:*.swap=38;5;45:
166             *.device=38;5;45:*.mount=38;5;45:*.automount=38;5;45:*.target=38;5;45:
167             *.path=38;5;45:*.timer=38;5;45:*.snapshot=38;5;45:*.application=38;5;116:
168             *.cue=38;5;116:*.description=38;5;116:*.directory=38;5;116:*.m3u=38;5;116:
169             *.m3u8=38;5;116:*.md5=38;5;116:*.properties=38;5;116:*.sfv=38;5;116:
170             *.srt=38;5;116:*.theme=38;5;116:*.torrent=38;5;116:*.urlview=38;5;116:
171             *.asc=38;5;192;3:*.enc=38;5;192;3:*.gpg=38;5;192;3:*.signature=38;5;192;3:
172             *.sig=38;5;192;3:*.p12=38;5;192;3:*.pem=38;5;192;3:*.pgp=38;5;192;3:
173             *.asc=38;5;192;3:*.enc=38;5;192;3:*.sig=38;5;192;3:*.signature=38;5;192;3:
174             *.32x=38;5;213:*.cdi=38;5;213:*.fm2=38;5;213:*.rom=38;5;213:*.sav=38;5;213:
175             *.st=38;5;213:*.a00=38;5;213:*.a52=38;5;213:*.A64=38;5;213:*.a64=38;5;213:
176             *.a78=38;5;213:*.adf=38;5;213:*.atr=38;5;213:*.gb=38;5;213:*.gba=38;5;213:
177             *.gbc=38;5;213:*.gel=38;5;213:*.gg=38;5;213:*.ggl=38;5;213:*.ipk=38;5;213:
178             *.j64=38;5;213:*.nds=38;5;213:*.nes=38;5;213:*.sms=38;5;213:*.pot=38;5;7:
179             *.pcb=38;5;7:*.mm=38;5;7:*.gbr=38;5;7:*.spl=38;5;7:*.scm=38;5;7:
180             *.Rproj=38;5;11:*.sis=38;5;7:*.1p=38;5;7:*.3p=38;5;7:*.cnc=38;5;7:
181             *.def=38;5;7:*.ex=38;5;7:*.example=38;5;7:*.feature=38;5;7:*.ger=38;5;7:
182             *.map=38;5;7:*.mf=38;5;7:*.mfasl=38;5;7:*.mi=38;5;7:*.mtx=38;5;7:*.pc=38;5;7:
183             *.pi=38;5;7:*.plt=38;5;7:*.pm=38;5;7:*.rb=38;5;7:*.rdf=38;5;7:*.rst=38;5;7:
184             *.ru=38;5;7:*.sch=38;5;7:*.sty=38;5;7:*.sug=38;5;7:*.tdy=38;5;7:*.tfm=38;5;7:
185             *.tfnt=38;5;7:*.tg=38;5;7:*.vcard=38;5;7:*.vcf=38;5;7:*.xln=38;5;7';
186              
187              
188             $internal_ls_color =~ s/\n//g;
189              
190             my $ls_colors_default = '
191             rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:
192             cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:
193             ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:
194             *.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:
195             *.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:
196             *.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:
197             *.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:
198             *.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:
199             *.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:
200             *.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:
201             *.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35
202             :*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:
203             *.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:
204             *.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:
205             *.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:
206             *.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:
207             *.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:
208             *.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:
209             *.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:
210             *.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:
211             *.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36';
212              
213             $ls_colors_default =~ s/\n|\s+//g;
214             #>
215              
216             ################################################################################
217             # If the $LS_COLORS environment variable is unset, use the default GNU
218             # specification from dircolors.
219             ################################################################################
220             my $extracted_ls_colors;
221             my $LS_COLORS = defined($ENV{LS_COLORS}) ? $ENV{LS_COLORS} : $ls_colors_default;
222              
223             ################################################################################
224             # This is for situations like:
225             # *.pl=38;5;196;1 (red with bold attribute)
226             ################################################################################
227             my %attributes = (
228             1 => 'bold',
229             2 => 'faint',
230             3 => 'italic',
231             4 => 'underline',
232             5 => 'blink',
233             6 => 'blink_ms',
234             7 => 'reverse',
235             );
236              
237             ################################################################################
238             # This is the internal LS_COLORS specification, taken from:
239             # https://github.com/trapd00r/LS_COLORS
240             ################################################################################
241             sub ls_color_internal {
242 0     0 1 0 $LS_COLORS = $internal_ls_color;
243 0         0 $extracted_ls_colors = parse_ls_colors($LS_COLORS);
244 0         0 ls_color(@_);
245             }
246              
247             ################################################################################
248             # Ability to use a custom specification, like so:
249             #
250             # ls_color_custom(
251             # {
252             # '.pl' => '38;5;196;1',
253             # 'Changes' => '48;5;197;38;5;220;1;3;4;8',
254             # }
255             # );
256             ################################################################################
257             sub ls_color_custom {
258 0     0 1 0 $LS_COLORS = shift;
259 0         0 $extracted_ls_colors = parse_ls_colors($LS_COLORS);
260 0         0 ls_color(@_);
261             }
262              
263             ################################################################################
264             # These are the default dircolors mappings from GNU dircolors/ls. This is what
265             # ls defaults to when the $LS_COLORS environment variable is unset.
266             ################################################################################
267             sub ls_color_default {
268 3     3 1 158215 $LS_COLORS= '
269             rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:
270             cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:
271             ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arc=01;31:*.arj=01;31:
272             *.taz=01;31:*.lha=01;31:*.lz4=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:
273             *.txz=01;31:*.tzo=01;31:*.t7z=01;31:*.zip=01;31:*.z=01;31:*.dz=01;31:
274             *.gz=01;31:*.lrz=01;31:*.lz=01;31:*.lzo=01;31:*.xz=01;31:*.zst=01;31:
275             *.tzst=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:
276             *.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:
277             *.rar=01;31:*.alz=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:
278             *.rz=01;31:*.cab=01;31:*.wim=01;31:*.swm=01;31:*.dwm=01;31:*.esd=01;31:
279             *.jpg=01;35:*.jpeg=01;35:*.mjpg=01;35:*.mjpeg=01;35:*.gif=01;35:*.bmp=01;35
280             :*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:
281             *.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:
282             *.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:
283             *.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:
284             *.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:
285             *.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=01;35:*.gl=01;35:*.dl=01;35:
286             *.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.ogv=01;35:
287             *.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.m4a=00;36:*.mid=00;36:
288             *.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:
289             *.wav=00;36:*.oga=00;36:*.opus=00;36:*.spx=00;36:*.xspf=00;36';
290              
291 3         561 $LS_COLORS =~ s/\n|\s+//g;
292              
293 3         24 $extracted_ls_colors = parse_ls_colors($LS_COLORS);
294 3         117 ls_color(@_);
295             }
296              
297             ################################################################################
298             # None of the ls_color_* variations are called, so use the LS_COLORS defined in
299             # the environment variable. This is what most users would want to use.
300             ################################################################################
301             $extracted_ls_colors = parse_ls_colors($LS_COLORS);
302              
303              
304             sub ls_color {
305 3     3 1 4 my @files;
306              
307 3 50       11 if(ref($_[0]) eq 'ARRAY') {
308 0         0 push(@files, @{$_[0]});
  0         0  
309 0         0 shift @_;
310             }
311             else {
312 3         6 push(@files, @_);
313             }
314              
315              
316 3         21 for my $file(@files) {
317 3         6 chomp $file;
318              
319 3 50       14 next if $file =~ m/^\s+$/;
320              
321             ################################################################################
322             # It's important to keep the dot if there is one, or else miscolorings can
323             # happen:
324             #
325             # *.bin=38;5;220 could color directories named bin/, for example.
326             ################################################################################
327 3         17 my($ext) = $file =~ m/.*([.]+.+)$/;
328              
329             ################################################################################
330             # Since we need to stat files (unless $NO_STAT is set), we need a real filename
331             # that's not padded with any whitespace.
332             ################################################################################
333 3         4 my $real_file;
334 3 50       10 if($file =~ m/^\s+(.+)/) {
335 0         0 $real_file = $1;
336             }
337             else {
338 3         3 $real_file = $file;
339             }
340              
341              
342              
343             ################################################################################
344             # ./recup_dir.5/
345             # Invalid \0 character in pathname for ftdir: \0ls++.conf at LsColor.pm
346             ################################################################################
347 3 50       7 if($real_file !~ m/\0/) {
348 3 50       328 -d $real_file and $ext = 'di';
349             }
350              
351             ################################################################################
352             # No regular extension found.
353             # Let's check file attributes. This will only work if called with absolute paths
354             # or from ./, since we can't stat() files we cannot access.
355             #
356             # https://github.com/trapd00r/File-LsColor/issues/1
357             ################################################################################
358 3 50 33     11 if(not defined($ext) and $NO_STAT == 0) {
359 0 0       0 -l $real_file and $ext = 'ln'; # symlink
360 0 0       0 -x $real_file and $ext = 'ex'; # executable
361 0 0       0 -d $real_file and $ext = 'di'; # beware, dirs have +x
362 0 0       0 -S $real_file and $ext = 'so'; # socket
363 0 0       0 -p $real_file and $ext = 'pi'; # fifo, pipe
364 0 0       0 -b $real_file and $ext = 'bd'; # block device
365 0 0       0 -c $real_file and $ext = 'cd'; # character special file
366              
367             ################################################################################
368             # A special case for directories that we can't stat(), but we can still safely
369             # assume that they are in fact directories.
370             ################################################################################
371 0 0       0 $real_file =~ m{/$} and $ext = 'di';
372             }
373              
374             ################################################################################
375             # No regular extension found and no file attribute added.
376             # The dircolors specification allows for matching with wildcards and full names,
377             # though, so these are all perfectly valid keys:
378             #
379             # Makefile
380             # README
381             # *Makefile.PL
382             ################################################################################
383 3 50       10 if(not defined($ext)) {
384 0         0 $ext = basename($real_file);
385             }
386              
387 3 50 0     11 if(exists($extracted_ls_colors->{$real_file})) {
    50          
    0          
388 0         0 $file = fg($extracted_ls_colors->{$real_file}, basename($real_file));
389             }
390             elsif(exists($extracted_ls_colors->{$ext})) {
391 3 100       6 if($COLORIZE_PATH) {
392 2         7 $file = sprintf("%s%s", _colorize_path($real_file), fg($extracted_ls_colors->{$ext}, basename($real_file)));
393             }
394             else {
395 1         7 $file = fg($extracted_ls_colors->{$ext}, $real_file);
396             }
397             }
398              
399             ################################################################################
400             # We still haven't found a valid mapping yet, but if $IGNORE_CASE is set, check
401             # if the lowercase version of the extension does in fact exist.
402             #
403             # Just make sure to use the non-lc:ed version while returning.
404             #
405             # https://github.com/trapd00r/File-LsColor/issues/9
406             ################################################################################
407             elsif($IGNORE_CASE && $extracted_ls_colors->{lc($ext)}) {
408 0         0 $file = fg($extracted_ls_colors->{lc($ext)}, $file);
409             }
410              
411             else {
412 0 0       0 if($COLORIZE_PATH) {
413             $file = sprintf "%s%s", _colorize_path($file),
414             exists($extracted_ls_colors->{basename($file)})
415 0 0       0 ? fg($extracted_ls_colors->{basename($file)},basename($file))
416             : basename($file);
417             }
418             # A file with no extension or other means of colorization?
419             else {
420             $file = exists($extracted_ls_colors->{basename($file)})
421 0 0       0 ? fg($extracted_ls_colors->{basename($file)}, $file)
422             : $file;
423             }
424             }
425             }
426 3 50       175 return wantarray() ? @files : join('', @files);
427             }
428              
429              
430             sub get_ls_colors {
431 5     5 1 11 return parse_ls_colors()
432             }
433              
434              
435             sub parse_ls_colors {
436 4 50   4 1 15 if(@_) {
437 4         1884 $LS_COLORS = shift @_;
438             }
439              
440             ################################################################################
441             # The way the dircolors specification is specified is actualy a bug.
442             # ':' shouldn't be used as a delimiter, since the way colors are specified using
443             # escape sequences are supposed to look like this:
444             #
445             # 38:5:196
446             #
447             # and not
448             #
449             # 38;5;196
450             #
451             # Someone, somewhere, a long time ago, read that specification wrong and here we
452             # are today.
453             ################################################################################
454 4         77 my @entities = split(/:/, $LS_COLORS);
455              
456 4         9 my %ft;
457 4         39 for my $ent(@entities) {
458              
459             ################################################################################
460             # Account for:
461             # · *.flac - but keep the dot in the extension
462             # · *MANIFEST
463             ################################################################################
464 389         1105 my ($filetype, $attributes) = $ent =~ m/[*]*(.?\S+)=([\d;]+|target)/;
465 389         2855 $ft{$filetype} = $attributes;
466             }
467              
468             # if symlink value is target, we use the target key's value
469             # if($ft{ln} eq 'target') {
470             # $ft{ln} = $ft{target};
471             # }
472 4         31 return \%ft;
473             }
474              
475             sub can_ls_color {
476 5     5 1 12 my $ft = shift;
477 5         11 my $table = get_ls_colors();
478              
479 5         49 $ft =~ s/^\s+//;
480              
481             ################################################################################
482             # If $File::LsColor::IGNORE_CASE is set, we need to color according to the
483             # lowercase definitions.
484             ################################################################################
485 5 100       15 $ft = lc($ft) if $File::LsColor::IGNORE_CASE;
486              
487             ################################################################################
488             # If called with an extension that exists, return it. A special case here so we
489             # can query for an extension with or without the period.
490             ################################################################################
491 5 100       31 return $table->{$ft} if $table->{$ft};
492 1 50       11 return $table->{".$ft"} if $table->{".$ft"};
493              
494             ################################################################################
495             # Else, check if called with a filename.ext
496             # Return undef if all else fails.
497             ################################################################################
498             {
499 3     3   34 no warnings;
  3         6  
  3         1079  
  1         2  
500 1         6 my($ext) = $ft =~ m/^.*([.].+)$/;
501 1 50       8 return $table->{$ext} ? $table->{$ext} : undef;
502             }
503             }
504              
505             sub slack_code_to_ls_code {
506 0     0 1 0 my %slack = (
507             NORMAL => 'no',
508             NORM => 'no',
509             FILE => 'fi',
510             RESET => 'rs',
511             DIR => 'di',
512             LNK => 'ln',
513             LINK => 'ln',
514             SYMLINK => 'ln',
515             ORPHAN => 'or',
516             MISSING => 'mi',
517             FIFO => 'pi',
518             PIPE => 'pi',
519             SOCK => 'so',
520             BLK => 'bd',
521             BLOCK => 'bd',
522             CHR => 'cd',
523             CHAR => 'cd',
524             DOOR => 'do',
525             EXEC => 'ex',
526             LEFT => 'lc',
527             LEFTCODE => 'lc',
528             RIGHT => 'rc',
529             RIGHTCODE => 'rc',
530             END => 'ec',
531             ENDCODE => 'ec',
532             SUID => 'su',
533             SETUID => 'su',
534             SGID => 'sg',
535             SETGID => 'sg',
536             STICKY => 'st',
537             OTHER_WRITABLE => 'ow',
538             OWR => 'ow',
539             STICKY_OTHER_WRITABLE => 'tw',
540             OWT => 'tw',
541             CAPABILITY => 'ca',
542             MULTIHARDLINK => 'mh',
543             CLRTOEOL => 'cl',
544             NULL => 'NULL',
545             );
546              
547 0         0 my $query = shift;
548             return $slack{uc($query)}
549 0 0       0 ? $slack{uc($query)}
550             : undef;
551             }
552              
553             sub _colorize_path {
554 2     2   3 my $what = shift;
555 3     3   23 use File::Basename;
  3         20  
  3         573  
556 2         178 my $dirname = dirname($what);
557              
558             $dirname = ($dirname eq '.')
559             ? ''
560 2 50       18 : fg($extracted_ls_colors->{di}, $dirname . '/');
561              
562 2         139 return $dirname;
563             }
564              
565              
566              
567             1;
568              
569              
570             __END__