Mercurial > hg > toybox
comparison toys/posix/ls.c @ 940:a425f97975d3
First pass at ls --color
author | Rob Landley <rob@landley.net> |
---|---|
date | Sun, 30 Jun 2013 23:52:45 -0500 |
parents | b58e86e366ab |
children | 62ba5ce62e9d |
comparison
equal
deleted
inserted
replaced
939:b58e86e366ab | 940:a425f97975d3 |
---|---|
3 * Copyright 2012 Andre Renaud <andre@bluewatersys.com> | 3 * Copyright 2012 Andre Renaud <andre@bluewatersys.com> |
4 * Copyright 2012 Rob Landley <rob@landley.net> | 4 * Copyright 2012 Rob Landley <rob@landley.net> |
5 * | 5 * |
6 * See http://opengroup.org/onlinepubs/9699919799/utilities/ls.html | 6 * See http://opengroup.org/onlinepubs/9699919799/utilities/ls.html |
7 | 7 |
8 USE_LS(NEWTOY(ls, "goACFHLRSacdfiklmnpqrstux1[-1Cglmnox][-cu][-ftS][-HL]", TOYFLAG_BIN)) | 8 USE_LS(NEWTOY(ls, USE_LS_COLOR("(color)")"goACFHLRSacdfiklmnpqrstux1[-1Cglmnox][-cu][-ftS][-HL]", TOYFLAG_BIN)) |
9 | 9 |
10 config LS | 10 config LS |
11 bool "ls" | 11 bool "ls" |
12 default y | 12 default y |
13 help | 13 help |
29 -m comma separated -n like -l but numeric uid/gid | 29 -m comma separated -n like -l but numeric uid/gid |
30 -o like -l but no group -x columns (horizontal sort) | 30 -o like -l but no group -x columns (horizontal sort) |
31 | 31 |
32 sorting (default is alphabetical): | 32 sorting (default is alphabetical): |
33 -f unsorted -r reverse -t timestamp -S size | 33 -f unsorted -r reverse -t timestamp -S size |
34 | |
35 config LS_COLOR | |
36 bool "ls --color" | |
37 default y | |
38 help | |
39 usage: ls --color | |
40 | |
41 --color device=yellow symlink=turquoise/red dir=blue socket=purple | |
42 files: exe=green suid=red suidfile=redback stickydir=greenback | |
34 */ | 43 */ |
35 | 44 |
36 #define FOR_ls | 45 #define FOR_ls |
37 #include "toys.h" | 46 #include "toys.h" |
38 | 47 |
189 | 198 |
190 ul -= transition; | 199 ul -= transition; |
191 *xpos = ul % (columns-1); | 200 *xpos = ul % (columns-1); |
192 | 201 |
193 return (*xpos*height) + widecols + (ul/(columns-1)); | 202 return (*xpos*height) + widecols + (ul/(columns-1)); |
203 } | |
204 | |
205 int color_from_mode(mode_t mode) | |
206 { | |
207 int color = 0; | |
208 | |
209 if (S_ISDIR(mode)) color = 256+34; | |
210 else if (S_ISLNK(mode)) color = 256+36; | |
211 else if (S_ISBLK(mode) || S_ISCHR(mode)) color = 256+33; | |
212 else if (S_ISREG(mode) && (mode&0111)) color = 256+32; | |
213 else if (S_ISFIFO(mode)) color = 33; | |
214 else if (S_ISSOCK(mode)) color = 256+35; | |
215 | |
216 return color; | |
194 } | 217 } |
195 | 218 |
196 // Display a list of dirtree entries, according to current format | 219 // Display a list of dirtree entries, according to current format |
197 // Output types -1, -l, -C, or stream | 220 // Output types -1, -l, -C, or stream |
198 | 221 |
288 | 311 |
289 // Loop through again to produce output. | 312 // Loop through again to produce output. |
290 memset(toybuf, ' ', 256); | 313 memset(toybuf, ' ', 256); |
291 width = 0; | 314 width = 0; |
292 for (ul = 0; ul<dtlen; ul++) { | 315 for (ul = 0; ul<dtlen; ul++) { |
293 unsigned curcol; | 316 unsigned curcol, color = 0; |
294 unsigned long next = next_column(ul, dtlen, columns, &curcol); | 317 unsigned long next = next_column(ul, dtlen, columns, &curcol); |
295 struct stat *st = &(sort[next]->st); | 318 struct stat *st = &(sort[next]->st); |
296 mode_t mode = st->st_mode; | 319 mode_t mode = st->st_mode; |
297 char et = endtype(st); | 320 char et = endtype(st); |
298 | 321 |
347 xprintf("%s% *ld %s%s%s%s% *"PRId64" %s ", perm, totals[2]+1, | 370 xprintf("%s% *ld %s%s%s%s% *"PRId64" %s ", perm, totals[2]+1, |
348 (long)st->st_nlink, usr, upad, grp, grpad, totals[5]+1, | 371 (long)st->st_nlink, usr, upad, grp, grpad, totals[5]+1, |
349 (int64_t)st->st_size, thyme); | 372 (int64_t)st->st_size, thyme); |
350 } | 373 } |
351 | 374 |
375 if ((flags & FLAG_color) && TT.screen_width) { | |
376 color = color_from_mode(st->st_mode); | |
377 if (color) printf("\033[%d;%dm", color>>8, color&255); | |
378 } | |
379 | |
352 if (flags & FLAG_q) { | 380 if (flags & FLAG_q) { |
353 char *p; | 381 char *p; |
354 for (p=sort[next]->name; *p; p++) xputc(isprint(*p) ? *p : '?'); | 382 for (p=sort[next]->name; *p; p++) xputc(isprint(*p) ? *p : '?'); |
355 } else xprintf("%s", sort[next]->name); | 383 } else xprintf("%s", sort[next]->name); |
356 if ((flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) && S_ISLNK(mode)) | 384 if (color) xprintf("\033[0m"); |
357 xprintf(" -> %s", sort[next]->symlink); | 385 |
386 if ((flags & (FLAG_l|FLAG_o|FLAG_n|FLAG_g)) && S_ISLNK(mode)) { | |
387 printf(" -> "); | |
388 if ((flags & FLAG_color) && TT.screen_width) { | |
389 struct stat st2; | |
390 | |
391 if (fstatat(dirfd, sort[next]->symlink, &st2, 0)) color = 256+31; | |
392 else color = color_from_mode(st2.st_mode); | |
393 | |
394 if (color) printf("\033[%d;%dm", color>>8, color&255); | |
395 } | |
396 | |
397 printf("%s", sort[next]->symlink); | |
398 if (color) printf("\033[0m"); | |
399 } | |
358 | 400 |
359 if (et) xputc(et); | 401 if (et) xputc(et); |
360 | 402 |
361 // Pad columns | 403 // Pad columns |
362 if (flags & (FLAG_C|FLAG_x)) { | 404 if (flags & (FLAG_C|FLAG_x)) { |
376 // Recurse into dirs if at top of the tree or given -R | 418 // Recurse into dirs if at top of the tree or given -R |
377 if (!indir->parent || (flags & FLAG_R)) | 419 if (!indir->parent || (flags & FLAG_R)) |
378 listfiles(openat(dirfd, sort[ul]->name, 0), sort[ul]); | 420 listfiles(openat(dirfd, sort[ul]->name, 0), sort[ul]); |
379 } | 421 } |
380 free(sort); | 422 free(sort); |
381 if (dirfd != AT_FDCWD) close(indir->data); | 423 if (dirfd != AT_FDCWD) close(dirfd); |
382 } | 424 } |
383 | 425 |
384 void ls_main(void) | 426 void ls_main(void) |
385 { | 427 { |
386 char **s, *noargs[] = {".", 0}; | 428 char **s, *noargs[] = {".", 0}; |
387 struct dirtree *dt; | 429 struct dirtree *dt; |
430 | |
431 TT.screen_width = 80; | |
432 terminal_size(&TT.screen_width, NULL); | |
433 if (TT.screen_width<2) TT.screen_width = 2; | |
388 | 434 |
389 // Do we have an implied -1 | 435 // Do we have an implied -1 |
390 if (!isatty(1) || (toys.optflags&(FLAG_l|FLAG_o|FLAG_n|FLAG_g))) | 436 if (!isatty(1) || (toys.optflags&(FLAG_l|FLAG_o|FLAG_n|FLAG_g))) |
391 toys.optflags |= FLAG_1; | 437 toys.optflags |= FLAG_1; |
392 else { | 438 else if (!(toys.optflags&(FLAG_1|FLAG_x|FLAG_m))) toys.optflags |= FLAG_C; |
393 TT.screen_width = 80; | |
394 terminal_size(&TT.screen_width, NULL); | |
395 if (TT.screen_width<2) TT.screen_width = 2; | |
396 if (!(toys.optflags&(FLAG_1|FLAG_x|FLAG_m))) toys.optflags |= FLAG_C; | |
397 } | |
398 // The optflags parsing infrastructure should really do this for us, | 439 // The optflags parsing infrastructure should really do this for us, |
399 // but currently it has "switch off when this is set", so "-dR" and "-Rd" | 440 // but currently it has "switch off when this is set", so "-dR" and "-Rd" |
400 // behave differently | 441 // behave differently |
401 if (toys.optflags & FLAG_d) toys.optflags &= ~FLAG_R; | 442 if (toys.optflags & FLAG_d) toys.optflags &= ~FLAG_R; |
402 | 443 |