commit 8373b544bf0cc6158c5a4180c12dc59f7eee3e01
parent 64ffcfd191ee8fe053b741d8e4dc806fc850a244
Author: Remy Noulin <loader2x@gmail.com>
Date: Fri, 29 Sep 2017 22:59:27 +0200
add md.c to show md files with highlighting
md.c | 393 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
package.yml | 17 +++
2 files changed, 410 insertions(+)
Diffstat:
| A | md.c | | | 393 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| A | package.yml | | | 17 | +++++++++++++++++ |
2 files changed, 410 insertions(+), 0 deletions(-)
diff --git a/md.c b/md.c
@@ -0,0 +1,393 @@
+#! /usr/bin/env sheepy
+//
+
+#include "libsheepyObject.h"
+#include "shpPackages/md4c/md4c.h"
+
+int argc;
+char **argv;
+
+typedef struct {
+ smallArrayt *out;
+ smallStringt *current;
+ MD_BLOCKTYPE blockquote;
+ MD_BLOCKTYPE li;
+ MD_BLOCKTYPE h;
+ unsigned level;
+ MD_BLOCKTYPE p;
+ MD_BLOCKTYPE em;
+ MD_BLOCKTYPE strong;
+ MD_BLOCKTYPE a;
+ MD_BLOCKTYPE img;
+ MD_BLOCKTYPE code;
+ MD_BLOCKTYPE del;
+ MD_BLOCKTYPE blockcode;
+ MD_BLOCKTYPE ul;
+ MD_BLOCKTYPE ol;
+ unsigned olCount;
+} outt;
+
+#define BLOCKQUOTE " "
+
+#define ADD_BLOCKQUOTE \
+ if(r->blockquote == MD_BLOCK_QUOTE) {\
+ prependG(r->current, BLOCKQUOTE);\
+ }
+
+#define ADD_BLOCKCODE \
+ if(r->blockcode == MD_BLOCK_CODE) {\
+ pushG(r->current, BLD BGRED WHT "`````````" RST "\n");\
+ r->blockcode = 0;\
+ }
+
+internal int
+enter_block_callback(MD_BLOCKTYPE type, void* detail, void* userdata)
+{
+ cast(outt *, r, userdata);
+
+ switch(type) {
+ case MD_BLOCK_DOC: /* noop */
+ break;
+ case MD_BLOCK_QUOTE:
+ r->blockquote = MD_BLOCK_QUOTE;
+ pushG(r->out, "");
+ //puts(MGT "blockquote" RST);
+ break;
+ case MD_BLOCK_UL:
+ r->ul = MD_BLOCK_UL;
+ pushG(r->out, "");
+ //puts(GRN "ul" RST);
+ break;
+ case MD_BLOCK_OL:
+ r->ol = MD_BLOCK_OL;
+ r->olCount = 1;
+ pushG(r->out, "");
+ //puts(GRN "ol" RST);
+ break;
+ case MD_BLOCK_LI:
+ r->li = MD_BLOCK_LI;
+ if(!isEmptyG(r->current)) {
+ ADD_BLOCKQUOTE
+ ADD_BLOCKCODE
+ pushG(r->out, r->current);
+ pushG(r->out,"");
+ free(r->current);
+ r->current=allocG("");
+ }
+ //puts(GRN "li" RST);
+ break;
+ case MD_BLOCK_HR:
+ pushG(r->out, "");
+ //puts(BLU "hr" RST);
+ break;
+ case MD_BLOCK_H:
+ r->h = MD_BLOCK_H;
+ r->level=((MD_BLOCK_H_DETAIL*)detail)->level;
+ if(!isEmptyG(r->current)) {
+ ADD_BLOCKCODE
+ pushG(r->out, r->current);
+ free(r->current);
+ r->current = allocG("");
+ }
+ //puts(BLU "hN" RST);
+ break;
+ case MD_BLOCK_CODE:
+ r->blockcode = MD_BLOCK_CODE;
+ pushG(r->out, "\n" BLD BGRED WHT "`````````" RST);
+ //puts(MGT "BLOCK_CODE" RST);
+ break;
+ /* case MD_BLOCK_HTML: #<{(| noop |)}># break; */
+ case MD_BLOCK_P:
+ if((r->li != MD_BLOCK_LI)&&(!isEmptyG(r->current))) {
+ ADD_BLOCKQUOTE
+ ADD_BLOCKCODE
+ pushG(r->out, r->current);
+ free(r->current);
+ r->current=allocG("");
+ }
+ //puts(GRN "p" RST);
+ break;
+ /* case MD_BLOCK_TABLE: RENDER_LITERAL(r, "<table>\n"); break; */
+ /* case MD_BLOCK_THEAD: RENDER_LITERAL(r, "<thead>\n"); break; */
+ /* case MD_BLOCK_TBODY: RENDER_LITERAL(r, "<tbody>\n"); break; */
+ /* case MD_BLOCK_TR: RENDER_LITERAL(r, "<tr>\n"); break; */
+ /* case MD_BLOCK_TH: render_open_td_block(r, "th", (MD_BLOCK_TD_DETAIL*)detail); break; */
+ /* case MD_BLOCK_TD: render_open_td_block(r, "td", (MD_BLOCK_TD_DETAIL*)detail); break; */
+ }
+
+ return 0;
+}
+
+internal int
+leave_block_callback(MD_BLOCKTYPE type, void* detail, void* userdata)
+{
+ cast(outt *, r, userdata);
+ static const MD_CHAR* head[6] = { "</h1>\n", "</h2>\n", "</h3>\n", "</h4>\n", "</h5>\n", "</h6>\n" };
+ /* MD_RENDER_HTML* r = (MD_RENDER_HTML*) userdata; */
+
+ switch(type) {
+ case MD_BLOCK_DOC: /*noop*/
+ break;
+ case MD_BLOCK_QUOTE:
+ r->blockquote = 0;
+ pushG(r->out, "");
+ //puts(MGT "/blockquote" RST);
+ break;
+ case MD_BLOCK_UL:
+ r->ul = 0;
+ pushG(r->out, "");
+ //puts(GRN "/ul" RST);
+ break;
+ case MD_BLOCK_OL:
+ r->ol = 0;
+ pushG(r->out, "");
+ //puts(GRN "/ol" RST);
+ break;
+ case MD_BLOCK_LI:
+ //puts(GRN "/li" RST);
+ if (r->li == MD_BLOCK_LI) {
+ if (r->ul == MD_BLOCK_UL) {
+ prependG(r->current, "- ");
+ }
+ if (r->ol == MD_BLOCK_OL) {
+ char *s = intToS(r->olCount);
+ pushG(&s, ". ");
+ prependG(r->current, s);
+ free(s);
+ r->olCount++;
+ }
+ r->li = 0;
+ ADD_BLOCKQUOTE
+ pushG(r->out, r->current);
+ free(r->current);
+ r->current=allocG("");
+ }
+ break;
+ case MD_BLOCK_HR: /*noop*/
+ break;
+ case MD_BLOCK_H:
+ //puts(BLU "</hN>" RST);
+ r->h = 0;
+ pushG(r->out, "");
+ prependG(r->current, "# ");
+ colorG(r->current, BLD YLW);
+ pushG(r->out, r->current);
+ pushG(r->out,"");
+ free(r->current);
+ r->current=allocG("");
+ break;
+ case MD_BLOCK_CODE:
+ //puts(MGT "/BLOCK_CODE" RST);
+ break;
+ case MD_BLOCK_HTML: /* noop */
+ break;
+ case MD_BLOCK_P:
+ //puts(GRN "/p" RST);
+ if (r->li == MD_BLOCK_LI) {
+ if (r->ul == MD_BLOCK_UL) {
+ prependG(r->current, "- ");
+ }
+ if (r->ol == MD_BLOCK_OL) {
+ char *s = intToS(r->olCount);
+ pushG(&s, ". ");
+ prependG(r->current, s);
+ free(s);
+ r->olCount++;
+ }
+ r->li = 0;
+ }
+ ADD_BLOCKQUOTE
+ pushG(r->out, r->current);
+ free(r->current);
+ r->current=allocG("");
+ break;
+ /* case MD_BLOCK_TABLE: RENDER_LITERAL(r, "</table>\n"); break; */
+ /* case MD_BLOCK_THEAD: RENDER_LITERAL(r, "</thead>\n"); break; */
+ /* case MD_BLOCK_TBODY: RENDER_LITERAL(r, "</tbody>\n"); break; */
+ /* case MD_BLOCK_TR: RENDER_LITERAL(r, "</tr>\n"); break; */
+ /* case MD_BLOCK_TH: RENDER_LITERAL(r, "</th>\n"); break; */
+ /* case MD_BLOCK_TD: RENDER_LITERAL(r, "</td>\n"); break; */
+ }
+
+ return 0;
+}
+
+internal int
+enter_span_callback(MD_SPANTYPE type, void* detail, void* userdata)
+{
+ cast(outt *, r, userdata);
+
+ /* MD_RENDER_HTML* r = (MD_RENDER_HTML*) userdata; */
+ /* */
+ /* if(r->image_nesting_level > 0) { */
+ /* #<{(| We are inside an image, i.e. rendering the ALT attribute of */
+ /* * <IMG> tag. |)}># */
+ /* return 0; */
+ /* } */
+
+ switch(type) {
+ case MD_SPAN_EM:
+ r->em = 1;
+ //puts(RED "em" RST);
+ break;
+ case MD_SPAN_STRONG:
+ r->strong=MD_SPAN_STRONG;
+ break;
+ case MD_SPAN_A:
+ r->a=MD_SPAN_A;
+ break;
+ case MD_SPAN_IMG:
+ r->img = MD_SPAN_IMG;
+ break;
+ case MD_SPAN_CODE:
+ r->code=MD_SPAN_CODE;
+ break;
+ case MD_SPAN_DEL:
+ r->del = MD_SPAN_DEL;
+ //puts(BLD RED "del" RST);
+ break;
+ }
+
+ return 0;
+}
+
+internal int
+leave_span_callback(MD_SPANTYPE type, void* detail, void* userdata)
+{
+ /* MD_RENDER_HTML* r = (MD_RENDER_HTML*) userdata; */
+ /* */
+ /* if(r->image_nesting_level > 0) { */
+ /* #<{(| We are inside an image, i.e. rendering the ALT attribute of */
+ /* * <IMG> tag. |)}># */
+ /* if(r->image_nesting_level == 1 && type == MD_SPAN_IMG) */
+ /* render_close_img_span(r, (MD_SPAN_IMG_DETAIL*) detail); */
+ /* return 0; */
+ /* } */
+ /* */
+ /* switch(type) { */
+ /* case MD_SPAN_EM: RENDER_LITERAL(r, "</em>"); break; */
+ /* case MD_SPAN_STRONG: RENDER_LITERAL(r, "</strong>"); break; */
+ /* case MD_SPAN_A: RENDER_LITERAL(r, "</a>"); break; */
+ /* case MD_SPAN_IMG: #<{(|noop, handled above|)}># break; */
+ /* case MD_SPAN_CODE: RENDER_LITERAL(r, "</code>"); break; */
+ /* case MD_SPAN_DEL: RENDER_LITERAL(r, "</del>"); break; */
+ /* } */
+
+ return 0;
+}
+
+internal int
+text_callback(MD_TEXTTYPE type, const MD_CHAR* text, MD_SIZE size, void* userdata)
+{
+ cast(outt *, r, userdata);
+ char *s = calloc(1, size+1);
+ smallStringt *t;
+
+ switch(type) {
+ case MD_TEXT_NULLCHAR:
+ break;
+ case MD_TEXT_BR:
+ pushG(r->out, "");
+ //puts(BLU "br" RST);
+ break;
+ case MD_TEXT_SOFTBR:
+ pushG(r->current, " ");
+ //puts(BLU "sbr" RST);
+ break;
+ case MD_TEXT_HTML:
+ strncpy(s, text, size); /*pushG(r->out, s);*/ //puts(BLU "html" RST);
+ break;
+ /* case MD_TEXT_ENTITY: render_entity(r, text, size, render_html_escaped); break; */
+ default:
+ strncpy(s, text, size);
+ t = allocG(s);
+ if (r->em == 1) {
+ colorG(t, GRN);
+ r->em = 0;
+ }
+ if (r->strong == MD_SPAN_STRONG) {
+ colorG(t, BLD);
+ r->strong = 0;
+ }
+ if (r->a == MD_SPAN_A) {
+ colorG(t, BLD UDL BLU);
+ r->a = 0;
+ }
+ if (r->img == MD_SPAN_IMG) {
+ //puts(BLD "IMG" RST);
+ colorG(t, UDL RED);
+ r->img = 0;
+ }
+ if (r->code == MD_SPAN_CODE) {
+ colorG(t, BGBLU);
+ r->code = 0;
+ }
+ if (r->del == MD_SPAN_DEL) {
+ colorG(t, INV);
+ r->del = 0;
+ }
+ pushNFreeG(r->current, t);
+ //puts(BLU "default" RST);
+ //printf(">%s<\n", s);
+ break;
+ }
+
+ free(s);
+
+ return 0;
+}
+
+internal void
+debug_log_callback(const char* msg, void* userdata)
+{
+ shEPrintfS("md4c %s", msg);
+}
+
+int main(int ARGC, char** ARGV) {
+
+ argc = ARGC;
+ argv = ARGV;
+
+ initLibsheepy(argv[0]);
+
+ if (argc < 2) {
+ puts(RED "Give a filename in parameter" RST);
+ XFAILURE
+ }
+
+ char *c = readFileG(c, argv[1]);
+
+ if (!c) {
+ puts(RED "Error reading:" RST);
+ puts(argv[1]);
+ XFAILURE
+ }
+
+ outt result;
+
+ memset(&result, 0, sizeof(result));
+
+ result.out = allocG(rtSmallArrayt);
+ result.current = allocG("");
+
+ unsigned parser_flags = MD_DIALECT_GITHUB;
+ unsigned renderer_flags = 0;
+
+ MD_RENDERER renderer = {
+ enter_block_callback,
+ leave_block_callback,
+ enter_span_callback,
+ leave_span_callback,
+ text_callback,
+ debug_log_callback,
+ parser_flags
+ };
+
+ md_parse(c, strlen(c), &renderer, &result);
+
+ logG(result.out);
+ //logVarG(result.out);
+
+ finalizeLibsheepy();
+
+}
diff --git a/package.yml b/package.yml
@@ -0,0 +1,17 @@
+---
+ name: md
+ version: 0.0.1
+ description: cat markdown files with syntax highlighting
+ repository:
+ type: git
+ url: git+https://github.com/RemyNoulin/md.git
+ keywords:
+ - utility
+ - command
+ author: Remy Noulin
+ license: MIT
+ bugs:
+ url: https://github.com/RemyNoulin/md/issues
+ homepage: https://github.com/RemyNoulin/md#readme
+ dependencies:
+ md4c: ""