| /* 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); |
| } |