gn.c (3659B)
1 #include <ctype.h> 2 #include <stdint.h> 3 #include <stdio.h> 4 #include <string.h> 5 #include <stdlib.h> 6 7 #include "tokens.h" 8 #include "output.h" 9 #include "util.h" 10 #include "opts.h" 11 12 outputformats outputformat; 13 mode m = NONE; 14 token tokens[1024]; 15 int tokcount = 0; 16 17 char *header = NULL, *footer = NULL; 18 19 char *stripwhitespace(char *expr) { 20 while (isblank(expr[0])) expr++; 21 22 while (isblank(expr[strlen(expr) - 1])) expr[strlen(expr) - 1] = 0; 23 24 return expr; 25 } 26 27 void formatcheck() { 28 types prev = NIL; 29 for (int i = 0; i < tokcount; i++) { 30 switch (prev) { 31 case NIL: 32 if (tokens[i].type != HEADING) eprint("Expected heading!"); 33 break; 34 case HEADING: 35 if (tokens[i].type != DATE) eprint("Expected date"); 36 break; 37 case DATE: 38 if (tokens[i].type != TODO) eprint("Expected todo|done marker"); 39 break; 40 } 41 prev = tokens[i].type; 42 } 43 } 44 45 int readuntil(char *file, int off, char end, types t) { 46 int j = 0; 47 char tok[256]; 48 49 off++; 50 while (file[off] != end) { 51 if (file[off] == 0) eprint("Never closed expression!") ; 52 tok[j] = file[off]; 53 off++; 54 j++; 55 } 56 57 tok[j] = 0; 58 59 memcpy(tokens[tokcount].data, stripwhitespace(tok), 256); 60 tokens[tokcount].type = t; 61 tokcount++; 62 63 return off; 64 } 65 66 void usage() { 67 eprint("usage: gn [-l -c -o format -p -H header -F footer -h] < note.gn"); 68 } 69 70 int main(int argc, char **argv) { 71 if (argc <= 1) usage(); 72 for (int i = 1; i < argc && argc != 1; i++) { 73 if (strcmp(argv[i], "-l") == 0) m |= LIST; 74 else if (strcmp(argv[i], "-c") == 0) m |= CHECK; 75 else if (strcmp(argv[i], "-o") == 0) { 76 i++; 77 if (!(i < argc)) eprint("expecet additional argument after -o!") ; 78 if (strcmp(argv[i], "goatnote") == 0) outputformat = GOATNOTE; 79 else if (strcmp(argv[i], "html") == 0) outputformat = HTML; 80 else if (strcmp(argv[i], "groff") == 0) outputformat = GROFF; 81 else if (strcmp(argv[i], "text") == 0) outputformat = TEXT; 82 83 m |= OUTPUT; 84 } 85 else if (strcmp(argv[i], "-p") == 0) m |= PRETTY; 86 else if (strcmp(argv[i], "-H") == 0) { 87 i++; 88 if (!(i < argc)) eprint("expecet additional argument after -H!"); 89 header = argv[i]; 90 } 91 92 else if (strcmp(argv[i], "-F") == 0) { 93 i++; 94 if (!(i < argc)) eprint("expecet additional argument after -F!"); 95 footer = argv[i]; 96 } 97 else if (strcmp(argv[i], "-h") == 0) usage(); 98 else usage(); 99 } 100 101 102 char file[INT16_MAX]; 103 int i; 104 char c; 105 while ((c = getchar()) != EOF) { 106 file[i] = c; 107 i++; 108 } 109 file[i] = 0; 110 111 for (i = 0; i < strlen(file); i++) { 112 switch (file[i]) { 113 case '*': i = readuntil(file, i, '*', HEADING); break; 114 case '[': i = readuntil(file, i, ']', DATE); break; 115 case '{': i = readuntil(file, i, '}', TODO); break; 116 case '-': i = readuntil(file, i, '\n', BULLET); break; 117 case ' ': 118 case '\n': 119 case '\t': 120 break; 121 default: 122 eprint("unknown char found!"); 123 } 124 } 125 126 if (header != NULL) printf("%s\n", header); 127 128 if ((m & LIST) == LIST) { 129 formatcheck(); 130 for (int i = 0; i < tokcount; i++) { 131 if (tokens[i].type == HEADING) { 132 if ((m & PRETTY) == PRETTY) 133 printf("\e[1m%s\e[0m \e[4m%s\e[0m \e[2m%s\e[0m\n", tokens[i].data, tokens[i+1].data, tokens[i+2].data); 134 else 135 printf("%s %s %s\n", tokens[i].data, tokens[i+1].data, tokens[i+2].data); 136 i += 2; 137 } 138 } 139 } 140 if ((m & CHECK) == CHECK) { 141 formatcheck(); 142 } 143 if ((m & OUTPUT) == OUTPUT) { 144 formatcheck(); 145 for (int i = 0; i < tokcount; i++){ 146 switch (outputformat) { 147 case HTML: printashtml(tokens[i]); break; 148 case GOATNOTE: printasgn(tokens[i]); break; 149 case GROFF: printasgroff(tokens[i]); break; 150 case TEXT: printastext(tokens[i]); break; 151 } 152 } 153 } 154 155 if (footer != NULL) printf("%s\n", footer); 156 return 0; 157 }