toybox/toys/pending/fmt.c
<<
>>
Prefs
   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
   9USE_FMT(NEWTOY(fmt, "w#", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LOCALE))
  10
  11config 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
  25GLOBALS(
  26  int width;
  27)
  28
  29static 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
  72void 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