Home | History | Annotate | Download | only in pending
      1 /* fmt.c - Text formatter
      2  *
      3  * Copyright 2017 The Android Open Source Project
      4  *
      5  * Deviations from original:
      6  *   we treat all whitespace as equal (no tab expansion, no runs of spaces)
      7  *   we don't try to recognize ends of sentences to double-space after ./?/!
      8 
      9 USE_FMT(NEWTOY(fmt, "w#", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
     10 
     11 config FMT
     12   bool "fmt"
     13   default y
     14   help
     15     usage: fmt [-w WIDTH] [FILE...]
     16 
     17     Reformat input to not exceed a maximum line length.
     18 
     19     -w WIDTH	maximum characters per line (default 75)
     20 */
     21 
     22 #define FOR_fmt
     23 #include "toys.h"
     24 
     25 GLOBALS(
     26   int width;
     27 )
     28 
     29 static void do_fmt(int fd, char *name)
     30 {
     31   FILE *fp = xfdopen(fd, "re");
     32   char *line = NULL;
     33   size_t allocated_length = 0;
     34   int cols = 0, is_first = 1, indent_end = 0, line_length;
     35 
     36   while ((line_length = getline(&line, &allocated_length, fp)) > 0) {
     37     int b = 0, e, w;
     38 
     39     while (b < line_length && isspace(line[b])) b++;
     40     if (b == line_length) {
     41       if (cols > 0) xputc('\n');
     42       xputc('\n');
     43       is_first = 1;
     44       cols = 0;
     45       continue;
     46     }
     47     if (is_first) indent_end = b;
     48 
     49     for (; b < line_length; b = e + 1) {
     50       while (isspace(line[b])) b++;
     51       for (e = b + 1; e < line_length && !isspace(line[e]);) e++;
     52       if (e >= line_length) break;
     53 
     54       line[e] = 0;
     55       w = utf8len(line + b);
     56 
     57       if (!is_first && (cols + (is_first?indent_end:1) + w) >= TT.width) {
     58         xputc('\n');
     59         is_first = 1;
     60         cols = 0;
     61       }
     62       xprintf("%.*s%.*s",is_first?indent_end:1,is_first?line:" ",(e-b),line+b);
     63       cols += (is_first?indent_end:1) + w;
     64       b = e + 1;
     65       is_first = 0;
     66     }
     67   }
     68   if (cols > 0) xputc('\n');
     69   fclose(fp);
     70 }
     71 
     72 void fmt_main(void)
     73 {
     74   if (TT.width < 0) error_exit("negative width: %d", TT.width);
     75   if (!TT.width) TT.width = 75;
     76 
     77   loopfiles(toys.optargs, do_fmt);
     78 }
     79