gn

thing1's goat note implementation
Log | Files | Refs

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 }