hare

The Hare programming language
git clone https://git.torresjrjr.com/hare.git
Log | Files | Refs | README | LICENSE

commit 1195ac84d2ddf64b9e43823f77d490ce5ff1fee2
parent c2c7d3b78ae84014787012a6ca78ff722de4c8e0
Author: Umar Getagazov <umar@handlerug.me>
Date:   Fri, 25 Mar 2022 22:30:47 +0700

haredoc: multi-line lists, references in lists

This commit adds the following:
- Support for rendering multi-line list items in HTML. To make a
  multi-line list item, write it just like this one.
- You can also write multi-line lists without spaces in the beginning,
like you'd wrap a normal paragraph. All references inside list items
are now parsed too.
- If you're wrapping a paragraph that has a hyphen at the wrapping point
 - prefix it with whitespace.

Signed-off-by: Umar Getagazov <umar@handlerug.me>

Diffstat:
Mcmd/haredoc/docstr.ha | 49++++++++++++++++++++++++++++++++-----------------
Mcmd/haredoc/html.ha | 27+++++++++++++++++++--------
2 files changed, 51 insertions(+), 25 deletions(-)

diff --git a/cmd/haredoc/docstr.ha b/cmd/haredoc/docstr.ha @@ -3,6 +3,7 @@ // (c) 2021 Drew DeVault <sir@cmpwn.com> // (c) 2021 Eyal Sawady <ecs@d2evs.net> // (c) 2021 Thomas Bracht Laumann Jespersen <t@laumann.xyz> +// (c) 2022 Umar Getagazov <umar@handlerug.me> use ascii; use bufio; use encoding::utf8; @@ -17,12 +18,13 @@ type paragraph = void; type text = str; type reference = ast::ident; type sample = str; -type list = []str; -type token = (paragraph | text | reference | sample | list); +type listitem = void; +type token = (paragraph | text | reference | sample | listitem); type docstate = enum { PARAGRAPH, TEXT, + LIST, }; type parser = struct { @@ -55,6 +57,15 @@ fn scandoc(par: *parser) (token | void) = { case => return scantext(par); }; + case docstate::LIST => + switch (rn) { + case '[' => + return scanref(par); + case '-' => + return scanlist(par); + case => + return scantext(par); + }; case docstate::PARAGRAPH => switch (rn) { case ' ', '\t' => @@ -98,6 +109,9 @@ fn scantext(par: *parser) (token | void) = { break; }; bufio::unreadrune(&par.src, rn); + if (par.state == docstate::LIST) { + break; + }; case => strio::appendrune(&buf, rn)!; }; @@ -219,21 +233,22 @@ fn scansample(par: *parser) (token | void) = { }; fn scanlist(par: *parser) (token | void) = { - let items: list = []; - for (true) { - match (bufio::scanrune(&par.src)!) { - case io::EOF => break; - case let rn: rune => - if (rn != '-') { - break; - }; + match (bufio::scanrune(&par.src)!) { + case io::EOF => return void; + case let rn: rune => + if (rn != '-') { + abort(); }; - // XXX: multi-line list items - append(items, match (bufio::scanline(&par.src)!) { - case io::EOF => break; - case let u: []u8 => - yield strings::fromutf8(u); - }); }; - return items; + const rn = match (bufio::scanrune(&par.src)!) { + case io::EOF => return void; + case let rn: rune => + yield rn; + }; + if (rn != ' ') { + bufio::unreadrune(&par.src, rn); + return strings::dup("-"): text; + }; + par.state = docstate::LIST; + return listitem; }; diff --git a/cmd/haredoc/html.ha b/cmd/haredoc/html.ha @@ -345,14 +345,23 @@ fn htmlref(ctx: *context, ref: ast::ident) (void | io::error) = { fn markup_html(ctx: *context, in: io::handle) (void | io::error) = { let parser = parsedoc(in); + let waslist = false; for (true) { const tok = match (scandoc(&parser)) { - case void => break; + case void => + if (waslist) { + fmt::fprintln(ctx.out, "</ul>")?; + }; + break; case let tok: token => yield tok; }; match (tok) { case paragraph => + if (waslist) { + fmt::fprintln(ctx.out, "</ul>")?; + waslist = false; + }; fmt::fprintln(ctx.out)?; fmt::fprint(ctx.out, "<p>")?; case let tx: text => @@ -371,18 +380,20 @@ fn markup_html(ctx: *context, in: io::handle) (void | io::error) = { case let re: reference => htmlref(ctx, re)?; case let sa: sample => + if (waslist) { + fmt::fprintln(ctx.out, "</ul>")?; + waslist = false; + }; fmt::fprint(ctx.out, "<pre class='sample'>")?; html_escape(ctx.out, sa)?; fmt::fprint(ctx.out, "</pre>")?; free(sa); - case let li: list => - fmt::fprintln(ctx.out, "<ul>")?; - for (let i = 0z; i < len(li); i += 1) { - fmt::fprintln(ctx.out, "<li>")?; - html_escape(ctx.out, li[i])?; - fmt::fprintln(ctx.out, "</li>")?; + case listitem => + if (!waslist) { + fmt::fprintln(ctx.out, "<ul>")?; + waslist = true; }; - fmt::fprintln(ctx.out, "</ul>")?; + fmt::fprint(ctx.out, "<li>")?; }; }; fmt::fprintln(ctx.out)?;