diff options
author | Loïc Hoguin <[email protected]> | 2016-10-18 18:04:35 +0200 |
---|---|---|
committer | Loïc Hoguin <[email protected]> | 2016-10-18 18:04:35 +0200 |
commit | b534d457c3813c4c2d905a04f6183e7317d66720 (patch) | |
tree | 0cae961b1b472d373f1449cac0ae1c149987db2d /src | |
parent | 2e4d6f4d5e239198e096e09e4207214951b42db1 (diff) | |
download | asciideck-b534d457c3813c4c2d905a04f6183e7317d66720.tar.gz asciideck-b534d457c3813c4c2d905a04f6183e7317d66720.tar.bz2 asciideck-b534d457c3813c4c2d905a04f6183e7317d66720.zip |
Fix the AST and add tests for formatting
Also opened the way to making configurable quoted text elements,
like the original Asciidoc allows. We could potentially end up
allowing users to define different types of quotes producing
custom AST.
Diffstat (limited to 'src')
-rw-r--r-- | src/asciideck_parser.erl | 70 | ||||
-rw-r--r-- | src/asciideck_to_manpage.erl | 8 |
2 files changed, 55 insertions, 23 deletions
diff --git a/src/asciideck_parser.erl b/src/asciideck_parser.erl index 90ae115..2744138 100644 --- a/src/asciideck_parser.erl +++ b/src/asciideck_parser.erl @@ -203,7 +203,7 @@ p1_maybe_p(Lines=[{LN, _}|_], AST, St) -> p1_p(Lines, AST, St, LN, []). p1_p([{_, <<>>}|Tail], AST0, St, LN, [_|Acc]) -> - Text = format(iolist_to_binary(lists:reverse(Acc))), + Text = format(iolist_to_binary(lists:reverse(Acc)), LN, St), case AST0 of [{block_title, Title}|AST] -> p1(Tail, [paragraph(Text, #{title => Title}, ann(LN, St))|AST], St); @@ -211,38 +211,64 @@ p1_p([{_, <<>>}|Tail], AST0, St, LN, [_|Acc]) -> p1(Tail, [paragraph(Text, #{}, ann(LN, St))|AST], St) end; p1_p([{_, Line}|Tail], AST, St, LN, Acc) -> + %% @todo We need to keep line/col information. To do this + %% we probably should keep an index of character number -> line/col + %% that we pass to the format function. Otherwise the line/col + %% information on text will point to the paragraph start. p1_p(Tail, AST, St, LN, [<<" ">>, Line|Acc]). %% Inline formatting. %% @todo Probably do it as part of the node functions that require it. -format(Text) -> - case format(Text, [], <<>>, $\s) of +format(Text, LN, St) -> + case format(Text, LN, St, [], <<>>, $\s) of [Bin] when is_binary(Bin) -> Bin; Formatted -> Formatted end. -format(<<>>, Acc, <<>>, _) -> +format(<<>>, _, _, Acc, <<>>, _) -> lists:reverse(Acc); -format(<<>>, Acc, BinAcc, _) -> +format(<<>>, _, _, Acc, BinAcc, _) -> lists:reverse([BinAcc|Acc]); -format(<< "link:", Rest0/bits >>, Acc, BinAcc, Prev) when Prev =:= $\s -> +format(<< "link:", Rest0/bits >>, LN, St, Acc0, BinAcc, Prev) when Prev =:= $\s -> case re:run(Rest0, "^([^[]*)\\[([^]]*)\\](.*)", [{capture, all, binary}]) of - nomatch -> format(Rest0, Acc, << BinAcc/binary, "link:" >>, $:); - {match, [_, Link, Text, Rest]} -> format(Rest, [{link, Link, Text}, BinAcc|Acc], <<>>, $]) - end; -format(<< $*, Rest0/bits >>, Acc, BinAcc, Prev) when Prev =:= $\s -> - case binary:split(Rest0, << $* >>) of - [_] -> format(Rest0, Acc, << BinAcc/binary, $* >>, $*); - [Em, Rest] -> format(Rest, [{em, Em}, BinAcc|Acc], <<>>, $*) + nomatch -> + format(Rest0, LN, St, Acc0, << BinAcc/binary, "link:" >>, $:); + {match, [_, Link, Text, Rest]} -> + Acc = case BinAcc of + <<>> -> Acc0; + _ -> [BinAcc|Acc0] + end, + format(Rest, LN, St, [rel_link(Text, Link, ann(LN, St))|Acc], <<>>, $]) end; -format(<< $`, Rest0/bits >>, Acc, BinAcc, Prev) when Prev =:= $\s -> - case binary:split(Rest0, << $` >>) of - [_] -> format(Rest0, Acc, << BinAcc/binary, $` >>, $`); - [Mono, Rest] -> format(Rest, [{mono, Mono}, BinAcc|Acc], <<>>, $`) +format(<< C, Rest0/bits >>, LN, St, Acc0, BinAcc, Prev) when Prev =:= $\s -> + %% @todo In some cases we must format inside the quoted text too. + %% Therefore we need to have some information about what to do here. + Quotes = #{ + $* => {strong, text}, + $` => {mono, literal} + }, + case maps:get(C, Quotes, undefined) of + undefined -> + format(Rest0, LN, St, Acc0, << BinAcc/binary, C >>, C); + {NodeType, QuotedType} -> + case binary:split(Rest0, << C >>) of + [_] -> + format(Rest0, LN, St, Acc0, << BinAcc/binary, $* >>, $*); + [QuotedText0, Rest] -> + Acc = case BinAcc of + <<>> -> Acc0; + _ -> [BinAcc|Acc0] + end, + QuotedText = case QuotedType of + text -> format(QuotedText0, LN, St); + literal -> QuotedText0 + end, + format(Rest, LN, St, [quoted(NodeType, QuotedText, ann(LN, St))|Acc], <<>>, $*) + end end; -format(<< C, Rest/bits >>, Acc, BinAcc, _) -> - format(Rest, Acc, << BinAcc/binary, C >>, C). +format(<< C, Rest/bits >>, LN, St, Acc, BinAcc, _) -> + format(Rest, LN, St, Acc, << BinAcc/binary, C >>, C). %% Second pass. @@ -308,6 +334,12 @@ ll(Nodes, Attrs, Ann) -> paragraph(Text, Attrs, Ann) -> {p, Attrs, Text, Ann}. +quoted(NodeType, Text, Ann) -> + {NodeType, #{}, Text, Ann}. + +rel_link(Text, Link, Ann) -> + {rel_link, #{target => Link}, Text, Ann}. + row(Nodes, Ann) -> {row, #{}, Nodes, Ann}. diff --git a/src/asciideck_to_manpage.erl b/src/asciideck_to_manpage.erl index dbdb74d..4158b4d 100644 --- a/src/asciideck_to_manpage.erl +++ b/src/asciideck_to_manpage.erl @@ -69,7 +69,7 @@ man([{ll, _Attrs, Items, _Ann}|Tail], Acc0) -> %% @todo Attributes. %% Currently acts as if options="headers" was always set. man([{table, _TAttrs, [{row, RowAttrs, Headers0, RowAnn}|Rows0], _TAnn}|Tail], Acc0) -> - Headers = [{cell, CAttrs, [{p, Attrs, [{em, P}], Ann}], CAnn} + Headers = [{cell, CAttrs, [{p, Attrs, [{strong, #{}, P, CAnn}], Ann}], CAnn} || {cell, CAttrs, [{p, Attrs, P, Ann}], CAnn} <- Headers0], Rows = [{row, RowAttrs, Headers, RowAnn}|Rows0], Acc = [[ @@ -133,16 +133,16 @@ man_table_contents_cols([{cell, _CAttrs, [{p, _PAttrs, Text, _PAnn}], _CAnn}|Tai man_format(Text) when is_binary(Text) -> Text; -man_format({link, Link, Text}) -> +man_format({rel_link, #{target := Link}, Text, _}) -> case re:run(Text, "^([-_:.a-zA-Z]*)(\\([0-9]\\))$", [{capture, all, binary}]) of nomatch -> [Text, " (", Link, ")"]; {match, [_, ManPage, ManSection]} -> ["\\fB", ManPage, "\\fR", ManSection] end; -man_format({em, Text}) -> +man_format({strong, _, Text, _}) -> ["\\fB", man_format(Text), "\\fR"]; %% We are already using a monospace font. %% @todo Maybe there's a readable formatting we could use to differentiate from normal text? -man_format({mono, Text}) -> +man_format({mono, _, Text, _}) -> man_format(Text); man_format(Text) when is_list(Text) -> [man_format(T) || T <- Text]. |