From 94c419801a05f1442182b0752fef0d89489b75b7 Mon Sep 17 00:00:00 2001 From: Alex Karle Date: Mon, 27 Dec 2021 12:09:25 -0500 Subject: [PATCH] Rebrand blag -> nihdoc The new name is a play on mdoc(7), jokingly pointing fun at the decision to "invent here" instead of use markdown. --- .gitignore | 2 +- Makefile | 20 ++++++++++---------- README | 20 +++++++++++--------- blag.1 | 44 -------------------------------------------- blag.c | 287 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- nihdoc.1 | 44 ++++++++++++++++++++++++++++++++++++++++++++ nihdoc.c | 287 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ test/big.html | 2 +- test/big.txt | 2 +- 9 files changed, 355 insertions(+), 353 deletions(-) delete mode 100644 blag.1 delete mode 100644 blag.c create mode 100644 nihdoc.1 create mode 100644 nihdoc.c diff --git a/.gitignore b/.gitignore index 01ecc2c..e4d67b4 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -blag +nihdoc # test file input diff --git a/Makefile b/Makefile index 5966e2d..cf08a4a 100644 --- a/Makefile +++ b/Makefile @@ -1,30 +1,30 @@ -# blag makefile +# nihdoc makefile CFLAGS = -g -O2 -Wall -Wpedantic -Wextra -blag: blag.c - $(CC) $(CFLAGS) -o $@ blag.c +nihdoc: nihdoc.c + $(CC) $(CFLAGS) -o $@ nihdoc.c .PHONY: check -check: blag +check: nihdoc @for f in test/*.txt; do \ printf "$$f ... "; \ base=$$(basename $$f txt)html; \ if [ -z $(GENBASE) ]; then \ - ./blag < $$f > /tmp/$$base; \ + ./nihdoc < $$f > /tmp/$$base; \ diff -u test/$$base /tmp/$$base; \ echo "success!"; \ else \ - ./blag < $$f > test/$$base; \ + ./nihdoc < $$f > test/$$base; \ echo "generated!"; \ fi; \ done .PHONY: clean clean: - rm -f blag + rm -f nihdoc .PHONY: install -install: blag +install: nihdoc mkdir -p $(HOME)/bin $(HOME)/share/man/man1 - install -m 555 blag $(HOME)/bin - install -m 444 blag.1 $(HOME)/share/man/man1 + install -m 555 nihdoc $(HOME)/bin + install -m 444 nihdoc.1 $(HOME)/share/man/man1 diff --git a/README b/README index b10ac0e..26086b0 100644 --- a/README +++ b/README @@ -1,11 +1,16 @@ -# blag +# nihdoc + + Not Invented Here Doc + - - - --- > "because markdown isn't in base!" -> ~akarle +> +> ~akarle + ## Description -blag is my take at a light markup language to improve my +nihdoc is my take at a light markup language to improve my time-to-publish on blog posts. I concede up front that others should likely use markdown, which is both prettier and more well-known, but as a personal challenge I try to keep my blog @@ -14,11 +19,11 @@ no markdown parser in base, I had to write my own! ## Usage -`blag` reads from stdin and prints HTML snippets to stdout. No +`nihdoc` reads from stdin and prints HTML snippets to stdout. No arguments are read and no files are accessible (on OpenBSD this is enforced via pledge(2)). Common usage is: - $ (cat header.html; blag < file.txt; cat footer.html) > file.html + $ (cat header.html; nihdoc < file.txt; cat footer.html) > file.html ## Support @@ -29,12 +34,9 @@ is enforced via pledge(2)). Common usage is: - > quotes - TAB code blocks - Inline `code`, _italics_, and *bold* -- Escaping via \ +- Escaping via \\ - Links: [https://alexkarle.com my site] or [https://alexkarle.com] ## TODO - Mixed lists -- Lots of code cleanup -- Error reporting on malformed blocks -- Tests diff --git a/blag.1 b/blag.1 deleted file mode 100644 index df57406..0000000 --- a/blag.1 +++ /dev/null @@ -1,44 +0,0 @@ -.Dd December 18, 2021 -.Dt BLAG 1 -.Os -.Sh NAME -.Nm blag -.Nd convert plaintext to HTML -.Sh SYNOPSIS -.Nm blag -< -.Ar in.txt -> -.Ar out.html -.Sh DESCRIPTION -.Nm -is a very basic plaintext-to-HTML converter. -It reads from stdin and writes to stdout so that it can -.Xr pledge 2 -to only stdio. -Any arguments given will produce an error. -.Pp -Like markdown, wrapped lines are supported, -and a blank line is needed to start a new paragraph. -.Pp -The following markup is supported: -.Pp -.Bl -bullet -indent -.It -Inline *bold*, _italics_, `code` (bold/italics disabled in code) -.It -backslash to escape -.It -[alexkarle.com] bare links and [alexkarle.com description] -.It -# headers (each # adds a level) -.It -Ordered and unordered lists via 1-9. and - respectively. -Nesting supported only within the same type (no mixing, yet). -.It -Code blocks (start line with TAB) -.It -Block quotes (start line with >) -.El -.Sh SEE ALSO -.Xr Markdown.pl 1 diff --git a/blag.c b/blag.c deleted file mode 100644 index c1ace00..0000000 --- a/blag.c +++ /dev/null @@ -1,287 +0,0 @@ -/* - * blag.c -- generate the blog! - * ~akarle, MIT License - * - * "because markdown isn't in base!" - */ -#include -#include -#include - - -/* Global Constants and Enums */ -char *FMT_STRS[] = { - ['_'] = "em", - ['*'] = "strong", - ['`'] = "code", -}; - -enum Block { - NONE, - HEADER, - HEADER_PARSE, - PARAGRAPH, - CODE, - QUOTE, - LIST, - LIST_PARSE, -}; - -enum Link { - NOL, - URL_PARSE, - DESC_PARSE, -}; - - -/* Start Global State */ -int c = '0'; -enum Block in = NONE; -enum Link in_link = NOL; -int hlvl = 0; -bool fmts[256] = {false}; /* indexed by _ * ` */ -bool escape = false; -char lnkbuf[2048] = {0}; -int lnkidx = 0; -int indent = 0; -int previndent = 0; -int listdepth = 0; -int lastc = '0'; -bool ol = false; -bool linestarted = false; - - -/* Helper functions */ -void putesc(int c) { - switch (c) { - case '<': printf("<"); break; - case '>': printf(">"); break; - case '&': printf("&"); break; - default: putchar(c); - } -} - -void newlist() { - in = LIST; - previndent = indent; - printf("<%s>\n
  • \n", ol ? "ol" : "ul"); - listdepth++; -} - -int endlist() { - in = LIST; - previndent = indent; - printf("
  • \n\n", ol ? "ol" : "ul"); - return --listdepth; -} - -void maybe_startp() { - /* All inline types should start the paragraph if no other major type present*/ - if (in == NONE) { - in = PARAGRAPH; - printf("

    \n"); - } -} - -void handle_lf() { - indent = 0; - linestarted = false; - - /* single line types (one lf to close) */ - if (in == HEADER) { - in = NONE; - printf("\n", hlvl); - } - - /* terminate url parsing in links */ - if (in_link == URL_PARSE) { - in_link = DESC_PARSE; - printf("\">"); - } - - /* multi-line types (two lf to close) */ - if (lastc == '\n') { - switch (in) { - case PARAGRAPH: printf("

    \n"); break; - case CODE: printf("\n"); break; - case QUOTE: printf("\n"); break; - case LIST: - previndent = 0; - while (endlist()) - ; - break; - default: - break; /* no op */ - } - in = NONE; - } -} - -bool fmt_disabled() { - /* `` blocks disable all but the next `, likewise CODE makes all disabled */ - if (in == CODE || in_link == URL_PARSE) { - return true; - } else { - return fmts['`'] && c != '`'; - } -} - -void toggle_format() { - if (!fmt_disabled()) { - maybe_startp(); - printf("<%s%s>", fmts[c] ? "/" : "", FMT_STRS[c]); - fmts[c] ^= true; - } else { - putesc(c); - } -} - -int parse() { - /* Mini state machine (home grown spaghetti code) */ - while ((c = getchar()) != EOF) { - /* Handle Escapes before all else */ - if (escape) { - maybe_startp(); - putesc(c); - escape = false; - continue; - } - - /* Store links as we go */ - if (in_link == URL_PARSE && c != ']') { - lnkbuf[lnkidx++] = c; - } - - /* Store the indentation */ - if (!linestarted && c == ' ') { - indent++; - continue; /* don't print leading indents */ - } - - /* Handle unique state changes by char */ - switch (c) { - case '\\': - escape = true; - break; - case '#': - if (in == NONE) { - in = HEADER_PARSE; - hlvl = 1; - } else if (in == HEADER_PARSE) { - hlvl++; - } else { - /* not a special # */ - putesc(c); - } - break; - case ' ': - if (in == HEADER_PARSE) { - printf("", hlvl); - in = HEADER; - } else if (in_link == URL_PARSE) { - in_link = DESC_PARSE; - printf("\">"); - } else if (in == LIST_PARSE) { - if (!listdepth) { - newlist(); - } else { - if (previndent < indent) { - newlist(); - } else if (previndent > indent) { - endlist(); - printf("\n
  • \n"); - } else { - in = LIST; - printf("
  • \n
  • \n"); - } - } - } else { - putesc(c); - } - break; - case '*': - case '`': - case '_': - toggle_format(); - break; - case '\t': - case '>': - if (in == NONE) { - in = c == '>' ? QUOTE : CODE; - printf("%s", c == '>' ? "
    " : "
    ");
    -                } else if (lastc == '\n' && c == (in == CODE ? '\t' : '>')) {
    -                    /* no op */
    -                } else {
    -                    putesc(c);
    -                }
    -                break;
    -            case '[':
    -                if (in_link == NOL && !fmt_disabled()) {
    -                    maybe_startp();
    -                    in_link = URL_PARSE;
    -                    lnkidx = 0;
    -                    printf("%s", lnkbuf);
    -                } else if (in_link == DESC_PARSE) {
    -                    in_link = NOL;
    -                    printf("");
    -                } else {
    -                    putesc(c);
    -                }
    -                break;
    -            case '1':
    -            case '2':
    -            case '3':
    -            case '4':
    -            case '5':
    -            case '6':
    -            case '7':
    -            case '8':
    -            case '9':
    -            case '.':
    -            case '-':
    -                if (in == NONE || !linestarted) {
    -                    ol = c != '-';
    -                    in = LIST_PARSE;
    -                } else if (in != LIST_PARSE) {
    -                    putesc(c);
    -                }
    -                break;
    -            case '\n':
    -                handle_lf();
    -                if (in != NONE) {
    -                    putesc(c);
    -                }
    -                break;
    -            default:
    -                maybe_startp();
    -                putesc(c);
    -                break;
    -        }
    -        lastc = c;
    -        linestarted = c != '\n';
    -    }
    -    /* pretend there's a final LF to close any blocks */
    -    handle_lf();
    -    return 0;
    -}
    -
    -int main(int argc, char *argv[]) {
    -    if (argc > 1) {
    -        fprintf(stderr, "error: %s takes no arguments\n", argv[0]);
    -        return 1;
    -    }
    -#ifdef __OpenBSD__
    -    pledge("stdio", "stdio");
    -#endif
    -    return parse();
    -}
    diff --git a/nihdoc.1 b/nihdoc.1
    new file mode 100644
    index 0000000..df57406
    --- /dev/null
    +++ b/nihdoc.1
    @@ -0,0 +1,44 @@
    +.Dd December 18, 2021
    +.Dt BLAG 1
    +.Os
    +.Sh NAME
    +.Nm blag
    +.Nd convert plaintext to HTML
    +.Sh SYNOPSIS
    +.Nm blag
    +<
    +.Ar in.txt
    +>
    +.Ar out.html
    +.Sh DESCRIPTION
    +.Nm
    +is a very basic plaintext-to-HTML converter.
    +It reads from stdin and writes to stdout so that it can
    +.Xr pledge 2
    +to only stdio.
    +Any arguments given will produce an error.
    +.Pp
    +Like markdown, wrapped lines are supported,
    +and a blank line is needed to start a new paragraph.
    +.Pp
    +The following markup is supported:
    +.Pp
    +.Bl -bullet -indent
    +.It
    +Inline *bold*, _italics_, `code` (bold/italics disabled in code)
    +.It
    +backslash to escape
    +.It
    +[alexkarle.com] bare links and [alexkarle.com description]
    +.It
    +# headers (each # adds a level)
    +.It
    +Ordered and unordered lists via 1-9. and - respectively.
    +Nesting supported only within the same type (no mixing, yet).
    +.It
    +Code blocks (start line with TAB)
    +.It
    +Block quotes (start line with >)
    +.El
    +.Sh SEE ALSO
    +.Xr Markdown.pl 1
    diff --git a/nihdoc.c b/nihdoc.c
    new file mode 100644
    index 0000000..c1ace00
    --- /dev/null
    +++ b/nihdoc.c
    @@ -0,0 +1,287 @@
    +/*
    + * blag.c -- generate the blog!
    + *  ~akarle, MIT License
    + *
    + * "because markdown isn't in base!"
    + */
    +#include 
    +#include 
    +#include 
    +
    +
    +/* Global Constants and Enums */
    +char *FMT_STRS[] = {
    +    ['_'] = "em",
    +    ['*'] = "strong",
    +    ['`'] = "code",
    +};
    +
    +enum Block {
    +    NONE,
    +    HEADER,
    +    HEADER_PARSE,
    +    PARAGRAPH,
    +    CODE,
    +    QUOTE,
    +    LIST,
    +    LIST_PARSE,
    +};
    +
    +enum Link {
    +    NOL,
    +    URL_PARSE,
    +    DESC_PARSE,
    +};
    +
    +
    +/* Start Global State */
    +int c = '0';
    +enum Block in = NONE;
    +enum Link in_link = NOL;
    +int hlvl = 0;
    +bool fmts[256] = {false}; /* indexed by _ * ` */
    +bool escape = false;
    +char lnkbuf[2048] = {0};
    +int lnkidx = 0;
    +int indent = 0;
    +int previndent = 0;
    +int listdepth = 0;
    +int lastc = '0';
    +bool ol = false;
    +bool linestarted = false;
    +
    +
    +/* Helper functions */
    +void putesc(int c) {
    +    switch (c) {
    +        case '<': printf("<"); break;
    +        case '>': printf(">"); break;
    +        case '&': printf("&"); break;
    +        default: putchar(c);
    +    }
    +}
    +
    +void newlist() {
    +    in = LIST;
    +    previndent = indent;
    +    printf("<%s>\n
  • \n", ol ? "ol" : "ul"); + listdepth++; +} + +int endlist() { + in = LIST; + previndent = indent; + printf("
  • \n\n", ol ? "ol" : "ul"); + return --listdepth; +} + +void maybe_startp() { + /* All inline types should start the paragraph if no other major type present*/ + if (in == NONE) { + in = PARAGRAPH; + printf("

    \n"); + } +} + +void handle_lf() { + indent = 0; + linestarted = false; + + /* single line types (one lf to close) */ + if (in == HEADER) { + in = NONE; + printf("\n", hlvl); + } + + /* terminate url parsing in links */ + if (in_link == URL_PARSE) { + in_link = DESC_PARSE; + printf("\">"); + } + + /* multi-line types (two lf to close) */ + if (lastc == '\n') { + switch (in) { + case PARAGRAPH: printf("

    \n"); break; + case CODE: printf("
    \n"); break; + case QUOTE: printf("
    \n"); break; + case LIST: + previndent = 0; + while (endlist()) + ; + break; + default: + break; /* no op */ + } + in = NONE; + } +} + +bool fmt_disabled() { + /* `` blocks disable all but the next `, likewise CODE makes all disabled */ + if (in == CODE || in_link == URL_PARSE) { + return true; + } else { + return fmts['`'] && c != '`'; + } +} + +void toggle_format() { + if (!fmt_disabled()) { + maybe_startp(); + printf("<%s%s>", fmts[c] ? "/" : "", FMT_STRS[c]); + fmts[c] ^= true; + } else { + putesc(c); + } +} + +int parse() { + /* Mini state machine (home grown spaghetti code) */ + while ((c = getchar()) != EOF) { + /* Handle Escapes before all else */ + if (escape) { + maybe_startp(); + putesc(c); + escape = false; + continue; + } + + /* Store links as we go */ + if (in_link == URL_PARSE && c != ']') { + lnkbuf[lnkidx++] = c; + } + + /* Store the indentation */ + if (!linestarted && c == ' ') { + indent++; + continue; /* don't print leading indents */ + } + + /* Handle unique state changes by char */ + switch (c) { + case '\\': + escape = true; + break; + case '#': + if (in == NONE) { + in = HEADER_PARSE; + hlvl = 1; + } else if (in == HEADER_PARSE) { + hlvl++; + } else { + /* not a special # */ + putesc(c); + } + break; + case ' ': + if (in == HEADER_PARSE) { + printf("", hlvl); + in = HEADER; + } else if (in_link == URL_PARSE) { + in_link = DESC_PARSE; + printf("\">"); + } else if (in == LIST_PARSE) { + if (!listdepth) { + newlist(); + } else { + if (previndent < indent) { + newlist(); + } else if (previndent > indent) { + endlist(); + printf("
  • \n
  • \n"); + } else { + in = LIST; + printf("
  • \n
  • \n"); + } + } + } else { + putesc(c); + } + break; + case '*': + case '`': + case '_': + toggle_format(); + break; + case '\t': + case '>': + if (in == NONE) { + in = c == '>' ? QUOTE : CODE; + printf("%s", c == '>' ? "
    " : "
    ");
    +                } else if (lastc == '\n' && c == (in == CODE ? '\t' : '>')) {
    +                    /* no op */
    +                } else {
    +                    putesc(c);
    +                }
    +                break;
    +            case '[':
    +                if (in_link == NOL && !fmt_disabled()) {
    +                    maybe_startp();
    +                    in_link = URL_PARSE;
    +                    lnkidx = 0;
    +                    printf("%s", lnkbuf);
    +                } else if (in_link == DESC_PARSE) {
    +                    in_link = NOL;
    +                    printf("");
    +                } else {
    +                    putesc(c);
    +                }
    +                break;
    +            case '1':
    +            case '2':
    +            case '3':
    +            case '4':
    +            case '5':
    +            case '6':
    +            case '7':
    +            case '8':
    +            case '9':
    +            case '.':
    +            case '-':
    +                if (in == NONE || !linestarted) {
    +                    ol = c != '-';
    +                    in = LIST_PARSE;
    +                } else if (in != LIST_PARSE) {
    +                    putesc(c);
    +                }
    +                break;
    +            case '\n':
    +                handle_lf();
    +                if (in != NONE) {
    +                    putesc(c);
    +                }
    +                break;
    +            default:
    +                maybe_startp();
    +                putesc(c);
    +                break;
    +        }
    +        lastc = c;
    +        linestarted = c != '\n';
    +    }
    +    /* pretend there's a final LF to close any blocks */
    +    handle_lf();
    +    return 0;
    +}
    +
    +int main(int argc, char *argv[]) {
    +    if (argc > 1) {
    +        fprintf(stderr, "error: %s takes no arguments\n", argv[0]);
    +        return 1;
    +    }
    +#ifdef __OpenBSD__
    +    pledge("stdio", "stdio");
    +#endif
    +    return parse();
    +}
    diff --git a/test/big.html b/test/big.html
    index fb172a8..29e7f14 100644
    --- a/test/big.html
    +++ b/test/big.html
    @@ -1,6 +1,6 @@
     

    hello world

    -This is an example blag file! +This is an example nihdoc file!

    This should be emphasized within a paragraph diff --git a/test/big.txt b/test/big.txt index 41b8591..6693f77 100644 --- a/test/big.txt +++ b/test/big.txt @@ -1,6 +1,6 @@ # hello world -This is an example blag file! +This is an example nihdoc file! _This should be emphasized within a paragraph_ -- libgit2 1.1.1