diff options
Diffstat (limited to 'toys')
-rw-r--r-- | toys/pending/fmt.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/toys/pending/fmt.c b/toys/pending/fmt.c new file mode 100644 index 00000000..618642a2 --- /dev/null +++ b/toys/pending/fmt.c @@ -0,0 +1,78 @@ +/* fmt.c - Text formatter + * + * Copyright 2017 The Android Open Source Project + * + * Deviations from original: + * we treat all whitespace as equal (no tab expansion, no runs of spaces) + * we don't try to recognize ends of sentences to double-space after ./?/! + +USE_FMT(NEWTOY(fmt, "w#", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE)) + +config FMT + bool "fmt" + default y + help + usage: fmt [-w WIDTH] [FILE...] + + Reformat input to not exceed a maximum line length. + + -w WIDTH maximum characters per line (default 75) +*/ + +#define FOR_fmt +#include "toys.h" + +GLOBALS( + int width; +) + +static void do_fmt(int fd, char *name) +{ + FILE *fp = xfdopen(fd, "re"); + char *line = NULL; + size_t allocated_length = 0; + int cols = 0, is_first = 1, indent_end = 0, line_length; + + while ((line_length = getline(&line, &allocated_length, fp)) > 0) { + int b = 0, e, w; + + while (b < line_length && isspace(line[b])) b++; + if (b == line_length) { + if (cols > 0) xputc('\n'); + xputc('\n'); + is_first = 1; + cols = 0; + continue; + } + if (is_first) indent_end = b; + + for (; b < line_length; b = e + 1) { + while (isspace(line[b])) b++; + for (e = b + 1; e < line_length && !isspace(line[e]);) e++; + if (e >= line_length) break; + + line[e] = 0; + w = utf8len(line + b); + + if (!is_first && (cols + (is_first?indent_end:1) + w) >= TT.width) { + xputc('\n'); + is_first = 1; + cols = 0; + } + xprintf("%.*s%.*s",is_first?indent_end:1,is_first?line:" ",(e-b),line+b); + cols += (is_first?indent_end:1) + w; + b = e + 1; + is_first = 0; + } + } + if (cols > 0) xputc('\n'); + fclose(fp); +} + +void fmt_main(void) +{ + if (TT.width < 0) error_exit("negative width: %d", TT.width); + if (!TT.width) TT.width = 75; + + loopfiles(toys.optargs, do_fmt); +} |