mirror of
https://github.com/Orc/discount.git
synced 2026-09-25 04:10:00 +03:00
change the external code block formatting option into an actual external code block formatter
This commit is contained in:
+70
-46
@@ -1663,21 +1663,75 @@ printtable(Paragraph *pp, MMIOT *f)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* external formatter caller for code blocks
|
||||
*/
|
||||
static int
|
||||
code_callback(Line *t, char *lang, int fenced, Line **ret, MMIOT *f)
|
||||
{
|
||||
if ( f->cb->e_codefmt ) {
|
||||
/* external code block formatter; copy the text into a buffer,
|
||||
* call the formatter to style it, then dump that styled text
|
||||
* directly to the queue
|
||||
*/
|
||||
char *text;
|
||||
char *fmt;
|
||||
int size, copy_p;
|
||||
Line *p;
|
||||
|
||||
for (size=0, p = t; p && (fenced ? p->is_fenced : 1); p = p->next )
|
||||
size += 1+S(p->text);
|
||||
|
||||
text = malloc(1+size);
|
||||
|
||||
for ( copy_p = 0; t && (fenced ? t->is_fenced : 1); t = t->next ) {
|
||||
memcpy(text+copy_p, T(t->text), S(t->text));
|
||||
copy_p += S(t->text);
|
||||
text[copy_p++] = '\n';
|
||||
}
|
||||
text[copy_p] = 0;
|
||||
|
||||
|
||||
fmt = (*(f->cb->e_codefmt))(text, copy_p, (lang && lang[0]) ? lang : 0);
|
||||
free(text);
|
||||
|
||||
if ( fmt ) {
|
||||
Qwrite(fmt, strlen(fmt), f);
|
||||
if ( f->cb->e_free )
|
||||
(*(f->cb->e_free))(fmt, f->cb->e_data);
|
||||
*ret = t;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
/* either the external formatter failed or doesn't exist,
|
||||
* so fall back to the traditional codeblock format
|
||||
*/
|
||||
*ret = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static Line *
|
||||
printfenced(Line *t, MMIOT *f)
|
||||
{
|
||||
Line *ret;
|
||||
|
||||
|
||||
Qstring("<pre><code", f);
|
||||
if ( t->fence_class )
|
||||
Qprintf(f, " class=\"%s\"", t->fence_class);
|
||||
Qchar('>', f);
|
||||
while ( (t = t->next) && t->is_fenced ) {
|
||||
code(f, T(t->text), S(t->text));
|
||||
Qchar('\n', f);
|
||||
|
||||
if ( !code_callback(t, t->fence_class, 1, &ret, f) ) {
|
||||
while ( (t = t->next) && t->is_fenced ) {
|
||||
code(f, T(t->text), S(t->text));
|
||||
Qchar('\n', f);
|
||||
}
|
||||
ret = t;
|
||||
}
|
||||
|
||||
Qstring("</code></pre>\n", f);
|
||||
return t;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1713,6 +1767,7 @@ printblock(Paragraph *pp, MMIOT *f)
|
||||
} while (t && (t = t->next) );
|
||||
text(f);
|
||||
Qstring(End[align], f);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1721,42 +1776,8 @@ static void
|
||||
printcode(Line *t, char *lang, MMIOT *f)
|
||||
{
|
||||
int blanks;
|
||||
Line *ret;
|
||||
|
||||
if ( f->cb->e_codefmt ) {
|
||||
/* external code block formatter; copy the text into a buffer,
|
||||
* call the formatter to style it, then dump that styled text
|
||||
* directly to the queue
|
||||
*/
|
||||
char *text;
|
||||
char *fmt;
|
||||
int size, copy_p;
|
||||
Line *p;
|
||||
|
||||
for (size=0, p = t; p; p = p->next )
|
||||
size += 1+S(p->text);
|
||||
|
||||
text = malloc(1+size);
|
||||
|
||||
for ( copy_p = 0; t ; t = t->next ) {
|
||||
memcpy(text+copy_p, T(t->text), S(t->text));
|
||||
copy_p += S(t->text);
|
||||
text[copy_p++] = '\n';
|
||||
}
|
||||
text[copy_p] = 0;
|
||||
|
||||
fmt = (*(f->cb->e_codefmt))(text, copy_p, (lang && lang[0]) ? lang : 0);
|
||||
free(text);
|
||||
|
||||
if ( fmt ) {
|
||||
Qwrite(fmt, strlen(fmt), f);
|
||||
if ( f->cb->e_free )
|
||||
(*(f->cb->e_free))(fmt, f->cb->e_data);
|
||||
return;
|
||||
}
|
||||
/* otherwise the external formatter failed and we need to
|
||||
* fall back to the traditional codeblock format
|
||||
*/
|
||||
}
|
||||
|
||||
Qstring("<pre><code", f);
|
||||
if (lang && lang[0]) {
|
||||
@@ -1765,16 +1786,19 @@ printcode(Line *t, char *lang, MMIOT *f)
|
||||
Qstring("\"", f);
|
||||
}
|
||||
Qstring(">", f);
|
||||
for ( blanks = 0; t ; t = t->next ) {
|
||||
if ( S(t->text) > t->dle ) {
|
||||
while ( blanks ) {
|
||||
|
||||
if ( !code_callback(t, lang, 0, &ret, f) ) {
|
||||
for ( blanks = 0; t ; t = t->next ) {
|
||||
if ( S(t->text) > t->dle ) {
|
||||
while ( blanks ) {
|
||||
Qchar('\n', f);
|
||||
--blanks;
|
||||
}
|
||||
code(f, T(t->text), S(t->text));
|
||||
Qchar('\n', f);
|
||||
--blanks;
|
||||
}
|
||||
code(f, T(t->text), S(t->text));
|
||||
Qchar('\n', f);
|
||||
else blanks++;
|
||||
}
|
||||
else blanks++;
|
||||
}
|
||||
Qstring("</code></pre>", f);
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "amalloc.h"
|
||||
@@ -97,46 +98,67 @@ free_it(char *object, void *ctx)
|
||||
free(object);
|
||||
}
|
||||
|
||||
|
||||
char *external_formatter = 0;
|
||||
|
||||
|
||||
#define RECEIVER 0
|
||||
#define SENDER 1
|
||||
|
||||
char *
|
||||
external_codefmt(char *src, int len, char *lang)
|
||||
{
|
||||
int extra = 0;
|
||||
int i, x;
|
||||
int child_status;
|
||||
int size, bufsize, curr;
|
||||
char *res;
|
||||
|
||||
if ( lang == 0 )
|
||||
lang = "generic_code";
|
||||
pid_t child;
|
||||
|
||||
for ( i=0; i < len; i++) {
|
||||
if ( src[i] == '&' )
|
||||
extra += 5;
|
||||
else if ( src[i] == '<' || src[i] == '>' )
|
||||
extra += 4;
|
||||
int tochild[2], toparent[2];
|
||||
|
||||
if ( pipe(tochild) != 0 || pipe(toparent) != 0 ) {
|
||||
perror("external_codefmt (pipe)");
|
||||
res = malloc(len+1);
|
||||
strcpy(res, src);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* 80 characters for the format wrappers */
|
||||
if ( (res = malloc(len+extra+80+strlen(lang))) ==0 )
|
||||
/* out of memory? drat! */
|
||||
return 0;
|
||||
if ( (child = fork()) > 0 ) {
|
||||
|
||||
sprintf(res, "<pre><code class=\"%s\">\n", lang);
|
||||
x = strlen(res);
|
||||
for ( i=0; i < len; i++ ) {
|
||||
switch (src[i]) {
|
||||
case '&': strcpy(&src[x], "&");
|
||||
x += 5 /*strlen(&)*/ ;
|
||||
break;
|
||||
case '<': strcpy(&src[x], "<");
|
||||
x += 4 /*strlen(<)*/ ;
|
||||
break;
|
||||
case '>': strcpy(&src[x], ">");
|
||||
x += 4 /*strlen(>)*/ ;
|
||||
break;
|
||||
default: res[x++] = src[i];
|
||||
break;
|
||||
close(tochild[RECEIVER]);
|
||||
close(toparent[SENDER]);
|
||||
|
||||
bufsize = 1000;
|
||||
res = malloc(1+bufsize);
|
||||
curr = 0;
|
||||
|
||||
/* parent */
|
||||
write(tochild[SENDER], src, len);
|
||||
close(tochild[SENDER]);
|
||||
|
||||
while ( (size = read(toparent[RECEIVER], res+curr, 1000)) > 0 ) {
|
||||
curr += size;
|
||||
res = realloc(res, bufsize += 1000);
|
||||
}
|
||||
res[curr] = 0;
|
||||
waitpid(child, &child_status, WNOHANG);
|
||||
|
||||
close(toparent[RECEIVER]);
|
||||
|
||||
return res;
|
||||
}
|
||||
strcpy(&res[x], "</code></pre>\n");
|
||||
else if ( child == 0 ) {
|
||||
close(tochild[SENDER]);
|
||||
close(toparent[RECEIVER]);
|
||||
close(1); dup2(toparent[SENDER], 1);
|
||||
close(0); dup2(tochild[RECEIVER], 0);
|
||||
system(external_formatter);
|
||||
close(0); close(tochild[RECEIVER]);
|
||||
close(1); close(toparent[SENDER]);
|
||||
exit(0);
|
||||
}
|
||||
res = malloc(len+1);
|
||||
strcpy(res, src);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -158,11 +180,12 @@ struct h_opt opts[] = {
|
||||
{ 0, 0, 'C', "prefix", "prefix for markdown extra footnotes" },
|
||||
{ 0, 0, 'o', "file", "write output to file" },
|
||||
{ 0, "squash", 'x', 0, "squash toc labels to be more like github" },
|
||||
{ 0, "codefmt",'X', 0, "use an external code formatter" },
|
||||
{ 0, "codefmt",'X', "command", "use an external code formatter" },
|
||||
{ 0, "help", '?', 0, "print a detailed usage message" },
|
||||
};
|
||||
#define NROPTS (sizeof opts/sizeof opts[0])
|
||||
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
@@ -268,6 +291,8 @@ main(int argc, char **argv)
|
||||
break;
|
||||
case 'X': use_e_codefmt = 1;
|
||||
mkd_set_flag_num(flags, MKD_FENCEDCODE);
|
||||
external_formatter = hoptarg(&blob);
|
||||
fprintf(stderr, "selected external formatter (%s)\n", external_formatter);
|
||||
break;
|
||||
case '?': hoptdescribe(pgm, opts, NROPTS, "[file]", 1);
|
||||
return 0;
|
||||
@@ -323,6 +348,7 @@ main(int argc, char **argv)
|
||||
}
|
||||
if ( squash )
|
||||
mkd_e_anchor(doc, (mkd_callback_t) anchor_format);
|
||||
|
||||
if ( use_e_codefmt )
|
||||
mkd_e_code_format(doc, (mkd_callback_t)external_codefmt);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user