aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLoïc Hoguin <[email protected]>2016-10-18 18:04:35 +0200
committerLoïc Hoguin <[email protected]>2016-10-18 18:04:35 +0200
commitb534d457c3813c4c2d905a04f6183e7317d66720 (patch)
tree0cae961b1b472d373f1449cac0ae1c149987db2d /src
parent2e4d6f4d5e239198e096e09e4207214951b42db1 (diff)
downloadasciideck-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.erl70
-rw-r--r--src/asciideck_to_manpage.erl8
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].