| fold.c - sbase - suckless unix tools | |
| git clone git://git.suckless.org/sbase | |
| Log | |
| Files | |
| Refs | |
| README | |
| LICENSE | |
| --- | |
| fold.c (2616B) | |
| --- | |
| 1 /* See LICENSE file for copyright and license details. */ | |
| 2 #include <ctype.h> | |
| 3 #include <stdint.h> | |
| 4 #include <stdio.h> | |
| 5 #include <stdlib.h> | |
| 6 #include <string.h> | |
| 7 | |
| 8 #include "text.h" | |
| 9 #include "util.h" | |
| 10 #include "utf.h" | |
| 11 | |
| 12 static int bflag = 0; | |
| 13 static int sflag = 0; | |
| 14 static size_t width = 80; | |
| 15 | |
| 16 static void | |
| 17 foldline(struct line *l, const char *fname) { | |
| 18 size_t i, col, last, spacesect, len; | |
| 19 Rune r; | |
| 20 int runelen; | |
| 21 | |
| 22 for (i = 0, last = 0, col = 0, spacesect = 0; i < l->len; i += r… | |
| 23 if (col >= width && ((l->data[i] != '\r' && l->data[i] !… | |
| 24 if (bflag && col > width) | |
| 25 i -= runelen; /* never split a ch… | |
| 26 len = ((sflag && spacesect) ? spacesect : i) - l… | |
| 27 if (fwrite(l->data + last, 1, len, stdout) != le… | |
| 28 eprintf("fwrite <stdout>:"); | |
| 29 if (l->data[i] != '\n') | |
| 30 putchar('\n'); | |
| 31 if (sflag && spacesect) | |
| 32 i = spacesect; | |
| 33 last = i; | |
| 34 col = 0; | |
| 35 spacesect = 0; | |
| 36 } | |
| 37 runelen = charntorune(&r, l->data + i, l->len - i); | |
| 38 if (!runelen || r == Runeerror) | |
| 39 eprintf("charntorune: %s: invalid utf\n", fname); | |
| 40 if (sflag && isblankrune(r)) | |
| 41 spacesect = i + runelen; | |
| 42 if (!bflag && iscntrl(l->data[i])) { | |
| 43 switch(l->data[i]) { | |
| 44 case '\b': | |
| 45 col -= (col > 0); | |
| 46 break; | |
| 47 case '\r': | |
| 48 col = 0; | |
| 49 break; | |
| 50 case '\t': | |
| 51 col += (8 - (col % 8)); | |
| 52 if (col >= width) | |
| 53 i--; | |
| 54 break; | |
| 55 } | |
| 56 } else { | |
| 57 col += bflag ? runelen : 1; | |
| 58 } | |
| 59 } | |
| 60 if (l->len - last) | |
| 61 fwrite(l->data + last, 1, l->len - last, stdout); | |
| 62 } | |
| 63 | |
| 64 static void | |
| 65 fold(FILE *fp, const char *fname) | |
| 66 { | |
| 67 static struct line line; | |
| 68 static size_t size = 0; | |
| 69 ssize_t len; | |
| 70 | |
| 71 while ((len = getline(&line.data, &size, fp)) > 0) { | |
| 72 line.len = len; | |
| 73 foldline(&line, fname); | |
| 74 } | |
| 75 if (ferror(fp)) | |
| 76 eprintf("getline %s:", fname); | |
| 77 } | |
| 78 | |
| 79 static void | |
| 80 usage(void) | |
| 81 { | |
| 82 eprintf("usage: %s [-bs] [-w num | -num] [FILE ...]\n", argv0); | |
| 83 } | |
| 84 | |
| 85 int | |
| 86 main(int argc, char *argv[]) | |
| 87 { | |
| 88 FILE *fp; | |
| 89 int ret = 0; | |
| 90 | |
| 91 ARGBEGIN { | |
| 92 case 'b': | |
| 93 bflag = 1; | |
| 94 break; | |
| 95 case 's': | |
| 96 sflag = 1; | |
| 97 break; | |
| 98 case 'w': | |
| 99 width = estrtonum(EARGF(usage()), 1, MIN(LLONG_MAX, SIZE… | |
| 100 break; | |
| 101 ARGNUM: | |
| 102 if (!(width = ARGNUMF())) | |
| 103 eprintf("illegal width value, too small\n"); | |
| 104 break; | |
| 105 default: | |
| 106 usage(); | |
| 107 } ARGEND | |
| 108 | |
| 109 if (!argc) { | |
| 110 fold(stdin, "<stdin>"); | |
| 111 } else { | |
| 112 for (; *argv; argc--, argv++) { | |
| 113 if (!strcmp(*argv, "-")) { | |
| 114 *argv = "<stdin>"; | |
| 115 fp = stdin; | |
| 116 } else if (!(fp = fopen(*argv, "r"))) { | |
| 117 weprintf("fopen %s:", *argv); | |
| 118 ret = 1; | |
| 119 continue; | |
| 120 } | |
| 121 fold(fp, *argv); | |
| 122 if (fp != stdin && fshut(fp, *argv)) | |
| 123 ret = 1; | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 ret |= fshut(stdin, "<stdin>") | fshut(stdout, "<stdout>"); | |
| 128 | |
| 129 return ret; | |
| 130 } |