diff options
author | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-11-05 02:39:33 +0100 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@gmx.de> | 2012-11-05 02:39:33 +0100 |
commit | 72679fd6ccc72d993309a256030d89ee5e21102b (patch) | |
tree | c66cc04dda5c9866876c264e2549e53b83071ebc /sys/src/cmd | |
parent | 4d1f113490803bdcc0caf2ccb7432719356095ce (diff) |
add google code wiki formatter aux/wikifmt
Diffstat (limited to 'sys/src/cmd')
-rw-r--r-- | sys/src/cmd/aux/mkfile | 1 | ||||
-rw-r--r-- | sys/src/cmd/aux/wikifmt.c | 451 |
2 files changed, 452 insertions, 0 deletions
diff --git a/sys/src/cmd/aux/mkfile b/sys/src/cmd/aux/mkfile index 0017e2cb9..678dd8db5 100644 --- a/sys/src/cmd/aux/mkfile +++ b/sys/src/cmd/aux/mkfile @@ -43,6 +43,7 @@ TARG=\ usage\ write\ wacom\ + wikifmt\ zerotrunc\ BIN=/$objtype/bin/aux diff --git a/sys/src/cmd/aux/wikifmt.c b/sys/src/cmd/aux/wikifmt.c new file mode 100644 index 000000000..80cd53f1b --- /dev/null +++ b/sys/src/cmd/aux/wikifmt.c @@ -0,0 +1,451 @@ +/* + * google code wiki to html converter. + * https://code.google.com/p/support/wiki/WikiSyntax + */ +#include <u.h> +#include <libc.h> + +enum { + HUNK = 8*1024, +}; + +char *buf; +char *pos; +char *epos; +char *opos; + +int inquote = 0; +int intable = 0; +int inlist = 0; +int indent = -1; + +void body(void); + +int +match(char *s) +{ + int n; + + n = strlen(s); + if(pos+n > epos) + return 0; + return cistrncmp(pos, s, n) == 0; +} + +int +got(char *s) +{ + if(!match(s)) + return 0; + pos += strlen(s); + return 1; +} + +char* +look(char *s, char *e) +{ + char *p; + int n; + + if(e == nil) + e = epos; + n = strlen(s); + e -= n; + for(p = pos; p <= e; p++) + if(cistrncmp(p, s, n) == 0) + return p; + return nil; +} + +void +eatspace(void) +{ + while(pos < epos && (*pos == ' ' || *pos == '\t')) + pos++; +} + +char* +trimback(char *s) +{ + while(s > pos && strchr("\t ", s[-1]) != nil) + s--; + return s; +} + +void +flush(void) +{ + int n; + + n = opos - buf; + if(n <= 0) + return; + if(write(1, buf, n) != n) + sysfatal("write: %r"); + opos = buf; +} + +void +output(char *s, int n) +{ + int r; + + if(n <= 0) + return; + r = HUNK - (opos - buf); + if(n > r){ + output(s, r); + output(s+r, n-r); + } else { + memmove(opos, s, n); + opos += n; + if(r == n) + flush(); + } +} + +void +string(char *s) +{ + output(s, strlen(s)); +} + +void +escape(char *e) +{ + char *p; + + for(p = pos; p < e; p++) + if(*p == '<'){ + output(pos, p - pos); + pos = p+1; + string("<"); + } else if(*p == '>'){ + output(pos, p - pos); + pos = p+1; + string(">"); + } else if(*p == '&'){ + output(pos, p - pos); + pos = p+1; + string("&"); + } + output(pos, p - pos); + pos = p; +} + +void +ebody(char *e) +{ + char *t; + + t = epos; + epos = trimback(e); + body(); + pos = e; + epos = t; +} + +int +tag(char *term, char *tag) +{ + char *e; + + if(!got(term)) + return 0; + if(e = look(term, nil)){ + eatspace(); + string("<"); string(tag); string(">"); + ebody(e); + string("</"); string(tag); string(">"); + pos += strlen(term); + } else + string(term); + return 1; +} + +int +heading(void) +{ + char *o, *s, *e; + int n; + + for(s = "======"; *s; s++) + if(got(s)) + break; + if(*s == 0) + return 0; + n = strlen(s); + e = look("=", look("\n", nil)); + if(e == nil) + e = look("\n", nil); + if(e == nil) + e = epos; + eatspace(); + string("<h"); + output("0123456"+n, 1); + string("><a name=\""); + o = pos; + while(pos < e){ + if((*pos >= 'a' && *pos <= 'z') + || (*pos >= 'A' && *pos <= 'Z') + || (*pos >= '0' && *pos <= '9') + || (*pos == '-')) + output(pos, 1); + else + output("_", 1); + pos++; + } + string("\"></a>"); + pos = o; + ebody(e); + while(got("=")) + ; + string("</h"); + output("0123456"+n, 1); + string(">"); + return 1; +} + +void +link(char *e) +{ + char *s, *o; + + s = o = pos; + while(s < epos){ + if(e != nil && s >= e) + break; + if(*s == 0 || strchr("<>[] \t\r\n", *s) != nil) + break; + s++; + } + if(s-4 >= o) + if(cistrncmp(s-4, ".png", 4) + && cistrncmp(s-4, ".jpg", 4) + && cistrncmp(s-4, ".gif", 4)){ + string("<a href=\""); + escape(s); + string("\">"); + eatspace(); + if(e != nil && pos < e) + ebody(e); + else { + pos = o; + escape(s); + } + string("</a>"); + } else { + string("<img src=\""); + escape(s); + string("\">"); + } +} + +void +body(void) +{ + char *s; + int t; + +Next: + if(pos >= epos) + return; + + if(got("\n") || got("\r\n")) + indent = -1; + if(got("\n") || got("\r\n")){ + string("<br>"); + while(got("\n") || got("\r\n")) + ; + } + + if(indent == -1){ + indent = 0; + for(;;){ + if(got(" ")) + indent++; + else if(got("\t")){ + indent += 8; + indent %= 8; + } + else break; + } + + if(intable && look("||", look("\n", nil)) == nil){ + string("</table>"); + intable = 0; + } + + string("\n"); + if((indent < inlist) || (indent < inquote)) + return; + + while(indent > 0){ + if(pos >= epos) + return; + if(got("*") || got("#")){ + s = pos-1; + eatspace(); + if(indent > inlist){ + if(*s == '*') + string("<ul><li>"); + else + string("<ol><li>"); + t = inlist; + inlist = indent; + body(); + inlist = t; + if(*s == '*') + string("</li></ul>"); + else + string("</li></ol>"); + } else { + string("</li><li>"); + break; + } + } else if(indent > inquote){ + string("<blockquote>"); + t = inquote; + inquote = indent; + body(); + inquote = t; + string("</blockquote>"); + } else + break; + } + + if(indent == 0){ + if(got("#")){ + if((pos = look("\n", nil)) == nil) + pos = epos; + goto Next; + } + if(heading()) + goto Next; + if(got("----")){ + while(got("-")) + ; + string("<hr>"); + goto Next; + } + } + } + + if(got("`")){ + if(s = look("`", nil)){ + escape(s); + pos = s+1; + } else + string("`"); + } + else if(got("<")){ + string("<"); + if(s = look(">", nil)){ + s++; + output(pos, s - pos); + pos = s; + } + } + else if(got("[")){ + if(s = look("]", nil)){ + link(s); + pos = s+1; + } else + string("["); + } + else if(tag("*", "b") || + tag("_", "i") || + tag("^", "sup") || + tag(",,", "sub") || + tag("~~", "strike")){ + } + else if(got("{{{")){ + if(s = look("}}}", nil)){ + if(look("\n", s)){ + string("<pre>"); + escape(s); + string("</pre>"); + } else { + string("<tt>"); + escape(s); + string("</tt>"); + } + pos = s+3; + } else + string("{{{"); + } + else if(got("||")){ + if(s = look("||", look("\n", nil))){ + eatspace(); + switch(intable){ + case 0: string("<table>"); + intable++; + case 1: string("<tr>"); + intable++; + } + string("<td>"); + ebody(s); + string("</td>"); + } else if(intable){ + string("</tr>"); + intable = 1; + } + } + else if(match("http://")) + link(nil); + else if(match("https://")) + link(nil); + else if(match("ftp://")) + link(nil); + else{ + output(pos, 1); + pos++; + } + goto Next; +} + +void +usage(void) +{ + fprint(2, "usage: %s [ file ]\n", argv0); + exits("usage"); +} + +void +main(int argc, char *argv[]) +{ + int n; + + ARGBEGIN{ + default: + usage(); + }ARGEND; + + if(argc != 0 && argc != 1) + usage(); + + if(*argv){ + if((n = open(*argv, OREAD)) < 0) + sysfatal("open %s: %r", *argv); + if(dup(n, 0) < 0) + sysfatal("dup: %r"); + } + + buf = opos = sbrk(HUNK); + pos = epos = buf + HUNK; + for(;;){ + if(brk(epos + HUNK + 8) < 0) + sysfatal("brk: %r"); + if((n = read(0, epos, HUNK)) < 0) + sysfatal("read: %r"); + if(n == 0) + break; + epos += n; + } + if(epos > pos && epos[-1] != '\n') + *epos++ = '\n'; + + body(); + flush(); + exits(0); +} |