md

cat markdown files with syntax highlighting
git clone https://noulin.net/git/md.git
Log | Files | Refs | README | LICENSE

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:
Amd.c | 393+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Apackage.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: ""