builtin / stripspace.con commit Sync with 'maint' (b7cd0c9)
   1#include "builtin.h"
   2#include "cache.h"
   3
   4/*
   5 * Returns the length of a line, without trailing spaces.
   6 *
   7 * If the line ends with newline, it will be removed too.
   8 */
   9static size_t cleanup(char *line, size_t len)
  10{
  11        while (len) {
  12                unsigned char c = line[len - 1];
  13                if (!isspace(c))
  14                        break;
  15                len--;
  16        }
  17
  18        return len;
  19}
  20
  21/*
  22 * Remove empty lines from the beginning and end
  23 * and also trailing spaces from every line.
  24 *
  25 * Turn multiple consecutive empty lines between paragraphs
  26 * into just one empty line.
  27 *
  28 * If the input has only empty lines and spaces,
  29 * no output will be produced.
  30 *
  31 * If last line does not have a newline at the end, one is added.
  32 *
  33 * Enable skip_comments to skip every line starting with "#".
  34 */
  35void stripspace(struct strbuf *sb, int skip_comments)
  36{
  37        int empties = 0;
  38        size_t i, j, len, newlen;
  39        char *eol;
  40
  41        /* We may have to add a newline. */
  42        strbuf_grow(sb, 1);
  43
  44        for (i = j = 0; i < sb->len; i += len, j += newlen) {
  45                eol = memchr(sb->buf + i, '\n', sb->len - i);
  46                len = eol ? eol - (sb->buf + i) + 1 : sb->len - i;
  47
  48                if (skip_comments && len && sb->buf[i] == '#') {
  49                        newlen = 0;
  50                        continue;
  51                }
  52                newlen = cleanup(sb->buf + i, len);
  53
  54                /* Not just an empty line? */
  55                if (newlen) {
  56                        if (empties > 0 && j > 0)
  57                                sb->buf[j++] = '\n';
  58                        empties = 0;
  59                        memmove(sb->buf + j, sb->buf + i, newlen);
  60                        sb->buf[newlen + j++] = '\n';
  61                } else {
  62                        empties++;
  63                }
  64        }
  65
  66        strbuf_setlen(sb, j);
  67}
  68
  69int cmd_stripspace(int argc, const char **argv, const char *prefix)
  70{
  71        struct strbuf buf = STRBUF_INIT;
  72        int strip_comments = 0;
  73
  74        if (argc == 2 && (!strcmp(argv[1], "-s") ||
  75                                !strcmp(argv[1], "--strip-comments")))
  76                strip_comments = 1;
  77        else if (argc > 1)
  78                usage("git stripspace [-s | --strip-comments] < input");
  79
  80        if (strbuf_read(&buf, 0, 1024) < 0)
  81                die_errno("could not read the input");
  82
  83        stripspace(&buf, strip_comments);
  84
  85        write_or_die(1, buf.buf, buf.len);
  86        strbuf_release(&buf);
  87        return 0;
  88}