/* * parse.c - a small program to format the search results * (and in the future also the info results). * * Copyright 2017, 2018 Einhard Leichtfuß * * This file is part of auria. * * auria is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published * by the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * auria is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with auria. If not, see . */ /* Call as `parse [color]'. */ #include #include #include #include #include #define COLOR_NOCOLOR "\e[0m" #define COLOR_BVIOLET "\e[1;35m" #define COLOR_BWHITE "\e[1;38m" #define COLOR_BGREEN "\e[1;32m" #define cond_set_color(c) (color ? printf("%s", (c)) : 0) #define print_line_offset(offset) printf("%*c", (offset), ' ') #define print_word_offset(line_offset) \ (first ? print_line_offset(line_offset) : putchar(' ')) _Bool color; /* colorized output */ int k; /* left line offset */ int j; /* right line offset */ _Bool break_lines; /* set iff stdout is a tty */ unsigned short width; /* terminal width, not relevant if ! break_lines */ unsigned short n; /* actual broken line maximum length; excl. offsets */ _Bool passthrough_word(); int getchar_mergews(_Bool); int passthrough_line(); int breaklines(int, int); int main(int argc, char **argv) { if (argc < 3) return 1; k = atoi(argv[1]); j = atoi(argv[2]); if (k < 0 || j < 0) return 1; color = 0; if (argc >= 4 && strcmp(argv[3], "color") == 0) { color = 1; } if (isatty(STDOUT_FILENO)) { break_lines = 1; struct winsize w; if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == -1) return 1; width = w.ws_col; n = width - k - j; } else { break_lines = 0; } /* * Parse input line for line. */ int c; while (1) { c = getchar(); if (c == EOF || c == '\n') return 1; /* Read and print package name - delimited by space. */ cond_set_color(COLOR_NOCOLOR COLOR_BVIOLET); fputs("aur/", stdout); cond_set_color(COLOR_NOCOLOR COLOR_BWHITE); ungetc(c, stdin); if (! passthrough_word()) return 1; cond_set_color(COLOR_NOCOLOR); putchar(' '); /* Read and print version string - delimited by space. */ cond_set_color(COLOR_BGREEN); if (! passthrough_word()) return 1; cond_set_color(COLOR_NOCOLOR); putchar('\n'); if (break_lines) { if (breaklines(n, k) == EOF) return 0; } else { print_line_offset(k); if (passthrough_line() == EOF) return 0; } } /* Should never be reached. */ return 0; } /* Returns 0 on end of line or end of file and 1 otherwise. */ _Bool passthrough_word() { int c; while (1) { c = getchar(); if (c == ' ') return 1; if (c == EOF || c == '\n') return 0; putchar(c); } } /* Like getchar(), but merge [ \t\v]* into a single space. * Iff trim_ws, ignore any whitespace. */ int getchar_mergews(_Bool trim_ws) { int c = getchar(); if (c == ' ' || c == '\t' || c == '\v') { do { c = getchar(); } while (c == ' ' || c == '\t' || c == '\v'); if (trim_ws) { return c; } else { ungetc(c, stdin); return ' '; } } else { return c; } } /* Passes through everything from stdin to stdout until a newline character * or EOF is read. * Converts [ \t\v]* to ' '. * Returns 0 on end of line and EOF on end of file. */ int passthrough_line() { int c; c = getchar_mergews(1); if (c == EOF) return EOF; else if (c == '\n') return 0; while (1) { if (c == EOF) { putchar('\n'); return EOF; } else if (c == '\n') { putchar('\n'); return 0; } putchar(c); c = getchar_mergews(0); } } /* Read description - delimited by newline - and print it broken into * lines of max. n chars with an offset of k chars. * Returns 0 on end of line and EOF on end of file. */ int breaklines(int n, int k) { int c; int i = 0; int wi = 0; char word[n]; _Bool first = 1; c = getchar_mergews(1); while (1) { if (c == '\n' || c == EOF) { if (wi != 0) { print_word_offset(k); printf("%.*s\n", wi, word); } else if (! first) putchar('\n'); if (c == '\n') return 0; else /* c == EOF */ return EOF; } if (c == ' ') { if (wi != 0) { i++; print_word_offset(k); printf("%.*s", wi, word); first = 0; wi = 0; } c = getchar_mergews(0); } else if (break_lines && i >= n) { if (first) { print_line_offset(k); printf("%.*s\n", wi, word); wi = 0; i = 0; } else { putchar('\n'); first = 1; i = wi; } } else { word[wi] = c; wi++; i++; c = getchar_mergews(0); } } }